Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Fortran line continuation, where it can not be used?

173 views
Skip to first unread message

Nasser M. Abbasi

unread,
Feb 12, 2012, 3:49:26 AM2/12/12
to

I thought I can use line continuation & any where I want to
break a statment?

But this program compiles ok with gfortran

-----------------------------------
program foo
integer, dimension(3,3) :: a
a = reshape( (/ 1, 2, 3, &
4, 5, 6, &
7, 8, 9/), &
(/ 3, 3 /))
end program foo
-------------------------------

but not this one:

------------------------
program foo
integer, dimension(3,3) :: b
b = reshape( (/ 1, 2, 3, &
4, 5, 6, &
7, 8, 9/ &
), &
(/ 3, 3 /))
end program foo
---------------------

$gfortran bug.f90
bug.f90:6.25:
7, 8, 9/ &
1
Error: Syntax error in array constructor at (1)

$gfortran -v
Using built-in specs.
COLLECT_GCC=gfortran
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-linux-gnu/4.6.1/lto-wrapper
Target: i686-linux-gnu
gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3)
$

What are the places where one can't use & to break
a Fortran statment?

thanks,
--Nasser

Tobias Burnus

unread,
Feb 12, 2012, 5:10:14 AM2/12/12
to
Nasser M. Abbasi wrote:
> 7, 8, 9/ &
> ), &

Try:

7, 8, 9/&
&), &

and observe both the spacing and the extra "&". The "/)" has a special
meaning similar to
end
which you can also not simply write as
en &
d

Tobias

Nasser M. Abbasi

unread,
Feb 12, 2012, 5:56:33 AM2/12/12
to
On 2/12/2012 4:10 AM, Tobias Burnus wrote:


>The "/)" has a special
> meaning similar to
> end
> which you can also not simply write as
> en&
> d
>

Well, yes, END is a key word in Fortran. Clearly one can't
break a keyword.

I did not know that /) was also a "keyword" like END and
IF and others, which is what I assume you mean by 'special
meaning'.

But it seems to be a special type of keyword, since I
can put spaces between the 2 tokens of this keyword and
write

/ )

while I can't do the same with say END:

EN D

I was looking again at Fortran after long time not using
it, so thanks for the information on /), this is good to know.

--Nasser

glen herrmannsfeldt

unread,
Feb 12, 2012, 8:42:48 AM2/12/12
to
Tobias Burnus <bur...@net-b.de> wrote:

(snip)

> and observe both the spacing and the extra "&". The "/)" has a special
> meaning similar to
> end
> which you can also not simply write as
> en &
> d

Maybe not quite like END.

END is special. In fixed form, you are also not allowd to use
use continuation lines for END. That is still in F2003.
Also, the initial line of a continued statement can't look
like an END statement. That is, you shouldn't:

END
3SUBROUTINE

It is convenient for the compiler to recognize an END statement
without the need to put continuation lines together first,
especially in the days when it was reading actual cards from
an actual card reader.

(Some years ago, before I knew this rule, I tried continuing end
with the VAX/VMS compiler. That compiler allowed it, and it worked!
But the rule against it is still there, at least in 2003.)

-- glen

glen herrmannsfeldt

unread,
Feb 12, 2012, 8:49:53 AM2/12/12
to
Nasser M. Abbasi <n...@12000.org> wrote:
> On 2/12/2012 4:10 AM, Tobias Burnus wrote:

>>The "/)" has a special
>> meaning similar to
>> end
>> which you can also not simply write as
>> en&
>> d

> Well, yes, END is a key word in Fortran. Clearly one can't
> break a keyword.

> I did not know that /) was also a "keyword" like END and
> IF and others, which is what I assume you mean by 'special
> meaning'.

The rule uses 'lexical token' not 'keyword'.

In free form, you are not supposed to put blanks within a
lexical token. You can continue across one if there is no
space before the &, or after the continuing &.

/&
&)

-- glen

Rafik Zurob

unread,
Feb 13, 2012, 12:03:32 AM2/13/12
to
Hi Nasser

I know you're asking about continuation in general, and Tobias answered
that. But for this specific case, you also have another alternative: As of
Fortran 2003, you can use [ ] instead of (/ /) for array constructors.

