         Edinburgh IMP77 Compiler - Version 8.4

    1  %begin
    2  
    3      {----------------------------------------------------------------------------}
    4      ! Convert a floating point number to a string, along the lines of
    5      ! +/-nnn.nnn@+/-nn, to occupy Places character spaces
    6      !                        with sf significant figures.
    7      ! Rounding/truncation will occur to ensure sf limits
    8      !
    9      ! %longreal f = floating point number to convert to a string
   10      ! %integer sf = number of significant figures required
   11      !      places = number of characters in converted string
   12      !
   13      ! N.B. sf must be in the range of accuracy of %longreal (<15)
   14      !  places must be slightly greater than sf
   15      !         (to allow for sign and scientific notation)
   16      !         sign uses 1 character (+ is omitted)
   17      !         decimal point uses 1 character
   18      !         scientific notation could use :
   19      !                1 char for "@" ndicating scientific notation
   20      !                1 char for sign of exponent (sign always present)
   21      !                1+ char for integer exponent
   22      !
   23      ! N.B. scientific notation is only used if the decimal string could
   24      !      not fit in the places required
   25      !
   26      ! eg. F to S (0.003999, 3, 7) -> " 0.004 " (note rounding creates zeros after the 4)
   27      ! or
   28      ! eg. F to S (0.003999, 3, 4) -> " 4.00@-3" (converted to scientific notation to fit)
   29      ! eg. F to S (0.003999, 3, 6) -> " 0.004" (fits exactly)
   30      !
   31      %string(255) %function imp77 F to S( %longreal f, %integer sf, places)
   32          %string(255) s,sx
   33          %string(15) science
   34          %integer dc,carry
   35          %integer sign,exponent, digit, point
   36  
   37          %if (sf > 14) %then sf = 14
   38  
   39          %begin
   40              %integer i
   41              %integerarray digits(1:sf+1)
   42  
   43              sign = 0
   44  
   45              %for i = 1,1,sf+1 %cycle
   46                  digits(i) = 0
   47              %repeat
   48  
   49              %if (f < 0) %then sign = 1 %and f = -f
   50  
   51              ! clear the floating point string
   52              length(s) = 0
   53  
   54              %if (f = 0) %start
   55                  ! convert to positive zero
   56                  sign = 0
   57                  dc = 2
   58                  sf = 2
   59                  exponent = 0
   60                  point = 1
   61              %finish %else %start
   62                  ! prepare the exponent, point values for (f # 0)
   63                  ! evaluate the exponent value
   64                  exponent = 0
   65                  %while f < 1 %cycle
   66                      f = f * 10
   67                      exponent = exponent - 1
   68                  %repeat
   69  
   70                  %while f >= 10 %cycle
   71                      f = f / 10
   72                      exponent = exponent + 1
   73                  %repeat
   74  
   75                  ! locate the decimal point
   76                  point = 1
   77                  ! zero the digit count
   78                  dc = 0
   79  
   80                  ! Loop to get the significant figure digits with an extra digit
   81                  ! so we can use it to round the the required sig figs
   82                  ! Rounding as we go through this loop can "oversize" the digit.
   83                  ! The next stage does the rounding to the correct sig fig.
   84                  %for i = 1,1,sf + 1 %cycle
   85                      digit = int pt(f)
   86                      %if (digit > 9) %then digit = 9
   87                      dc = dc + 1
   88                      digits(dc) = digit
   89                      f = (f - digit)*10
   90                  %repeat
   91  
   92                  ! do the rounding to the sf significant figures
   93                  %if (digits(dc) > 4) %start
   94                      ! we need to possibly round up the digits sequence
   95                      carry = 1
   96                      %for i = dc - 1,-1,1 %cycle
   97                          digits(i) = digits(i) + carry
   98                          %if (digits(i) > 9) %start
   99                              carry = 1
  100                              digits(i) = 0
  101                          %finish %else %start
  102                              carry = 0
  103                          %finish
  104                      %repeat
  105                  %finish
  106                  ! ignore the rounding digit
  107                  dc = dc - 1
  108  
  109                  ! Now eliminate any trailing zeros
  110                  ! We assume that rounding has created
  111                  ! a sequence of trailing zeros
  112                  %while (digits(dc) = 0) %and (dc > 1) %cycle
  113                      dc = dc - 1
  114                  %repeat
  115                  sf = dc
  116              %finish
  117  
  118              length(s) = 0
  119              point = 1
  120              %for i = 1,1,sf %cycle
  121                  s = s.tostring(digits(i) + '0')
  122                  %if (point = i) %then s = s."."
  123              %repeat
  124              %if (sf = point) %then s = s."0"
  125              %if (exponent < 0) %then s=s."@-".itos(-exponent,0)
  126              %if (exponent > 0) %then s=s."@+".itos(exponent,0)
  127              science = s
  128  
  129              ! So, now for the other floating point layouts
  130              ! we should see which version will fit into the places allowed
  131              ! 1) 0.00000nnnn (point <= 0)
  132              ! OR
  133              ! 2) nnnn.0 (point = sf)
  134              ! OR
  135              ! 3) nnnn00000.0 (point > sf)
  136              !
  137              length(s) = 0
  138              point = exponent + 1
  139              ! First form the sig fig digit string
  140              ! possibly including a decimal point
  141              %for i = 1,1,sf %cycle
  142                  s = s.tostring(digits(i) + '0')
  143                  %if (point = i) %then s = s."."
  144              %repeat
  145  
  146              ! Checking for format (1)
  147              ! 1) 0.00000nnnn (point <= 0)
  148              %if (point <= 0) %start
  149                  %for i=1,1,-point %cycle
  150                      s = "0".s
  151                  %repeat
  152                  s = "0.".s
  153              %finish
  154  
  155              ! Checking for format (2)
  156              ! 2) nnnn.0 (point = sf)
  157              %if (point = sf) %start
  158                  s = s."0"
  159              %finish
  160  
  161              ! Checking for format (3)
  162              ! 3) nnnn00000.0 (point > sf)
  163              %if (point > sf) %start
  164                  %for i = 1,1,(point - sf) %cycle
  165                      s = s."0"
  166                  %repeat
  167                  s = s.".0"
  168              %finish
  169  
  170              ! Check to see which fits scientific v decimal notation
  171              ! Preference is for the decimal notation
  172              %if (length(s) > places) %start
  173                  s = science
  174              %finish
  175  
  176              %if (sign # 0) %start
  177                  s = "-".s
  178              %finish %else %start
  179                  s = " ".s
  180              %finish
  181  
  182              %if (length(s) < places) %start
  183                  %while (length(s) < places) %cycle
  184                      s = s." "
  185                  %repeat
  186              %finish
  187          %end
  188  
  189          %result = s
  190      %end
?SX unused
  191  {----------------------------------------------------------------------------}
  192  {----------------------------------------------------------------------------}
  193      %routine imp77 print(%longreal f, %integer sf,places)
  194          printstring( imp77 F to S( f, sf, places ) )
  195      %end
  196  {----------------------------------------------------------------------------}
  197  {----------------------------------------------------------------------------}
  198      ! Print a floating point number out, along the lines of
  199      ! +/-nnn.nnn@+/-nn, to occupy Places character spaces.
  200      ! Note - there's a bug in this code such that it does not
  201      ! round the number properly.  EG 3.999999999 to 4 places
  202      ! should be 4.00 but we print 3.99
  203  
  204      %routine imp77 printfl(%longreal x, %integer places)
  205          %integer exponent, digit, point, printexpo
  206  
  207          %if x = 0 %start
  208              printsymbol('0')
  209              printsymbol('.')
  210              printsymbol('0')
  211              %while places > 3 %cycle
  212                  printsymbol('0')
  213                  places = places - 1
  214              %repeat
  215              %return
  216          %finish
  217  
  218          %if x < 0 %then printsymbol('-') %and x = -x %and places = places - 1
  219  
  220          %if places < 3 %then places = 3
  221     
  222          exponent = 0
  223          printexpo = 0
  224  
  225          %while x < 1 %cycle
  226              x = x * 10
  227              exponent = exponent - 1
  228          %repeat
  229  
  230          %while x >= 10 %cycle
  231              x = x / 10
  232              exponent = exponent + 1
  233          %repeat
  234  
  235          ! Now X is between 1.0 and 9.99 and exponent is set accordingly
  236          ! If the exponent is "large" we will use scientific notation
  237          point = places - 2;     ! for useful digits after the "0."
  238          %if exponent >= places %or exponent < -point %start
  239              printexpo = exponent
  240              exponent = 0
  241              places = places - 2
  242          %finish
  243  
  244          ! Now the exponent is small-ish
  245          %if exponent < 0 %start;      ! 0.nnnn
  246              printsymbol('0')
  247              printsymbol('.')
  248              places = places - 2
  249  
  250              %while exponent < -1 %cycle
  251                  printsymbol('0')
  252                  exponent = exponent + 1
  253                  places = places - 1
  254              %repeat
  255  
  256              point = -1; ! because we've already passed that
  257          %else;          ! nnn.nnn
  258              point = exponent
  259          %finish
  260  
  261          %while places > 0 %cycle
  262              digit = int pt(x)
  263              ! Rounding as we go through this loop can "oversize" the digit.  This
  264              ! of course tells us that we should have printed (eg) 40000 but we
  265              ! are now stuck with printing 39999
  266              %if digit > 9 %then digit = 9
  267              printsymbol(digit + '0')
  268              x = (x - digit)*10
  269              %if point = 0 %then printsymbol('.') %and places = places - 1
  270              point = point - 1
  271              places = places - 1
  272          %repeat
  273  
  274          %if printexpo # 0 %start
  275              printsymbol('@')
  276  !!            write68k(printexpo, 1)
  277          %finish
  278      %end
  279  
  280  %endofprogram
?IMP77PRINTFL unused
?IMP77PRINT unused

  166 Statements compiled
