From 174ff0b018c4aca4f3da48fbbaf4d6336e3f5e14 Mon Sep 17 00:00:00 2001 From: Xavier Leroy Date: Sat, 4 Jun 2011 08:55:55 +0000 Subject: [PATCH] PR#3806, 4752, 5246: added "hypot" and "copysign" to Pervasives. git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@11065 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02 --- Changes | 9 +++++ boot/ocamlc | Bin 1105808 -> 1105808 bytes boot/ocamldep | Bin 309845 -> 309845 bytes boot/ocamllex | Bin 171051 -> 171051 bytes byterun/floats.c | 63 ++++++++++++++++++++++++++------ config/s-templ.h | 6 +-- configure | 6 +-- otherlibs/threads/pervasives.ml | 2 + stdlib/pervasives.ml | 2 + stdlib/pervasives.mli | 13 +++++++ 10 files changed, 84 insertions(+), 17 deletions(-) diff --git a/Changes b/Changes index df9364dfe..89381d8d3 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,15 @@ OCaml 3.13.0: - The official name of the language is now OCaml. - Warning 28 is now enabled by default. +Standard library: +- Added float functions "hypot" and "copysign" (PR#3806, PR#4752, PR#5246) +- Hashtbl: + . Statistically-better generic hash function based on Murmur 3 (PR#5225) + . Fixed behavior of generic hash function w.r.t. -0.0 and NaN (PR#5222) + . Added optional "seed" parameter to Hashtbl.create for diversification + . Added new functorial interface "MakeSeeded" to support diversification + with user-provided hash functions. + Objective Caml 3.12.0: ---------------------- diff --git a/boot/ocamlc b/boot/ocamlc index ef25dbe8034b9f3972632e0f15c0ec3a95bc852c..13eaa14bca4ad170329f00d95153fe17bf93ba2f 100755 GIT binary patch delta 64 zcmV-G0Kfl`zeA9}Lx6+pBViB delta 64 zcmV-G0Kfl`zeA9}Lx6+o&G delta 39 xcmV+?0NDT4^b*zd5`csOgaU*Ev;?ua5ZiJ(7nrdk;E5TczwHJk6qmud1e9xl5xf8Z diff --git a/boot/ocamllex b/boot/ocamllex index 55f00e07994bbf054939c69088503a2467e3c981..6a5ad851613225c9fa3338730156b14be2253b84 100755 GIT binary patch delta 35 tcmV+;0NnqpxC*Pd3V?(Gv;uIO5OLKGSCZnJdL3eo(Ht(plb3*-0;?AJ55E8a delta 35 tcmV+;0NnqpxC*Pd3V?(Gv;uIO5ZiJ(7nrdk;E5TczwHJk6qkUT0;?0G4=4Zt diff --git a/byterun/floats.c b/byterun/floats.c index d1d178a32..c067e60d2 100644 --- a/byterun/floats.c +++ b/byterun/floats.c @@ -326,12 +326,32 @@ CAMLprim value caml_ceil_float(value f) return caml_copy_double(ceil(Double_val(f))); } +CAMLexport double caml_hypot(double x, double y) +{ +#ifdef HAS_C99_FLOAT_OPS + return hypot(x, y); +#else + double tmp, ratio; + if (x != x) return x; /* NaN */ + if (y != y) return y; /* NaN */ + x = fabs(x); y = fabs(y); + if (x < y) { tmp = x; x = y; y = tmp; } + if (x == 0.0) return 0.0; + ratio = y / x; + return x * sqrt(1.0 + ratio * ratio); +#endif +} + +CAMLprim value caml_hypot_float(value f, value g) +{ + return caml_copy_double(caml_hypot(Double_val(f), Double_val(g))); +} + /* These emulations of expm1() and log1p() are due to William Kahan. See http://www.plunk.org/~hatch/rightway.php */ - CAMLexport double caml_expm1(double x) { -#ifdef HAS_EXPM1_LOG1P +#ifdef HAS_C99_FLOAT_OPS return expm1(x); #else double u = exp(x); @@ -345,7 +365,7 @@ CAMLexport double caml_expm1(double x) CAMLexport double caml_log1p(double x) { -#ifdef HAS_EXPM1_LOG1P +#ifdef HAS_C99_FLOAT_OPS return log1p(x); #else double u = 1. + x; @@ -366,6 +386,34 @@ CAMLprim value caml_log1p_float(value f) return caml_copy_double(caml_log1p(Double_val(f))); } +union double_as_two_int32 { + double d; +#if defined(ARCH_BIG_ENDIAN) || (defined(__arm__) && !defined(__ARM_EABI__)) + struct { uint32 h; uint32 l; } i; +#else + struct { uint32 l; uint32 h; } i; +#endif +}; + +CAMLexport double caml_copysign(double x, double y) +{ +#ifdef HAS_C99_FLOAT_OPS + return copysign(x, y); +#else + union double_as_two_int32 ux, uy; + ux.d = x; + uy.d = y; + ux.i.h &= 0x7FFFFFFFU; + ux.i.h |= (uy.i.h & 0x80000000U); + return ux.d; +#endif +} + +CAMLprim value caml_copysign_float(value f, value g) +{ + return caml_copy_double(caml_copysign(Double_val(f), Double_val(g))); +} + CAMLprim value caml_eq_float(value f, value g) { return Val_bool(Double_val(f) == Double_val(g)); @@ -429,14 +477,7 @@ CAMLprim value caml_classify_float(value vd) return Val_int(FP_normal); } #else - union { - double d; -#if defined(ARCH_BIG_ENDIAN) || (defined(__arm__) && !defined(__ARM_EABI__)) - struct { uint32 h; uint32 l; } i; -#else - struct { uint32 l; uint32 h; } i; -#endif - } u; + union double_as_two_int32 u; uint32 h, l; u.d = Double_val(vd); diff --git a/config/s-templ.h b/config/s-templ.h index a65b178a8..52f3cf609 100644 --- a/config/s-templ.h +++ b/config/s-templ.h @@ -52,10 +52,10 @@ /* Define SUPPORT_DYNAMIC_LINKING if dynamic loading of C stub code via dlopen() is available. */ -#define HAS_EXPM1_LOG1P +#define HAS_C99_FLOAT_OPS -/* Define HAS_EXPM1_LOG1P if the math functions expm1() and log1p() - are available. (Standard C99 but not C89.) */ +/* Define HAS_C99_FLOAT_OPS if conforms to ISO C99. + In particular, it should provide expm1(), log1p(), hypot(), copysign(). */ /* 2. For the Unix library. */ diff --git a/configure b/configure index 8754cd614..019272552 100755 --- a/configure +++ b/configure @@ -869,9 +869,9 @@ fi # For the Pervasives module -if sh ./trycompile expm1.c $mathlib; then - echo "expm1() and log1p() found." - echo "#define HAS_EXPM1_LOG1P" >> s.h +if sh ./hasgot2 -i math.h $mathlib expm1 log1p hypot copysign; then + echo "expm1(), log1p(), hypot(), copysign() found." + echo "#define HAS_C99_FLOAT_OPS" >> s.h fi # For the Sys module diff --git a/otherlibs/threads/pervasives.ml b/otherlibs/threads/pervasives.ml index 08115a2ff..748e96796 100644 --- a/otherlibs/threads/pervasives.ml +++ b/otherlibs/threads/pervasives.ml @@ -94,6 +94,7 @@ external acos : float -> float = "caml_acos_float" "acos" "float" external asin : float -> float = "caml_asin_float" "asin" "float" external atan : float -> float = "caml_atan_float" "atan" "float" external atan2 : float -> float -> float = "caml_atan2_float" "atan2" "float" +external hypot : float -> float -> float = "caml_hypot_float" "caml_hypot" "float" external cos : float -> float = "caml_cos_float" "cos" "float" external cosh : float -> float = "caml_cosh_float" "cosh" "float" external log : float -> float = "caml_log_float" "log" "float" @@ -107,6 +108,7 @@ external tanh : float -> float = "caml_tanh_float" "tanh" "float" external ceil : float -> float = "caml_ceil_float" "ceil" "float" external floor : float -> float = "caml_floor_float" "floor" "float" external abs_float : float -> float = "%absfloat" +external copysign : float -> float -> float = "caml_copysign_float" "caml_copysign" "float" external mod_float : float -> float -> float = "caml_fmod_float" "fmod" "float" external frexp : float -> float * int = "caml_frexp_float" external ldexp : float -> int -> float = "caml_ldexp_float" diff --git a/stdlib/pervasives.ml b/stdlib/pervasives.ml index 7a1c0aeab..b4277953c 100644 --- a/stdlib/pervasives.ml +++ b/stdlib/pervasives.ml @@ -91,6 +91,7 @@ external acos : float -> float = "caml_acos_float" "acos" "float" external asin : float -> float = "caml_asin_float" "asin" "float" external atan : float -> float = "caml_atan_float" "atan" "float" external atan2 : float -> float -> float = "caml_atan2_float" "atan2" "float" +external hypot : float -> float -> float = "caml_hypot_float" "caml_hypot" "float" external cos : float -> float = "caml_cos_float" "cos" "float" external cosh : float -> float = "caml_cosh_float" "cosh" "float" external log : float -> float = "caml_log_float" "log" "float" @@ -104,6 +105,7 @@ external tanh : float -> float = "caml_tanh_float" "tanh" "float" external ceil : float -> float = "caml_ceil_float" "ceil" "float" external floor : float -> float = "caml_floor_float" "floor" "float" external abs_float : float -> float = "%absfloat" +external copysign : float -> float -> float = "caml_copysign_float" "caml_copysign" "float" external mod_float : float -> float -> float = "caml_fmod_float" "fmod" "float" external frexp : float -> float * int = "caml_frexp_float" external ldexp : float -> int -> float = "caml_ldexp_float" diff --git a/stdlib/pervasives.mli b/stdlib/pervasives.mli index 13905ecc3..7c35f6d4d 100644 --- a/stdlib/pervasives.mli +++ b/stdlib/pervasives.mli @@ -314,6 +314,13 @@ external atan2 : float -> float -> float = "caml_atan2_float" "atan2" "float" and [y] are used to determine the quadrant of the result. Result is in radians and is between [-pi] and [pi]. *) +external hypot : float -> float -> float = "caml_hypot_float" "caml_hypot" "float" +(** [hypot x y] returns [sqrt(x *. x + y *. y)], that is, the length + of the hypotenuse of a right-angled triangle with sides of length + [x] and [y], or, equivalently, the distance of the point [(x,y)] + to origin. + @since 3.13.0 *) + external cosh : float -> float = "caml_cosh_float" "cosh" "float" (** Hyperbolic cosine. Argument is in radians. *) @@ -337,6 +344,12 @@ external floor : float -> float = "caml_floor_float" "floor" "float" external abs_float : float -> float = "%absfloat" (** [abs_float f] returns the absolute value of [f]. *) +external copysign : float -> float -> float = "caml_copysign_float" "caml_copysign" "float" +(** [copysign x y] returns a float whose absolute value is that of [x] + and whose sign is that of [y]. If [x] is [nan], returns [nan]. + If [y] is [nan], returns either [x] or [-. x], but it is not + specified which. *) + external mod_float : float -> float -> float = "caml_fmod_float" "fmod" "float" (** [mod_float a b] returns the remainder of [a] with respect to [b]. The returned value is [a -. n *. b], where [n]