Annotation of OpenXM_contrib/PHC/Ada/Math_Lib/Numbers/multprec_natural_numbers.adb, Revision 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>