9

In Fortran 77, numerical code that ran on IBM, CDC, Cray etc, how was overflow typically handled?

Did it raise an exception? (I would expect such an exception to be inexact on vector machines, i.e. to potentially be raised some cycles after the overflow occurred?)

Did it work along the lines eventually adopted in IEEE 754, producing special 'infinite' values?

Or something else?

8
  • 15
    What is a 'dusty deck Fortran'? Also, you might want to specify systems/usage/area here, as Fortran not only covers next to all computers build since the 60s, but as well next to all usages - which do vary widely in their need to handle overflow. Last but not least what kind of overflow. range, stack, memory, record overflow, or what?
    – Raffzahn
    Commented Jun 29, 2020 at 7:14
  • 7
    @Raffzahn The description "dusty deck Fortran" usually referred to code written before there were any global standards for the language which were actually useful for "real Fortran written by real programmers" (not quiche-eaters). if you want a definite cut-off point, I would say "anything written before Fortran 77."
    – alephzero
    Commented Jun 29, 2020 at 10:32
  • 4
    @alephzero - Fortran IV was pretty well defined, so I'm not sure why you consider Fortran 77 to be a good dividing line.
    – Jon Custer
    Commented Jun 29, 2020 at 14:51
  • 5
    @alephzero Well, if dusty deck is pre F77, then the question is contradicting the headline, as it asks specific for F77, doesn't it?
    – Raffzahn
    Commented Jun 29, 2020 at 14:53
  • 6
    @alephzero - I've always understood "dusty deck" to refer to any old program, i.e., fodder for this forum, regardless of standardization of language. The implication is simply that it's a forgotten program, dusty because it's a long time since it was loaded into the card-reader hopper.
    – dave
    Commented Jun 29, 2020 at 23:30

10 Answers 10

15