Rafik
Visit the Fortran Cafe at http://ibm.com/rational/cafe/

"Nasser M. Abbasi" <n...@12000.org> wrote in message
news:jh85sv$tbf$1...@speranza.aioe.org...

Nasser M. Abbasi

unread,
Feb 13, 2012, 6:31:44 AM2/13/12
to
On 2/12/2012 11:03 PM, Rafik Zurob wrote:
> Hi Nasser
>
> I know you're asking about continuation in general, and Tobias answered
> that. But for this specific case, you also have another alternative: As of
> Fortran 2003, you can use [ ] instead of (/ /) for array constructors.

Thanks. I just looked that up. My first goal was to see
if I declare a matrix by writing it in the code
in the same logical order I wanted for it.
(row 1, then below it, row2, then below it row 3, etc...)

For example, if I wanted to declare a 3 by 2 matrix,
then I'd like to write, in the code, the following

A=[1 2 3;
4 5 6]

Just like I do in matlab. More natural, for me at
least.

The closest I got to is this:
---------------------------------
program t
implicit none
integer :: B(2,3)=transpose(reshape( &
[1,2,3, &
4,5,6] &
,[3,2]))

print '(3i3)', B(1,:)
print '(3i3)', B(2,:)
end program t
---------------------------------

$gfortran -std=f2008 t.f90
$./a.out
1 2 3
4 5 6

so the logical order agrees with the textual layout in
the code. This is just to make it easier for me to
play around with small matrices and try things.

It is not as easy as in Matlab.

I had to transpose it, and the SHAPE=[3,2] is
transpose of the B(2,3).

Unless someone has a simpler way to do this
sort of thing.

I could ofcourse just write

-------------------------------------
program t
implicit none
integer :: B(2,3)=reshape([1,4,2,5,3,6],[2,3])

print '(3i3)', B(1,:)
print '(3i3)', B(2,:)

end program t
---------------------------

and this gives same output
$./a.out
1 2 3
4 5 6

But you see, not as intuitive as the first way, had
to write down the numbers in column major. Not
a natural way. Also, had to duplicate (2,3) in
2 places, for the SHAPE and for the declaration.

But again, I just started looking at this. may be will
find an easier or better way.

--Nasser

Nasser M. Abbasi

unread,
Feb 13, 2012, 6:33:32 AM2/13/12
to
On 2/13/2012 5:31 AM, Nasser M. Abbasi wrote:

>
> For example, if I wanted to declare a 3 by 2 matrix,
> then I'd like to write, in the code, the following
>
> A=[1 2 3;
> 4 5 6]
>

opps, typo, meant 2 by 3 matrix.

--Nasser

Ian Bush

unread,
Feb 13, 2012, 7:17:04 AM2/13/12
to
Well you could use the shape intrinsic for the later
problem, and the order argument to reshape for the former:

Wot now? cat abc.f90
program t
implicit none
integer :: B(2,3)=reshape( &
[1,2,3, &
4,5,6] &
, Shape( B ), order = [ 2, 1 ] )

print '(3i3)', B(1,:)
print '(3i3)', B(2,:)
end program t
Wot now? nagfor -f2003 -C=all -C=undefined abc.f90
NAG Fortran Compiler Release 5.2(721)
[NAG Fortran Compiler normal termination]
Wot now? ./a.out
1 2 3
4 5 6

Also it avoids transpose which I'm not totally sure is allowed in
initialisation expressions (but I could be wrong)

Ian


Ron Shepard

unread,
Feb 13, 2012, 12:23:01 PM2/13/12
to
In article <jhasav$4sh$1...@speranza.aioe.org>,
"Nasser M. Abbasi" <n...@12000.org> wrote:

> integer :: B(2,3)=transpose(reshape( &
> [1,2,3, &
> 4,5,6] &
> ,[3,2]))

There are several goals in writing good code, and one of them is
clarity. Doing something like this is going to cause other
programmers to scratch their heads.

Fortran has a nice, simple, well-defined approach to the storage
order of matrices. When programming in fortran, you should use that
to advantage. This is an asset, not a liability. I program in
several languages with various conventions for array storage order,
and although the functionality is the same regardless, fortran is by
far the easiest to keep straight.

$.02 -Ron Shepard

glen herrmannsfeldt

