home *** CD-ROM | disk | FTP | other *** search
/ Hall of Fame / HallofFameCDROM.cdr / pcmag / v9n10.lzh / NUMBERS.PAS < prev    next >
Pascal/Delphi Source File  |  1989-11-04  |  9KB  |  324 lines

  1. UNIT numbers;
  2.  
  3. (********************)
  4. (**)  INTERFACE   (**)
  5. (********************)
  6.  
  7. CONST POOLSIZE = 128;
  8.  
  9. TYPE
  10.   NumberPtr = ^Number;
  11.   NPPtr = ^NumberPool;
  12.   Number = object
  13.     np : NPPtr;
  14.     CONSTRUCTOR init(iNp : NPPtr);
  15.     DESTRUCTOR done;
  16.     FUNCTION  im : Real; virtual;
  17.     FUNCTION  re : Real; virtual;
  18.     FUNCTION  equal(VAR nv : Number) : Boolean; virtual;
  19.     FUNCTION  numer : Integer; virtual;
  20.     FUNCTION  denom : Integer; virtual;
  21.     PROCEDURE error(s : STRING);
  22.     PROCEDURE cleanup;
  23.     FUNCTION  GetPool : NPPtr;
  24.   END;
  25.  
  26.   ComplexPtr = ^Complex;
  27.   Complex = object(Number)
  28.     a, b : Real;
  29.     CONSTRUCTOR init(x, y : Real; iNp : NPPtr);
  30.     CONSTRUCTOR initFrom(VAR nv : complex);
  31.     CONSTRUCTOR ReadLn(iNp : NPPtr);
  32.     DESTRUCTOR done;
  33.     FUNCTION im : Real; virtual;
  34.     FUNCTION re : Real; virtual;
  35.     FUNCTION equal(VAR nv : Number) : Boolean; virtual;
  36.     FUNCTION asString : STRING;
  37.     FUNCTION plus(VAR nv : Number) : ComplexPtr;
  38.     FUNCTION minus(VAR nv : Number) : ComplexPtr;
  39.     FUNCTION times(VAR nv : Number) : ComplexPtr;
  40.     FUNCTION divBy(VAR nv : Number) : ComplexPtr;
  41.   END;
  42.  
  43.   RationalPtr = ^Rational;
  44.   Rational = object(Number)
  45.     n, d : LongInt;
  46.     CONSTRUCTOR init(x, y : LongInt; iNp : NPPtr);
  47.     CONSTRUCTOR InitFrom(VAR nv : Rational);
  48.     CONSTRUCTOR ReadLn(iNp : NPPtr);
  49.     DESTRUCTOR done;
  50.     FUNCTION  re : Real; virtual;
  51.     FUNCTION  im : Real; virtual;
  52.     FUNCTION  equal(VAR nv : Number) : Boolean; virtual;
  53.     FUNCTION  numer : Integer; virtual;
  54.     FUNCTION  denom : Integer; virtual;
  55.     FUNCTION  asString : STRING;
  56.     FUNCTION  plus (VAR nv : Number) : RationalPtr;
  57.     FUNCTION  minus(VAR nv : Number) : RationalPtr;
  58.     FUNCTION  times(VAR nv : Number) : RationalPtr;
  59.     FUNCTION  divBy(VAR nv : Number) : RationalPtr;
  60.     PROCEDURE reduce;
  61.   END;
  62.  
  63.   Pool = object
  64.     p : ARRAY[1..POOLSIZE] OF NumberPtr;
  65.     ixcur : 1..POOLSIZE;
  66.     PROCEDURE init;
  67.     PROCEDURE gc;
  68.   END;
  69.  
  70.   NumberPool = object(Pool)
  71.     FUNCTION newComplexPtr(x, y : Real) : ComplexPtr;
  72.     FUNCTION newRationalPtr(x, y : LongInt) : RationalPtr;
  73.   END;
  74.  
  75. (********************)
  76. (**)IMPLEMENTATION(**)
  77. (********************)
  78.  
  79.   PROCEDURE Pool.init; BEGIN ixcur := 1; END;
  80.  
  81.   PROCEDURE Pool.gc; {Garbage Collection}
  82.   VAR i : Integer;
  83.   BEGIN
  84.     FOR i := 1 TO ixcur-1 DO Dispose(p[i],done);
  85.     ixcur := 1;
  86.   END;
  87.  
  88.   FUNCTION NumberPool.newComplexPtr(x, y : Real) : ComplexPtr;
  89.   BEGIN
  90.     p[ixcur] := New(ComplexPtr, init(x, y, @self));
  91.     newComplexPtr := ComplexPtr(p[ixcur]);
  92.     Inc(ixcur);
  93.   END;
  94.  
  95.   FUNCTION NumberPool.newRationalPtr(x, y : LongInt) : RationalPtr;
  96.   BEGIN
  97.     p[ixcur] := New(RationalPtr, init(x, y, @self));
  98.     newRationalPtr := RationalPtr(p[ixcur]);
  99.     Inc(ixcur);
  100.   END;
  101.  
  102. (************* Methods for Object: Number ************)
  103.  
  104.   constructor Number.init(iNp : NPPtr); BEGIN np := iNp; END;
  105.  
  106.   DESTRUCTOR Number.done; BEGIN END;
  107.  
  108.   PROCEDURE Number.error(s : STRING);
  109.   BEGIN
  110.     WriteLn('Error in class "Number": ', s);
  111.     Halt(1);
  112.   END;
  113.  
  114.   FUNCTION Number.im : Real; BEGIN error('im'); END;
  115.  
  116.   FUNCTION Number.re : Real; BEGIN error('re'); END;
  117.  
  118.   FUNCTION Number.numer : Integer; BEGIN error('numer'); END;
  119.  
  120.   FUNCTION Number.denom : Integer; BEGIN error('denom'); END;
  121.  
  122.   FUNCTION Number.equal(VAR nv : Number) : Boolean;
  123.   BEGIN error('equal') END;
  124.  
  125.   PROCEDURE Number.Cleanup; BEGIN np^.gc; END;
  126.  
  127.   FUNCTIOn Number.GetPool : NPPtr; BEGIN GetPool := np; END;
  128.  
  129.   (************* Methods for Object: Complex ***********)
  130.  
  131.   CONSTRUCTOR Complex.init(x, y : Real; iNp : NPPtr);
  132.   BEGIN a := x; b := y; Number.Init(iNp); END;
  133.  
  134.   CONSTRUCTOR complex.initFrom(VAR nv : Complex);
  135.   BEGIN Init(nv.re, nv.im, nv.getpool); END;
  136.  
  137.   CONSTRUCTOR Complex.ReadLn(iNp : NPPtr);
  138.   VAR s : STRING;
  139.     p, q, err : Integer;
  140.   BEGIN
  141.     System.ReadLn(s);
  142.     p := pos('+', s);
  143.     IF p = 0 THEN
  144.       BEGIN
  145.         p := pos('-',Copy(S,2,pred(length(S))));
  146.         IF p > 0 THEN inc(P);
  147.       END;
  148.     q := pos('i', s);
  149.     IF (p = 0) THEN
  150.       BEGIN
  151.         IF q <> 0 THEN Fail;
  152.         Val(s, a, err);
  153.         IF err <> 0 THEN Fail;
  154.         b := 0;
  155.       END
  156.     ELSE
  157.       BEGIN
  158.         IF q = 0 THEN Fail;
  159.         Val(Copy(s, 1, p-1), a, err);
  160.         IF err <> 0 THEN Fail;
  161.         Val(Copy(s, p+1, q-p-1), b, err);
  162.         IF err <> 0 THEN Fail;
  163.       END;
  164.     IF s[p] = '-' THEN b := -b;
  165.     init(a, b, np);
  166.   END;
  167.  
  168.   DESTRUCTOR Complex.done; BEGIN END;
  169.  
  170.   FUNCTION Complex.im : Real; BEGIN im := b; END;
  171.  
  172.   FUNCTION Complex.re : Real; BEGIN re := a; END;
  173.  
  174.   FUNCTION Complex.equal(VAR nv : Number) : Boolean;
  175.   BEGIN equal := (a = nv.re) AND (b = nv.im); END;
  176.  
  177.   FUNCTION Complex.asString : STRING;
  178.   VAR ret, s : STRING;
  179.   BEGIN
  180.     Str(a:1:2, ret); Str(abs(b):1:2, s);
  181.     IF b < 0 THEN ret := ret+'-'+s+'i'
  182.     ELSE ret := ret+'+'+s+'i';
  183.     asString := ret;
  184.   END;
  185.  
  186.   FUNCTION Complex.plus(VAR nv : Number) : ComplexPtr;
  187.   BEGIN
  188.     plus := np^.newComplexPtr(a + nv.re, b + nv.im);
  189.   END;
  190.  
  191.   FUNCTION Complex.minus(VAR nv : Number) : ComplexPtr;
  192.   BEGIN
  193.     minus := np^.newComplexPtr(a - nv.re, b - nv.im);
  194.   END;
  195.  
  196.   FUNCTION Complex.times(VAR nv : Number) : ComplexPtr;
  197.   BEGIN
  198.     times := np^.newComplexPtr(a * nv.re - b * nv.im,
  199.                                a * nv.im + b * nv.re);
  200.   END;
  201.  
  202.   FUNCTION Complex.divBy(VAR nv : Number) : ComplexPtr;
  203.   VAR m2 : Real;
  204.   BEGIN
  205.     WITH nv DO m2 := re * re + im * im;
  206.     IF (m2 = 0) THEN error('Attempt to divide by 0 in class Complex');
  207.     divby := np^.newComplexPtr((a * nv.re + b * nv.im) / m2,
  208.                                (b * nv.re - a * nv.im) / m2);
  209.   END;
  210.  
  211.   (************* Methods for Object: Rational **********)
  212.  
  213.   CONSTRUCTOR Rational.init(x, y : LongInt; iNp : NPPtr);
  214.   BEGIN
  215.     IF (y = 0) THEN BEGIN
  216.       WriteLn('Attempt to init Rational with zero denominator');
  217.       Halt(1);
  218.     END;
  219.     n := x; d := y;
  220.     reduce;
  221.     Number.Init(iNp);
  222.   END;
  223.  
  224.   CONSTRUCTOR Rational.InitFrom(var nv : Rational);
  225.   BEGIN Init(nv.numer, nv.denom, nv.getpool); END;
  226.  
  227.   CONSTRUCTOR Rational.ReadLn(iNp : NPPtr);
  228.   VAR s : STRING;
  229.       p, err : Integer;
  230.   BEGIN
  231.     System.ReadLn(s);
  232.     p := pos('/', s);
  233.     IF (p = 0) THEN
  234.       BEGIN
  235.         Val(s, n, err);
  236.         IF err <> 0 THEN Fail;
  237.         d := 1;
  238.       END
  239.     ELSE
  240.       BEGIN
  241.         Val(Copy(s, 1, p-1), n, err);
  242.         IF err <> 0 THEN Fail;
  243.         Val(Copy(s, p+1, Length(s)), d, err);
  244.         IF err <> 0 THEN Fail;
  245.       END;
  246.     init(n, d, inp);
  247.   END;
  248.  
  249.   DESTRUCTOR rational.done; BEGIN END;
  250.  
  251.   PROCEDURE Rational.reduce;
  252.   VAR g : LongInt;
  253.  
  254.     FUNCTION gcd(x, y : LongInt) : LongInt;
  255.     VAR r : LongInt;
  256.     BEGIN
  257.       WHILE (y <> 0) DO
  258.         BEGIN
  259.           r := x MOD y;
  260.           x := y;
  261.           y := r
  262.         END;
  263.       gcd := x;
  264.     END;
  265.  
  266.   BEGIN
  267.     IF (d < 0) THEN BEGIN d := -d; n := -n; END;
  268.     g := gcd(n, d);
  269.     IF (g <> 0) AND (g <> 1) AND (g <> -1) THEN
  270.       BEGIN
  271.         n := n DIV g;
  272.         d := d DIV g;
  273.       END;
  274.   END;
  275.  
  276.   FUNCTION Rational.re : Real; BEGIN re := n/d; END;
  277.  
  278.   FUNCTION Rational.im : Real; BEGIN im := 0;   END;
  279.  
  280.   FUNCTION Rational.numer : Integer; BEGIN numer := n; END;
  281.  
  282.   FUNCTION Rational.denom : Integer; BEGIN denom := d; END;
  283.  
  284.   FUNCTION Rational.asString : STRING;
  285.   VAR t, u : STRING;
  286.   BEGIN
  287.     Str(n, t);
  288.     IF (d <> 1) THEN
  289.       BEGIN Str(d, u); t := t+'/'+u; END;
  290.     asString := t;
  291.   END;
  292.  
  293.   FUNCTION Rational.plus(VAR nv : Number) : RationalPtr;
  294.   BEGIN
  295.     plus := np^.newRationalPtr(n * nv.denom + d * nv.numer, d * nv.denom);
  296.   END;
  297.  
  298.   FUNCTION Rational.minus(VAR nv : Number) : RationalPtr;
  299.   BEGIN
  300.     minus := np^.newRationalPtr(n * nv.denom - d * nv.numer, d * nv.denom);
  301.   END;
  302.  
  303.   FUNCTION Rational.times(VAR nv : Number) : RationalPtr;
  304.   BEGIN
  305.     times := np^.newRationalPtr(n * nv.numer, d * nv.denom);
  306.   END;
  307.  
  308.   FUNCTION Rational.divBy(VAR nv : Number) : RationalPtr;
  309.   BEGIN
  310.     IF (nv.numer = 0) THEN BEGIN
  311.       WriteLn('Attempt to divide by 0 in class Rational');
  312.       Halt(1)
  313.     END;
  314.     divby := np^.newRationalPtr(n * nv.denom, d * nv.numer);
  315.   END;
  316.  
  317.   FUNCTION Rational.equal(VAR nv : Number) : Boolean;
  318.   BEGIN
  319.     equal := (n = nv.numer) AND (d = nv.denom);
  320.   END;
  321.  
  322. END.
  323.  
  324.