home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / misc / math / excalc / source / exintegers.mod < prev    next >
Text File  |  1995-05-08  |  14KB  |  585 lines

  1. (*********************************************************************)
  2. (*                                                                   *)
  3. (* Module ExIntegers Copyright © 1995 by Computer Inspirations       *)
  4. (*                                                                   *)
  5. (* Design : Michael Griebling                                        *)
  6. (* Change : Original                                                 *)
  7. (*                                                                   *)
  8. (*********************************************************************)
  9.  
  10. MODULE ExIntegers;
  11.  
  12. (*  Some Functions to perform bit manipulation on ExNumbers.
  13.     This module deals with integral ExNumbers in the range
  14.     from -5.9863E51 to 5.9863E51.  Any numbers outside this
  15.     range are represented with the maximum (or minimum)
  16.     ExNumber from this range.
  17. *)
  18.  
  19. IMPORT io, Cnv := Conversions, Str := Strings, X := ExNumbers,
  20.        XM := ExMathLib0, SYSTEM;
  21.  
  22. TYPE
  23.   BaseType * = SHORTINT;
  24.  
  25.  
  26. CONST
  27.   MaxBase2Bits = 172;    (* ln(9.99E51) / ln(2) *)
  28.   LogicalSize  = MaxBase2Bits DIV 16;
  29.   Left         = FALSE;
  30.   Right        = TRUE;
  31.  
  32. TYPE
  33.   LogicalType = ARRAY LogicalSize+1 OF SET;
  34.   LogicalProc = PROCEDURE(a,b: SET) : SET;
  35.   ExNumbProc  = PROCEDURE(VAR a: X.ExNumType; b,c: X.ExNumType);
  36.  
  37. VAR
  38.   LogZero   : LogicalType; (* All bits cleared or 0  *)
  39.   MaxNumber : X.ExNumType;   (*  2 ** MaxBase2Bits - 1 *)
  40.   MinNumber : X.ExNumType;   (* -2 ** MaxBase2Bits + 1 *)
  41.   Two       : X.ExNumType;   (* The value "2" *)
  42.   Cnt       : INTEGER;
  43.  
  44.  
  45. (*--------------------------------------*)
  46. (* Local bit manipulations functions.   *)
  47.  
  48. PROCEDURE And (op1, op2 : SET) : SET;
  49. BEGIN
  50.   RETURN op1 * op2;
  51. END And;
  52.  
  53. PROCEDURE AndNot (op1, op2 : SET) : SET;
  54. BEGIN
  55.   RETURN op1 - op2;
  56. END AndNot;
  57.  
  58. PROCEDURE Or (op1, op2 : SET) : SET;
  59. BEGIN
  60.   RETURN op1 + op2;
  61. END Or;
  62.  
  63. PROCEDURE Xor (op1, op2 : SET) : SET;
  64. BEGIN
  65.   RETURN op1 / op2;
  66. END Xor;
  67.  
  68.  
  69. (*--------------------------------------*)
  70. (* Miscellaneous local procedures       *)
  71.  
  72. PROCEDURE Max (x, y : INTEGER) : INTEGER;
  73. BEGIN
  74.   IF x > y THEN
  75.     RETURN x;
  76.   ELSE
  77.     RETURN y;
  78.   END;
  79. END Max;
  80.  
  81.  
  82. PROCEDURE ConstrainExNum (VAR Number : X.ExNumType);
  83. (* Limit Number to be within MinNumber to MaxNumber and
  84.    eliminate any fractional portions. *)
  85. BEGIN
  86.   X.ExMin(Number, MaxNumber, Number);
  87.   X.ExMax(Number, MinNumber, Number);
  88.   X.ExTrunc(Number);
  89. END ConstrainExNum;
  90.  
  91.  
  92. PROCEDURE ExNumToLogical (Numb        : X.ExNumType;
  93.                           VAR Logical : LogicalType);
  94. VAR
  95.   DivScale : X.ExNumType;
  96.   Scale    : X.ExNumType;
  97.   Temp     : X.ExNumType;
  98.   Temp2    : X.ExNumType;
  99.   LogCnt   : INTEGER;
  100. BEGIN
  101.   (* Constrain op1, op2 to be within the logical number set *)
  102.   ConstrainExNum(Numb);
  103.  
  104.   (* translation scaling factor *)
  105.   X.ExNumb(65536, 0, 0, Scale);
  106.   X.ExDiv(DivScale, X.Ex1, Scale);
  107.  
  108.   (* perform conversion *)
  109.   LogCnt  := 0;
  110.   Logical := LogZero;
  111.   WHILE NOT X.IsZero(Numb) DO
  112.     X.ExMult(Temp2, Numb, DivScale);
  113.     X.ExTrunc(Temp2);
  114.     X.ExMult(Temp, Temp2, Scale);
  115.     X.ExSub(Temp, Numb, Temp);
  116.     IF LogCnt > LogicalSize THEN RETURN END;
  117.     (* $RangeChk- *)
  118.     Logical[LogCnt] := SYSTEM.VAL(SET, SHORT(X.ExToLongInt(Temp)));
  119.     (* $RangeChk= *)
  120.     Numb := Temp2;
  121.     INC(LogCnt);
  122.   END;
  123. END ExNumToLogical;
  124.  
  125. PROCEDURE LogicalToExNum (Logical  : LogicalType;
  126.                           VAR Numb : X.ExNumType);
  127. VAR
  128.   Scale  : X.ExNumType;
  129.   Temp   : X.ExNumType;
  130.   LogCnt : INTEGER;
  131.   INumb  : LONGINT;
  132. BEGIN
  133.   (* translation scaling factor *)
  134.   X.ExNumb(65536, 0, 0, Scale);
  135.  
  136.   (* perform conversion *)
  137.   Numb := X.Ex0;
  138.   FOR LogCnt := LogicalSize TO 0 BY -1 DO
  139.     X.ExMult(Numb, Numb, Scale);
  140.     INumb := SYSTEM.VAL(INTEGER, Logical[LogCnt]);
  141.     IF INumb < 0 THEN INC(INumb, 10000H) END;
  142.     X.ExNumb(INumb, 0, 0, Temp);
  143.     X.ExAdd(Numb, Numb, Temp);
  144.   END;
  145. END LogicalToExNum;
  146.  
  147.  
  148. (*--------------------------------------*)
  149. (* Local procedure to perform general   *)
  150. (* logical operations on ExNumbers.     *)
  151.  
  152. PROCEDURE LOp (VAR Result : X.ExNumType;
  153.                op1        : X.ExNumType;
  154.                Oper       : LogicalProc;
  155.                op2        : X.ExNumType);
  156. VAR
  157.   i : INTEGER;
  158.   Lop1, Lop2 : LogicalType;
  159. BEGIN
  160.   (* Translate to logicals *)
  161.   ExNumToLogical(op1, Lop1);
  162.   ExNumToLogical(op2, Lop2);
  163.  
  164.   (* Operate on Lop1 and Lop2 one quad at a time *)
  165.   FOR i := 0 TO LogicalSize DO
  166.     Lop2[i] := Oper(Lop1[i], Lop2[i]);
  167.   END;
  168.  
  169.   (* Translate back the result *)
  170.   LogicalToExNum(Lop2, Result);
  171. END LOp;
  172.  
  173.  
  174. (*--------------------------------------*)
  175. (* Local procedure to perform general   *)
  176. (* single bit operations on ExNumbers.  *)
  177.  
  178. PROCEDURE LBit (VAR Result : X.ExNumType;
  179.                 number     : X.ExNumType;
  180.                 Oper       : LogicalProc;
  181.                 bitnum     : INTEGER);
  182. VAR
  183.   Temp : X.ExNumType;
  184. BEGIN
  185.   (* Constrain number to be within the logical number set *)
  186.   ConstrainExNum(number);
  187.  
  188.   (* constrain bitnum from 0 to MaxBase2Bits *)
  189.   IF bitnum > MaxBase2Bits THEN
  190.     (* no bits are changed *)
  191.     Result := number;
  192.     RETURN;
  193.   END;
  194.  
  195.   (* calculate 2**bitnum *)
  196.   XM.xtoi(Temp, Two, bitnum);
  197.  
  198.   (* set the bitnum bit position *)
  199.   LOp(Result, number, Oper, Temp);
  200. END LBit;
  201.  
  202.  
  203. PROCEDURE ExSetBit *(VAR Result : X.ExNumType;
  204.                      number     : X.ExNumType;
  205.                      bitnum     : INTEGER);
  206. BEGIN
  207.   LBit(Result, number, Or, bitnum);
  208. END ExSetBit;
  209.  
  210.  
  211. PROCEDURE ExClearBit *(VAR Result : X.ExNumType;
  212.                        number     : X.ExNumType;
  213.                        bitnum     : INTEGER);
  214. BEGIN
  215.   LBit(Result, number, AndNot, bitnum);
  216. END ExClearBit;
  217.  
  218.  
  219. PROCEDURE ExToggleBit *(VAR Result : X.ExNumType;
  220.                         number     : X.ExNumType;
  221.                         bitnum     : INTEGER);
  222. BEGIN
  223.   LBit(Result, number, Xor, bitnum);
  224. END ExToggleBit;
  225.  
  226.  
  227. PROCEDURE^ ExAnd *(VAR Result : X.ExNumType;
  228.                    op1, op2   : X.ExNumType);
  229.  
  230.  
  231. (*--------------------------------------*)
  232. (* Local function to extract a bit from *)
  233. (* an ExNumber.                         *)
  234.  
  235. PROCEDURE Bit (number : X.ExNumType;
  236.                bitnum : INTEGER) : BOOLEAN;
  237. VAR
  238.   Temp : X.ExNumType;
  239. BEGIN
  240.   (* Constrain number to be within the logical number set *)
  241.   ConstrainExNum(number);
  242.  
  243.   (* constrain bitnum from 0 to MaxBase2Bits - 1 *)
  244.   IF bitnum >= MaxBase2Bits THEN
  245.     (* assume FALSE *)
  246.     RETURN FALSE;
  247.   END;
  248.  
  249.   (* calculate 2**bitnum *)
  250.   XM.xtoi(Temp, Two, bitnum);
  251.  
  252.   (* extract the bitnum bit *)
  253.   ExAnd(number, number, Temp);
  254.  
  255.   (* translate to boolean *)
  256.   RETURN NOT X.IsZero(number);
  257. END Bit;
  258.  
  259.  
  260. (*--------------------------------------*)
  261. (* Local procedure to perform general   *)
  262. (* bit shifting operations on ExNumbers.*)
  263.  
  264. PROCEDURE LShift (VAR Result : X.ExNumType;
  265.                   number     : X.ExNumType;
  266.                   ExOper     : ExNumbProc;
  267.                   bits       : INTEGER);
  268. VAR
  269.   Temp : X.ExNumType;
  270. BEGIN
  271.   (* Constrain number to be within the logical number set *)
  272.   ConstrainExNum(number);
  273.  
  274.   (* constrain bitnum from 0 to MaxBase2Bits *)
  275.   IF bits > MaxBase2Bits THEN
  276.     (* shifted out of range *)
  277.     Result := X.Ex0;
  278.     RETURN;
  279.   END;
  280.  
  281.   (* calculate 2**bits *)
  282.   XM.xtoi(Temp, Two, bits);
  283.  
  284.   (* shift the number *)
  285.   ExOper(Result, number, Temp);
  286.  
  287.   (* Constrain number to be within the logical number set *)
  288.   ConstrainExNum(Result);
  289. END LShift;
  290.  
  291.  
  292. (*--------------------------------------*)
  293. (* Local procedure to perform general   *)
  294. (* bit rotation operations on ExNumbers.*)
  295.  
  296. PROCEDURE LRotate (VAR Result : X.ExNumType;
  297.                    number     : X.ExNumType;
  298.                    Shiftright : BOOLEAN;
  299.                    bits       : INTEGER);
  300. VAR
  301.   ShiftCnt : INTEGER;
  302.   SavedBit : BOOLEAN;
  303.   Half     : X.ExNumType;
  304. BEGIN
  305.   (* Constrain number to be within the logical number set *)
  306.   ConstrainExNum(number);
  307.  
  308.   (* constrain bitnum from 0 to MaxBase2Bits *)
  309.   bits := bits MOD (MaxBase2Bits + 1);
  310.   X.ExNumb(0, 5, 0, Half);
  311.  
  312.   FOR ShiftCnt := 1 TO bits DO
  313.     IF Shiftright THEN
  314.       (* save the bit to be shifted *)
  315.       SavedBit := Bit(number, 0);
  316.  
  317.       (* shift the number right *)
  318.       X.ExMult(number, number, Half);
  319.       X.ExTrunc(number);
  320.       IF SavedBit THEN
  321.         ExSetBit(number, number, MaxBase2Bits-1);
  322.       END;
  323.     ELSE
  324.       (* save the bit to be shifted *)
  325.       SavedBit := Bit(number, MaxBase2Bits-1);
  326.  
  327.       (* shift the number left *)
  328.       X.ExMult(number, number, Two);
  329.  
  330.       (* restore the saved bit *)
  331.       IF SavedBit THEN
  332.         ExSetBit(number, number, 0);
  333.       END;
  334.     END;
  335.  
  336.   END;
  337.  
  338.   (* Constrain number to be within the logical number set *)
  339.   Result := number;
  340.   ConstrainExNum(Result);
  341. END LRotate;
  342.  
  343.  
  344. (*--------------------------------------*)
  345. (* Exported procedures.                 *)
  346.  
  347. PROCEDURE ExAnd *(VAR Result : X.ExNumType;
  348.                   op1, op2   : X.ExNumType);
  349. BEGIN
  350.   LOp(Result, op1, And, op2);
  351. END ExAnd;
  352.  
  353.  
  354. PROCEDURE ExOr *(VAR Result : X.ExNumType;
  355.                  op1, op2   : X.ExNumType);
  356. BEGIN
  357.   LOp(Result, op1, Or, op2);
  358. END ExOr;
  359.  
  360.  
  361. PROCEDURE ExXor *(VAR Result : X.ExNumType;
  362.                   op1, op2   : X.ExNumType);
  363. BEGIN
  364.   LOp(Result, op1, Xor, op2);
  365. END ExXor;
  366.  
  367.  
  368. PROCEDURE ExIntDiv *(VAR Result : X.ExNumType;
  369.                      op1, op2   : X.ExNumType);
  370. BEGIN
  371.   (* Constrain inputs to be integers *)
  372.   ConstrainExNum(op1); ConstrainExNum(op2);
  373.   X.ExDiv(Result, op1, op2);
  374.   X.ExTrunc(Result);
  375. END ExIntDiv;
  376.  
  377.  
  378. PROCEDURE ExMod *(VAR Result : X.ExNumType;
  379.                   op1, op2   : X.ExNumType);
  380. BEGIN
  381.   (* Result := op1 - (op1 DIV op2) * op2 *)
  382.   ConstrainExNum(op1); ConstrainExNum(op2);
  383.   ExIntDiv(Result, op1, op2);
  384.   X.ExMult(Result, Result, op2);
  385.   X.ExSub(Result, op1, Result);
  386. END ExMod;
  387.  
  388.  
  389. PROCEDURE ExOnesComp *(VAR Result : X.ExNumType;
  390.                        number     : X.ExNumType);
  391. BEGIN
  392.   (* Constrain number to be within the logical number set *)
  393.   ConstrainExNum(number);
  394.   IF number.Sign = X.positive THEN
  395.     (* Subtract from the maximum number *)
  396.     X.ExSub(Result, MaxNumber, number);
  397.   ELSE
  398.     (* Subtract from the minimum number *)
  399.     X.ExSub(Result, MinNumber, number);
  400.   END;
  401.  
  402.   (* Complement the sign bit *)
  403.   X.ExChgSign(Result);
  404. END ExOnesComp;
  405.  
  406.  
  407. PROCEDURE ExShl *(VAR Result : X.ExNumType;
  408.                   number     : X.ExNumType;
  409.                   numbits    : INTEGER);
  410. BEGIN
  411.   LShift(Result, number, X.ExMult, numbits);
  412.  
  413.   (* Determine the resultant sign *)
  414.   X.ExAbs(Result);
  415.   IF Bit (Result, MaxBase2Bits-1) THEN
  416.     X.ExChgSign(Result); (* negate *)
  417.   END;
  418. END ExShl;
  419.  
  420.  
  421. PROCEDURE ExRol *(VAR Result : X.ExNumType;
  422.                   number     : X.ExNumType;
  423.                   numbits    : INTEGER);
  424. BEGIN
  425.   LRotate(Result, number, Left, numbits);
  426. END ExRol;
  427.  
  428.  
  429. PROCEDURE ExShr *(VAR Result : X.ExNumType;
  430.                   number     : X.ExNumType;
  431.                   numbits    : INTEGER);
  432. BEGIN
  433.   LShift(Result, number, X.ExDiv, numbits);
  434.   X.ExAbs(Result);  (* clear the sign *)
  435. END ExShr;
  436.  
  437.  
  438. PROCEDURE ExAshr *(VAR Result : X.ExNumType;
  439.                    number     : X.ExNumType;
  440.                    numbits    : INTEGER);
  441. VAR
  442.   ShiftCnt : INTEGER;
  443.   SavedBit : BOOLEAN;
  444. BEGIN
  445.   (* Constrain number to be within the logical number set *)
  446.   ConstrainExNum(number);
  447.  
  448.   (* constrain bitnum from 0 to MaxBase2Bits *)
  449.   IF numbits > MaxBase2Bits THEN
  450.     (* shifted out of range *)
  451.     Result := X.Ex0;
  452.     RETURN;
  453.   END;
  454.  
  455.   (* set the SavedBit to the current sign *)
  456.   SavedBit := number.Sign = X.negative;
  457.  
  458.   (* shift the number *)
  459.   FOR ShiftCnt := 1 TO numbits DO
  460.     (* shift the number right *)
  461.     X.ExDiv(number, number, Two);
  462.  
  463.     (* restore the saved bit *)
  464.     IF SavedBit THEN
  465.       ExSetBit(number, number, MaxBase2Bits-1);
  466.     END;
  467.   END;
  468.  
  469.   (* truncate any fraction *)
  470.   Result := number;
  471.   X.ExTrunc(Result);
  472. END ExAshr;
  473.  
  474.  
  475. PROCEDURE ExRor *(VAR Result : X.ExNumType;
  476.                   number     : X.ExNumType;
  477.                   numbits    : INTEGER);
  478. BEGIN
  479.   LRotate(Result, number, Right, numbits);
  480. END ExRor;
  481.  
  482.  
  483. (* $CopyArrays- *)
  484. PROCEDURE StrToExInt *(S     : ARRAY OF CHAR;
  485.                        Base  : BaseType;
  486.                        VAR A : X.ExNumType);
  487. VAR
  488.   EndCnt, InCnt : LONGINT;
  489.   Multiplier    : INTEGER;
  490.   Scale, Temp   : X.ExNumType;
  491.  
  492.   PROCEDURE DigitIs() : LONGINT;
  493.   VAR
  494.     Str : ARRAY 2 OF CHAR;
  495.     Digits : LONGINT;
  496.   BEGIN
  497.     (* Extract a digit *)
  498.     Str[0] := S[InCnt]; Str[1] := 0X;
  499.     INC(InCnt);
  500.  
  501.     IF ~Cnv.StrToInt(Str, Digits, Base) THEN
  502.       X.ExStatus := X.IllegalNumber;
  503.       RETURN 0;
  504.     END;
  505.     RETURN Digits;
  506.   END DigitIs;
  507.  
  508. BEGIN
  509.   A := X.Ex0;
  510.   InCnt := 0;
  511.   EndCnt := Str.Length(S);
  512.   X.ExNumb(Base, 0, 0, Scale);
  513.  
  514.   (* skip leading blanks *)
  515.   WHILE (InCnt < EndCnt) & (S[InCnt] = ' ') DO INC(InCnt) END;
  516.  
  517.   WHILE (InCnt < EndCnt) & (X.ExStatus # X.IllegalNumber) DO
  518.     X.ExNumb(DigitIs(), 0, 0, Temp);
  519.     X.ExMult(A, A, Scale);
  520.     X.ExAdd(A, A, Temp);
  521.   END;
  522. END StrToExInt;
  523.  
  524.  
  525. PROCEDURE ExIntToStr*(A     : X.ExNumType;
  526.                       Base  : BaseType;
  527.                       VAR S : ARRAY OF CHAR);
  528. VAR
  529.   InCnt : INTEGER;
  530.   InvScale, Scale, Temp, Temp2 : X.ExNumType;
  531.  
  532.   PROCEDURE PutDigits(Numb : LONGINT);
  533.   VAR
  534.     Res : ARRAY 81 OF CHAR;
  535.     Ok  : BOOLEAN;
  536.   BEGIN
  537.     Ok := Cnv.IntToStr(Numb, Res, Base, 4, '0');
  538.     Str.Insert(S, 0, Res);
  539.   END PutDigits;
  540.  
  541. BEGIN
  542.   (* Constrain number to be within the logical number set *)
  543.   ConstrainExNum(A);
  544.  
  545.   S := "";
  546.   InCnt := 0;
  547.   X.ExNumb(Base, 0, 0, Scale);
  548.   XM.xtoi(Scale, Scale, 4);
  549.   X.ExDiv(InvScale, X.Ex1, Scale);
  550.  
  551.   (* translate number to a string *)
  552.   REPEAT
  553.     (* Temp := A MOD Scale *)
  554.     X.ExMult(Temp2, A, InvScale);
  555.     X.ExTrunc(Temp2);
  556.     X.ExMult(Temp, Temp2, Scale);
  557.     X.ExSub(Temp, A, Temp);
  558.  
  559.     (* Translate to character *)
  560.     PutDigits(X.ExToLongInt(Temp));
  561.  
  562.     (* Reduce A by scaling factor *)
  563.     A := Temp2;
  564.   UNTIL X.IsZero(A);
  565. END ExIntToStr;
  566.  
  567.  
  568. BEGIN
  569.   (* create the number 2 *)
  570.   X.ExNumb(2, 0, 0, Two);
  571.  
  572.   (* Initialize the maximum number *)
  573.   XM.xtoi(MaxNumber, Two, MaxBase2Bits);
  574.   X.ExSub(MaxNumber, MaxNumber, X.Ex1);
  575.  
  576.   (* Initialize the minimum number *)
  577.   MinNumber := MaxNumber;
  578.   X.ExChgSign(MinNumber);
  579.  
  580.   (* Initialize the zero logical *)
  581.   FOR Cnt := 0 TO LogicalSize DO
  582.     LogZero[Cnt] := {};
  583.   END;
  584. END ExIntegers.
  585.