home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hall of Fame
/
HallofFameCDROM.cdr
/
pcmag
/
v9n10.lzh
/
NUMBERS.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1989-11-04
|
9KB
|
324 lines
UNIT numbers;
(********************)
(**) INTERFACE (**)
(********************)
CONST POOLSIZE = 128;
TYPE
NumberPtr = ^Number;
NPPtr = ^NumberPool;
Number = object
np : NPPtr;
CONSTRUCTOR init(iNp : NPPtr);
DESTRUCTOR done;
FUNCTION im : Real; virtual;
FUNCTION re : Real; virtual;
FUNCTION equal(VAR nv : Number) : Boolean; virtual;
FUNCTION numer : Integer; virtual;
FUNCTION denom : Integer; virtual;
PROCEDURE error(s : STRING);
PROCEDURE cleanup;
FUNCTION GetPool : NPPtr;
END;
ComplexPtr = ^Complex;
Complex = object(Number)
a, b : Real;
CONSTRUCTOR init(x, y : Real; iNp : NPPtr);
CONSTRUCTOR initFrom(VAR nv : complex);
CONSTRUCTOR ReadLn(iNp : NPPtr);
DESTRUCTOR done;
FUNCTION im : Real; virtual;
FUNCTION re : Real; virtual;
FUNCTION equal(VAR nv : Number) : Boolean; virtual;
FUNCTION asString : STRING;
FUNCTION plus(VAR nv : Number) : ComplexPtr;
FUNCTION minus(VAR nv : Number) : ComplexPtr;
FUNCTION times(VAR nv : Number) : ComplexPtr;
FUNCTION divBy(VAR nv : Number) : ComplexPtr;
END;
RationalPtr = ^Rational;
Rational = object(Number)
n, d : LongInt;
CONSTRUCTOR init(x, y : LongInt; iNp : NPPtr);
CONSTRUCTOR InitFrom(VAR nv : Rational);
CONSTRUCTOR ReadLn(iNp : NPPtr);
DESTRUCTOR done;
FUNCTION re : Real; virtual;
FUNCTION im : Real; virtual;
FUNCTION equal(VAR nv : Number) : Boolean; virtual;
FUNCTION numer : Integer; virtual;
FUNCTION denom : Integer; virtual;
FUNCTION asString : STRING;
FUNCTION plus (VAR nv : Number) : RationalPtr;
FUNCTION minus(VAR nv : Number) : RationalPtr;
FUNCTION times(VAR nv : Number) : RationalPtr;
FUNCTION divBy(VAR nv : Number) : RationalPtr;
PROCEDURE reduce;
END;
Pool = object
p : ARRAY[1..POOLSIZE] OF NumberPtr;
ixcur : 1..POOLSIZE;
PROCEDURE init;
PROCEDURE gc;
END;
NumberPool = object(Pool)
FUNCTION newComplexPtr(x, y : Real) : ComplexPtr;
FUNCTION newRationalPtr(x, y : LongInt) : RationalPtr;
END;
(********************)
(**)IMPLEMENTATION(**)
(********************)
PROCEDURE Pool.init; BEGIN ixcur := 1; END;
PROCEDURE Pool.gc; {Garbage Collection}
VAR i : Integer;
BEGIN
FOR i := 1 TO ixcur-1 DO Dispose(p[i],done);
ixcur := 1;
END;
FUNCTION NumberPool.newComplexPtr(x, y : Real) : ComplexPtr;
BEGIN
p[ixcur] := New(ComplexPtr, init(x, y, @self));
newComplexPtr := ComplexPtr(p[ixcur]);
Inc(ixcur);
END;
FUNCTION NumberPool.newRationalPtr(x, y : LongInt) : RationalPtr;
BEGIN
p[ixcur] := New(RationalPtr, init(x, y, @self));
newRationalPtr := RationalPtr(p[ixcur]);
Inc(ixcur);
END;
(************* Methods for Object: Number ************)
constructor Number.init(iNp : NPPtr); BEGIN np := iNp; END;
DESTRUCTOR Number.done; BEGIN END;
PROCEDURE Number.error(s : STRING);
BEGIN
WriteLn('Error in class "Number": ', s);
Halt(1);
END;
FUNCTION Number.im : Real; BEGIN error('im'); END;
FUNCTION Number.re : Real; BEGIN error('re'); END;
FUNCTION Number.numer : Integer; BEGIN error('numer'); END;
FUNCTION Number.denom : Integer; BEGIN error('denom'); END;
FUNCTION Number.equal(VAR nv : Number) : Boolean;
BEGIN error('equal') END;
PROCEDURE Number.Cleanup; BEGIN np^.gc; END;
FUNCTIOn Number.GetPool : NPPtr; BEGIN GetPool := np; END;
(************* Methods for Object: Complex ***********)
CONSTRUCTOR Complex.init(x, y : Real; iNp : NPPtr);
BEGIN a := x; b := y; Number.Init(iNp); END;
CONSTRUCTOR complex.initFrom(VAR nv : Complex);
BEGIN Init(nv.re, nv.im, nv.getpool); END;
CONSTRUCTOR Complex.ReadLn(iNp : NPPtr);
VAR s : STRING;
p, q, err : Integer;
BEGIN
System.ReadLn(s);
p := pos('+', s);
IF p = 0 THEN
BEGIN
p := pos('-',Copy(S,2,pred(length(S))));
IF p > 0 THEN inc(P);
END;
q := pos('i', s);
IF (p = 0) THEN
BEGIN
IF q <> 0 THEN Fail;
Val(s, a, err);
IF err <> 0 THEN Fail;
b := 0;
END
ELSE
BEGIN
IF q = 0 THEN Fail;
Val(Copy(s, 1, p-1), a, err);
IF err <> 0 THEN Fail;
Val(Copy(s, p+1, q-p-1), b, err);
IF err <> 0 THEN Fail;
END;
IF s[p] = '-' THEN b := -b;
init(a, b, np);
END;
DESTRUCTOR Complex.done; BEGIN END;
FUNCTION Complex.im : Real; BEGIN im := b; END;
FUNCTION Complex.re : Real; BEGIN re := a; END;
FUNCTION Complex.equal(VAR nv : Number) : Boolean;
BEGIN equal := (a = nv.re) AND (b = nv.im); END;
FUNCTION Complex.asString : STRING;
VAR ret, s : STRING;
BEGIN
Str(a:1:2, ret); Str(abs(b):1:2, s);
IF b < 0 THEN ret := ret+'-'+s+'i'
ELSE ret := ret+'+'+s+'i';
asString := ret;
END;
FUNCTION Complex.plus(VAR nv : Number) : ComplexPtr;
BEGIN
plus := np^.newComplexPtr(a + nv.re, b + nv.im);
END;
FUNCTION Complex.minus(VAR nv : Number) : ComplexPtr;
BEGIN
minus := np^.newComplexPtr(a - nv.re, b - nv.im);
END;
FUNCTION Complex.times(VAR nv : Number) : ComplexPtr;
BEGIN
times := np^.newComplexPtr(a * nv.re - b * nv.im,
a * nv.im + b * nv.re);
END;
FUNCTION Complex.divBy(VAR nv : Number) : ComplexPtr;
VAR m2 : Real;
BEGIN
WITH nv DO m2 := re * re + im * im;
IF (m2 = 0) THEN error('Attempt to divide by 0 in class Complex');
divby := np^.newComplexPtr((a * nv.re + b * nv.im) / m2,
(b * nv.re - a * nv.im) / m2);
END;
(************* Methods for Object: Rational **********)
CONSTRUCTOR Rational.init(x, y : LongInt; iNp : NPPtr);
BEGIN
IF (y = 0) THEN BEGIN
WriteLn('Attempt to init Rational with zero denominator');
Halt(1);
END;
n := x; d := y;
reduce;
Number.Init(iNp);
END;
CONSTRUCTOR Rational.InitFrom(var nv : Rational);
BEGIN Init(nv.numer, nv.denom, nv.getpool); END;
CONSTRUCTOR Rational.ReadLn(iNp : NPPtr);
VAR s : STRING;
p, err : Integer;
BEGIN
System.ReadLn(s);
p := pos('/', s);
IF (p = 0) THEN
BEGIN
Val(s, n, err);
IF err <> 0 THEN Fail;
d := 1;
END
ELSE
BEGIN
Val(Copy(s, 1, p-1), n, err);
IF err <> 0 THEN Fail;
Val(Copy(s, p+1, Length(s)), d, err);
IF err <> 0 THEN Fail;
END;
init(n, d, inp);
END;
DESTRUCTOR rational.done; BEGIN END;
PROCEDURE Rational.reduce;
VAR g : LongInt;
FUNCTION gcd(x, y : LongInt) : LongInt;
VAR r : LongInt;
BEGIN
WHILE (y <> 0) DO
BEGIN
r := x MOD y;
x := y;
y := r
END;
gcd := x;
END;
BEGIN
IF (d < 0) THEN BEGIN d := -d; n := -n; END;
g := gcd(n, d);
IF (g <> 0) AND (g <> 1) AND (g <> -1) THEN
BEGIN
n := n DIV g;
d := d DIV g;
END;
END;
FUNCTION Rational.re : Real; BEGIN re := n/d; END;
FUNCTION Rational.im : Real; BEGIN im := 0; END;
FUNCTION Rational.numer : Integer; BEGIN numer := n; END;
FUNCTION Rational.denom : Integer; BEGIN denom := d; END;
FUNCTION Rational.asString : STRING;
VAR t, u : STRING;
BEGIN
Str(n, t);
IF (d <> 1) THEN
BEGIN Str(d, u); t := t+'/'+u; END;
asString := t;
END;
FUNCTION Rational.plus(VAR nv : Number) : RationalPtr;
BEGIN
plus := np^.newRationalPtr(n * nv.denom + d * nv.numer, d * nv.denom);
END;
FUNCTION Rational.minus(VAR nv : Number) : RationalPtr;
BEGIN
minus := np^.newRationalPtr(n * nv.denom - d * nv.numer, d * nv.denom);
END;
FUNCTION Rational.times(VAR nv : Number) : RationalPtr;
BEGIN
times := np^.newRationalPtr(n * nv.numer, d * nv.denom);
END;
FUNCTION Rational.divBy(VAR nv : Number) : RationalPtr;
BEGIN
IF (nv.numer = 0) THEN BEGIN
WriteLn('Attempt to divide by 0 in class Rational');
Halt(1)
END;
divby := np^.newRationalPtr(n * nv.denom, d * nv.numer);
END;
FUNCTION Rational.equal(VAR nv : Number) : Boolean;
BEGIN
equal := (n = nv.numer) AND (d = nv.denom);
END;
END.