The XL Fortran compiler has a "subscriptorder" directive that allows you to
reverse the order of subscripts on arrays:
http://publib.boulder.ibm.com/infocenter/comphelp/v111v131/topic/com.ibm.xlf131.aix.doc/language_ref/subscriptorder.html
For example:
!IBM* SUBSCRIPTORDER(A(2,1))
INTEGER A(3,2)
makes the array shape become (2, 3) instead of (3, 2).
While this was done to help people with programs that looped over Fortran
arrays in row major order (See explanation in the linked page above), it's
dangerous. It will confuse every Fortran developer reading your code
without noticing or understanding the directive. While it's still
supported, I doubt that the directive is still in use today.
To get back on topic, I understand your desire to write the matrix similar
to how one would write it on paper. I can think of some ways, but they'll
cost you on the performance side:
1. Create a function matrix(input, cols, rows):
pure function matrix(input, cols, rows)
integer, intent(in) :: input(:)
integer, intent(in) :: rows, cols
integer matrix(cols, rows)
matrix = reshape(input, shape(matrix), order=[2, 1])
end function
The problem with this is that you can't use it in an initialization
expression. i.e.
integer :: B(2, 3) = matrix([1,2,3, &
4,5,6], 2, 3)
will not work, but the following will:
integer :: B(2, 3);
B = matrix([1,2,3, &
4,5,6], 2, 3)
You can make B allocatable and elide providing 2, 3 on the declaration:
integer, allocatable :: B(:, :)
B = matrix([1,2,3, &
4,5,6], 2, 3)
F2003 compilers will automatically allocate B to have the shape of the
function result. Of course, that's going to cost you performance.
You might not like making B allocatable or specifying 2, 3 twice, and so an
alternative is:
2. Create a subroutine create_matrix(input, output)
pure subroutine assign_matrix(lhs, rhs)
integer, intent(out) :: lhs(:,:)
integer, intent(in) :: rhs(:)
lhs = reshape(rhs, shape(lhs), order=[2,1])
end subroutine
This way, your code would be:
integer :: B(2, 3)
call assign_matrix(B, [1,2,3 &
4,5,6])
The caveat is that you can't use assign_matrix in an expression.
But this looks like an assignment routine, so why not make it a defined
assignment? So:
3. Create a parameterized derived type, with a user-defined assignment
routine:
type matrix(rows, cols)
integer, len :: rows, cols
integer data(cols, rows)
end type
interface assignment(=)
pure subroutine assign_matrix(lhs, rhs)
type(matrix(*, *)), intent(out) :: lhs
integer, intent(in) :: rhs(:)
end subroutine
end interface
type(matrix(2, 3)) B
B = [1, 2, 3, &
4, 5, 6]
You can even declare B above as type(matrix(rows=2, cols=3)) for
readability.
You can also make the defined assignment above a generic binding, but you'll
need to make the lhs argument polymorphic.
There are several issues with this: 1. Most compilers don't currently
implement F2003 parametrized derived types. I think only IBM, Cray, and
possibly PGI support them. 2. Your defined assignment is a function call
that can't appear in initialization expressions, just the like 1 and 2
above. Note that I made rows and cols length parameters instead of kind
parameters in order to make one assignment routine work for all values.
4. If you give your source file a capital letter extension (e.g. F90), most
compilers will run your source through a preprocessor before compiling it.
You could try writing a function-like macro to wrap the reshape. The big
caveat here is that your preprocessor has to know about Fortran continuation
line characters and array constructor syntax. I haven't tested, but I'm
guessing most preprocessors support the former but not the latter. (I'm not
even sure whether our preprocessor would consider an array constructor one
values or multiple values.) The advantage of using a macro (if you can get
one to work) is that you can use it in initialization expressions.
Personally, I would live with the reshape. It's not how a mathematician
would write the matrix, but it is familiar to Fortran developers.
Regards
Rafik
"Nasser M. Abbasi" <
n...@12000.org> wrote in message
news:jhbvj3$3b7$1...@speranza.aioe.org...