For FORTRAN 77, the difference in how you access normal SIDL arrays and r-arrays is profound. Normal SIDL arrays are passed in as an integer*8, and you either access them using an function API or by converting the array data to a index into a known array. R-arrays appear like normal FORTRAN 77 arrays, so there is a big incentive to use r-arrays unless you cannot.
The client-side interface for the solve example introduced in Section 5.4 behaves as if it is a FORTRAN 77 function with the following declarations:
subroutine num_Linsol_solve_f(self, A, x, b, m, n) implicit none C in num.Linsol self integer*8 self integer*4 m, n C in rarray<double,2> A(m,n) double precision A(0:m-1, 0:n-1) C inout rarray<double> x(n) double precision x(0:n-1) C in rarray<double> b(m) double precision b(0:m-1) end
FORTRAN 77 programmers should note that the array indices go from 0 to
m instead of the normal 1 to m. This is a concession
to the C and C++ programmers who have to deal with the fact that A is
stored in column-major order.
On the server-side, the interface for solve appears as follows:
subroutine num_Linsol_solve_fi(self, A, x, b, m, n) implicit none C in num.Linsol self integer*8 self C in int m integer*4 m C in int n integer*4 n C in rarray<double,2> A(m,n) double precision A(0:m-1, 0:n-1) C inout rarray<double> x(n) double precision x(0:n-1) C in rarray<double> b(m) double precision b(0:m-1) C DO-NOT-DELETE splicer.begin(num.Linsol.solve) C Insert the implementation here... C DO-NOT-DELETE splicer.end(num.Linsol.solve) end
Note again that the array indices go from 0 to m. The
implementation should avoid changing the data in in
parameters.
The remainder of this section is dedicated to how you access normal SIDL arrays. The normal SIDL C function API is available from FORTRAN 77 to create, destroy and access array elements and meta-data. The function name for FORTRAN has _f appended.
For SIDL types dcomplex, double, fcomplex , float, int and long, SIDL provides a method to get direct access to the array elements. For the other types, you must use the functional API to access array elements.
For type X, there is a FORTRAN 77 function called sidl_X__array_access_f to provide a method to get direct access. An example is given below. Of course, this will not work if your FORTRAN 77 compiler does array bounds checking.
integer*4 lower(1), upper(1), stride(1), i, index(1) integer*4 value, refindex, refarray(1), modval integer*8 nextprime, tmp lower(1) = 0 value = 0 upper(1) = len - 1 call sidl_int__array_create_f(1, lower, upper, retval) call sidl_int__array_access_f(retval, refarray, lower, $ upper, stride, refindex) do i = 0, len - 1 tmp = value value = nextprime(tmp) modval = mod(i, 3) if (modval .eq. 0) then call sidl_int__array_set1_f(retval, i, value) else if (modval .eq. 1) then index(1) = i call sidl_int__array_set_f(retval, index, value) else C this is equivalent to the sidl_int__array_set_f(retval, index, value) refarray(refindex + stride(1)*(i - lower(1))) = $ value endif endif enddo
To access a two dimensional array, the expression referring to element i, j is
refarray(refindex + stride(1) * (i - lower(1)) + stride(2) * (j - lower(2))
To access a three dimensional array, the expression referring to element i, j k is
refarray(refindex + stride(1) * (i - lower(1)) + stride(2) * (j - lower(2))
You can call things like LINPACK or BLAS if you want, but you should check the stride to make sure the array is packed as you need it to be. stride(i) indicates the distance between elements in dimension i. A value of 1 means elements are packed densely in dimension i. Negative stride values are possible, and when an array is a slice of another array, there may be no dimension with a stride of 1.
For a dcomplex array, the reference array should a FORTRAN array of REAL*8 instead of a FORTRAN array of double complex to avoid potential alignment problems. For a fcomplex array, the reference array is a COMPLEX*8 because we don't anticipate an alignment problem in this case.