[BACK]Return to multprec_natural_numbers.adb CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / PHC / Ada / Math_Lib / Numbers

Annotation of OpenXM_contrib/PHC/Ada/Math_Lib/Numbers/multprec_natural_numbers.adb, Revision 1.1.1.1

1.1       maekawa     1: with unchecked_deallocation;
                      2:
                      3: package body Multprec_Natural_Numbers is
                      4:
                      5: -- NOTES ON THE CHOICE OF REPRESENTATION AND IMPLEMENTATION :
                      6: --   1) The base is decimal, for convenience of input/output.
                      7: --      Everything should remain correct if another base is chosen,
                      8: --      except of course the function "Decimal_Places".
                      9: --      The base is such that factor times the base is still a standard
                     10: --      natural number, so that standard arithmetic can be used.
                     11: --   2) A natural number is implemented by means of a coefficient array.
                     12: --      The advantage over a linked-list representation is that the
                     13: --      coefficients can be accessed faster.  The disadvantage of some
                     14: --      wasted storage is countered by the aim of implementing higher
                     15: --      precision floating-point numbers, where the mantissa is fixed.
                     16: --   3) The usage of a pointer to access the coefficient vector permits
                     17: --      to have uniformity in input/output, since on input it is not
                     18: --      known in advance how long a natural number may be.
                     19: --   4) A natural number n for which Empty(n) holds is considered as zero.
                     20:
                     21:   fact : constant natural := 10;
                     22:   expo : constant natural := 8;
                     23:   the_base : constant natural := fact**expo;
                     24:
                     25: -- DATATRUCTURES :
                     26:
                     27:   type Natural_Number_Rep ( size : natural ) is record
                     28:     numb : Array_of_Naturals(0..size);
                     29:   end record;
                     30:
                     31: -- AUXILIARY :
                     32:
                     33:   function Size ( n : natural ) return natural is
                     34:
                     35:   -- DESCRIPTION :
                     36:   --   Determines the size of the natural number to represent n.
                     37:
                     38:     acc : natural := the_base;
                     39:
                     40:   begin
                     41:     for i in 0..n loop
                     42:       if n < acc
                     43:        then return i;
                     44:        else acc := acc*the_base;
                     45:       end if;
                     46:     end loop;
                     47:     return n;
                     48:   end Size;
                     49:
                     50: -- CREATORS :
                     51:
                     52:   function Create ( n : natural ) return Array_of_Naturals is
                     53:
                     54:     res : Array_of_Naturals(0..Size(n));
                     55:     remainder : natural := n;
                     56:
                     57:   begin
                     58:     for i in res'range loop
                     59:       res(i) := remainder mod the_base;
                     60:       remainder := remainder/the_base;
                     61:     end loop;
                     62:     return res;
                     63:   end Create;
                     64:
                     65:   function Create ( n : natural ) return Natural_Number is
                     66:
                     67:     res : Natural_Number := Create(Create(n));
                     68:
                     69:   begin
                     70:     return res;
                     71:   end Create;
                     72:
                     73:   function Create ( n : Array_of_Naturals ) return Natural_Number is
                     74:
                     75:     res : Natural_Number;
                     76:     res_rep : Natural_Number_Rep(n'last);
                     77:
                     78:   begin
                     79:     res_rep.numb := n;
                     80:     res := new Natural_Number_Rep'(res_rep);
                     81:     return res;
                     82:   end Create;
                     83:
                     84:   function Create ( n : Natural_Number ) return natural is
                     85:
                     86:     res : natural;
                     87:
                     88:   begin
                     89:     if Empty(n)
                     90:      then res := 0;
                     91:      else res := Coefficient(n,Size(n));
                     92:           for i in reverse 0..Size(n)-1 loop
                     93:             res := res*the_base + Coefficient(n,i);
                     94:           end loop;
                     95:     end if;
                     96:     return res;
                     97:   end Create;
                     98:
                     99: -- SELECTORS :
                    100:
                    101:   function Base return natural is
                    102:   begin
                    103:     return the_base;
                    104:   end Base;
                    105:
                    106:   function Exponent return natural is
                    107:   begin
                    108:     return expo;
                    109:   end Exponent;
                    110:
                    111:   function Empty ( n : Natural_Number ) return boolean is
                    112:   begin
                    113:     return ( n = null );
                    114:   end Empty;
                    115:
                    116:   function Size ( n : Natural_Number ) return natural is
                    117:   begin
                    118:     if n = null
                    119:      then return 0;
                    120:      else return n.size;
                    121:     end if;
                    122:   end Size;
                    123:
                    124:   function Decimal_Places ( n : natural ) return natural is
                    125:
                    126:     acc : natural := 1;
                    127:
                    128:   begin
                    129:     for i in 0..n loop
                    130:       if n < acc
                    131:        then return i;
                    132:        else acc := acc*10;
                    133:       end if;
                    134:     end loop;
                    135:     return n;
                    136:   end Decimal_Places;
                    137:
                    138:   function Decimal_Places ( n : Natural_Number ) return natural is
                    139:
                    140:     res : natural := 0;
                    141:
                    142:   begin
                    143:     if not Empty(n)
                    144:      then for i in reverse 0..Size(n) loop
                    145:             if n.numb(i) /= 0
                    146:              then res := Decimal_Places(n.numb(i)) + i*expo;
                    147:                   exit;
                    148:             end if;
                    149:           end loop;
                    150:     end if;
                    151:     return res;
                    152:   end Decimal_Places;
                    153:
                    154:   function Coefficient ( n : Natural_Number; i : natural ) return natural is
                    155:   begin
                    156:     if (n = null or else i > n.size)
                    157:      then return 0;
                    158:      else return n.numb(i);
                    159:     end if;
                    160:   end Coefficient;
                    161:
                    162:   function Coefficients ( n : Natural_Number ) return Array_of_Naturals is
                    163:
                    164:     na : Array_of_Naturals(0..0) := (0..0 => 0);
                    165:
                    166:   begin
                    167:     if Empty(n)
                    168:      then return na;
                    169:      else return n.numb;
                    170:     end if;
                    171:   end Coefficients;
                    172:
                    173: -- COMPARISON AND COPYING :
                    174: --   Note that these implementations are all independent of the
                    175: --   actual representation of Natural_Number as they use the selectors.
                    176:
                    177:   function Equal ( n1,n2 : Array_of_Naturals ) return boolean is
                    178:   begin
                    179:     if n1'first /= n2'first
                    180:      then return false;
                    181:      elsif n1'last /= n2'last
                    182:          then return false;
                    183:          else for i in n1'range loop
                    184:                 if n1(i) /= n2(i)
                    185:                  then return false;
                    186:                 end if;
                    187:               end loop;
                    188:               return true;
                    189:     end if;
                    190:   end Equal;
                    191:
                    192:   function Equal ( n1 : Natural_Number; n2 : natural ) return boolean is
                    193:   begin
                    194:     if Empty(n1)
                    195:      then if n2 = 0
                    196:            then return true;
                    197:            else return false;
                    198:           end if;
                    199:      else declare
                    200:             n2cff : constant Array_of_Naturals := Create(n2);
                    201:           begin
                    202:             if n2cff'last > Size(n1)
                    203:              then return false;
                    204:              else for i in n2cff'range loop
                    205:                     if Coefficient(n1,i) /= n2cff(i)
                    206:                      then return false;
                    207:                     end if;
                    208:                   end loop;
                    209:                   for i in n2cff'last+1..Size(n1) loop
                    210:                     if Coefficient(n1,i) /= 0
                    211:                      then return false;
                    212:                     end if;
                    213:                   end loop;
                    214:             end if;
                    215:           end;
                    216:           return true;
                    217:     end if;
                    218:   end Equal;
                    219:
                    220:   function Equal ( n1,n2 : Natural_Number ) return boolean is
                    221:
                    222:     min_size : natural;
                    223:
                    224:   begin
                    225:     if Empty(n1)
                    226:      then return Equal(n2,0);
                    227:      else if Empty(n2)
                    228:            then return Equal(n1,0);
                    229:            else if Size(n1) < Size(n2)
                    230:                  then for i in Size(n1)+1..Size(n2) loop
                    231:                         if Coefficient(n2,i) /= 0
                    232:                          then return false;
                    233:                         end if;
                    234:                       end loop;
                    235:                       min_size := Size(n1);
                    236:                  elsif Size(n1) > Size(n2)
                    237:                      then for i in Size(n2)+1..Size(n1) loop
                    238:                             if Coefficient(n1,i) /= 0
                    239:                              then return false;
                    240:                             end if;
                    241:                           end loop;
                    242:                           min_size := Size(n2);
                    243:                      else min_size := Size(n1);
                    244:                 end if;
                    245:                 return Equal(Coefficients(n1)(0..min_size),
                    246:                              Coefficients(n2)(0..min_size));
                    247:           end if;
                    248:     end if;
                    249:   end Equal;
                    250:
                    251:   function "<" ( n1 : Natural_Number; n2 : natural ) return boolean is
                    252:   begin
                    253:     if Empty(n1)
                    254:      then if n2 > 0
                    255:            then return true;
                    256:            else return false;
                    257:           end if;
                    258:      else declare
                    259:             n2cff : constant Array_of_Naturals := Create(n2);
                    260:           begin
                    261:             if n2cff'last > Size(n1)
                    262:              then return true;
                    263:              else if n2cff'last < Size(n1)
                    264:                    then for i in reverse n2cff'last+1..Size(n1) loop
                    265:                           if Coefficient(n1,i) /= 0
                    266:                            then return false;
                    267:                           end if;
                    268:                         end loop;
                    269:                   end if;
                    270:                   for i in reverse n2cff'range loop
                    271:                     if Coefficient(n1,i) >= n2cff(i)
                    272:                      then return false;
                    273:                     end if;
                    274:                   end loop;
                    275:             end if;
                    276:           end;
                    277:           return true;
                    278:     end if;
                    279:   end "<";
                    280:
                    281:   function "<" ( n1 : natural; n2 : Natural_Number ) return boolean is
                    282:   begin
                    283:     if Empty(n2)
                    284:      then return false;
                    285:      else declare
                    286:             n1cff : constant Array_of_Naturals := Create(n1);
                    287:           begin
                    288:             if n1cff'last > Size(n2)
                    289:              then return false;
                    290:              else if n1cff'last < Size(n2)
                    291:                    then for i in reverse n1cff'last+1..Size(n2) loop
                    292:                           if Coefficient(n2,i) /= 0
                    293:                            then return true;
                    294:                           end if;
                    295:                         end loop;
                    296:                   end if;
                    297:                   for i in reverse n1cff'range loop
                    298:                     if n1cff(i) >= Coefficient(n2,i)
                    299:                      then return false;
                    300:                     end if;
                    301:                   end loop;
                    302:             end if;
                    303:           end;
                    304:           return true;
                    305:     end if;
                    306:   end "<";
                    307:
                    308:   function "<" ( n1,n2 : Natural_Number ) return boolean is
                    309:
                    310:     min_size : natural;
                    311:
                    312:   begin
                    313:     if Empty(n1)
                    314:      then if Empty(n2)
                    315:            then return false;
                    316:            else return true;
                    317:           end if;
                    318:      else if Empty(n2)
                    319:            then return false;
                    320:            else if Size(n1) < Size(n2)
                    321:                  then for i in Size(n1)+1..Size(n2) loop
                    322:                         if Coefficient(n2,i) /= 0
                    323:                          then return true;
                    324:                         end if;
                    325:                       end loop;
                    326:                       min_size := Size(n1);
                    327:                  elsif Size(n1) > Size(n2)
                    328:                      then for i in Size(n2)+1..Size(n1) loop
                    329:                             if Coefficient(n1,i) /= 0
                    330:                              then return false;
                    331:                             end if;
                    332:                           end loop;
                    333:                           min_size := Size(n2);
                    334:                      else min_size := Size(n1);
                    335:                 end if;
                    336:                 for i in reverse 0..min_size loop
                    337:                   if Coefficient(n1,i) < Coefficient(n2,i)
                    338:                    then return true;
                    339:                    elsif Coefficient(n1,i) > Coefficient(n2,i)
                    340:                        then return false;
                    341:                   end if;
                    342:                 end loop;
                    343:                 return false;      -- n1 = n2
                    344:           end if;
                    345:     end if;
                    346:   end "<";
                    347:
                    348:   function ">" ( n1 : Natural_Number; n2 : natural ) return boolean is
                    349:   begin
                    350:     if Empty(n1)
                    351:      then return false;
                    352:      else declare
                    353:             n2cff : constant Array_of_Naturals := Create(n2);
                    354:           begin
                    355:             if n2cff'last > Size(n1)
                    356:              then return false;
                    357:              else if n2cff'last < Size(n1)
                    358:                    then for i in n2cff'last+1..Size(n1) loop
                    359:                           if Coefficient(n1,i) /= 0
                    360:                            then return true;
                    361:                           end if;
                    362:                         end loop;
                    363:                   end if;
                    364:                   for i in reverse n2cff'range loop
                    365:                     if Coefficient(n1,i) <= n2cff(i)
                    366:                      then return false;
                    367:                     end if;
                    368:                   end loop;
                    369:             end if;
                    370:           end;
                    371:           return true;
                    372:     end if;
                    373:   end ">";
                    374:
                    375:   function ">" ( n1 : natural; n2 : Natural_Number ) return boolean is
                    376:   begin
                    377:     if Empty(n2)
                    378:      then if n1 > 0
                    379:            then return true;
                    380:            else return false;
                    381:           end if;
                    382:      else declare
                    383:             n1cff : constant Array_of_Naturals := Create(n1);
                    384:           begin
                    385:             if n1cff'last > Size(n2)
                    386:              then return true;
                    387:              else if n1cff'last < Size(n2)
                    388:                    then for i in n1cff'last+1..Size(n2) loop
                    389:                           if Coefficient(n2,i) /= 0
                    390:                            then return false;
                    391:                           end if;
                    392:                         end loop;
                    393:                   end if;
                    394:                   for i in reverse n1cff'range loop
                    395:                     if n1cff(i) <= Coefficient(n2,i)
                    396:                      then return false;
                    397:                     end if;
                    398:                   end loop;
                    399:             end if;
                    400:           end;
                    401:           return true;
                    402:     end if;
                    403:   end ">";
                    404:
                    405:   function ">" ( n1,n2 : Natural_Number ) return boolean is
                    406:
                    407:     min_size : natural;
                    408:
                    409:   begin
                    410:     if Empty(n2)
                    411:      then if Empty(n1)
                    412:            then return false;
                    413:            else return true;
                    414:           end if;
                    415:      else if Empty(n1)
                    416:            then return false;
                    417:            else if Size(n1) < Size(n2)
                    418:                  then for i in Size(n1)+1..Size(n2) loop
                    419:                         if Coefficient(n2,i) /= 0
                    420:                          then return false;
                    421:                         end if;
                    422:                       end loop;
                    423:                       min_size := Size(n1);
                    424:                  elsif Size(n1) > Size(n2)
                    425:                      then for i in Size(n2)+1..Size(n1) loop
                    426:                             if Coefficient(n1,i) /= 0
                    427:                              then return true;
                    428:                             end if;
                    429:                           end loop;
                    430:                           min_size := Size(n2);
                    431:                      else min_size := Size(n1);
                    432:                 end if;
                    433:                 for i in reverse 0..min_size loop
                    434:                   if Coefficient(n1,i) > Coefficient(n2,i)
                    435:                    then return true;
                    436:                    elsif Coefficient(n1,i) < Coefficient(n2,i)
                    437:                        then return false;
                    438:                   end if;
                    439:                 end loop;
                    440:                 return false;  -- n1 = n2
                    441:           end if;
                    442:     end if;
                    443:   end ">";
                    444:
                    445:   procedure Copy ( n1 : in natural; n2 : in out Natural_Number ) is
                    446:   begin
                    447:     Clear(n2);
                    448:     n2 := Create(n1);
                    449:   end Copy;
                    450:
                    451:   procedure Copy ( n1 : in Natural_Number; n2 : in out Natural_Number ) is
                    452:   begin
                    453:     Clear(n2);
                    454:     if not Empty(n1)
                    455:      then declare
                    456:             n2rep : Natural_Number_Rep(Size(n1));
                    457:           begin
                    458:             for i in n2rep.numb'range loop
                    459:               n2rep.numb(i) := n1.numb(i);
                    460:             end loop;
                    461:             n2 := new Natural_Number_Rep'(n2rep);
                    462:           end;
                    463:     end if;
                    464:   end Copy;
                    465:
                    466: -- AUXILIARIES FOR ARITHMETIC OPERATIONS :
                    467:
                    468:   function Extend ( n : Array_of_Naturals; carry : natural )
                    469:                   return Natural_Number_Rep is
                    470:
                    471:   -- DESCRIPTION :
                    472:   --   Extends the array of naturals as much as need to store the carry
                    473:   --   obtained from adding a number to a natural number.
                    474:
                    475:   begin
                    476:     if carry = 0
                    477:      then declare
                    478:             nrep : Natural_Number_Rep(n'last);
                    479:           begin
                    480:             nrep.numb := n;
                    481:             return nrep;
                    482:           end;
                    483:      else declare
                    484:             np1 : Array_of_Naturals(n'first..n'last+1);
                    485:             carry1 : natural;
                    486:           begin
                    487:             np1(n'range) := n;
                    488:             np1(np1'last) := carry mod the_base;
                    489:             carry1 := carry/the_base;
                    490:             return Extend(np1,carry1);
                    491:           end;
                    492:     end if;
                    493:   end Extend;
                    494:
                    495:   procedure Extend ( n : in out Natural_Number; carry : in natural ) is
                    496:
                    497:   -- DESCRIPTION :
                    498:   --   Extends the coefficient vector of the natural number to store
                    499:   --   the carry-over.
                    500:
                    501:   begin
                    502:     if carry /= 0
                    503:      then declare
                    504:             res : Natural_Number
                    505:                 := new Natural_Number_Rep'(Extend(n.numb,carry));
                    506:           begin
                    507:             Clear(n);
                    508:             n := res;
                    509:           end;
                    510:     end if;
                    511:   end Extend;
                    512:
                    513:   procedure Mul_Fact ( n : in out Natural_Number; f : in natural ) is
                    514:
                    515:   -- DESCRIPTION :
                    516:   --   Multiplies the number n with 0 < f <= fact and stores the result in n.
                    517:
                    518:     prod,carry : natural;
                    519:
                    520:   begin
                    521:     if not Empty(n)
                    522:      then carry := 0;
                    523:           for i in n.numb'range loop
                    524:             prod := n.numb(i)*f + carry;
                    525:             n.numb(i) := prod mod the_base;
                    526:             carry := prod/the_base;
                    527:           end loop;
                    528:           Extend(n,carry);
                    529:     end if;
                    530:   end Mul_Fact;
                    531:
                    532:   procedure Mul_Base ( n : in out Natural_Number; k : in natural ) is
                    533:
                    534:   -- DESCRIPTION :
                    535:   --   Multiplies the number n with the_base**k.
                    536:
                    537:   begin
                    538:     if k > 0 and not Empty(n)
                    539:      then declare
                    540:             npk : Natural_Number_Rep(n.size+k);
                    541:           begin
                    542:             npk.numb(0..k-1) := (0..k-1 => 0);
                    543:             npk.numb(k..npk.numb'last) := n.numb(n.numb'range);
                    544:             Clear(n);
                    545:             n := new Natural_Number_Rep'(npk);
                    546:           end;
                    547:     end if;
                    548:   end Mul_Base;
                    549:
                    550:   procedure Div_Base ( n : in out Natural_Number; k : in natural ) is
                    551:
                    552:   -- DESCRIPTION :
                    553:   --   Divides the number n by the_base**k.
                    554:
                    555:   begin
                    556:     if k > 0 and not Empty(n)
                    557:      then if k > Size(n)
                    558:            then Clear(n);
                    559:            else declare
                    560:                   nmk : Natural_Number_Rep(n.size-k);
                    561:                 begin
                    562:                   for i in nmk.numb'range loop
                    563:                     nmk.numb(i) := n.numb(k+i);
                    564:                   end loop;
                    565:                   Clear(n);
                    566:                   n := new Natural_Number_Rep'(nmk);
                    567:                 end;
                    568:           end if;
                    569:     end if;
                    570:   end Div_Base;
                    571:
                    572: -- ARITHMETIC OPERATIONS :
                    573:
                    574:   function "+" ( n1 : Natural_Number; n2 : natural ) return Natural_Number is
                    575:
                    576:     res : Natural_Number;
                    577:
                    578:   begin
                    579:     if Empty(n1)
                    580:      then res := Create(n2);
                    581:      else declare
                    582:             cff : Array_of_Naturals(n1.numb'range);
                    583:             sum,carry : natural;
                    584:           begin
                    585:             carry := n2;
                    586:             for i in cff'range loop
                    587:               sum := n1.numb(i) + carry;
                    588:               cff(i) := sum mod the_base;
                    589:               carry := sum/the_base;
                    590:             end loop;
                    591:             res := new Natural_Number_Rep'(Extend(cff,carry));
                    592:           end;
                    593:     end if;
                    594:     return res;
                    595:   end "+";
                    596:
                    597:   function "+" ( n1 : natural; n2 : Natural_Number ) return Natural_Number is
                    598:   begin
                    599:     return n2+n1;
                    600:   end "+";
                    601:
                    602:   function "+" ( n1,n2 : Natural_Number ) return Natural_Number is
                    603:
                    604:     res : Natural_Number;
                    605:     sum,carry : natural;
                    606:
                    607:   begin
                    608:     if Empty(n1)
                    609:      then Copy(n2,res);
                    610:      elsif Empty(n2)
                    611:          then Copy(n1,res);
                    612:          else carry := 0;
                    613:               if Size(n1) > Size(n2)
                    614:                then declare
                    615:                       res_rep : Natural_Number_Rep(Size(n1)) := n1.all;
                    616:                     begin
                    617:                       for i in n2.numb'range loop
                    618:                         sum := res_rep.numb(i) + n2.numb(i) + carry;
                    619:                         res_rep.numb(i) := sum mod the_base;
                    620:                         carry := sum/the_base;
                    621:                       end loop;
                    622:                       if carry /= 0
                    623:                        then for i in n2.numb'last+1..n1.numb'last loop
                    624:                               sum := res_rep.numb(i) + carry;
                    625:                               res_rep.numb(i) := sum mod the_base;
                    626:                               carry := sum/the_base;
                    627:                               exit when (carry = 0);
                    628:                             end loop;
                    629:                       end if;
                    630:                       res := new Natural_Number_Rep'(res_rep);
                    631:                     end;
                    632:                else declare
                    633:                       res_rep : Natural_Number_Rep(Size(n2)) := n2.all;
                    634:                     begin
                    635:                       for i in n1.numb'range loop
                    636:                         sum := res_rep.numb(i) + n1.numb(i) + carry;
                    637:                         res_rep.numb(i) := sum mod the_base;
                    638:                         carry := sum/the_base;
                    639:                       end loop;
                    640:                       if carry /= 0
                    641:                        then for i in n1.numb'last+1..n2.numb'last loop
                    642:                               sum := res_rep.numb(i) + carry;
                    643:                               res_rep.numb(i) := sum mod the_base;
                    644:                               carry := sum/the_base;
                    645:                               exit when (carry = 0);
                    646:                             end loop;
                    647:                       end if;
                    648:                       res := new Natural_Number_Rep'(res_rep);
                    649:                     end;
                    650:              end if;
                    651:              Extend(res,carry);
                    652:     end if;
                    653:     return res;
                    654:   end "+";
                    655:
                    656:   procedure Add ( n1 : in out Natural_Number; n2 : in natural ) is
                    657:
                    658:     sum,carry : natural;
                    659:
                    660:   begin
                    661:     if Empty(n1)
                    662:      then n1 := Create(n2);
                    663:      else carry := n2;
                    664:           for i in n1.numb'range loop
                    665:             sum := n1.numb(i) + carry;
                    666:             n1.numb(i) := sum mod the_base;
                    667:             carry := sum/the_base;
                    668:           end loop;
                    669:           Extend(n1,carry);
                    670:     end if;
                    671:   end Add;
                    672:
                    673:   procedure Add ( n1 : in out Natural_Number; n2 : in Natural_Number ) is
                    674:
                    675:     res : Natural_Number;
                    676:     sum,carry : natural;
                    677:
                    678:   begin
                    679:     if Empty(n1)
                    680:      then Copy(n2,n1);
                    681:      elsif not Empty(n2)
                    682:          then carry := 0;
                    683:               if Size(n1) >= Size(n2)
                    684:                then for i in n2.numb'range loop
                    685:                       sum := n1.numb(i) + n2.numb(i) + carry;
                    686:                       n1.numb(i) := sum mod the_base;
                    687:                       carry := sum/the_base;
                    688:                     end loop;
                    689:                     if carry /= 0
                    690:                      then for i in n2.numb'last+1..n1.numb'last loop
                    691:                             sum := n1.numb(i) + carry;
                    692:                             n1.numb(i) := sum mod the_base;
                    693:                             carry := sum/the_base;
                    694:                             exit when (carry = 0);
                    695:                           end loop;
                    696:                           Extend(n1,carry);
                    697:                     end if;
                    698:                else declare
                    699:                       res_rep : Natural_Number_Rep(Size(n2)) := n2.all;
                    700:                     begin
                    701:                       for i in n1.numb'range loop
                    702:                         sum := res_rep.numb(i) + n1.numb(i) + carry;
                    703:                         res_rep.numb(i) := sum mod the_base;
                    704:                         carry := sum/the_base;
                    705:                       end loop;
                    706:                       if carry /= 0
                    707:                        then for i in n1.numb'last+1..n2.numb'last loop
                    708:                               sum := res_rep.numb(i) + carry;
                    709:                               res_rep.numb(i) := sum mod the_base;
                    710:                               carry := sum/the_base;
                    711:                               exit when (carry = 0);
                    712:                             end loop;
                    713:                       end if;
                    714:                       Clear(n1);
                    715:                       n1 := new Natural_Number_Rep'(res_rep);
                    716:                       if carry /= 0
                    717:                        then Extend(n1,carry);
                    718:                       end if;
                    719:                     end;
                    720:               end if;
                    721:     end if;
                    722:   end Add;
                    723:
                    724:   function "-" ( n1 : Natural_Number; n2 : natural ) return Natural_Number is
                    725:
                    726:     res : Natural_Number;
                    727:     diff,carry : integer;
                    728:
                    729:   begin
                    730:     if not Empty(n1)
                    731:      then Copy(n1,res);
                    732:           declare
                    733:             n2cff : constant Array_of_Naturals := Create(n2);
                    734:             index : natural := n2cff'first;
                    735:           begin
                    736:             carry := n2cff(index);
                    737:             for i in n1.numb'range loop
                    738:               diff := n1.numb(i) - carry;
                    739:               if diff >= 0
                    740:                then res.numb(i) := diff mod the_base;
                    741:                     carry := diff/the_base;
                    742:                else diff := the_base + diff;
                    743:                     res.numb(i) := diff mod the_base;
                    744:                     carry := diff/the_base + (res.numb(i)+carry)/the_base;
                    745:               end if;
                    746:               if index < n2cff'last
                    747:                then index := index+1;
                    748:                     carry := carry + n2cff(index);
                    749:               end if;
                    750:               exit when (carry = 0);
                    751:             end loop;
                    752:           end;
                    753:     end if;
                    754:     return res;
                    755:   end "-";
                    756:
                    757:   function "-" ( n1 : natural; n2 : Natural_Number ) return Natural_Number is
                    758:
                    759:     tmp : Natural_Number := Create(n1);
                    760:     res : Natural_Number := tmp - n2;
                    761:
                    762:   begin
                    763:     Clear(tmp);
                    764:     return res;
                    765:   end "-";
                    766:
                    767:   function "-" ( n1,n2 : Natural_Number ) return Natural_Number is
                    768:
                    769:     res,diff : Natural_Number;
                    770:
                    771:   begin
                    772:     Copy(n1,res);
                    773:     if not Empty(n2)
                    774:      then for i in reverse n2.numb'range loop
                    775:             Copy(res,diff);
                    776:             Div_Base(diff,i);
                    777:             if not Empty(diff)
                    778:              then Sub(diff,n2.numb(i));
                    779:                   for j in diff.numb'range loop
                    780:                     res.numb(i+j) := diff.numb(j);
                    781:                   end loop;
                    782:                   Clear(diff);
                    783:             end if;
                    784:           end loop;
                    785:     end if;
                    786:     return res;
                    787:   end "-";
                    788:
                    789:   function "+" ( n : Natural_Number ) return Natural_Number is
                    790:
                    791:     res : Natural_Number;
                    792:
                    793:   begin
                    794:     Copy(n,res);
                    795:     return res;
                    796:   end "+";
                    797:
                    798:   function "-" ( n : Natural_Number ) return Natural_Number is
                    799:
                    800:     res : Natural_Number;
                    801:
                    802:   begin
                    803:     Copy(n,res);
                    804:     return res;
                    805:   end "-";
                    806:
                    807:   procedure Min ( n : in out Natural_Number ) is
                    808:   begin
                    809:     null;
                    810:   end Min;
                    811:
                    812:   procedure Sub ( n1 : in out Natural_Number; n2 : in natural ) is
                    813:
                    814:     diff,carry : integer;
                    815:
                    816:   begin
                    817:     if not Empty(n1) and n2 > 0
                    818:      then declare
                    819:             n2cff : constant Array_of_Naturals := Create(n2);
                    820:             index : natural := n2cff'first;
                    821:           begin
                    822:             carry := n2cff(index);
                    823:             for i in n1.numb'range loop
                    824:               diff := n1.numb(i) - carry;
                    825:               if diff >= 0
                    826:                then n1.numb(i) := diff mod the_base;
                    827:                     carry := diff/the_base;
                    828:                else diff := the_base + diff;
                    829:                     n1.numb(i) := diff mod the_base;
                    830:                     carry := diff/the_base + (n1.numb(i)+carry)/the_base;
                    831:               end if;
                    832:               if index < n2cff'last
                    833:                then index := index+1;
                    834:                     carry := carry + n2cff(index);
                    835:               end if;
                    836:               exit when (carry = 0);
                    837:             end loop;
                    838:           end;
                    839:     end if;
                    840:   end Sub;
                    841:
                    842:   procedure Sub ( n1 : in out Natural_Number; n2 : in Natural_Number ) is
                    843:
                    844:     res,diff : Natural_Number;
                    845:
                    846:   begin
                    847:     if not Empty(n1) and not Empty(n2)
                    848:      then for i in reverse n2.numb'range loop
                    849:             Copy(n1,diff);
                    850:             Div_Base(diff,i);
                    851:             if not Empty(diff)
                    852:              then Sub(diff,n2.numb(i));
                    853:                   for j in diff.numb'range loop
                    854:                     n1.numb(i+j) := diff.numb(j);
                    855:                   end loop;
                    856:                   Clear(diff);
                    857:             end if;
                    858:           end loop;
                    859:     end if;
                    860:   end Sub;
                    861:
                    862:   function "*" ( n1 : Natural_Number; n2 : natural ) return Natural_Number is
                    863:
                    864:     res,prod,nres : Natural_Number;
                    865:     remainder,modfact : natural;
                    866:     cnt : natural := 0;
                    867:
                    868:   begin
                    869:     if n2 /= 0
                    870:      then remainder := n2;
                    871:           while remainder /= 0 loop
                    872:             modfact := remainder mod fact;
                    873:             if modfact /= 0
                    874:              then Copy(n1,prod);
                    875:                   Mul_Fact(prod,modfact);
                    876:                   for i in 1..cnt loop
                    877:                     Mul_Fact(prod,fact);
                    878:                   end loop;
                    879:                   Add(res,prod);
                    880:                   Clear(prod);
                    881:             end if;
                    882:             cnt := cnt+1;
                    883:             remainder := remainder/fact;
                    884:           end loop;
                    885:     end if;
                    886:     return res;
                    887:   end "*";
                    888:
                    889:   function "*" ( n1 : natural; n2 : Natural_Number ) return Natural_Number is
                    890:   begin
                    891:     return n2*n1;
                    892:   end "*";
                    893:
                    894:   function "*" ( n1,n2 : Natural_Number ) return Natural_Number is
                    895:
                    896:     res,prod : Natural_Number;
                    897:
                    898:   begin
                    899:     if (Empty(n1) or else Empty(n2))
                    900:      then return res;
                    901:      else if Size(n1) >= Size(n2)
                    902:            then for i in n2.numb'range loop
                    903:                   prod := n1*n2.numb(i);
                    904:                   Mul_Base(prod,i);
                    905:                   Add(res,prod);
                    906:                   Clear(prod);
                    907:                 end loop;
                    908:            else for i in n1.numb'range loop
                    909:                   prod := n2*n1.numb(i);
                    910:                   Mul_Base(prod,i);
                    911:                   Add(res,prod);
                    912:                   Clear(prod);
                    913:                 end loop;
                    914:           end if;
                    915:     end if;
                    916:     return res;
                    917:   end "*";
                    918:
                    919:   procedure Mul ( n1 : in out Natural_Number; n2 : in natural ) is
                    920:
                    921:     res,prod : Natural_Number;
                    922:     remainder,modfact : natural;
                    923:     cnt : natural := 0;
                    924:
                    925:   begin
                    926:     if n2 = 0
                    927:      then Clear(n1);
                    928:      else remainder := n2;
                    929:           while remainder /= 0 loop
                    930:             modfact := remainder mod fact;
                    931:             if modfact /= 0
                    932:              then Copy(n1,prod);
                    933:                   Mul_Fact(prod,modfact);
                    934:                   for i in 1..cnt loop
                    935:                     Mul_Fact(prod,fact);
                    936:                   end loop;
                    937:                   Add(res,prod);
                    938:                   Clear(prod);
                    939:             end if;
                    940:             cnt := cnt+1;
                    941:             remainder := remainder/fact;
                    942:           end loop;
                    943:           Clear(n1);
                    944:           n1 := res;
                    945:     end if;
                    946:   end Mul;
                    947:
                    948:   procedure Mul ( n1 : in out Natural_Number; n2 : in Natural_Number ) is
                    949:
                    950:     res,prod : Natural_Number;
                    951:
                    952:   begin
                    953:     if not Empty(n1)
                    954:      then if Empty(n2)
                    955:            then Clear(n1);
                    956:            else if Size(n1) >= Size(n2)
                    957:                  then for i in n2.numb'range loop
                    958:                         prod := n1*n2.numb(i);
                    959:                         Mul_Base(prod,i);
                    960:                         Add(res,prod);
                    961:                         Clear(prod);
                    962:                       end loop;
                    963:                  else for i in n1.numb'range loop
                    964:                         prod := n2*n1.numb(i);
                    965:                         Mul_Base(prod,i);
                    966:                         Add(res,prod);
                    967:                         Clear(prod);
                    968:                       end loop;
                    969:                 end if;
                    970:                 Clear(n1);
                    971:                 n1 := res;
                    972:           end if;
                    973:     end if;
                    974:   end Mul;
                    975:
                    976:   function "**" ( n1 : Natural_Number; n2 : natural ) return Natural_Number is
                    977:
                    978:     res : Natural_Number;
                    979:
                    980:   begin
                    981:     if n2 = 0
                    982:      then res := Create(1);
                    983:      else if not Empty(n1)
                    984:            then Copy(n1,res);
                    985:                 for i in 1..n2-1 loop
                    986:                   Mul(res,n1);
                    987:                 end loop;
                    988:           end if;
                    989:     end if;
                    990:     return res;
                    991:   end "**";
                    992:
                    993:   function "**" ( n1 : natural; n2 : Natural_Number ) return Natural_Number is
                    994:
                    995:     res,cnt : Natural_Number;
                    996:
                    997:   begin
                    998:     if Equal(n2,0)
                    999:      then res := Create(1);
                   1000:      else res := Create(n1);
                   1001:           if n1 /= 0
                   1002:            then cnt := Create(1);
                   1003:                 while not Equal(cnt,n2) loop
                   1004:                   Mul(res,n1);
                   1005:                   Add(cnt,1);
                   1006:                 end loop;
                   1007:                 Clear(cnt);
                   1008:           end if;
                   1009:     end if;
                   1010:     return res;
                   1011:   end "**";
                   1012:
                   1013:   function "**" ( n1,n2 : Natural_Number ) return Natural_Number is
                   1014:
                   1015:     res,cnt : Natural_Number;
                   1016:
                   1017:   begin
                   1018:     if Equal(n2,0)
                   1019:      then res := Create(1);
                   1020:      else if not Empty(n1)
                   1021:            then Copy(n1,res);
                   1022:                 cnt := Create(1);
                   1023:                 while not Equal(cnt,n2) loop
                   1024:                   Mul(res,n1);
                   1025:                   Add(cnt,1);
                   1026:                 end loop;
                   1027:                 Clear(cnt);
                   1028:           end if;
                   1029:     end if;
                   1030:     return res;
                   1031:   end "**";
                   1032:
                   1033:   procedure Small_Div ( n1 : in Natural_Number; n2 : in natural;
                   1034:                         q : out Natural_Number; r : out natural ) is
                   1035:
                   1036:   -- DESCRIPTION :
                   1037:   --   n1 = n2*q + r, only applies when n2 <= fact.
                   1038:
                   1039:    -- res : Natural_Number;
                   1040:     carry : natural := 0;
                   1041:
                   1042:   begin
                   1043:     if n2 /= 0
                   1044:      then if not Empty(n1)
                   1045:            then -- res := new Natural_Number_Rep(Size(n1));
                   1046:                 q := new Natural_Number_Rep(Size(n1));
                   1047:                 for i in reverse 1..Size(n1) loop
                   1048:                  -- res.numb(i) := (n1.numb(i)+carry)/n2;
                   1049:                   q.numb(i) := (n1.numb(i)+carry)/n2;
                   1050:                   carry := (n1.numb(i)+carry) mod n2;
                   1051:                   carry := carry*the_base;
                   1052:                 end loop;
                   1053:                -- res.numb(0) := (n1.numb(0)+carry)/n2;
                   1054:                 q.numb(0) := (n1.numb(0)+carry)/n2;
                   1055:                 carry := (n1.numb(0)+carry) mod n2;
                   1056:           end if;
                   1057:      else raise NUMERIC_ERROR;
                   1058:     end if;
                   1059:    -- q := res;
                   1060:     r := carry;
                   1061:   end Small_Div;
                   1062:
                   1063:   procedure Small_Div ( n1 : in out Natural_Number; n2 : in natural;
                   1064:                         r : out natural ) is
                   1065:
                   1066:     q : Natural_Number;
                   1067:
                   1068:   begin
                   1069:     Small_Div(n1,n2,q,r);
                   1070:     Copy(q,n1); Clear(q);
                   1071:   end Small_Div;
                   1072:
                   1073:   procedure Big_Div ( n1 : in Natural_Number; n2 : in natural;
                   1074:                       q : out Natural_Number; r : out natural ) is
                   1075:
                   1076:   -- DESCRIPTION :
                   1077:   --   This division has to be applied when n2 > fact.
                   1078:
                   1079:     wrkn1,shiftn1,remn1,acc,qres,qsub : Natural_Number;
                   1080:     cntshf,cntsub,rres : natural;
                   1081:
                   1082:   begin
                   1083:     if n2 /= 0
                   1084:      then
                   1085:        if n1 < n2
                   1086:         then
                   1087:           q := qres;
                   1088:           r := Create(n1);
                   1089:         else
                   1090:           Copy(n1,shiftn1);                  -- we have n1 >= n2
                   1091:           Small_Div(shiftn1,fact,wrkn1,rres);
                   1092:           cntshf := 0;
                   1093:           while not (wrkn1 < n2) loop        -- invariant n2 <= shiftn1
                   1094:             acc := Create(rres);
                   1095:             for i in 1..cntshf loop
                   1096:               Mul_Fact(acc,fact);
                   1097:             end loop;
                   1098:             Add(remn1,acc); Clear(acc);
                   1099:             Copy(wrkn1,shiftn1);
                   1100:             cntshf := cntshf + 1;
                   1101:             Small_Div(wrkn1,fact,rres);      -- at end of loop
                   1102:           end loop;                          --   shiftn1/fact < n2 <= shiftn1
                   1103:           Clear(wrkn1);
                   1104:           cntsub := 0;
                   1105:           while not (shiftn1 < n2) loop      -- subtract n2 from shiftn1
                   1106:             cntsub := cntsub + 1;
                   1107:             Sub(shiftn1,n2);
                   1108:           end loop;
                   1109:           qsub := Create(cntsub);            -- intermediate quotient
                   1110:           for i in 1..cntshf loop
                   1111:             Mul_Fact(qsub,fact);
                   1112:             Mul_Fact(shiftn1,fact);
                   1113:           end loop;
                   1114:           Add(shiftn1,remn1);
                   1115:           Clear(remn1);
                   1116:           Div(shiftn1,n2,qres,r);            -- recursive call
                   1117:           Add(qsub,qres);                    -- collect results
                   1118:           q := qsub;
                   1119:           Clear(qres); Clear(shiftn1);       -- cleaning up
                   1120:        end if;
                   1121:      else
                   1122:        raise NUMERIC_ERROR;
                   1123:     end if;
                   1124:   end Big_Div;
                   1125:
                   1126:   function "/" ( n1 : Natural_Number; n2 : natural ) return Natural_Number is
                   1127:
                   1128:     res : Natural_Number;
                   1129:     r : natural;
                   1130:
                   1131:   begin
                   1132:     if not Empty(n1)
                   1133:      then if n2 <= fact
                   1134:            then Small_Div(n1,n2,res,r);
                   1135:            else Big_Div(n1,n2,res,r);
                   1136:           end if;
                   1137:     end if;
                   1138:     return res;
                   1139:   end "/";
                   1140:
                   1141:   function "/" ( n1 : natural; n2 : Natural_Number ) return natural is
                   1142:
                   1143:     res : natural;
                   1144:
                   1145:   begin
                   1146:     if n1 < n2
                   1147:      then res := 0;
                   1148:      elsif not Empty(n2)
                   1149:          then res := Create(n2);
                   1150:               res := n1/res;
                   1151:          else raise NUMERIC_ERROR;
                   1152:     end if;
                   1153:     return res;
                   1154:   end "/";
                   1155:
                   1156:   function "/" ( n1,n2 : Natural_Number ) return Natural_Number is
                   1157:
                   1158:     res,rrr : Natural_Number;
                   1159:
                   1160:   begin
                   1161:     Div(n1,n2,res,rrr);
                   1162:     Clear(rrr);
                   1163:     return res;
                   1164:   end "/";
                   1165:
                   1166:   function Rmd ( n1 : Natural_Number; n2 : natural ) return natural is
                   1167:
                   1168:     res : natural;
                   1169:     q : Natural_Number;
                   1170:
                   1171:   begin
                   1172:     if n2 <= fact
                   1173:      then Small_Div(n1,n2,q,res);
                   1174:      else Big_Div(n1,n2,q,res);
                   1175:     end if;
                   1176:     Clear(q);
                   1177:     return res;
                   1178:   end Rmd;
                   1179:
                   1180:   function Rmd ( n1 : natural; n2 : Natural_Number ) return natural is
                   1181:
                   1182:     res : natural;
                   1183:
                   1184:   begin
                   1185:     if n1 < n2
                   1186:      then res := n1;
                   1187:      elsif not Empty(n2)
                   1188:          then res := Create(n2);
                   1189:               res := n1 mod res;
                   1190:          else raise NUMERIC_ERROR;
                   1191:     end if;
                   1192:     return res;
                   1193:   end Rmd;
                   1194:
                   1195:   function Rmd ( n1,n2 : Natural_Number ) return Natural_Number is
                   1196:
                   1197:     res,q : Natural_Number;
                   1198:
                   1199:   begin
                   1200:     Div(n1,n2,q,res);
                   1201:     Clear(q);
                   1202:     return res;
                   1203:   end Rmd;
                   1204:
                   1205:   procedure Div ( n1 : in out Natural_Number; n2 : in natural ) is
                   1206:
                   1207:     r : natural;
                   1208:
                   1209:   begin
                   1210:     Div(n1,n2,r);
                   1211:   end Div;
                   1212:
                   1213:   procedure Div ( n1 : in out Natural_Number; n2 : in Natural_Number ) is
                   1214:
                   1215:     r : Natural_Number;
                   1216:
                   1217:   begin
                   1218:     Div(n1,n2,r);
                   1219:     Clear(r);
                   1220:   end Div;
                   1221:
                   1222:   procedure Div ( n1 : in Natural_Number; n2 : in natural;
                   1223:                   q : out Natural_Number; r : out natural ) is
                   1224:   begin
                   1225:     if n2 <= fact
                   1226:      then Small_Div(n1,n2,q,r);
                   1227:      else Big_Div(n1,n2,q,r);
                   1228:     end if;
                   1229:   end Div;
                   1230:
                   1231:   procedure Div ( n1 : in out Natural_Number; n2 : in natural;
                   1232:                   r : out natural ) is
                   1233:
                   1234:     q : Natural_Number;
                   1235:
                   1236:   begin
                   1237:     Div(n1,n2,q,r);
                   1238:     Copy(q,n1); Clear(q);
                   1239:   end Div;
                   1240:
                   1241:   procedure Div ( n1,n2 : in Natural_Number;
                   1242:                   q : out Natural_Number; r : out Natural_Number ) is
                   1243:
                   1244:     wrkn1,shiftn1,remn1,acc,qres,qsub : Natural_Number;
                   1245:     cntshf,cntsub,rres : natural;
                   1246:
                   1247:   begin
                   1248:     if (Empty(n2) or else Equal(n2,0))
                   1249:      then
                   1250:        raise NUMERIC_ERROR;
                   1251:      else
                   1252:        if n1 < n2
                   1253:         then
                   1254:           q := qres;
                   1255:           Copy(n1,r);
                   1256:         else
                   1257:           Copy(n1,shiftn1);                  -- we have n1 >= n2
                   1258:           Small_Div(shiftn1,fact,wrkn1,rres);
                   1259:           cntshf := 0;
                   1260:           while not (wrkn1 < n2) loop        -- invariant n2 <= shiftn1
                   1261:             acc := Create(rres);
                   1262:             for i in 1..cntshf loop
                   1263:               Mul_Fact(acc,fact);
                   1264:             end loop;
                   1265:             Add(remn1,acc); Clear(acc);
                   1266:             Copy(wrkn1,shiftn1);
                   1267:             cntshf := cntshf + 1;
                   1268:             Small_Div(wrkn1,fact,rres);      -- at end of loop
                   1269:           end loop;                          --   shiftn1/fact < n2 <= shiftn1
                   1270:           Clear(wrkn1);
                   1271:           cntsub := 0;
                   1272:           while not (shiftn1 < n2) loop      -- subtract n2 from shiftn1
                   1273:             cntsub := cntsub + 1;
                   1274:             Sub(shiftn1,n2);
                   1275:           end loop;
                   1276:           qsub := Create(cntsub);            -- intermediate quotient
                   1277:           for i in 1..cntshf loop
                   1278:             Mul_Fact(qsub,fact);
                   1279:             Mul_Fact(shiftn1,fact);
                   1280:           end loop;
                   1281:           Add(shiftn1,remn1);
                   1282:           Clear(remn1);
                   1283:           Div(shiftn1,n2,qres,r);            -- recursive call
                   1284:           Add(qsub,qres);                    -- collect results
                   1285:           q := qsub;
                   1286:           Clear(qres); Clear(shiftn1);       -- cleaning up
                   1287:        end if;
                   1288:     end if;
                   1289:   end Div;
                   1290:
                   1291:   procedure Div ( n1 : in out Natural_Number; n2 : in Natural_Number;
                   1292:                   r : out Natural_Number ) is
                   1293:
                   1294:     q : Natural_Number;
                   1295:
                   1296:   begin
                   1297:     Div(n1,n2,q,r);
                   1298:     Copy(q,n1); Clear(q);
                   1299:   end Div;
                   1300:
                   1301: -- DESTRUCTOR :
                   1302:
                   1303:   procedure Clear ( n : in out Natural_Number ) is
                   1304:
                   1305:     procedure free is
                   1306:       new unchecked_deallocation(Natural_Number_Rep,Natural_Number);
                   1307:
                   1308:   begin
                   1309:     if not Empty(n)
                   1310:      then free(n);
                   1311:     end if;
                   1312:   end Clear;
                   1313:
                   1314: end Multprec_Natural_Numbers;

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>