No one can be fooled who has ever seen Fortran matrix code and a comparable implementation in C.
At the function call ABI level, because of array slicing support, one-dimensional array references tend to be
origin,stride,length with each element accessed as (using C syntax)
origin[stride*index] for
index=1..length, inclusive. (In fact,
gfortran also records
offset,
minimum_index, and
maximum_index also, making it
origin[offset+stride*index] for
index=minimum_index..maximum_index, or something along those lines.)
Even with this "added complication" in array indexing, naïvely written Fortran array/matrix code tends to beat code written in naïve C to achieve the same, i.e. by physicists and such, in my experience. It does not mean that "Fortran is faster/better than C", unless you limit the domain to "for naïve programmers". Since naïvety can be a positive quality for example when making new science utilising linear algebra – such is easier to review, reproduce, and verify –, Fortran will always have niches where it is preferable to C, unless something even more suitable for naïve programmers comes along.
I'm sure most of you have seen
my own matrix interface in C, where both matrices and views to matrices are the same thing, so you can have e.g. two matrices and three vectors using the same data – row-major and column-major matrices (transposes), main diagonal and two sub-diagonal vectors (immediately above and below), as often needed for C² continuity in piecewise cubic curve models – where any change to one is immediately visible in all others, because they refer to the exact same data. I do use row and column numbering starting from zero, though. In my experience, any heavier operation like matrix-matrix multiplication, benefits from heuristic check that considers the matrix shapes, and reorders one or both matrices to temporary storage to optimize cache locality. Much better gains are available if sequences of operations (like multiple matrices multiplied together, or raising a square matrix to a power) can be optimized. Since element access to a matrix just isn't a bottleneck; it's the cache locality/memory bandwidth and algorithmic optimizations (to minimize the number of base operations needed) that yield true efficiency improvements.