diff -r 8ec85c250ed3 pure/lib/primitives.pure --- a/pure/lib/primitives.pure Sat Jul 17 16:47:24 2010 +0200 +++ b/pure/lib/primitives.pure Thu Jul 22 17:25:24 2010 +0200 @@ -726,6 +726,15 @@ _ = doublep x; end); +/* IEEE floating point infinities and NaNs. */ + +const inf = 1.0e307 * 1.0e307; const nan = inf-inf; + +/* Predicates to check for inf and nan values. */ + +infp x = case x of x::double = x==inf || x==-inf; _ = 0 end; +nanp x = case x of x::double = ~(x==x); _ = 0 end; + /* Predicates to check for various kinds of function objects (named, anonymous or thunk) and global variable symbols. */ @@ -1067,15 +1076,235 @@ extern double pow(double, double); namespace; -x::double^y::double = __C::pow x y; +x::double ^ y::double = impl x y with + +/* C0 + Upon successful completion, these functions shall return the value + of x raised to the power y. + + .. see below */ + +/* C1 + For finite values of x < 0, and finite non-integer values of y, a + domain error shall occur and [MX] [Option Start] either a NaN (if + representable), or [Option End] an implementation-defined value + shall be returned. */ + + impl x y = nan + if finp x && x < 0 + && finp y && ~intvalp y + ; + +/* C2 + If the correct value would cause overflow, a range error shall occur + and pow(), powf(), and powl() shall return ±HUGE_VAL, ±HUGE_VALF, + and ±HUGE_VALL, respectively, with the same sign as the correct + value of the function. + + .. deferred to host */ + +/* C3 + If the correct value would cause underflow, and is not + representable, a range error may occur, and [MX] [Option Start] + either 0.0 (if supported), or [Option End] an + implementation-defined value shall be returned. + + .. deferred to host */ + +/* C4 + [MX] [Option Start] If x or y is a NaN, a NaN shall be returned + (unless specified elsewhere in this description). + + see below */ + +/* C5 + For any value of y (including NaN), if x is +1, 1.0 shall be + returned. */ + + impl x y = 1.0 if x == 1; + +/* C6 + For any value of x (including NaN), if y is ±0, 1.0 shall be + returned. */ + + impl x y = 1.0 if y == 0; + +/* C4 implementation */ + + impl x y = nan if nanp x || nanp y; + +/* C7 + For any odd integer value of y > 0, if x is ±0, ±0 shall be + returned. */ + + impl x y = double x + if x == 0 + && y > 0 + && oddintp y + ; + +/* C8 + For y > 0 and not an odd integer, if x is ±0, +0 shall be returned. +*/ + + impl x y = 0.0 + if x == 0 + && y > 0 + && ~oddintp y + ; + +/* C9 + If x is -1, and y is ±Inf, 1.0 shall be returned. +*/ + + impl x y = 1.0 + if x == -1 + && infp y + ; + +/* C10 + For |x| < 1, if y is -Inf, +Inf shall be returned. +*/ + + impl x y = inf + if abs x < 1 + && neginfp y + ; + +/* C11 + For |x| > 1, if y is -Inf, +0 shall be returned. +*/ + + impl x y = 0.0 + if abs x > 1 + && neginfp y + ; + +/* C12 + For |x| < 1, if y is +Inf, +0 shall be returned. +*/ + + impl x y = 0.0 + if abs x < 1 + && posinfp y + ; + +/* C13 + For |x| > 1, if y is +Inf, +Inf shall be returned. +*/ + + impl x y = inf + if abs x > 1 + && posinfp y + ; + +/* C14 + For y an odd integer < 0, if x is -Inf, -0 shall be returned. +*/ + + impl x y = -0.0 + if neginfp x + && oddintp y + && y < 0 + ; + +/* C15 + For y < 0 and not an odd integer, if x is -Inf, +0 shall be returned. +*/ + + impl x y = 0.0 + if y < 0 + && ~oddintp y + && neginfp x + ; + +/* C16 + For y an odd integer > 0, if x is -Inf, -Inf shall be returned. +*/ + + impl x y = -inf + if y > 0 + && oddintp y + && neginfp x + ; + +/* C17 + For y > 0 and not an odd integer, if x is -Inf, +Inf shall be returned. +*/ + + impl x y = inf + if y > 0 + && ~oddintp y + && neginfp x + ; + +/* C18 + For y < 0, if x is +Inf, +0 shall be returned. +*/ + + impl x y = 0.0 + if y < 0 + && posinfp x + ; + +/* C19 + For y > 0, if x is +Inf, +Inf shall be returned. +*/ + + impl x y = inf + if y > 0 + && posinfp x + ; + +/* C20 + For y an odd integer < 0, if x is ±0, a pole error shall occur and + ±HUGE_VAL, ±HUGE_VALF, and ±HUGE_VALL shall be returned for pow(), + powf(), and powl(), respectively. + + .. does not handle the -0.0 case: how do i tell -0.0 from +0.0? */ + + impl x y = inf + if y < 0 && oddintp y + && x == 0 + ; + +/* C21 + For y < 0 and not an odd integer, if x is ±0, a pole error shall + occur and HUGE_VAL, HUGE_VALF, and HUGE_VALL shall be returned for + pow(), powf(), and powl(), respectively. +*/ + + impl x y = inf + if y < 0 && ~oddintp y + && x == 0 + ; + +/* C22 + If the correct value would cause underflow, and is representable, + a range error may occur and the correct value shall be returned. + [Option End] + + .. deferred to host */ + +/* C0 implementation */ + + impl x y = __C::pow x y otherwise; + +end with + neginfp x = infp x && x < 0; + posinfp x = infp x && x > 0; + finp x = ~infp x; + oddintp x = intvalp x && int x mod 2; +end; + x::int^y::int | x::bigint^y::bigint | x::int^y::bigint | -x::bigint^y::int = __C::pow (double x) (double y); +x::bigint^y::int = (double x) ^ (double y); x::double^y::int | -x::double^y::bigint = __C::pow x (double y); +x::double^y::bigint = x ^ (double y); x::int^y::double | -x::bigint^y::double = __C::pow (double x) y; +x::bigint^y::double = (double x) ^ y; /* Pointer arithmetic. We do this using bigints, so that the code is portable to 64 bit systems. */ @@ -1097,16 +1326,6 @@ x::pointer==y::pointer = bigint x == bigint y; x::pointer~=y::pointer = bigint x ~= bigint y; -/* IEEE floating point infinities and NaNs. Place these after the definitions - of the built-in operators so that the double arithmetic works. */ - -const inf = 1.0e307 * 1.0e307; const nan = inf-inf; - -/* Predicates to check for inf and nan values. */ - -infp x = case x of x::double = x==inf || x==-inf; _ = 0 end; -nanp x = case x of x::double = ~(x==x); _ = 0 end; - /* Some common special cases of finite arithmetic sequences are implemented here using the runtime for better performance. */