home *** CD-ROM | disk | FTP | other *** search
- MODULE ExIntegers;
-
- (* Some Functions to perform bit manipulation on ExNumbers.
- This module deals with integral ExNumbers in the range
- from -5.9863E51 to 5.9863E51. Any numbers outside this
- range are represented with the maximum (or minimum)
- ExNumber from this range.
- *)
-
- IMPORT io, Cnv := Conversions, Str := Strings, X := ExNumbers,
- XM := ExMathLib0, SYSTEM;
-
- TYPE
- BaseType * = SHORTINT;
-
-
- CONST
- MaxBase2Bits = 172; (* ln(9.99E51) / ln(2) *)
- LogicalSize = MaxBase2Bits DIV 16;
- Left = FALSE;
- Right = TRUE;
-
- TYPE
- LogicalType = ARRAY LogicalSize+1 OF SET;
- LogicalProc = PROCEDURE(a,b: SET) : SET;
- ExNumbProc = PROCEDURE(VAR a: X.ExNumType; b,c: X.ExNumType);
-
- VAR
- LogZero : LogicalType; (* All bits cleared or 0 *)
- MaxNumber : X.ExNumType; (* 2 ** MaxBase2Bits - 1 *)
- MinNumber : X.ExNumType; (* -2 ** MaxBase2Bits + 1 *)
- Two : X.ExNumType; (* The value "2" *)
- Cnt : INTEGER;
-
-
- (*--------------------------------------*)
- (* Local bit manipulations functions. *)
-
- PROCEDURE And (op1, op2 : SET) : SET;
- BEGIN
- RETURN op1 * op2;
- END And;
-
- PROCEDURE AndNot (op1, op2 : SET) : SET;
- BEGIN
- RETURN op1 - op2;
- END AndNot;
-
- PROCEDURE Or (op1, op2 : SET) : SET;
- BEGIN
- RETURN op1 + op2;
- END Or;
-
- PROCEDURE Xor (op1, op2 : SET) : SET;
- BEGIN
- RETURN op1 / op2;
- END Xor;
-
-
- (*--------------------------------------*)
- (* Miscellaneous local procedures *)
-
- PROCEDURE Max (x, y : INTEGER) : INTEGER;
- BEGIN
- IF x > y THEN
- RETURN x;
- ELSE
- RETURN y;
- END;
- END Max;
-
-
- PROCEDURE ConstrainExNum (VAR Number : X.ExNumType);
- (* Limit Number to be within MinNumber to MaxNumber and
- eliminate any fractional portions. *)
- BEGIN
- X.ExMin(Number, MaxNumber, Number);
- X.ExMax(Number, MinNumber, Number);
- X.ExTrunc(Number);
- END ConstrainExNum;
-
-
- PROCEDURE ExNumToLogical (Numb : X.ExNumType;
- VAR Logical : LogicalType);
- VAR
- DivScale : X.ExNumType;
- Scale : X.ExNumType;
- Temp : X.ExNumType;
- Temp2 : X.ExNumType;
- LogCnt : INTEGER;
- BEGIN
- (* Constrain op1, op2 to be within the logical number set *)
- ConstrainExNum(Numb);
-
- (* translation scaling factor *)
- X.ExNumb(65536, 0, 0, Scale);
- X.ExDiv(DivScale, X.Ex1, Scale);
-
- (* perform conversion *)
- LogCnt := 0;
- Logical := LogZero;
- WHILE NOT X.IsZero(Numb) DO
- X.ExMult(Temp2, Numb, DivScale);
- X.ExTrunc(Temp2);
- X.ExMult(Temp, Temp2, Scale);
- X.ExSub(Temp, Numb, Temp);
- IF LogCnt > LogicalSize THEN RETURN END;
- (* $RangeChk- *)
- Logical[LogCnt] := SYSTEM.VAL(SET, SHORT(X.ExToLongInt(Temp)));
- (* $RangeChk= *)
- Numb := Temp2;
- INC(LogCnt);
- END;
- END ExNumToLogical;
-
- PROCEDURE LogicalToExNum (Logical : LogicalType;
- VAR Numb : X.ExNumType);
- VAR
- Scale : X.ExNumType;
- Temp : X.ExNumType;
- LogCnt : INTEGER;
- INumb : LONGINT;
- BEGIN
- (* translation scaling factor *)
- X.ExNumb(65536, 0, 0, Scale);
-
- (* perform conversion *)
- Numb := X.Ex0;
- FOR LogCnt := LogicalSize TO 0 BY -1 DO
- X.ExMult(Numb, Numb, Scale);
- INumb := SYSTEM.VAL(INTEGER, Logical[LogCnt]);
- IF INumb < 0 THEN INC(INumb, 10000H) END;
- X.ExNumb(INumb, 0, 0, Temp);
- X.ExAdd(Numb, Numb, Temp);
- END;
- END LogicalToExNum;
-
-
- (*--------------------------------------*)
- (* Local procedure to perform general *)
- (* logical operations on ExNumbers. *)
-
- PROCEDURE LOp (VAR Result : X.ExNumType;
- op1 : X.ExNumType;
- Oper : LogicalProc;
- op2 : X.ExNumType);
- VAR
- i : INTEGER;
- Lop1, Lop2 : LogicalType;
- BEGIN
- (* Translate to logicals *)
- ExNumToLogical(op1, Lop1);
- ExNumToLogical(op2, Lop2);
-
- (* Operate on Lop1 and Lop2 one quad at a time *)
- FOR i := 0 TO LogicalSize DO
- Lop2[i] := Oper(Lop1[i], Lop2[i]);
- END;
-
- (* Translate back the result *)
- LogicalToExNum(Lop2, Result);
- END LOp;
-
-
- (*--------------------------------------*)
- (* Local procedure to perform general *)
- (* single bit operations on ExNumbers. *)
-
- PROCEDURE LBit (VAR Result : X.ExNumType;
- number : X.ExNumType;
- Oper : LogicalProc;
- bitnum : INTEGER);
- VAR
- Temp : X.ExNumType;
- BEGIN
- (* Constrain number to be within the logical number set *)
- ConstrainExNum(number);
-
- (* constrain bitnum from 0 to MaxBase2Bits *)
- IF bitnum > MaxBase2Bits THEN
- (* no bits are changed *)
- Result := number;
- RETURN;
- END;
-
- (* calculate 2**bitnum *)
- XM.xtoi(Temp, Two, bitnum);
-
- (* set the bitnum bit position *)
- LOp(Result, number, Oper, Temp);
- END LBit;
-
-
- PROCEDURE ExSetBit *(VAR Result : X.ExNumType;
- number : X.ExNumType;
- bitnum : INTEGER);
- BEGIN
- LBit(Result, number, Or, bitnum);
- END ExSetBit;
-
-
- PROCEDURE ExClearBit *(VAR Result : X.ExNumType;
- number : X.ExNumType;
- bitnum : INTEGER);
- BEGIN
- LBit(Result, number, AndNot, bitnum);
- END ExClearBit;
-
-
- PROCEDURE ExToggleBit *(VAR Result : X.ExNumType;
- number : X.ExNumType;
- bitnum : INTEGER);
- BEGIN
- LBit(Result, number, Xor, bitnum);
- END ExToggleBit;
-
-
- PROCEDURE^ ExAnd *(VAR Result : X.ExNumType;
- op1, op2 : X.ExNumType);
-
-
- (*--------------------------------------*)
- (* Local function to extract a bit from *)
- (* an ExNumber. *)
-
- PROCEDURE Bit (number : X.ExNumType;
- bitnum : INTEGER) : BOOLEAN;
- VAR
- Temp : X.ExNumType;
- BEGIN
- (* Constrain number to be within the logical number set *)
- ConstrainExNum(number);
-
- (* constrain bitnum from 0 to MaxBase2Bits - 1 *)
- IF bitnum >= MaxBase2Bits THEN
- (* assume FALSE *)
- RETURN FALSE;
- END;
-
- (* calculate 2**bitnum *)
- XM.xtoi(Temp, Two, bitnum);
-
- (* extract the bitnum bit *)
- ExAnd(number, number, Temp);
-
- (* translate to boolean *)
- RETURN NOT X.IsZero(number);
- END Bit;
-
-
- (*--------------------------------------*)
- (* Local procedure to perform general *)
- (* bit shifting operations on ExNumbers.*)
-
- PROCEDURE LShift (VAR Result : X.ExNumType;
- number : X.ExNumType;
- ExOper : ExNumbProc;
- bits : INTEGER);
- VAR
- Temp : X.ExNumType;
- BEGIN
- (* Constrain number to be within the logical number set *)
- ConstrainExNum(number);
-
- (* constrain bitnum from 0 to MaxBase2Bits *)
- IF bits > MaxBase2Bits THEN
- (* shifted out of range *)
- Result := X.Ex0;
- RETURN;
- END;
-
- (* calculate 2**bits *)
- XM.xtoi(Temp, Two, bits);
-
- (* shift the number *)
- ExOper(Result, number, Temp);
-
- (* Constrain number to be within the logical number set *)
- ConstrainExNum(Result);
- END LShift;
-
-
- (*--------------------------------------*)
- (* Local procedure to perform general *)
- (* bit rotation operations on ExNumbers.*)
-
- PROCEDURE LRotate (VAR Result : X.ExNumType;
- number : X.ExNumType;
- Shiftright : BOOLEAN;
- bits : INTEGER);
- VAR
- ShiftCnt : INTEGER;
- SavedBit : BOOLEAN;
- Half : X.ExNumType;
- BEGIN
- (* Constrain number to be within the logical number set *)
- ConstrainExNum(number);
-
- (* constrain bitnum from 0 to MaxBase2Bits *)
- bits := bits MOD (MaxBase2Bits + 1);
- X.ExNumb(0, 5, 0, Half);
-
- FOR ShiftCnt := 1 TO bits DO
- IF Shiftright THEN
- (* save the bit to be shifted *)
- SavedBit := Bit(number, 0);
-
- (* shift the number right *)
- X.ExMult(number, number, Half);
- X.ExTrunc(number);
- IF SavedBit THEN
- ExSetBit(number, number, MaxBase2Bits-1);
- END;
- ELSE
- (* save the bit to be shifted *)
- SavedBit := Bit(number, MaxBase2Bits-1);
-
- (* shift the number left *)
- X.ExMult(number, number, Two);
-
- (* restore the saved bit *)
- IF SavedBit THEN
- ExSetBit(number, number, 0);
- END;
- END;
-
- END;
-
- (* Constrain number to be within the logical number set *)
- Result := number;
- ConstrainExNum(Result);
- END LRotate;
-
-
- (*--------------------------------------*)
- (* Exported procedures. *)
-
- PROCEDURE ExAnd *(VAR Result : X.ExNumType;
- op1, op2 : X.ExNumType);
- BEGIN
- LOp(Result, op1, And, op2);
- END ExAnd;
-
-
- PROCEDURE ExOr *(VAR Result : X.ExNumType;
- op1, op2 : X.ExNumType);
- BEGIN
- LOp(Result, op1, Or, op2);
- END ExOr;
-
-
- PROCEDURE ExXor *(VAR Result : X.ExNumType;
- op1, op2 : X.ExNumType);
- BEGIN
- LOp(Result, op1, Xor, op2);
- END ExXor;
-
-
- PROCEDURE ExIntDiv *(VAR Result : X.ExNumType;
- op1, op2 : X.ExNumType);
- BEGIN
- (* Constrain inputs to be integers *)
- ConstrainExNum(op1); ConstrainExNum(op2);
- X.ExDiv(Result, op1, op2);
- X.ExTrunc(Result);
- END ExIntDiv;
-
-
- PROCEDURE ExMod *(VAR Result : X.ExNumType;
- op1, op2 : X.ExNumType);
- BEGIN
- (* Result := op1 - (op1 DIV op2) * op2 *)
- ConstrainExNum(op1); ConstrainExNum(op2);
- ExIntDiv(Result, op1, op2);
- X.ExMult(Result, Result, op2);
- X.ExSub(Result, op1, Result);
- END ExMod;
-
-
- PROCEDURE ExOnesComp *(VAR Result : X.ExNumType;
- number : X.ExNumType);
- BEGIN
- (* Constrain number to be within the logical number set *)
- ConstrainExNum(number);
- IF number.Sign = X.positive THEN
- (* Subtract from the maximum number *)
- X.ExSub(Result, MaxNumber, number);
- ELSE
- (* Subtract from the minimum number *)
- X.ExSub(Result, MinNumber, number);
- END;
-
- (* Complement the sign bit *)
- X.ExChgSign(Result);
- END ExOnesComp;
-
-
- PROCEDURE ExShl *(VAR Result : X.ExNumType;
- number : X.ExNumType;
- numbits : INTEGER);
- BEGIN
- LShift(Result, number, X.ExMult, numbits);
-
- (* Determine the resultant sign *)
- X.ExAbs(Result);
- IF Bit (Result, MaxBase2Bits-1) THEN
- X.ExChgSign(Result); (* negate *)
- END;
- END ExShl;
-
-
- PROCEDURE ExRol *(VAR Result : X.ExNumType;
- number : X.ExNumType;
- numbits : INTEGER);
- BEGIN
- LRotate(Result, number, Left, numbits);
- END ExRol;
-
-
- PROCEDURE ExShr *(VAR Result : X.ExNumType;
- number : X.ExNumType;
- numbits : INTEGER);
- BEGIN
- LShift(Result, number, X.ExDiv, numbits);
- X.ExAbs(Result); (* clear the sign *)
- END ExShr;
-
-
- PROCEDURE ExAshr *(VAR Result : X.ExNumType;
- number : X.ExNumType;
- numbits : INTEGER);
- VAR
- ShiftCnt : INTEGER;
- SavedBit : BOOLEAN;
- BEGIN
- (* Constrain number to be within the logical number set *)
- ConstrainExNum(number);
-
- (* constrain bitnum from 0 to MaxBase2Bits *)
- IF numbits > MaxBase2Bits THEN
- (* shifted out of range *)
- Result := X.Ex0;
- RETURN;
- END;
-
- (* set the SavedBit to the current sign *)
- SavedBit := number.Sign = X.negative;
-
- (* shift the number *)
- FOR ShiftCnt := 1 TO numbits DO
- (* shift the number right *)
- X.ExDiv(number, number, Two);
-
- (* restore the saved bit *)
- IF SavedBit THEN
- ExSetBit(number, number, MaxBase2Bits-1);
- END;
- END;
-
- (* truncate any fraction *)
- Result := number;
- X.ExTrunc(Result);
- END ExAshr;
-
-
- PROCEDURE ExRor *(VAR Result : X.ExNumType;
- number : X.ExNumType;
- numbits : INTEGER);
- BEGIN
- LRotate(Result, number, Right, numbits);
- END ExRor;
-
-
- (* $CopyArrays- *)
- PROCEDURE StrToExInt *(S : ARRAY OF CHAR;
- Base : BaseType;
- VAR A : X.ExNumType);
- VAR
- EndCnt, InCnt : LONGINT;
- Multiplier : INTEGER;
- Scale, Temp : X.ExNumType;
-
- PROCEDURE DigitIs() : LONGINT;
- VAR
- Str : ARRAY 2 OF CHAR;
- Digits : LONGINT;
- BEGIN
- (* Extract a digit *)
- Str[0] := S[InCnt]; Str[1] := 0X;
- INC(InCnt);
-
- IF ~Cnv.StrToInt(Str, Digits, Base) THEN
- X.ExStatus := X.IllegalNumber;
- RETURN 0;
- END;
- RETURN Digits;
- END DigitIs;
-
- BEGIN
- A := X.Ex0;
- InCnt := 0;
- EndCnt := Str.Length(S);
- X.ExNumb(Base, 0, 0, Scale);
-
- (* skip leading blanks *)
- WHILE (InCnt < EndCnt) & (S[InCnt] = ' ') DO INC(InCnt) END;
-
- WHILE (InCnt < EndCnt) & (X.ExStatus # X.IllegalNumber) DO
- X.ExNumb(DigitIs(), 0, 0, Temp);
- X.ExMult(A, A, Scale);
- X.ExAdd(A, A, Temp);
- END;
- END StrToExInt;
-
-
- PROCEDURE ExIntToStr*(A : X.ExNumType;
- Base : BaseType;
- VAR S : ARRAY OF CHAR);
- VAR
- InCnt : INTEGER;
- InvScale, Scale, Temp, Temp2 : X.ExNumType;
-
- PROCEDURE PutDigits(Numb : LONGINT);
- VAR
- Res : ARRAY 81 OF CHAR;
- Ok : BOOLEAN;
- BEGIN
- Ok := Cnv.IntToStr(Numb, Res, Base, 4, '0');
- Str.Insert(S, 0, Res);
- END PutDigits;
-
- BEGIN
- (* Constrain number to be within the logical number set *)
- ConstrainExNum(A);
-
- S := "";
- InCnt := 0;
- X.ExNumb(Base, 0, 0, Scale);
- XM.xtoi(Scale, Scale, 4);
- X.ExDiv(InvScale, X.Ex1, Scale);
-
- (* translate number to a string *)
- REPEAT
- (* Temp := A MOD Scale *)
- X.ExMult(Temp2, A, InvScale);
- X.ExTrunc(Temp2);
- X.ExMult(Temp, Temp2, Scale);
- X.ExSub(Temp, A, Temp);
-
- (* Translate to character *)
- PutDigits(X.ExToLongInt(Temp));
-
- (* Reduce A by scaling factor *)
- A := Temp2;
- UNTIL X.IsZero(A);
- END ExIntToStr;
-
-
- BEGIN
- (* create the number 2 *)
- X.ExNumb(2, 0, 0, Two);
-
- (* Initialize the maximum number *)
- XM.xtoi(MaxNumber, Two, MaxBase2Bits);
- X.ExSub(MaxNumber, MaxNumber, X.Ex1);
-
- (* Initialize the minimum number *)
- MinNumber := MaxNumber;
- X.ExChgSign(MinNumber);
-
- (* Initialize the zero logical *)
- FOR Cnt := 0 TO LogicalSize DO
- LogZero[Cnt] := {};
- END;
- END ExIntegers.
-