1------------------------------------------------------------------------------ 2-- -- 3-- GNAT COMPILER COMPONENTS -- 4-- -- 5-- U I N T P -- 6-- -- 7-- B o d y -- 8-- -- 9-- Copyright (C) 1992-2015, Free Software Foundation, Inc. -- 10-- -- 11-- GNAT is free software; you can redistribute it and/or modify it under -- 12-- terms of the GNU General Public License as published by the Free Soft- -- 13-- ware Foundation; either version 3, or (at your option) any later ver- -- 14-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- 15-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- 16-- or FITNESS FOR A PARTICULAR PURPOSE. -- 17-- -- 18-- As a special exception under Section 7 of GPL version 3, you are granted -- 19-- additional permissions described in the GCC Runtime Library Exception, -- 20-- version 3.1, as published by the Free Software Foundation. -- 21-- -- 22-- You should have received a copy of the GNU General Public License and -- 23-- a copy of the GCC Runtime Library Exception along with this program; -- 24-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- 25-- <http://www.gnu.org/licenses/>. -- 26-- -- 27-- GNAT was originally developed by the GNAT team at New York University. -- 28-- Extensive contributions were provided by Ada Core Technologies Inc. -- 29-- -- 30------------------------------------------------------------------------------ 31 32with Output; use Output; 33with Tree_IO; use Tree_IO; 34 35with GNAT.HTable; use GNAT.HTable; 36 37package body Uintp is 38 39 ------------------------ 40 -- Local Declarations -- 41 ------------------------ 42 43 Uint_Int_First : Uint := Uint_0; 44 -- Uint value containing Int'First value, set by Initialize. The initial 45 -- value of Uint_0 is used for an assertion check that ensures that this 46 -- value is not used before it is initialized. This value is used in the 47 -- UI_Is_In_Int_Range predicate, and it is right that this is a host value, 48 -- since the issue is host representation of integer values. 49 50 Uint_Int_Last : Uint; 51 -- Uint value containing Int'Last value set by Initialize 52 53 UI_Power_2 : array (Int range 0 .. 64) of Uint; 54 -- This table is used to memoize exponentiations by powers of 2. The Nth 55 -- entry, if set, contains the Uint value 2 ** N. Initially UI_Power_2_Set 56 -- is zero and only the 0'th entry is set, the invariant being that all 57 -- entries in the range 0 .. UI_Power_2_Set are initialized. 58 59 UI_Power_2_Set : Nat; 60 -- Number of entries set in UI_Power_2; 61 62 UI_Power_10 : array (Int range 0 .. 64) of Uint; 63 -- This table is used to memoize exponentiations by powers of 10 in the 64 -- same manner as described above for UI_Power_2. 65 66 UI_Power_10_Set : Nat; 67 -- Number of entries set in UI_Power_10; 68 69 Uints_Min : Uint; 70 Udigits_Min : Int; 71 -- These values are used to make sure that the mark/release mechanism does 72 -- not destroy values saved in the U_Power tables or in the hash table used 73 -- by UI_From_Int. Whenever an entry is made in either of these tables, 74 -- Uints_Min and Udigits_Min are updated to protect the entry, and Release 75 -- never cuts back beyond these minimum values. 76 77 Int_0 : constant Int := 0; 78 Int_1 : constant Int := 1; 79 Int_2 : constant Int := 2; 80 -- These values are used in some cases where the use of numeric literals 81 -- would cause ambiguities (integer vs Uint). 82 83 ---------------------------- 84 -- UI_From_Int Hash Table -- 85 ---------------------------- 86 87 -- UI_From_Int uses a hash table to avoid duplicating entries and wasting 88 -- storage. This is particularly important for complex cases of back 89 -- annotation. 90 91 subtype Hnum is Nat range 0 .. 1022; 92 93 function Hash_Num (F : Int) return Hnum; 94 -- Hashing function 95 96 package UI_Ints is new Simple_HTable ( 97 Header_Num => Hnum, 98 Element => Uint, 99 No_Element => No_Uint, 100 Key => Int, 101 Hash => Hash_Num, 102 Equal => "="); 103 104 ----------------------- 105 -- Local Subprograms -- 106 ----------------------- 107 108 function Direct (U : Uint) return Boolean; 109 pragma Inline (Direct); 110 -- Returns True if U is represented directly 111 112 function Direct_Val (U : Uint) return Int; 113 -- U is a Uint for is represented directly. The returned result is the 114 -- value represented. 115 116 function GCD (Jin, Kin : Int) return Int; 117 -- Compute GCD of two integers. Assumes that Jin >= Kin >= 0 118 119 procedure Image_Out 120 (Input : Uint; 121 To_Buffer : Boolean; 122 Format : UI_Format); 123 -- Common processing for UI_Image and UI_Write, To_Buffer is set True for 124 -- UI_Image, and false for UI_Write, and Format is copied from the Format 125 -- parameter to UI_Image or UI_Write. 126 127 procedure Init_Operand (UI : Uint; Vec : out UI_Vector); 128 pragma Inline (Init_Operand); 129 -- This procedure puts the value of UI into the vector in canonical 130 -- multiple precision format. The parameter should be of the correct size 131 -- as determined by a previous call to N_Digits (UI). The first digit of 132 -- Vec contains the sign, all other digits are always non-negative. Note 133 -- that the input may be directly represented, and in this case Vec will 134 -- contain the corresponding one or two digit value. The low bound of Vec 135 -- is always 1. 136 137 function Least_Sig_Digit (Arg : Uint) return Int; 138 pragma Inline (Least_Sig_Digit); 139 -- Returns the Least Significant Digit of Arg quickly. When the given Uint 140 -- is less than 2**15, the value returned is the input value, in this case 141 -- the result may be negative. It is expected that any use will mask off 142 -- unnecessary bits. This is used for finding Arg mod B where B is a power 143 -- of two. Hence the actual base is irrelevant as long as it is a power of 144 -- two. 145 146 procedure Most_Sig_2_Digits 147 (Left : Uint; 148 Right : Uint; 149 Left_Hat : out Int; 150 Right_Hat : out Int); 151 -- Returns leading two significant digits from the given pair of Uint's. 152 -- Mathematically: returns Left / (Base ** K) and Right / (Base ** K) where 153 -- K is as small as possible S.T. Right_Hat < Base * Base. It is required 154 -- that Left > Right for the algorithm to work. 155 156 function N_Digits (Input : Uint) return Int; 157 pragma Inline (N_Digits); 158 -- Returns number of "digits" in a Uint 159 160 procedure UI_Div_Rem 161 (Left, Right : Uint; 162 Quotient : out Uint; 163 Remainder : out Uint; 164 Discard_Quotient : Boolean := False; 165 Discard_Remainder : Boolean := False); 166 -- Compute Euclidean division of Left by Right. If Discard_Quotient is 167 -- False then the quotient is returned in Quotient (otherwise Quotient is 168 -- set to No_Uint). If Discard_Remainder is False, then the remainder is 169 -- returned in Remainder (otherwise Remainder is set to No_Uint). 170 -- 171 -- If Discard_Quotient is True, Quotient is set to No_Uint 172 -- If Discard_Remainder is True, Remainder is set to No_Uint 173 174 ------------ 175 -- Direct -- 176 ------------ 177 178 function Direct (U : Uint) return Boolean is 179 begin 180 return Int (U) <= Int (Uint_Direct_Last); 181 end Direct; 182 183 ---------------- 184 -- Direct_Val -- 185 ---------------- 186 187 function Direct_Val (U : Uint) return Int is 188 begin 189 pragma Assert (Direct (U)); 190 return Int (U) - Int (Uint_Direct_Bias); 191 end Direct_Val; 192 193 --------- 194 -- GCD -- 195 --------- 196 197 function GCD (Jin, Kin : Int) return Int is 198 J, K, Tmp : Int; 199 200 begin 201 pragma Assert (Jin >= Kin); 202 pragma Assert (Kin >= Int_0); 203 204 J := Jin; 205 K := Kin; 206 while K /= Uint_0 loop 207 Tmp := J mod K; 208 J := K; 209 K := Tmp; 210 end loop; 211 212 return J; 213 end GCD; 214 215 -------------- 216 -- Hash_Num -- 217 -------------- 218 219 function Hash_Num (F : Int) return Hnum is 220 begin 221 return Types."mod" (F, Hnum'Range_Length); 222 end Hash_Num; 223 224 --------------- 225 -- Image_Out -- 226 --------------- 227 228 procedure Image_Out 229 (Input : Uint; 230 To_Buffer : Boolean; 231 Format : UI_Format) 232 is 233 Marks : constant Uintp.Save_Mark := Uintp.Mark; 234 Base : Uint; 235 Ainput : Uint; 236 237 Digs_Output : Natural := 0; 238 -- Counts digits output. In hex mode, but not in decimal mode, we 239 -- put an underline after every four hex digits that are output. 240 241 Exponent : Natural := 0; 242 -- If the number is too long to fit in the buffer, we switch to an 243 -- approximate output format with an exponent. This variable records 244 -- the exponent value. 245 246 function Better_In_Hex return Boolean; 247 -- Determines if it is better to generate digits in base 16 (result 248 -- is true) or base 10 (result is false). The choice is purely a 249 -- matter of convenience and aesthetics, so it does not matter which 250 -- value is returned from a correctness point of view. 251 252 procedure Image_Char (C : Character); 253 -- Internal procedure to output one character 254 255 procedure Image_Exponent (N : Natural); 256 -- Output non-zero exponent. Note that we only use the exponent form in 257 -- the buffer case, so we know that To_Buffer is true. 258 259 procedure Image_Uint (U : Uint); 260 -- Internal procedure to output characters of non-negative Uint 261 262 ------------------- 263 -- Better_In_Hex -- 264 ------------------- 265 266 function Better_In_Hex return Boolean is 267 T16 : constant Uint := Uint_2 ** Int'(16); 268 A : Uint; 269 270 begin 271 A := UI_Abs (Input); 272 273 -- Small values up to 2**16 can always be in decimal 274 275 if A < T16 then 276 return False; 277 end if; 278 279 -- Otherwise, see if we are a power of 2 or one less than a power 280 -- of 2. For the moment these are the only cases printed in hex. 281 282 if A mod Uint_2 = Uint_1 then 283 A := A + Uint_1; 284 end if; 285 286 loop 287 if A mod T16 /= Uint_0 then 288 return False; 289 290 else 291 A := A / T16; 292 end if; 293 294 exit when A < T16; 295 end loop; 296 297 while A > Uint_2 loop 298 if A mod Uint_2 /= Uint_0 then 299 return False; 300 301 else 302 A := A / Uint_2; 303 end if; 304 end loop; 305 306 return True; 307 end Better_In_Hex; 308 309 ---------------- 310 -- Image_Char -- 311 ---------------- 312 313 procedure Image_Char (C : Character) is 314 begin 315 if To_Buffer then 316 if UI_Image_Length + 6 > UI_Image_Max then 317 Exponent := Exponent + 1; 318 else 319 UI_Image_Length := UI_Image_Length + 1; 320 UI_Image_Buffer (UI_Image_Length) := C; 321 end if; 322 else 323 Write_Char (C); 324 end if; 325 end Image_Char; 326 327 -------------------- 328 -- Image_Exponent -- 329 -------------------- 330 331 procedure Image_Exponent (N : Natural) is 332 begin 333 if N >= 10 then 334 Image_Exponent (N / 10); 335 end if; 336 337 UI_Image_Length := UI_Image_Length + 1; 338 UI_Image_Buffer (UI_Image_Length) := 339 Character'Val (Character'Pos ('0') + N mod 10); 340 end Image_Exponent; 341 342 ---------------- 343 -- Image_Uint -- 344 ---------------- 345 346 procedure Image_Uint (U : Uint) is 347 H : constant array (Int range 0 .. 15) of Character := 348 "0123456789ABCDEF"; 349 350 Q, R : Uint; 351 begin 352 UI_Div_Rem (U, Base, Q, R); 353 354 if Q > Uint_0 then 355 Image_Uint (Q); 356 end if; 357 358 if Digs_Output = 4 and then Base = Uint_16 then 359 Image_Char ('_'); 360 Digs_Output := 0; 361 end if; 362 363 Image_Char (H (UI_To_Int (R))); 364 365 Digs_Output := Digs_Output + 1; 366 end Image_Uint; 367 368 -- Start of processing for Image_Out 369 370 begin 371 if Input = No_Uint then 372 Image_Char ('?'); 373 return; 374 end if; 375 376 UI_Image_Length := 0; 377 378 if Input < Uint_0 then 379 Image_Char ('-'); 380 Ainput := -Input; 381 else 382 Ainput := Input; 383 end if; 384 385 if Format = Hex 386 or else (Format = Auto and then Better_In_Hex) 387 then 388 Base := Uint_16; 389 Image_Char ('1'); 390 Image_Char ('6'); 391 Image_Char ('#'); 392 Image_Uint (Ainput); 393 Image_Char ('#'); 394 395 else 396 Base := Uint_10; 397 Image_Uint (Ainput); 398 end if; 399 400 if Exponent /= 0 then 401 UI_Image_Length := UI_Image_Length + 1; 402 UI_Image_Buffer (UI_Image_Length) := 'E'; 403 Image_Exponent (Exponent); 404 end if; 405 406 Uintp.Release (Marks); 407 end Image_Out; 408 409 ------------------- 410 -- Init_Operand -- 411 ------------------- 412 413 procedure Init_Operand (UI : Uint; Vec : out UI_Vector) is 414 Loc : Int; 415 416 pragma Assert (Vec'First = Int'(1)); 417 418 begin 419 if Direct (UI) then 420 Vec (1) := Direct_Val (UI); 421 422 if Vec (1) >= Base then 423 Vec (2) := Vec (1) rem Base; 424 Vec (1) := Vec (1) / Base; 425 end if; 426 427 else 428 Loc := Uints.Table (UI).Loc; 429 430 for J in 1 .. Uints.Table (UI).Length loop 431 Vec (J) := Udigits.Table (Loc + J - 1); 432 end loop; 433 end if; 434 end Init_Operand; 435 436 ---------------- 437 -- Initialize -- 438 ---------------- 439 440 procedure Initialize is 441 begin 442 Uints.Init; 443 Udigits.Init; 444 445 Uint_Int_First := UI_From_Int (Int'First); 446 Uint_Int_Last := UI_From_Int (Int'Last); 447 448 UI_Power_2 (0) := Uint_1; 449 UI_Power_2_Set := 0; 450 451 UI_Power_10 (0) := Uint_1; 452 UI_Power_10_Set := 0; 453 454 Uints_Min := Uints.Last; 455 Udigits_Min := Udigits.Last; 456 457 UI_Ints.Reset; 458 end Initialize; 459 460 --------------------- 461 -- Least_Sig_Digit -- 462 --------------------- 463 464 function Least_Sig_Digit (Arg : Uint) return Int is 465 V : Int; 466 467 begin 468 if Direct (Arg) then 469 V := Direct_Val (Arg); 470 471 if V >= Base then 472 V := V mod Base; 473 end if; 474 475 -- Note that this result may be negative 476 477 return V; 478 479 else 480 return 481 Udigits.Table 482 (Uints.Table (Arg).Loc + Uints.Table (Arg).Length - 1); 483 end if; 484 end Least_Sig_Digit; 485 486 ---------- 487 -- Mark -- 488 ---------- 489 490 function Mark return Save_Mark is 491 begin 492 return (Save_Uint => Uints.Last, Save_Udigit => Udigits.Last); 493 end Mark; 494 495 ----------------------- 496 -- Most_Sig_2_Digits -- 497 ----------------------- 498 499 procedure Most_Sig_2_Digits 500 (Left : Uint; 501 Right : Uint; 502 Left_Hat : out Int; 503 Right_Hat : out Int) 504 is 505 begin 506 pragma Assert (Left >= Right); 507 508 if Direct (Left) then 509 Left_Hat := Direct_Val (Left); 510 Right_Hat := Direct_Val (Right); 511 return; 512 513 else 514 declare 515 L1 : constant Int := 516 Udigits.Table (Uints.Table (Left).Loc); 517 L2 : constant Int := 518 Udigits.Table (Uints.Table (Left).Loc + 1); 519 520 begin 521 -- It is not so clear what to return when Arg is negative??? 522 523 Left_Hat := abs (L1) * Base + L2; 524 end; 525 end if; 526 527 declare 528 Length_L : constant Int := Uints.Table (Left).Length; 529 Length_R : Int; 530 R1 : Int; 531 R2 : Int; 532 T : Int; 533 534 begin 535 if Direct (Right) then 536 T := Direct_Val (Left); 537 R1 := abs (T / Base); 538 R2 := T rem Base; 539 Length_R := 2; 540 541 else 542 R1 := abs (Udigits.Table (Uints.Table (Right).Loc)); 543 R2 := Udigits.Table (Uints.Table (Right).Loc + 1); 544 Length_R := Uints.Table (Right).Length; 545 end if; 546 547 if Length_L = Length_R then 548 Right_Hat := R1 * Base + R2; 549 elsif Length_L = Length_R + Int_1 then 550 Right_Hat := R1; 551 else 552 Right_Hat := 0; 553 end if; 554 end; 555 end Most_Sig_2_Digits; 556 557 --------------- 558 -- N_Digits -- 559 --------------- 560 561 -- Note: N_Digits returns 1 for No_Uint 562 563 function N_Digits (Input : Uint) return Int is 564 begin 565 if Direct (Input) then 566 if Direct_Val (Input) >= Base then 567 return 2; 568 else 569 return 1; 570 end if; 571 572 else 573 return Uints.Table (Input).Length; 574 end if; 575 end N_Digits; 576 577 -------------- 578 -- Num_Bits -- 579 -------------- 580 581 function Num_Bits (Input : Uint) return Nat is 582 Bits : Nat; 583 Num : Nat; 584 585 begin 586 -- Largest negative number has to be handled specially, since it is in 587 -- Int_Range, but we cannot take the absolute value. 588 589 if Input = Uint_Int_First then 590 return Int'Size; 591 592 -- For any other number in Int_Range, get absolute value of number 593 594 elsif UI_Is_In_Int_Range (Input) then 595 Num := abs (UI_To_Int (Input)); 596 Bits := 0; 597 598 -- If not in Int_Range then initialize bit count for all low order 599 -- words, and set number to high order digit. 600 601 else 602 Bits := Base_Bits * (Uints.Table (Input).Length - 1); 603 Num := abs (Udigits.Table (Uints.Table (Input).Loc)); 604 end if; 605 606 -- Increase bit count for remaining value in Num 607 608 while Types.">" (Num, 0) loop 609 Num := Num / 2; 610 Bits := Bits + 1; 611 end loop; 612 613 return Bits; 614 end Num_Bits; 615 616 --------- 617 -- pid -- 618 --------- 619 620 procedure pid (Input : Uint) is 621 begin 622 UI_Write (Input, Decimal); 623 Write_Eol; 624 end pid; 625 626 --------- 627 -- pih -- 628 --------- 629 630 procedure pih (Input : Uint) is 631 begin 632 UI_Write (Input, Hex); 633 Write_Eol; 634 end pih; 635 636 ------------- 637 -- Release -- 638 ------------- 639 640 procedure Release (M : Save_Mark) is 641 begin 642 Uints.Set_Last (Uint'Max (M.Save_Uint, Uints_Min)); 643 Udigits.Set_Last (Int'Max (M.Save_Udigit, Udigits_Min)); 644 end Release; 645 646 ---------------------- 647 -- Release_And_Save -- 648 ---------------------- 649 650 procedure Release_And_Save (M : Save_Mark; UI : in out Uint) is 651 begin 652 if Direct (UI) then 653 Release (M); 654 655 else 656 declare 657 UE_Len : constant Pos := Uints.Table (UI).Length; 658 UE_Loc : constant Int := Uints.Table (UI).Loc; 659 660 UD : constant Udigits.Table_Type (1 .. UE_Len) := 661 Udigits.Table (UE_Loc .. UE_Loc + UE_Len - 1); 662 663 begin 664 Release (M); 665 666 Uints.Append ((Length => UE_Len, Loc => Udigits.Last + 1)); 667 UI := Uints.Last; 668 669 for J in 1 .. UE_Len loop 670 Udigits.Append (UD (J)); 671 end loop; 672 end; 673 end if; 674 end Release_And_Save; 675 676 procedure Release_And_Save (M : Save_Mark; UI1, UI2 : in out Uint) is 677 begin 678 if Direct (UI1) then 679 Release_And_Save (M, UI2); 680 681 elsif Direct (UI2) then 682 Release_And_Save (M, UI1); 683 684 else 685 declare 686 UE1_Len : constant Pos := Uints.Table (UI1).Length; 687 UE1_Loc : constant Int := Uints.Table (UI1).Loc; 688 689 UD1 : constant Udigits.Table_Type (1 .. UE1_Len) := 690 Udigits.Table (UE1_Loc .. UE1_Loc + UE1_Len - 1); 691 692 UE2_Len : constant Pos := Uints.Table (UI2).Length; 693 UE2_Loc : constant Int := Uints.Table (UI2).Loc; 694 695 UD2 : constant Udigits.Table_Type (1 .. UE2_Len) := 696 Udigits.Table (UE2_Loc .. UE2_Loc + UE2_Len - 1); 697 698 begin 699 Release (M); 700 701 Uints.Append ((Length => UE1_Len, Loc => Udigits.Last + 1)); 702 UI1 := Uints.Last; 703 704 for J in 1 .. UE1_Len loop 705 Udigits.Append (UD1 (J)); 706 end loop; 707 708 Uints.Append ((Length => UE2_Len, Loc => Udigits.Last + 1)); 709 UI2 := Uints.Last; 710 711 for J in 1 .. UE2_Len loop 712 Udigits.Append (UD2 (J)); 713 end loop; 714 end; 715 end if; 716 end Release_And_Save; 717 718 --------------- 719 -- Tree_Read -- 720 --------------- 721 722 procedure Tree_Read is 723 begin 724 Uints.Tree_Read; 725 Udigits.Tree_Read; 726 727 Tree_Read_Int (Int (Uint_Int_First)); 728 Tree_Read_Int (Int (Uint_Int_Last)); 729 Tree_Read_Int (UI_Power_2_Set); 730 Tree_Read_Int (UI_Power_10_Set); 731 Tree_Read_Int (Int (Uints_Min)); 732 Tree_Read_Int (Udigits_Min); 733 734 for J in 0 .. UI_Power_2_Set loop 735 Tree_Read_Int (Int (UI_Power_2 (J))); 736 end loop; 737 738 for J in 0 .. UI_Power_10_Set loop 739 Tree_Read_Int (Int (UI_Power_10 (J))); 740 end loop; 741 742 end Tree_Read; 743 744 ---------------- 745 -- Tree_Write -- 746 ---------------- 747 748 procedure Tree_Write is 749 begin 750 Uints.Tree_Write; 751 Udigits.Tree_Write; 752 753 Tree_Write_Int (Int (Uint_Int_First)); 754 Tree_Write_Int (Int (Uint_Int_Last)); 755 Tree_Write_Int (UI_Power_2_Set); 756 Tree_Write_Int (UI_Power_10_Set); 757 Tree_Write_Int (Int (Uints_Min)); 758 Tree_Write_Int (Udigits_Min); 759 760 for J in 0 .. UI_Power_2_Set loop 761 Tree_Write_Int (Int (UI_Power_2 (J))); 762 end loop; 763 764 for J in 0 .. UI_Power_10_Set loop 765 Tree_Write_Int (Int (UI_Power_10 (J))); 766 end loop; 767 768 end Tree_Write; 769 770 ------------- 771 -- UI_Abs -- 772 ------------- 773 774 function UI_Abs (Right : Uint) return Uint is 775 begin 776 if Right < Uint_0 then 777 return -Right; 778 else 779 return Right; 780 end if; 781 end UI_Abs; 782 783 ------------- 784 -- UI_Add -- 785 ------------- 786 787 function UI_Add (Left : Int; Right : Uint) return Uint is 788 begin 789 return UI_Add (UI_From_Int (Left), Right); 790 end UI_Add; 791 792 function UI_Add (Left : Uint; Right : Int) return Uint is 793 begin 794 return UI_Add (Left, UI_From_Int (Right)); 795 end UI_Add; 796 797 function UI_Add (Left : Uint; Right : Uint) return Uint is 798 begin 799 -- Simple cases of direct operands and addition of zero 800 801 if Direct (Left) then 802 if Direct (Right) then 803 return UI_From_Int (Direct_Val (Left) + Direct_Val (Right)); 804 805 elsif Int (Left) = Int (Uint_0) then 806 return Right; 807 end if; 808 809 elsif Direct (Right) and then Int (Right) = Int (Uint_0) then 810 return Left; 811 end if; 812 813 -- Otherwise full circuit is needed 814 815 declare 816 L_Length : constant Int := N_Digits (Left); 817 R_Length : constant Int := N_Digits (Right); 818 L_Vec : UI_Vector (1 .. L_Length); 819 R_Vec : UI_Vector (1 .. R_Length); 820 Sum_Length : Int; 821 Tmp_Int : Int; 822 Carry : Int; 823 Borrow : Int; 824 X_Bigger : Boolean := False; 825 Y_Bigger : Boolean := False; 826 Result_Neg : Boolean := False; 827 828 begin 829 Init_Operand (Left, L_Vec); 830 Init_Operand (Right, R_Vec); 831 832 -- At least one of the two operands is in multi-digit form. 833 -- Calculate the number of digits sufficient to hold result. 834 835 if L_Length > R_Length then 836 Sum_Length := L_Length + 1; 837 X_Bigger := True; 838 else 839 Sum_Length := R_Length + 1; 840 841 if R_Length > L_Length then 842 Y_Bigger := True; 843 end if; 844 end if; 845 846 -- Make copies of the absolute values of L_Vec and R_Vec into X and Y 847 -- both with lengths equal to the maximum possibly needed. This makes 848 -- looping over the digits much simpler. 849 850 declare 851 X : UI_Vector (1 .. Sum_Length); 852 Y : UI_Vector (1 .. Sum_Length); 853 Tmp_UI : UI_Vector (1 .. Sum_Length); 854 855 begin 856 for J in 1 .. Sum_Length - L_Length loop 857 X (J) := 0; 858 end loop; 859 860 X (Sum_Length - L_Length + 1) := abs L_Vec (1); 861 862 for J in 2 .. L_Length loop 863 X (J + (Sum_Length - L_Length)) := L_Vec (J); 864 end loop; 865 866 for J in 1 .. Sum_Length - R_Length loop 867 Y (J) := 0; 868 end loop; 869 870 Y (Sum_Length - R_Length + 1) := abs R_Vec (1); 871 872 for J in 2 .. R_Length loop 873 Y (J + (Sum_Length - R_Length)) := R_Vec (J); 874 end loop; 875 876 if (L_Vec (1) < Int_0) = (R_Vec (1) < Int_0) then 877 878 -- Same sign so just add 879 880 Carry := 0; 881 for J in reverse 1 .. Sum_Length loop 882 Tmp_Int := X (J) + Y (J) + Carry; 883 884 if Tmp_Int >= Base then 885 Tmp_Int := Tmp_Int - Base; 886 Carry := 1; 887 else 888 Carry := 0; 889 end if; 890 891 X (J) := Tmp_Int; 892 end loop; 893 894 return Vector_To_Uint (X, L_Vec (1) < Int_0); 895 896 else 897 -- Find which one has bigger magnitude 898 899 if not (X_Bigger or Y_Bigger) then 900 for J in L_Vec'Range loop 901 if abs L_Vec (J) > abs R_Vec (J) then 902 X_Bigger := True; 903 exit; 904 elsif abs R_Vec (J) > abs L_Vec (J) then 905 Y_Bigger := True; 906 exit; 907 end if; 908 end loop; 909 end if; 910 911 -- If they have identical magnitude, just return 0, else swap 912 -- if necessary so that X had the bigger magnitude. Determine 913 -- if result is negative at this time. 914 915 Result_Neg := False; 916 917 if not (X_Bigger or Y_Bigger) then 918 return Uint_0; 919 920 elsif Y_Bigger then 921 if R_Vec (1) < Int_0 then 922 Result_Neg := True; 923 end if; 924 925 Tmp_UI := X; 926 X := Y; 927 Y := Tmp_UI; 928 929 else 930 if L_Vec (1) < Int_0 then 931 Result_Neg := True; 932 end if; 933 end if; 934 935 -- Subtract Y from the bigger X 936 937 Borrow := 0; 938 939 for J in reverse 1 .. Sum_Length loop 940 Tmp_Int := X (J) - Y (J) + Borrow; 941 942 if Tmp_Int < Int_0 then 943 Tmp_Int := Tmp_Int + Base; 944 Borrow := -1; 945 else 946 Borrow := 0; 947 end if; 948 949 X (J) := Tmp_Int; 950 end loop; 951 952 return Vector_To_Uint (X, Result_Neg); 953 954 end if; 955 end; 956 end; 957 end UI_Add; 958 959 -------------------------- 960 -- UI_Decimal_Digits_Hi -- 961 -------------------------- 962 963 function UI_Decimal_Digits_Hi (U : Uint) return Nat is 964 begin 965 -- The maximum value of a "digit" is 32767, which is 5 decimal digits, 966 -- so an N_Digit number could take up to 5 times this number of digits. 967 -- This is certainly too high for large numbers but it is not worth 968 -- worrying about. 969 970 return 5 * N_Digits (U); 971 end UI_Decimal_Digits_Hi; 972 973 -------------------------- 974 -- UI_Decimal_Digits_Lo -- 975 -------------------------- 976 977 function UI_Decimal_Digits_Lo (U : Uint) return Nat is 978 begin 979 -- The maximum value of a "digit" is 32767, which is more than four 980 -- decimal digits, but not a full five digits. The easily computed 981 -- minimum number of decimal digits is thus 1 + 4 * the number of 982 -- digits. This is certainly too low for large numbers but it is not 983 -- worth worrying about. 984 985 return 1 + 4 * (N_Digits (U) - 1); 986 end UI_Decimal_Digits_Lo; 987 988 ------------ 989 -- UI_Div -- 990 ------------ 991 992 function UI_Div (Left : Int; Right : Uint) return Uint is 993 begin 994 return UI_Div (UI_From_Int (Left), Right); 995 end UI_Div; 996 997 function UI_Div (Left : Uint; Right : Int) return Uint is 998 begin 999 return UI_Div (Left, UI_From_Int (Right)); 1000 end UI_Div; 1001 1002 function UI_Div (Left, Right : Uint) return Uint is 1003 Quotient : Uint; 1004 Remainder : Uint; 1005 pragma Warnings (Off, Remainder); 1006 begin 1007 UI_Div_Rem 1008 (Left, Right, 1009 Quotient, Remainder, 1010 Discard_Remainder => True); 1011 return Quotient; 1012 end UI_Div; 1013 1014 ---------------- 1015 -- UI_Div_Rem -- 1016 ---------------- 1017 1018 procedure UI_Div_Rem 1019 (Left, Right : Uint; 1020 Quotient : out Uint; 1021 Remainder : out Uint; 1022 Discard_Quotient : Boolean := False; 1023 Discard_Remainder : Boolean := False) 1024 is 1025 begin 1026 pragma Assert (Right /= Uint_0); 1027 1028 Quotient := No_Uint; 1029 Remainder := No_Uint; 1030 1031 -- Cases where both operands are represented directly 1032 1033 if Direct (Left) and then Direct (Right) then 1034 declare 1035 DV_Left : constant Int := Direct_Val (Left); 1036 DV_Right : constant Int := Direct_Val (Right); 1037 1038 begin 1039 if not Discard_Quotient then 1040 Quotient := UI_From_Int (DV_Left / DV_Right); 1041 end if; 1042 1043 if not Discard_Remainder then 1044 Remainder := UI_From_Int (DV_Left rem DV_Right); 1045 end if; 1046 1047 return; 1048 end; 1049 end if; 1050 1051 declare 1052 L_Length : constant Int := N_Digits (Left); 1053 R_Length : constant Int := N_Digits (Right); 1054 Q_Length : constant Int := L_Length - R_Length + 1; 1055 L_Vec : UI_Vector (1 .. L_Length); 1056 R_Vec : UI_Vector (1 .. R_Length); 1057 D : Int; 1058 Remainder_I : Int; 1059 Tmp_Divisor : Int; 1060 Carry : Int; 1061 Tmp_Int : Int; 1062 Tmp_Dig : Int; 1063 1064 procedure UI_Div_Vector 1065 (L_Vec : UI_Vector; 1066 R_Int : Int; 1067 Quotient : out UI_Vector; 1068 Remainder : out Int); 1069 pragma Inline (UI_Div_Vector); 1070 -- Specialised variant for case where the divisor is a single digit 1071 1072 procedure UI_Div_Vector 1073 (L_Vec : UI_Vector; 1074 R_Int : Int; 1075 Quotient : out UI_Vector; 1076 Remainder : out Int) 1077 is 1078 Tmp_Int : Int; 1079 1080 begin 1081 Remainder := 0; 1082 for J in L_Vec'Range loop 1083 Tmp_Int := Remainder * Base + abs L_Vec (J); 1084 Quotient (Quotient'First + J - L_Vec'First) := Tmp_Int / R_Int; 1085 Remainder := Tmp_Int rem R_Int; 1086 end loop; 1087 1088 if L_Vec (L_Vec'First) < Int_0 then 1089 Remainder := -Remainder; 1090 end if; 1091 end UI_Div_Vector; 1092 1093 -- Start of processing for UI_Div_Rem 1094 1095 begin 1096 -- Result is zero if left operand is shorter than right 1097 1098 if L_Length < R_Length then 1099 if not Discard_Quotient then 1100 Quotient := Uint_0; 1101 end if; 1102 1103 if not Discard_Remainder then 1104 Remainder := Left; 1105 end if; 1106 1107 return; 1108 end if; 1109 1110 Init_Operand (Left, L_Vec); 1111 Init_Operand (Right, R_Vec); 1112 1113 -- Case of right operand is single digit. Here we can simply divide 1114 -- each digit of the left operand by the divisor, from most to least 1115 -- significant, carrying the remainder to the next digit (just like 1116 -- ordinary long division by hand). 1117 1118 if R_Length = Int_1 then 1119 Tmp_Divisor := abs R_Vec (1); 1120 1121 declare 1122 Quotient_V : UI_Vector (1 .. L_Length); 1123 1124 begin 1125 UI_Div_Vector (L_Vec, Tmp_Divisor, Quotient_V, Remainder_I); 1126 1127 if not Discard_Quotient then 1128 Quotient := 1129 Vector_To_Uint 1130 (Quotient_V, (L_Vec (1) < Int_0 xor R_Vec (1) < Int_0)); 1131 end if; 1132 1133 if not Discard_Remainder then 1134 Remainder := UI_From_Int (Remainder_I); 1135 end if; 1136 1137 return; 1138 end; 1139 end if; 1140 1141 -- The possible simple cases have been exhausted. Now turn to the 1142 -- algorithm D from the section of Knuth mentioned at the top of 1143 -- this package. 1144 1145 Algorithm_D : declare 1146 Dividend : UI_Vector (1 .. L_Length + 1); 1147 Divisor : UI_Vector (1 .. R_Length); 1148 Quotient_V : UI_Vector (1 .. Q_Length); 1149 Divisor_Dig1 : Int; 1150 Divisor_Dig2 : Int; 1151 Q_Guess : Int; 1152 R_Guess : Int; 1153 1154 begin 1155 -- [ NORMALIZE ] (step D1 in the algorithm). First calculate the 1156 -- scale d, and then multiply Left and Right (u and v in the book) 1157 -- by d to get the dividend and divisor to work with. 1158 1159 D := Base / (abs R_Vec (1) + 1); 1160 1161 Dividend (1) := 0; 1162 Dividend (2) := abs L_Vec (1); 1163 1164 for J in 3 .. L_Length + Int_1 loop 1165 Dividend (J) := L_Vec (J - 1); 1166 end loop; 1167 1168 Divisor (1) := abs R_Vec (1); 1169 1170 for J in Int_2 .. R_Length loop 1171 Divisor (J) := R_Vec (J); 1172 end loop; 1173 1174 if D > Int_1 then 1175 1176 -- Multiply Dividend by d 1177 1178 Carry := 0; 1179 for J in reverse Dividend'Range loop 1180 Tmp_Int := Dividend (J) * D + Carry; 1181 Dividend (J) := Tmp_Int rem Base; 1182 Carry := Tmp_Int / Base; 1183 end loop; 1184 1185 -- Multiply Divisor by d 1186 1187 Carry := 0; 1188 for J in reverse Divisor'Range loop 1189 Tmp_Int := Divisor (J) * D + Carry; 1190 Divisor (J) := Tmp_Int rem Base; 1191 Carry := Tmp_Int / Base; 1192 end loop; 1193 end if; 1194 1195 -- Main loop of long division algorithm 1196 1197 Divisor_Dig1 := Divisor (1); 1198 Divisor_Dig2 := Divisor (2); 1199 1200 for J in Quotient_V'Range loop 1201 1202 -- [ CALCULATE Q (hat) ] (step D3 in the algorithm) 1203 1204 -- Note: this version of step D3 is from the original published 1205 -- algorithm, which is known to have a bug causing overflows. 1206 -- See: http://www-cs-faculty.stanford.edu/~uno/err2-2e.ps.gz 1207 -- and http://www-cs-faculty.stanford.edu/~uno/all2-pre.ps.gz. 1208 -- The code below is the fixed version of this step. 1209 1210 Tmp_Int := Dividend (J) * Base + Dividend (J + 1); 1211 1212 -- Initial guess 1213 1214 Q_Guess := Tmp_Int / Divisor_Dig1; 1215 R_Guess := Tmp_Int rem Divisor_Dig1; 1216 1217 -- Refine the guess 1218 1219 while Q_Guess >= Base 1220 or else Divisor_Dig2 * Q_Guess > 1221 R_Guess * Base + Dividend (J + 2) 1222 loop 1223 Q_Guess := Q_Guess - 1; 1224 R_Guess := R_Guess + Divisor_Dig1; 1225 exit when R_Guess >= Base; 1226 end loop; 1227 1228 -- [ MULTIPLY & SUBTRACT ] (step D4). Q_Guess * Divisor is 1229 -- subtracted from the remaining dividend. 1230 1231 Carry := 0; 1232 for K in reverse Divisor'Range loop 1233 Tmp_Int := Dividend (J + K) - Q_Guess * Divisor (K) + Carry; 1234 Tmp_Dig := Tmp_Int rem Base; 1235 Carry := Tmp_Int / Base; 1236 1237 if Tmp_Dig < Int_0 then 1238 Tmp_Dig := Tmp_Dig + Base; 1239 Carry := Carry - 1; 1240 end if; 1241 1242 Dividend (J + K) := Tmp_Dig; 1243 end loop; 1244 1245 Dividend (J) := Dividend (J) + Carry; 1246 1247 -- [ TEST REMAINDER ] & [ ADD BACK ] (steps D5 and D6) 1248 1249 -- Here there is a slight difference from the book: the last 1250 -- carry is always added in above and below (cancelling each 1251 -- other). In fact the dividend going negative is used as 1252 -- the test. 1253 1254 -- If the Dividend went negative, then Q_Guess was off by 1255 -- one, so it is decremented, and the divisor is added back 1256 -- into the relevant portion of the dividend. 1257 1258 if Dividend (J) < Int_0 then 1259 Q_Guess := Q_Guess - 1; 1260 1261 Carry := 0; 1262 for K in reverse Divisor'Range loop 1263 Tmp_Int := Dividend (J + K) + Divisor (K) + Carry; 1264 1265 if Tmp_Int >= Base then 1266 Tmp_Int := Tmp_Int - Base; 1267 Carry := 1; 1268 else 1269 Carry := 0; 1270 end if; 1271 1272 Dividend (J + K) := Tmp_Int; 1273 end loop; 1274 1275 Dividend (J) := Dividend (J) + Carry; 1276 end if; 1277 1278 -- Finally we can get the next quotient digit 1279 1280 Quotient_V (J) := Q_Guess; 1281 end loop; 1282 1283 -- [ UNNORMALIZE ] (step D8) 1284 1285 if not Discard_Quotient then 1286 Quotient := Vector_To_Uint 1287 (Quotient_V, (L_Vec (1) < Int_0 xor R_Vec (1) < Int_0)); 1288 end if; 1289 1290 if not Discard_Remainder then 1291 declare 1292 Remainder_V : UI_Vector (1 .. R_Length); 1293 Discard_Int : Int; 1294 pragma Warnings (Off, Discard_Int); 1295 begin 1296 UI_Div_Vector 1297 (Dividend (Dividend'Last - R_Length + 1 .. Dividend'Last), 1298 D, 1299 Remainder_V, Discard_Int); 1300 Remainder := Vector_To_Uint (Remainder_V, L_Vec (1) < Int_0); 1301 end; 1302 end if; 1303 end Algorithm_D; 1304 end; 1305 end UI_Div_Rem; 1306 1307 ------------ 1308 -- UI_Eq -- 1309 ------------ 1310 1311 function UI_Eq (Left : Int; Right : Uint) return Boolean is 1312 begin 1313 return not UI_Ne (UI_From_Int (Left), Right); 1314 end UI_Eq; 1315 1316 function UI_Eq (Left : Uint; Right : Int) return Boolean is 1317 begin 1318 return not UI_Ne (Left, UI_From_Int (Right)); 1319 end UI_Eq; 1320 1321 function UI_Eq (Left : Uint; Right : Uint) return Boolean is 1322 begin 1323 return not UI_Ne (Left, Right); 1324 end UI_Eq; 1325 1326 -------------- 1327 -- UI_Expon -- 1328 -------------- 1329 1330 function UI_Expon (Left : Int; Right : Uint) return Uint is 1331 begin 1332 return UI_Expon (UI_From_Int (Left), Right); 1333 end UI_Expon; 1334 1335 function UI_Expon (Left : Uint; Right : Int) return Uint is 1336 begin 1337 return UI_Expon (Left, UI_From_Int (Right)); 1338 end UI_Expon; 1339 1340 function UI_Expon (Left : Int; Right : Int) return Uint is 1341 begin 1342 return UI_Expon (UI_From_Int (Left), UI_From_Int (Right)); 1343 end UI_Expon; 1344 1345 function UI_Expon (Left : Uint; Right : Uint) return Uint is 1346 begin 1347 pragma Assert (Right >= Uint_0); 1348 1349 -- Any value raised to power of 0 is 1 1350 1351 if Right = Uint_0 then 1352 return Uint_1; 1353 1354 -- 0 to any positive power is 0 1355 1356 elsif Left = Uint_0 then 1357 return Uint_0; 1358 1359 -- 1 to any power is 1 1360 1361 elsif Left = Uint_1 then 1362 return Uint_1; 1363 1364 -- Any value raised to power of 1 is that value 1365 1366 elsif Right = Uint_1 then 1367 return Left; 1368 1369 -- Cases which can be done by table lookup 1370 1371 elsif Right <= Uint_64 then 1372 1373 -- 2 ** N for N in 2 .. 64 1374 1375 if Left = Uint_2 then 1376 declare 1377 Right_Int : constant Int := Direct_Val (Right); 1378 1379 begin 1380 if Right_Int > UI_Power_2_Set then 1381 for J in UI_Power_2_Set + Int_1 .. Right_Int loop 1382 UI_Power_2 (J) := UI_Power_2 (J - Int_1) * Int_2; 1383 Uints_Min := Uints.Last; 1384 Udigits_Min := Udigits.Last; 1385 end loop; 1386 1387 UI_Power_2_Set := Right_Int; 1388 end if; 1389 1390 return UI_Power_2 (Right_Int); 1391 end; 1392 1393 -- 10 ** N for N in 2 .. 64 1394 1395 elsif Left = Uint_10 then 1396 declare 1397 Right_Int : constant Int := Direct_Val (Right); 1398 1399 begin 1400 if Right_Int > UI_Power_10_Set then 1401 for J in UI_Power_10_Set + Int_1 .. Right_Int loop 1402 UI_Power_10 (J) := UI_Power_10 (J - Int_1) * Int (10); 1403 Uints_Min := Uints.Last; 1404 Udigits_Min := Udigits.Last; 1405 end loop; 1406 1407 UI_Power_10_Set := Right_Int; 1408 end if; 1409 1410 return UI_Power_10 (Right_Int); 1411 end; 1412 end if; 1413 end if; 1414 1415 -- If we fall through, then we have the general case (see Knuth 4.6.3) 1416 1417 declare 1418 N : Uint := Right; 1419 Squares : Uint := Left; 1420 Result : Uint := Uint_1; 1421 M : constant Uintp.Save_Mark := Uintp.Mark; 1422 1423 begin 1424 loop 1425 if (Least_Sig_Digit (N) mod Int_2) = Int_1 then 1426 Result := Result * Squares; 1427 end if; 1428 1429 N := N / Uint_2; 1430 exit when N = Uint_0; 1431 Squares := Squares * Squares; 1432 end loop; 1433 1434 Uintp.Release_And_Save (M, Result); 1435 return Result; 1436 end; 1437 end UI_Expon; 1438 1439 ---------------- 1440 -- UI_From_CC -- 1441 ---------------- 1442 1443 function UI_From_CC (Input : Char_Code) return Uint is 1444 begin 1445 return UI_From_Int (Int (Input)); 1446 end UI_From_CC; 1447 1448 ----------------- 1449 -- UI_From_Int -- 1450 ----------------- 1451 1452 function UI_From_Int (Input : Int) return Uint is 1453 U : Uint; 1454 1455 begin 1456 if Min_Direct <= Input and then Input <= Max_Direct then 1457 return Uint (Int (Uint_Direct_Bias) + Input); 1458 end if; 1459 1460 -- If already in the hash table, return entry 1461 1462 U := UI_Ints.Get (Input); 1463 1464 if U /= No_Uint then 1465 return U; 1466 end if; 1467 1468 -- For values of larger magnitude, compute digits into a vector and call 1469 -- Vector_To_Uint. 1470 1471 declare 1472 Max_For_Int : constant := 3; 1473 -- Base is defined so that 3 Uint digits is sufficient to hold the 1474 -- largest possible Int value. 1475 1476 V : UI_Vector (1 .. Max_For_Int); 1477 1478 Temp_Integer : Int := Input; 1479 1480 begin 1481 for J in reverse V'Range loop 1482 V (J) := abs (Temp_Integer rem Base); 1483 Temp_Integer := Temp_Integer / Base; 1484 end loop; 1485 1486 U := Vector_To_Uint (V, Input < Int_0); 1487 UI_Ints.Set (Input, U); 1488 Uints_Min := Uints.Last; 1489 Udigits_Min := Udigits.Last; 1490 return U; 1491 end; 1492 end UI_From_Int; 1493 1494 ------------ 1495 -- UI_GCD -- 1496 ------------ 1497 1498 -- Lehmer's algorithm for GCD 1499 1500 -- The idea is to avoid using multiple precision arithmetic wherever 1501 -- possible, substituting Int arithmetic instead. See Knuth volume II, 1502 -- Algorithm L (page 329). 1503 1504 -- We use the same notation as Knuth (U_Hat standing for the obvious) 1505 1506 function UI_GCD (Uin, Vin : Uint) return Uint is 1507 U, V : Uint; 1508 -- Copies of Uin and Vin 1509 1510 U_Hat, V_Hat : Int; 1511 -- The most Significant digits of U,V 1512 1513 A, B, C, D, T, Q, Den1, Den2 : Int; 1514 1515 Tmp_UI : Uint; 1516 Marks : constant Uintp.Save_Mark := Uintp.Mark; 1517 Iterations : Integer := 0; 1518 1519 begin 1520 pragma Assert (Uin >= Vin); 1521 pragma Assert (Vin >= Uint_0); 1522 1523 U := Uin; 1524 V := Vin; 1525 1526 loop 1527 Iterations := Iterations + 1; 1528 1529 if Direct (V) then 1530 if V = Uint_0 then 1531 return U; 1532 else 1533 return 1534 UI_From_Int (GCD (Direct_Val (V), UI_To_Int (U rem V))); 1535 end if; 1536 end if; 1537 1538 Most_Sig_2_Digits (U, V, U_Hat, V_Hat); 1539 A := 1; 1540 B := 0; 1541 C := 0; 1542 D := 1; 1543 1544 loop 1545 -- We might overflow and get division by zero here. This just 1546 -- means we cannot take the single precision step 1547 1548 Den1 := V_Hat + C; 1549 Den2 := V_Hat + D; 1550 exit when Den1 = Int_0 or else Den2 = Int_0; 1551 1552 -- Compute Q, the trial quotient 1553 1554 Q := (U_Hat + A) / Den1; 1555 1556 exit when Q /= ((U_Hat + B) / Den2); 1557 1558 -- A single precision step Euclid step will give same answer as a 1559 -- multiprecision one. 1560 1561 T := A - (Q * C); 1562 A := C; 1563 C := T; 1564 1565 T := B - (Q * D); 1566 B := D; 1567 D := T; 1568 1569 T := U_Hat - (Q * V_Hat); 1570 U_Hat := V_Hat; 1571 V_Hat := T; 1572 1573 end loop; 1574 1575 -- Take a multiprecision Euclid step 1576 1577 if B = Int_0 then 1578 1579 -- No single precision steps take a regular Euclid step 1580 1581 Tmp_UI := U rem V; 1582 U := V; 1583 V := Tmp_UI; 1584 1585 else 1586 -- Use prior single precision steps to compute this Euclid step 1587 1588 -- For constructs such as: 1589 -- sqrt_2: constant := 1.41421_35623_73095_04880_16887_24209_698; 1590 -- sqrt_eps: constant long_float := long_float( 1.0 / sqrt_2) 1591 -- ** long_float'machine_mantissa; 1592 -- 1593 -- we spend 80% of our time working on this step. Perhaps we need 1594 -- a special case Int / Uint dot product to speed things up. ??? 1595 1596 -- Alternatively we could increase the single precision iterations 1597 -- to handle Uint's of some small size ( <5 digits?). Then we 1598 -- would have more iterations on small Uint. On the code above, we 1599 -- only get 5 (on average) single precision iterations per large 1600 -- iteration. ??? 1601 1602 Tmp_UI := (UI_From_Int (A) * U) + (UI_From_Int (B) * V); 1603 V := (UI_From_Int (C) * U) + (UI_From_Int (D) * V); 1604 U := Tmp_UI; 1605 end if; 1606 1607 -- If the operands are very different in magnitude, the loop will 1608 -- generate large amounts of short-lived data, which it is worth 1609 -- removing periodically. 1610 1611 if Iterations > 100 then 1612 Release_And_Save (Marks, U, V); 1613 Iterations := 0; 1614 end if; 1615 end loop; 1616 end UI_GCD; 1617 1618 ------------ 1619 -- UI_Ge -- 1620 ------------ 1621 1622 function UI_Ge (Left : Int; Right : Uint) return Boolean is 1623 begin 1624 return not UI_Lt (UI_From_Int (Left), Right); 1625 end UI_Ge; 1626 1627 function UI_Ge (Left : Uint; Right : Int) return Boolean is 1628 begin 1629 return not UI_Lt (Left, UI_From_Int (Right)); 1630 end UI_Ge; 1631 1632 function UI_Ge (Left : Uint; Right : Uint) return Boolean is 1633 begin 1634 return not UI_Lt (Left, Right); 1635 end UI_Ge; 1636 1637 ------------ 1638 -- UI_Gt -- 1639 ------------ 1640 1641 function UI_Gt (Left : Int; Right : Uint) return Boolean is 1642 begin 1643 return UI_Lt (Right, UI_From_Int (Left)); 1644 end UI_Gt; 1645 1646 function UI_Gt (Left : Uint; Right : Int) return Boolean is 1647 begin 1648 return UI_Lt (UI_From_Int (Right), Left); 1649 end UI_Gt; 1650 1651 function UI_Gt (Left : Uint; Right : Uint) return Boolean is 1652 begin 1653 return UI_Lt (Left => Right, Right => Left); 1654 end UI_Gt; 1655 1656 --------------- 1657 -- UI_Image -- 1658 --------------- 1659 1660 procedure UI_Image (Input : Uint; Format : UI_Format := Auto) is 1661 begin 1662 Image_Out (Input, True, Format); 1663 end UI_Image; 1664 1665 function UI_Image 1666 (Input : Uint; 1667 Format : UI_Format := Auto) return String 1668 is 1669 begin 1670 Image_Out (Input, True, Format); 1671 return UI_Image_Buffer (1 .. UI_Image_Length); 1672 end UI_Image; 1673 1674 ------------------------- 1675 -- UI_Is_In_Int_Range -- 1676 ------------------------- 1677 1678 function UI_Is_In_Int_Range (Input : Uint) return Boolean is 1679 begin 1680 -- Make sure we don't get called before Initialize 1681 1682 pragma Assert (Uint_Int_First /= Uint_0); 1683 1684 if Direct (Input) then 1685 return True; 1686 else 1687 return Input >= Uint_Int_First 1688 and then Input <= Uint_Int_Last; 1689 end if; 1690 end UI_Is_In_Int_Range; 1691 1692 ------------ 1693 -- UI_Le -- 1694 ------------ 1695 1696 function UI_Le (Left : Int; Right : Uint) return Boolean is 1697 begin 1698 return not UI_Lt (Right, UI_From_Int (Left)); 1699 end UI_Le; 1700 1701 function UI_Le (Left : Uint; Right : Int) return Boolean is 1702 begin 1703 return not UI_Lt (UI_From_Int (Right), Left); 1704 end UI_Le; 1705 1706 function UI_Le (Left : Uint; Right : Uint) return Boolean is 1707 begin 1708 return not UI_Lt (Left => Right, Right => Left); 1709 end UI_Le; 1710 1711 ------------ 1712 -- UI_Lt -- 1713 ------------ 1714 1715 function UI_Lt (Left : Int; Right : Uint) return Boolean is 1716 begin 1717 return UI_Lt (UI_From_Int (Left), Right); 1718 end UI_Lt; 1719 1720 function UI_Lt (Left : Uint; Right : Int) return Boolean is 1721 begin 1722 return UI_Lt (Left, UI_From_Int (Right)); 1723 end UI_Lt; 1724 1725 function UI_Lt (Left : Uint; Right : Uint) return Boolean is 1726 begin 1727 -- Quick processing for identical arguments 1728 1729 if Int (Left) = Int (Right) then 1730 return False; 1731 1732 -- Quick processing for both arguments directly represented 1733 1734 elsif Direct (Left) and then Direct (Right) then 1735 return Int (Left) < Int (Right); 1736 1737 -- At least one argument is more than one digit long 1738 1739 else 1740 declare 1741 L_Length : constant Int := N_Digits (Left); 1742 R_Length : constant Int := N_Digits (Right); 1743 1744 L_Vec : UI_Vector (1 .. L_Length); 1745 R_Vec : UI_Vector (1 .. R_Length); 1746 1747 begin 1748 Init_Operand (Left, L_Vec); 1749 Init_Operand (Right, R_Vec); 1750 1751 if L_Vec (1) < Int_0 then 1752 1753 -- First argument negative, second argument non-negative 1754 1755 if R_Vec (1) >= Int_0 then 1756 return True; 1757 1758 -- Both arguments negative 1759 1760 else 1761 if L_Length /= R_Length then 1762 return L_Length > R_Length; 1763 1764 elsif L_Vec (1) /= R_Vec (1) then 1765 return L_Vec (1) < R_Vec (1); 1766 1767 else 1768 for J in 2 .. L_Vec'Last loop 1769 if L_Vec (J) /= R_Vec (J) then 1770 return L_Vec (J) > R_Vec (J); 1771 end if; 1772 end loop; 1773 1774 return False; 1775 end if; 1776 end if; 1777 1778 else 1779 -- First argument non-negative, second argument negative 1780 1781 if R_Vec (1) < Int_0 then 1782 return False; 1783 1784 -- Both arguments non-negative 1785 1786 else 1787 if L_Length /= R_Length then 1788 return L_Length < R_Length; 1789 else 1790 for J in L_Vec'Range loop 1791 if L_Vec (J) /= R_Vec (J) then 1792 return L_Vec (J) < R_Vec (J); 1793 end if; 1794 end loop; 1795 1796 return False; 1797 end if; 1798 end if; 1799 end if; 1800 end; 1801 end if; 1802 end UI_Lt; 1803 1804 ------------ 1805 -- UI_Max -- 1806 ------------ 1807 1808 function UI_Max (Left : Int; Right : Uint) return Uint is 1809 begin 1810 return UI_Max (UI_From_Int (Left), Right); 1811 end UI_Max; 1812 1813 function UI_Max (Left : Uint; Right : Int) return Uint is 1814 begin 1815 return UI_Max (Left, UI_From_Int (Right)); 1816 end UI_Max; 1817 1818 function UI_Max (Left : Uint; Right : Uint) return Uint is 1819 begin 1820 if Left >= Right then 1821 return Left; 1822 else 1823 return Right; 1824 end if; 1825 end UI_Max; 1826 1827 ------------ 1828 -- UI_Min -- 1829 ------------ 1830 1831 function UI_Min (Left : Int; Right : Uint) return Uint is 1832 begin 1833 return UI_Min (UI_From_Int (Left), Right); 1834 end UI_Min; 1835 1836 function UI_Min (Left : Uint; Right : Int) return Uint is 1837 begin 1838 return UI_Min (Left, UI_From_Int (Right)); 1839 end UI_Min; 1840 1841 function UI_Min (Left : Uint; Right : Uint) return Uint is 1842 begin 1843 if Left <= Right then 1844 return Left; 1845 else 1846 return Right; 1847 end if; 1848 end UI_Min; 1849 1850 ------------- 1851 -- UI_Mod -- 1852 ------------- 1853 1854 function UI_Mod (Left : Int; Right : Uint) return Uint is 1855 begin 1856 return UI_Mod (UI_From_Int (Left), Right); 1857 end UI_Mod; 1858 1859 function UI_Mod (Left : Uint; Right : Int) return Uint is 1860 begin 1861 return UI_Mod (Left, UI_From_Int (Right)); 1862 end UI_Mod; 1863 1864 function UI_Mod (Left : Uint; Right : Uint) return Uint is 1865 Urem : constant Uint := Left rem Right; 1866 1867 begin 1868 if (Left < Uint_0) = (Right < Uint_0) 1869 or else Urem = Uint_0 1870 then 1871 return Urem; 1872 else 1873 return Right + Urem; 1874 end if; 1875 end UI_Mod; 1876 1877 ------------------------------- 1878 -- UI_Modular_Exponentiation -- 1879 ------------------------------- 1880 1881 function UI_Modular_Exponentiation 1882 (B : Uint; 1883 E : Uint; 1884 Modulo : Uint) return Uint 1885 is 1886 M : constant Save_Mark := Mark; 1887 1888 Result : Uint := Uint_1; 1889 Base : Uint := B; 1890 Exponent : Uint := E; 1891 1892 begin 1893 while Exponent /= Uint_0 loop 1894 if Least_Sig_Digit (Exponent) rem Int'(2) = Int'(1) then 1895 Result := (Result * Base) rem Modulo; 1896 end if; 1897 1898 Exponent := Exponent / Uint_2; 1899 Base := (Base * Base) rem Modulo; 1900 end loop; 1901 1902 Release_And_Save (M, Result); 1903 return Result; 1904 end UI_Modular_Exponentiation; 1905 1906 ------------------------ 1907 -- UI_Modular_Inverse -- 1908 ------------------------ 1909 1910 function UI_Modular_Inverse (N : Uint; Modulo : Uint) return Uint is 1911 M : constant Save_Mark := Mark; 1912 U : Uint; 1913 V : Uint; 1914 Q : Uint; 1915 R : Uint; 1916 X : Uint; 1917 Y : Uint; 1918 T : Uint; 1919 S : Int := 1; 1920 1921 begin 1922 U := Modulo; 1923 V := N; 1924 1925 X := Uint_1; 1926 Y := Uint_0; 1927 1928 loop 1929 UI_Div_Rem (U, V, Quotient => Q, Remainder => R); 1930 1931 U := V; 1932 V := R; 1933 1934 T := X; 1935 X := Y + Q * X; 1936 Y := T; 1937 S := -S; 1938 1939 exit when R = Uint_1; 1940 end loop; 1941 1942 if S = Int'(-1) then 1943 X := Modulo - X; 1944 end if; 1945 1946 Release_And_Save (M, X); 1947 return X; 1948 end UI_Modular_Inverse; 1949 1950 ------------ 1951 -- UI_Mul -- 1952 ------------ 1953 1954 function UI_Mul (Left : Int; Right : Uint) return Uint is 1955 begin 1956 return UI_Mul (UI_From_Int (Left), Right); 1957 end UI_Mul; 1958 1959 function UI_Mul (Left : Uint; Right : Int) return Uint is 1960 begin 1961 return UI_Mul (Left, UI_From_Int (Right)); 1962 end UI_Mul; 1963 1964 function UI_Mul (Left : Uint; Right : Uint) return Uint is 1965 begin 1966 -- Case where product fits in the range of a 32-bit integer 1967 1968 if Int (Left) <= Int (Uint_Max_Simple_Mul) 1969 and then 1970 Int (Right) <= Int (Uint_Max_Simple_Mul) 1971 then 1972 return UI_From_Int (Direct_Val (Left) * Direct_Val (Right)); 1973 end if; 1974 1975 -- Otherwise we have the general case (Algorithm M in Knuth) 1976 1977 declare 1978 L_Length : constant Int := N_Digits (Left); 1979 R_Length : constant Int := N_Digits (Right); 1980 L_Vec : UI_Vector (1 .. L_Length); 1981 R_Vec : UI_Vector (1 .. R_Length); 1982 Neg : Boolean; 1983 1984 begin 1985 Init_Operand (Left, L_Vec); 1986 Init_Operand (Right, R_Vec); 1987 Neg := (L_Vec (1) < Int_0) xor (R_Vec (1) < Int_0); 1988 L_Vec (1) := abs (L_Vec (1)); 1989 R_Vec (1) := abs (R_Vec (1)); 1990 1991 Algorithm_M : declare 1992 Product : UI_Vector (1 .. L_Length + R_Length); 1993 Tmp_Sum : Int; 1994 Carry : Int; 1995 1996 begin 1997 for J in Product'Range loop 1998 Product (J) := 0; 1999 end loop; 2000 2001 for J in reverse R_Vec'Range loop 2002 Carry := 0; 2003 for K in reverse L_Vec'Range loop 2004 Tmp_Sum := 2005 L_Vec (K) * R_Vec (J) + Product (J + K) + Carry; 2006 Product (J + K) := Tmp_Sum rem Base; 2007 Carry := Tmp_Sum / Base; 2008 end loop; 2009 2010 Product (J) := Carry; 2011 end loop; 2012 2013 return Vector_To_Uint (Product, Neg); 2014 end Algorithm_M; 2015 end; 2016 end UI_Mul; 2017 2018 ------------ 2019 -- UI_Ne -- 2020 ------------ 2021 2022 function UI_Ne (Left : Int; Right : Uint) return Boolean is 2023 begin 2024 return UI_Ne (UI_From_Int (Left), Right); 2025 end UI_Ne; 2026 2027 function UI_Ne (Left : Uint; Right : Int) return Boolean is 2028 begin 2029 return UI_Ne (Left, UI_From_Int (Right)); 2030 end UI_Ne; 2031 2032 function UI_Ne (Left : Uint; Right : Uint) return Boolean is 2033 begin 2034 -- Quick processing for identical arguments. Note that this takes 2035 -- care of the case of two No_Uint arguments. 2036 2037 if Int (Left) = Int (Right) then 2038 return False; 2039 end if; 2040 2041 -- See if left operand directly represented 2042 2043 if Direct (Left) then 2044 2045 -- If right operand directly represented then compare 2046 2047 if Direct (Right) then 2048 return Int (Left) /= Int (Right); 2049 2050 -- Left operand directly represented, right not, must be unequal 2051 2052 else 2053 return True; 2054 end if; 2055 2056 -- Right operand directly represented, left not, must be unequal 2057 2058 elsif Direct (Right) then 2059 return True; 2060 end if; 2061 2062 -- Otherwise both multi-word, do comparison 2063 2064 declare 2065 Size : constant Int := N_Digits (Left); 2066 Left_Loc : Int; 2067 Right_Loc : Int; 2068 2069 begin 2070 if Size /= N_Digits (Right) then 2071 return True; 2072 end if; 2073 2074 Left_Loc := Uints.Table (Left).Loc; 2075 Right_Loc := Uints.Table (Right).Loc; 2076 2077 for J in Int_0 .. Size - Int_1 loop 2078 if Udigits.Table (Left_Loc + J) /= 2079 Udigits.Table (Right_Loc + J) 2080 then 2081 return True; 2082 end if; 2083 end loop; 2084 2085 return False; 2086 end; 2087 end UI_Ne; 2088 2089 ---------------- 2090 -- UI_Negate -- 2091 ---------------- 2092 2093 function UI_Negate (Right : Uint) return Uint is 2094 begin 2095 -- Case where input is directly represented. Note that since the range 2096 -- of Direct values is non-symmetrical, the result may not be directly 2097 -- represented, this is taken care of in UI_From_Int. 2098 2099 if Direct (Right) then 2100 return UI_From_Int (-Direct_Val (Right)); 2101 2102 -- Full processing for multi-digit case. Note that we cannot just copy 2103 -- the value to the end of the table negating the first digit, since the 2104 -- range of Direct values is non-symmetrical, so we can have a negative 2105 -- value that is not Direct whose negation can be represented directly. 2106 2107 else 2108 declare 2109 R_Length : constant Int := N_Digits (Right); 2110 R_Vec : UI_Vector (1 .. R_Length); 2111 Neg : Boolean; 2112 2113 begin 2114 Init_Operand (Right, R_Vec); 2115 Neg := R_Vec (1) > Int_0; 2116 R_Vec (1) := abs R_Vec (1); 2117 return Vector_To_Uint (R_Vec, Neg); 2118 end; 2119 end if; 2120 end UI_Negate; 2121 2122 ------------- 2123 -- UI_Rem -- 2124 ------------- 2125 2126 function UI_Rem (Left : Int; Right : Uint) return Uint is 2127 begin 2128 return UI_Rem (UI_From_Int (Left), Right); 2129 end UI_Rem; 2130 2131 function UI_Rem (Left : Uint; Right : Int) return Uint is 2132 begin 2133 return UI_Rem (Left, UI_From_Int (Right)); 2134 end UI_Rem; 2135 2136 function UI_Rem (Left, Right : Uint) return Uint is 2137 Remainder : Uint; 2138 Quotient : Uint; 2139 pragma Warnings (Off, Quotient); 2140 2141 begin 2142 pragma Assert (Right /= Uint_0); 2143 2144 if Direct (Right) and then Direct (Left) then 2145 return UI_From_Int (Direct_Val (Left) rem Direct_Val (Right)); 2146 2147 else 2148 UI_Div_Rem 2149 (Left, Right, Quotient, Remainder, Discard_Quotient => True); 2150 return Remainder; 2151 end if; 2152 end UI_Rem; 2153 2154 ------------ 2155 -- UI_Sub -- 2156 ------------ 2157 2158 function UI_Sub (Left : Int; Right : Uint) return Uint is 2159 begin 2160 return UI_Add (Left, -Right); 2161 end UI_Sub; 2162 2163 function UI_Sub (Left : Uint; Right : Int) return Uint is 2164 begin 2165 return UI_Add (Left, -Right); 2166 end UI_Sub; 2167 2168 function UI_Sub (Left : Uint; Right : Uint) return Uint is 2169 begin 2170 if Direct (Left) and then Direct (Right) then 2171 return UI_From_Int (Direct_Val (Left) - Direct_Val (Right)); 2172 else 2173 return UI_Add (Left, -Right); 2174 end if; 2175 end UI_Sub; 2176 2177 -------------- 2178 -- UI_To_CC -- 2179 -------------- 2180 2181 function UI_To_CC (Input : Uint) return Char_Code is 2182 begin 2183 if Direct (Input) then 2184 return Char_Code (Direct_Val (Input)); 2185 2186 -- Case of input is more than one digit 2187 2188 else 2189 declare 2190 In_Length : constant Int := N_Digits (Input); 2191 In_Vec : UI_Vector (1 .. In_Length); 2192 Ret_CC : Char_Code; 2193 2194 begin 2195 Init_Operand (Input, In_Vec); 2196 2197 -- We assume value is positive 2198 2199 Ret_CC := 0; 2200 for Idx in In_Vec'Range loop 2201 Ret_CC := Ret_CC * Char_Code (Base) + 2202 Char_Code (abs In_Vec (Idx)); 2203 end loop; 2204 2205 return Ret_CC; 2206 end; 2207 end if; 2208 end UI_To_CC; 2209 2210 ---------------- 2211 -- UI_To_Int -- 2212 ---------------- 2213 2214 function UI_To_Int (Input : Uint) return Int is 2215 pragma Assert (Input /= No_Uint); 2216 2217 begin 2218 if Direct (Input) then 2219 return Direct_Val (Input); 2220 2221 -- Case of input is more than one digit 2222 2223 else 2224 declare 2225 In_Length : constant Int := N_Digits (Input); 2226 In_Vec : UI_Vector (1 .. In_Length); 2227 Ret_Int : Int; 2228 2229 begin 2230 -- Uints of more than one digit could be outside the range for 2231 -- Ints. Caller should have checked for this if not certain. 2232 -- Fatal error to attempt to convert from value outside Int'Range. 2233 2234 pragma Assert (UI_Is_In_Int_Range (Input)); 2235 2236 -- Otherwise, proceed ahead, we are OK 2237 2238 Init_Operand (Input, In_Vec); 2239 Ret_Int := 0; 2240 2241 -- Calculate -|Input| and then negates if value is positive. This 2242 -- handles our current definition of Int (based on 2s complement). 2243 -- Is it secure enough??? 2244 2245 for Idx in In_Vec'Range loop 2246 Ret_Int := Ret_Int * Base - abs In_Vec (Idx); 2247 end loop; 2248 2249 if In_Vec (1) < Int_0 then 2250 return Ret_Int; 2251 else 2252 return -Ret_Int; 2253 end if; 2254 end; 2255 end if; 2256 end UI_To_Int; 2257 2258 -------------- 2259 -- UI_Write -- 2260 -------------- 2261 2262 procedure UI_Write (Input : Uint; Format : UI_Format := Auto) is 2263 begin 2264 Image_Out (Input, False, Format); 2265 end UI_Write; 2266 2267 --------------------- 2268 -- Vector_To_Uint -- 2269 --------------------- 2270 2271 function Vector_To_Uint 2272 (In_Vec : UI_Vector; 2273 Negative : Boolean) 2274 return Uint 2275 is 2276 Size : Int; 2277 Val : Int; 2278 2279 begin 2280 -- The vector can contain leading zeros. These are not stored in the 2281 -- table, so loop through the vector looking for first non-zero digit 2282 2283 for J in In_Vec'Range loop 2284 if In_Vec (J) /= Int_0 then 2285 2286 -- The length of the value is the length of the rest of the vector 2287 2288 Size := In_Vec'Last - J + 1; 2289 2290 -- One digit value can always be represented directly 2291 2292 if Size = Int_1 then 2293 if Negative then 2294 return Uint (Int (Uint_Direct_Bias) - In_Vec (J)); 2295 else 2296 return Uint (Int (Uint_Direct_Bias) + In_Vec (J)); 2297 end if; 2298 2299 -- Positive two digit values may be in direct representation range 2300 2301 elsif Size = Int_2 and then not Negative then 2302 Val := In_Vec (J) * Base + In_Vec (J + 1); 2303 2304 if Val <= Max_Direct then 2305 return Uint (Int (Uint_Direct_Bias) + Val); 2306 end if; 2307 end if; 2308 2309 -- The value is outside the direct representation range and must 2310 -- therefore be stored in the table. Expand the table to contain 2311 -- the count and digits. The index of the new table entry will be 2312 -- returned as the result. 2313 2314 Uints.Append ((Length => Size, Loc => Udigits.Last + 1)); 2315 2316 if Negative then 2317 Val := -In_Vec (J); 2318 else 2319 Val := +In_Vec (J); 2320 end if; 2321 2322 Udigits.Append (Val); 2323 2324 for K in 2 .. Size loop 2325 Udigits.Append (In_Vec (J + K - 1)); 2326 end loop; 2327 2328 return Uints.Last; 2329 end if; 2330 end loop; 2331 2332 -- Dropped through loop only if vector contained all zeros 2333 2334 return Uint_0; 2335 end Vector_To_Uint; 2336 2337end Uintp; 2338