unread,
Feb 13, 2012, 2:54:22 PM2/13/12
to
Nasser M. Abbasi <n...@12000.org> wrote:

(snip)
> Thanks. I just looked that up. My first goal was to see
> if I declare a matrix by writing it in the code
> in the same logical order I wanted for it.
> (row 1, then below it, row2, then below it row 3, etc...)

> For example, if I wanted to declare a 3 by 2 matrix,
> then I'd like to write, in the code, the following

(as you note later, this is, mathematically, 2 by 3)

> A=[1 2 3;
> 4 5 6]

> Just like I do in matlab. More natural, for me at least.

More often, you read a matrix in from a file, in which case you
can use implied DO to read it in any way you want it.

I believe that in some of the early Fortran matrix routines
it was done the other way around. That is, instead of reversing
the storage order, one instead reversed the subscript order.

When MATMUL was added, though, one had to choose an order.
(Well, you could still use MATMUL but assume the arguments
are in the opposite order.)

(snip)
> integer :: B(2,3)=transpose(reshape( &
> [1,2,3, &
> 4,5,6] &
> ,[3,2]))

(snip)
> so the logical order agrees with the textual layout in
> the code. This is just to make it easier for me to
> play around with small matrices and try things.

When you get to large matrices, the visual aspect is less important.
It is rare to print out a 10000 by 10000 matrix, and if you do you
won't expect 10000 elements on one line of print.

> It is not as easy as in Matlab.

> I had to transpose it, and the SHAPE=[3,2] is
> transpose of the B(2,3).

> Unless someone has a simpler way to do this
> sort of thing.

> I could ofcourse just write

(snip)
> integer :: B(2,3)=reshape([1,4,2,5,3,6],[2,3])

(snip)
> But you see, not as intuitive as the first way, had
> to write down the numbers in column major. Not
> a natural way. Also, had to duplicate (2,3) in
> 2 places, for the SHAPE and for the declaration.

I believe you can:

integer :: B(2,3)=reshape([1,4,2,5,3,6],shape(B))

such that the shape only goes in one place.

There is a C feature not in Fortran through 2003, but maybe
in 2008, where you can size an array based on its initialization.

int B[][]={{1,2,3},{4,5,6}};

as computers are better at counting than people, it is sometimes
more convenient. Actually, there is another reason for this:
some arrays are sized based on preprocessor expansion, where it
would be difficult to know the size. There is an additional feature,
in that C allows for a trailing comma:

int B[][]={{1,2,3,},{4,5,6,},};

Also generates B[2][3], and not B[3][4] as you might think.
There are arrays defined similar to:

int C[][]={
#ifdef option1
{1,2,3},
#endif
#ifder option2
{4,5,6},
#endif
// etc.
};

where it would be difficult to remove the trailing comma in the
last one.

> But again, I just started looking at this. may be will
> find an easier or better way.

-- glen

Nasser M. Abbasi

unread,
Feb 13, 2012, 4:02:33 PM2/13/12
to
On 2/13/2012 11:23 AM, Ron Shepard wrote:
> In article<jhasav$4sh$1...@speranza.aioe.org>,
> "Nasser M. Abbasi"<n...@12000.org> wrote:
>
>> integer :: B(2,3)=transpose(reshape(&
>> [1,2,3,&
>> 4,5,6]&
>> ,[3,2]))
>
> There are several goals in writing good code, and one of them is
> clarity. Doing something like this is going to cause other
> programmers to scratch their heads.
>

But that is my point. It is confusing way to do thing, just
that so the programmer can write the matrix in the natural
way they think about it.

That is why Matlab is simpler here.

> Fortran has a nice, simple, well-defined approach to the storage
> order of matrices.

I am not talking about internal ordering or anything and all
that. You missed my whole point.

I am talking about someone learning the language and wants
to enter a small matrix, as shown in the textbook, to test
some algorithm on.

Text books write a matrix in the natural way, one row on
top of the other. Text books do not show a matrix like this

1 2 3
4 5 6

not this way:

integer :: B(2,3)=reshape([1,4,2,5,3,6],[2,3])

If you think the above way is more natural, then all powers
to you. I do not think it is natural way to enter a matrix.

I think it is clumsy and confusing.

> $.02 -Ron Shepard

