From: jlg@cochiti.lanl.gov (Jim Giles)
Newsgroups: comp.lang.misc
Subject: Re: Fortran90 and Arrays
Date: 7 Apr 92 17:49:54 GMT
Article-I.D.: newshost.1992Apr7.174954.10303
Organization: Los Alamos National Laboratory

In article <ROCKWELL.92Apr6230831@socrates.umd.edu>, rockwell@socrates.umd.edu (Raul Deluth Miller-Rockwell) writes:
|> [...]
|> >        A(0: :2) = A(1: :2)
|> [...]
|> You're leaving out the big picture here, which is: why are you doing
|> this operation in the first place?  Chances are, there are other ways
|> of expressing the algorithm which don't involve this sort "partial
|> array mangling".

On the contrary.  There are numerous numerical problems for which 
manipulating the odd elements on one time step and the even elements
on the next is _exactly_ what you want to do.  In fact, for these 
problems _IF_ an alternate algorithm exists at all, it is usually
less stable numerically, slower, or both.  This example was chosen
to demonstrate the simplicity of notation for manipulating arrays with
stride.

|> [... operator precedence rules ...]
|> So, what's the precedence of subtraction vs greatest common
|> denominator?  How about antibase vs nth root?  Or are you going to say
|> that people shouldn't be allowed to use operators for things which
|> aren't included in Fortran?

No, I don't mind other operators.  If you want to invent them go ahead.
Fortran 90 allows you to.  All user defined unary operators have the
same precedence - and it's higher than any of the Fortran built-in
operators.  All user defined infix operators have the same precedence - 
and it's lower than any of the built-in operators.  That's a simple
enough rule.

As for your examples: most of my number theory books represent the
greatest common devisor of A and B as `(A,B)' or even GCD(A,B).
I'm not aware of any commonly used operator for GCD nor of any
number theory texts which use it.  Similarly, roots are given 
in number mathematical notation with an overbar on the radical 
which covers the argument of the root - that is, no precedence
ordering is necessary since the argument is explicitly specified.
Once again `root(N,arg)' for the Nth root of arg seems more
natural than any operator syntax. Etc..

|> [...]
|> I disagree.  But I'd probably agree if I had to use Fortran's crippled
|> data types -- there's just too much bookkeeping required for operator
|> syntax to be very useful.

I consider J's treatment of type to be crippled.  It gives me (so far
as you've presented) inadequate control over the operational use of
data.  Something like Fortran (or Ada, C, Pascal, Modula, etc.) is
much preferable to the "typeless" identifier system used in J.

|> [...]
|> >  Some of these cannot be done on arrays of arbitrary rank.
|> >  Transposition, for example, makes no sense for arrays of rank less
|> >  than two.
|> 
|> It's an identity operation on arrays of rank less than two.  That's
|> different, in my opinion, from "makes no sense".

It generally makes no sense to explicitly apply an identity operation.
If you know the type of your argument ahead of time, you don't bother.
If you don't know your type ahead of time, your code will be inefficient
and likely buggy since you're coding in the dark.

|> [...]
|> >  So, the use of these operations requires _some_ static knowledge of
|> >  the rank of the arguments.  This static knowledge should be encoded
|> >  explicitly into the function definition so that the optimizer has a
|> >  chance of producing good code.
|> 
|> Most likely the static information will be explicitly encoded into
|> either the function definition or the code which uses that definition.

So far, you have not presented _any_ method of doin
g so in J.  If such
a capability exists, please present it.
|> [...]
|> If not, and if the user determines that that particular function is
|> time critical, then the user can nail down additional aspects of the
|> function.  But remember that usually only a small fraction of any
|> major piece of code is time critical.

From what you've presented so far, _any_ component of a program which
is written in J seems likely to me to be the largest time consumer
of the ewntire programming environment - even if it's rarely used.

|> [...]
|> >  Other operations (like the arithmetical operations and the item
|> >  counts) don't depend on rank at all - they can be applied to the
|> >  array as if it were rank one.  Such a coercion in the procedure
|> >  call mechanism was already possible in Fortran 77.
|> 
|> Well, this depends on your definition of an item.  I use 'item' to
|> mean a sub array (whose dimension may be obtained by dropping the
|> first dimension of the original array).  I use the term 'atom' to mean
|> a scalar element of an array.  For example, if I've a rank 5 array, I
|> may wish to add each of its items a rank 4 array.

That's what I said.  Your rank 5 array is a rank one array whose elements
are large.  Fortran 90 has a way of doing that.

|> [...]
|> As I understand it, this definition has nothing to do with the
|> intuition of somebody who's never learned what the operation does.

I'm not interested in novice programmers per se.  I'm interested in
_expert_ programmers.  But you're right, the decision of whether the
default semantics of arrays is row-wise of column-wise does not effect
novices - so the natural column-wise ordering should be chosen since
that's what most _existing_ programmers are familiar with.

|> [...]
|> catenate will append two arrays of the same rank, or it will append an
|> item onto an array.  If you wish to append a length three vector to a
|> 3x3 array, you would need to define an operation which appends each
|> item of the 3 element vector to the corresponding item of the 3x3
|> array.  This might be done as follows:
|> >       vector   ,"_1  array
|> 
|> Here, 'comma rank minus-one' defines the desired operation.

You mean `comma quote underscore one'.  And, I don't know what this
does, but it appears to explicitly denote a direction - which is what 
I said _should_ be done.  You have presented an example which supports
my position which was that there should be no default direction for
those operations for which no `natural' default exists.

|> [...]
|> The advantage of this rule is 'rank' has a consistent and easily
|> understandable definition which is usable with any operation in the
|> language.  No exceptions are needed.

I still don't understand what it does.  Does it apply to the vector
or to the array?  

|> [... generic function definitions ...]
|> Why bother?  You've added verbosity, but I don't see that you've added
|> functionality. [...]

Exactly.  I _wanted_ the function to be more verbose so that I can
read the code several months later (or read other people's code) and
have a chance of seeing what it means.  It also gives more explicit
information to the compiler for optimization purposes.   

You gave no J example of the code to do this operation, but I suspect 
it will contain no clues at all about the rank of it's arguments - and 
therefore provide neither the compiler nor the programmer any idea what's 
going on.  Further, the example was stated as requiring a function to 
handle arrays of rank 4 through 7 - without an run-time test, how does 
your J code insure that arrays of rank greater than 7 aren't incorrectly 
passed?

J. Giles
Newsgroups: comp.lang.misc