ETHZ_Logo RAMSES_Logo_Right   RAMSES   RAMSES_Logo_Left Systems Ecology  
Start    search button      Modules:   A-Z   Function   Layer        QuickRefs:   DM   AuxLib   AuxLibE   SciLib   EasyMW   MW   ISIS   RMSLib

DEFINITION MODULE DMConversions;

  (*******************************************************************

    Module  DMConversions     ('Dialog Machine' DM_V3.0)

      Copyright (c) 1986-2006 by Andreas Fischlin, Alex Itten and
      ETH Zurich.

    Purpose   Provides routines to convert numbers into strings
              and vice versa.

    Remarks   The routines converting a string to a number test
              for syntactical correctness. Upon returning from the
              routine the variable done indicates whether the
              string contained a syntactically correct number or
              not.  The syntax for integers, cardinals, and reals
              is similar to that adopted by the language
              Modula-2.

              IMPORTANT IMPLEMENTATION RESTRICTION:

              Under the Unix Platform (BatchDM, RASS - RAMSES
              Simulation Server) the implementation of this
              module assumes you can compute gradual underflows
              without triggering exceptions.  E.g.
              StringToReal("1.0E-50",...)  will generate an
              underflow and the resulting real number will be
              denormalized.  Enabling underflow exceptions will
              prevent a successful completion of such string to
              number conversions.  Please make sure underflow
              exceptions are disabled. See also module DMFloatEnv
              for further details on how to set and control the
              floating point environment of the computer on
              which the 'Dialog Machine' is running.

              This module belongs to the 'Dialog Machine'.


    Programming

      o Design
        Andreas Fischlin          23/04/1986

      o Implementation
        Alex Itten                30/10/1986
        Andreas Fischlin          19/03/1987


    ETH Zurich
    Systems Ecology
    CHN E 35.1
    Universitaetstrasse 16
    8092 Zurich
    SWITZERLAND

    URLs:
        <mailto:RAMSES@env.ethz.ch>
        <http://www.sysecol.ethz.ch>
        <http://www.sysecol.ethz.ch/SimSoftware/RAMSES>


    Last revision of definition:  22/03/2000  AF

  *******************************************************************)


  FROM SYSTEM IMPORT BYTE;


  TYPE
    RealFormat = (FixedFormat, ScientificNotation);

    (*
      The following general conventions hold:

      o Conversions from a string into a number:

        The string will be analyzed and interpreted according to
        the EBNF syntax as given for each converting routine.  If
        the conversion is not successful the parameter done will be
        set to FALSE.  The number variable passed to hold the
        result is left untouched if the converions fails. Since
        range errors (e.g. numbers of type INTEGER are restricted
        to the range [-32768..+32767]) done may be FALSE although
        the string content was syntactically correct.  To
        differentiate between a range and syntax error use
        procedure IllegalSyntaxDetected immediately after calling
        the conversion routine.

      o Conversions from a number into a string:

        The conversion of the number will produce "length" digits, if
        necessary leading blanks will be inserted (exception
        BytesToHexString) to produce exactly length characters. If the
        number has more than "length" digits then all digits are
        filled into the result string. If the result string is too
        small to hold all digits, then a questionMark ("?") will be
        returned in string[0].

        EBNF for digits:

          decDigit = ("0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9")
          hexDigit = (decDigit|"A"|"a"|"B"|"b"|"C"|"c"|"D"|"d"|"E"|"e"|"F"|"f")

    *)




  PROCEDURE StringToCard(str: ARRAY OF CHAR; VAR card: CARDINAL;
                         VAR done: BOOLEAN);
    (*
      converts a cardinal number from str according to EBNF-syntax:
      ["+"]{}
      The accepted range is [0..65535]
    *)

  PROCEDURE CardToString(card: CARDINAL; VAR str: ARRAY OF CHAR;
                         length: CARDINAL);

  PROCEDURE StringToLongCard(str: ARRAY OF CHAR; VAR lcard: LONGCARD;
                         VAR done: BOOLEAN);
    (*
      converts a long cardinal number from str according to EBNF-syntax:
      ["+"]{}["D"|"d"]
      The accepted range is [0D..4294967295D]
    *)

  PROCEDURE LongCardToString(lcard: LONGCARD; VAR str: ARRAY OF CHAR;
                         length: CARDINAL);

  PROCEDURE StringToInt(str: ARRAY OF CHAR; VAR int: INTEGER;
                        VAR done: BOOLEAN);
    (*
      converts an integer number from str according to EBNF-syntax:
      ["-"|"+"]{}
      The accepted range is [-32768..+32767]
    *)

  PROCEDURE IntToString(int: INTEGER; VAR str: ARRAY OF CHAR;
                        length: CARDINAL);

  PROCEDURE StringToLongInt(str: ARRAY OF CHAR; VAR lint: LONGINT;
                        VAR done: BOOLEAN);
    (*
      converts a long integer number from str according to EBNF-syntax:
      ["-"|"+"]{}["D"|"d"]
      The accepted range is [-2147483648D..+2147483647D]
    *)
  PROCEDURE LongIntToString(lint: LONGINT; VAR str: ARRAY OF CHAR;
                        length: CARDINAL);

  PROCEDURE StringToReal(str:ARRAY OF CHAR; VAR real: REAL;
                         VAR done: BOOLEAN);
    (*
      converts a real number from str according to EBNF-syntax:

      ["-"|"+"]
      (
        ( {}  ["."|","] [{}] |
         [{}] ("."|",")  {}   )
        [ "E" ["-"|"+"] {} ]
      | ( "INF" | ("NAN") "(" {} ")" )
      ). (syntax case insensitive)

      The accepted range consists of 3 intervals:
       [-3.38E+38..-3.38E-38], 0.0, [+3.38E-38..+3.38E+38]

      For encoding NAN's (Not A Number) see IEEE 754 standard for
      floating-point arithmetic or SANE manual, p. 41, Table 5-1.

      Ex.: 0.123, 2,5, -31e+34, 2.1234E+24, .1, .1e+3, 2E-24,
           NAN, -INF, +nan(017), -NaN(02)
    *)

  PROCEDURE RealToString(real: REAL; VAR str: ARRAY OF CHAR;
                         length, dec: CARDINAL; f: RealFormat);

    (*
      Converts a real number real into the string str, using length
      digits and max. dec digits after the decimal point ".".
      Depending on the chosen format f, the number is converted in
      either fixed or scientific notation:

      Examples:

        fixed format:      scientific format:

        |xxxx#xxxx#xxxx#   |xxxx#xxxx#xxxx#    length   dec   comment

           -123.456         -1.234E+02           10      3
            -123.45          -1.23E+02           10      2
         -123.45678         -1.234E+02           10      6     truncates decimal digits
          123.4              1.2E+02              3      2     truncates decimal digits
                                                               and overwrites right
                                                               boundary

      If str is too small to represent the number "real" correctly
      (e.g. HIGH(str)<8), then a questionMark ("?") will be
      returned in str[0]. Otherwise, if HIGH(str) is equal or
      larger than 8 and the number is too large to be represented
      in fixed format in the given string str, then the number will
      be displayed in scientific format. If you want to be sure
      that a real number does  not take more room than a specified
      length, you may use a string variable of TYPE
      ARRAY[0..maxLength] OF CHAR (but maxLength must always be
      greater or equal than 8).

      The current implementation returns up to 19 significiant
      digits, But only 6 (!) decimal digits are always correct (=
      TRUNC(6.924) = TRUNC(lg10(2^23)).  Type REAL reals are
      single precision real numbers according to the IEEE 754
      standard for floating-point arithmetic and have 23 binary
      digits in their fractional part (8 for the exponent, 1 for
      the sign).  Positive numbers begin always with at least one
      leading blank so they are as long as their negative
      equivalences.

      For fixed format DMConversions knows two SPECIAL CASES:

      1. length = 1    Numbers are shown with significant digits always
                       and their representation requires as many
                       characters as needed (given destination string is
                       large enough).  Thus the format may be
                       automatically switched accordingly.  E.g.
                       0.0000000000001 if dec = 2 is not shown as 0.00
                       but as 1.00E-13.  Numbers have always dec decimal
                       digits, unless the destination string is too
                       small to hold that many characters.  Numbers
                       larger than 1.0E+7 or smaller than 1.0E-7 (7 =
                       number of significant digits) are shown in
                       ScientificNotation to minimize character usage.
                       If the string is to small to hold a number
                       according to the latter rule, the format may
                       change even for smaller numbers.  No leading
                       blanks are inserted, but, positive numbers have a
                       single leading blank (" ") in place of the
                       negative sign.

      2. length = 0    In adition to the case "length = 1"
                       - a leading blank is never inserted (positive numbers too)
                       - trailing zeros "0" are suppressed (in both formats).
                       - exponents in scientific formats have no
                         leading zeros
                       - max. 7 significiant digits are displayed, since
                         single precision reals (32 bit) do not support
                         more digits. This avoids the display of
                         spurious digits and prevents unwanted
                         ugly displays, such as 0.79999993 instead of 0.8.

                       This case is particularly useful when the number
                       is to be inserted in the middle of some text
                       or for interactive dialogs. Information is
                       always preserved up to dec significant,
                       decimal digits (unless dec>7) and format is chosen
                       according to minimum space requirements.
                       For interactive use it is a good idea to specify
                       dec not too large, i.e. up to the maximum
                       significant numbers, i.e. <= 7.

                       For output on text files use 9 decimal digits to
                       minimize conversion errors when subsequent
                       reading is planned.

       Examples:

       fixed format:       scientific format:

       |xxxx#xxxx#xxxx#    |xxxx#xxxx#xxxx#    length  dec  comment

          123.50000            1.2350E+02        1      4   see special case 1
         123.5                1.235E+2           0      4   see special case 2

         (This feature is used in DMEntryForms to display real numbers) *)



  PROCEDURE StringToLongReal(Str:ARRAY OF CHAR; VAR longReal: LONGREAL;
                        VAR done: BOOLEAN);
    (*
      converts a real number from str according to EBNF-syntax:

      ["-"|"+"]
      (
        ( {}  ["."|","] [{}] |
         [{}] ("."|",")  {}   )
        [ ["D"] | ("D"|"E")["-"|"+"]{} ]
      | ( "INF" | ("NAN") "(" {} ")" )
      ).  (syntax case insensitive)

      The accepted range consists of 3 intervals:
       [-1.79D+308..-1.79D-308], 0.0, [+1.79D-308..+1.79D+308]

      For encoding NAN's (Not A Number) see IEEE 754 standard for
      floating-point arithmetic or SANE manual, p.  41, Table 5-1.

      Ex.: 0.123, 2,5, 0.2415D, 31e+34, 2.1234E+24, .1, .1e+3, 2D-24
           NAN, -INF, +nan(017), -NaN(02)
    *)

  PROCEDURE LongRealToString(longreal: LONGREAL; VAR str: ARRAY OF CHAR;
                           length, dec: CARDINAL; f: RealFormat);

    (*
      Converts a real number real into the string str, using length
      digits and max. dec digits after the decimal point ".".
      Depending on the chosen format f, the number is converted in
      either fixed or scientific notation:

       Examples:

       fixed format:       scientific format:

       |xxxx#xxxx#xxxx#    |xxxx#xxxx#xxxx#    length  dec  comment

           -123.45678       -1.23478E+002        13     5
              123.456          1.236E+002        11     3
        -12345.678          -1.23E+004           10     5   truncates decimal digits
         123.4               1.2E+002             3  >  0   truncates decimal digits
                                                            and overwrites right
                                                            boundary

      If str is too small to represent the number "longreal"
      correctly (e.g. HIGH(str)<9), then a questionMark ("?")
      will be returned in str[0].  Otherwise, if HIGH(str) is
      equal or larger than 8 and the number is too large to be
      represented in fixed format in the given string str, then
      the number will be displayed in scientific format.  If you
      want to be sure that a real number does not take more room
      than a specified length, you may use a string variable of
      TYPE ARRAY[0..maxLength] OF CHAR (but maxLength must always
      be greater or equal than 9).

      The current implementation returns up to 19 significiant
      digits, But only 15 decimal digits are always correct (=
      TRUNC(15.654) = TRUNC(lg10(2^52)).  Type LONGREAL reals are
      double precision real numbers according to the IEEE 754
      standard for floating-point arithmetic and have 52 binary
      digits in their fractional part (11 for the exponent, 1 for
      the sign).  Positive numbers begin always with at least one
      leading blank so they are as long as their negative
      equivalences.

      For fixed format DMConversions knows two exceptional SPECIAL CASES:

      1. length = 1    Numbers are shown with significant digits always
                       and their representation requires as many
                       characters as needed (given destination string is
                       large enough).  Thus the format may be
                       automatically switched accordingly.  E.g.
                       0.0000000000001 if dec = 2 is not shown as 0.00
                       but as 1.00E-13.  Numbers have always dec decimal
                       digits, unless the destination string is too
                       small to hold that many characters.  Numbers
                       larger than 1.0E+16 or smaller than 1.0E-16 (16 =
                       number of significant digits) are shown in
                       ScientificNotation to minimize character usage.
                       If the string is to small to hold a number
                       according to the latter rule, the format may
                       change even for smaller numbers.  No leading
                       blanks are inserted, but, positive numbers have a
                       single leading blank (" ") in place of the
                       negative sign.

      2. length = 0    In adition to the case "length = 1"
                       - a leading blank is never inserted (positive numbers too)
                       - trailing zeros "0" are suppressed (in both formats).
                       - exponents in scientific formats have no
                         leading zeros
                       - max. 16 significiant digits are displayed, since
                         double precision reals (64 bit) do only
                         support that many digits on the average
                         (16th digit may already be wrong in some
                         cases).  This avoids the display of
                         spurious digits and prevents unwanted
                         ugly displays, such as 0.79999999999993
                         instead of 0.8.

                       This case is particularly useful when the number
                       is to be inserted in the middle of some text
                       or for interactive dialogs. Information is
                       always preserved up to dec significant,
                       decimal digits (unless dec>15) and format is chosen
                       according to minimum space requirements.
                       For interactive use it is a good idea to specify
                       dec not too large, i.e. up to the maximum
                       significant numbers, i.e. <= 15.

                       For output on text files use 17 decimal digits to
                       minimize conversion errors when subsequent
                       reading is planned.

       Examples:

       fixed format:       scientific format:

       |xxxx#xxxx#xxxx#    |xxxx#xxxx#xxxx#    length dec  comment

         123.50000           1.2350E+002          1     4   see special case 1
        123.5               1.235E+2              0     4   see special case 2

    *)



  PROCEDURE HexStringToBytes(hstr: ARRAY OF CHAR; VAR x: ARRAY OF BYTE;
                             VAR done: BOOLEAN);
    (*
      converts the bytes from hstr according to EBNF-syntax:
      {}.  There must be an even number of hexDigits
      present.
    *)
  PROCEDURE BytesToHexString(x: ARRAY OF BYTE; VAR hstr: ARRAY OF CHAR);
    (*
      Conversion between any variable and a hexadecimal
      representation. Note that in hex 1 byte needs 2 characters.
      Formatting is always done in the most simplest form, e.g. no
      leading blanks.
    *)

  PROCEDURE SetHexDigitsUpperCase( upperC: BOOLEAN );
    (* Allows to specify whether the result produced by BytesToHexString
    will contain upper case letters or not *)



  PROCEDURE IllegalSyntaxDetected(): BOOLEAN;
    (*
      Returns whether any of the procedures StringToXyz (where Xyz
      stands for Card, LongCard, Int, LongInt, Real, or LongReal)
      has detected a syntax error.  Typically this procedure is
      called if any of these conversion routines has returned done
      = FALSE and you want to differenciate the cause of this
      failure, i.e. whether it is due to a syntax or a range error.
    *)



  PROCEDURE UndefREAL(): REAL;
  PROCEDURE UndefLONGREAL(): LONGREAL;
    (*

      These two procedures return an undefined value according to
      IEEE standard for binary floating-point arithmetic IEEE Std
      754-1985.  The value is "NAN(017)" (NAN - Not A Number,
      NANASCBIN ~ attempt to convert invalid ASCII string) and is
      a signalling NAN, i.e. it will signal an exception unless
      involved in a mere assignment statement.  Any involvement
      in numeric expressions or a relation will trigger a fatal
      exception of type "invalid operand" (given of course this
      exception is currently enabled).

      The following codes may help you to interprete NAN numbers:

         1 : invalid square root such as sqrt(-1)
         2 : invalid addition such as +INF  - +INF
         4 : invalid division such as 0/0
         8 : invalid multiply such as 0*INF
         9 : invalid remainder or mod such as x REM 0
        17 : attempt to convert invalid ASCII string
        20 : result of converting comp NaN to floating
        21 : attempt to create a NaN with a zero code such as NAN(0)
             Note: NAN(0) (Macintosh) and NAN(255) (Sun) ~ INF
        33 : invalid argument to trigonometric routine
        34 : invalid argument to inverse trig routine
        36 : invalid argument to log routine
        37 : invalid argument to x^i or x^y routine
        38 : invalid argument to financial routine

      Note INF corresponds always to NAN(0), regardless of platform.
      However, the result of operations involving operands of value
      NAN and/or INF may be platform dependent.

      On the Macintosh platform the following, diagnostic error
      messages are produced: "Invalid operands (SANE)" or "REAL
      overflow or invalid operand (System)".  The actual message
      displayed depends on the current floating-point arithmetic
      in use.  If SANE is in use ("'alwaysSANE' on" in section
      "SANE" of the User.Profile), the first error message is
      shown.  Otherwise ("'alwaysSANE' off" in section "SANE" of
      the User.Profile), then the Fink arithmetic is in use for
      single precision real arithmetic and the second error
      message is shown.  Note, for LONGREAL, i.e. double
      precision real arithmetic, MacMETH always uses SANE on the
      Macintosh platform, regardless of the settings of flag
      'alwaysSANE'.  Note also, if SANE is in use and flag
      'invalidHalt' is off, the use of UndefREAL() in an
      expressions triggers never an exception.

      IMPORTANT IMPLEMENTATION RESTRICTION of SANE (Macintosh
      platform only): In case you set "'invalidHalt' off" in
      section "SANE" of your User.Profile (or by calling
      DisableHalt(invalid) from module DMFloatEnv), the
      evaluation of relations involving NANs may differ from what
      you might expect; see final comments below for procedure
      IsUndefREAL and IsUndefLONGREAL.

      Typical usage: Use these values to code that a real
      variable has currently no defined value, e.g. a missing
      value in a series of measurements, by assigning it to the
      real variable.  This behavior may be useful in various
      situations to detect missing values.  For instance the
      curve drawing routines from module DM2DGraphs automatically
      temporarily pause the plotting if such a value is encountered.
    *)

  PROCEDURE IsUndefREAL(x: REAL): BOOLEAN;
  PROCEDURE IsUndefLONGREAL(x: LONGREAL): BOOLEAN;
    (*
      These two procedures allow to inspect an undefined real value in a
      boolean expression.  Any NAN value, i.e. Not A Number, is
      detected, not only UndefREAL() values.  This includes also +INF
      and -INF, values which may result from overflows (By the way, note,
      you may use INF values in relations such as MAX(REAL) < +INF
      which evaluates to TRUE etc.).

      Important note: You may call these routines regardless of the
      current settings of the floating point environment (see
      DMFloatEnv). This contrasts to a direct comparison such as
      made in example (1)

         IF x = UndefREAL() THEN ...                       (1)

      where your program will normally be halted (assuming you
      use default settings, i.e. "'invalidHalt' on" in section
      "SANE" of your User.Profile).  Using IsUndefREAL will allow
      you to avoid the triggering of an exception as shown in
      example (2)

         IF IsUndefREAL(x) THEN ...                        (2)

      Hence, whenever possible, use these routines to detect the
      values UndefREAL() resp. UndefLONGREAL().

      IMPORTANT IMPLEMENTATION RESTRICTION of SANE (Macintosh
      platform only): In case you set "'invalidHalt' off" in
      section "SANE" of your User.Profile (or by calling
      DisableHalt(invalid) from module DMFloatEnv), no exception
      is triggered while example (1) is executed.  HOWEVER, its
      evaluation will always be FALSE, even in cases where x
      holds actually the value UndefREAL()!

      IMPORTANT IMPLEMENTATION RESTRICTION: With compilers
      supporting assignment compatibility beetween REAL and
      LONGREAL such as MacMETH you can call the two routines
      by using an actual parameter of different type than x.
      However, in all these cases the result returned is
      undefined. It is the programmer's responsibility to
      use as actual real paramater only a variable of an
      identical type than that of the formal parameter x.
    *)


END DMConversions.

  Contact RAMSES@env.ethz.ch Last updated: 25-Jul-2011 [Top of page]