Module: internal Author: Jonathan Bachrach Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND //// PROTOCOL // BOOTED: define ... class ... end; // BOOTED: define ... class ... end; // BOOTED: define ... class ... end; // BOOTED: define ... class ... end; ///---*** LET'S ELIMINATE THIS! define generic contagious-type (x :: , y :: ) => (result :: ); ///---*** LET'S ELIMINATE THIS! define inline function contagious-call (function :: , x :: , y :: ) let type :: = contagious-type(x, y); function(as(type, x), as(type, y)) end function contagious-call; define macro numeric-properties-predicate-definer { define numeric-properties-predicate ?:name (?domain:name) } => { define open generic ?name (x :: ) => (result :: ); define sealed domain ?name (?domain) } // Default sealed domain to { define numeric-properties-predicate ?:name } => { define numeric-properties-predicate ?name () } end macro numeric-properties-predicate-definer; define numeric-properties-predicate zero?; define numeric-properties-predicate positive?; define numeric-properties-predicate negative?; define numeric-properties-predicate integral?; /// DRM specifies odd? & even? as being functions restricted to , but /// we extend them to be open generics with methods. define numeric-properties-predicate odd?; define numeric-properties-predicate even?; define macro binary-arithmetic-function-definer { define binary-arithmetic-function ?:name (?domain1:name, ?domain2:name) } => { define open generic ?name (x :: , y :: ) => (#rest values :: ); define sealed domain ?name (?domain1, ?domain2) } // Default sealed domain to (, ) { define binary-arithmetic-function ?:name } => { define binary-arithmetic-function ?name (, ) } end macro binary-arithmetic-function-definer; define binary-arithmetic-function \+; define binary-arithmetic-function \-; define binary-arithmetic-function \*; define binary-arithmetic-function \/; define binary-arithmetic-function \^ (, ); define macro unary-arithmetic-function-definer { define unary-arithmetic-function ?:name (?domain:name) } => { define open generic ?name (x :: ) => (#rest values :: ); define sealed domain ?name (?domain) } // Default sealed domain to { define unary-arithmetic-function ?:name } => { define unary-arithmetic-function ?name () } end macro unary-arithmetic-function-definer; define unary-arithmetic-function negative; define unary-arithmetic-function abs; define generic floor (real :: ) => (result :: , remainder :: ); define generic ceiling (real :: ) => (result :: , remainder :: ); define generic round (real :: ) => (result :: , remainder :: ); define generic truncate (real :: ) => (result :: , remainder :: ); define generic floor/ (real1 :: , real2 :: ) => (result :: , remainder :: ); define generic ceiling/ (real1 :: , real2 :: ) => (result :: , remainder :: ); define generic round/ (real1 :: , real2 :: ) => (result :: , remainder :: ); define generic truncate/ (real1 :: , real2 :: ) => (result :: , remainder :: ); define generic modulo (real1 :: , real2 :: ) => (result :: ); define generic remainder (real1 :: , real2 :: ) => (result :: ); //// CONDITIONS define open abstract class (, ) inherited slot condition-format-string = "Arithmetic error"; end class ; define sealed class () inherited slot condition-format-string = "Division by zero"; end class ; define sealed domain make (singleton()); define sealed domain initialize (); define sealed class () inherited slot condition-format-string = "Arithmetic overflow"; end class ; define sealed domain make (singleton()); define sealed domain initialize (); define sealed class () inherited slot condition-format-string = "Arithmetic underflow"; end class ; define sealed domain make (singleton()); define sealed domain initialize (); //// IMPLEMENTATION // Currently only is implemented, with domains sealed over . // Someday either further restrict the sealed domains or implement . ///---*** kab, 4-June-96: These comparison methods are wrong. ///---*** Using contagious-call makes them non-transitive (cf CLtL vs ANSI-CL). ///---*** Further, the DRM states that comparing a and a should ///---*** convert the to a ; we're doing the opposite. ///---*** I don't have time to fix them right now, so just noting it for later. define macro binary-comparison-method-definer { define binary-comparison-method ?:name } => { define method ?name (x :: , y :: ) => (result :: ) contagious-call(?name, x, y) end method ?name; define sealed domain ?name (, ) } end macro binary-comparison-method-definer; define binary-comparison-method \=; define binary-comparison-method \<; define macro binary-arithmetic-method-definer { define binary-arithmetic-method ?:name } => { define inline method ?name (x :: , y :: ) => (result :: ) contagious-call(?name, x, y) end method ?name } end macro binary-arithmetic-method-definer; define binary-arithmetic-method \+; define binary-arithmetic-method \-; define binary-arithmetic-method \*; /// As \/ isn't defined for , we must define explicit methods /// directly as the methods above would just result in an /// infinite recursion as it would be the only applicable method! define method \/ (x :: , y :: ) => (result :: ) x / as(, y) end method \/; define method \/ (x :: , y :: ) => (result :: ) as(, x) / y end method \/; define method \/ (x :: , y :: ) => (result :: ) contagious-call(\/, x, y) end method \/; define inline method floor (real :: ) => (result :: , remainder :: ) contagious-call(floor/, real, 1); end method floor; define inline method ceiling (real :: ) => (result :: , remainder :: ) contagious-call(ceiling/, real, 1); end method ceiling; define inline method round (real :: ) => (result :: , remainder :: ) contagious-call(round/, real, 1); end method round; define inline method truncate (real :: ) => (result :: , remainder :: ) contagious-call(truncate/, real, 1); end method truncate; define inline method floor/ (real :: , divisor :: ) => (integer :: , remainder :: ) let (integer :: , remainder :: ) = truncate/(real, divisor); if (~zero?(remainder) & if (negative?(divisor)) positive?(real) else negative?(real) end if) values(integer - 1, remainder + divisor) else values(integer, remainder) end if end method floor/; define inline method ceiling/ (real :: , divisor :: ) => (integer :: , remainder :: ) let (integer :: , remainder :: ) = truncate/(real, divisor); if (~zero?(remainder) & if (negative?(divisor)) negative?(real) else positive?(real) end if) values(integer + 1, remainder - divisor) else values(integer, remainder) end if end method ceiling/; define inline method round/ (real :: , divisor :: ) => (integer :: , remainder :: ) let (integer :: , remainder :: ) = truncate/(real, divisor); let threshold :: = abs(divisor) / 2.0; case remainder > threshold | (remainder = threshold & odd?(integer)) => if (negative?(divisor)) values(integer - 1, remainder + divisor) else values(integer + 1, remainder - divisor) end if; begin let minus-threshold = negative(threshold); remainder < minus-threshold | (remainder = minus-threshold & odd?(integer)) end => if (negative?(divisor)) values(integer + 1, remainder - divisor) else values(integer - 1, remainder + divisor) end if; otherwise => values(integer, remainder) end case end method round/; define inline method truncate/ (real :: , divisor :: ) => (quotient :: , remainder :: ) contagious-call(truncate/, real, divisor) end method truncate/; define inline method modulo (real :: , divisor :: ) => (result :: ) let (integer :: , remainder :: ) = floor/(real, divisor); remainder end method modulo; define inline method remainder (real :: , divisor :: ) => (result :: ) let (integer :: , remainder :: ) = truncate/(real, divisor); remainder end method remainder; define inline method abs (x :: ) => (result :: ) if (negative?(x)) negative(x) else x end end method abs; // eof