MODULE NbrInt64;
IMPORT SYSTEM, NbrInt8, NbrInt16, NbrInt32, Streams;
TYPE
Integer* = RECORD
low, hi: NbrInt32.Integer
END;
VAR
MinNbr-, MaxNbr-, One, Two: Integer;
CONST
Eq = 4000H; Lt = 100H; Gt = 000H;
PROCEDURE -Compare( ): NbrInt32.Integer;
CODE {SYSTEM.i386, SYSTEM.FPU}
FILD QWORD [EBP+8] ; b- > ST(1)
FILD QWORD [EBP+16] ; a- > ST(0)
FCOMPP
DB 9BH, 0DFH, 0E0H ; FSTSW AX
AND EAX, 4500H ; use c3, c2, c0
END Compare;
PROCEDURE ">"*( a, b: Integer ): BOOLEAN;
BEGIN
RETURN Compare() = Gt
END ">";
PROCEDURE ">"*( a: Integer; b: NbrInt32.Integer ): BOOLEAN;
BEGIN
RETURN a > Long( b )
END ">";
PROCEDURE ">"*( a: Integer; b: NbrInt16.Integer ): BOOLEAN;
BEGIN
RETURN a > Long( NbrInt32.Long( b ) )
END ">";
PROCEDURE ">"*( a: Integer; b: NbrInt8.Integer ): BOOLEAN;
BEGIN
RETURN a > Long( NbrInt32.Long( NbrInt16.Long( b ) ) )
END ">";
PROCEDURE ">"*( a: NbrInt32.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( a ) > b
END ">";
PROCEDURE ">"*( a: NbrInt16.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( NbrInt32.Long( a ) ) > b
END ">";
PROCEDURE ">"*( a: NbrInt8.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( NbrInt32.Long( NbrInt16.Long( a ) ) ) > b
END ">";
PROCEDURE ">="*( a, b: Integer ): BOOLEAN;
BEGIN
RETURN Compare() # Lt
END ">=";
PROCEDURE ">="*( a: Integer; b: NbrInt32.Integer ): BOOLEAN;
BEGIN
RETURN a >= Long( b )
END ">=";
PROCEDURE ">="*( a: Integer; b: NbrInt16.Integer ): BOOLEAN;
BEGIN
RETURN a >= Long( NbrInt32.Long( b ) )
END ">=";
PROCEDURE ">="*( a: Integer; b: NbrInt8.Integer ): BOOLEAN;
BEGIN
RETURN a >= Long( NbrInt32.Long( NbrInt16.Long( b ) ) )
END ">=";
PROCEDURE ">="*( a: NbrInt32.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( a ) >= b
END ">=";
PROCEDURE ">="*( a: NbrInt16.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( NbrInt32.Long( a ) ) >= b
END ">=";
PROCEDURE ">="*( a: NbrInt8.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( NbrInt32.Long( NbrInt16.Long( a ) ) ) >= b
END ">=";
PROCEDURE "<"*( a, b: Integer ): BOOLEAN;
BEGIN
RETURN Compare() = Lt
END "<";
PROCEDURE "<"*( a: Integer; b: NbrInt32.Integer ): BOOLEAN;
BEGIN
RETURN a < Long( b )
END "<";
PROCEDURE "<"*( a: Integer; b: NbrInt16.Integer ): BOOLEAN;
BEGIN
RETURN a < Long( NbrInt32.Long( b ) )
END "<";
PROCEDURE "<"*( a: Integer; b: NbrInt8.Integer ): BOOLEAN;
BEGIN
RETURN a < Long( NbrInt32.Long( NbrInt16.Long( b ) ) )
END "<";
PROCEDURE "<"*( a: NbrInt32.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( a ) < b
END "<";
PROCEDURE "<"*( a: NbrInt16.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( NbrInt32.Long( a ) ) < b
END "<";
PROCEDURE "<"*( a: NbrInt8.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( NbrInt32.Long( NbrInt16.Long( a ) ) ) < b
END "<";
PROCEDURE "<="*( a, b: Integer ): BOOLEAN;
BEGIN
RETURN Compare() # Gt
END "<=";
PROCEDURE "<="*( a: Integer; b: NbrInt32.Integer ): BOOLEAN;
BEGIN
RETURN a <= Long( b )
END "<=";
PROCEDURE "<="*( a: Integer; b: NbrInt16.Integer ): BOOLEAN;
BEGIN
RETURN a <= Long( NbrInt32.Long( b ) )
END "<=";
PROCEDURE "<="*( a: Integer; b: NbrInt8.Integer ): BOOLEAN;
BEGIN
RETURN a <= Long( NbrInt32.Long( NbrInt16.Long( b ) ) )
END "<=";
PROCEDURE "<="*( a: NbrInt32.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( a ) <= b
END "<=";
PROCEDURE "<="*( a: NbrInt16.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( NbrInt32.Long( a ) ) <= b
END "<=";
PROCEDURE "<="*( a: NbrInt8.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( NbrInt32.Long( NbrInt16.Long( a ) ) ) <= b
END "<=";
PROCEDURE "="*( a, b: Integer ): BOOLEAN;
BEGIN
RETURN Compare() = Eq
END "=";
PROCEDURE "="*( a: Integer; b: NbrInt32.Integer ): BOOLEAN;
BEGIN
RETURN a = Long( b )
END "=";
PROCEDURE "="*( a: Integer; b: NbrInt16.Integer ): BOOLEAN;
BEGIN
RETURN a = Long( NbrInt32.Long( b ) )
END "=";
PROCEDURE "="*( a: Integer; b: NbrInt8.Integer ): BOOLEAN;
BEGIN
RETURN a = Long( NbrInt32.Long( NbrInt16.Long( b ) ) )
END "=";
PROCEDURE "="*( a: NbrInt32.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( a ) = b
END "=";
PROCEDURE "="*( a: NbrInt16.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( NbrInt32.Long( a ) ) = b
END "=";
PROCEDURE "="*( a: NbrInt8.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( NbrInt32.Long( NbrInt16.Long( a ) ) ) = b
END "=";
PROCEDURE "#"*( a, b: Integer ): BOOLEAN;
BEGIN
RETURN Compare() # Eq
END "#";
PROCEDURE "#"*( a: Integer; b: NbrInt32.Integer ): BOOLEAN;
BEGIN
RETURN a # Long( b )
END "#";
PROCEDURE "#"*( a: Integer; b: NbrInt16.Integer ): BOOLEAN;
BEGIN
RETURN a # Long( NbrInt32.Long( b ) )
END "#";
PROCEDURE "#"*( a: Integer; b: NbrInt8.Integer ): BOOLEAN;
BEGIN
RETURN a # Long( NbrInt32.Long( NbrInt16.Long( b ) ) )
END "#";
PROCEDURE "#"*( a: NbrInt32.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( a ) # b
END "#";
PROCEDURE "#"*( a: NbrInt16.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( NbrInt32.Long( a ) ) # b
END "#";
PROCEDURE "#"*( a: NbrInt8.Integer; b: Integer ): BOOLEAN;
BEGIN
RETURN Long( NbrInt32.Long( NbrInt16.Long( a ) ) ) # b
END "#";
PROCEDURE "-"*( a: Integer ): Integer;
CODE {SYSTEM.i386, SYSTEM.FPU}
MOV EAX, [EBP+12]
MOV EBX, [EBP+8]
MOV ECX, [EBP+16]
NEG EAX
NEG EBX
SBB EAX, 0
MOV [ECX+4], EAX
MOV [ECX], EBX
END "-";
PROCEDURE ":="*( VAR a: Integer; b: NbrInt32.Integer );
BEGIN
a := Long( b )
END ":=";
PROCEDURE ":="*( VAR a: Integer; b: NbrInt16.Integer );
BEGIN
a := Long( NbrInt32.Long( b ) )
END ":=";
PROCEDURE ":="*( VAR a: Integer; b: NbrInt8.Integer );
BEGIN
a := Long( NbrInt32.Long( NbrInt16.Long( b ) ) )
END ":=";
PROCEDURE "+"*( a, b: Integer ): Integer;
CODE {SYSTEM.i386}
MOV EAX, [EBP+16]
MOV EBX, [EBP+20]
MOV ECX, [EBP+24]
ADD EAX, [EBP+8]
ADC EBX, [EBP+12]
MOV [ECX+0], EAX
MOV [ECX+4], EBX
END "+";
PROCEDURE "+"*( a: Integer; b: NbrInt32.Integer ): Integer;
BEGIN
RETURN a + Long( b )
END "+";
PROCEDURE "+"*( a: Integer; b: NbrInt16.Integer ): Integer;
BEGIN
RETURN a + Long( NbrInt32.Long( b ) )
END "+";
PROCEDURE "+"*( a: Integer; b: NbrInt8.Integer ): Integer;
BEGIN
RETURN a + Long( NbrInt32.Long( NbrInt16.Long( b ) ) )
END "+";
PROCEDURE "+"*( a: NbrInt32.Integer; b: Integer ): Integer;
BEGIN
RETURN Long( a ) + b
END "+";
PROCEDURE "+"*( a: NbrInt16.Integer; b: Integer ): Integer;
BEGIN
RETURN Long( NbrInt32.Long( a ) ) + b
END "+";
PROCEDURE "+"*( a: NbrInt8.Integer; b: Integer ): Integer;
BEGIN
RETURN Long( NbrInt32.Long( NbrInt16.Long( a ) ) ) + b
END "+";
PROCEDURE "-"*( a, b: Integer ): Integer;
CODE {SYSTEM.i386}
MOV EAX, [EBP+16]
MOV EBX, [EBP+20]
MOV ECX, [EBP+24]
SUB EAX, [EBP+8]
SBB EBX, [EBP+12]
MOV [ECX+0], EAX
MOV [ECX+4], EBX
END "-";
PROCEDURE "-"*( a: Integer; b: NbrInt32.Integer ): Integer;
BEGIN
RETURN a - Long( b )
END "-";
PROCEDURE "-"*( a: Integer; b: NbrInt16.Integer ): Integer;
BEGIN
RETURN a - Long( NbrInt32.Long( b ) )
END "-";
PROCEDURE "-"*( a: Integer; b: NbrInt8.Integer ): Integer;
BEGIN
RETURN a - Long( NbrInt32.Long( NbrInt16.Long( b ) ) )
END "-";
PROCEDURE "-"*( a: NbrInt32.Integer; b: Integer ): Integer;
BEGIN
RETURN Long( a ) - b
END "-";
PROCEDURE "-"*( a: NbrInt16.Integer; b: Integer ): Integer;
BEGIN
RETURN Long( NbrInt32.Long( a ) ) - b
END "-";
PROCEDURE "-"*( a: NbrInt8.Integer; b: Integer ): Integer;
BEGIN
RETURN Long( NbrInt32.Long( NbrInt16.Long( a ) ) ) - b
END "-";
PROCEDURE "*"*( a, b: Integer ): Integer;
CODE {SYSTEM.i386, SYSTEM.FPU}
FILD QWORD [EBP+a]
FILD QWORD [EBP+b]
FMULP
MOV EAX, [EBP+24]
FISTP QWORD[EAX]
FWAIT
END "*";
PROCEDURE "*"*( a: Integer; b: NbrInt32.Integer ): Integer;
BEGIN
RETURN a * Long( b )
END "*";
PROCEDURE "*"*( a: Integer; b: NbrInt16.Integer ): Integer;
BEGIN
RETURN a * Long( NbrInt32.Long( b ) )
END "*";
PROCEDURE "*"*( a: Integer; b: NbrInt8.Integer ): Integer;
BEGIN
RETURN a * Long( NbrInt32.Long( NbrInt16.Long( b ) ) )
END "*";
PROCEDURE "*"*( a: NbrInt32.Integer; b: Integer ): Integer;
BEGIN
RETURN Long( a ) * b
END "*";
PROCEDURE "*"*( a: NbrInt16.Integer; b: Integer ): Integer;
BEGIN
RETURN Long( NbrInt32.Long( a ) ) * b
END "*";
PROCEDURE "*"*( a: NbrInt8.Integer; b: Integer ): Integer;
BEGIN
RETURN Long( NbrInt32.Long( NbrInt16.Long( a ) ) ) * b
END "*";
PROCEDURE "DIV"*( a, b: Integer ): Integer;
VAR cw, cw0: INTEGER;
CODE {SYSTEM.i386, SYSTEM.FPU}
MOV EAX, [EBP+12] ; b must be positive(check msb)
CMP EAX, 0
JGE ok
PUSH 8 ; ASSERT Trap
INT 3
ok:
FNCLEX
FSTCW [EBP+cw]
MOV [EBP+cw0], 077AH ; rounding to-infty, allow zero divide, invalid operation
FLDCW [EBP+cw0] ; set rounding to 01, round down
FILD QWORD [EBP+a]
FILD QWORD [EBP+b]
FDIVP
MOV EAX, [EBP+24]
FISTP QWORD[EAX]
FLDCW [EBP+cw] ; reset rounding
FWAIT
END "DIV";
PROCEDURE "DIV"*( a: Integer; b: NbrInt32.Integer ): Integer;
BEGIN
RETURN a DIV Long( b )
END "DIV";
PROCEDURE "DIV"*( a: Integer; b: NbrInt16.Integer ): Integer;
BEGIN
RETURN a DIV Long( NbrInt32.Long( b ) )
END "DIV";
PROCEDURE "DIV"*( a: Integer; b: NbrInt8.Integer ): Integer;
BEGIN
RETURN a DIV Long( NbrInt32.Long( NbrInt16.Long( b ) ) )
END "DIV";
PROCEDURE "DIV"*( a: NbrInt32.Integer; b: Integer ): Integer;
BEGIN
RETURN Long( a ) DIV b
END "DIV";
PROCEDURE "DIV"*( a: NbrInt16.Integer; b: Integer ): Integer;
BEGIN
RETURN Long( NbrInt32.Long( a ) ) DIV b
END "DIV";
PROCEDURE "DIV"*( a: NbrInt8.Integer; b: Integer ): Integer;
BEGIN
RETURN Long( NbrInt32.Long( NbrInt16.Long( a ) ) ) DIV b
END "DIV";
PROCEDURE "MOD"*( a, b: Integer ): Integer;
VAR cw, cw0: INTEGER;
CODE {SYSTEM.i386, SYSTEM.FPU}
MOV EAX, [EBP+12] ; b must be positive(check msb)
CMP EAX, 0
JGE ok
PUSH 8 ; ASSERT Trap
INT 3
ok:
FNCLEX
FSTCW [EBP+cw]
MOV [EBP+cw0], 077FH ; was 77AH- > wrong because zero is not an exception here
FLDCW [EBP+cw0] ; set rounding to 01, round down, mask exceptions
FILD QWORD [EBP+a]
FILD QWORD [EBP+b]
FILD QWORD [EBP+b]
FDIVR ST0, ST2 ; ST(0) := a DIV b = ST(2) DIV ST(0)
FRNDINT
FMULP
FSUBP
MOV EAX, [EBP+24]
FISTP QWORD[EAX]
FLDCW [EBP+cw] ; reset rounding
FWAIT
END "MOD";
PROCEDURE "MOD"*( a: Integer; b: NbrInt32.Integer ): Integer;
BEGIN
RETURN a MOD Long( b )
END "MOD";
PROCEDURE "MOD"*( a: Integer; b: NbrInt16.Integer ): Integer;
BEGIN
RETURN a MOD Long( NbrInt32.Long( b ) )
END "MOD";
PROCEDURE "MOD"*( a: Integer; b: NbrInt8.Integer ): Integer;
BEGIN
RETURN a MOD Long( NbrInt32.Long( NbrInt16.Long( b ) ) )
END "MOD";
PROCEDURE "MOD"*( a: NbrInt32.Integer; b: Integer ): Integer;
BEGIN
RETURN Long( a ) MOD b
END "MOD";
PROCEDURE "MOD"*( a: NbrInt16.Integer; b: Integer ): Integer;
BEGIN
RETURN Long( NbrInt32.Long( a ) ) MOD b
END "MOD";
PROCEDURE "MOD"*( a: NbrInt8.Integer; b: Integer ): Integer;
BEGIN
RETURN Long( NbrInt32.Long( NbrInt16.Long( a ) ) ) MOD b
END "MOD";
PROCEDURE AbsVal( a: Integer ): Integer;
CODE {SYSTEM.i386, SYSTEM.FPU}
FILD QWORD [EBP+a]
FABS
MOV EAX, [EBP+16]
FISTP QWORD[EAX]
FWAIT
END AbsVal;
PROCEDURE Abs*( a: Integer ): Integer;
BEGIN
IF a > MinNbr THEN RETURN AbsVal( a ) ELSE RETURN a END
END Abs;
PROCEDURE Dec*( VAR a: Integer );
BEGIN
IF a > MinNbr THEN
IF a.low = 0 THEN a.hi := a.hi - 1 END;
a.low := a.low - 1
END
END Dec;
PROCEDURE Inc*( VAR a: Integer );
BEGIN
IF a < MaxNbr THEN
IF a.low = -1 THEN a.hi := a.hi + 1 END;
a.low := a.low + 1
END
END Inc;
PROCEDURE Odd*( a: Integer ): BOOLEAN;
BEGIN
RETURN (a MOD Two) = One
END Odd;
PROCEDURE Long*( i: NbrInt32.Integer ): Integer;
CODE {SYSTEM.i386}
MOV EAX, [EBP+i]
CDQ
MOV EBX, [EBP+12]
MOV [EBX+0], EAX
MOV [EBX+4], EDX
END Long;
PROCEDURE IsInt32*( i: Integer ): BOOLEAN;
BEGIN
IF (i >= NbrInt32.MinNbr) & (i <= NbrInt32.MaxNbr) THEN RETURN TRUE ELSE RETURN FALSE END
END IsInt32;
PROCEDURE Short*( h: Integer ): NbrInt32.Integer;
BEGIN
RETURN h.low
END Short;
PROCEDURE Max*( x1, x2: Integer ): Integer;
BEGIN
IF x1 > x2 THEN RETURN x1 ELSE RETURN x2 END
END Max;
PROCEDURE Min*( x1, x2: Integer ): Integer;
BEGIN
IF x1 < x2 THEN RETURN x1 ELSE RETURN x2 END
END Min;
PROCEDURE Sign*( x: Integer ): NbrInt8.Integer;
VAR sign: NbrInt8.Integer;
BEGIN
IF x < 0 THEN sign := -1
ELSIF x = 0 THEN sign := 0
ELSE sign := 1
END;
RETURN sign
END Sign;
PROCEDURE StringToInt*( string: ARRAY OF CHAR; VAR x: Integer );
VAR negative: BOOLEAN; i: NbrInt8.Integer;
BEGIN
i := 0;
WHILE string[i] = CHR( 20H ) DO NbrInt8.Inc( i ) END;
IF string[i] = CHR( 2DH ) THEN negative := TRUE; NbrInt8.Inc( i ) ELSE negative := FALSE END;
x := 0;
WHILE string[i] # 0X DO
IF (CHR( 30H ) <= string[i]) & (string[i] <= CHR( 39H )) THEN x := 10 * x + LONG( ORD( string[i] ) - 30H )
ELSE
END;
NbrInt8.Inc( i )
END;
IF negative THEN x := -x END
END StringToInt;
PROCEDURE IntToString*( x: Integer; VAR string: ARRAY OF CHAR );
VAR positive: BOOLEAN; i, k: NbrInt8.Integer;
a: ARRAY 21 OF CHAR;
BEGIN
IF x > MinNbr THEN
IF x < 0 THEN x := -x; positive := FALSE ELSE positive := TRUE END;
WHILE x > 0 DO a[i] := CHR( Short( x MOD 10 ) + 30H ); x := x DIV 10; NbrInt8.Inc( i ) END;
IF i = 0 THEN a[0] := CHR( 30H ); NbrInt8.Inc( i ) END;
a[i] := 0X; k := 0;
IF ~positive THEN
string[k] := CHR( 2DH ); NbrInt8.Inc( k )
END;
REPEAT
NbrInt8.Dec( i ); string[k] := a[i]; NbrInt8.Inc( k );
IF (i > 0) & ((i MOD 3) = 0) THEN
string[k] := CHR( 2CH ); NbrInt8.Inc( k )
END
UNTIL i = 0;
string[k] := 0X
ELSE COPY( "-9,223,372,036,854,775,808", string )
END
END IntToString;
PROCEDURE Load*( R: Streams.Reader; VAR x: Integer );
BEGIN
NbrInt32.Load( R, x.low ); NbrInt32.Load( R, x.hi )
END Load;
PROCEDURE Store*( W: Streams.Writer; x: Integer );
BEGIN
NbrInt32.Store( W, x.low ); NbrInt32.Store( W, x.hi )
END Store;
BEGIN
MinNbr.low := 0; MinNbr.hi := LONGINT(80000000H); MaxNbr.low :=LONGINT( 0FFFFFFFFH); MaxNbr.hi :=LONGINT( 7FFFFFFFH); One := Long( 1 );
Two := Long( 2 )
END NbrInt64.