diff options
author | Lukas Larsson <[email protected]> | 2011-07-26 17:11:41 +0200 |
---|---|---|
committer | Lukas Larsson <[email protected]> | 2011-10-11 17:10:19 +0200 |
commit | e04883d448df6e622535020449903e2f2a0f32c9 (patch) | |
tree | c7db6e79663481ff9e9f1cb2b79b86cfe61cfec9 /erts/emulator/beam/big.c | |
parent | 622daf3b96666f8bbabec44a15b26a188a83b95e (diff) | |
download | otp-e04883d448df6e622535020449903e2f2a0f32c9.tar.gz otp-e04883d448df6e622535020449903e2f2a0f32c9.tar.bz2 otp-e04883d448df6e622535020449903e2f2a0f32c9.zip |
Update integer and floating point number comparisons
For floating point values which are greater than 9007199254740990.0 or
smaller than -9007199254740990.0, the floating point numbers are now
converted to integers during comparison with an integer. This makes
number comparisons transitive for large floating point numbers.
Diffstat (limited to 'erts/emulator/beam/big.c')
-rw-r--r-- | erts/emulator/beam/big.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c index d18de9ae5d..51e5d2d305 100644 --- a/erts/emulator/beam/big.c +++ b/erts/emulator/beam/big.c @@ -1584,6 +1584,63 @@ big_to_double(Wterm x, double* resp) return 0; } +Eterm +double_to_big(double x, Eterm *heap) +{ + int is_negative; + int ds; + ErtsDigit* xp; + Eterm tmp_res; + int i; + size_t sz; + Eterm* hp; + double dbase; + + if ((x < (double) (MAX_SMALL + 1)) && (x > (double) (MIN_SMALL - 1))) { + Sint xi = x; + return make_small(xi); + } + + if (x >= 0) { + is_negative = 0; + } else { + is_negative = 1; + x = -x; + } + + /* Unscale & (calculate exponent) */ + ds = 0; + dbase = ((double) (D_MASK) + 1); + while (x >= 1.0) { + x /= dbase; /* "shift" right */ + ds++; + } + sz = BIG_NEED_SIZE(ds); /* number of words including arity */ + + hp = heap; + tmp_res = make_big(hp); + xp = (ErtsDigit*) (hp + 1); + + for (i = ds - 1; i >= 0; i--) { + ErtsDigit d; + + x *= dbase; /* "shift" left */ + d = x; /* trunc */ + xp[i] = d; /* store digit */ + x -= d; /* remove integer part */ + } + while ((ds & (BIG_DIGITS_PER_WORD - 1)) != 0) { + xp[ds++] = 0; + } + + if (is_negative) { + *hp = make_neg_bignum_header(sz-1); + } else { + *hp = make_pos_bignum_header(sz-1); + } + return tmp_res; +} + /* ** Estimate the number of decimal digits (include sign) |