my 1.5 cents.

--Nasser

Gordon Sande

unread,
Feb 13, 2012, 4:28:58 PM2/13/12
to
What is wrong with

integer :: B(2,3)

then

B(1,:) = [ 1, 2, 3 ]
B(2,:) = [ 4, 5, 6 ]

or

B(:,1) = [ 1, 4 ]
B(:,2) = [ 2, 5 ]
B(:,3) = [ 3, 6 ]

Sometimes the matrix will be constructed from rows and sometimes from columns.
Once it achieves anything beyond trivial toy size any attempt to enter
the whole
matrix at once will become confusing. Not all toy examples scale reasonably.

In other cases one would set B to zero and then specify a few
individual elements.
Trying to put a few nonzeros in the midst of a long string of zeros can
be quite
error prone.

As to the original question. Think about things like <=, >=, ==. /= or
=>. These
might be though of as digraphs. Some languages even have trigraphs!





Nasser M. Abbasi

unread,
Feb 13, 2012, 4:33:26 PM2/13/12
to
On 2/13/2012 1:54 PM, glen herrmannsfeldt wrote:

>> A=[1 2 3;
>> 4 5 6]
>
>> Just like I do in matlab. More natural, for me at least.
>
> More often, you read a matrix in from a file, in which case you
> can use implied DO to read it in any way you want it.

Not my point. Again, I am talking about someone using
Fortran to solve a matrix problem in a text book where the
matrix is shown in the natural way, and want to enter
this matrix to Fortran. This is the context here.

>
> When you get to large matrices, the visual aspect is less important.

I know. But this is not my point again.

> It is rare to print out a 10000 by 10000 matrix, and if you do you
> won't expect 10000 elements on one line of print.

of course. But no one said anything about 10000 by 10000 matrix.
Clearly if I have 10000 by 10000 matrix, I would not type
it in by hand.

You are just making stuff up now to cloud the basic issue.

>
> I believe you can:
>
> integer :: B(2,3)=reshape([1,4,2,5,3,6],shape(B))
>
> such that the shape only goes in one place.

Ok, this helps a little. but the it is still confusing
vs. the natural way to type a matrix as in Matlab.

>
> There is a C feature not in Fortran through 2003, but maybe
> in 2008, where you can size an array based on its initialization.
>
> int B[][]={{1,2,3},{4,5,6}};
>

Great, This is how it should be in Fortran then.

I believe that a programming language should allow the
user to express the problem in the natural way to the user,
and not have the user adjust their ways to express the
problem in order to meet the needs of the language.

The language should serve the user, not the user serving
the language.

>
> -- glen

--Nasser

glen herrmannsfeldt

unread,
Feb 13, 2012, 5:17:26 PM2/13/12
to
Nasser M. Abbasi <n...@12000.org> wrote:

>>> A=[1 2 3;
>>> 4 5 6]

>>> Just like I do in matlab. More natural, for me at least.

(snip, I wrote)
>> More often, you read a matrix in from a file, in which case you
>> can use implied DO to read it in any way you want it.

> Not my point. Again, I am talking about someone using
> Fortran to solve a matrix problem in a text book where the
> matrix is shown in the natural way, and want to enter
> this matrix to Fortran. This is the context here.

