system/base/unknown/src/real

Raw file
Back to index

PACKET real DEFINES                            (* Autor: J.Liedtke *) 
                                               (* Stand: 30.04.80  *) 
   text , 
   int ,
   real ,
   round ,
   floor , 
   frac ,
   INCR ,
   DECR ,
   abs , 
   ABS , 
   sign ,
   SIGN ,
   MOD ,
   min ,
   max ,
   put , 
   get , 
   max real ,
   small real :

LET mantissa length = 13 ;

TEXT VAR mantissa ;

ROW 10 REAL VAR real digit ;
 
INT VAR i ; REAL VAR d := 0.0 ;
FOR i FROM 1 UPTO 10 REP
  real digit (i) := d ;
  d := d + 1.0
PER ;
 
REAL PROC max real : 9.999999999999e126 ENDPROC max real ;
 
REAL PROC small real : 1.0e-12 ENDPROC small real ;
 
PROC sld (INT CONST in, REAL VAR real, INT VAR out) :
  EXTERNAL 96 
ENDPROC sld ; 
 
INT PROC decimal exponent (REAL CONST mantissa) : 
  EXTERNAL 97 
ENDPROC decimal exponent ; 
 
PROC set exp (INT CONST exponent, REAL VAR number) : 
  EXTERNAL 98 
ENDPROC set exp ; 
 
REAL PROC tenpower (INT CONST exponent) :
  REAL VAR result := 1.0 ;
  set exp (exponent, result) ;
  result
ENDPROC tenpower ;

REAL PROC floor (REAL CONST real) : 
  EXTERNAL 99 
ENDPROC floor ; 
 
REAL PROC round (REAL CONST real, INT CONST digits) : 
 
  REAL VAR result := real ;
  IF (real <> 0.0) CAND (decimal exponent (real) + digits < mantissa length)
    THEN round result ;
  FI ;
  result .

round result :
  set exp (decimal exponent (result) + digits, result) ;
  IF result >= 0.0
    THEN result := floor (result + 0.5)
    ELSE result := floor (result - 0.5)
  FI ;
  set exp (decimal exponent (result) - digits, result) .

ENDPROC round ; 
 
TEXT VAR result ;
 
TEXT PROC text (REAL CONST real) : 
 
  REAL VAR value := rounded to seven digits ; 
  IF value = 0.0 
    THEN "0.0" 
    ELSE 
      process sign ; 
      get mantissa (value) ; 
      INT CONST exponent := decimal exponent (value) ; 
      get short mantissa ; 
      IF exponent > 7 OR exponent < LENGTH short mantissa - 7 
        THEN scientific notation 
        ELSE short notation 
      FI 
    FI . 
 
rounded to seven digits : 
  round ( real * tenpower( -decimal exponent(real) ) , 6 ) 
        * tenpower ( decimal exponent(real) ) . 
 
process sign : 
  IF value < 0.0 
    THEN result := "-" ; 
         value := - value 
    ELSE result := "" 
  FI . 
 
get short mantissa : 
  INT VAR i := 7 ; 
  WHILE (mantissa SUB i) = "0" REP 
    i DECR 1 
  UNTIL i=1 END REP ; 
  TEXT CONST short mantissa := subtext (mantissa, 1, i) . 
 
scientific notation : 
  result CAT (mantissa SUB 1) ; 
  result CAT "." ; 
  result CAT subtext (mantissa, 2, 7) ; 
  result + "e" + text (exponent) . 
 
short notation : 
  result CAT subtext (short mantissa, 1, exponent+1) ; 
  result CAT (exponent+1 - LENGTH short mantissa) * "0" ; 
  result CAT "." ; 
  IF exponent < 0 
    THEN result + (-exponent-1) * "0" + short mantissa 
    ELSE result + subtext (short mantissa, exponent+2) 
  FI . 
 
ENDPROC text ; 
 
PROC get mantissa (REAL CONST number) :

  REAL VAR real mantissa := number ;
  mantissa := "" ;
  INT VAR i , digit ;
  FOR i FROM 1 UPTO mantissa length REP
    sld (0, real mantissa, digit) ;
    mantissa CAT code (digit + 48)
  PER ;

ENDPROC get mantissa ;

PROC put (REAL CONST real) : 
 
  put (text (real) ) 
 
ENDPROC put ; 
 
TEXT PROC text (REAL CONST real, INT CONST length, fracs) :
 
  REAL VAR value := round (real, fracs) ;
  INT VAR  exponent  := decimal exponent (value) ;
           IF value = 0.0 THEN exponent := 0 FI ;
  INT VAR  floors    := exponent + 1 ,
           floor length := length - fracs - 1 ;
           IF value < 0.0 THEN floor length DECR 1 FI ;
 
  IF value too big
    THEN length * "*"
    ELSE transformed value
  FI .
 
transformed value :
  process leading blanks and sign ;
  get mantissa (value) ;
  result CAT subtext (mantissa, 1, floors) ;
  IF LENGTH mantissa < floors
    THEN result CAT (floors - LENGTH mantissa) * "0"
  FI ;
  result CAT "." ;
  IF exponent < 0
    THEN result CAT (-floors) * "0" ;
         result CAT subtext (mantissa, 1, length - LENGTH result)
    ELSE result CAT subtext (mantissa, floors+1, floors + fracs)
  FI ;
  IF LENGTH result < length
    THEN result CAT (length - LENGTH result) * "0"
  FI ;
  result .
 
process leading blanks and sign :
  result := (floor length - max(floors,0)) * " " ;
  IF value < 0.0
    THEN result CAT "-" ;
         value := - value
  FI .
 
value too big :
  floors > floor length .
 
ENDPROC text ;
 
REAL PROC real (TEXT CONST text) : 
 
  skip leading blanks ;
  sign ; 
  mantissa part ; 
  exponent ; 
  check correct conversion ;
  result . 
 
skip leading blanks :
  INT VAR pos := 1 ;
  skip blanks .
 
skip blanks :
  WHILE (text SUB pos) = " " REP
    pos INCR 1
  PER .
 
sign : 
  BOOL VAR negative ; 
  IF (text SUB pos) = "-" 
    THEN negative := TRUE ; 
         pos INCR 1
  ELIF (text SUB pos) = "+" 
    THEN negative := FALSE ; 
         pos INCR 1
  ELSE   negative := FALSE
  FI . 
 
mantissa part: 
  REAL VAR value := 0.0 ; 
  INT VAR exponent pos := 0 ;
  WHILE pos <= LENGTH text REP 
    TEXT VAR digit := text SUB pos ; 
    IF digit <= "9" AND digit >= "0" 
      THEN value := value * 10.0 + real digit (code (digit) - 47) ;
           pos INCR 1 
    ELIF digit = "." 
      THEN pos INCR 1 ;
           exponent pos := pos
    ELSE LEAVE mantissa part 
    FI 
  END REP . 
 
exponent : 
  INT VAR exp ;
  IF exponent pos > 0
    THEN exp := exponent pos - pos
    ELSE exp := 0
  FI ;
  IF (text SUB pos) = "e" 
    THEN exp INCR int (subtext(text,pos+1)) 
  FI . 
 
check correct conversion :
  skip blanks ;
  IF pos > LENGTH text
    THEN set conversion (TRUE)
    ELSE set conversion (FALSE)
  FI .
 
result : 
  value := value * tenpower (exp) ; 
  IF negative 
    THEN - value 
    ELSE value 
  FI . 
 
ENDPROC real ; 
 
TEXT VAR word ;
 
PROC get (REAL VAR value) : 
 
  get (word) ; 
  value := real (word) 
 
ENDPROC get ; 
 
REAL PROC abs (REAL CONST value) : 
 
  IF value >= 0.0 
    THEN  value 
    ELSE -value 
  FI 
 
ENDPROC abs ; 
 
REAL OP ABS (REAL CONST value) : 
 
  abs (value) 
 
ENDOP ABS ; 
 
INT PROC sign (REAL CONST value) :
 
  IF   value < 0.0 THEN -1
  ELIF value = 0.0 THEN  0
  ELSE                   1
  FI
 
ENDPROC sign ;
 
INT OP SIGN (REAL CONST value) :
 
  sign (value)
 
ENDOP SIGN ;
 
REAL OP MOD (REAL CONST left, right) :
 
  REAL VAR result := left - floor (left/right) * right ;
  IF left < 0.0
    THEN result + abs (right)
    ELSE result
  FI
 
ENDOP MOD ;
 
REAL PROC frac (REAL CONST value) :
 
  value - floor (value)
 
ENDPROC frac ;
 
REAL PROC max (REAL CONST a, b) :
 
  IF a > b THEN a ELSE b FI
 
ENDPROC max ;
 
REAL PROC min (REAL CONST a, b) :
 
  IF a < b THEN a ELSE b FI
 
ENDPROC min ;
 
OP INCR (REAL VAR dest, REAL CONST increment) :
 
  dest := dest + increment
 
ENDOP INCR ;
 
OP DECR (REAL VAR dest, REAL CONST decrement) : 
 
  dest := dest - decrement
 
ENDOP DECR ;
 
INT PROC int (REAL CONST value) :
 
  INT VAR result := 0, digit ,i ;
  REAL VAR mantissa := value ;
 
  FOR i FROM 0 UPTO decimal exponent (value) REP
    sld (0, mantissa, digit) ;
    result := result * 10 + digit 
  PER ;
 
  IF value < 0.0
    THEN - result
    ELSE   result
  FI
 
ENDPROC int ;
 
REAL PROC real (INT CONST value) :
 
  IF value < 0
    THEN - real (-value)
  ELIF value < 10
    THEN real digit (value+1)
    ELSE split value into head and last digit ;
         real (head) * 10.0 + real digit (last digit+1)
  FI .
 
split value into head and last digit :
  INT CONST
  head := value DIV 10 ,
  last digit := value - head * 10 .
 
ENDPROC real ;
 
ENDPACKET real ;