decimal 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +1 -2
- data/BSDL +22 -0
- data/COPYING +2 -2
- data/{README → README.rdoc} +3 -2
- data/TODO +1 -2
- data/decimal.c +258 -31
- data/decimal.gemspec +9 -8
- data/depend +1 -1
- data/extconf.rb +9 -10
- data/inum193.h +2346 -0
- data/inum200.h +2350 -0
- data/inum21.h +2348 -0
- data/inum22.h +2429 -0
- data/lib/decimal/math.rb +2 -1
- data/ruby18compat.h +6 -6
- data/test_decimal.rb +1 -1
- metadata +39 -55
- data/GPL +0 -340
- data/inum18.h +0 -376
- data/inum191.h +0 -350
- data/inum192.h +0 -332
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a8097ff905177fba0cb30a72729889f1f0e8c2a5
|
4
|
+
data.tar.gz: ca7f019d9016491724ced8f63dc8014a9b36f336
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9aae38f7a8bff309748cd1c61279323411c39bcf5238c95539d27e5d98b4ede7a6e7b3ed2f712b01490e386ce03d669c493ca5e75aff600ab4246f45d0d4901e
|
7
|
+
data.tar.gz: 475772f7f6cc6e888743d1b0b66696fe90a98f5a46022b023049ac5c554ce59f3d3fbc3bd4ac205c31435ec8123513f34c6eea1d395d86f50caae9e2ba07bc69
|
data/.document
CHANGED
data/BSDL
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (C) 1993-2014 Tadashi Saito. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
4
|
+
modification, are permitted provided that the following conditions
|
5
|
+
are met:
|
6
|
+
1. Redistributions of source code must retain the above copyright
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
10
|
+
documentation and/or other materials provided with the distribution.
|
11
|
+
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
13
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
14
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
15
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
16
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
17
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
18
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
19
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
20
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
21
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
22
|
+
SUCH DAMAGE.
|
data/COPYING
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Decimal is copyrighted free software by Tadashi Saito <tad.a.diggier[at]
|
2
2
|
gmail.com>.
|
3
|
-
You can redistribute it and/or modify it under either the terms of the
|
4
|
-
|
3
|
+
You can redistribute it and/or modify it under either the terms of the
|
4
|
+
2-clause BSDL (see the file BSDL), or the conditions below:
|
5
5
|
|
6
6
|
1. You may make and give away verbatim copies of the source form of the
|
7
7
|
software without restriction, provided that you duplicate all of the
|
data/{README → README.rdoc}
RENAMED
@@ -7,13 +7,14 @@ precise, stable and easy-to-use solution.
|
|
7
7
|
== Webpages
|
8
8
|
|
9
9
|
* {Home}[http://decimal.rubyforge.org/]
|
10
|
+
* {GitHub}[https://github.com/tadd/decimal]
|
10
11
|
* {Latest API Documents}[http://decimal.rubyforge.org/rdoc/]
|
11
12
|
* {Project Page at RubyForge}[http://rubyforge.org/projects/decimal/]
|
12
13
|
* {Mailing Lists}[http://rubyforge.org/mail/?group_id=1994]
|
13
14
|
|
14
15
|
== Requirements
|
15
16
|
|
16
|
-
Ruby 1.
|
17
|
+
Ruby 1.9.3 / 2.0.0 / 2.1.x / 2.2.x
|
17
18
|
|
18
19
|
== Install
|
19
20
|
|
@@ -50,7 +51,7 @@ Use like Float with few exceptions including Decimal#divide.
|
|
50
51
|
|
51
52
|
== License
|
52
53
|
|
53
|
-
Ruby's. See COPYING and
|
54
|
+
Ruby's. See COPYING and BSDL for more details.
|
54
55
|
|
55
56
|
== Author
|
56
57
|
|
data/TODO
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
* Preserve scale of zeros
|
2
2
|
* Implement "decimal/compat/bigdecimal", a bigdecimal-compatible layer
|
3
|
-
* Implement decimal ** otherdecimal, decimal ** -integer
|
4
|
-
(with Decimal#power(other, scale=decimal.scale, mode=Decimal::ROUND_XXX))
|
5
3
|
* Be a good friend with other Numeric classes (using Kernel.autoload?)
|
6
4
|
- OtherNumerics#to_decimal, Decimal#to_*
|
7
5
|
* Define `marshal_dump' and `marshal_load'
|
@@ -13,6 +11,7 @@
|
|
13
11
|
* Static value for well-used value like 0, 1 or 10 ?
|
14
12
|
|
15
13
|
done:
|
14
|
+
- Implement decimal ** otherdecimal and decimal ** -integer
|
16
15
|
- Implement Math functions
|
17
16
|
- Implement webpages
|
18
17
|
- Support RubyGems
|
data/decimal.c
CHANGED
@@ -23,9 +23,6 @@
|
|
23
23
|
#include <util.h>
|
24
24
|
#endif
|
25
25
|
|
26
|
-
/* we need support both of 1.8/1.9 with the same source! */
|
27
|
-
#include "ruby18compat.h"
|
28
|
-
|
29
26
|
/*
|
30
27
|
* unfortunately, few copies of Integer functions
|
31
28
|
* are needed from original Ruby
|
@@ -772,7 +769,7 @@ do_round(const Decimal *d, long scale, VALUE mode, VALUE *inump)
|
|
772
769
|
long diff;
|
773
770
|
int lower;
|
774
771
|
int trailing_nonzero, negative;
|
775
|
-
VALUE inum, inumabs, shift, ary;
|
772
|
+
VALUE inum = Qundef, inumabs, shift, ary;
|
776
773
|
|
777
774
|
if (d == DEC_PINF) rb_raise(eDomainError, "Infinity");
|
778
775
|
if (d == DEC_NINF) rb_raise(eDomainError, "-Infinity");
|
@@ -1027,7 +1024,6 @@ divmod(const Decimal *a, const Decimal *b, VALUE *divp, VALUE *modp)
|
|
1027
1024
|
}
|
1028
1025
|
else if (DEC_ISINF(b)) {
|
1029
1026
|
const int a_negative = INUM_NEGATIVE_P(a->inum);
|
1030
|
-
VALUE div_inum;
|
1031
1027
|
|
1032
1028
|
if (a_negative != (b == DEC_NINF)) { /* signs differ */
|
1033
1029
|
if (divp) *divp = INT2FIX(-1);
|
@@ -1177,19 +1173,173 @@ dec_divmod(VALUE x, VALUE y)
|
|
1177
1173
|
return rb_assoc_new(div, mod);
|
1178
1174
|
}
|
1179
1175
|
|
1176
|
+
static VALUE math_ln(VALUE x, VALUE scale, VALUE mode);
|
1177
|
+
static VALUE math_exp(int argc, VALUE *argv, VALUE module UNUSED);
|
1178
|
+
|
1180
1179
|
static VALUE
|
1181
|
-
|
1180
|
+
power_with_math_exp(VALUE x, VALUE y, VALUE scale, VALUE mode)
|
1181
|
+
{
|
1182
|
+
VALUE x_ln;
|
1183
|
+
VALUE argv[3];
|
1184
|
+
|
1185
|
+
x_ln = math_ln(x, LONG2NUM(FIX2LONG(scale)+1), ROUND_DOWN);
|
1186
|
+
argv[0] = dec_mul(y, x_ln);
|
1187
|
+
argv[1] = scale;
|
1188
|
+
argv[2] = mode;
|
1189
|
+
return math_exp(3, argv, Qnil);
|
1190
|
+
}
|
1191
|
+
|
1192
|
+
static VALUE
|
1193
|
+
power_with_positive_fixnum(VALUE x, VALUE y)
|
1182
1194
|
{
|
1183
1195
|
VALUE inum;
|
1196
|
+
Decimal *a;
|
1184
1197
|
|
1198
|
+
GetDecimal(x, a);
|
1185
1199
|
/* XXX: valid to rb_warn() out of here by rb_big_pow()? */
|
1186
|
-
inum = INUM_POW(
|
1200
|
+
inum = INUM_POW(a->inum, y);
|
1187
1201
|
if (TYPE(inum) == T_FLOAT) /* got Infinity with warning, by too-big y */
|
1188
1202
|
return VALUE_PINF;
|
1189
|
-
return WrapDecimal(dec_raw_new(inum,
|
1203
|
+
return WrapDecimal(dec_raw_new(inum, a->scale * FIX2LONG(y)));
|
1204
|
+
}
|
1205
|
+
|
1206
|
+
static VALUE dec_eq(VALUE x, VALUE y);
|
1207
|
+
static VALUE dec_lt(VALUE x, VALUE y);
|
1208
|
+
static VALUE dec_gt(VALUE x, VALUE y);
|
1209
|
+
static VALUE dec_abs(VALUE x);
|
1210
|
+
static VALUE dec_zero_p(VALUE x);
|
1211
|
+
static VALUE dec_finite_p(VALUE x);
|
1212
|
+
|
1213
|
+
static VALUE
|
1214
|
+
power_body(VALUE x, VALUE y, VALUE scale, VALUE mode)
|
1215
|
+
{
|
1216
|
+
int y_negative_p, y_finite_p, y_integer_p, y_zero_p, y_positive_p,
|
1217
|
+
y_odd_p, y_pinf_p, y_ninf_p, y_nan_p, y_one_p;
|
1218
|
+
int x_finite_p, x_negative_p, x_nan_p, x_pone_p, x_none_p, x_zero_p,
|
1219
|
+
x_abs, x_abs_lt_1, x_abs_gt_1, x_ninf_p, x_pinf_p;
|
1220
|
+
long l = 0; /* dummy value */
|
1221
|
+
|
1222
|
+
if (FIXNUM_P(y)) {
|
1223
|
+
l = FIX2LONG(y);
|
1224
|
+
y_integer_p = y_finite_p = Qtrue;
|
1225
|
+
y_zero_p = (l == 0);
|
1226
|
+
y_one_p = (l == 1);
|
1227
|
+
y_positive_p = (l > 0);
|
1228
|
+
y_negative_p = (l < 0);
|
1229
|
+
y_odd_p = (l % 2 != 0);
|
1230
|
+
y_pinf_p = y_ninf_p = y_nan_p = Qfalse;
|
1231
|
+
} else { /* it's a Decimal */
|
1232
|
+
y_finite_p = dec_finite_p(y);
|
1233
|
+
y_integer_p = (y_finite_p && !dec_zero_p(dec_mod(y, INT2FIX(1))));
|
1234
|
+
y_zero_p = dec_zero_p(y);
|
1235
|
+
y_one_p = dec_eq(y, INT2FIX(1));
|
1236
|
+
y_positive_p = dec_gt(y, INT2FIX(0));
|
1237
|
+
y_negative_p = dec_lt(y, INT2FIX(0));
|
1238
|
+
y_odd_p = (y_finite_p && !dec_zero_p(dec_mod(y, INT2FIX(2))));
|
1239
|
+
y_pinf_p = (y == VALUE_PINF);
|
1240
|
+
y_ninf_p = (y == VALUE_NINF);
|
1241
|
+
y_nan_p = (y == VALUE_NaN);
|
1242
|
+
}
|
1243
|
+
x_finite_p = dec_finite_p(x);
|
1244
|
+
x_negative_p = dec_lt(x, INT2FIX(0));
|
1245
|
+
x_nan_p = (x == VALUE_NaN);
|
1246
|
+
x_pone_p = dec_eq(x, INT2FIX(1));
|
1247
|
+
x_none_p = dec_eq(x, INT2FIX(-1));
|
1248
|
+
x_zero_p = dec_zero_p(x);
|
1249
|
+
x_abs = dec_abs(x);
|
1250
|
+
x_abs_lt_1 = dec_lt(x_abs, INT2FIX(1));
|
1251
|
+
x_abs_gt_1 = dec_gt(x_abs, INT2FIX(1));
|
1252
|
+
x_ninf_p = (x == VALUE_NINF);
|
1253
|
+
x_pinf_p = (x == VALUE_PINF);
|
1254
|
+
|
1255
|
+
if (x_negative_p && x_finite_p && !y_integer_p && y_finite_p) {
|
1256
|
+
rb_raise(rb_eArgError, "in a**b, a is negative and b is not integer");
|
1257
|
+
}
|
1258
|
+
if (x_pone_p || y_zero_p) {
|
1259
|
+
return WrapDecimal(dec_raw_new(INT2FIX(1), 0));
|
1260
|
+
}
|
1261
|
+
if (x_zero_p && y_positive_p) {
|
1262
|
+
return WrapDecimal(dec_raw_new(DEC_PZERO, 0));
|
1263
|
+
}
|
1264
|
+
if (x_none_p && (y_pinf_p || y_ninf_p)) {
|
1265
|
+
return WrapDecimal(dec_raw_new(INT2FIX(1), 0));
|
1266
|
+
}
|
1267
|
+
if (x_abs_lt_1 && y_ninf_p) {
|
1268
|
+
return VALUE_PINF;
|
1269
|
+
}
|
1270
|
+
if ((x_abs_gt_1 && y_ninf_p) || (x_abs_lt_1 && y_pinf_p)) {
|
1271
|
+
return WrapDecimal(dec_raw_new(DEC_PZERO, 0));
|
1272
|
+
}
|
1273
|
+
if (x_abs_gt_1 && y_pinf_p) {
|
1274
|
+
return VALUE_PINF;
|
1275
|
+
}
|
1276
|
+
if (x_ninf_p) {
|
1277
|
+
if (y_negative_p) {
|
1278
|
+
return WrapDecimal(dec_raw_new(DEC_PZERO, 0));
|
1279
|
+
}
|
1280
|
+
if (y_positive_p) {
|
1281
|
+
return y_odd_p ? VALUE_NINF : VALUE_PINF;
|
1282
|
+
}
|
1283
|
+
}
|
1284
|
+
if (x_pinf_p) {
|
1285
|
+
if (y_negative_p) {
|
1286
|
+
return WrapDecimal(dec_raw_new(DEC_PZERO, 0));
|
1287
|
+
}
|
1288
|
+
if (y_positive_p) {
|
1289
|
+
return VALUE_PINF;
|
1290
|
+
}
|
1291
|
+
}
|
1292
|
+
if (x_zero_p && y_negative_p) {
|
1293
|
+
/* FIXME; pole error? */
|
1294
|
+
rb_raise(rb_eArgError, "in a**b, a is 0 and y is negative");
|
1295
|
+
}
|
1296
|
+
if (x_nan_p || y_nan_p) {
|
1297
|
+
return VALUE_NaN;
|
1298
|
+
}
|
1299
|
+
if (y_one_p) return x;
|
1300
|
+
if (FIXNUM_P(y)) {
|
1301
|
+
if (l > 0) return power_with_positive_fixnum(x, y);
|
1302
|
+
y = WrapDecimal(inum_to_dec(y));
|
1303
|
+
}
|
1304
|
+
return power_with_math_exp(x, y, scale, mode);
|
1305
|
+
}
|
1306
|
+
|
1307
|
+
/*
|
1308
|
+
* dec.power(otherdec, scale=(), rounding=:unnecessary)
|
1309
|
+
*/
|
1310
|
+
/* :nodoc: */
|
1311
|
+
static VALUE
|
1312
|
+
dec_power(int argc, VALUE *argv, VALUE x)
|
1313
|
+
{
|
1314
|
+
VALUE mode = ROUND_UNNECESSARY;
|
1315
|
+
VALUE y, scale, vmode;
|
1316
|
+
|
1317
|
+
rb_scan_args(argc, argv, "12", &y, &scale, &vmode);
|
1318
|
+
switch (argc) {
|
1319
|
+
case 3:
|
1320
|
+
Check_Type(vmode, T_SYMBOL);
|
1321
|
+
if (!valid_rounding_mode_p(vmode)) {
|
1322
|
+
rb_raise(rb_eArgError, "invalid rounding mode %s",
|
1323
|
+
RSTRING_PTR(rb_inspect(vmode)));
|
1324
|
+
}
|
1325
|
+
mode = vmode;
|
1326
|
+
/* fall through */
|
1327
|
+
case 2:
|
1328
|
+
Check_Type(scale, T_FIXNUM);
|
1329
|
+
break;
|
1330
|
+
case 1:
|
1331
|
+
if (mode != ROUND_UNNECESSARY) {
|
1332
|
+
rb_raise(rb_eArgError, "scale number argument needed");
|
1333
|
+
}
|
1334
|
+
}
|
1335
|
+
|
1336
|
+
if (!FIXNUM_P(y) && !DECIMAL_P(y)) {
|
1337
|
+
rb_raise(rb_eTypeError, "2nd argument %s must be Fixnum or Decimal",
|
1338
|
+
RSTRING_PTR(rb_inspect(y)));
|
1339
|
+
}
|
1340
|
+
return power_body(x, y, scale, mode);
|
1190
1341
|
}
|
1191
1342
|
|
1192
|
-
/* TODO: implement dec ** otherdec */
|
1193
1343
|
/*
|
1194
1344
|
* call-seq:
|
1195
1345
|
* dec ** fix => decimal
|
@@ -1201,26 +1351,7 @@ power_with_fixnum(const Decimal *x, VALUE y)
|
|
1201
1351
|
static VALUE
|
1202
1352
|
dec_pow(VALUE x, VALUE y)
|
1203
1353
|
{
|
1204
|
-
|
1205
|
-
long l;
|
1206
|
-
|
1207
|
-
CHECK_NAN(x);
|
1208
|
-
Check_Type(y, T_FIXNUM);
|
1209
|
-
l = FIX2LONG(y);
|
1210
|
-
if (l < 0) rb_raise(rb_eArgError, "in a**b, b should be positive integer");
|
1211
|
-
if (l == 0) return WrapDecimal(dec_raw_new(INT2FIX(1), 0));
|
1212
|
-
if (l == 1) return x;
|
1213
|
-
|
1214
|
-
if (x == VALUE_PINF) return x;
|
1215
|
-
if (x == VALUE_NINF) {
|
1216
|
-
return l % 2 == 0 ? VALUE_PINF : VALUE_NINF;
|
1217
|
-
}
|
1218
|
-
GetDecimal(x, a);
|
1219
|
-
if (a->inum == DEC_PZERO) return x;
|
1220
|
-
if (a->inum == DEC_NZERO) {
|
1221
|
-
return l % 2 == 0 ? dec_uminus(x) : x;
|
1222
|
-
}
|
1223
|
-
return power_with_fixnum(a, y);
|
1354
|
+
return dec_power(1, &y, x);
|
1224
1355
|
}
|
1225
1356
|
|
1226
1357
|
static int
|
@@ -1890,7 +2021,7 @@ math_ldexp10(VALUE module UNUSED, VALUE x, VALUE exp)
|
|
1890
2021
|
if (DEC_VALUE_ISINF(x))
|
1891
2022
|
return x;
|
1892
2023
|
|
1893
|
-
if (
|
2024
|
+
if (FIXNUM_P(x) || TYPE(x) == T_BIGNUM) {
|
1894
2025
|
integer = Qtrue;
|
1895
2026
|
d = inum_to_dec(x);
|
1896
2027
|
}
|
@@ -1922,7 +2053,7 @@ math_frexp10(VALUE module UNUSED, VALUE x)
|
|
1922
2053
|
if (DEC_VALUE_ISINF(x))
|
1923
2054
|
return rb_assoc_new(x, INT2FIX(0));
|
1924
2055
|
|
1925
|
-
if (
|
2056
|
+
if (FIXNUM_P(x) || TYPE(x) == T_BIGNUM) {
|
1926
2057
|
integer = Qtrue;
|
1927
2058
|
d = inum_to_dec(x);
|
1928
2059
|
}
|
@@ -1971,6 +2102,100 @@ math_frexp10(VALUE module UNUSED, VALUE x)
|
|
1971
2102
|
return rb_assoc_new(WrapDecimal(mant), LONG2NUM(exp));
|
1972
2103
|
}
|
1973
2104
|
|
2105
|
+
/* :nodoc: */
|
2106
|
+
static VALUE
|
2107
|
+
math_exp(int argc, VALUE *argv, VALUE module UNUSED) /* (x, scale, rounding=:down) */
|
2108
|
+
{
|
2109
|
+
VALUE x, scale, mode;
|
2110
|
+
int negative;
|
2111
|
+
VALUE z, x1, y, i, d;
|
2112
|
+
VALUE argv2[3]; /* for divide / round */
|
2113
|
+
|
2114
|
+
rb_scan_args(argc, argv, "21", &x, &scale, &mode);
|
2115
|
+
switch (argc) {
|
2116
|
+
case 3:
|
2117
|
+
Check_Type(mode, T_SYMBOL);
|
2118
|
+
if (!valid_rounding_mode_p(mode)) {
|
2119
|
+
rb_raise(rb_eArgError, "invalid rounding mode %s",
|
2120
|
+
RSTRING_PTR(rb_inspect(mode)));
|
2121
|
+
}
|
2122
|
+
/* fall through */
|
2123
|
+
default:
|
2124
|
+
Check_Type(scale, T_FIXNUM);
|
2125
|
+
if (NIL_P(mode)) mode = ROUND_DOWN;
|
2126
|
+
break;
|
2127
|
+
}
|
2128
|
+
if (FIXNUM_P(x) || TYPE(x) == T_BIGNUM) x = WrapDecimal(inum_to_dec(x));
|
2129
|
+
if (dec_nan_p(x)) return VALUE_NaN;
|
2130
|
+
if (dec_zero_p(x)) return WrapDecimal(dec_raw_new(INT2FIX(1), 0));
|
2131
|
+
if (dec_infinite_p(x) != Qnil) {
|
2132
|
+
if (x == VALUE_PINF)
|
2133
|
+
return VALUE_PINF;
|
2134
|
+
return WrapDecimal(dec_raw_new(DEC_PZERO, 0));
|
2135
|
+
}
|
2136
|
+
negative = dec_lt(x, INT2FIX(0));
|
2137
|
+
if (negative) x = dec_uminus(x);
|
2138
|
+
|
2139
|
+
y = WrapDecimal(dec_raw_new(INT2FIX(1), 0));
|
2140
|
+
x1 = WrapDecimal(dec_raw_new(INT2FIX(1), 0));
|
2141
|
+
z = INT2FIX(1);
|
2142
|
+
i = INT2FIX(0);
|
2143
|
+
argv2[1] = INUM_PLUS(scale, INT2FIX(1));
|
2144
|
+
argv2[2] = ROUND_DOWN;
|
2145
|
+
for (;;) {
|
2146
|
+
x1 = dec_mul(x1, x);
|
2147
|
+
INUM_INC(i);
|
2148
|
+
z = INUM_MUL(z, i);
|
2149
|
+
argv2[0] = z;
|
2150
|
+
d = dec_divide(3, argv2, x1);
|
2151
|
+
if (dec_zero_p(d)) break;
|
2152
|
+
y = dec_plus(y, d);
|
2153
|
+
}
|
2154
|
+
if (negative) {
|
2155
|
+
argv2[0] = y;
|
2156
|
+
argv2[1] = scale;
|
2157
|
+
argv2[2] = mode;
|
2158
|
+
y = dec_divide(3, argv2, WrapDecimal(dec_raw_new(INT2FIX(1), 0)));
|
2159
|
+
} else {
|
2160
|
+
argv2[0] = scale;
|
2161
|
+
argv2[1] = mode;
|
2162
|
+
y = dec_round(2, argv2, y);
|
2163
|
+
}
|
2164
|
+
return y;
|
2165
|
+
}
|
2166
|
+
|
2167
|
+
/* internal use only */
|
2168
|
+
static VALUE
|
2169
|
+
math_ln(VALUE x, VALUE scale, VALUE mode)
|
2170
|
+
{
|
2171
|
+
VALUE u, u2, i, d, y;
|
2172
|
+
VALUE argv[3], scale_more;
|
2173
|
+
|
2174
|
+
if (dec_eq(x, INT2FIX(1))) return WrapDecimal(dec_raw_new(DEC_PZERO, 0));
|
2175
|
+
|
2176
|
+
scale_more = LONG2FIX(FIX2LONG(scale) + 1);
|
2177
|
+
argv[0] = dec_plus(x, INT2FIX(1));
|
2178
|
+
argv[1] = scale_more;
|
2179
|
+
argv[2] = ROUND_DOWN;
|
2180
|
+
u = dec_divide(3, argv, dec_minus(x, INT2FIX(1)));
|
2181
|
+
|
2182
|
+
u2 = dec_mul(u, u);
|
2183
|
+
y = u;
|
2184
|
+
i = INT2FIX(1);
|
2185
|
+
for (;;) {
|
2186
|
+
u = dec_floor(1, &scale_more, dec_mul(u, u2));
|
2187
|
+
i = INUM_PLUS(i, INT2FIX(2));
|
2188
|
+
argv[0] = i;
|
2189
|
+
d = dec_divide(3, argv, u);
|
2190
|
+
if (dec_zero_p(d)) break;
|
2191
|
+
y = dec_plus(y, d);
|
2192
|
+
}
|
2193
|
+
y = dec_mul(y, INT2FIX(2));
|
2194
|
+
argv[0] = scale;
|
2195
|
+
argv[1] = mode;
|
2196
|
+
return dec_round(2, argv, y);
|
2197
|
+
}
|
2198
|
+
|
1974
2199
|
/* initialize minimum Math functions in C */
|
1975
2200
|
/* not documented yet. */
|
1976
2201
|
static void
|
@@ -1979,6 +2204,7 @@ init_math(void)
|
|
1979
2204
|
mMath = rb_define_module_under(cDecimal, "Math");
|
1980
2205
|
rb_define_module_function(mMath, "ldexp10", math_ldexp10, 2);
|
1981
2206
|
rb_define_module_function(mMath, "frexp10", math_frexp10, 1);
|
2207
|
+
rb_define_module_function(mMath, "exp", math_exp, -1);
|
1982
2208
|
}
|
1983
2209
|
|
1984
2210
|
|
@@ -2071,6 +2297,7 @@ Init_decimal(void)
|
|
2071
2297
|
rb_define_method(cDecimal, "%", dec_mod, 1);
|
2072
2298
|
rb_define_method(cDecimal, "modulo", dec_mod, 1);
|
2073
2299
|
rb_define_method(cDecimal, "divmod", dec_divmod, 1);
|
2300
|
+
rb_define_method(cDecimal, "power", dec_power, -1);
|
2074
2301
|
rb_define_method(cDecimal, "**", dec_pow, 1);
|
2075
2302
|
rb_define_method(cDecimal, "==", dec_eq, 1);
|
2076
2303
|
rb_define_method(cDecimal, "<=>", dec_cmp, 1);
|