Someone around 1956 made the decision on how Fortran arrays
would work, and they still work that way today. (Even more, the
Fortran I compiler stored arrays in decreasing memory order, but
that isn't visible to the programmer.)

>> When you get to large matrices, the visual aspect is less important.

> I know. But this is not my point again.

There are a large number (maybe too many) interpreted languages
that are more commonly used for testing out math problems in
textbooks. There are also many hand calculators that can do it.
There are also many compiled languages with row-major ordering.

>> It is rare to print out a 10000 by 10000 matrix, and if you do you
>> won't expect 10000 elements on one line of print.

> of course. But no one said anything about 10000 by 10000 matrix.
> Clearly if I have 10000 by 10000 matrix, I would not type
> it in by hand.

There are many Fortran features that would be done differently
if designed today. When Fortran was still fairly new, some
people at IBM tried to develop a replacement for it, without
a requirement for back compatibility. PL/I is still around, but
not nearly as popular. (And PL/I does use row-major ordering.)

> You are just making stuff up now to cloud the basic issue.

Maybe, but maybe not. Fortran is most commonly used for larger
problems, when speed is especially important. Many algorithms
are tested in other languages before being implemented in Fortran.

But much of the reason that Fortran stays popular is the large
set of subroutine libraries written over the years, and much of
that is for matrix processing.

>> I believe you can:

>> integer :: B(2,3)=reshape([1,4,2,5,3,6],shape(B))

>> such that the shape only goes in one place.

> Ok, this helps a little. but the it is still confusing
> vs. the natural way to type a matrix as in Matlab.

Matlab, Mathematica, R, octave (for those who like matlab but
can't afford it), and many more, are especially convenient for
quick tests of smaller problems.

>> There is a C feature not in Fortran through 2003, but maybe
>> in 2008, where you can size an array based on its initialization.

>> int B[][]={{1,2,3},{4,5,6}};

> Great, This is how it should be in Fortran then.

And note that C is also row-major.

By the way, does anyone here watch the TV series "24"?
There is one episode where Chloe find some data needs to
be converted between row-major and column-major (I don't
remember which direction) which turns out to be a major
problem.

> I believe that a programming language should allow the
> user to express the problem in the natural way to the user,
> and not have the user adjust their ways to express the
> problem in order to meet the needs of the language.

It is just one of those things you get used to, and after
not so long stop worrying about. Well, except that you have to
remember it long enough to get the loops in the right order
for fast processing of arrays.

> The language should serve the user, not the user serving
> the language.

Fortran is now over 50 years old. If you don't like it, use
another language. There are plenty to choose from. (Most of
which use row-major order.)

-- glen

Paul van Delst

unread,
Feb 13, 2012, 5:28:51 PM2/13/12
to
Nasser M. Abbasi wrote:
> On 2/13/2012 11:23 AM, Ron Shepard wrote:
>> In article<jhasav$4sh$1...@speranza.aioe.org>,
>> "Nasser M. Abbasi"<n...@12000.org> wrote:
>>
>>> integer :: B(2,3)=transpose(reshape(&
>>> [1,2,3,&
>>> 4,5,6]&
>>> ,[3,2]))
>>
>> There are several goals in writing good code, and one of them is
>> clarity. Doing something like this is going to cause other
>> programmers to scratch their heads.
>>
>
> But that is my point. It is confusing way to do thing, just
> that so the programmer can write the matrix in the natural
> way they think about it.
>
> That is why Matlab is simpler here.

Well, both Fortran and matlab store data in the same way (column major). However, matlab's interface to the user is the
opposite of that, i,e, it is (row, column) not (column, row).

>> a=[1 2 3; 4 5 6]

a =

1 2 3
4 5 6

>> size(a)

ans =

2 3

>> for j=1:3,
for i=1:2,
t=sprintf('%d',a(i,j));
disp(t)
end
end
1
4
2
5
3
6


In Fortran, however, the meory layout and "interface" to the user are the same, always (column,row):

program test_mat
integer, parameter :: col=2, row=3
integer :: b(col,row)
integer :: j

b = reshape([1,2,3,4,5,6],shape(b))
do j = 1, row
do i = 1, col
print *, b(i,j)
end do
end do
end program test_mat

scratch : gfortran test_mat.f90
scratch : a.out
1
2
3
4
5
6


Fortran seems clearer to me (but, being only an occasional matlab user, obviously I'm biased :o).

Other than that, dunno what the fuss is about.


cheers,

paulv

Tobias Burnus

unread,
Feb 13, 2012, 6:02:10 PM2/13/12
to
Am 13.02.2012 22:33, schrieb Nasser M. Abbasi:
> On 2/13/2012 1:54 PM, glen herrmannsfeldt wrote:
>> There is a C feature not in Fortran through 2003, but maybe
>> in 2008, where you can size an array based on its initialization.
>>
>> int B[][]={{1,2,3},{4,5,6}};

Fortran has - only for parameters - implied-shape arrays:

integer, parameter :: A(*) = [ 1, 2, 3, 4]

I don't know why the Fortran standard doesn't allow it for
nonparameters. Maybe to avoid the accidental setting of the SAVE
attribute, for users which forget the implicit save?

One cannot simply avoid the RESHAPE as Fortran allows:
[ Array, 1, 2 ] or [ [3,4,5], 1, 2]
thus, without the reshape one cannot simply see whether a new row should
be started or just an additional element.

Tobias

Rafik Zurob

unread,
Feb 13, 2012, 5:57:57 PM2/13/12
to
> There is a C feature not in Fortran through 2003, but maybe
> in 2008, where you can size an array based on its initialization.
>
> int B[][]={{1,2,3},{4,5,6}};
>

You might be thinking of implicit-shape arrays. These arrays, however, have
to have the PARAMETER attribute.
e.g.

integer, parameter :: b(*,*) = reshape(...etc)

Paul van Delst

unread,
Feb 13, 2012, 6:06:07 PM2/13/12
to
Just for the record, matlab (was originally written in Fortran!) also uses column major order for storage. It's just
referencing an array is done via (row,column).

So, while matlab may appear to be row-major, it isn't. At least, not entirely. :o)

cheers,

paulv

glen herrmannsfeldt

unread,
Feb 13, 2012, 6:10:40 PM2/13/12
to
For any interpreted language, execution speed is generally
not the most important consideration. Changing the order between
storage and user visible form won't affect the speed much.

For a compiled language like Fortran, it is often important
to loop through a multidimensional array in the right order.
The storage order must be consistent, as seen by the programmer.

-- glen

glen herrmannsfeldt

unread,
Feb 13, 2012, 6:14:54 PM2/13/12
to
Rafik Zurob <nos...@hotmail.com> wrote:
>> There is a C feature not in Fortran through 2003, but maybe
>> in 2008, where you can size an array based on its initialization.

>> int B[][]={{1,2,3},{4,5,6}};

> You might be thinking of implicit-shape arrays.
> These arrays, however, have to have the PARAMETER attribute.
> e.g.

> integer, parameter :: b(*,*) = reshape(...etc)

Is that new in F2008, and so not in F2003?

Can one initialize a non-PARAMETER based on one?

integer, parameter :: b(*,*) = reshape(...etc)

integer c(size(b,1),size(b,2)) = b

-- glen


Paul van Delst

unread,
Feb 13, 2012, 6:39:48 PM2/13/12
to
glen herrmannsfeldt wrote:
> Paul van Delst <paul.v...@noaa.gov> wrote:
>
>> Just for the record, matlab (was originally written in Fortran!)
>> also uses column major order for storage. It's just referencing
>> an array is done via (row,column).
>
>> So, while matlab may appear to be row-major, it isn't.
>> At least, not entirely. :o)
>
> For any interpreted language, execution speed is generally
> not the most important consideration.

Oh, I beg to differ. "Misuse" of looping constructs in matlab or IDL can increase execution times by orderS of
magnitude. Dunno about matlab, but it's not unusual for IDL users to see their code execution times decrease from many
hours to less than a minute simply by rearranging their code to avoid looping (i.e. using the matrix capabilities.)

And that's quite apart from accessing memory out-of-order.

dpb

unread,
Feb 13, 2012, 6:58:00 PM2/13/12
to
On 2/13/2012 5:39 PM, Paul van Delst wrote:
> glen herrmannsfeldt wrote:
>> Paul van Delst<paul.v...@noaa.gov> wrote:
>>
>>> Just for the record, matlab (was originally written in Fortran!)
>>> also uses column major order for storage. It's just referencing
>>> an array is done via (row,column).
>>
>>> So, while matlab may appear to be row-major, it isn't.
>>> At least, not entirely. :o)

Actually, as far as storage order it isn't at all. It is column-major
through and through.

As noted, it's only syntax that's the difference.

>> For any interpreted language, execution speed is generally
>> not the most important consideration.
>
> Oh, I beg to differ. "Misuse" of looping constructs in matlab or IDL can increase execution times by orderS of
> magnitude. Dunno about matlab, but it's not unusual for IDL users to see their code execution times decrease from many
> hours to less than a minute simply by rearranging their code to avoid looping (i.e. using the matrix capabilities.)
>
> And that's quite apart from accessing memory out-of-order.

Agreed and it's certainly possible to illustrate the same phenomena in
Matlab altho it's not always as much so as once was as Matlab now
implements jit compiler which can often hide a lot of sins (or at least
keep the effects of same small enough that the effect is tolerable).

>> Changing the order between
>> storage and user visible form won't affect the speed much.
>>
>> For a compiled language like Fortran, it is often important
>> to loop through a multidimensional array in the right order.
>> The storage order must be consistent, as seen by the programmer.

It can be _very_ significant in Matlab just as it is in Fortran to
actually traverse in proper order for the identical reason.

--

Rafik Zurob

unread,
Feb 13, 2012, 7:11:50 PM2/13/12
to
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...

Rafik Zurob

unread,
Feb 13, 2012, 7:14:29 PM2/13/12
to
Yes, implicit-shape arrays are a Fortran 2008 feature. Since the arrays are
parameters, you have access to their size, bounds, shape, and values at
compile time. So your example with size works.

Regards

Rafik

"glen herrmannsfeldt" <g...@ugcs.caltech.edu> wrote in message
news:jhc5he$ii7$1...@speranza.aioe.org...

Rafik Zurob

unread,
Feb 13, 2012, 7:23:57 PM2/13/12
to
I can't believe I wrote "implicit-shape" twice. They're actually called
"implied-shape". I'll take it as a sign that it's dinner time.

Rafik

"Rafik Zurob" <nos...@hotmail.com> wrote in message
news:VFg_q.4595$hJ4....@newsfe20.iad...

glen herrmannsfeldt

unread,
Feb 13, 2012, 8:00:58 PM2/13/12
to
Paul van Delst <paul.v...@noaa.gov> wrote:
> glen herrmannsfeldt wrote:
>> Paul van Delst <paul.v...@noaa.gov> wrote:

>>> Just for the record, matlab (was originally written in Fortran!)
>>> also uses column major order for storage. It's just referencing
>>> an array is done via (row,column).

>>> So, while matlab may appear to be row-major, it isn't.
>>> At least, not entirely. :o)

