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 // BOOTED: define ... class ... end; // BOOTED: define ... class ... end; // BOOTED: define ... class ... end; define sealed method make (class == , #rest all-keys, #key) => (res) uninstantiable-error(class); end method; define sealed method make (class == , #rest all-keys, #key) => (res) uninstantiable-error(class); end method; ///---*** NOTE: Is there a way to eliminate contagious-type??? // The methods more specific than are just here because the compiler // can't fols object-class({type estimate: }) yet. define inline method contagious-type (x :: , y :: ) => (result :: ) object-class(y) end method contagious-type; define inline method contagious-type (x :: , y :: ) => (result == ) end method contagious-type; define inline method contagious-type (x :: , y :: ) => (result == ) end method contagious-type; define inline method contagious-type (x :: , y :: ) => (result :: ) object-class(x) end method contagious-type; define inline method contagious-type (x :: , y :: ) => (result == ) end method contagious-type; define inline method contagious-type (x :: , y :: ) => (result == ) end method contagious-type; define inline method contagious-type (x :: , y :: ) => (result == ) end method contagious-type; define inline method contagious-type (x :: , y :: ) => (result == ) end method contagious-type; define inline method contagious-type (x :: , y :: ) => (result == ) end method contagious-type; define inline method contagious-type (x :: , y :: ) => (result == ) end method contagious-type; define sealed inline method as (class == , x :: ) => (result :: ) x end method as; // These are needed because the more specific single/double combos seem to // prevent the above method from being selected. define sealed inline method as (class == , x :: ) => (result :: ) x end method as; define sealed inline method as (class == , x :: ) => (result :: ) x end method as; /// NOTE: Should we implement , convert to it instead of /// if the has more than 53 significant /// bits, the size of a 's mantissa define sealed inline method as (class == , x :: ) => (result :: ) as(, x) end method as; define constant $maximum-single-float-mantissa = ash(1, 24) - 2; define constant $minimum-single-float-mantissa = -(ash(1, 24) - 2); /// If the has more bits than can be represented by a 's /// mantissa (i.e., 24), we'll convert it to a instead define sealed inline method as (class == , x :: ) => (result :: ) if (x < $minimum-single-float-mantissa | x > $maximum-single-float-mantissa) as(, x) else as(, x) end end method as; //// CONDITIONS -- These functions are invoked by the low-level runtime //// when the indicated hardware exception is raised. define function float-divide-by-0 () error(make()) end function float-divide-by-0; define function float-overflow () error(make()) end function float-overflow; define function float-underflow () error(make()) end function float-underflow; /// SINGLE FLOAT ///---*** Is this really necessary? define method shallow-copy (x :: ) => (copy :: ) primitive-raw-as-single-float(primitive-single-float-as-raw(x)) end method shallow-copy; define sealed inline method as (class == , x :: ) => (result :: ) primitive-raw-as-single-float(primitive-integer-as-single-float(integer-as-raw(x))) end method as; define sealed inline method as (class == , x :: ) => (result :: ) primitive-raw-as-single-float (primitive-double-float-as-single(primitive-double-float-as-raw(x))) end method as; define inline-only function decode-single-float (x :: ) => (decoded :: ) primitive-wrap-machine-word (primitive-cast-single-float-as-machine-word(primitive-single-float-as-raw(x))) end function decode-single-float; define inline-only function encode-single-float (x :: ) => (encoded :: ) primitive-raw-as-single-float (primitive-cast-machine-word-as-single-float(primitive-unwrap-machine-word(x))) end function encode-single-float; define sealed inline method \= (x :: , y :: ) => (result :: ) primitive-single-float-equals? (primitive-single-float-as-raw(x), primitive-single-float-as-raw(y)) end method \=; define sealed inline method \< (x :: , y :: ) => (result :: ) primitive-single-float-less-than? (primitive-single-float-as-raw(x), primitive-single-float-as-raw(y)) end method \<; define sealed inline method zero? (x :: ) => (result :: ) primitive-single-float-equals? (primitive-single-float-as-raw(x), primitive-single-float-as-raw(0.0)) end method zero?; define sealed inline method positive? (x :: ) => (result :: ) primitive-single-float-less-than? (primitive-single-float-as-raw(0.0), primitive-single-float-as-raw(x)) end method positive?; define sealed inline method negative? (x :: ) => (result :: ) primitive-single-float-less-than? (primitive-single-float-as-raw(x), primitive-single-float-as-raw(0.0)) end method negative?; define sealed inline method integral? (x :: ) => (result :: ) let (integer, remainder :: ) = truncate/(x, 1.0); remainder = 0.0 end method integral?; define sealed inline method \+ (x :: , y :: ) => (z :: ) primitive-raw-as-single-float (primitive-single-float-add (primitive-single-float-as-raw(x), primitive-single-float-as-raw(y))) end method \+; define sealed inline method \- (x :: , y :: ) => (z :: ) primitive-raw-as-single-float (primitive-single-float-subtract (primitive-single-float-as-raw(x), primitive-single-float-as-raw(y))) end method \-; define sealed inline method \* (x :: , y :: ) => (z :: ) primitive-raw-as-single-float (primitive-single-float-multiply (primitive-single-float-as-raw(x), primitive-single-float-as-raw(y))) end method \*; define sealed inline method \/ (x :: , y :: ) => (z :: ) primitive-raw-as-single-float (primitive-single-float-divide (primitive-single-float-as-raw(x), primitive-single-float-as-raw(y))) end method \/; define sealed inline method negative (x :: ) => (z :: ) primitive-raw-as-single-float (primitive-single-float-negate(primitive-single-float-as-raw(x))) end method negative; define sealed inline method truncate/ (real :: , divisor :: ) => (result :: , remainder :: ) let divided = real / divisor; let result = raw-as-integer (primitive-single-float-as-integer (primitive-single-float-as-raw(divided))); values(result, divisor * (divided - as(, result))) end method truncate/; define sealed inline method \^ (base :: , power :: ) => (result :: ) let negative-result? = negative?(base) & odd?(power); let result = primitive-raw-as-single-float (primitive-single-float-expt (primitive-single-float-as-raw(abs(base)), primitive-integer-as-single-float(integer-as-raw(power)))); if (negative-result?) negative(result) else result end end method \^; /// DOUBLE FLOAT ///---*** Is this really necessary? define method shallow-copy (x :: ) => (copy :: ) primitive-raw-as-double-float(primitive-double-float-as-raw(x)) end method shallow-copy; define sealed inline method as (class == , x :: ) => (result :: ) primitive-raw-as-double-float(primitive-integer-as-double-float(integer-as-raw(x))) end method as; define sealed inline method as (class == , x :: ) => (result :: ) primitive-raw-as-double-float (primitive-single-float-as-double(primitive-single-float-as-raw(x))) end method as; define inline-only function decode-double-float (x :: ) => (low :: , high :: ) let (low :: , high :: ) = primitive-cast-double-float-as-machine-words(primitive-double-float-as-raw(x)); values(primitive-wrap-machine-word(low), primitive-wrap-machine-word(high)) end function decode-double-float; define inline-only function encode-double-float (low :: , high :: ) => (encoded :: ) primitive-raw-as-double-float (primitive-cast-machine-words-as-double-float(primitive-unwrap-machine-word(low), primitive-unwrap-machine-word(high))) end function encode-double-float; define sealed inline method \= (x :: , y :: ) => (result :: ) primitive-double-float-equals? (primitive-double-float-as-raw(x), primitive-double-float-as-raw(y)) end method \=; define sealed inline method \< (x :: , y :: ) => (result :: ) primitive-double-float-less-than? (primitive-double-float-as-raw(x), primitive-double-float-as-raw(y)) end method \<; define sealed inline method zero? (x :: ) => (result :: ) primitive-double-float-equals? (primitive-double-float-as-raw(x), primitive-double-float-as-raw(0.0d0)) end method zero?; define sealed inline method positive? (x :: ) => (result :: ) primitive-double-float-less-than? (primitive-double-float-as-raw(0.0d0), primitive-double-float-as-raw(x)) end method positive?; define sealed inline method negative? (x :: ) => (result :: ) primitive-double-float-less-than? (primitive-double-float-as-raw(x), primitive-double-float-as-raw(0.0d0)) end method negative?; define sealed inline method integral? (x :: ) => (result :: ) let (integer, remainder :: ) = truncate/(x, 1.0d0); remainder = 0.0d0 end method integral?; define sealed inline method \+ (x :: , y :: ) => (z :: ) primitive-raw-as-double-float (primitive-double-float-add (primitive-double-float-as-raw(x), primitive-double-float-as-raw(y))) end method \+; define sealed inline method \- (x :: , y :: ) => (z :: ) primitive-raw-as-double-float (primitive-double-float-subtract (primitive-double-float-as-raw(x), primitive-double-float-as-raw(y))) end method \-; define sealed inline method \* (x :: , y :: ) => (z :: ) primitive-raw-as-double-float (primitive-double-float-multiply (primitive-double-float-as-raw(x), primitive-double-float-as-raw(y))) end method \*; define sealed inline method \/ (x :: , y :: ) => (z :: ) primitive-raw-as-double-float (primitive-double-float-divide (primitive-double-float-as-raw(x), primitive-double-float-as-raw(y))) end method \/; define sealed inline method negative (x :: ) => (z :: ) primitive-raw-as-double-float (primitive-double-float-negate(primitive-double-float-as-raw(x))) end method negative; define sealed inline method truncate/ (real :: , divisor :: ) => (result :: , remainder :: ) let divided = real / divisor; let result = raw-as-integer (primitive-double-float-as-integer (primitive-double-float-as-raw(divided))); values(result, divisor * (divided - as(, result))) end method truncate/; define sealed inline method \^ (base :: , power :: ) => (result :: ) let negative-result? = negative?(base) & odd?(power); let result = primitive-raw-as-double-float (primitive-double-float-expt (primitive-double-float-as-raw(abs(base)), primitive-integer-as-double-float(integer-as-raw(power)))); if (negative-result?) negative(result) else result end end method \^; /// EXTENDED FLOAT ///--- NOTE: In our implementation, == ... define constant = ;