Next: Converting powers Up: Implementation Previous: Utilising intrinsic compiled

Maintaining appropriate precision

FortranForm will not always produce code of the correct precision, typically only digits are printed. This behaviour was improved in version where floats were (sometimes unnecessarily) printed to full machine precision. However, some compilers do not keep the correct precision unless floats are specified with single or double precision exponents.


In[4]:= FortranForm[100 Pi t //N]

Out[4]//FortranForm= 314.159*t
The default setting for AssignPrecision produces $MachinePrecision digit, double precision C and FORTRAN code for efficiency. In FortranAssign, floating point numbers are coerced into exponent form by default, using an appropriate exponent which is determined by the requested precision.

In[5]:= FortranAssign[100 Pi t, AssignIndent->""]

Out[5]//OutputForm= 3.141592653589793239d2*t
If the requested precision is less than or equal to digits, then single precision floating point numbers are output.

In[6]:= FortranAssign[100 Pi t, AssignPrecision->8,
          AssignIndent->""]

Out[6]//OutputForm= 3.14159265e2*t
Considerable time may be required to coerce numbers into exponent form. The option AssignFortranNumbers can be used to suppress this form if it is not required by the compiler.

Constants and function arguments can be maintained in exact form if required. This is advantageous if, for example, a symbol occurs many times - it need only be assigned a value once at the beginning of a file. This is also useful if integer arithmetic is required.


In[7]:= FortranAssign[100 Pi t, AssignPrecision->Infinity,
          AssignIndent->""]

Out[7]//OutputForm= 100*Pi*t
As demonstrated, when converting symbolic expressions (a variant of) the function N is applied to convert all numerical constants to reals, with the precision controlled by the option AssignPrecision. Evaluation can be delayed until the code is compiled and executed, by specifying analogous lower case functions (these are all documented and declared in the package).


In[8]:= FortranAssign[sin[1],AssignIndent->""]

Out[8]//OutputForm= sin(1.d0)
Function types can be inferred from the precision of the argument. Thus, explicit use of the dsin/DSIN function is unnecessary. Care should be exercised when using coercion in an expression containing a mixture of single and double precision values. In such cases, the appropriate precision may not be maintained.

This section is concluded with some issues concerning the range of floating point and integer numbers. Mathematica utilises so-called arbitrary precision (or BigNum) arithmetic. Therefore some numbers contained in symbolic expressions may not be admissible in a corresponding compiled language statement. The option AssignRange has been provided to test the range of numbers occurring in the input. Single or double precision real and float ranges are selected for the test according to the setting for AssignPrecision. For details of the IEEE standards see [31][25] (the former reference contains a useful section on rounding strategies, while the latter contains an interesting section on machine representation of numbers). A comprehensive survey of the pitfals of floating point arithmetic is given in [9].

Integer numbers which are outside the permissible range are coerced to floats.


In[9]:= FortranAssign[10^20 t,AssignPrecision->Infinity,
          AssignRange->True]

AssignRange::integer: 
                                                                63
   Expression contains integers outside the permissible range -2
         63
     to 2   - 1 which cannot be represented in IEEE double
     precision and have been converted to floating point numbers.

Out[9]//OutputForm= 1.d20*t
A warning message is output if floating point numbers lie outside the permissible range.


In[10]:= FortranAssign[10.^40 t,AssignPrecision->8,AssignRange->True]

AssignRange::float: 
   Expression contains machine numbers outside the permissible range 
              -38              38
    1.17549 10    to 1.70141 10   for IEEE single precision.

Out[10]//OutputForm= 1.e40*t


bondaren@thsun1.jinr.ru