4 /* Begin borrowing from MRI 1.8.6 stable */
5 #if defined(__FreeBSD__) && __FreeBSD__ < 4
6 #include <floatingpoint.h>
17 #ifdef WORDS_BIGENDIAN
18 #define word0(x) ((unsigned int *)&x)[0]
19 #define word1(x) ((unsigned int *)&x)[1]
21 #define word0(x) ((unsigned int *)&x)[1]
22 #define word1(x) ((unsigned int *)&x)[0]
25 #include "shotgun/lib/shotgun.h"
26 #include "shotgun/lib/string.h"
27 #include "shotgun/lib/array.h"
28 #include "shotgun/lib/bignum.h"
29 #include "shotgun/lib/float.h"
31 int float_radix() { return FLT_RADIX
; }
32 int float_rounds() { return FLT_ROUNDS
; }
33 double float_min() { return DBL_MIN
; }
34 double float_max() { return DBL_MAX
; }
35 int float_min_exp() { return DBL_MIN_EXP
; }
36 int float_max_exp() { return DBL_MAX_EXP
; }
37 int float_min_10_exp() { return DBL_MIN_10_EXP
; }
38 int float_max_10_exp() { return DBL_MAX_10_EXP
; }
39 int float_dig() { return DBL_DIG
; }
40 int float_mant_dig() { return DBL_MANT_DIG
; }
41 double float_epsilon() { return DBL_EPSILON
; }
43 OBJECT
float_new(STATE
, double dbl
) {
46 o
= object_memory_new_opaque(state
, BASIC_CLASS(floatpoint
), sizeof(double));
47 value
= (double *)BYTES_OF(o
);
52 /* This functions is only used when unmarshalling.
53 * The assumptions made here are therefore safe.
54 * String#to_f uses string_to_double
56 OBJECT
float_from_string(STATE
, char *str
) {
59 d
= strtod(str
, &endp
);
60 if (str
!= endp
&& *endp
== '\0') {
61 return float_new(state
, d
);
63 /* When we get here, we might have a system that doesn't conform to
64 C99 (OpenBSD is at least one) that can't handle Infinity / NaN.
65 We test the strings here manually and fix it if needed. */
72 } else if (*str
== '+') {
76 if (*str
== 'I' || *str
== 'i') {
77 return float_new(state
, sign
? -HUGE_VAL
: HUGE_VAL
);
79 if (*str
== 'N' || *str
== 'n') {
80 word0(d
) = 0x7ff80000;
82 return float_new(state
, d
);
88 void float_into_string(STATE
, OBJECT self
, char *buf
, int sz
) {
89 snprintf(buf
, sz
, "%+.17e", FLOAT_TO_DOUBLE(self
));
92 OBJECT
float_compare(STATE
, double a
, double b
) {
101 OBJECT
float_coerce(STATE
, OBJECT value
) {
102 if(FIXNUM_P(value
)) {
103 return float_new(state
, (double)N2I(value
));
104 } else if(BIGNUM_P(value
)) {
105 return float_new(state
, bignum_to_double(state
, value
));