decimal 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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);
|