(j3.2006) Units of measurement in Fortran

Van Snyder van.snyder
Wed Apr 20 06:21:33 UTC 2011


I was an official reviewer for DoD-1, which became Ada.  I tried in 
about 1981-1983 to convince DoD to include units in Strawman, then in 
Woodenman, then in Tinman, then in Steelman, then in Red, Green, Yellow, 
and Blue, then in Ada when it finally had a name.  Colonel Whittaker 
said "Huh?"

I tried in 1986 to convince X3J3 to add units to Fortran 90.

I tried in 1997 to convince J3 to add units to Fortran 2003.

I tried in 2004 to convince J3 to add units to Fortran 2008.

It is astonishing to me that Fortran, the language whose proponents 
claim is the premiere vehicle for computations to support science and 
engineering, does not provide support for systems of measurement.

I have completed a draft of a TR to provide units of measurement in 
Fortran.  I will propose it as a work item for the next revision of 
Fortran, either as a TR, or to be incorporated directly into the next 
work plan.

I have put the draft in the Tutorials directory on the server.  Its name 
is Units-TR-7.pdf.

The front matter is five pages.  Then one page of boilerplate.  Then 
fifteen pages of requirements plus one page describing related 
functionality not requested.  then fourteen pages of proposed edits to 
10-007r1.

Dick Hendrickson gave me some useful feedback on an earlier revision.  
Additional feedback is welcome.

During the last six or so months, I have read nearly a dozen papers on 
the topic of units of measurement in programming languages, going back 
to about 1983.

There have been two broad methods proposed:

1.  Support for units of measurement are faked by overloading arithmetic 
operations, usually by replacing floating-point numbers by derived type 
objects ("records" in Pascal or Ada, which were the most common vehicles 
addressed by the papers I read).

2.  Units of measurement are an intrinsic part of the language.

The advantage of (1) is that it doesn't need changes in the language.

The disadvantages are numerous, and include

1a. An enormous number of procedures if kind type parameters are used 
for exponents of the fundamental units.

Consider the seven fundamental units of physical quantities that SI 
defines: Length, Time, Mass, Thermodynamic temperature, Electric 
current, Amount of a substance, and Luminous Intensity.

In physical problems, one needs the exponent range to be (at least) 
-3..3 for length, -2..1 for time, -2..2 for mass, and -1..1 for the 
rest.  Multiply these out, then multiply by the number of kinds of real 
numbers, and you have the number of functions you need in order to 
overload unary operators (22,680 or 34,020).  Square it and you have 
have the number needed in order to overload binary operators 
(514,382,400).   The result is over two billion for three unary 
operators (count exponentiation as unary since the exponent has to be 
unitless) and four binary ones (2,057,597,640).  If you want to add 
radians, which SI doesn't count as a fundamental unit, multiply by a 
skosh more than four.  If you want fractional exponents, even only ones 
that can have a denominator of only either 1 or 2, square it again.  
Then explain how the units of the result of exponentiation get computed 
by the processor if kind type parameters are used.  This doesn't count 
assignment or I/O.  Add another hundred thousand procedures or so.

Too bad we removed macros from the 2008 work plan.

1b. There is a runtime penalty if components or length type parameters 
are used.  Yeah, it can be turned off by changing the guts of the 
derived type to just the value, and crossing your fingers and hoping 
that the compiler optimizes away the functions by inlining them.  As 
Dijkstra said, this makes as much sense as the hostess on the airplane 
telling you to buckle your seatbelt before the airplane is pushed out 
from the gate, and then coming around and taking it away after you've 
taxied out to the end of the runway and are preparing to take off.  The 
problem that doomed the Mars Climate Orbiter was a runtime problem.

1c. It's difficult to include I/O processing of units.  About as 
difficult as faking namelist.

1d. If you want units of measure, which SI calls "dimensions" instead of 
units, you need more fields (floating-point ones instead of integers) in 
the derived-type object that represents each floating-point number, and 
more runtime work.  By dimensions, I mean things like meters and feet, 
seconds and days, kilograms and pounds,... instead of the more abstract 
length, time, mass.  This work can't be turned off by deleting the 
components because then the distinction between pound-seconds and 
Newton-seconds disappears.  It also doesn't get optimized away when the 
quantities in the operation are the fundamental quantities of your 
system (e.g. meters, seconds kilograms), for which the scale factors 
happen to be 1.0 and the offsets happen to be 0.0.

1e. If you want units other than physical units, such as dollars or 
pound sterling for financial work, you need more components, or more 
length or kind type parameters, and more functions.  If you want units 
that aren't simply powers of fundamental units, for example decibels, 
you need yet more.

1f. Nobody does it because of the above problems.  Would you like to 
write a few hundred functions (or maybe a few thousand) for your 
particular application, or would you only use the facility if you had a 
library?  Do you really expect to have a library of two billion functions?

The advantage of (2) is that it has few of the disadvantages of (1).  
Especially the last one.  If units of measure were an intrinsic part of 
the language, they would be used.  The disadvantages of (2) are

2a. It requires changes in the language.

2b. Support for units of measure (i.e. dimensions such as feet and 
meters instead of fundamental abstractions such as length) requires 
runtime action, but the processor sees that requirement in the 
declaration of objects and can optimize it.





More information about the J3 mailing list