home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / math / verylarg / vlncls.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-10-22  |  27.6 KB  |  1,102 lines

  1. unit vlncls;     { a class of Very Large Number }
  2.  
  3. {))))))))))))))))))))))))))))))))))))))}
  4. {}          interface                 {}
  5. {))))))))))))))))))))))))))))))))))))))}
  6.  
  7.  
  8. uses  Dos, CRT;
  9.  
  10. const
  11.    vlSize = 1000;     {essentially no limit }
  12. { the real working limit is wksize set in Unit Initialization }
  13.    vlmemsize = vlsize*4+4;
  14. type
  15.    pWordArray = ^tWordArray;
  16.    tWordArray = array[1..vlSize] of word;
  17.  
  18. type pchar4 = array[0..4]of char;
  19.  
  20. type
  21.   pVryLrgNo = ^tVryLrgNo;
  22.   tVryLrgNo = object
  23.     count : integer;
  24.     max : integer;
  25.     sign : integer;
  26.     tVLN : tWordArray;
  27.     constructor Init( cnt, maxC, sgn : integer; pnew :pWordArray);
  28. {    procedure store( var S : tStream);
  29.     constructor load( var S : tStream);
  30.  }
  31.     procedure SetVal( cnt, sgn : integer; pnew :pWordArray);
  32.     procedure SetSmall(n:integer); { set immediate to 16 bits, signed }
  33.     procedure Clear( n : integer);
  34.  
  35.     procedure WriteHex;
  36.     procedure WriteDecimal ( mode : integer);
  37.  
  38.     procedure AddBy(other : pVryLrgNo);
  39.     procedure AddN(n:integer);
  40.     procedure SubBy(other : pVryLrgNo);
  41.     procedure SubN(n:integer);
  42.     procedure TwosComplAbs( cnt : integer );
  43.     procedure Copy( other : pVryLrgNo );   { copy other into self }
  44.     procedure Recount;
  45.     procedure MulBy(other : pVryLrgNo);
  46.     procedure MulN(n:integer);
  47.     procedure DivN(n:integer);
  48.     function  FindnoBinDig : integer;        { how many binary digits }
  49.     procedure BigSHL(cnt  : integer);         {shift left by words }
  50.     procedure MultiSHL(sf_cnt : integer);         {shift left by words }
  51.     procedure Shr1Bit;         {shift right one bit}
  52.     procedure ShL1Bit;         {shift left one bit}
  53.     function  FindDivShift(other : pVryLrgNo) : integer;
  54.                                    {shift in prep for dividing}
  55.     procedure DivBy( dvsr, remnd : pVryLrgNo);
  56.     procedure GetRandom(binCnt  : integer);
  57.     procedure TwoNth(n:integer );
  58.     procedure TenNth(n:integer );
  59.     procedure NthRoot(n:integer );
  60.     procedure NthPower(n:integer );
  61.                                 { a random number with n bits }
  62.     end;
  63.  
  64.  
  65. {const
  66.   rVryLrgNo: TStreamRec = (
  67.     ObjType: 193;
  68.     VmtLink: Ofs(TypeOf(tVryLrgNo)^);
  69.     Load: @tVryLrgNo.Load;
  70.     Store: @tVryLrgNo.Store);
  71. }
  72.  
  73.   function MaxOfW(a,b : word) : word;
  74.   function IsGrEqAbs(n1, n2  : pVryLrgNo): boolean;  { true if n1>= n2 }
  75.   function IsEqAbs(n1, n2  : pVryLrgNo): boolean;
  76.       { true if n1= n2 }
  77.   procedure HexWord( w : word; var pS : pchar4);
  78.   procedure SetWkSize(n:integer);
  79.   function  GetWkSize : integer;
  80.   procedure CloseTempRegs;
  81.   procedure OpenTempRegs;
  82.   procedure CallError(s:String);
  83.  
  84.   var
  85.       dec_10e9 ,       { divisor for Decimal printout}
  86.       decPointShift    {offset for fraction printout }
  87.                    : pVryLrgNo;
  88.  
  89. {))))))))))))))))))))))))))))))))))))))}
  90. {}           implementation           {}
  91. {))))))))))))))))))))))))))))))))))))))}
  92.  
  93.   var
  94.    VLNtemp1,     { used in NthRoot,DivN, NthPower }
  95.    VLNtemp2,     { used in NthRoot, writeFraction [divby]}
  96.    VLNtemp3,     { used in NthRoot, writeFraction [divby]}
  97.    VLNoprnd ,    { used in MulN, DivN, AddN, SubN, NthRoot}
  98.    quotn,        { used in Divby }
  99.    tmpDvsr,      { used in DivBy}
  100.    remd,         { used in DivBy}
  101.    accumReg,     { used in MulBy }
  102.    carryReg      { used in MulBy }
  103.             : pVryLrgNo;
  104.  
  105.    wksize : integer;
  106.  
  107.       { storage for temporary variable }
  108.  
  109. {)))))))))))))))))))))}
  110. {}  function MaxOfW  {} (a,b : word) : word;
  111. {)))))))))))))))))))))}
  112.   begin
  113.     if a>b then MaxOfW := a else MaxOfW  := b;
  114.   end;
  115.  
  116.  
  117.  
  118. {))))))))))))))))))))))))))))))))))))}
  119. {}  procedure tVryLrgNo.GetRandom   {} (binCnt  : integer);
  120. {))))))))))))))))))))))))))))))))))))}
  121. var
  122.    bitsRemain, i     : integer;
  123. begin
  124.    bitsRemain := binCnt mod 16 ;   {0 to 15}
  125.    Count :=  (binCnt) div 16 ;   {16 bits per word }
  126.    if max<count then
  127.       begin
  128.        callError('Random too big error');
  129.        exit;
  130.       end;
  131.    sign := 1; {positive}
  132.    for i := Count+1 downto 1 do
  133.       tVLN[i] := random(32768) shl 1 + random(2);
  134.  
  135.    if bitsRemain>0 then      { value is 0 to 15}
  136.      begin
  137.        inc(Count);
  138.        for i := 15 downto bitsRemain do   {reduce MS Byte}
  139.           tVLN[Count] := tVLN[Count] shr 1;
  140.      end;
  141.    if tVLN[Count]=0 then dec(count);
  142. end;
  143.  
  144.  
  145. {)))))))))))))))))))))))))))))))))))))}
  146. {}   procedure tVryLrgNo.Recount;    {}
  147. {)))))))))))))))))))))))))))))))))))))}
  148. {test if fewer words are needed }
  149. var i : integer;
  150. begin
  151.    i := count;
  152.    while i > 0 do begin
  153.       if tVLN[i] = 0 then
  154.           dec(count)
  155.       else break;
  156.       dec(i);
  157.       end;
  158. end;
  159.  
  160. {))))))))))))))))))))))))))))))))}
  161. {}  procedure tVryLrgNo.BigSHL  {}(cnt  : integer);
  162. {))))))))))))))))))))))))))))))))}
  163.   var i: integer;
  164.   begin
  165.   if cnt+count>max then
  166.     begin
  167.     writeln('Shift Left too far, beyond max word size.');
  168.     exit;
  169.     end;
  170.   for i := count  downto 1 do
  171.      tVLN[i+cnt]:= tVLN[i];
  172.   for i := 1 to cnt do
  173.      tVLN[i] := 0;
  174.   count := count + cnt;
  175.   end;
  176.  
  177. {))))))))))))))))))))))))))))))))))}
  178. {}  procedure tVryLrgNo.MultiSHL  {}(sf_cnt : integer);
  179. {))))))))))))))))))))))))))))))))))} {shift data left n bits}
  180.   var
  181.     i, BigCnt  : integer;
  182.     new,
  183.     wLeft, wRight : word;
  184.   begin
  185.    if (count = 0) or (sf_cnt=0) then exit;
  186.    BigCnt := sf_cnt shr 4;
  187.    sf_cnt := sf_cnt and $F;
  188.    new := 0;
  189.  
  190.    for i := count downto 1 do
  191.      begin
  192.       wLeft  := (tVLN[i] shl sf_cnt) ;
  193.       wRight :=  tVLN[i] shr (16-sf_cnt);
  194.       tVLN[i+1] := new or wRight;   { combine them  }
  195.       new := wLeft;
  196.      end;
  197.    inc(count); Recount;
  198.  
  199.    if max<count then
  200.       begin
  201.        callError('shl too big error');
  202.        exit;
  203.       end;
  204.  
  205.     tVLN[1]:= new;    {lowest term }
  206.  
  207.    if BigCnt>0 then
  208.      BigShl(BigCnt);
  209.  
  210.    end;
  211. {)))))))))))))))))))))))))))))))))))))}
  212. {}   procedure  tVryLrgNo.Shr1Bit;   {}
  213. {)))))))))))))))))))))))))))))))))))))}
  214.  var i : integer;
  215.  begin
  216.  if count=0 then exit;  {not an error }
  217.    for i := 1 to count-1 do
  218.      begin
  219.       tVLN[i] := tVLN[i] shr 1;
  220.       if odd(tVLN[i+1]) then inc(tVLN[i],$8000);
  221.      end;
  222.    tVLN[count] := tVLN[count] shr 1;
  223.  end;
  224.  
  225. {)))))))))))))))))))))))))))))))))))))}
  226. {}   procedure  tVryLrgNo.ShL1Bit;   {}
  227. {)))))))))))))))))))))))))))))))))))))}
  228.  var i : integer;
  229.      tmp : boolean;
  230.  begin
  231.    tmp := (tVLN[count] and $8000 <> 0);
  232.  
  233.    for i :=  count downto 1 do
  234.      begin
  235.       if (tVLN[i] and $8000 <> 0) then
  236.          inc(tVLN[i+1]);
  237.       tVLN[i] := tVLN[i] shl 1;
  238.      end;
  239.        if tmp then
  240.         begin
  241.          inc(count);
  242.          tVLN[count]:= 1;
  243.         end;
  244.    if max<count then
  245.       begin
  246.        callError('shl too big error');
  247.        exit;
  248.       end;
  249.  end;
  250.  
  251. {)))))))))))))))))))))))))))))))))))))}
  252. {}  function tVryLrgNo.FindDivShift  {} (other : pVryLrgNo) : integer;
  253. {)))))))))))))))))))))))))))))))))))))}
  254.   var
  255.     n : integer;
  256.     wo, ws : longint;
  257.   begin
  258.    {compare MS Word of each }
  259.    {Shl til bigger then shr til smaller}
  260.    wo := other^.tVLN[other^.count];
  261.    ws := tVLN[count];
  262.    n := 0;
  263.  
  264.    while (wo>ws) do  { avoid overflow }
  265.      begin
  266.       ws := ws shl 1;
  267.       inc(n);
  268.      end;
  269.  
  270.    while wo<=ws do        {make ws slightly smaller }
  271.      begin
  272.       ws := ws shr 1;
  273.       dec(n);
  274.      end;
  275.    FindDivShift := n+1;
  276.  end;
  277.  
  278.  
  279. {))))))))))))))))))))))))))))))))))))}
  280. {}  function tVryLrgNo.FindnoBinDig {}   : integer;
  281. {))))))))))))))))))))))))))))))))))))}
  282.                              { how many binary digits }
  283. var
  284.   tmpc : integer;
  285.   tmpw : word;
  286. begin
  287.   Recount;  { possibly remove zero words from the top }
  288.   tmpw := tVLN[count];
  289.   tmpc := 0;
  290.   while tmpw > 0 do
  291.     begin
  292.     tmpw := tmpw shr 1;
  293.     inc(tmpc);
  294.     end;
  295.   FindnoBinDig := tmpc + (count-1) * 16;
  296. end;
  297.  
  298. {)))))))))))))))))))))))))))))))))}
  299. {}  procedure tVryLrgNo.Copy     {} ( other : pVryLrgNo );
  300. {)))))))))))))))))))))))))))))))))}
  301.  
  302.  { copy other into self       }
  303.  
  304.  var i : integer;
  305.   begin
  306.     if max<other^.count then
  307.       begin
  308.        callError('copy too big error');
  309.        exit;
  310.       end;
  311.     count := other^.count;
  312.     sign  := other^.sign;
  313.     for i := 1 to count do
  314.        tVLN[i] := other^.tVLN[i];
  315.  
  316.   end;
  317.  
  318.  {))))))))))))))))))))))))))))))))))))))}
  319.  {}  procedure tVryLrgNo.TwosComplAbs  {}( cnt : integer );
  320.  {))))))))))))))))))))))))))))))))))))))}
  321.  var
  322.     StillZero : boolean;
  323.     i : integer;
  324.  begin
  325.    StillZero := true;
  326.    for i := 1 to cnt do
  327.      if StillZero then
  328.        begin
  329.         if tVLN[i] <>  0 then begin
  330.            tVLN[i] := - tVLN[i];
  331.            StillZero := false;
  332.            end;
  333.        end
  334.        else tVLN[i] := (- tVLN[i] -1);
  335.  end;
  336.  
  337. {))))))))))))))))))))))))))))))}
  338. {} procedure tVryLrgNo.SetVal {}  ( cnt, sgn : integer;
  339. {))))))))))))))))))))))))))))))}   pnew     : pWordArray);
  340. var
  341.     i : integer;
  342. Begin
  343.    if cnt >0 then
  344.      for i := 1 to cnt do
  345.        tVLN[i] := pnew^[i] ;
  346.    count := cnt;
  347.    sign := sgn;
  348. end;
  349.  
  350. {)))))))))))))))))))))))))))))))))}
  351. {}   procedure tVryLrgNo.Clear   {}  ( n : integer);
  352. {)))))))))))))))))))))))))))))))))}
  353. var i : integer;
  354. begin
  355.    if max<n then
  356.       begin
  357.        callError('Clear too big error');
  358.        exit;
  359.       end;
  360.    count := 0;
  361.    sign := 1;
  362.    for i := 1 to n do
  363.       tvln[i] := 0;
  364.  
  365. end;
  366.  
  367. {))))))))))))))))))))))))))))))}
  368. {} constructor tVryLrgNo.Init {} ( cnt, maxC, sgn :integer;
  369. {))))))))))))))))))))))))))))))}    pnew :pWordArray);
  370.  
  371.  begin
  372.    max := maxC;
  373.    SetVal( cnt, sgn, pnew );
  374.    end;
  375.  
  376.  
  377.  
  378. {))))))))))))))))))))))))))}
  379. {}   procedure  HexWord   {} ( w : word; var pS : pchar4);
  380. {))))))))))))))))))))))))))}
  381.  
  382.  const hexlist : array[0..15] of char =
  383.     '0123456789ABCDEF';
  384.  
  385.  var
  386.    i : integer;
  387.  begin
  388.    for i := 3 downto 0 do begin
  389.      ps[i] := hexlist[w and $F];
  390.      w := w shr 4;
  391.      end;
  392.    ps[4] := #0;
  393.  end;
  394.  
  395.  
  396.  
  397. {))))))))))))))))))))))))))))))))))}
  398. {}  procedure tVryLrgNo.WriteHex; {}
  399. {))))))))))))))))))))))))))))))))))}
  400.  var i : integer;
  401.      pn : pchar4;
  402.  begin
  403.    if sign>0 then write('[+] ') else write('[-] ');
  404.    if count=0 then
  405.      write('--0--')
  406.    else
  407.      for i := count downto 1 do begin
  408.         HexWord( tVLN[i] , pn );
  409.         if i mod 12 = 0 then
  410.           Writeln(pn+' ')
  411.         else
  412.           Write(pn+' ');
  413.         end;
  414.  end;
  415.  
  416.  
  417.  
  418.  {))))))))))))))))))))))))))))))))))))))}
  419.  {}  procedure tVryLrgNo.WriteDecimal  {} ( mode : integer);
  420.  {))))))))))))))))))))))))))))))))))))))}
  421.  
  422.  { mode = 0 , normal = MSB first }
  423.  { mode = 1 ,          LSB first }
  424.  { mode = 2 , just top two terms }
  425.  
  426.  var
  427.     tmp : pVryLrgNo;
  428.     tempLI : longint;
  429.     saveBillions : array[1..100{vlsize}] of longint;
  430.     inx, i : integer;
  431.  begin
  432.  tmp := accumReg ; { an unused scratch register }
  433.  inx := 1;
  434.  tmp^.copy(@self);
  435.  write('VLN= ');
  436.  if tmp^.count=0 then
  437.     begin
  438.      write('  -000- ');
  439.      exit;
  440.     end;
  441.  while (tmp^.Count > 0) do
  442.     begin
  443.       tmp^.DivBy(dec_10e9, remd );     { divide by 10 exp 9 }
  444.       case remd^.count of
  445.         2: begin
  446.             tempLI := remd^.tvln[2];
  447.             tempLI := tempLI shl 16 + remd^.tvln[1];
  448.            end;
  449.         1:  tempLI := remd^.tvln[1];
  450.         0:  tempLI := 0;
  451.       end;
  452.       case mode of
  453.          0:   begin
  454.                  saveBillions[inx] := tempLI ;
  455.                  write('+');
  456.               end;
  457.          1:    begin
  458.                   write(templi,'[',inx*9-9,']  ');
  459.                   if (inx mod 4=0) then
  460.                      begin
  461.                       writeln;
  462.                       write(' --- ');
  463.                      end;
  464.                  end;
  465.          2:   begin
  466.                 write('+');
  467.                 if (tmp^.Count <3)
  468.                    then
  469.                        write(templi,'[',inx*9-9,']  ');
  470.               end;
  471.          end;
  472.       inc(inx);
  473.     end;
  474.     if mode=0 then
  475.        for i := inx-1 downto 1 do
  476.           begin
  477.             if (i mod 4=(inx-1) mod 4) then
  478.                begin
  479.                 writeln;
  480.                 write(' --- ');
  481.                end;
  482.              write(saveBillions[i],'[',i*9-9,']  ');
  483.           end;
  484.  
  485.  
  486.  end;
  487.  
  488.  
  489.  {)))))))))))))))))))))))))}
  490.  {}    function IsEqAbs   {}(n1, n2  : pVryLrgNo): boolean;
  491.  {)))))))))))))))))))))))))}
  492.   var
  493.     i , j , k : integer;
  494.     IGA : boolean;
  495.   begin
  496.     IsEqAbs := true;    {assume true}
  497.     n1^.Recount; n2^.Recount;
  498.     if n1^.count <> n2^.count then
  499.       begin
  500.         IsEqAbs := false;
  501.         exit;
  502.       end;
  503.     for i := n1^.count downto 1 do;
  504.        if n1^.tVLN[i] <> n2^.tVLN[i] then
  505.           begin
  506.             IsEqAbs := false;
  507.             exit;
  508.           end;
  509.   end;
  510.  
  511.  {)))))))))))))))))))))))))))}
  512.  {}    function IsGrEqAbs   {}(n1, n2  : pVryLrgNo): boolean;
  513.  {)))))))))))))))))))))))))))}
  514.  
  515.   { is n1 >= n2 ,ignore sign, assume both positive}
  516.   var
  517.     k : integer;
  518.     IGA : boolean;
  519.   begin
  520.     n1^.Recount; n2^.Recount;
  521.     IsGrEqAbs := not (n1^.count < n2^.count);  { first apprx. }
  522.  
  523.     if n1^.count = n2^.count  then    {almost the same }
  524.           { same number of terms}
  525.         for k := n1^.count  downto 1 do
  526.            begin
  527.             if (n1^.tVLN[k] < n2^.tVLN[k]) then
  528.                begin
  529.                 IsGrEqAbs := false;
  530.                 break;
  531.                end;
  532.             if (n1^.tVLN[k] > n2^.tVLN[k]) then
  533.                break;
  534.            end;
  535.   end;
  536.  
  537.  {)))))))))))))))))))))))))))))))}
  538.  {}   procedure AddWordArrays   {}( t1, t2 : pWordArray;
  539.  {)))))))))))))))))))))))))))))))}
  540.                  var c1, c2 : integer);  { t2 + t1 --> t2 }
  541.                  {input word arrays and counts }
  542.  var
  543.     i , carry, realcount,
  544.     msbs_pre : integer;
  545. begin
  546.    carry := 0;
  547.    realcount := MaxOfW(c1,c2);
  548.  
  549.    for i := c1 +1 to realcount do
  550.        t1^[i] := 0;  {we want to add all terms, clear higher }
  551.    for i := c2 +1 to realcount do
  552.        t2^[i] := 0;
  553.  
  554.  
  555.    if c1 > 0 then   { at least adder > 0 }
  556.          for i := 1 to realcount do begin
  557.            msbs_pre := (t1^[i] and $8000 ) shr 1
  558.                + (t2^[i] and $8000 );
  559.            t2^[i] := t2^[i] + t1^[i] + carry;
  560.  
  561.          case msbs_pre shr 1 of
  562.              $6000 : carry := 1;
  563.              0     : carry := 0;
  564.              else if (t2^[i] and $8000 = 0) then
  565.                  carry := 1
  566.                  else carry := 0;
  567.              end;
  568.          end;
  569.   c2 := realcount;
  570.   if carry<>0 then begin {after all ordinary terms added}
  571.     i := realcount +1;
  572.     t2^[i] := 1;
  573.     c2 := i;
  574.     end;
  575.  end;
  576.  
  577.  
  578.  
  579.  
  580. {(((((((((((((((((((((((((((((((}
  581. {}    procedure AddAbsolute    {}  (n2, n1  : pVryLrgNo);
  582. {(((((((((((((((((((((((((((((((}
  583.  
  584.     { n1+n2 --> n2}
  585.     {ignore sign, assume both positive}
  586.   var
  587.     i ,ovfl_det,  carry, realcount : integer;
  588.  begin
  589.    carry := 0;
  590.    realcount := MaxOfW(n1^.count,n2^.count);
  591.  
  592.    for i := n1^.count +1 to realcount do
  593.        n1^.tVLN[i] := 0;  {we want to add all terms }
  594.    for i := n2^.count +1 to realcount do
  595.        n2^.tVLN[i] := 0;
  596.  
  597.  
  598.    if n1^.count > 0 then   { at least adder > 0 }
  599.          for i := 1 to realcount do begin
  600.            ovfl_det := (n2^.tVLN[i] and $8000 ) shr 1
  601.                     + (n1^.tVLN[i] and $8000 );
  602.            n2^.tVLN[i] := n2^.tVLN[i] + n1^.tVLN[i] + carry;
  603.  
  604.            case ovfl_det shr 1 of
  605.               0     : carry := 0;
  606.               $6000 : carry := 1
  607.               else
  608.                 if (n2^.tVLN[i] and $8000 = 0) then
  609.                    carry := 1
  610.                 else carry := 0;
  611.               end
  612.          end;
  613.   n2^.count := realcount;
  614.  
  615.   if carry<>0 then begin {after all ordinary terms added}
  616.     i := realcount +1;
  617.     n2^.tVLN[i] := 1;
  618.     n2^.count := i;
  619.     end;
  620.  
  621.   if n2^.count>n2^.max then
  622.       begin
  623.        callError('Add Abs too big error');
  624.        exit;
  625.       end;
  626.  end;
  627.  
  628.  
  629. {(((((((((((((((((((((((((((((((}
  630. {}    procedure SubAbsolute    {}  (n2, n1  : pVryLrgNo);
  631. {(((((((((((((((((((((((((((((((}
  632.  
  633.     { n2-n1 --> n2}
  634.     {ignore sign, assume both positive, n2>=n1}
  635.     { assume n2 >= n1 >= 0}
  636.   var
  637.     i , borrow, realcount,
  638.      ovfl_det : integer;
  639.  begin
  640.    borrow := 0;
  641.    realcount := MaxOfW(n1^.count,n2^.count);
  642.  
  643.    for i := n1^.count +1 to realcount do
  644.        n1^.tVLN[i] := 0;  {we want to sub all terms }
  645.    for i := n2^.count +1 to realcount do
  646.        n2^.tVLN[i] := 0;
  647.  
  648.  
  649.    if n1^.count > 0 then   { if something in subt' }
  650.          for i := 1 to realcount do begin
  651.            ovfl_det := (n1^.tVLN[i] and $8000 ) shr 1
  652.                     + (n2^.tVLN[i] and $8000 );
  653.            n2^.tVLN[i] := n2^.tVLN[i] - n1^.tVLN[i] - borrow;
  654.  
  655.            case ovfl_det shr 1 of
  656.               $4000 : borrow := 0;
  657.               $2000 : borrow := 1
  658.               else
  659.                 if (n2^.tVLN[i] and $8000 = 0) then
  660.                    borrow := 0
  661.                 else borrow := 1;
  662.               end
  663.          end;
  664.  
  665.    n2^.recount;
  666.    if n2^.count>n2^.max then
  667.       begin
  668.        callError('Sub Abs too big error');
  669.        exit;
  670.       end;
  671.  
  672.  end;
  673.  
  674.  {(((((((((((((((((((((((((((((((}
  675.  {}  procedure tVryLrgNo.addBy  {}(other : pVryLrgNo);
  676.  {(((((((((((((((((((((((((((((((}
  677.  var  i : integer;
  678.  begin
  679.    if  ((sign +other^.sign) <> 0) then
  680.      { does second term reinforce first term}
  681.       AddAbsolute( @self, other)  { me := me + other }
  682.    else if IsGrEqAbs(@self, other) then begin
  683.      { does first term dominate }
  684.         SubAbsolute( @self, other);
  685.         Recount;
  686.         end
  687.    else begin
  688.      SubAbsolute( @self, other);
  689.      TwosComplAbs(other^.count);  {how many terms neeeded}
  690.      sign := - sign;
  691.      Recount;
  692.      end;
  693.  end;
  694.  
  695.  {(((((((((((((((((((((((((((((((}
  696.  {}  procedure tVryLrgNo.subBy  {} (other : pVryLrgNo);
  697.  {(((((((((((((((((((((((((((((((}
  698.  var  i : integer;
  699.  begin
  700.    if  ((sign +other^.sign) = 0) then
  701.      { does second term reinforce first term}
  702.       AddAbsolute( @self, other)  { me := me - other }
  703.    else if IsGrEqAbs(@self, other) then  begin
  704.      { does first term dominate }
  705.        SubAbsolute( @self, other);
  706.        Recount;
  707.        end
  708.    else begin
  709.      SubAbsolute( @self, other);
  710.      TwosComplAbs(other^.count);  {how many terms neeeded}
  711.      sign := - sign;
  712.      Recount;
  713.      end;
  714.  end;
  715.  
  716.  
  717. {(((((((((((((((((((((((((((((((}
  718. {}  procedure tVryLrgNo.mulBy  {}(other : pVryLrgNo);
  719. {(((((((((((((((((((((((((((((((}
  720.  var
  721.      long1, long2 : longint;
  722.      tempAccum  : longint;
  723.      i1, i2,
  724.      c0, s0 : integer;
  725.      shifter, ovfl_det : integer;
  726.      answer_sign : integer;
  727.  
  728.  begin
  729.    answer_sign := sign * other^.sign;
  730. {    sign := 1;
  731.     other^.sign := 1;
  732.  }
  733.    for i1 := 1 to wksize do
  734.      begin
  735.      accumReg^.tVLN[i1] := 0;
  736.      carryReg^.tVLN[i1] := 0;
  737.      end; { clear acumulators}
  738.  
  739.    if (count + other^.count > max )  then
  740.      begin
  741.      writeln('multiply result - too big error');
  742.      exit;
  743.      end;
  744.  
  745.    for i1 := 1 to other^.count do
  746.        {this 'other' term by each of the self terms}
  747.        for i2 := 1 to count do begin
  748.           long1 := longint(tVLN[i2]) *
  749.                    longint(other^.tVLN[i1]);
  750.  
  751.           shifter := i1+i2 ;     { pick destination position }
  752.           tempAccum := accumReg^.tVLN[shifter];
  753.  
  754.           ovfl_det := ((tempAccum and $8000 ) shr 15)
  755.                + ((long1 shr 16) and $8000 ) shr 14;
  756.           tempAccum := tempAccum shl 16 +
  757.                  accumReg^.tVLN[shifter-1] ;
  758.  
  759.           inc(tempAccum, long1);    { add in this terms}
  760.  
  761.           accumReg^.tVLN[shifter-1] :=  tempAccum and $FFFF;
  762.           accumReg^.tVLN[shifter]   :=  (tempAccum shr 16) and $FFFF;
  763.  
  764.     if (ovfl_det = 3)  or
  765.                  ( (ovfl_det<>0) and
  766.                  (tempAccum and $80000000 = 0))
  767.       then
  768.          inc(carryReg^.tVLN[shifter+1]);
  769.  
  770.    end;
  771.    count := count + other^.count;
  772.    c0 := count;
  773.    sign := answer_sign;
  774.  
  775.    AddWordArrays( @carryReg^.tVLN[1],
  776.                   @accumReg^.tVLN[1], c0, count );
  777.    SetVal( count, sign, @accumReg^.tVLN[1]);
  778.              { put answer away }
  779.    Recount;
  780.  
  781.  end;
  782.  
  783.  
  784. {(((((((((((((((((((((((((((((((}
  785. {}  procedure tVryLrgNo.divBy  {} ( dvsr,
  786. {(((((((((((((((((((((((((((((((}   remnd : pVryLrgNo);
  787.  
  788.   var i,    SAdj,
  789.       BShf, emptyBits,
  790.       sizeOfQ : integer;
  791.       dcnt : integer;
  792.       answer_sign : integer;
  793.  
  794.  begin
  795.     tmpDvsr^.copy(dvsr);
  796.     answer_sign := sign * dvsr^.sign;
  797.     sign := 1;
  798.     tmpDvsr^.sign := 1;       { work with positive values }
  799.  
  800.     dcnt := tmpDvsr^.count;
  801.     quotn^.Clear(Count);
  802.     remnd^.clear(Count);
  803.     BShf := count - dcnt;
  804.  
  805.     if (BShf<0 ) or
  806.          ((BShf=0) and
  807.                (dvsr^.tVLN[dcnt]>=tVLN[dcnt])  ) then
  808.           begin                {divisor >= dividend }
  809.             remnd^.copy(@self);
  810.             remnd^.recount;
  811.             Count := 0;
  812.             exit;
  813.             end;
  814.  
  815.     SAdj :=  tmpDvsr^.FindDivShift(@self);   {returns -15 to +15}
  816.             {number of bits to shift divisor}
  817.     if SAdj<0 then
  818.       begin
  819.       SAdj := 16 + SAdj;
  820.       dec(BShf);    { dvsr starts  smaller then dividend }
  821.       end;
  822.  
  823.     tmpDvsr^.BigShl(BShf);    {shift divisor into position}
  824.     tmpDvsr^.MultiSHL(SAdj);
  825.  
  826.     emptybits := BShf * 16 + SAdj;
  827.         {zeros at bottom of divisor}
  828.     sizeOfQ := 0;
  829.     tmpDvsr^.Recount;
  830.  
  831.     while emptybits >= 0 do
  832.       begin
  833.        quotn^.ShL1Bit;
  834.        while IsGrEqAbs(@self,tmpDvsr) do
  835.            { make sure that we have to shift}
  836.          begin  {subtract again }
  837.           subBy(tmpDvsr);
  838.           inc(quotn^.tVLN[1],1); {put a bit into the answer }
  839.          end;
  840.        quotn^.count := (sizeOfQ+16) div 16;
  841.        dec(emptybits);
  842.        if emptybits>=0 then
  843.           tmpDvsr^.Shr1Bit;
  844.        tmpDvsr^.Recount;
  845.        inc(sizeOfQ);
  846.       end;
  847.  
  848.       Recount;
  849.       remnd^.copy(@self);
  850.       quotn^.sign := answer_sign;
  851.       remnd^.sign := answer_sign;
  852.       quotn^.Recount;
  853.       copy(quotn);
  854. end;
  855.  
  856. {------------------------------------------------------}
  857. {     common  routines, higher than basic service      }
  858. {------------------------------------------------------}
  859.  
  860.  
  861. {(((((((((((((((((((((((((((((())((}
  862. {}  procedure tVryLrgNo.SetSmall  {} (n:integer );
  863. {((((((((((((((((((((((((((((((((((}
  864. begin
  865.    count := 1;
  866.    sign := 1;
  867.    if n<0 then begin
  868.      sign := -1;
  869.      n:= -n;
  870.      end;
  871.    tvln[1] := n;
  872. end;
  873.  
  874. {((((((((((((((((((((((((((((((((}
  875. {}  procedure tVryLrgNo.MulN   {} (n:integer );
  876. {((((((((((((((((((((((((((((((((}
  877.  
  878. begin
  879.     VLNoprnd^.SetSmall(n);
  880.     MulBy(VLNoprnd);
  881. end;
  882.  
  883. {((((((((((((((((((((((((((((((((}
  884. {}  procedure tVryLrgNo.AddN    {} (n:integer );
  885. {((((((((((((((((((((((((((((((((}
  886. begin
  887.     VLNoprnd^.SetSmall(n);
  888.     AddBy(VLNoprnd);
  889. end;
  890.  
  891. {((((((((((((((((((((((((((((((((}
  892. {}  procedure tVryLrgNo.SubN    {} (n:integer );
  893. {((((((((((((((((((((((((((((((((}
  894. begin
  895.     VLNoprnd^.SetSmall(n);
  896.     SubBy(VLNoprnd);
  897. end;
  898.  
  899. {((((((((((((((((((((((((((((((((}
  900. {}  procedure tVryLrgNo.DivN    {} (n:integer );
  901. {((((((((((((((((((((((((((((((((}
  902. begin
  903.     VLNoprnd^.SetSmall(n);
  904.     DivBy(VLNoprnd, VLNtemp1);
  905. end;
  906.  
  907.  
  908. {((((((((((((((((((((((((((((((((}
  909. {}  procedure tVryLrgNo.TwoNth  {} (n:integer );
  910. {((((((((((((((((((((((((((((((((}
  911. var
  912.  i : integer;
  913. begin
  914.  count := n shr 4 +1;
  915.  n := n mod 16;      {up to 15 additional bits}
  916.  if count > max then
  917.     begin
  918.      writeln('Two Big in TwoNth');
  919.      exit;
  920.     end;
  921.   for i := 1 to count-1 do
  922.      tvln[i] := 0;
  923.   tvln[count] := 1 shl n;
  924.   sign := 1;
  925. end;
  926.  
  927. {((((((((((((((((((((((((((((((((}
  928. {}  procedure tVryLrgNo.TenNth  {} (n:integer );
  929. {((((((((((((((((((((((((((((((((}
  930. var
  931.  i : integer;
  932. begin
  933.   SetSmall(10);  { + 10 }
  934.   if n<= 0 then
  935.      SetSmall(1)
  936.   else
  937.      begin
  938.         if n>1 then  NthPower(n);
  939.      end;
  940. end;
  941.  
  942. {((((((((((((((((((((((((((((((((((}
  943. {}  procedure tVryLrgNo.NthPower  {}(n:integer );
  944. {((((((((((((((((((((((((((((((((((}
  945. var
  946.  i : integer;
  947. begin
  948.  VLNtemp1^.Copy(@self);
  949.  for i := 1 to n-1 do
  950.    MulBy(VLNtemp1);
  951. end;
  952.  
  953. {(((((((((((((((((((((((((((((((((}
  954. {}  procedure tVryLrgNo.NthRoot  {} (n:integer );
  955. {(((((((((((((((((((((((((((((((((}
  956.  
  957. { Newtons algorithm }
  958. var i,j,loopCount: integer;
  959.                                 sg: integer;
  960. begin
  961.  if n<2 then
  962.     begin
  963.      writeln('Illegal Root parameter');
  964.      exit;
  965.     end;
  966.  i := FindnoBinDig;
  967.  i:= i  div n;
  968.  if i=0 then i:= 1;
  969.  
  970.  VLNtemp1^.TwoNth(i); {establish first guess}
  971. { write('Orig Guess  ');  VLNtemp1.WriteHex;  writeln;}
  972.  loopCount:= 0;
  973.  repeat
  974.      write('.');
  975.      inc(loopcount);
  976.      VLNtemp2^.Copy(VLNtemp1);   { a copy of the guess }
  977.      VLNtemp2^.NthPower(n);           { Guess^Nth power = close to orig number}
  978.      VLNtemp3^.copy(@self);           { copy of the original }
  979.      VLNtemp3^.SubBy(VLNtemp2);          {Missed by this much}
  980.      sg := VLNtemp3^.sign;
  981.  
  982.      VLNtemp2^.Copy(VLNtemp1);     {original guess again }
  983.      for j := 1 to n-2 do
  984.          VLNtemp2^.MulBy(VLNtemp1); { becomes guess^(n-1)  }
  985.      VLNtemp2^.MulN(n);             { n times guess}
  986.      VLNtemp3^.DivBy(VLNtemp2, VLNoprnd);     {delta guess}
  987.  
  988.      VLNtemp2^.Copy(VLNtemp1);     {original guess again }
  989.      VLNtemp2^.ShR1Bit;             { set 1/4 of original guess }
  990.      VLNtemp2^.ShR1Bit;
  991.      if IsGrEqAbs(VLNtemp3 ,VLNtemp2 ) then
  992.          VLNtemp3^.Copy(VLNtemp2)  ;              { limit the delta }
  993.  
  994. {     write('           Delta= '); VLNtemp3.WriteHex; writeln;}
  995.      VLNtemp1^.AddBy(VLNtemp3);
  996. {     write('Guess= '); VLNtemp1.WriteHex; writeln;}
  997.      VLNtemp2^.Copy(VLNtemp1);
  998.  
  999.  until ((VLNtemp3^.Count<=1) and
  1000.        (VLNtemp3^.tVLN[1]=0)) or (loopcount>=50) ;
  1001.  
  1002.  { writeln('loopcount  ',loopcount);}
  1003.  Copy(VLNtemp1);               { return answer   }
  1004. { writeln('error sign = ',sg);}
  1005.  if sg<0 then subN(1);    {adjust lsb according to just missed trend}
  1006. end;
  1007.  
  1008. procedure SetWkSize ( n:integer);
  1009. begin
  1010.    wksize := n;
  1011. end;
  1012.  
  1013. function GetWkSize : integer;
  1014. begin
  1015.    GetWkSize := wksize;
  1016. end;
  1017.  
  1018.  
  1019. procedure CallError(S:String);
  1020. begin
  1021.   writeln(S);
  1022.   halt;
  1023. end;
  1024.  
  1025. procedure OpenTempRegs;
  1026. var memSz : integer;
  1027. begin
  1028.    memSz := wksize*2+6;
  1029.    getmem(VLNtemp1,memsz);
  1030.    getmem(VLNtemp2,memsz);
  1031.    getmem(VLNtemp3,memsz);
  1032.    getmem(VLNoprnd,memsz);
  1033.    getmem(quotn,   memsz);
  1034.    getmem(remd,    memsz);
  1035.    getmem(tmpDvsr, memsz);
  1036.    getmem(accumReg,memsz);
  1037.    getmem(carryReg,memsz);
  1038.  
  1039.    VLNtemp1^.Init(0,wksize,1,nil);
  1040.    VLNtemp2^.Init(0,wksize,1,nil);
  1041.    VLNtemp3^.Init(0,wksize,1,nil);
  1042.    VLNoprnd^.Init(0,wksize,1,nil);
  1043.    quotn^.Init(0,wksize,1,nil);
  1044.    remd^.Init(0,wksize,1,nil);
  1045.    tmpDvsr^.Init(0,wksize,1,nil);
  1046.    accumReg^.Init(0,wksize,1,nil);
  1047.    CarryReg^.Init(0,wksize,1,nil);
  1048. end;
  1049.  
  1050. procedure CloseTempRegs;
  1051. var memsz : integer;
  1052. begin
  1053.    memSz := wksize*2+6;
  1054.    freemem(VLNtemp1,memsz);
  1055.    freemem(VLNtemp2,memsz);
  1056.    freemem(VLNtemp3,memsz);
  1057.    freemem(VLNoprnd,memsz);
  1058.    freemem(quotn,   memsz);
  1059.    freemem(remd,    memsz);
  1060.    freemem(accumReg,memsz);
  1061.    freemem(carryReg,memsz);
  1062.  
  1063.    freemem(dec_10e9, 10);
  1064.    freemem(decPointShift, 22);
  1065. end;
  1066.  
  1067.  
  1068. {            Unit initialization                        }
  1069. begin
  1070.  
  1071.    getmem(dec_10e9, 10);    { 2 * (words + sign + count + max) }
  1072.    getmem(decPointShift, 22);
  1073.  
  1074.    writeln('Unit Init Now!');
  1075.    with dec_10e9^ do
  1076.       begin
  1077.        count := 2;
  1078.        max := 2;
  1079.        sign := 1;
  1080.        tvln[1] := $CA00;        { = 1 * 10^9 }
  1081.        tvln[2] := $3B9A;
  1082.       end;
  1083.  
  1084.    with decPointShift^ do
  1085.       begin
  1086.        count := 8;
  1087.        max := 8;
  1088.        sign := 1;
  1089.     tVLN[1] := $0;
  1090.     tVLN[2] := $0;
  1091.     tVLN[3] := $9f10;  { 10 ^ 36 gives 36 decimal precision}
  1092.     tVLN[4] := $b34b;
  1093.     tVLN[5] := $715;
  1094.     tVLN[6] := $7bc9;
  1095.     tVLN[7] := $97ce;
  1096.     tVLN[8] := $c0;
  1097.       end;
  1098.  
  1099.     wksize := 100;
  1100.  
  1101. end.
  1102.