>> For any interpreted language, execution speed is generally
>> not the most important consideration.

> Oh, I beg to differ. "Misuse" of looping constructs in matlab
> or IDL can increase execution times by orderS of magnitude.
> Dunno about matlab, but it's not unusual for IDL users to
> see their code execution times decrease from many hours to
> less than a minute simply by rearranging their code to avoid
> looping (i.e. using the matrix capabilities.)

That is generally true of interpreted languages.

> And that's quite apart from accessing memory out-of-order.

I was specifically, and only, discussing memory order.

It is the overhead of the interpreter that tends to swamp
memory order effects. That overhead is very variable as
you note. To measure just memory order, you would have
to remove all other conditions that might effect the time.

-- glen

dpb

unread,
Feb 13, 2012, 8:08:33 PM2/13/12
to
...

And, to demonstrate--

>> a=[1 2 3;4 5 6]
a =
1 2 3
4 5 6
>> a(4)
ans =
5
>> a(:,1)
ans =
1
4
>> a(1,:)
ans =
1 2 3
>> a(:)
ans =
1
4
2
5
3
6
>>

Note the array specified in the brackets is displayed as written but
when looking at the element order the entries were/are stored in column
major order.

--

Richard Maine

unread,
Feb 13, 2012, 8:09:39 PM2/13/12
to
Rafik Zurob <nos...@hotmail.com> wrote:

