Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: Notesfiles hp 2.0 03/25/85; site hpislb.UUCP
Path: utzoo!watmath!clyde!burl!ulysses!mhuxr!mhuxt!houxm!vax135!petsd!pesnta!hplabs!hpisla!gore
From: gore@hpisla.UUCP (Jacob Gore)
Newsgroups: net.lang
Subject: Re: What language do you use for scientific programming?
Message-ID: <64500002@hpislb.UUCP>
Date: Mon, 19-Aug-85 01:57:00 EDT
Article-I.D.: hpislb.64500002
Posted: Mon Aug 19 01:57:00 1985
Date-Received: Sun, 25-Aug-85 01:52:30 EDT
References: <909@oddjob.UUCP>
Organization: HP Instrument Systems Lab - Loveland, CO
Lines: 240


     
># Written  9:23 pm  Aug 12, 1985 by paul@oddjob.UUCP in net.lang
>
>I've been curious for a while what scientist/engineering types on the net
>use for scientific programming.  I know the low regard in which fortran is
>held by the systems types on the net, but I haven't found anything better
>than fortran to use.

I'm a "software engineering type" full-time, and "systems type" part time.
Still, you might find my reply useful.  I'm posting this instead of mailing
it to you, as you asked, because it might draw some corrections from folks
on the net.  THIS IS RATHER LONG, but I think you and people who share your
questions will find this interesting.

Sorry to throw another language at you (I see somebody's already proposed a
LISP), but if I were you, I would try using Ada.  Let me try to address
your problems a few at a time:

>I am learning Pascal and Modula-2, but they have the major
>weaknesses of no double precision data type (...), clumsy i/o, and no
>exponentiation operator.  C shares the last two weaknesses.

Ada is quite similar to Pascal and Modula-2.  It does have double-precision
real types.  In fact, you can pretty much specify arbitrary precision, as
long as you keep in mind that your program will run faster if there is a
hardware data type in your machine that can support the precision that you
asked for (otherwise, you could be executing lots of simulation code).

Ada follows the philosophy that anything that can be safely put into a
library should not be a burden to the compiler.  Following this philosophy,
I/O is not "built into the language" (which usually means that I/O routines
are in the library anyway, but the compiler has to parse calls to those
routines differently from calls to user-written routines).  DoD (who set
the requirements for the language) does require provision of library
routines that do minimal I/O, in the manner similar to that of Modula-2,
but slightly more convenient.

If you are used to formatted I/O, you probably won't like them.  However,
routines for formatted I/O might be available from whoever sells you the
compiler, and if they aren't, you can write them yourself (though most
"scientific/engineering types" probably won't want to), and it will fit
right in with the supplied libraries.

There is a built-in exponentiation operator ('**'), but it is only defined
for the  **  operation (i.e., the power must be integer).
Again, a more general '**' operator may be provided in the libraries, and
if it's not, you can write your own.  You can even call it '**' and use it
exactly as you would use the original operator -- Ada figures out from the
types of the operands which operator to use.

>The advantages of fortran in my opinion are 1.
>at least two real precisions, 2. standard and powerful i/o routines, and 3.
>very wide availability with great portability (because of the existance of a
>standard for the language).  Is there any other language which shares these
>properties but also has some of the constructs I would like to use (while,
>do ... while, case, structures, pointers).

