[comp.lang.c] NOT Educating FORTRAN programmers to use C

kurtk@tekcae.CAX.TEK.COM (Kurt Krueger) (01/09/90)

In article <1024@sdrc.UUCP> spabdul@sdrc.UUCP (abdul shammaa) writes:

> How do you convince your managment that it's time to throw away the
> ancient FORTRAN 4 when there are thousands and thousands of lines of that
> crap :-( ?! To make matters worse, most to the developers are those who
> fear "C" or just don't want to change.  I am getting sick and tired of
> looking at variable names that look like: I1, I2, KK, IKK, RR etc.. and
> at GOTO statments that you have to use in FORTRAN 4.  You may be asking
> why FORTRAN 4? Well, because as the upper managment puts it "Our software
> has to run on so many hardware platforms".  That's true, BUT, I don't
> believe that that reason should keep up in the middle ages of software
> technology.

>  ...   Mind you these are CAE applications which are
> complex by nature.  So one need not the added burden and limitations of
> the programming language itself.


That is probably the BEST argument to keep the implementation in Fortran.
CAE applications are complex and tend to require a lot of the processor.  With
the exception of UNIX, you tend to get the best performance with the Fortran
compiler.  Your management is no dummy. I know you don't like this, but these
are current time facts of life.

Most of your definition of 'crap' in Fortran is the style of the programmer.
I can generate 4x that type of 'crap' in C.  Fortunately, the SCIENCE of
computer programming was upon us before C became popular, it was entirely an
ART when Fortran came about.  Thus 'crap' was acceptable in Fortran 4, but not
so in C.  It is not acceptable in f77 (but that doesn't stop anyone).

It might enlighten you to read a book by Kernighan (THE K in K&R) and Plauger
called "The Elements of Programming Style".  It's about (GASP!) Fortran.
Shows the difference between good Fortran and 'crap'. Too late for the ignorant
type who used 200+ GOTO's.  If the dyed-in-the-wool Fortran programmers in
you organization haven't read it, they should.

I'm  still a firm believer that if you want performance on multiple
platforms, Fortran (but f77 PLEASE!) is still the way to go.  Fortran
does some things real nice (try passing a variable dimensioned 3-d
array into a C function - UGH!, or dealing with COMPLEX variables),
and some things are ugly (f77 does not support dynamic memory
allocation or pointers, but all argument passing is by pointers, and it does
support pointers to functions (via EXTERNAL)).  The optimizers are generally
VERY good at turning array reference operations into the equivalent C pointer
reference.

This argument will weaken as years go by, but it could very well be a
different language than C that we will be discussing.  I guarantee that
Fortran will still be the 'other' language discussed.

One last question  - are you sure that you don't fear Fortran and don't want
to change?

(My credentials - 15 years Fortran on CDC equipment (excellent Fortran, no C)
 3 years C on Unix.  Language of choice - DEPENDS ON THE APPLICATION.  When
 it's a push, I'll use C.  If it's bsd Unix, I do my best to avoid f77)

_______________________________________________________________________________

--- Lively discussion welcomed, personal attacks to /dev/null

dmocsny@uceng.UC.EDU (daniel mocsny) (01/09/90)

In article <5303@tekgen.BV.TEK.COM> kurtk@tekcae.CAX.TEK.COM (Kurt Krueger) writes:
>It might enlighten you to read a book by Kernighan (THE K in K&R) and Plauger
>called "The Elements of Programming Style".  It's about (GASP!) Fortran.
>Shows the difference between good Fortran and 'crap'. Too late for the ignorant
>type who used 200+ GOTO's.  If the dyed-in-the-wool Fortran programmers in
>you organization haven't read it, they should.

I have seen FORTRAN "de-spaghetti-fier" utilities advertised, e.g.,
from Cobalt Blue. These programs purport to transform such FORTRAN
'crap' into cleanly structured (insofar as such is possible)
FORTRAN code. If these programs work, then it's never "too late" for 
the code with 200+ GOTO's.

Does anyone have experience with such programs?

Also, I think being unhappy with someone else's choice of language is
a problem the computer should be able to solve. I.e., we should find
ways to use computers as tools to allow each individual to structure
his/her own sensory environment to his/her liking, while still
retaining the ability to communicate coherently with people who choose
to structure their sensory environments in different ways. Obviously
we are a long way from being able to do that---we couldn't imagine
a big project getting too far off the ground if one programmer
thought/wrote in C, the next in Lisp, the next in Snobol, the next
in FORTRAN, etc. However, I think the programming community as a whole
has *vastly* overlooked the scope for using language translators to
assist the programmer in working with someone else's foreign code in
the way (s)he prefers.

Sorry for this slight detour from the proper domain of this newsgroup.
But when I see debates over which language programmers should use, I
wonder why the debaters automatically assume the errant programmers
must assume the entire burden for changing their ways. If constructs
in one language map 1:1 onto constructs in another, then who cares
which language a programmer prefers? If a project requires specific
language features that are outside of this directly-mappable core
subset, the programmers have to change. But even then, the best way to
get a feel for a new language is to take some familiar code you wrote
in your old language and see what it looks like in the new. 

Dan Mocsny
dmocsny@uceng.uc.edu

tps@chem.ucsd.edu (Tom Stockfisch) (01/10/90)

In article <5303@tekgen.BV.TEK.COM> kurtk@tekcae.CAX.TEK.COM (Kurt Krueger) writes:
>In article <1024@sdrc.UUCP> spabdul@sdrc.UUCP (abdul shammaa) writes:
>> why FORTRAN 4? Well, because as the upper managment puts it "Our software
>> has to run on so many hardware platforms".  That's true, BUT, I don't
>> believe that that reason should keep up in the middle ages of software
>> technology. ...   Mind you these are CAE applications which are
>> complex by nature.  So one need not the added burden and limitations of
>> the programming language itself.

>That is probably the BEST argument to keep the implementation in Fortran.
>CAE applications are complex and tend to require a lot of the processor.  With
>the exception of UNIX, you tend to get the best performance with the Fortran
>compiler.

Is this really still true?  Apart from Cray work, I have found I can write
things to run faster or at least the same speed in C.
Also, I wouldn't classify UNIX as an "exception."

>Most of your definition of 'crap' in Fortran is the style of the programmer.

But there is no way to write a loop in Fortran without using statement labels.
And misspelled variable references result in definitions of new variables
initiallized to zero.

>I can generate 4x that type of 'crap' in C.

I agree.  Getting an old f77 type to switch to C must be accompanied by
teaching them how to write reasonable code.

>It might enlighten you to read a book by Kernighan (THE K in K&R) and Plauger
>called "The Elements of Programming Style".

Isn't this the book that preaches to make it right before you make it fast?
Also, this ignores the importance of memory complexity, where malloc()
helps out enormously.  In Monte Carlo simulations I have done recently
on an 8meg machine, the most
important thing to do was to reduce memory requirements so the program
could run in the background without swapping.  This made orders of magnitude
difference in run time.

>I'm  still a firm believer that if you want performance on multiple
>platforms, Fortran (but f77 PLEASE!) is still the way to go.

I've heard this time and again, and I don't think it is true any longer,
except possibly for vectorizing machines.  I've used machines that didn't
*have* a fortran compiler.

>Fortran does some things real nice (try passing a variable dimensioned 3-d
>array into a C function - UGH!

double	arr1[10][20][30], arr2[40][50][60];

main()
{
	int	m1, m2, m3;
	double	*arr3;	/* really m1Xm2Xm3 */

	doSomething( &arr1[0][0][0], 10, 20, 30 );
	doSomething( &arr2[0][0][0], 40, 50, 60 );
	getSizes( &m1, &m2, &m3 );
	arr3 =	(double *)malloc( m1*m2*m3*sizeof(double) );
	doSomething( arr3, m1, m2, m3 );
	...
}

void
doSomething( a, nlayer, nrow, ncol )
	double	*a;
#		define A(i,j,k) a[ ((i)*nrow + (j))*ncol + (k) ]
{
	...
	A(1,2,3) =	...
	...
}

As illustrated, fortran's variable-dimensioned array arguments can be
simulated in C with little effort.  Simulating dynamically allocated
arrays in Fortran is extremely difficult.

> , or dealing with COMPLEX variables),

>The optimizers are generally
>VERY good at turning array reference operations into the equivalent C pointer
>reference.

They can not reasonably perform this optimization for arrays of indices,
such as might be used in a pivoting scheme for Gaussian elimination.

>This argument will weaken as years go by, but it could very well be a
>different language than C that we will be discussing.  I guarantee that
>Fortran will still be the 'other' language discussed.

Fortran what? 4?, 77?, eighty-twelve?  The "other language", in a few years
will probably be C++ (unless I'm being overly optimistic), which has
much more in common with C than F-whateve-comes-after-77 has in common
with F77.
-- 

|| Tom Stockfisch, UCSD Chemistry	tps@chem.ucsd.edu

jlg@lambda.UUCP (Jim Giles) (01/10/90)

From article <646@chem.ucsd.EDU>, by tps@chem.ucsd.edu (Tom Stockfisch):
> [...]                       Apart from Cray work, I have found I can write
> things to run faster or at least the same speed in C.

Then, whoever wrote the Fortran compiler on those machines was either
incompetent or (more likely) he foolishly used the same 'backend' as
the C compiler.  C is inherently slower because extensive pointer use
inhibits optimizations.  The optimizations most affected are pipelining
and vectorization (so now you see why Fortran still beats C on the Cray).
most C compilers don't even bother trying certain optimizations because
the compiler writer felt the time would be wasted since the presence
of pointers would usually inhibit the optimization anyway.

Note: one other small point - at least in principle, Fortran should
be faster at character manipulation than C.  This is because Fortran
character type can keep explicit lengths of all strings and, therefore,
omit prescanning.  A C user can go out of the way to keep string
lengths too - but usually doesn't.  The only built-in string feature
in the C language is the string constant - which uses the less efficient
null termination method for string lengths.

Aside from the above two issues Fortran and C are identical with
respect to optimization.  A C program which uses no pointers should
(at least in principle) not suffer any inhibitions to optimizations.
How common such C programs are (and how common such a style might
become) I leave to your judgement.

> [...]
>>Most of your definition of 'crap' in Fortran is the style of the programmer.
> 
> But there is no way to write a loop in Fortran without using statement labels.
> And misspelled variable references result in definitions of new variables
> initiallized to zero.

Yes, and the same sort of errors (a slip of the finger while typing) can
cause serious problems in C as well.  Besides, most Fortran compilers
now have an IMPLICIT NONE statement which will cause the compiler to
require declaration of all variables and procedures used in the body
of the program (we are still lobbying X3J3 to require IMPLICIT NONE
in Fortran 8x).

As for loops without labels, Fortran 8x _will_ have a complete complement
of label-less flow control constructs.  I doubt that any future C will
have pointerless array manipulation though (that's one of the differences
between the two languages - one is striving to improve, the other thinks
it's already perfect).

> [...]
>>I can generate 4x that type of 'crap' in C.
> 
> I agree.  Getting an old f77 type to switch to C must be accompanied by
> teaching them how to write reasonable code.

If reasonable coding is a prerequisite for using C, then most C users
haven't met the grade yet.  Actually, neither language has a monopoly
on bad programmers - nor on good ones!  Poor Fortran programmers tend
to use GOTO too liberally and in inappropriate ways.  Poor C programmers
tend to do the same thing with pointers (the GOTO of data structuring).
Fortran programmers tend to write monolithic programs, C programmers
tend to fragment theirs.  -- Etc..

> [...]
>>It might enlighten you to read a book by Kernighan (THE K in K&R) and Plauger
>>called "The Elements of Programming Style".
> 
> Isn't this the book that preaches to make it right before you make it fast?

And quite right too!  What's the use of getting the wrong answer at
lightning speed?  Debug the code _first_, then make it fast - since
optimizations often obscure the structure of the program.

> [...]
> Also, this ignores the importance of memory complexity, where malloc()
> helps out enormously.  [...]

I don't see how malloc helps in complexity.  Dynamic memory is _always_
more complex than static memory.  The only way dynamic memory is useful
is for objects whose size _can't_ be known at compile time or for large
items which aren't in use simultaneously (and you want to keep your 
program size small.  Either way, you code becomes _more_ complex when
you use dynamic memory.

Besides, malloc isn't part of C - it's part of the support library.
If your Fortran has access to a LOC function (I have written LOC
functions for systems that _didn't_ have it), and if you can turn
off array bounds checking, then Fortran can even use malloc!

C still has the problem that malloc() returns a pointer to the new
space and that any code using the dynamically allocated space has its
optimizations inhibited by that.  The Fortran 8x proposal has allocatable
arrays which _aren't_ associated with pointers.  This will permit the
code to be optimized just as if static arrays _only_ were used.

> [...] 
>>Fortran does some things real nice (try passing a variable dimensioned 3-d
>>array into a C function - UGH!
> double	arr1[10][20][30], arr2[40][50][60];
> main() {
> 	int	m1, m2, m3;
> 	double	*arr3;	/* really m1Xm2Xm3 */
> 	doSomething( &arr1[0][0][0], 10, 20, 30 );
> 	doSomething( &arr2[0][0][0], 40, 50, 60 );
> 	getSizes( &m1, &m2, &m3 );
> 	arr3 =	(double *)malloc( m1*m2*m3*sizeof(double) );
> 	doSomething( arr3, m1, m2, m3 );
>   ... }
> void
> doSomething( a, nlayer, nrow, ncol )
> 	double	*a;
> #		define A(i,j,k) a[ ((i)*nrow + (j))*ncol + (k) ]
> {
> 	...
> 	A(1,2,3) =	...
> 	...
> }

You're taking it on faith that your optimizer can do strength reduction
and get those multiplies out of loops.  Most Fortran compilers special
case the array indices - even if they don't otherwise do any strength
reduction.  I've seen a lot of C compilers that don't do strength
reduction at all.  This is simply an implementation issue though
and not a valid point of comparison for the two languages.

However, there _is_ a valid point to be raised here: you must define
macros such as above for each array argument that gets passed and
again in each other procedure that uses them.  Since this is extra
work that isn't required in Fortran, there is a potential for error
here that Fortran doesn't present.  For example: on my keyboard,
plus '+' and equal '=' are on the same key - suppose I mistype
the first plus in the macro as an equal?  The compiler won't catch
it!  (I use this example because I've actually seen it done - it took
several manhours to track down the problem.)

The "structured programming" rule that C violates in this case is:
"If it's something simple that the machine can do automatically,
the let the machine do it - don't take any chances on possible 
user error."

> [...]
> As illustrated, fortran's variable-dimensioned array arguments can be
> simulated in C with little effort.  Simulating dynamically allocated
> arrays in Fortran is extremely difficult.

Not at all!  The syntax compares one for one:

    C                         Fortran

   *p                         MEM(P)
   *(p+i)                     MEM(P+I)
   p=malloc(amount)           P=MALLOC(AMOUNT)
   ...                        ...

At least, for a properly written Fortran version of MALLOC.  Note that
the syntax is nearly identical except '*' is spelled 'MEM' and the
parenthesis are required in dereferencing even for just the pointer.
Of course, the Fortran compiler is required to do some things that
are automatic with C (like scaling the pointer arithmetic), but if
the previous example was considered an adequate replacemment for
Fortran arrays, then this should do nicely as a replacement for
C's pointers.
 
> [...] 
>>The optimizers are generally
>>VERY good at turning array reference operations into the equivalent C pointer
>>reference.

I disagree with this.  The compiler sould be able to do _better_ than the
C pointering scheme does - no pointer aliasing!

> [...]
> They can not reasonably perform this optimization for arrays of indices,
> such as might be used in a pivoting scheme for Gaussian elimination.

A survey of 100+ production programs indicates that over 90% of all array
indexes are simple loop itertation variables or linear combinations of
loop iteration variables.  The gather/scatter problem you refer to _is_
important.  Nevertheless, a compiler which 'special cases' array index
calculations will find a lot of reward in execution speed.

>>This argument will weaken as years go by, but it could very well be a
>>different language than C that we will be discussing.  I guarantee that
>>Fortran will still be the 'other' language discussed.
> 
> Fortran what? 4?, 77?, eighty-twelve?
> [...]

Actually, it makes a LOT more sense for a Fortran shop to wait for
Fortran 8x than it does for them to switch to C.  The conversion
would be easier, for starters.  I currently oppose the 8x proposal
because it contains features which will severly cripple the language.
Assuming they get rid of these though, the proposal will address all
the deficiencies you remarked upon - somtimes in ways considerably
better than what's available in C (like allocatable arrays).

Frankly, I don't see any reason for someone who is satisfied with
C to switch to Fortran either (any version).  Neither language is
_better_ than the other.  They are simply different.  Each has
strengths and weaknesses that the other doesn't.  I certainly would
not recommend that working code in _either_ language be targeted
for conversion into something new until such time a a language comes
along which really _is_ better than these are.

> [...]                          The "other language", in a few years
> will probably be C++ (unless I'm being overly optimistic), which has
> much more in common with C than F-whateve-comes-after-77 has in common
> with F77.

You don't sound optimistic to me.  C++ is not very good.  Objective C
is marginally better.  I was hoping for a language without C's awful
syntax and with real data structuring ability (which neither C nor
Fortran have).  For one thing, I'd like to be forced into using pointers
only when pointers are what I really want.  Object Oriented programming
features are welcome when they become muture - preferably with a _much_
cleaner implementation than C++ provides.  Polymorphism and encapsulation
can be better provided by generic functions with late-binding permitted.
If you could add inheritance without going to objects, it might make a
better language in the long run.

chris@mimsy.umd.edu (Chris Torek) (01/10/90)

(Since I refuse to be baited by jlg, I will not respond to most of
this, but one point, at least, requires a followup.)

In article <14186@lambda.UUCP> jlg@lambda.UUCP (Jim Giles) writes:
>C is inherently slower [than FORTRAN] because extensive pointer use
>inhibits optimizations.

Like all sweeping statements, this one (actually `these two') is
(are) false.

There is a large class of machines on which pointers are as efficient
as, or or more efficient than, arrays, and on which the optimisations
made possible by knowing that two FORTRAN arrays are not aliased---
this is the big one; arrays, passed to subroutines by address, are
often not known not to interfere with each other in C, so compilers are
hard-pressed to use hardware vector instructions---simply do not exist.

There is a large class of problems, too, which cannot make use of
vector instructions.  Only for those problems that can, on those machines
that can, is this a significant loss.

(This of course is what `noalias' was all about.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

jlg@lambda.UUCP (Jim Giles) (01/11/90)

From article <21730@mimsy.umd.edu>, by chris@mimsy.umd.edu (Chris Torek):
> In article <14186@lambda.UUCP> jlg@lambda.UUCP (Jim Giles) writes:
>>C is inherently slower [than FORTRAN] because extensive pointer use
>>inhibits optimizations.
> 
> Like all sweeping statements, this one (actually `these two') is
> (are) false.
> 
> There is a large class of machines on which pointers are as efficient
> as, or or more efficient than, arrays, [...]

Like many C supporters, Chris Torek tends to confuse wishful thinking
with facts.  The above "large class of machines" is actually increasingly
narrow.  Even cheap home computers are starting to be built with pipelining
CPUs in them.  Many intermediate range machines are becoming available
which are vector archetectures.

Even on the class of machines that Chris Torek is talking about, the
use of pointers is not "as efficient as, or or more efficient than, arrays".
The weakness of this claim is that, on the machines he is discussing,
arrays and pointer manipulation are semantically _identical_!  So the
best you can hope for, given equal quality implementation, is exactly
equal performance.

> [...]
> There is a large class of problems, too, which cannot make use of
> vector instructions.  Only for those problems that can, on those machines
> that can, is this a significant loss.

There is an even larger class of problems which can be, at least,
partially vectorized.  And nearly all problems can benefit from
code movement optimizations on pipelined machines (at least, if
pointer usage hasn't inhibited such optimizations).

> [...]
> (This of course is what `noalias' was all about.)

Exactly right.  But the last I heard, 'noalias' had been deleted from
the proposed standard.  I've not seen any C compilers with it yet.

Even if 'noalias' were to become part of the standard, this would still
only mean that Fortran programmers could not expect anything more than
equal performance from the massive expense of moving to C.  Hardly a
reason to switch.

J. Giles

tps@chem.ucsd.edu (Tom Stockfisch) (01/11/90)

In article <14186@lambda.UUCP> jlg@lambda.UUCP (Jim Giles) writes:
>From article <646@chem.ucsd.EDU>, by tps@chem.ucsd.edu (Tom Stockfisch):

>....  C is inherently slower because extensive pointer use
>inhibits optimizations.  The optimizations most affected are pipelining
>and vectorization (so now you see why Fortran still beats C on the Cray).
>most C compilers don't even bother trying certain optimizations because
>the compiler writer felt the time would be wasted since the presence
>of pointers would usually inhibit the optimization anyway.

In the absence of vectorization, I don't think pointer aliasing is a
significant hindrance to optimization.  With vectorization, you
need some sort of "noalias" pragma.  There are, after all,
vectorizing compilers for the Cray and other vector machines.

>Note: one other small point - at least in principle, Fortran should
>be faster at character manipulation than C.

You write character manipulation programs in Fortran?

>The only built-in string feature
>in the C language is the string constant - which uses the less efficient
>null termination method for string lengths.

The standard allows str*() to be built-in.

>Aside from the above two issues Fortran and C are identical with
>respect to optimization.

I have worked on a machine that has a double-word fetch instruction.  It
works only on double-word boundaries.  Fortran cannot make use of it
because the 77 standard allows any two consecutive members of
a real array to be equivalenced as a double precsion array.  Double
precision memory fetches with fortran then require two fetch instructions,
taking almost twice as long.  The problem is compounded by the fact that
the machine has dual processors which must share a single memory bus.
A reasonable C implementation on this machine would simply require
type "double" to be aligned on 8 byte boundary.

>> And misspelled variable references result in definitions of new variables
>> initiallized to zero.

[Someone pointed out my partial error here, the new variable is not 
guaranteed to start off zero]

>Yes, and the same sort of errors (a slip of the finger while typing) can
>cause serious problems in C as well.

I have never found a C typo as insidious.  If you type "+" for "=" it
should be obvious when you proofread.  There is also a decent chance
you'll get a syntax error.  When you type "leng" instead
of "len" in Fortran, you may forget exactly how you abbreviated
"length" and stare at it for hours without seeing what's wrong.
What's more, it is guaranteed that you *won't* get a syntax error.

>Besides, most Fortran compilers
>now have an IMPLICIT NONE statement

Given that it is Not Portable, I won't use it.

>(we are still lobbying X3J3 to require IMPLICIT NONE
>in Fortran 8x).

Good for you.

>As for loops without labels, Fortran 8x _will_ have a complete complement
>of label-less flow control constructs.  I doubt that any future C will
>have pointerless array manipulation though (that's one of the differences
>between the two languages - one is striving to improve, the other thinks
>it's already perfect).

I think it is only fair to compare Fortran 8x to C++, not C.

>Poor Fortran programmers tend
>to use GOTO too liberally and in inappropriate ways.  Poor C programmers
>tend to do the same thing with pointers (the GOTO of data structuring).

"Address Of" considered harmful?

>> Also, this ignores the importance of memory complexity, where malloc()
>> helps out enormously.  [...]

>I don't see how malloc helps in complexity.  Dynamic memory is _always_
>more complex than static memory.  The only way dynamic memory is useful
>is for objects whose size _can't_ be known at compile time or for large
>items which aren't in use simultaneously (and you want to keep your 
>program size small.  Either way, you code becomes _more_ complex when
>you use dynamic memory.

I was talking about complexity theory "complexity".  Fortran programs
must be compiled to use the maximum amount of memory someone might
ever want, or be faced with requiring the source to be re-edited
and re-compiled.  This wastes memory.  As I pointed out, wasting
memory can waste a lot of time if swapping occurs.

>Besides, malloc isn't part of C - it's part of the support library.

It's officially part of standard C.  It has been de facto part of
pre-standard C.

>If your Fortran has access to a LOC function (I have written LOC
>functions for systems that _didn't_ have it), and if you can turn
>off array bounds checking, then Fortran can even use malloc!

Highly unportable.

>C still has the problem that malloc() returns a pointer to the new
>space and that any code using the dynamically allocated space has its
>optimizations inhibited by that.  The Fortran 8x proposal has allocatable
>arrays which _aren't_ associated with pointers.  This will permit the
>code to be optimized just as if static arrays _only_ were used.

I don't see why a noalias pragma can't fix that.

>>>Fortran does some things real nice (try passing a variable dimensioned 3-d
>>>array into a C function - UGH!
>> void
>> doSomething( a, nlayer, nrow, ncol )
>> 	double	*a;
>> #		define A(i,j,k) a[ ((i)*nrow + (j))*ncol + (k) ]
>> {
>> 	...
>> 	A(1,2,3) =	...
>> 	...
>> }

>You're taking it on faith that your optimizer can do strength reduction
>and get those multiplies out of loops.

This is just an example that shows it isn't too painful to do.  I might
write the code differently if I thought the addressing scheme was
to slow.

>However, there _is_ a valid point to be raised here: you must define
>macros such as above for each array argument that gets passed and
>again in each other procedure that uses them.  Since this is extra
>work that isn't required in Fortran, there is a potential for error
>here that Fortran doesn't present.

Certainly on balance, C saves effort by being more expressive.  Adding
a few extra characters in a declaration does not seem to terrible to me.
It is more than offset by being able to say

	A( i+j, k-1, l/2 +7 ) +=	x

instead of

	A( i+j, k-1, l/2 +7 ) = A( i+j, k-1, l/2 +7 ) +	x

>For example: on my keyboard,
>plus '+' and equal '=' are on the same key - suppose I mistype
>the first plus in the macro as an equal?  The compiler won't catch
>it!

Yes it will.  "(i)*nrow" is not an lvalue.

>(I use this example because I've actually seen it done - it took
>several manhours to track down the problem.)

I don't understand why.  "+" doesn't look anything like "=".  If you
mistype an operator, I don't think you can reasonably expect the
compiler to catch it for you.  What if you type "+" for "-"?
The =/== typo is probably a better criticism, although lint usually
can catch it and people who work mostly with C tend not to do it.

>> As illustrated, fortran's variable-dimensioned array arguments can be
>> simulated in C with little effort.  Simulating dynamically allocated
>> arrays in Fortran is extremely difficult.
>
>Not at all!  The syntax compares one for one:
>
>    C                         Fortran
>
>   *p                         MEM(P)
>   *(p+i)                     MEM(P+I)
>   p=malloc(amount)           P=MALLOC(AMOUNT)
>   ...                        ...

What do you use for "[]"?

>Of course, the Fortran compiler is required to do some things that
>are automatic with C (like scaling the pointer arithmetic), but if
>the previous example was considered an adequate replacemment for
>Fortran arrays, then this should do nicely as a replacement for
>C's pointers.

Not at all.  The C macro is perfectly portable, the fortran MALLOC
is completely unportable.

>Actually, it makes a LOT more sense for a Fortran shop to wait for
>Fortran 8x than it does for them to switch to C.

How many years will they have to wait for Fortran 8x?
How many more years after that before stable compilers exist on
most machines?  From what I've heard, Fortran 8x might be,
like Ada, way too difficult to implement.

>I currently oppose the 8x proposal
>because it contains features which will severly cripple the language.
>Assuming they get rid of these though,

Is progress being made on revamping the proposal?

>I certainly would
>not recommend that working code in _either_ language be targeted
>for conversion into something new until such time a a language comes
>along which really _is_ better than these are.

Depends on the code.  I would probably leave most numerical Fortran
programs alone.  A compiler written in Fortran I would probably
translate to something else or rewrite from scratch.

>> [...]                          The "other language", in a few years
>> will probably be C++ (unless I'm being overly optimistic), which has
>> much more in common with C than F-whateve-comes-after-77 has in common
>> with F77.
>
>You don't sound optimistic to me.  C++ is not very good.  Objective C
>is marginally better....  Object Oriented programming
>features are welcome when they become muture

I think C++ is extremely useful right now.  Exception handling would
be very nice, but the Object Oriented stuff already available is fine.

>- preferably with a _much_
>cleaner implementation than C++ provides.

Fortran8x will have a cleaner implementation than C++?
-- 

|| Tom Stockfisch, UCSD Chemistry	tps@chem.ucsd.edu

karl@haddock.ima.isc.com (Karl Heuer) (01/12/90)

In article <14186@lambda.UUCP> jlg@lambda.UUCP (Jim Giles) writes:
>...at least in principle, Fortran should be faster at character manipulation
>than C.  [null-terminated strings are less efficient]

It depends on what operations you're trying to perform.  Some are faster with
counted strings, others with null-terminated strings.

Karl W. Z. Heuer (karl@haddock.isc.com or ima!haddock!karl), The Walking Lint

jlg@lambda.UUCP (Jim Giles) (01/12/90)

From article <649@chem.ucsd.EDU>, by tps@chem.ucsd.edu (Tom Stockfisch):
> In the absence of vectorization, I don't think pointer aliasing is a
> significant hindrance to optimization.

In a previous article I made the incorrect statement that the number
of machines which can be well optimized in the presence of pointers
is growing narrow.  The fact is that the set of such machines is zero
(at least, to the best of my knowledge).  Consider the following code:

   z=1;
   *a=2;
   *b=1;

If you could tell that a and b were not aliased (to each other
or to z), the the generated code would be to set a register to
one, store z, store b, increment, and store a.  However, if you
can't detect aliasing the sequence must be in the order given.
On all machines I know, this would require at least one more
instruction - so even on a RISC machine with no pipelining or
vectorization to worry about this code would be 20% slower because
of the possibility of aliasing.  If these were arrays and this
sequence of code were in an inner loop, this slowdown could
strongly effect the whole code's performance.

The truth is, any machine which has registers to schedule,
program control over cache management, pipelining, or vectors
can be effected by aliasing.  The severity of the effect depends
on the program.

> [...]                                With vectorization, you
> need some sort of "noalias" pragma.  There are, after all,
> vectorizing compilers for the Cray and other vector machines.

Pragmas are non-portable and require explicit user intervention
(which merely presents another opportunity for user error).
Other than that, 'noalias' is useful on ALL machines and will
probably only _ever_ be available on a small percentage.

> You write character manipulation programs in Fortran?

Why not?  It's as fast as the fastest mechanism C has for Characters
(or should be), it has built-in concatenate and substring syntax
(instead of C's clumsy looking function calls for these features),
and it's widely regarded as something that Fortran did (nearly)
right - even by people who otherwise don't like Fortran.

> The standard allows str*() to be built-in.

Most ANSI standards allow additional features to be implemented in
a conforming processor.  I don't consider these extensions to be
an inherent part of the language.  C also allows the user to define
additional data types - something which really _is_ lacking in Fortran.

However, the only built-in feature of C which pertains to character
strings are character string constants - which are implemented a
null terminated sequences denoted by character pointers.  This
also happens to be the usual implementation of strings by most C
programmers.  In fact, this is such a common choice that most
people _assume_ a pointer to a null terminated string is what
is meant by the phrase "character string".  This implementation
is less effecient than that used by most Fortrans (or Pascals,
Modulas, etc. for that matter).

However, as I said in my original posting, this is a secondary
issue since a careful C programmer _can_ handle strings efficiently
(even though most don't).

> 
>>Aside from the above two issues Fortran and C are identical with
>>respect to optimization.
> 
> I have worked on a machine that has a double-word fetch instruction.  It
> works only on double-word boundaries.  Fortran cannot make use of it
> because the 77 standard allows any two consecutive members of
> a real array to be equivalenced as a double precsion array.  Double
> precision memory fetches with fortran then require two fetch instructions,
> [...]

I too have worked on such machines.  What you're saying is hogwash.
Unless the implementor was an idiot, he would _always_ allocate double
precision variables on double word boundaries.  The only time he would
fai to do so would be if the double _really_was_ equivalanced to a
single word object.  Even THEN he would insert a "dead" word in the
memory allocation so that the double word objects were properly aligned.
The only way for optimization to be inhibited would be if he equivalenced
two different double word objects to an array of singles - AND the two
equivalances were an odd number of words apart!  In this case, most
implementations I've seen will still do the fast loads/stores/ on the
properly aligned data and will issue a warning about the other.

Common blocks are handled slightly differently but, even here, the
compiler can always generate efficient code for properly alligned
doubles and innefficient code (plus a warning message) for improperly
alligned doubles.  The techniques for doing this sort of thing have
been public domain for over 25 YEARS!  If your compiler can't do
this stuff, that's how far out of date it is.

> A reasonable C implementation on this machine would simply require
> type "double" to be aligned on 8 byte boundary.

Which just means that C CAN'T do something that Fortran CAN.  And,
if C DID allow doubles on odd words, it would face the same optimization
problems - worse: because the compiler can't necessarily tell if
a pointer-to-double will be properly aligned until run-time.

So, what I said still applies: except for pointers (and character
constants), both C and Fortran are identically optimizable.

J. Giles

chris@mimsy.umd.edu (Chris Torek) (01/12/90)

In article <14191@lambda.UUCP> jlg@lambda.UUCP (Jim Giles) writes:
-In a previous article I made the incorrect statement that the number
-of machines which can be well optimized in the presence of pointers
-is growing narrow.  The fact is that the set of such machines is zero
-(at least, to the best of my knowledge).  Consider the following code:
-
-  z=1;
-  *a=2;
-  *b=1;
-
-If you could tell that a and b were not aliased (to each other
-or to z), the the generated code would be to set a register to
-one, store z, store b, increment, and store a.

1) you *can* tell aliasing (automatically, in the compiler) in many cases
   (not all).

-However, if you
-can't detect aliasing the sequence must be in the order given.
-On all machines I know, this would require at least one more
-instruction - so even on a RISC machine with no pipelining or
-vectorization to worry about this code would be 20% slower because
-of the possibility of aliasing.

2) even when you cannot, this is false.  The generated code
   would be `store 2 in register z', `store register z in *b',
   `decreemnt register z', `store register z in *a'.

-If these were arrays and this
-sequence of code were in an inner loop, this slowdown could
-strongly effect the whole code's performance.

... and you would simply write

	#pragma nonintersecting a, b

or something similar.

I refuse to read or respond to anything futher from jlg (at least for a few
weeks); it is bad for my blood pressure.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

jlg@lambda.UUCP (Jim Giles) (01/12/90)

From article <649@chem.ucsd.EDU>, by tps@chem.ucsd.edu (Tom Stockfisch):
> I have never found a C typo as insidious.  If you type "+" for "=" it
> should be obvious when you proofread.

So should misspelled identifiers.  This kind of fatuous argument
is _barely worth responding to.  The old "forgotten */" problem with
C is often _very_ insidious.

>>Besides, most Fortran compilers
>>now have an IMPLICIT NONE statement
> 
> Given that it is Not Portable, I won't use it.

You mean like "pragms nolaias", which you mentioned as a solution for
a C problem?  You can't use non-portability as an objection if you
previously recommended a non-portable feature yourself.

Besides, I freely admit that Fortran _should_ have IMPLICIT NONE,
not just as an option, but as the default behaviour!  I don't defend
Fortran's use of implicit declarations.  I'm just pointing out
that C is not free of problems caused by typos just because is
requires all variables to be declared (as _you_ have implied).

>> [... remarks about Fortran trying to improve and C not ...]
> I think it is only fair to compare Fortran 8x to C++, not C.

C++ and Fortran 8x don't compare at all!  They start from different
languages and move in different directions.  Your idea of comparing
them further strengthens my main point: Fortran and C are different
languages with different strengths and weeknesses.  This is even MORE
true of Fortran 8x and C++.  They are aimed at different people using
different problem domains and the users whose problems fall in one
domain would be fools to use the other language.

> 
>>Poor Fortran programmers tend
>>to use GOTO too liberally and in inappropriate ways.  Poor C programmers
>>tend to do the same thing with pointers (the GOTO of data structuring).
> 
> "Address Of" considered harmful?

In fact, YES!  Dijkstra has written articles which might very well
have had that title.  C.A.R. Hoare has written that he doubted that
a language containing pointers could ever be truly called 'structured'.

> [...]
>>Besides, malloc isn't part of C - it's part of the support library.
> 
> It's officially part of standard C.  It has been de facto part of
> pre-standard C.

No.  It's part of the C standard - not part of standard C.  The
distinction is even made in the abstract of the proposed standard:
"Sections are included that detail the C language itself and the
contents of the C language execution library."

The distinction is important because a better way of providing
dynamic memory is to have an 'allocate' feature built into the
language itself which doesn't rely on user-visable pointers (and
their obnoxious tendency toward causing aliasing problems).

> 
>>If your Fortran has access to a LOC function (I have written LOC
>>functions for systems that _didn't_ have it), and if you can turn
>>off array bounds checking, then Fortran can even use malloc!
> 
> Highly unportable.

Agreed, but see below!

> [... argument that 'allocate' is better than malloc() ...]
> 
> I don't see why a noalias pragma can't fix that.

*****************************
> Highly unportable.
*****************************

I copied your own statement from above with my mouse.  What's sauce
for the goose ....

> [... argument that macros instead of real array refs are not good ...]

> Certainly on balance, C saves effort by being more expressive.

Even were I to agree that C is "Certainly on balance" more expressive,
this doesn't address the point that I made!  With respect to arrays
C is _NOT_ more expressive!

> [...]                                                          Adding
> a few extra characters in a declaration does not seem to terrible to me.
> It is more than offset by being able to say
> 	A( i+j, k-1, l/2 +7 ) +=	x
> instead of
> 	A( i+j, k-1, l/2 +7 ) = A( i+j, k-1, l/2 +7 ) +	x

C has existed for nearly 20 years.  The concept of 'expression
languages' has existed for nearly 30.  Yet, most language
designers don't choose to include such operators as above
(though they certainly are aware that they could).  Further,
implementors are constantly barraged with user requests for this
feature as local extensions - so users also seem pretty lukewarm
about these operators.

There have been studies to determine objectively whether such
assignments are helpful or not.  They have all been inconclusive.
It doesn't seem that any failing in the language can be said
to be "more than offset" by the presence of these assignments.
I, personally, regard the existence or absence of this assignment
syntax as completely irrelevant.

Studies have also been done to determine whether assignment should
be an expression-level operator or a statement-level one.  These
have shown that user productivity suffers if the operator is
an expression-level one.  Any possible advantage to having these
operators is probably "more than offset" by this failing.

> The =/== typo is probably a better criticism, although lint usually
> can catch it and people who work mostly with C tend not to do it.

And - people who work mostly with C tend not to use lint very much
either.  I think the two tendencies cancel.  I still can't imagine
why lint isn't built into the compiler.

> [...]
>>    C                         Fortran
>>
>>   *p                         MEM(P)
>>   *(p+i)                     MEM(P+I)
>>   p=malloc(amount)           P=MALLOC(AMOUNT)
>>   ...                        ...
> 
> What do you use for "[]"?

Syntactic sugar - irrelevant to the functionality.
> 
>>Of course, the Fortran compiler is required to do some things that
>>are automatic with C (like scaling the pointer arithmetic), but if
>>the previous example was considered an adequate replacemment for
>>Fortran arrays, then this should do nicely as a replacement for
>>C's pointers.
> 
> Not at all.  The C macro is perfectly portable, the fortran MALLOC
> is completely unportable.

Look again.  The Fortran would have to use non-standard features if
I used C's version of malloc().  But, the above doesn't imply that
I'm doing so.  If worst comes to worst, I _might_ have to statically
allocate the MEM array to a large size - but the above code is
completely portable!  This worst-case scenario would intail swapping
inefficiency (as you pointed out).  However, in 20+ years of programming,
I've _NEVER_ encountered a mainframe or mini which forced me to
statically allocate MEM.  Most actually make it easier by having
a compiler or loader directive like "dyn=MEM".

Meanwhile, if worst comes to worst, _YOU_ might get stuck with a
C compiler that doesn't support "pragma=noalias".  Which language
suffers from its respective failing most often (and what this
costs) I leave to your judgement.

So, I repeat: if your macros are considered an adequate replacement
for arrays, then this scheme should be considered adequate for
dynamic memory.  (I consider _NEITHER_ of these ideas adequate.
I don't support Fortran's lack of dynamic memory any more than
I support C's lack of genuine arrays.  But your claims about
the nature of these deficiencies are not valid.)

> [...] 
>>Actually, it makes a LOT more sense for a Fortran shop to wait for
>>Fortran 8x than it does for them to switch to C.
> 
> How many years will they have to wait for Fortran 8x?

That's not relevant to my remark!  For now, it makes more sense to wait
that it does to switch to C.  Later, it will make more sense to switch
to 8x than to C (or, still to wait, since 8x is supposed to be upward
compatible).

Besides, how many years will you have to wait for ANSI C.  Last I heard
it hasn't been approved yet either.

> How many more years after that before stable compilers exist on
> most machines?

Again, the same might be said about C.  And don't try to tell me that
C is already portable - I know better.  I just watched Cray porting
all the UNIX utilities to UNICOS!  Rumor is that it took more time
than estimated by a factor of 3!  (<- Not 3 factorial, by the way,
just 3. :-)  Apparently, moving from a 32-bit byte addressed machine
to a 64 bit word addressed machine was the main problem.  The C
code apparently hade _LOTS_ of assumptions along those lines.

By the way, the original estimate for porting the software was
based on Cray experience in porting Pascal and Fortran.  It appears
that, in this case, C was less portable than those other languages
by a lot (even if it wasn't a factor of 3 as per rumor, I know that
it was considerably behind schedule).

> [...]                        From what I've heard, Fortran 8x might be,
> like Ada, way too difficult to implement.

No. The only things that are really _new_ are the array syntax
(which is only difficult to implement on vector machines - which
have already received considerable study by the vendors of such
machines anyway), and the pointer facility (which is so bizarre
that no experience with other languages will be of help.  These
are both straightforward to implement, but efficient versions
may take a while.  The whole-array stuff should start out giving
about the same performance as existing equivalent loops - and
should improve from there.  The pointer stuff (as currently given)
will probably _always_ negatively impact performance in those
programs which use it.

Most of the other features are off-the-shelf copies of things done
in other languages (eg. derived types are just like Pascal records
or C structs - Fortran 8x is even simpler by not allowing variants).

> [... I oppose the current proposed Fortran standard ...]
> Is progress being made on revamping the proposal?

No.  The committee apparently believes the public review was sufficiently
positive this time to justify approval.  This, in spite of 1/3 opposed,
1/3 in favor, and 1/3 supporting the proposal in spirit but not liking
many of the new features.  The committee is viewing this as 2/3
approval - I would consider it 2/3 against.  For one thing, the
response has been much smaller this time.  The reason for not responding
that I heard the most was "they ignored my comments the first time,
they probably will again".

> Depends on the code.  I would probably leave most numerical Fortran
> programs alone.  A compiler written in Fortran I would probably
> translate to something else or rewrite from scratch.

I wouldn't rewrite a working compiler under any circumstances.  If
I were to code a compiler, I too wouldn't use Fortran.  I wouldn't
use C either (or C++, or Objective C, or ...).  My choice of existing
languages would be Modula2 or Objective Pascal.  My choice of experimental
languages would be Nemesis (of course - I am one of the designers :-).

> [...]
>>- preferably with a _much_
>>cleaner implementation than C++ provides.
> 
> Fortran8x will have a cleaner implementation than C++?

As I said before, C++ and Fortran 8x are languages which started in a
different place and _diverged_ from there.  Fortran 8x won't have
cleaner Object-Oriented stuff than C++ simply because it won't have ANY!
Objective Pascal is _much_ cleaner than C++.  Unfortunately, it's not
widely available yet.

J. Giles

jlg@lambda.UUCP (Jim Giles) (01/13/90)

From article <21778@mimsy.umd.edu>, by chris@mimsy.umd.edu (Chris Torek):
> In article <14191@lambda.UUCP> jlg@lambda.UUCP (Jim Giles) writes:
> -  z=1;
> -  *a=2;
> -  *b=1;
> 2) even when you cannot, this is false.  The generated code
>    would be `store 2 in register z', `store register z in *b',
>    `decreemnt register z', `store register z in *a'.

This doesn't do what the original code requires.  For one thing,
the original z wasn't a register.  For another, this code puts
the value 2 into *b and the number 1 into z and *a - so if no aliasing
is present, only z get its proper final value.  The only proper code
sequence for the original problem is 'load 1 (accumulator), store z,
increment, store *a, decrement, store *b' - which is one more instruction
than you want in the case where no aliasing has occurred.

Of course, if you machine had a method of storing immediate values directly
into memory (without registers at all), then the sequence could be done
efficiently without worrying about aliasing.  This is rarely the case, and
even so, the example is only a simplified example of how aliasing can
cause register scheduling problems - _real_code_ would present much more
complicated situations.

> [...] 
> ... and you would simply write
> 	#pragma nonintersecting a, b
> or something similar.

You could - if you had pragmas, if the compiler supported this particular
type of pragma, and if you were sure that neither *a nor *b pointed to
z (which isn't obvious from the example given).

> I refuse to read or respond to anything futher from jlg (at least for a few
> weeks); it is bad for my blood pressure.

I can understand that.  If you try to support an invalid position, 
it must get really difficult when you face someone that can detect
the bullsh*t.  

In any case, my original statement still stands -- I can't think of
any machines which don't suffer from inhibited optimization in the
presence of pointers.

J. Giles

karl@haddock.ima.isc.com (Karl Heuer) (01/13/90)

In article <14191@lambda.UUCP> jlg@lambda.UUCP (Jim Giles) writes:
>From article <649@chem.ucsd.EDU>, by tps@chem.ucsd.edu (Tom Stockfisch):
>>[Because the F77 standard allows a double precision array to be equivalenced
>>to an arbitrary point in a real array, double precision objects might not be
>>aligned and hence Fortran cannot make use of the double-word fetch.]
>
>...The only way for optimization to be inhibited would be if he equivalenced
>two different double word objects to an array of singles - AND the two
>equivalances were an odd number of words apart!  In this case, most
>implementations I've seen will still do the fast loads/stores/ on the
>properly aligned data and will issue a warning about the other.

And if the misaligned double is passed (by reference) as an argument to a
separately-compiled function, does it still work?  If so, it seems that the
compiler is forced to assume possible misalignment of doubles received as
formal parameters.  This is not terribly efficient.

>>A reasonable C implementation on this machine would simply require
>>type "double" to be aligned on 8 byte boundary.
>
>Which just means that C CAN'T do something that Fortran CAN.

Much like the way that Fortran CAN'T support a function that can be passed the
same object in two distinct arguments, because it wants to be able to assume
the lack of aliasing.

>And, if C DID allow doubles on odd words, it would face the same optimization
>problems - worse: because the compiler can't necessarily tell if a
>pointer-to-double will be properly aligned until run-time.

You're hypothesizing a feature and then assuming that it would be badly
implemented.  If I were implementing a language extension to allow misaligned
objects (not necessarily restricted to |double|), I would do so with a new
type qualifier |unaligned|.  Given |int unaligned x|, |&x| would have the
type |int unaligned *|, which could not be safely stored in a plain |int *|.
Fetching would be done the "hard way" only if the object has the |unaligned|
qualifier.  If my earlier conjecture about Fortran's assumptions is correct,
this C extension would be more efficient than Fortran.

Karl W. Z. Heuer (karl@haddock.isc.com or ima!haddock!karl), The Walking Lint
Followups to comp.lang.misc.

spabdul@sdrc.UUCP (abdul shammaa) (01/13/90)

In article <5303@tekgen.BV.TEK.COM>, kurtk@tekcae.CAX.TEK.COM (Kurt Krueger)
writes:

> Most of your definition of 'crap' in Fortran is the style of the programmer.
> I can generate 4x that type of 'crap' in C.

Well, anyone can generate bad code regardless of the language.  However, a
good programmer can make C far more readable than FORTRAN 4.  The fact that
variable and function names in C are not limited to six character long makes
life a lot easier.  And I don't mean that you abuse the fact that C does
not_place_a_restriction_on_variable_lengths  :-) That kind of variable
name would be too much.

> computer programming was upon us before C became popular, it was entirely an
> ART when Fortran came about.  Thus 'crap' was acceptable in Fortran 4, but not
> so in C.  It is not acceptable in f77 (but that doesn't stop anyone).
> 
> It might enlighten you to read a book by Kernighan (THE K in K&R) and Plauger
> called "The Elements of Programming Style".  It's about (GASP!) Fortran.
> Shows the difference between good Fortran and 'crap'. Too late for the ignorant
> type who used 200+ GOTO's.  If the dyed-in-the-wool Fortran programmers in
> you organization haven't read it, they should.
> 
> I'm  still a firm believer that if you want performance on multiple
> platforms, Fortran (but f77 PLEASE!) is still the way to go.  Fortran
> does some things real nice (try passing a variable dimensioned 3-d
> array into a C function - UGH!, or dealing with COMPLEX variables),

How about the performance and productivity of the programmer?  Should that
not be taken into account, too?
I am not sure what the difference is in passing a variable dimensioned
3-d array between C or FORTRAN.  On the other hand, COMPLEX variables
are built into FORTRAN, which is nice...But that's why you have structures
in C.  You can build your own little utility that may have any complex
variable operations your heart desires.  Besides, how often, for example,
do you really use complex variables VS. the need to allocate memory on the
fly? ;-)
I agree that you sacrifice some things when you use C rather than FORTRAN,
but it's my opinion that you gain a lot more.  C can be very powerful in good
hands but dangerous in not so good of hands.  So, make sure that you don't
hire those bad hands in your organization! :-)

> and some things are ugly (f77 does not support dynamic memory...

I am sorry, let's clear up somthing: you're talking about f77 but I'm
talking about FORTRAN 4.

> One last question  - are you sure that you don't fear Fortran and don't want
> to change?
> 
> (My credentials - 15 years Fortran on CDC equipment (excellent Fortran, no C)
>  3 years C on Unix.  Language of choice - DEPENDS ON THE APPLICATION.  When
>  it's a push, I'll use C.  If it's bsd Unix, I do my best to avoid f77)

Ok, here is the story...
The first computer language I learned was FORTRAN, and I loved it.  As an
engineer, I did 3 years of FORTRAN programming (but it was f77), not to
mention all programming in undergraduate and graduate school.
There came a time when my previous employer imposed C on us.  I did not
like it a the begining (I guess it was fear), but I soon saw the light.
Then, we moved from C to an Object Oriented Language (in house).  OOL was even
much better than C!  If I write my own application, I'll write it in a hybrid
object oriented programming language even if looks nothing like C.
So you see, one does not fear what he already knows, but he/she fears the
unknow.  If some new language comes up tomorrow that claims to be better
than OOP, I'm (objectively) eager to check it out.  Are you?  If you're
not, may be that's why we're having this dual.

-----------------------------------------------------------------------------
Disclaimer: The above does not necessarliy represent the views or opinoins
	    of my organization.

					uunet!sdrc!spabdul

seanf@sco.COM (Sean Fagan) (01/14/90)

In article <14191@lambda.UUCP> jlg@lambda.UUCP (Jim Giles) writes:
>The truth is, any machine which has registers to schedule,
>program control over cache management, pipelining, or vectors
>can be effected by aliasing.  The severity of the effect depends
>on the program.

And some compilers do a remarkebly good job at coping with this.  However,
yeah, you're right:  there are some constructs in C which cannot be
optimized very well, if at all.  However, let's pose this question to you:
when was the last time you tried to write an OS in FORTRAN?  There are, of
course, dozens written in C, but very few written in FORTRAN.  In that
respect, C is a *much* more powerful language than FORTRAN.

>> The standard allows str*() to be built-in.
>Most ANSI standards allow additional features to be implemented in
>a conforming processor.  I don't consider these extensions to be
>an inherent part of the language.  

So, you don't consider PRINT, READ, WRITE, COS, SIN, etc., to be parts of
FORTRAN?  Well, uhm, gosh, if they're *not*, then C compilers tend to
generate better code, from my experience.

FORTRAN has some advantages, optimization-wise, over C:  no pointers, hence
no aliasing, and, well, I guess that's the major one.  The language is much
older than C, so most of the compilers are more "mature" than C compilers.

However, C has at least one advantage, optimization-wise, over FORTRAN (at
least, as I understand FORTRAN, and as I understand how things have been
implemented):  a C "module" does not consist of one routine per file.  This
lets inline functions, global optimization and analysis, etc., be used,
which you can't do easily in FORTRAN.  (N.B.:  I could be wrong.  However,
all instances of optimizing FORTRAN compilers I've seen [CDC Cyber and Cray
machines {this has been a Seymour-plug}], would treat each routine as it's
own file, and I've been under the impression that this was required.)

-- 
Sean Eric Fagan  | "If a compiler emits correct code purely by divine guidance
seanf@sco.COM    |  and has no memory at all, it can still be a C compiler."
(408) 458-1422   |           -- Chris Torek (chris@cs.umd.edu)
-----------------+ Any opinions expressed are my own, not my employers'.

tps@chem.ucsd.edu (Tom Stockfisch) (01/15/90)

In article <14191@lambda.UUCP> jlg@lambda.UUCP (Jim Giles) writes:
>From article <649@chem.ucsd.EDU>, by tps@chem.ucsd.edu (Tom Stockfisch):

>> I have worked on a machine that has a double-word fetch instruction.  It
>> works only on double-word boundaries.  Fortran cannot make use of it
>> because the 77 standard allows any two consecutive members of
>> a real array to be equivalenced as a double precsion array.  Double
>> precision memory fetches with fortran then require two fetch instructions,
>> [...]

>I too have worked on such machines.  What you're saying is hogwash.
>Unless the implementor was an idiot, he would _always_ allocate double
>precision variables on double word boundaries.  The only time he would
>fai to do so would be if the double _really_was_ equivalanced to a
>single word object.  Even THEN he would insert a "dead" word in the
>memory allocation so that the double word objects were properly aligned.
>The only way for optimization to be inhibited would be if he equivalenced
>two different double word objects to an array of singles - AND the two
>equivalances were an odd number of words apart!  In this case, most
>implementations I've seen will still do the fast loads/stores/ on the
>properly aligned data and will issue a warning about the other.

What does a non-"idiot"ic compiler do with the following code:

C	FILE A
	subroutine sub( a, m )
	double precision a(m)

	...
		a(i) = a(i) + 1
C		many more accesses of a()
	...
	end

C	FILE B
	program
	real r(5)
	double precision d1(2), d2(2)
	equivalence ( d1(1), r(1) ), ( d2(1), r(2) )
C	d1() and d2() can't both be aligned on an 8 byte boundary

	call sub( d1, 2 )
	call sub( d2, 2 )
	end

If the double word fetch is used in subroutine "sub", then one of the
two calls to sub in the main program will cause an un-aligned memory
violation.  Assuming global optimization is not done, does the
compiler test (at run time) the alignment of a() and jump to one of
two different versions of the body of "sub", one for aligned (fast)
and one for unaligned (slow)?  Please note that if the latter, this
has to be done for essentially every subroutine that has double
precision array arguments, generating *a lot* of extra code.
-- 

|| Tom Stockfisch, UCSD Chemistry	tps@chem.ucsd.edu

jlg@lambda.UUCP (Jim Giles) (01/17/90)

From article <4459@scolex.sco.COM>, by seanf@sco.COM (Sean Fagan):
> [...]                            However, let's pose this question to you:
> when was the last time you tried to write an OS in FORTRAN?  There are, of
> course, dozens written in C, but very few written in FORTRAN.  In that
> respect, C is a *much* more powerful language than FORTRAN.

Fine - since I never recommended Fortran as an OS implementation language.
However, I wouldn't recommend C either.  Of widely available languages, I
might pick something like Modula2.  Better languages than that exist, but
are not widely available.  Actually, so few people have need to write
operating systems that a language targeted just for that would be unlikely
to be a large scale success.

> [...]
>>> The standard allows str*() to be built-in.
>>Most ANSI standards allow additional features to be implemented in
>>a conforming processor.  I don't consider these extensions to be
>>an inherent part of the language.  
> 
> So, you don't consider PRINT, READ, WRITE, COS, SIN, etc., to be parts of
> FORTRAN?  [...]

Yes, I _do_ consider all the above features to be part of Fortran.  They
are all _required_ by the existing standard.  The _proposed_ ANSI C
standard on the other hand does not contain any such requirement for
'str*()'.  Therefore, it is not an inherent part of the language.  Many
Fortran implementations provide pointers - the standard allows such
extensions - but I don't consider pointers to be part of Fortran.  Just
because the language standard _allows_ a feature, doesn't make that
feature a part of the language.

> [...]
> However, C has at least one advantage, optimization-wise, over FORTRAN    
> [...]                                                                    
>             :  a C "module" does not consist of one routine per file.  This
> lets inline functions, global optimization and analysis, etc., be used,

It is true that in a Fortran environment, a 'file' is simply an external
storage object which may contain source for one or more procedures.  The
separate compilation rules of Fortran require the compiler to treat each
procedure separately - even if they do reside on the same file.  This allows
subsequent changes to the whole program to be performed by compiling only
those routines which are actually changed.

On the other hand, C uses files as part of the scoping mechanism.  It is
possible for the compiler to make use of its knowledge of other procedures
in the same file as the one current being compiled.  This would allow such
optimizations as you mention.  I'm not aware of any C compiler that I have
access to which actually performs such optimizations though.  This has
drawbacks anyway: in order to change one procedure you must recompile the
whole file.  What is worse, most C implementations will load all the
procedures from a given source file into the executable - even if some
are not actually on the call tree.

Other languages permit these types of optimizations as well (Pascal,
Modula2, etc.).  These languages too, however, suffer from the fact
that most implementations don't.

Fortran 90 (the new official title of the proposed standard) will address
this issue to a minor extent with 'INTERNAL' procedures.  I hope that
implementors will choose to optimize these (as well as their counterparts
in other languages - including C).

J. Giles

jlg@lambda.UUCP (Jim Giles) (01/17/90)

From article <651@chem.ucsd.EDU>, by tps@chem.ucsd.edu (Tom Stockfisch):
> 	subroutine sub( a, m )
> 	double precision a(m)
> 	...
> 	end
> 	program
> 	real r(5)
> 	double precision d1(2), d2(2)
> 	equivalence ( d1(1), r(1) ), ( d2(1), r(2) )
> C	d1() and d2() can't both be aligned on an 8 byte boundary
> 	call sub( d1, 2 )
> 	call sub( d2, 2 )
> 	end


As I said before, whichever double was odd-aligned would receive a
warning message.  Most users regard such a problem as a mistake on
their part.  The only implementation I've seen where there was any
debate on this issue was one where the subroutine was always compiled
to generate the slow references.  By popular demand from the users,
this implementation was changed to always use the fast references
for double.  This required the implementor to issue a fatal for the
subroutine call which was mis-aligned.  I don't know anyone who
complained about this (in spite of the fact that it was, strictly
speaking, non-standard).

By the way, both Fortran and C exhibit this same problem for character
data types.  Neither language requires characters to be word aligned,
and so, on word addressed machines, the compiler must generate lond
sequences of code to fetch/store character arguments.  Contrary to the
above experience, I suspect _most_ users would complain if characters
had to be word aligned.  Further, I suspect they would also complain
if forced to use you 'unaligned' attribute in their declarations.

J. Giles

jlg@lambda.UUCP (Jim Giles) (01/17/90)

From article <14196@lambda.UUCP>, by jlg@lambda.UUCP (Jim Giles):
> From article <651@chem.ucsd.EDU>, by tps@chem.ucsd.edu (Tom Stockfisch):
> [...]                    Further, I suspect they would also complain
> if forced to use you 'unaligned' attribute in their declarations.

My mistake.  It was Karl Heuer who made that suggestion.


J. Giles

gsarff@meph.UUCP (gary sarff) (01/18/90)

In article <21778@mimsy.umd.edu>, chris@mimsy.umd.edu (Chris Torek) writes:
>In article <14191@lambda.UUCP> jlg@lambda.UUCP (Jim Giles) writes:
>-In a previous article I made the incorrect statement that the number
>-of machines which can be well optimized in the presence of pointers
>-is growing narrow.  The fact is that the set of such machines is zero
>-(at least, to the best of my knowledge).  Consider the following code:
>-
>-  z=1;
>-  *a=2;
>-  *b=1;
>-
>-If you could tell that a and b were not aliased (to each other
>-or to z), the the generated code would be to set a register to
>-one, store z, store b, increment, and store a.
>
>1) you *can* tell aliasing (automatically, in the compiler) in many cases
>   (not all).
>
>-However, if you
>-can't detect aliasing the sequence must be in the order given.
>-On all machines I know, this would require at least one more
>-instruction - so even on a RISC machine with no pipelining or
>-vectorization to worry about this code would be 20% slower because
>-of the possibility of aliasing.
>
>2) even when you cannot, this is false.  The generated code
>   would be `store 2 in register z', `store register z in *b',
>   `decreemnt register z', `store register z in *a'.
>
Read the code again. z=2? *a=1?  No no no!.
>
>I refuse to read or respond to anything futher from jlg (at least for a few
>weeks); it is bad for my blood pressure.

It might be better for everyone if you don't respond if you can't at least get
your examples right when you tell someone else they are wrong in a posting.
It might help lower your blood pressure too.

goudreau@dg-rtp.dg.com (Bob Goudreau) (01/19/90)

In article <14195@lambda.UUCP> jlg@lambda.UUCP (Jim Giles) writes:
>>>> The standard allows str*() to be built-in.
>>>Most ANSI standards allow additional features to be implemented in
>>>a conforming processor.  I don't consider these extensions to be
>>>an inherent part of the language.  
>> 
>> So, you don't consider PRINT, READ, WRITE, COS, SIN, etc., to be parts of
>> FORTRAN?  [...]
>
>Yes, I _do_ consider all the above features to be part of Fortran.  They
>are all _required_ by the existing standard.  The _proposed_ ANSI C
>standard on the other hand does not contain any such requirement for
>'str*()'.  Therefore, it is not an inherent part of the language.  Many
>Fortran implementations provide pointers - the standard allows such
>extensions - but I don't consider pointers to be part of Fortran.  Just
>because the language standard _allows_ a feature, doesn't make that
>feature a part of the language.

Jim, I think you misunderstand the distinction between the standard
library functions defined in the ANSI C Standard (which is no longer
*proposed*, but *approved*) and "additional features".  See section
1.7 of the Standard for details.

The upshot is that the C Standard really defines two language
translation standards:  hosted and freestanding (think of them as
along the same lines as full FORTRAN 77 and its standard subset (G?)).
The former (hosted) is a superset of the latter and is of course by
far the most popular -- most C users *want* the use of the standard
library functions (unless they're writing a device driver or something
at a similar low level) and most compilers provide them.  And the ANSI
Standard cleary states that a conforming hosted implementation is
*required* to accept any strictly conforming program -- i.e., a
program using "only those features of the language and library
specified in this standard".

So as far as hosted implentation go, the Standard goes far beyond just
*allowing* the standard library functions to be available; it *requires*
them to be there, and implementors are free to "build them in" to the
compiler.  In that respect, the str*() functions are as much an
"inherent part of the language" of (hosted) ANSI C as PRINT, SIN, etc.
are part of FORTRAN.

--------------
Bob Goudreau				+1 919 248 6231
Data General Corporation		...!mcnc!rti!xyzzy!goudreau
62 Alexander Drive			goudreau@dg-rtp.dg.com
Research Triangle Park, NC  27709, USA

seanf@sco.COM (Sean Fagan) (01/19/90)

In article <14195@lambda.UUCP> jlg@lambda.UUCP (Jim Giles) writes:
>> So, you don't consider PRINT, READ, WRITE, COS, SIN, etc., to be parts of
>> FORTRAN?  [...]
>Yes, I _do_ consider all the above features to be part of Fortran.  They
>are all _required_ by the existing standard.  The _proposed_ ANSI C
>standard on the other hand does not contain any such requirement for
>'str*()'.  Therefore, it is not an inherent part of the language.  

They *are* required, for *hosted* implementations.  Non-hosted
implementations aren't expected to run on the same system you're compiling
on; therefore, the library might not make a whole lot of sense.  Think about
it:  if you're writing something for an embedded controller (something most
people would pick C for instead of FORTRAN), you don't really *care*
whether or not strftime is in the library, do you?  If you're on a hosted
implementation, then the libraries *are required to be there*, just like in
FORTRAN.  Most people will not deal with non-hosted implementations, so it's
pretty much a moot point, except for those that know they're special
anyway.

Look:  I like C.  A *lot*.  I also like FORTRAN.  There are a lot of things
I'd prefer to do in FORTRAN than Pascal, or even C, on the right system (a
Cyber is a damnably good FORTRAN engine, as are Cray's).  However, on a UNIX
machine, I'm probably going to use C instead of FORTRAN (the compiler is
probably better, the library is probably designed to work with it instead of
any other language, etc.).  On a Cyber, again, I use FORTRAN, almost
exclusively (well, an occasional assembly routine).  Different systems,
different languages.

-- 
Sean Eric Fagan  | "If a compiler emits correct code purely by divine guidance
seanf@sco.COM    |  and has no memory at all, it can still be a C compiler."
(408) 458-1422   |           -- Chris Torek (chris@cs.umd.edu)
-----------------+ Any opinions expressed are my own, not my employers'.

levy@cbnewsc.ATT.COM (Daniel R. Levy) (01/21/90)

> > You write character manipulation programs in Fortran?
> 
> Why not?  It's as fast as the fastest mechanism C has for Characters
> (or should be), it has built-in concatenate and substring syntax
> (instead of C's clumsy looking function calls for these features),
> and it's widely regarded as something that Fortran did (nearly)
> right - even by people who otherwise don't like Fortran.

Well... depends on what you're doing with the strings.  Fortran uses the
convention that character strings are right-padded with blanks (for things
like READ with a-format where the input buffer is longer than the input record
[strictly speaking, isn't this really a nonstandard but common extension to
accommodate variable size input records?], the INQUIRE statement, and assigning
one string to another).  This means juggling the length information along with
the strings (nothing stops you from doing that in C B.T.W.) and/or having a
function analogous to C's "strlen" to give you the length of a blank-padded
string.  You can't concatenate or print a "zero length" string -- that
must be special-cased.  And, of course, information about trailing blanks in
input records is lost.  E.g.:

C
C  FORTRAN77 code to read two lines (assumed 80-characters wide, max),
C  put their concatention in a buffer,
C  then print the concatenation between double quotes
C
	CHARACTER*80 STR1, STR2
	CHARACTER*160 STR3
	READ(5,10) STR1
	READ(5,10) STR2
10	FORMAT(A)
	LSTR1=LENGTH(STR1)
	LSTR2=LENGTH(STR2)
	IF (LSTR1.EQ.0) THEN
		STR3=STR2
		LSTR3=LSTR2
	ELSE IF (LSTR2.EQ.0) THEN
		STR3=STR1
		LSTR3=LSTR1
	ELSE
		STR3=STR1(1:LSTR1)//STR2(1:LSTR2)
		LSTR3=LSTR1+LSTR2
	ENDIF
	IF (LSTR3.EQ.0) THEN
		WRITE(6,20)
20		FORMAT(1X,'""')
	ELSE
		WRITE(6,30)STR3(1:LSTR3)
30		FORMAT(1X,A)
	ENDIF
	STOP
	END

	FUNCTION LENGTH(STRING)
	CHARACTER*(*) STRING
	DO 10 LENGTH=LEN(STRING),1,-1
10	IF (STRING(LENGTH:LENGTH).NE.' ') RETURN
	LENGTH=0
	RETURN
	END

Ugh.  Now let's try that in C...

#include <stdio.h>
main()
{
	char str1[81];
	char str2[81];
	char str3[161];
	void exit();

	(void) gets(str1);
	(void) gets(str2);
	(void) sprintf(str3,"%s%s",str1,str2);
	(void) printf("\"%s\"\n",str3);
	exit(0);
}
	
'Nuff said.
-- 
Daniel R. Levy                     >>> God: just say "yes" <<<
AT&T Bell Laboratories     UNIX(R) mail:  att!ttbcad!levy, att!cbnewsc!levy
5555 West Touhy Avenue     Any opinions expressed in the message above are
Skokie, Illinois  60077    mine, and not necessarily AT&T's.

jeenglis@alcor.usc.edu (Joe English) (01/21/90)

levy@cbnewsc.ATT.COM (Daniel R. Levy) writes:
>C
>C  FORTRAN77 code to read two lines (assumed 80-characters wide, max),
>C  put their concatention in a buffer,
>C  then print the concatenation between double quotes
>C

[ 35 lines deleted ]

>Ugh.  Now let's try that in C...
>
[ 15 lines deleted ]

Well, some might say that using sprintf() to 
do the concatenation is cheating, so let's do
it "by hand:"

    char *src,*dst;
    int remaining;

    dst = str3;
    remaining = BUFLEN;

    src = str1;
    while (*src && remaining) {
        *dst++ = *src++;
        remaining--;
    }
    src = str2;
    while (*src && remaining)  {
        *dst++ = *src++;
        remaining--;
    }
    *dst = '\0';

The C implementation is still shorter, but more
importantly it's a lot clearer (to me, anyway.) It
also looks more "efficient" than the Fortran version,
but I'll leave that for Jim Giles to decide since he's
the one who knows what the optimizer can and can't do.


--Joe English

  jeenglis@nunki.usc.edu

jlg@lambda.UUCP (Jim Giles) (01/23/90)

From article <12974@cbnewsc.ATT.COM>, by levy@cbnewsc.ATT.COM (Daniel R. Levy):
> [... Use of Character variables in Fortran ...]
>
> Well... depends on what you're doing with the strings.  Fortran uses the
> convention that character strings are right-padded with blanks (for things
                            ^^^^^^^

Depends on how you define strings.  I don't define Fortran character
variables as being strings.  They are fixed length.  I define them
to be a type of character array with some useful operators defined for
them.

A genuine string type in Fortran would certainly be a welcome addition.
But, the lack of such a type doesn't make C the language of choice for
the manipulation of character data.

> C
> C  FORTRAN77 code to read two lines (assumed 80-characters wide, max),
> C  put their concatention in a buffer,
> C  then print the concatenation between double quotes
> [... This is followed by a program which doesn't do the above
>      described operation.   ...]
>
> Ugh.  Now let's try that in C...
> [...  This is followed by a C program which doesn't do either the
>       operation described for the Fortran NOR the operation that
>       the Fortran version _actually_does_.    ...]
> 
> 'Nuff said.

Yes - "'Nuff said"!  You clearly don't have any idea what you're talking
about.  A Fortran program which does what the above comment lines claims
would have been as short as your C version (and whould have been more
efficient because the C version included a few locations where "pre-
scanning' the strings would have been required.

Instead of doing what the comments claim, your Fortran code laboriously
stripped the blanks from the input strings (a fact which accounts for
MOST of the bulk of the program).  Yet, the C code wasn't subject to
that laborious process (in spite of the possible presence of trailing
blanks).

To be sure, to get the Fortran version to match the behaviour of the
C version (of vice versa) would have required some additional coding.
And, for those _few_ simple things like your example, the C code is
slightly shorter (at the expense of speed).  Fortran is not perfect
either: most applications require the user to carry around string
lengths in order to do much of the work required.  In order to
provide efficiency, the C programmer ALSO would have to maintain
string lengths explicitly.  In this case, Fortran's improved
syntax is a direct win.

A "perfect" language would provide a genuine string type which
maintained the string lengths implicitly (and NOT by terminating
with some special character).  The "perfect" language would also
have substring and concatenation built into the syntax instead of
function calls like C has.

J. Giles

jlg@lambda.UUCP (Jim Giles) (01/23/90)

From article <7536@chaph.usc.edu>, by jeenglis@alcor.usc.edu (Joe English):
> [...]
>     src = str2;
>     while (*src && remaining)  {
>         *dst++ = *src++;
>         remaining--;
>     }

Terribly innefficient.  It relies on your compiler being _really_ clever
about optimizing.  A _VERY_ good C compiler _might_ make the above loop
into a block move instruction.  It would still have to prescan the string
to find out how long the block move should be.  Assuming (in addition to
all the miracles so far) that the compiler does prescanning with a single
instruction also (block scan), the time for this is roughly twice what the
equivalent Fortran code would use.

I don't know why you didn't use strlen() followed by memcpy().  This would
do exactly the optimizations (plus or minus a couple of function calls)
that most C compilers would otherwise miss.  Assuming that ANSI compatible
C compilers are close on the horizon, I would bet that memcpy() and
strlen() would be "inlined" by most compilers.

Indeed, for your whole example (which had two loops as above), I don't
see why you didn't use strcpy() followed by strcat().  This would assume
that the two library functions were efficiently implemented (these two
are usually written in assembly).  Using these, you still have to pay
for the prescanning of the input strings, but you would pay less for
procedure call overhead.

Finally, if you had not used gets() to get the original strings, but
had used something which returned the length explicitly, you could
have used memcpy() only!  This would _FINALLY_ be as efficient as
Fortran concatenation (plus or minus the procedure call - Fortran
is _MORE_ likely to inline, at least until ANSI C compilers are
widely available).

Still, it doesn't look as good.  In Fortran, concatenation is
simply:
      STRING3 = STRING1 // STRING2

Much more legible IMHO.

J. Giles

mcdonald@aries.scs.uiuc.edu (Doug McDonald) (01/23/90)

>> [...]
>>     src = str2;
>>     while (*src && remaining)  {
>>         *dst++ = *src++;
>>         remaining--;
>>     }
Assuming that it is known that remaining is less than the allocation
of either src or dst, then one could save the character at
(src + remaining), replace it with zero, copy until zero was hit,
and then fix up the marker byte. You provide the code and the
exact place to put the marker byte.

This takes only one loop with only one test.

Doug McDonald