> I can't believe I wrote "implicit-shape" twice. They're actually called
> "implied-shape". I'll take it as a sign that it's dinner time.

Now there's a good idea. As my wife won't be home on valentine's day
(and restaurants are horribly crowded then anyway), tonight, and
particularly right now, sounds good. :-)

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain

Nasser M. Abbasi

unread,
Feb 14, 2012, 12:24:57 AM2/14/12
to
On 2/13/2012 3:28 PM, Gordon Sande wrote:

>
> What is wrong with
>
> integer :: B(2,3)
>
> then
>
> B(1,:) = [ 1, 2, 3 ]
> B(2,:) = [ 4, 5, 6 ]
>

Nothing wrong with it. It is perfect!

That is what I wanted. I do not have to type it out at
declaration time. As long as I can type it as it appears in
the textbook any where else, that is fine.

So, your solution is the one I will use. Simple, and
natural. I did not know I can do that. I am just learning
Fortran, after long time.

thanks,
--Nasser

Ron Shepard

unread,
Feb 14, 2012, 2:06:43 AM2/14/12
to
In article <jhbtp6$u86$1...@speranza.aioe.org>,
"Nasser M. Abbasi" <n...@12000.org> wrote:

> integer :: B(2,3)=reshape([1,4,2,5,3,6],[2,3])
>
> If you think the above way is more natural, then all powers
> to you.

