Added spec:commit task to commit changes to spec/ruby sources.
[rbx.git] / shotgun / lib / float.c
blob23a099d14154dbe9c62fd879f59f72b3b5a3d423
1 #include <string.h>
2 #include <math.h>
4 /* Begin borrowing from MRI 1.8.6 stable */
5 #if defined(__FreeBSD__) && __FreeBSD__ < 4
6 #include <floatingpoint.h>
7 #endif
9 #ifdef HAVE_FLOAT_H
10 #include <float.h>
11 #endif
13 #ifdef HAVE_IEEEFP_H
14 #include <ieeefp.h>
15 #endif
17 #ifdef WORDS_BIGENDIAN
18 #define word0(x) ((unsigned int *)&x)[0]
19 #define word1(x) ((unsigned int *)&x)[1]
20 #else
21 #define word0(x) ((unsigned int *)&x)[1]
22 #define word1(x) ((unsigned int *)&x)[0]
23 #endif
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) {
44 double *value;
45 OBJECT o;
46 o = object_memory_new_opaque(state, BASIC_CLASS(floatpoint), sizeof(double));
47 value = (double *)BYTES_OF(o);
48 *value = dbl;
49 return 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) {
57 char *endp;
58 double d;
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. */
67 int sign = 0;
69 if (*str == '-') {
70 sign = 1;
71 str++;
72 } else if (*str == '+') {
73 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;
81 word1(d) = 0;
82 return float_new(state, d);
85 return Qnil;
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) {
93 if(a < b) {
94 return I2N(-1);
95 } else if(a > b) {
96 return I2N(1);
98 return I2N(0);
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));
107 return value;