rubysl-bigdecimal 1.0.0 → 2.0.2
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 +4 -4
- data/.travis.yml +3 -2
- data/README.md +48 -17
- data/{lib/bigdecimal/bigdecimal_en.html → bigdecimal_en.html} +54 -58
- data/{lib/bigdecimal/bigdecimal_ja.html → bigdecimal_ja.html} +6 -6
- data/ext/rubysl/bigdecimal/bigdecimal.c +2234 -1120
- data/ext/rubysl/bigdecimal/bigdecimal.h +114 -57
- data/lib/bigdecimal/jacobian.rb +13 -11
- data/lib/bigdecimal/ludcmp.rb +24 -20
- data/lib/bigdecimal/math.rb +33 -62
- data/lib/bigdecimal/newton.rb +6 -5
- data/lib/bigdecimal/util.rb +87 -43
- data/lib/rubysl/bigdecimal/version.rb +1 -1
- data/rubysl-bigdecimal.gemspec +3 -1
- metadata +20 -23
- data/lib/bigdecimal/README +0 -60
- data/lib/bigdecimal/sample/linear.rb +0 -71
- data/lib/bigdecimal/sample/nlsolve.rb +0 -38
- data/lib/bigdecimal/sample/pi.rb +0 -20
@@ -1,25 +1,76 @@
|
|
1
1
|
/*
|
2
2
|
*
|
3
|
-
* Ruby BigDecimal(Variable decimal precision) extension library.
|
3
|
+
* Ruby BigDecimal(Variable decimal precision) extension library.
|
4
4
|
*
|
5
|
-
* Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp)
|
5
|
+
* Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp)
|
6
6
|
*
|
7
|
-
* You may distribute under the terms of either the GNU General Public
|
8
|
-
* License or the Artistic License, as specified in the README file
|
9
|
-
* of this BigDecimal distribution.
|
7
|
+
* You may distribute under the terms of either the GNU General Public
|
8
|
+
* License or the Artistic License, as specified in the README file
|
9
|
+
* of this BigDecimal distribution.
|
10
10
|
*
|
11
11
|
* NOTES:
|
12
12
|
* 2003-03-28 V1.0 checked in.
|
13
13
|
*
|
14
14
|
*/
|
15
15
|
|
16
|
-
#ifndef
|
17
|
-
#define
|
16
|
+
#ifndef RUBY_BIG_DECIMAL_H
|
17
|
+
#define RUBY_BIG_DECIMAL_H 1
|
18
|
+
|
19
|
+
// Use RSTRING_PTR without caching on Rubinius
|
20
|
+
#define RSTRING_NOT_MODIFIED 1
|
21
|
+
|
22
|
+
#include "ruby/ruby.h"
|
23
|
+
#include <float.h>
|
18
24
|
|
19
25
|
#if defined(__cplusplus)
|
20
26
|
extern "C" {
|
21
27
|
#endif
|
22
28
|
|
29
|
+
#ifndef HAVE_LABS
|
30
|
+
static inline long
|
31
|
+
labs(long const x)
|
32
|
+
{
|
33
|
+
if (x < 0) return -x;
|
34
|
+
return x;
|
35
|
+
}
|
36
|
+
#endif
|
37
|
+
|
38
|
+
#ifndef HAVE_LLABS
|
39
|
+
static inline LONG_LONG
|
40
|
+
llabs(LONG_LONG const x)
|
41
|
+
{
|
42
|
+
if (x < 0) return -x;
|
43
|
+
return x;
|
44
|
+
}
|
45
|
+
#endif
|
46
|
+
|
47
|
+
#ifdef vabs
|
48
|
+
# undef vabs
|
49
|
+
#endif
|
50
|
+
#if SIZEOF_VALUE <= SIZEOF_INT
|
51
|
+
# define vabs abs
|
52
|
+
#elif SIZEOF_VALUE <= SIZEOF_LONG
|
53
|
+
# define vabs labs
|
54
|
+
#elif SIZEOF_VALUE <= SIZEOF_LONG_LONG
|
55
|
+
# define vabs llabs
|
56
|
+
#endif
|
57
|
+
|
58
|
+
extern VALUE rb_cBigDecimal;
|
59
|
+
|
60
|
+
#if SIZEOF_BDIGITS >= 8
|
61
|
+
# define RMPD_COMPONENT_FIGURES 19
|
62
|
+
# define RMPD_BASE ((BDIGIT)10000000000000000000U)
|
63
|
+
#elif SIZEOF_BDIGITS >= 4
|
64
|
+
# define RMPD_COMPONENT_FIGURES 9
|
65
|
+
# define RMPD_BASE ((BDIGIT)1000000000U)
|
66
|
+
#elif SIZEOF_BDIGITS >= 2
|
67
|
+
# define RMPD_COMPONENT_FIGURES 4
|
68
|
+
# define RMPD_BASE ((BDIGIT)10000U)
|
69
|
+
#else
|
70
|
+
# define RMPD_COMPONENT_FIGURES 2
|
71
|
+
# define RMPD_BASE ((BDIGIT)100U)
|
72
|
+
#endif
|
73
|
+
|
23
74
|
/*
|
24
75
|
* NaN & Infinity
|
25
76
|
*/
|
@@ -29,15 +80,10 @@ extern "C" {
|
|
29
80
|
#define SZ_NINF "-Infinity"
|
30
81
|
|
31
82
|
/*
|
32
|
-
* #define VP_EXPORT other than static to let VP_ routines
|
83
|
+
* #define VP_EXPORT other than static to let VP_ routines
|
33
84
|
* be called from outside of this module.
|
34
85
|
*/
|
35
|
-
#define VP_EXPORT static
|
36
|
-
|
37
|
-
#define U_LONG unsigned long
|
38
|
-
#define S_LONG long
|
39
|
-
#define U_INT unsigned int
|
40
|
-
#define S_INT int
|
86
|
+
#define VP_EXPORT static
|
41
87
|
|
42
88
|
/* Exception codes */
|
43
89
|
#define VP_EXCEPTION_ALL ((unsigned short)0x00FF)
|
@@ -45,12 +91,14 @@ extern "C" {
|
|
45
91
|
#define VP_EXCEPTION_NaN ((unsigned short)0x0002)
|
46
92
|
#define VP_EXCEPTION_UNDERFLOW ((unsigned short)0x0004)
|
47
93
|
#define VP_EXCEPTION_OVERFLOW ((unsigned short)0x0001) /* 0x0008) */
|
48
|
-
#define VP_EXCEPTION_ZERODIVIDE ((unsigned short)
|
94
|
+
#define VP_EXCEPTION_ZERODIVIDE ((unsigned short)0x0010)
|
49
95
|
|
50
96
|
/* Following 2 exceptions cann't controlled by user */
|
51
97
|
#define VP_EXCEPTION_OP ((unsigned short)0x0020)
|
52
98
|
#define VP_EXCEPTION_MEMORY ((unsigned short)0x0040)
|
53
99
|
|
100
|
+
#define RMPD_EXCEPTION_MODE_DEFAULT 0U
|
101
|
+
|
54
102
|
/* Computation mode */
|
55
103
|
#define VP_ROUND_MODE ((unsigned short)0x0100)
|
56
104
|
#define VP_ROUND_UP 1
|
@@ -61,6 +109,8 @@ extern "C" {
|
|
61
109
|
#define VP_ROUND_FLOOR 6
|
62
110
|
#define VP_ROUND_HALF_EVEN 7
|
63
111
|
|
112
|
+
#define RMPD_ROUNDING_MODE_DEFAULT VP_ROUND_HALF_UP
|
113
|
+
|
64
114
|
#define VP_SIGN_NaN 0 /* NaN */
|
65
115
|
#define VP_SIGN_POSITIVE_ZERO 1 /* Positive zero */
|
66
116
|
#define VP_SIGN_NEGATIVE_ZERO -1 /* Negative zero */
|
@@ -75,13 +125,13 @@ extern "C" {
|
|
75
125
|
*/
|
76
126
|
typedef struct {
|
77
127
|
VALUE obj; /* Back pointer(VALUE) for Ruby object. */
|
78
|
-
|
128
|
+
size_t MaxPrec; /* Maximum precision size */
|
79
129
|
/* This is the actual size of pfrac[] */
|
80
130
|
/*(frac[0] to frac[MaxPrec] are available). */
|
81
|
-
|
131
|
+
size_t Prec; /* Current precision size. */
|
82
132
|
/* This indicates how much the. */
|
83
133
|
/* the array frac[] is actually used. */
|
84
|
-
|
134
|
+
SIGNED_VALUE exponent; /* Exponent part. */
|
85
135
|
short sign; /* Attributes of the value. */
|
86
136
|
/*
|
87
137
|
* ==0 : NaN
|
@@ -93,23 +143,30 @@ typedef struct {
|
|
93
143
|
* -3 : Negative infinite number
|
94
144
|
*/
|
95
145
|
short flag; /* Not used in vp_routines,space for user. */
|
96
|
-
|
146
|
+
BDIGIT frac[1]; /* Pointer to array of fraction part. */
|
97
147
|
} Real;
|
98
148
|
|
99
|
-
/*
|
149
|
+
/*
|
100
150
|
* ------------------
|
101
151
|
* EXPORTables.
|
102
152
|
* ------------------
|
103
153
|
*/
|
104
154
|
|
105
155
|
VP_EXPORT Real *
|
106
|
-
VpNewRbClass(
|
156
|
+
VpNewRbClass(size_t mx, char const *str, VALUE klass);
|
107
157
|
|
108
|
-
VP_EXPORT Real *VpCreateRbObject(
|
158
|
+
VP_EXPORT Real *VpCreateRbObject(size_t mx,const char *str);
|
109
159
|
|
110
|
-
|
111
|
-
|
112
|
-
|
160
|
+
static inline BDIGIT
|
161
|
+
rmpd_base_value(void) { return RMPD_BASE; }
|
162
|
+
static inline size_t
|
163
|
+
rmpd_component_figures(void) { return RMPD_COMPONENT_FIGURES; }
|
164
|
+
static inline size_t
|
165
|
+
rmpd_double_figures(void) { return 1+DBL_DIG; }
|
166
|
+
|
167
|
+
#define VpBaseFig() rmpd_component_figures()
|
168
|
+
#define VpDblFig() rmpd_double_figures()
|
169
|
+
#define VpBaseVal() rmpd_base_value()
|
113
170
|
|
114
171
|
/* Zero,Inf,NaN (isinf(),isnan() used to check) */
|
115
172
|
VP_EXPORT double VpGetDoubleNaN(void);
|
@@ -118,50 +175,50 @@ VP_EXPORT double VpGetDoubleNegInf(void);
|
|
118
175
|
VP_EXPORT double VpGetDoubleNegZero(void);
|
119
176
|
|
120
177
|
/* These 2 functions added at v1.1.7 */
|
121
|
-
VP_EXPORT
|
122
|
-
VP_EXPORT
|
178
|
+
VP_EXPORT size_t VpGetPrecLimit(void);
|
179
|
+
VP_EXPORT size_t VpSetPrecLimit(size_t n);
|
123
180
|
|
124
181
|
/* Round mode */
|
125
|
-
VP_EXPORT int
|
126
|
-
VP_EXPORT unsigned
|
127
|
-
VP_EXPORT unsigned
|
182
|
+
VP_EXPORT int VpIsRoundMode(unsigned short n);
|
183
|
+
VP_EXPORT unsigned short VpGetRoundMode(void);
|
184
|
+
VP_EXPORT unsigned short VpSetRoundMode(unsigned short n);
|
128
185
|
|
129
186
|
VP_EXPORT int VpException(unsigned short f,const char *str,int always);
|
130
|
-
#if 0
|
187
|
+
#if 0 /* unused */
|
131
188
|
VP_EXPORT int VpIsNegDoubleZero(double v);
|
132
189
|
#endif
|
133
|
-
VP_EXPORT
|
134
|
-
VP_EXPORT
|
135
|
-
VP_EXPORT void *VpMemAlloc(
|
190
|
+
VP_EXPORT size_t VpNumOfChars(Real *vp,const char *pszFmt);
|
191
|
+
VP_EXPORT size_t VpInit(BDIGIT BaseVal);
|
192
|
+
VP_EXPORT void *VpMemAlloc(size_t mb);
|
136
193
|
VP_EXPORT void VpFree(Real *pv);
|
137
|
-
VP_EXPORT Real *VpAlloc(
|
138
|
-
VP_EXPORT
|
139
|
-
VP_EXPORT
|
140
|
-
VP_EXPORT
|
141
|
-
VP_EXPORT
|
194
|
+
VP_EXPORT Real *VpAlloc(size_t mx, const char *szVal);
|
195
|
+
VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw);
|
196
|
+
VP_EXPORT size_t VpAddSub(Real *c,Real *a,Real *b,int operation);
|
197
|
+
VP_EXPORT size_t VpMult(Real *c,Real *a,Real *b);
|
198
|
+
VP_EXPORT size_t VpDivd(Real *c,Real *r,Real *a,Real *b);
|
142
199
|
VP_EXPORT int VpComp(Real *a,Real *b);
|
143
|
-
VP_EXPORT
|
200
|
+
VP_EXPORT ssize_t VpExponent10(Real *a);
|
144
201
|
VP_EXPORT void VpSzMantissa(Real *a,char *psz);
|
145
202
|
VP_EXPORT int VpToSpecialString(Real *a,char *psz,int fPlus);
|
146
|
-
VP_EXPORT void VpToString(Real *a,char *psz,
|
147
|
-
VP_EXPORT void VpToFString(Real *a,char *psz,
|
148
|
-
VP_EXPORT int VpCtoV(Real *a,const char *int_chr,
|
149
|
-
VP_EXPORT int VpVtoD(double *d,
|
203
|
+
VP_EXPORT void VpToString(Real *a, char *psz, size_t fFmt, int fPlus);
|
204
|
+
VP_EXPORT void VpToFString(Real *a, char *psz, size_t fFmt, int fPlus);
|
205
|
+
VP_EXPORT int VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, const char *exp_chr, size_t ne);
|
206
|
+
VP_EXPORT int VpVtoD(double *d, SIGNED_VALUE *e, Real *m);
|
150
207
|
VP_EXPORT void VpDtoV(Real *m,double d);
|
151
|
-
#if 0
|
208
|
+
#if 0 /* unused */
|
152
209
|
VP_EXPORT void VpItoV(Real *m,S_INT ival);
|
153
210
|
#endif
|
154
211
|
VP_EXPORT int VpSqrt(Real *y,Real *x);
|
155
|
-
VP_EXPORT int VpActiveRound(Real *y,Real *x,
|
156
|
-
VP_EXPORT int VpMidRound(Real *y,
|
157
|
-
VP_EXPORT int VpLeftRound(Real *y,
|
158
|
-
VP_EXPORT void VpFrac(Real *y,Real *x);
|
159
|
-
VP_EXPORT int VpPower(Real *y,Real *x,
|
212
|
+
VP_EXPORT int VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t il);
|
213
|
+
VP_EXPORT int VpMidRound(Real *y, unsigned short f, ssize_t nf);
|
214
|
+
VP_EXPORT int VpLeftRound(Real *y, unsigned short f, ssize_t nf);
|
215
|
+
VP_EXPORT void VpFrac(Real *y, Real *x);
|
216
|
+
VP_EXPORT int VpPower(Real *y, Real *x, SIGNED_VALUE n);
|
160
217
|
|
161
218
|
/* VP constants */
|
162
219
|
VP_EXPORT Real *VpOne(void);
|
163
220
|
|
164
|
-
/*
|
221
|
+
/*
|
165
222
|
* ------------------
|
166
223
|
* MACRO definitions.
|
167
224
|
* ------------------
|
@@ -179,12 +236,12 @@ VP_EXPORT Real *VpOne(void);
|
|
179
236
|
/* VpGetSign(a) returns 1,-1 if a>0,a<0 respectively */
|
180
237
|
#define VpGetSign(a) (((a)->sign>0)?1:(-1))
|
181
238
|
/* Change sign of a to a>0,a<0 if s = 1,-1 respectively */
|
182
|
-
#define VpChangeSign(a,s) {if((s)>0) (a)->sign=(short)Abs((
|
239
|
+
#define VpChangeSign(a,s) {if((s)>0) (a)->sign=(short)Abs((ssize_t)(a)->sign);else (a)->sign=-(short)Abs((ssize_t)(a)->sign);}
|
183
240
|
/* Sets sign of a to a>0,a<0 if s = 1,-1 respectively */
|
184
241
|
#define VpSetSign(a,s) {if((s)>0) (a)->sign=(short)VP_SIGN_POSITIVE_FINITE;else (a)->sign=(short)VP_SIGN_NEGATIVE_FINITE;}
|
185
242
|
|
186
243
|
/* 1 */
|
187
|
-
#define VpSetOne(a) {(a)->
|
244
|
+
#define VpSetOne(a) {(a)->Prec=(a)->exponent=(a)->frac[0]=1;(a)->sign=VP_SIGN_POSITIVE_FINITE;}
|
188
245
|
|
189
246
|
/* ZEROs */
|
190
247
|
#define VpIsPosZero(a) ((a)->sign==VP_SIGN_POSITIVE_ZERO)
|
@@ -209,12 +266,12 @@ VP_EXPORT Real *VpOne(void);
|
|
209
266
|
#define VpHasVal(a) (a->frac[0])
|
210
267
|
#define VpIsOne(a) ((a->Prec==1)&&(a->frac[0]==1)&&(a->exponent==1))
|
211
268
|
#define VpExponent(a) (a->exponent)
|
212
|
-
#ifdef
|
269
|
+
#ifdef BIGDECIMAL_DEBUG
|
213
270
|
int VpVarCheck(Real * v);
|
214
|
-
VP_EXPORT int VPrint(FILE *fp,char *cntl_chr,Real *a);
|
215
|
-
#endif /*
|
271
|
+
VP_EXPORT int VPrint(FILE *fp,const char *cntl_chr,Real *a);
|
272
|
+
#endif /* BIGDECIMAL_DEBUG */
|
216
273
|
|
217
274
|
#if defined(__cplusplus)
|
218
275
|
} /* extern "C" { */
|
219
276
|
#endif
|
220
|
-
#endif /*
|
277
|
+
#endif /* RUBY_BIG_DECIMAL_H */
|
data/lib/bigdecimal/jacobian.rb
CHANGED
@@ -21,18 +21,20 @@
|
|
21
21
|
# fx is f.values(x).
|
22
22
|
#
|
23
23
|
module Jacobian
|
24
|
+
module_function
|
25
|
+
|
24
26
|
#--
|
25
27
|
def isEqual(a,b,zero=0.0,e=1.0e-8)
|
26
28
|
aa = a.abs
|
27
29
|
bb = b.abs
|
28
30
|
if aa == zero && bb == zero then
|
29
|
-
|
31
|
+
true
|
30
32
|
else
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
if ((a-b)/(aa+bb)).abs < e then
|
34
|
+
true
|
35
|
+
else
|
36
|
+
false
|
37
|
+
end
|
36
38
|
end
|
37
39
|
end
|
38
40
|
#++
|
@@ -52,17 +54,17 @@ module Jacobian
|
|
52
54
|
s = f.zero
|
53
55
|
deriv = []
|
54
56
|
if(nRetry>100) then
|
55
|
-
|
57
|
+
raise "Singular Jacobian matrix. No change at x[" + i.to_s + "]"
|
56
58
|
end
|
57
59
|
dx = dx*f.two
|
58
60
|
x[i] += dx
|
59
61
|
fxNew = f.values(x)
|
60
62
|
for j in 0...n do
|
61
63
|
if !isEqual(fxNew[j],fx[j],f.zero,f.eps) then
|
62
|
-
|
63
|
-
|
64
|
+
ok += 1
|
65
|
+
deriv <<= (fxNew[j]-fx[j])/dx
|
64
66
|
else
|
65
|
-
|
67
|
+
deriv <<= f.zero
|
66
68
|
end
|
67
69
|
end
|
68
70
|
x[i] = xSave
|
@@ -77,7 +79,7 @@ module Jacobian
|
|
77
79
|
for i in 0...n do
|
78
80
|
df = dfdxi(f,fx,x,i)
|
79
81
|
for j in 0...n do
|
80
|
-
|
82
|
+
dfdx[j*n+i] = df[j]
|
81
83
|
end
|
82
84
|
end
|
83
85
|
dfdx
|
data/lib/bigdecimal/ludcmp.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
|
1
3
|
#
|
2
4
|
# Solves a*x = b for x, using LU decomposition.
|
3
5
|
#
|
4
6
|
module LUSolve
|
7
|
+
module_function
|
8
|
+
|
5
9
|
# Performs LU decomposition of the n by n matrix a.
|
6
10
|
def ludecomp(a,n,zero=0,one=1)
|
7
11
|
prec = BigDecimal.limit(nil)
|
@@ -12,24 +16,24 @@ module LUSolve
|
|
12
16
|
nrmrow = zero
|
13
17
|
ixn = i*n
|
14
18
|
for j in 0...n do
|
15
|
-
|
16
|
-
|
19
|
+
biggst = a[ixn+j].abs
|
20
|
+
nrmrow = biggst if biggst>nrmrow
|
17
21
|
end
|
18
22
|
if nrmrow>zero then
|
19
|
-
|
20
|
-
else
|
21
|
-
|
23
|
+
scales <<= one.div(nrmrow,prec)
|
24
|
+
else
|
25
|
+
raise "Singular matrix"
|
22
26
|
end
|
23
27
|
end
|
24
28
|
n1 = n - 1
|
25
29
|
for k in 0...n1 do # Gaussian elimination with partial pivoting.
|
26
30
|
biggst = zero;
|
27
31
|
for i in k...n do
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
32
|
+
size = a[ps[i]*n+k].abs*scales[ps[i]]
|
33
|
+
if size>biggst then
|
34
|
+
biggst = size
|
35
|
+
pividx = i
|
36
|
+
end
|
33
37
|
end
|
34
38
|
raise "Singular matrix" if biggst<=zero
|
35
39
|
if pividx!=k then
|
@@ -42,10 +46,10 @@ module LUSolve
|
|
42
46
|
psin = ps[i]*n
|
43
47
|
a[psin+k] = mult = a[psin+k].div(pivot,prec)
|
44
48
|
if mult!=zero then
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
+
pskn = ps[k]*n
|
50
|
+
for j in (k+1)...n do
|
51
|
+
a[psin+j] -= mult.mult(a[pskn+j],prec)
|
52
|
+
end
|
49
53
|
end
|
50
54
|
end
|
51
55
|
end
|
@@ -72,12 +76,12 @@ module LUSolve
|
|
72
76
|
x <<= b[ps[i]] - dot
|
73
77
|
end
|
74
78
|
(n-1).downto(0) do |i|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
79
|
+
dot = zero
|
80
|
+
psin = ps[i]*n
|
81
|
+
for j in (i+1)...n do
|
82
|
+
dot = a[psin+j].mult(x[j],prec) + dot
|
83
|
+
end
|
84
|
+
x[i] = (x[i]-dot).div(a[psin+i],prec)
|
81
85
|
end
|
82
86
|
x
|
83
87
|
end
|
data/lib/bigdecimal/math.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
|
1
3
|
#
|
2
4
|
#--
|
3
5
|
# Contents:
|
@@ -5,7 +7,6 @@
|
|
5
7
|
# sin (x, prec)
|
6
8
|
# cos (x, prec)
|
7
9
|
# atan(x, prec) Note: |x|<1, x=0.9999 may not converge.
|
8
|
-
# exp (x, prec)
|
9
10
|
# log (x, prec)
|
10
11
|
# PI (prec)
|
11
12
|
# E (prec) == exp(1.0,prec)
|
@@ -29,11 +30,12 @@
|
|
29
30
|
# puts sin(a,100) # -> 0.10000000000000000000......E1
|
30
31
|
#
|
31
32
|
module BigMath
|
33
|
+
module_function
|
32
34
|
|
33
|
-
# Computes the square root of x to the specified number of digits of
|
35
|
+
# Computes the square root of x to the specified number of digits of
|
34
36
|
# precision.
|
35
37
|
#
|
36
|
-
# BigDecimal.new('2').sqrt(16).to_s
|
38
|
+
# BigDecimal.new('2').sqrt(16).to_s
|
37
39
|
# -> "0.14142135623730950488016887242096975E1"
|
38
40
|
#
|
39
41
|
def sqrt(x,prec)
|
@@ -49,6 +51,14 @@ module BigMath
|
|
49
51
|
n = prec + BigDecimal.double_fig
|
50
52
|
one = BigDecimal("1")
|
51
53
|
two = BigDecimal("2")
|
54
|
+
x = -x if neg = x < 0
|
55
|
+
if x > (twopi = two * BigMath.PI(prec))
|
56
|
+
if x > 30
|
57
|
+
x %= twopi
|
58
|
+
else
|
59
|
+
x -= twopi while x > twopi
|
60
|
+
end
|
61
|
+
end
|
52
62
|
x1 = x
|
53
63
|
x2 = x.mult(x,n)
|
54
64
|
sign = 1
|
@@ -65,7 +75,7 @@ module BigMath
|
|
65
75
|
d = sign * x1.div(z,m)
|
66
76
|
y += d
|
67
77
|
end
|
68
|
-
y
|
78
|
+
neg ? -y : y
|
69
79
|
end
|
70
80
|
|
71
81
|
# Computes the cosine of x to the specified number of digits of precision.
|
@@ -77,6 +87,14 @@ module BigMath
|
|
77
87
|
n = prec + BigDecimal.double_fig
|
78
88
|
one = BigDecimal("1")
|
79
89
|
two = BigDecimal("2")
|
90
|
+
x = -x if x < 0
|
91
|
+
if x > (twopi = two * BigMath.PI(prec))
|
92
|
+
if x > 30
|
93
|
+
x %= twopi
|
94
|
+
else
|
95
|
+
x -= twopi while x > twopi
|
96
|
+
end
|
97
|
+
end
|
80
98
|
x1 = one
|
81
99
|
x2 = x.mult(x,n)
|
82
100
|
sign = 1
|
@@ -98,12 +116,16 @@ module BigMath
|
|
98
116
|
|
99
117
|
# Computes the arctangent of x to the specified number of digits of precision.
|
100
118
|
#
|
101
|
-
# If x is
|
102
|
-
# Raises an argument error if x > 1.
|
119
|
+
# If x is NaN, returns NaN.
|
103
120
|
def atan(x, prec)
|
104
121
|
raise ArgumentError, "Zero or negative precision for atan" if prec <= 0
|
105
|
-
return BigDecimal("NaN") if x.
|
106
|
-
|
122
|
+
return BigDecimal("NaN") if x.nan?
|
123
|
+
pi = PI(prec)
|
124
|
+
x = -x if neg = x < 0
|
125
|
+
return pi.div(neg ? -2 : 2, prec) if x.infinite?
|
126
|
+
return pi / (neg ? -4 : 4) if x.round(prec) == 1
|
127
|
+
x = BigDecimal("1").div(x, prec) if inv = x > 1
|
128
|
+
x = (-1 + sqrt(1 + x**2, prec))/x if dbl = x > 0.5
|
107
129
|
n = prec + BigDecimal.double_fig
|
108
130
|
y = x
|
109
131
|
d = y
|
@@ -117,63 +139,12 @@ module BigMath
|
|
117
139
|
y += d
|
118
140
|
r += 2
|
119
141
|
end
|
142
|
+
y *= 2 if dbl
|
143
|
+
y = pi / 2 - y if inv
|
144
|
+
y = -y if neg
|
120
145
|
y
|
121
146
|
end
|
122
147
|
|
123
|
-
# Computes the value of e (the base of natural logarithms) raised to the
|
124
|
-
# power of x, to the specified number of digits of precision.
|
125
|
-
#
|
126
|
-
# If x is infinite or NaN, returns NaN.
|
127
|
-
#
|
128
|
-
# BigMath::exp(BigDecimal.new('1'), 10).to_s
|
129
|
-
# -> "0.271828182845904523536028752390026306410273E1"
|
130
|
-
def exp(x, prec)
|
131
|
-
raise ArgumentError, "Zero or negative precision for exp" if prec <= 0
|
132
|
-
return BigDecimal("NaN") if x.infinite? || x.nan?
|
133
|
-
n = prec + BigDecimal.double_fig
|
134
|
-
one = BigDecimal("1")
|
135
|
-
x1 = one
|
136
|
-
y = one
|
137
|
-
d = y
|
138
|
-
z = one
|
139
|
-
i = 0
|
140
|
-
while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
|
141
|
-
m = BigDecimal.double_fig if m < BigDecimal.double_fig
|
142
|
-
x1 = x1.mult(x,n)
|
143
|
-
i += 1
|
144
|
-
z *= i
|
145
|
-
d = x1.div(z,m)
|
146
|
-
y += d
|
147
|
-
end
|
148
|
-
y
|
149
|
-
end
|
150
|
-
|
151
|
-
# Computes the natural logarithm of x to the specified number of digits
|
152
|
-
# of precision.
|
153
|
-
#
|
154
|
-
# Returns x if x is infinite or NaN.
|
155
|
-
#
|
156
|
-
def log(x, prec)
|
157
|
-
raise ArgumentError, "Zero or negative argument for log" if x <= 0 || prec <= 0
|
158
|
-
return x if x.infinite? || x.nan?
|
159
|
-
one = BigDecimal("1")
|
160
|
-
two = BigDecimal("2")
|
161
|
-
n = prec + BigDecimal.double_fig
|
162
|
-
x = (x - one).div(x + one,n)
|
163
|
-
x2 = x.mult(x,n)
|
164
|
-
y = x
|
165
|
-
d = y
|
166
|
-
i = one
|
167
|
-
while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
|
168
|
-
m = BigDecimal.double_fig if m < BigDecimal.double_fig
|
169
|
-
x = x2.mult(x,n)
|
170
|
-
i += two
|
171
|
-
d = x.div(i,m)
|
172
|
-
y += d
|
173
|
-
end
|
174
|
-
y*two
|
175
|
-
end
|
176
|
-
|
177
148
|
# Computes the value of pi to the specified number of digits of precision.
|
178
149
|
def PI(prec)
|
179
150
|
raise ArgumentError, "Zero or negative argument for PI" if prec <= 0
|