For this example, I would probably put spaces between the columns

integer :: B(2,3)=reshape([1,4, 2,5, 3,6], shape(B))

and I would use shape() rather than type the dimensions twice, but
otherwise, yes, this is the natural way to think of a matrix as a
collection of column vectors, and in fortran, you enter those
vectors one at a time in order.

I understand your point. As I said, I use several languages that do
things in various ways, and to me the fortran way is completely
natural and is consistent with most of the linear algebra that I do.
I suggest that instead of trying to force fortran to look like one
of the lesser languages, go ahead and embrace the way that fortran
orders things and take advantage of it.

$.02 -Ron Shepard

Thomas Koenig

unread,
Feb 16, 2012, 3:15:51 PM2/16/12
to
Rafik Zurob <nos...@hotmail.com> schrieb:

> !IBM* SUBSCRIPTORDER(A(2,1))
> INTEGER A(3,2)

> makes the array shape become (2, 3) instead of (3, 2).

Ouch. That has to be one of the worst Fortran extensions ever,
right after the AT statement (a COME FROM for debugging).

Out of curiosity: Is AT still supported in current compilers?

glen herrmannsfeldt

unread,
Feb 16, 2012, 3:33:00 PM2/16/12
to
Thomas Koenig <tko...@netcologne.de> wrote:

(snip)
>> !IBM* SUBSCRIPTORDER(A(2,1))
>> INTEGER A(3,2)
>> makes the array shape become (2, 3) instead of (3, 2).

> Ouch. That has to be one of the worst Fortran extensions ever,
> right after the AT statement (a COME FROM for debugging).

> Out of curiosity: Is AT still supported in current compilers?

AT is a Fortran G feature that was never in Fortran H.
(The idea being debug with G, production run with H.)

I don't remember if it got into VS Fortran, though.

As far as I know, VS Fortran is 'current' for z/OS.
(Some might want a newer one, though.)

-- glen

John Harper

unread,
Feb 22, 2012, 4:34:23 PM2/22/12
to
AT is in my old VS Fortran manual Release 1 (February 1981), marked as an
IBM extension, and it referred one to the DEBUG ststement, also an IBM
extension.

-- John Harper


David Thompson

unread,
Mar 1, 2012, 5:53:49 AM3/1/12
to
On Mon, 13 Feb 2012 19:54:22 +0000 (UTC), glen herrmannsfeldt
<g...@ugcs.caltech.edu> wrote:

> Nasser M. Abbasi <n...@12000.org> wrote:
<snip: row-major and transpose etc.>

> There is a C feature not in Fortran through 2003, but maybe
> in 2008, where you can size an array based on its initialization.
>
> int B[][]={{1,2,3},{4,5,6}};
>
Only for the 'top' dimension (leftmost in C). Lower dimensions must
still be specified explicitly. For rank 1 there is only 'top'.

> as computers are better at counting than people, it is sometimes
> more convenient. Actually, there is another reason for this:
> some arrays are sized based on preprocessor expansion, where it
> would be difficult to know the size. There is an additional feature,
> in that C allows for a trailing comma:
>
> int B[][]={{1,2,3,},{4,5,6,},};
>
> Also generates B[2][3], and not B[3][4] as you might think.

Per above this doesn't work as written, but
int B[][3] = that initializer list
does do [2][3] not [3][3].

<snip rest>

glen herrmannsfeldt

unread,
Mar 1, 2012, 6:41:44 AM3/1/12
to
David Thompson <dave.th...@verizon.net> wrote:

(snip, I wrote)
>> int B[][]={{1,2,3},{4,5,6}};

> Only for the 'top' dimension (leftmost in C). Lower dimensions must
> still be specified explicitly. For rank 1 there is only 'top'.

Hmm. I tested it out before posting, but my test did have
the second dimension. I am not sure now why I posted it this way.

-- glen
0 new messages