While this may cover many ways of overflow (from integer and counter all the way to record, I assume the Overflow in question is about floating point, which more precisely means over/underflow of the exponent.

The exact handling varies widely between compilers and machines. Fortran 77 did not make any assumptions here (AFAIK), it at all, it was expected that the program will be aborted like with any other machine error.

In general: Fortran is, much like Assembler, not a 'nanny' language, made to pamper every possible fault, but expects the programmer to write a program tailored to its data, not producing any error under normal condition. As a result, program abort is a sensible default solution.

Of course, it's always possible to add checks. Already early Fortran (no number) for the IBM 704 added the ability to check for conditions (ACCUMULATOR OVERFLOW, QUOTIENT OVERFLOW, and DIVIDE CHECK) after a calculation.

Over the years all modern compilers have added specific tools to handle such conditions, especially when IEEE float became a thing in the 1980s. For example Oracles's F77 compiler for SPARC and x86 may be told to not abort right away, but record 'flags' about operations. These can be tested when the programmer expects some error condition and is willing to handle it.

      x = d_max_subnormal() / 2.0
      ieeer = ieee_flags( 'get', 'exception', 'overflow', out ) 
      IF ( out .eq. 'overflow') PRINT *,'overflow flag raised' 

This is mainly done due performance reasons. Error checking costs time and Fortran users act usually at the top end of what's available in computing power, so any additional code is to be avoided.

Then again, Oracle F77 allows as well for generation of exceptions. It's a modern implementation, so it gets soft on anyone short of a real programmer. This means an exception handler can be added:

      EXTERNAL myhandler                         
      i = ieee_handler ('set', 'division', myhandler )

With IEEE FP rules became defined about what results of operation with not fitting values (*1) should be, enabling to continue operations after overflow even further.

Long story short: Check Machine and Compiler Manual in Operation.


*1 - Trying to avoid the word 'not numbers'

2
  • 1
    I don't think this would justify a separate question, but were there any notable floating-point formats that accommodated a propagating "error" value prior to IEEE-754? Given that FORTRAN's behavior when trying to output a number that won't fit in a field isn't to trigger a fatal error, nor to botch the formatting of everything that follows (the way printf does), but instead replace all the digits with asterisks, having a floating-point "invalid number" value which would be output as all asterisks would seem to fit that philosophy.
    – supercat
    Commented Jun 29, 2020 at 17:15
  • 5
    @supercat The CDC 6600 floating-point format supported infinite and indefinite floating-point operands. For details on how those were propagated, see the linked specifications.
    – njuffa
    Commented Jun 29, 2020 at 19:18
10

I don't recall any overflow handling on the FORTRAN 77 compiler that I worked on and supported (Honeywell Series 60 Level 62). Any overflow would cause a program abort, so it was up to the programmer to ensure that overflows did not happen. This compiler was designed to be compatible with IBM System/360 FORTRAN, and even used the same base-16 floating point format.

10

I only have experience of ICL mainframes, CDC, Prime 300, Data General Nova and Eclipse. On those, the programs just crashed. Like Mick's answer, it would be up to the programmer to figure it out. These were variants of Fortran II (lots of 3- way jumps), Fortran IV (or 66) and Fortran V (what the vendor called it).

Fortran was mainly used for High Performance stuff so range and error checking was hardly done. Some of the ones published ones generated out of bounds problems which weren't easy to spot. Like stack based stuff nowadays, if it doesn't overwrite the stack frame, nothing except the result will tell you that it has gone wrong.

One of the common problems was storage of characters in integers. There was no character type. On the CDCs, only 48 of the 60 bits were used for integers. With 6-bit characters, you could store 10 characters in an integer but you'd get an overflow exception if you tried printing with I format. It was OK when printed with A format.

The other common problem was the incorrect order of variables or occasionally untyped variables in common blocks. This caused everything to misalign. Most of the Fortran variants did not have the concept of include files.

There was no concept of IMPLICIT NONE but you could do IMPLICIT COMPLEX since hardly anyone used COMPLEX. That would spot problems like

DO 10 I = 1.5

instead of

DO 10 I = 1,5

Without using IMPLICIT COMPLEX, the easiest way was to always include the increment since the following were illegal

DO 10 I = 1.100,1
DO 10 I = 1, 100.1

Since Fortran II and IV allowed spaces in variable names some people went crazy over this. Very often only the first 6 characters of the variable name were recognized so

COORDS X = 20D2
COORDS Y = -30.0

would actually assign

COORDS = -30.0

Stuff like that often produced spectacular crashes with the coder complaining why doesn't the compiler warn me about this

5
  • 5
    Nit: Since Fortran II and IV allowed spaces... -- actually, just ignored spaces everywhere in source code except in Hollerith strings. I know this since I programmed on pre-perforated cards that only had the even columns.
    – dave
    Commented Jun 29, 2020 at 23:38
  • 1
    I said allow instead of ignore because F90/95 and later do not allow spaces in variable names.
    – cup
    Commented Jun 30, 2020 at 16:23
  • 1
    I parted ways with FORTRAN pretty much as soon as I read the Revised Report on Algol.
    – dave
    Commented Jun 30, 2020 at 18:42
  • 1
    I started with Algol 60 and decided to learn Fortran for fun. Job-wise, it came in more useful than Algol 60 or 68 or Pascal. I taught myself from the manual so I knew most of the obscure features like an array called if. In those days, it was one of the few languages that could do graphics and programs could be overlaid. These fun features weren't available in all languages. Knowing how to overlay a program efficiently was quite an art in the late 70s.
    – cup
    Commented Jun 30, 2020 at 19:14
  • 1
    Job-wise, it was MACRO-11 for me. And I knew the "delights' of ODL, the Overlay Descriptor Language used by the Task Builder.
    – dave
    Commented Jun 30, 2020 at 20:13
7

Before IEE 754, there was no floating point equivalents to "NaN" or "Inf". Overflow, underflow, and division by zero generated interrupts which would be ignored, trapped, or terminated the program with a default error message (and most likely a core dump as well).

These options could often be controlled from Fortran by a collection of routines such as

  • CALL ERRSET - define how many times to ignore each type of error occurred before it was either reported as a warning or terminated the code. Don't ask why it was useful to ignore the first 17 overflows but the 18th one would caused a fatal error, but you could do that sort of thing if you really wanted to!

  • CALL ERRSAV - retrieve the current settings for ERRSET, in order the override them temporarily and then restore them

  • CALL ERRMSG - create user defined error messages.

The same routines also controlled floating point errors on input - e.g. attempting to enter a FP number with the exponent outside the valid range.

All this was rather OS and hardware dependent, but it was fairly common to use it to disable underflows (which returned zero) if the numerical algorithm didn't care about that.

I can't find a useful set of documentation of these on the web - Google found some references to IBM documentation but they were too fragmented to be worth linking to.

2
  • 4
    At least one pre-IEEE-754 system did support infinite and indefinite floating-point operands. See the section "Floating Point Arithmetic" in the CDC 6600 specifications reproduced here: gsmall.us/Computing/CDC6400/Archive/CDC-6600-R-M.htm . I have a vague recollection of reading that W. Kahan's work leading to IEEE-754 was in part inspired by the CDC 6600.
    – njuffa
    Commented Jun 29, 2020 at 19:22
  • 1
    "generated interrupts" => "generated exceptions". Commented Jun 30, 2020 at 20:51
7

The answer is "it depends".

If your object program is running on a machine that traps on arithmetic overflow, you'll get a trap on arithmetic overflow.

If there's a latching overflow indicator, there might be a way to interrogate it; with ICL 1900 FORTRAN, you could CALL OVERFL(K) to set K depending on whether overflow had occurred (K=1 for overflow, and somewhat oddly, K=2 for no overflow).

You might get compile-time debugging options to insert checks for overflow; again with the ICL 1900, compiling in TRACE mode caused overflow checks to be inserted at "certain points".

1900 FORTRAN manual.

There's another FORTRAN manual in the same place, this time explicitly for FORTRAN 77, but it requires the DjVu reader, so I did not link it here.

6

As a Fortran Compiler writer for dusty deck (and other computers), let me add that many answers, although correct, are not focusing on the implementation Fortran language, but features that they might have remembered using from Fortran. Many of those features, although correctly described, are mainly about features provided by the operating system or run-time libraries which would have been equally available to other language programs running on the same platform (be it Algol, Autocode, Assembler or whatever).

Most of the time the Fortran compiler just generated the most efficient machine code it could for the program supplied. Performance (whether in Whetstones or Dhrystones or whatever) was the thing to care about.

So, basically, the answer is: it depends. The hardware may generate a fault or it may not. There may be features to capture it or there may not. Sometimes the overflow/underflow happened silently and the bits just fell of the end of the accumulator! Sometimes you could effect what happened on overflow by appropriate job control commands and not from the program at all.

The compiler just had to generate the best arithmetic op-codes it could and stuff the consequences.

Event capture is just a modern artefact. When Ada included it I remember programmers wondering how it could be useful!

5

On BESM-6 the ALU/FPU interrupts (overflow, division by zero) were inexact, thus it was impossible to recover and continue, but it was possible to handle them with a mechanism akin to the setjmp/longjmp capability in the C language, where the "setjmp" equivalent was IFOVFL(DUMMY), returning 0 at setup, and 1 on exception, and the "longjmp" was triggered by an arithmetic exception.

Here's how it worked (emulator printout):

F O R E X   ИПM AH CCCP           BEPCИЯ  2.02 OT  15.07.80

             1       A = 1.0                                                                       1
             2       I = 0                                                                         2
             3       IF (IFOVFL(0).EQ.1) GOTO 10                                                   3
             4   20  A=A+A                                                                         4
             5       I=I+1                                                                         5
             6       GOTO 20                                                                       6
             7   10  PRINT 1,I                                                                     7
             8    1  FORMAT(I6)                                                                    8
             9       END                                                                           9

       *NO LOAD LIST
       *EXECUTE
62

The maximum value of the exponent field was 63, and the value of 1.0 was represented as 0.5*21, therefore the max. representable power of 2 was 262, as the printed value indicates.

5

On IBM H/W, overflows & underflows generated an interrupt and generally resulted in an exception with the program being cancelled.

On CDC under NOS any runtime error was noted by the Peripheral Processor and at the end of the time slice, the program was cancelled with a less than helpful message and diagnostic snap dumps which may or may not be close to the part of the code that actually produced the problem.

4

In my dusty memory, F77 on a CDC Cyber 175 would crash on floating-point overflow, and I would assume that applies from 6600 to 176 as well. That might have been due to local setup.

1
  • 2
    The CDC Cybers (and the 6x00/7600 before them) would not crash the program on GENERATING an infinite or indefinite value. It would crash the program when a subsequent operation attempted to USE an infinite or indefinite value. Standard programmer debugging trick: Preset all memory for the program to indefinite + address (which is still indefinite) and your program would crash IMMEDIATELY when you tried to use something you hadn't initialized or previously computed, and where it came from. Commented Jul 1, 2020 at 11:44
4

The PDP-8, a tiny minicomputer compared to some of the examples here, did the following in its floating point package:

The input conversion routine halts on overflow during calculation of the mantissa. Typing RUBOUT and pressing CONTINUE on the console will restart the routine.

Overflow during exponent calculation yields an unpredictable result; the package may halt in which case it may be restarted as above.

Capacity of the input routine is approximately from .999999E-615 to .999999E+615.

The overflow halt may be eliminated by depositing 7000 (NOP) into location 7564. If this is done or if the user continues from the overflow halt without typing RUBOUT, the contents of the floating accumulator will be unpredictable.

The PDP-8 had a full FORTRAN-IV compiler, thought admittedly a very constrained one to work with the machine's 8 Kw core. I think it can safely be said that the PDP-8 handled overflow “not very gracefully”.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .