home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol133 / basicops.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1984-04-29  |  21.9 KB  |  1,013 lines

  1. EXTERNAL flptdemo :: basicops(1);
  2.  
  3. {-------------------------------------------------------------------}
  4. {                                    }
  5. {    PROGRAM TITLE  :  EXTENDED PRECISION FLOATING POINT PACKAGE    }
  6. {                  BASIC OPERATIONS MODULE            }
  7. {                                    }
  8. {    WRITTEN BY     :  LANFRANCO EMILIANI                }
  9. {               MAURITS DE BRAUWWEG 11                }
  10. {               2597-KD DEN HAAG                    }
  11. {               THE NETHERLANDS                    }
  12. {                                    }
  13. {    INITIAL ISSUE  :  DECEMBER 1982                        }
  14. {                                        }
  15. {    PRESENT ISSUE  :  DECEMBER 1982                    }
  16. {                                    }
  17. {    DOCUMENTED IN  :  FILE FLPTPACK.DOC                }
  18. {                                    }
  19. {-------------------------------------------------------------------}
  20.  
  21. {$F-,R- to increase the speed of execution }
  22.  
  23. function absol(u : newreal) : newreal;
  24. begin
  25. absol.s := plus;
  26. absol.f := u.f;
  27. absol.e := u.e
  28. end;
  29.  
  30. function isequal(u, v : newreal) : boolean;
  31. var
  32.     i    : integer;
  33. begin
  34. if ((u.s = plus) and (v.s = minus)) or
  35.    ((u.s = minus) and (v.s = plus)) or
  36.    (u.e <> v.e)
  37.     then isequal := false 
  38.     else
  39.     begin
  40.     i := 1;
  41.     while (u.f[i] = v.f[i]) and (i < n) do i:= i + 1;
  42.     if u.f[i] = v.f[i] then isequal := true else isequal := false
  43.     end;
  44. end;
  45.  
  46. function isgreater(u, v : newreal) : boolean;
  47. var
  48.     i    : integer;
  49. begin
  50. if (u.s = plus) and (v.s = minus) then isgreater := true
  51.   else
  52.   begin
  53.   if (u.s = minus) and (v.s = plus) then isgreater := false
  54.     else {like signs}
  55.     begin
  56.     if u.e > v.e then isgreater := true
  57.       else
  58.       begin
  59.       if u.e < v.e then isgreater := false
  60.     else {like signs and exponents}
  61.     begin
  62.     i := 1;
  63.     while (u.f[i] = v.f[i]) and (i < n) do i := i + 1;
  64.     if u.f[i] > v.f[i] then isgreater := true else isgreater := false
  65.     end
  66.       end
  67.     end
  68.   end
  69. end;
  70.  
  71. function islower(u, v : newreal) : boolean;
  72. begin
  73. if isgreater(u, v) or isequal(u, v) then islower := false
  74. else islower := true
  75. end;
  76.  
  77. function iseqgreat(u, v : newreal) : boolean;
  78. begin
  79. if islower(u, v) then iseqgreat := false else iseqgreat := true
  80. end;
  81.  
  82. function iseqlower(u, v : newreal) : boolean;
  83. begin
  84. if isgreater(u,v) then iseqlower := false else iseqlower := true
  85. end;
  86.  
  87. function isinteger(u : newreal) : boolean;
  88. {WARNING : the following listing is only valid for n <= 6}
  89. var
  90.     i    : integer;
  91. begin
  92. if ((u.e > 0) and (u.e < 129)) or (u.e > (128 + n)) then isinteger := false
  93.   else
  94.     begin
  95.     i := n;
  96.     while (u.f[i] = 0) and (i > 0) do i := i - 1;
  97.     case u.e of
  98.       0  :  if i = 0 then isinteger := true else isinteger := false;
  99.     129  :  if i = 1 then isinteger := true else isinteger := false;
  100.     130  :  if i = 2 then isinteger := true else isinteger := false;
  101.     131  :  if i = 3 then isinteger := true else isinteger := false;
  102.     132  :  if i = 4 then isinteger := true else isinteger := false;
  103.     133  :  if i = 5 then isinteger := true else isinteger := false;
  104.     134  :  if i = 6 then isinteger := true else isinteger := false
  105.     end {case}
  106.     end
  107. end;
  108.  
  109.  
  110. function intadd(u, v : newinteger) : newinteger;
  111. {called by add}
  112. var
  113.     carry    : 0..1;
  114.     j    : integer;
  115.     result  : newinteger;
  116.     cplmt    : newinteger;
  117. begin
  118. carry := 0;
  119. if u.s = v.s then    {like signs}
  120.     begin
  121.     intadd.s := u.s;
  122.     for j := n downto 1 do 
  123.         intadd.f[j] := byteadd(carry, u.f[j], v.f[j]);
  124.     intadd.f[0] := carry
  125.     end
  126. else            {unlike signs}
  127.     begin
  128.     if u.s = plus then
  129.         for j := n downto 1 do
  130.             result.f[j] := bytesub(carry, u.f[j], v.f[j])
  131.     else
  132.         for j := n downto 1 do
  133.             result.f[j] := bytesub(carry, v.f[j], u.f[j]);
  134.     if carry = 0 then
  135.         begin
  136.         result.f[0] := carry;
  137.         result.s := plus
  138.         end
  139.     else
  140.         begin
  141.         result.s := minus;
  142.         carry := 0;
  143.         for j:= n downto 1 do
  144.             cplmt.f[j] := bytesub(carry, 0, result.f[j]);
  145.         cplmt.f[0] := 0;
  146.         result.f := cplmt.f
  147.         end;
  148.     intadd := result
  149.     end;
  150. end;
  151.  
  152. procedure increm (var carry : carrytyp; var u : fraction);
  153. {called by add and by divde}
  154. var
  155.     i    : integer;
  156. begin
  157. carry := 0;
  158. u[n] := byteadd(carry, u[n], 1);
  159. if carry = 1 then
  160.     begin
  161.     for i := (n-1) downto 1 do u[i] := byteadd(carry, u[i], 0);
  162.     if carry =1 then
  163.         begin
  164.         for i := (n-1) downto 1 do u[i+1] := u[i];
  165.         u[1] := 1
  166.         end;
  167.     end;
  168. end;
  169.  
  170.  
  171. function add(u, v : newreal) : newreal;
  172. var
  173.     aux        : newreal;
  174.     shift, exponent : integer;
  175.     i, j        : integer;
  176.     dummy1, dummy2, dummy3  : newinteger;
  177.     temp        : byte;
  178.     carry        : carrytyp;
  179.  
  180. begin
  181. shift := u.e - v.e;
  182. if shift < 0 then
  183.         begin
  184.         aux := u; u := v; v := aux; shift := -shift
  185.         end;
  186. if shift >= (n+2) then add := u
  187.     else
  188.         begin
  189.         exponent := u.e;
  190.         v.f[0] := 0;
  191.         i := 0;
  192.         while i <> shift do
  193.             begin
  194.             for j := n downto 1 do v.f[j] := v.f[j-1];
  195.             i := i + 1
  196.             end;
  197.         dummy1.s := u.s;
  198.         dummy1.f := u.f;
  199.         dummy2.s := v.s;
  200.         dummy2.f := v.f;
  201.         dummy3 := intadd(dummy1, dummy2);
  202.         add.s := dummy3.s;
  203.         if dummy3.f[0] <> 0 then
  204.             begin
  205.             temp := dummy3.f[n];
  206.             for j := (n-1) downto 0 do
  207.                 dummy3.f[j+1] := dummy3.f[j];
  208.             dummy3.f[0] := 0;
  209.             exponent := exponent + 1;
  210.             {rounding if required}
  211.             if (mode = rounded) and ((temp > 128) or
  212.               ((temp = 128) and odd(dummy3.f[n] + 1))) then
  213.                 begin
  214.                 increm(carry, dummy3.f);
  215.                 if carry = 1 then
  216.                     exponent := exponent + 1
  217.                 end;
  218.             end
  219.         else
  220.             begin
  221.             {remove leading zeros}
  222.             i := 1;
  223.             while (dummy3.f[1] = 0) and (i <> n) do
  224.                 begin
  225.                 for j := 1 to (n-1) do
  226.                    dummy3.f[j] := dummy3.f[j+1];
  227.                 dummy3.f[n] := 0;
  228.                 exponent := exponent - 1;
  229.                 i := i + 1
  230.                 end;
  231.             {the result is zero}
  232.             if dummy3.f[1] = 0 then
  233.                 begin
  234.                 add.s := plus;
  235.                 exponent := 0
  236.                 end;
  237.             end;
  238.         dummy3.f[0] := 0;
  239.         add.f := dummy3.f;
  240.         if (exponent>=0) and (exponent<=255) then add.e:=exponent
  241.             else
  242.            begin
  243.            if exponent < 0 then
  244.             begin
  245.             writeln('SUM OR DIFF EXPONENT UNDERFLOW !');
  246.             add.s := plus;
  247.             for i := 0 to n do add.f[i] := 0;
  248.             add.e := 0
  249.             end
  250.            else
  251.             begin
  252.             writeln('SUM OR DIFF EXPONENT OVERFLOW !');
  253.             add.f[0] := 0;
  254.             for i := 1 to n do add.f[i] := 255;
  255.             add.e := 255
  256.             end;
  257.            end;
  258.         end;
  259. end;
  260.  
  261. function sub(u, v : newreal) : newreal;
  262. begin
  263. if v.s = plus then v.s := minus else v.s := plus;
  264. sub := add(u, v)
  265. end;
  266.  
  267. procedure incr (var carry : carrytyp; var u : double_fraction);
  268. {called by mult}
  269. var
  270.     i    : integer;
  271. begin
  272. carry := 0;
  273. u[n] := byteadd(carry, u[n], 1);
  274. if carry = 1 then
  275.     begin
  276.     for i := (n-1) downto 1 do u[i] := byteadd(carry, u[i], 0);
  277.     if carry =1 then
  278.         begin
  279.         for i := (n-1) downto 1 do u[i+1] := u[i];
  280.         u[1] := 1
  281.         end;
  282.     end;
  283. end;
  284.  
  285.  
  286. function multp(u, v : newreal) : newreal;
  287. var
  288.     aux        : double_fraction;
  289.     k        : byte;
  290.     i, j, exponent    : integer;
  291.     carry        : carrytyp;
  292. begin
  293. if u.s = v.s then multp.s := plus else multp.s := minus;
  294. exponent := u.e + v.e - 128;
  295. for j := 0 to twicen do aux[j] := 0;
  296. for j := n downto 1 do
  297.     begin
  298.     k := 0;
  299.     for i := n downto 1 do bytemul(k, aux[i+j], u.f[i], v.f[j]);
  300.     aux[j] := k
  301.     end;
  302. {remove leading zeros}
  303. j := 1;
  304. while (aux[1] = 0) and (j <> twicen) do
  305.     begin
  306.     for i := 1 to (twicen - 1) do aux[i] := aux[i+1];
  307.     aux[twicen] := 0;
  308.     exponent := exponent - 1;
  309.     j := j + 1
  310.     end;
  311. if aux[1] = 0 then  {the result is zero}
  312.     begin
  313.     multp.s := plus;
  314.     exponent := 0
  315.     end;
  316. {rounding if required}
  317. if (mode = rounded) and ((aux[n+1] > 128) or
  318.   ((aux[n+1] = 128) and odd(aux[n] + 1))) then
  319.     begin
  320.     incr(carry, aux);
  321.     if carry = 1 then exponent := exponent + 1
  322.     end;
  323. for i := 0 to n do multp.f[i] := aux[i];
  324. if (exponent >= 0) and (exponent <= 255) then multp.e := exponent
  325.     else
  326.    begin
  327.    if exponent < 0 then
  328.         begin
  329.         writeln('PRODUCT EXPONENT UNDERFLOW !');
  330.         multp.s := plus;
  331.         for i := 0 to n do multp.f[i] := 0;
  332.         multp.e := 0
  333.         end
  334.     else
  335.         begin
  336.         writeln('PRODUCT EXPONENT OVERFLOW !');
  337.         multp.f[0] := 0;
  338.         for i := 1 to n do multp.f[i] := 255;
  339.         multp.e := 255
  340.         end;
  341.    end;
  342. end;
  343.  
  344. procedure dvd(u : double_fraction; v : fraction; var q, r : fraction);
  345. {called by divde and by modu}
  346. var
  347.     aa        : fraction;
  348.     d        : 1..128;
  349.     k, newk        : byte;
  350.     kk        : carrytyp;
  351.     i, j        : integer;
  352.     t1        : real;
  353.     qu        : byte;
  354. begin
  355. d := 256 div (v[1] + 1);
  356. if d = 1 then u[0] := 0 else
  357.     begin  {normalisation}
  358.     k := 0;
  359.     for i := twicen downto 1 do u[i] := byt1mul(k, u[i], d);
  360.     u[0] := k;
  361.     k := 0;
  362.     for i := n downto 1 do v[i] := byt1mul(k, v[i], d);
  363.     end;  {normalisation}
  364. v[0] := 0;
  365. for j := 0 to n do
  366.     begin
  367.     if u[j] >= v[1] then qu := 255
  368.     else
  369.     t1 := (u[j]*256.0 + u[j+1]) / v[1];
  370.     if t1 < 254.5 then qu := round(t1) else qu := 255;
  371.     while (v[1]*256.0 + v[2]*1.0)*qu >
  372.         (u[j]*0.655360E5 + u[j+1]*256.0 + u[j+2]*1.0) do
  373.         qu := qu - 1;
  374.     k := 0;
  375.     for i := n downto 1 do aa[i] := byt1mul(k, qu, v[i]);
  376.     aa[0] := k;
  377.     kk := 0;
  378.     for i := n downto 0 do u[j+i] := bytesub(kk, u[j+i], aa[i]);
  379.     q[j] := qu;
  380.     if kk = 1 then
  381.         begin
  382.         q[j] := qu - 1;
  383.         kk := 0;
  384.         for i := n downto 0 do u[j+i] := byteadd(kk, u[j+i], v[i]);
  385.         end;
  386.     end;
  387. if d = 1 then for i := 1 to n do r[i] := u[i+n]
  388.    else
  389.     begin
  390.     k := 0;
  391.     for i := 1 to n do
  392.         begin
  393.         byt1div(newk, r[i], k, u[i+n], d);
  394.         k := newk
  395.         end;
  396.     end;
  397. end;
  398.  
  399.  
  400. function divde(u, v : newreal) : newreal;
  401. label 999;
  402. var
  403.     i, j    : integer;
  404.     exponent: integer;
  405.     alfa    : double_fraction;
  406.     gamma, delta : fraction;
  407.     carry    : carrytyp;
  408. begin
  409. if v.f[1] = 0 then
  410.     begin
  411.     if u.f[1] <> 0 then
  412.         begin
  413.         writeln('ATTEMPTED DIVISION BY ZERO !');
  414.         {quotient set to max positive value}
  415.         divde.s := plus;
  416.         divde.f[0] := 0;
  417.         for i := 1 to n do divde.f[i] := 255;
  418.         divde.e := 255
  419.         end
  420.        else
  421.         begin
  422.         writeln('ATTEMPTED DIVISION OF ZERO BY ZERO !');
  423.         {quotient set to plus one}
  424.         divde.s := plus;
  425.         divde.f[0] := 0;
  426.         divde.f[1] := 1;
  427.         for i := 2 to n do divde.f[i] := 0;
  428.         divde.e := 129
  429.         end;
  430.     goto 999
  431.     end;
  432. if u.s = v.s then divde.s := plus else divde.s := minus;
  433. exponent := u.e - v.e + 128;
  434. for i := 1 to n do alfa[i] := u.f[i];
  435. for i := (n+1) to twicen do alfa[i] := 0;
  436. dvd(alfa, v.f, gamma, delta);
  437. if gamma[0] <> 0 then
  438.     begin
  439.     for i := (n-1) downto 0 do gamma[i+1] := gamma[i];
  440.     gamma[0] := 0;
  441.     exponent := exponent + 1
  442.     end
  443.    else
  444.     begin
  445.     {remove leading zeros}
  446.     i := 1;
  447.     while (gamma[1] = 0) and (i <> n) do
  448.         begin
  449.         for j := 0 to (n-1) do gamma[j] := gamma[j+1];
  450.         gamma[n] := 0;
  451.         exponent := exponent - 1;
  452.         i := i + 1
  453.         end;
  454.     if gamma[1] = 0 then {the result is zero}
  455.         begin
  456.         divde.s := plus;
  457.         exponent := 0
  458.         end;
  459.     end;
  460. {rounding if required}
  461. if mode = rounded then
  462.     begin
  463.     {doubling the remainder}
  464.     carry := 0;
  465.     for i := n downto 1 do delta[i] := byt1mul(carry, delta[i], 2);
  466.     delta[0] := carry;
  467.     {comparing the divisor with twice the remainder}
  468.     i := 0;
  469.     v.f[0] := 0;
  470.     while (v.f[i] = delta[i]) and (i < n) do i := (i+1);
  471.     if (v.f[i]<delta[i]) or ((v.f[i]=delta[i]) and odd(gamma[n]+1))
  472.     then
  473.         begin
  474.         increm(carry, gamma);
  475.         if carry = 1 then exponent := exponent + 1
  476.         end;
  477.     end;
  478. divde.f := gamma;
  479. if (exponent >= 0) and (exponent <= 255) then divde.e := exponent
  480.         else
  481.     begin
  482.     if exponent < 0 then
  483.         begin
  484.         writeln('QUOTIENT EXPONENT UNDERFLOW !');
  485.         divde.s := plus;
  486.         for i := 0 to n do divde.f[i] := 0;
  487.         divde.e := 0
  488.         end
  489.     else
  490.         begin
  491.         writeln('QUOTIENT EXPONENT OVERFLOW !');
  492.         divde.f[0] := 0;
  493.         for i := 1 to n do divde.f[i] := 255;
  494.         divde.e := 255
  495.         end;
  496.     end;
  497. 999 :
  498. end;
  499.  
  500. function modu(u, v : newreal) : newreal;
  501. label 9999;
  502. var
  503.     zero, aux, w        : newreal;
  504.     i, j, k, exponent, limit: integer;
  505.     alfa            : double_fraction;
  506.     gamma, delta        : fraction;
  507. begin
  508. with zero do begin s := plus; for i := 0 to n do f[i] := 0; e := 0 end;
  509. if (v.f[1] = 0) or (v.s = minus) then
  510.     begin
  511.     writeln('ATTEMPTED COMPUTING REMAINDER FOR ZERO OR NEG DIVISOR');
  512.     writeln('       VALUE OF MODULO SET TO ZERO');
  513.     modu := zero
  514.     end
  515.   else
  516.   begin
  517.   if (u.f[1] = 0) or (iseqlower(absol(u), v)) then modu := zero
  518.     else
  519.     begin
  520.     aux := u;
  521.     exponent := v.e;
  522.     {start the division and then, for (u.e - v.e) div n times,
  523.      continue dividing after replacement of the dividend by the
  524.      remainder of the previous division}
  525.     limit := (u.e - v.e) div n;
  526.     for k := 0 to limit do
  527.     begin
  528.     for i := 1 to n do alfa[i] := aux.f[i];
  529.     for i := (n+1) to twicen do alfa[i] := 0;
  530.     delta[0] := 0; {value not set within divd}
  531.     dvd(alfa, v.f, gamma, delta);
  532.     {remove leading zeros}
  533.     i := 1;
  534.     while (delta[1] = 0) and (i <> n) do
  535.         begin
  536.         for j := 0 to (n-1) do delta[j] := delta[j+1];
  537.         delta[n] := 0;
  538.         exponent := exponent - 1;
  539.         i := i + 1
  540.         end;
  541.     if delta[1] = 0 then {the result is zero}
  542.         begin
  543.         modu := zero;
  544.         goto 9999
  545.         end;
  546.     aux.f := delta;
  547.     if exponent >= 0 then aux.e := exponent 
  548.         else 
  549.         begin
  550.         writeln('MODULO EXPONENT UNDERFLOW !');
  551.         modu := zero;
  552.         goto 9999
  553.         end;
  554.     end;
  555.     limit := (u.e - v.e) mod n;
  556.     aux.e := aux.e + limit;
  557.     {as long as the remainder exceeds the divisor keep subtracting
  558.      the divisor from it}
  559.     aux := absol(aux); {to speed up the steps which follow}
  560.     w := v;
  561.     w.e := w.e + limit - 1;
  562.     repeat
  563.     while isgreater(aux, w) do aux := sub(aux, w);
  564.     if w.e > 0 then w.e := w.e - 1;
  565.     limit := limit - 1;
  566.     until limit = - 1;
  567.     aux.s := u.s;      {to set the correct sign again}
  568.     modu := aux
  569.     end
  570.   end;
  571. 9999:
  572. end;
  573.  
  574.  
  575. function putnreal(inp : extdatum) : newreal;
  576. {called by do_read}
  577. var
  578.     carry    : digits;
  579.     i, j, k    : integer;
  580.     t    : integer;
  581.     u    : array[1..3] of digits;
  582.     v    : array[1..nn] of digits;
  583.     w    : array[1..(nn+3)] of digits;
  584.     ten, one, pointone, aaa, auxiliary        : newreal;
  585.  
  586. begin
  587. for j := 1 to nn  do v[j] := inp.f[j];
  588. u[1] := 2; u[2] := 5; u[3] := 6;
  589. aaa.s := inp.s;
  590. aaa.f[0] := 0;
  591. for i := 1 to n do
  592.     begin
  593.     {multiplication}
  594.     for j := 1 to (nn+3) do w[j] := 0;
  595.     for j := nn downto 1 do
  596.         begin
  597.         carry := 0;
  598.         for k := 3 downto 1 do
  599.             begin
  600.             t := u[k]*v[j] + w[k+j] + carry;
  601.             w[k+j] := t mod 10;
  602.             carry := t div 10
  603.             end;
  604.         w[j] := carry
  605.         end;
  606.     {getting the byte}
  607.     aaa.f[i] := w[1]*100 + w[2]*10 + w[3];
  608.     {left shift}
  609.     for j := 1 to 3 do
  610.         begin
  611.         for k := 1 to (nn+2) do w[k] := w[k+1];
  612.         w[nn] := 0
  613.         end;
  614.     {re-assignment}
  615.     for j := 1 to nn do v[j] := w[j]
  616.     end;
  617. aaa.e := 128;
  618. {finalizing the transformation}
  619. if inp.e = 0 then
  620. {apart from normalisation putnreal can be set equal to aaa}
  621.    begin
  622.    {remove leading zeros}
  623.    {this would not be necessary if the calling procedure is do_read}
  624.    j := 1;
  625.    while (aaa.f[1] = 0) and (j <> n) do
  626.     begin
  627.     for i := 1 to (n - 1) do aaa.f[i] := aaa.f[i + 1];
  628.     aaa.f[n] := 0;
  629.     aaa.e := aaa.e - 1;
  630.     j := j + 1
  631.     end;
  632.    {the result is zero}
  633.    if aaa.f[1] = 0 then
  634.     begin
  635.     aaa.s := plus;
  636.     aaa.e := 0
  637.     end;
  638.    putnreal := aaa
  639.    end
  640.     else
  641.         begin
  642.         with one do
  643.             begin
  644.             s := plus; f[0] := 0; f[1] := 1;
  645.             for i := 2 to n do f[i] := 0;
  646.             e := 129 end;
  647.         auxiliary := one;
  648.         if inp.e > 0 then
  649.             begin
  650.             with ten do
  651.                 begin
  652.                 s := plus; f[0] := 0; f[1] := 10;
  653.                 for i := 2 to n do f[i] := 0;
  654.                 e := 129 end;
  655.             for i := 1 to inp.e do
  656.             auxiliary := multp(auxiliary, ten)
  657.             end
  658.            else {exponent < 0}
  659.             begin
  660.             with pointone do 
  661.                 begin
  662.                 s := plus; f[0] := 0; f[1] := 25;
  663.                 for i := 2 to n do f[i] := 153;
  664.                 if mode = rounded then f[n] := 154;
  665.                 e := 128 end;
  666.             for i := inp.e to -1 do
  667.             auxiliary := multp(auxiliary, pointone);
  668.             end;
  669.         putnreal := multp(aaa, auxiliary)
  670.         end;
  671. end;
  672.  
  673.  
  674. procedure do_read(var u : extdatum; var v : newreal);
  675. const
  676.     z        = 48;    {ord('0')}
  677. var
  678.     ch        : char;
  679.     exposign    : signtype;
  680.     i, j        : integer;
  681.     temp, exponent    : integer;
  682. begin
  683. read(ch);
  684. {skipping leading blanks}
  685. while ch = ' ' do read(ch);
  686. if ch = '-' then
  687.     begin
  688.     u.s := minus;
  689.     read(ch)
  690.     end
  691.   else
  692.     begin
  693.     u.s := plus;
  694.     if ch = '+' then read(ch)
  695.     end;
  696. while not (ch in ['0'..'9']) do
  697.   begin
  698.   writeln('INPUT STRING NOT FOUND : PLEASE TRY AGAIN.');
  699.   read(ch)
  700.   end;
  701. {getting the fraction}
  702. exponent := 0;
  703. u.f[0] := 0;
  704. i := 1;
  705. {skipping leading zeros}
  706. while ch = '0' do read(ch);
  707. while (ch in ['0'..'9']) and (i <= prec) do
  708.     begin
  709.     u.f[i] := ord(ch) - z;
  710.     exponent := exponent + 1;
  711.     i := i + 1;
  712.     read(ch)
  713.     end;
  714. if ch = '.' then
  715.     begin
  716.     read(ch);
  717.     {skipping further non significant digits}
  718.     if exponent = 0 then
  719.         begin
  720.         while ch = '0' do
  721.             begin
  722.             read(ch);
  723.             exponent := exponent - 1
  724.             end
  725.         end;
  726.     while (ch in ['0'..'9']) and (i <= prec) do
  727.         begin
  728.         u.f[i] := ord(ch) - z;
  729.         i := i + 1;
  730.         read(ch)
  731.         end
  732.     end;
  733. for j := i to nn do u.f[j] := 0;
  734. if (ch in ['0'..'9']) then writeln(
  735.   'INPUT STRING TOO LONG : DIGITS BEYOND THE ',prec:1,'TH DIGIT ARE IGNORED');
  736. writeln('
  737.   INPUT STRING CONSISTS OF A ',u.s:1,' SIGN AND ',(i-1):1,' DIGIT(S).');
  738. {skipping further digits}
  739. while (ch in ['0'..'9']) do read(ch);
  740. if (ch = 'E') or (ch = 'e') then
  741.     begin
  742.     read(ch);
  743.     temp := 0;
  744.     if ch = '-' then
  745.         begin
  746.         exposign := minus;
  747.         read(ch)
  748.         end
  749.       else
  750.         begin
  751.         exposign := plus;
  752.         if ch = '+' then read(ch)
  753.         end;
  754.     while not (ch in ['0'..'9']) do
  755.         begin
  756.         writeln('EXPONENT NOT FOUND : PLEASE TRY AGAIN.');
  757.         read(ch)
  758.         end;
  759.     temp := ord(ch) - z;
  760.     i := 1;
  761.     read(ch);
  762.     while (ch in ['0'..'9']) and (i < 3) do
  763.         begin
  764.         temp := 10*temp + ord(ch) - z;
  765.         i := i + 1;
  766.         read(ch)
  767.         end;
  768.     if (ch in ['0'..'9']) then 
  769.     writeln('
  770.     EXPONENT STRING TOO LONG : DIGITS BEYOND THE 3RD ARE IGNORED.');
  771.     writeln('
  772.     EXPONENT CONSISTS OF A ',exposign:1,' SIGN AND ', i:1, ' DIGIT(S).');
  773.     {skipping further digits}
  774.     while (ch in ['0'..'9']) do read(ch);
  775.     if exposign = minus then exponent := exponent - temp
  776.     else exponent := exponent + temp
  777.     end;
  778. u.e := exponent;
  779. v := putnreal(u)
  780. end;
  781.  
  782.  
  783. procedure inc(i : integer; var u : long_fraction);
  784. {called by auxmult}
  785. begin
  786. if u[i] <> 9 then u[i] := u[i] + 1
  787.     else
  788.     begin
  789.     u[i] := 0;
  790.     inc(i-1, u)
  791.     end;
  792. end;
  793.  
  794.  
  795. function auxmult(u, v : extdatum) : extdatum;
  796. {called by getnreal}
  797. var
  798.     aux        : long_fraction;
  799.     k        : digits;
  800.     t        : 0..maxint;
  801.     i, j, exponent    : integer;
  802. begin
  803. if u.s = v.s then auxmult.s := plus else auxmult.s := minus;
  804. exponent := u.e + v.e;
  805. for j := 1 to twicenn do aux[j] := 0;
  806. for j := nn downto 1 do
  807.     begin
  808.     k := 0;
  809.     for i := nn downto 1 do
  810.         begin
  811.         t := u.f[i]*v.f[j] + aux[i+j] + k;
  812.         aux[i+j] := t mod 10;
  813.         k := t div 10
  814.         end;
  815.     aux[j] := k;
  816.     end;
  817. {remove leading zeros}
  818. j := 1;
  819. while (aux[1] = 0) and (j <> twicenn) do
  820.     begin
  821.     for i := 0 to (twicenn - 1) do aux[i] := aux[i+1];
  822.     aux[twicenn] := 0;
  823.     exponent := exponent - 1;
  824.     j := j + 1
  825.     end;
  826. {rounding if required}
  827. if (mode = rounded) and (aux[nn+1] > 5) then
  828.     begin
  829.     inc(nn, aux);
  830.     if aux[0] <> 0 then
  831.         begin
  832.         for j := (twicenn - 1) downto 0 do aux[j+1] := aux[j];
  833.         aux[0] := 0;
  834.         exponent := exponent + 1
  835.         end;
  836.     end;
  837. auxmult.f[0] :=0;
  838. for i := 1 to nn do auxmult.f[i] := aux[i];
  839. auxmult.e := exponent;
  840. end;
  841.  
  842.  
  843. function getnreal(inp : newreal) : extdatum;
  844. {WARNING : the following listing is only valid for n <= 6}
  845. {called by do_write}
  846. var
  847.     carry    : digits;
  848.     i, j, k    : integer;
  849.     t, shift, exponent    : integer;
  850.     u     : array[1..3] of digits;
  851.     v, aa, bb, cc, dd, ee, ff    : array[1..nn] of digits;
  852.     w, aaa, bbb    : array[0..(nn+3)] of digits;
  853.     ccc, auxiliary, twohun56, one, oneover256 : extdatum;
  854. begin
  855. {(1/256)*10^2}
  856.     aa[1]:=3;    aa[2]:=9;    aa[3]:=0;    aa[4]:=6;
  857.     aa[5]:=2;    aa[6]:=5;
  858.     for i := 7 to nn do aa[i] := 0;
  859. {(1/256^2)*10^4}
  860.     bb[1]:=1;    bb[2]:=5;    bb[3]:=2;    bb[4]:=5;
  861.     bb[5]:=8;    bb[6]:=7;    bb[7]:=8;    bb[8]:=9;
  862.     bb[9]:=0;    bb[10]:=6;    bb[11]:=2;    bb[12]:=5;
  863.     for i := 13 to nn do bb[i] := 0;
  864. {(1/256^3)*10^7}
  865.     cc[1]:=5;    cc[2]:=9;    cc[3]:=6;    cc[4]:=0;
  866.     cc[5]:=4;    cc[6]:=6;    cc[7]:=4;    cc[8]:=4;
  867.     cc[9]:=7;    cc[10]:=7;    cc[11]:=5;    cc[12]:=3;
  868.     cc[13]:=9;    
  869.     if mode=rounded then cc[14]:=1 else cc[14]:=0;
  870. {(1/256^4)*10^9}
  871.     dd[1]:=2;    dd[2]:=3;    dd[3]:=2;    dd[4]:=8;
  872.     dd[5]:=3;    dd[6]:=0;    dd[7]:=6;    dd[8]:=4;
  873.     dd[9]:=3;    dd[10]:=6;    dd[11]:=5;    dd[12]:=3;
  874.     dd[13]:=8;
  875.     if mode=rounded then dd[14]:=7 else dd[14]:=6;
  876. {(1/256^5)*10^12}
  877.     ee[1]:=9;    ee[2]:=0;    ee[3]:=9;    ee[4]:=4;
  878.     ee[5]:=9;    ee[6]:=4;    ee[7]:=7;    ee[8]:=0;
  879.     ee[9]:=1;    ee[10]:=7;    ee[11]:=7;    ee[12]:=2;
  880.     ee[13]:=9;
  881.     if mode=rounded then ee[14]:=3 else ee[14]:=2;
  882. {(1/245^6)*10^14}
  883.     ff[1]:=3;    ff[2]:=5;    ff[3]:=5;    ff[4]:=2;
  884.     ff[5]:=7;    ff[6]:=1;    ff[7]:=3;    ff[8]:=6;
  885.     ff[9]:=7;    ff[10]:=8;    ff[11]:=8;    ff[12]:=0;
  886.     ff[13]:=0;    ff[14]:=5;
  887. for i := 0 to (nn+3) do bbb[i] := 0;
  888. aaa[0] := 0;
  889. for i := 1 to n do
  890.     begin
  891.     u[1] := inp.f[i] div 100;
  892.     u[2] := (inp.f[i] mod 100) div 10;
  893.     u[3] := (inp.f[i] mod 100) mod 10;
  894.     case i of
  895.         1 : begin v := aa; shift := 0 end;
  896.         2 : begin v := bb; shift := 2 end;
  897.         3 : begin v := cc; shift := 5 end;
  898.         4 : begin v := dd; shift := 7 end;
  899.         5 : begin v := ee; shift := 10 end;
  900.         6 : begin v := ff; shift := 12 end;
  901.     end; {case}
  902.     {multiplication}
  903.     for j := 1 to (nn+3) do w[j] := 0;
  904.     for j := nn downto 1 do
  905.         begin
  906.         carry := 0;
  907.         for k := 3 downto 1 do
  908.             begin
  909.             t := u[k]*v[j]+w[k+j]+carry;
  910.             w[k+j] := t mod 10;
  911.             carry := t div 10
  912.             end;
  913.         w[j] := carry
  914.         end;
  915.     {shift to the right}
  916.     for j := 1 to shift do
  917.         begin
  918.         for k := nn+2 downto 1 do w[k+1] := w[k];
  919.         w[1] := 0
  920.         end;
  921.     {addition}
  922.     carry := 0;
  923.     for j := nn+3 downto 1 do 
  924.         begin
  925.         aaa[j] := (bbb[j] + w[j] + carry) mod 10;
  926.         carry := (bbb[j] + w[j] + carry) div 10
  927.         end;
  928.     aaa[0] := carry + aaa[0];  {WARNING : valid only for n <= 9}
  929.     bbb := aaa
  930.     end;
  931. exponent := 1;
  932. {conditional shift to the right}
  933. if aaa[0] <> 0 then
  934.     begin
  935.     for k := nn+2 downto 0 do aaa[k+1] := aaa[k];
  936.     aaa[0] := 0;
  937.     exponent := exponent + 1
  938.     end
  939.    else
  940.     begin
  941.     {remove leading zeros}
  942.     j := 1;
  943.     while (aaa[1] = 0) and (j <> nn+3) do
  944.         begin
  945.         for i := 1 to nn+2 do aaa[i] := aaa[i+1];
  946.         aaa[nn+3] := 0;
  947.         exponent := exponent - 1;
  948.         j := j + 1
  949.         end;
  950.     end;
  951. ccc.s := inp.s;
  952. for i := 0 to nn do ccc.f[i] := aaa[i];
  953. ccc.e := exponent;
  954. {the result is zero}
  955. if ccc.f[1] = 0 then
  956.     begin
  957.     ccc.s := plus;
  958.     ccc.e := 1    {to display an exponent of zero equal to 0}
  959.     end;
  960. if (inp.e = 128) or (ccc.f[1] = 0) then getnreal := ccc
  961.     else
  962.         begin
  963.         one.s := plus;
  964.         one.f[0] := 0;
  965.         one.f[1] := 1;
  966.         for i := 2 to nn do one.f[i] := 0;
  967.         one.e := 1;
  968.         auxiliary := one;
  969.         if inp.e > 128 then 
  970.             begin
  971.             twohun56.s := plus;
  972.             twohun56.f[0] := 0;
  973.             twohun56.f[1] := 2;
  974.             twohun56.f[2] := 5;
  975.             twohun56.f[3] := 6;
  976.             for i := 4 to nn do twohun56.f[i] := 0;
  977.             twohun56.e := 3;
  978.             for i := 129 to inp.e do
  979.                auxiliary := auxmult(auxiliary, twohun56)
  980.             end
  981.            else  {exponent < 128}
  982.             begin
  983.             with oneover256 do
  984.                 begin s := plus; f[0] := 0; f[1] := 3;
  985.                 f[2] := 9; f[3] := 0; f[4] := 6; f[5] := 2;
  986.                 f[6] := 5;
  987.                 for j := 7 to nn do f[j] := 0;
  988.                 e := -2 end;
  989.             for i := inp.e to 127 do
  990.                 auxiliary := auxmult(auxiliary, oneover256);
  991.             end;
  992.         getnreal := auxmult(ccc, auxiliary)
  993.         end;
  994. end;
  995.  
  996. procedure do_write(u : newreal);
  997. var
  998.     aux : extdatum;
  999.     i   : integer;
  1000. begin
  1001. aux := getnreal(u);
  1002. if aux.s = plus then write('+') else write('-');
  1003. write(aux.f[1]:1, '.');
  1004. for i := 2 to prec do write(aux.f[i]:1);
  1005. write('E');
  1006. if (aux.e - 1) < 0 then write('-') else write('+');
  1007. if abs(aux.e - 1) < 10 then write('0');
  1008. write(abs(aux.e - 1):1)
  1009. end;
  1010.  
  1011. {$F+,R+ }
  1012. . {end of the module basicops}
  1013.