Ada is portable.  DoD will not let anyone call a compiler "an Ada compiler"
unless it follows the standard to the letter.  There are some provisions
for writing machine-dependent code, but you usually have to go out of your
way to use them.  These are usually of concern to us "system types."
Availability is another matter -- there are not too many compilers around,
certainly not as many as there are FORTRAN compilers.  Still, there are
quite a few, especially for larger machines (VAX and above, and I think
even some 68000's).

Ada has the programming constructs you want.  It has pointers.  It has
structures (with pitfalls of Pascal structures eliminated).  It has some
convenient features that neither Pascal nor FORTRAN (nor Modula-2, for that
matter) offer, and I'll talk about them after we're done with your
questions.

>Perhaps the answer is fortran
>itself; what new features does the upcoming revision to the fortran standard
>have?

Yes, FORTRAN-77 has a lot of what you want (perhaps everything), but
other people have already posted replies about it, so I won't repeat them.
I would still use Ada instead of FORTRAN-77.

Did you ask about complex numbers?  Most of my "scientific type" friends
want complex numbers.  Well, the story here is the same as with I/O and
exponentiation.  Complex numbers are handled by a library package which
defines representation of the numbers, as well as the '+', '-' and whatever
other operators may be applicable.  In fact, it may define a '+' to add a
complex to a complex, a complex to a real, a real to a complex.  They all
have the same name ("+"), but Ada will figure out which one to call from
the types of the operands (during compilation).  Note that the
representation of complex numbers is quite irrelevant with this
arrangement:  if you decide that for your program will run faster if they
are stored as (angle, magnitude) instead of (real, imaginary), you simply
change the inside of the library package, and the program that uses it will
not be affected.

Now for features that you probably haven't thought of since they are not in
FORTRAN.  Some of these are especially useful if you are writing
mathematical (or any other type) libraries for use by other people
(customers).

As you probably began to suspect from my replies above, it is very easy to
write self-contained, complete, and easy-to-use libraries.  The features
that help this are:

  (1) Automatic initialization of local data.  I've seen people go through
      a lot of pain to initialize data that routines in a library need
      for more than just the duration of one routine call.  The tricks
      usually involve checking if a routine is called for the first time,
      and if so, the data is initialized.  Ada does this at compile-time
      (load-time, technically).  By the time the library is loaded into
      memory, its static data is initialized.

  (2) Error signalling.  In FORTRAN, when a customer calls your routine
      with bad input parameters (or at the wrong time, etc.), you have two
      options:

	(a) Let the program die.

	(b) Detect that an error is about to occur and set some global flag
	    or a special ERROR parameter.

      I think method (a) stinks, mostly because the user gets a message
      like "Floating-point exception in ", instead of something like "The second
      coefficient cannot be zero, see ".

      However, it is used quite often because the second method is
      inconvenient to use:  after each call to your library routine, the
      customer has to check if the flag has been set.  Ada provides a third
      method, which is much more convenient:

	(c) The library routine signals an error; the user has a section in
	    his/her program that traps selected errors and handles them
	    accordingly.  If the user does not provide such an error trap,
	    it is possible to work your own trap in.  If neither you nor
	    the user provide a trap for this error, it is trapped by the
	    system and the program stops.  The result of the last situation
	    is similar to the result of method (a), but you still can signal
	    a more descriptive message than something like "Division by zero",
	    which is what you would get if the system raised the error instead
	    of your own routine.

  (3) Meaningful routine names.  FORTRAN limits all names to 6
      characters;  I don't know if FORTRAN-77 still has that
      restriction.  I do not recall reading anything about name length
      restrictions in the Ada standard, but if there is one, it is
      *very* generous.

      In addition to that advantage, Ada allows to call similar routine
      that take parameters of different types by the same name.  This
      technique is called "overloading the name", and there is nothing
      negative about it, despite the way it sounds.  This extends to
      the ability to overload existing operators, such as '+' and '**'.
      (Unlike Algol-68, there is no way to create new operators, only
      overload the existing ones.  Overloaded operators have the same
      precedence within arithmetic expressions as their counterparts
      for integers.)

  (4) Ability to pass parameters by name (instead of just their
      relative positions within the call) or not to pass them at all.
      Many statistical library routines have a dozen or two of
      arguments, most of which the user wants to default to their usual
      values.  In most languages, the best way to do this is to pass
      some agreed-upon value, usually 0, which will be replaced with
      the default value by the routine.  So the call might look like

	CALL FUNFNC (1985, 34, 0,0,0,0,0, -23, 0,0,0,0, 1, 0,0,0,0,0,0)
      
      In Ada, it would like this:

	FUNNY_FUCNTION (YEAR:=1985, DISTRICT:=34,
			PENALTY:=-23, COEFFICIENT:=1);

      The order of the parameters, when passed by name, does not
      matter.
      
      If you were a customer, which statement would you prefer to use?
      Well, if you do want to pass values for most of the parameters,
      you might prefer memorizing their positions to spelling out the
      name for each of them.  But even that is easier to do in Ada:

	FUNNY_FUNCTION (1985, 34, ,,,,, -23, ,,,, 1, ,,,,,);

      And there is no confusion over which parameter gets the default
      value, and which actually gets the value of zero!

  (5) Ability to pass multi-dimensional arrays, where any dimension can be
      of any size.  The bottom and top index of each dimension get passed
      automatically.  Thus, you can easily write a routine that, for
      example, multiplies two matrices, without knowing in advance the size
      of either matrix.

  (6) Source code savings through generic coding.  You can write a routine
      that operates on data of some generic type (or types), and then
      create, in a simple declaration, instances of that routine that
      operate on specific types of data.  For example, you could have a
      generic library called MATRIX_MATH that works on matrices where each
      element is of type ELEM_TYPE.  Then you can create an instance of
      this library that works on real numbers by declaring (I'm not sure if
      I remember the exact syntax)

	REAL_MATRIX : MATRIX_MATH(REAL);

      and an instance of the same library that works on matrices of complex
      numbers by declaring

	COMPLEX_MATRIX : MATRIX_MATH(COMPLEX);
      
      Meanwhile, inside the source code for your generic library, all
      matrix elements are declared to be of type ELEM_TYPE, which will be
      replaced with REAL during compilation of the first instance and with
      COMPLEX during the compilation of the second instance.  Also during
      the compilation, all references to operators and functions that take
      elements of type ELEM_TYPE will be replaced with calls to the
      appropriate routines (remember overloading?).

Other advantages of Ada include:

  (1) Ability to write modular, yet efficient code.  If readability
      concerns warrant putting a code segment into a separate procedure,
      but the procedure is to be called from within a frequent loop, the
      compiler can be told to expand the procedure inline.  This way, you
      do not lose time on procedure calls during execution, and you don't
      have to sacrifice readability for efficiency.

  (2) Ability to write parallel programs.  Many numerical solutions can utilize
      parallel programming.  This is especially true for solutions that use
      matrices.

Again, I apologize for the length of this posting.  I welcome all arguments
against what I said (or neglected to say).  All flames concerning Ada, though,
divert to /dev/null, or its equivalent on your system.

Jacob Gore
Hewlett-Packard Instrument Systems Lab (until 9/13/85)
{ihnp4 or hplabs}!hpfcla!hpisla!gore

Northwestern Univ. Comp. Sci. Research Lab (afterwards)
2145 Sheridan Rd
Evanston, IL  60201