1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* ext/bigdecimal/bigdecimal.c: add RDoc document. a patch from

mathew <meta at pobox.com>.   [ruby-core:07050]


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10428 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2006-06-29 09:09:33 +00:00
parent 0c11152794
commit 60bf66e0cd
7 changed files with 705 additions and 38 deletions

View file

@ -1,6 +1,12 @@
Thu Jun 29 18:00:51 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* ext/bigdecimal/bigdecimal.c: add RDoc document. a patch from
mathew <meta at pobox.com>. [ruby-core:07050]
Wed Jun 28 14:53:09 2006 Eric Hodel <drbrain@segment7.net>
* lib/optparse.rb: RDoc patch from Robin Stocker <robin@nibor.org>
[ruby-core:08087]
Wed Jun 28 23:23:48 2006 Yukihiro Matsumoto <matz@ruby-lang.org>

View file

@ -41,8 +41,125 @@ VALUE rb_cBigDecimal;
*/
#define DoSomeOne(x,y) rb_num_coerce_bin(x,y)
#if 0
/* BigDecimal provides arbitrary-precision floating point decimal arithmetic.
*
* Copyright (C) 2002 by Shigeo Kobayashi <shigeo@tinyforest.gr.jp>.
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file
* of the BigDecimal distribution.
*
* Documented by mathew <meta@pobox.com>.
*
* = Introduction
*
* Ruby provides built-in support for arbitrary precision integer arithmetic.
* For example:
*
* 42**13 -> 1265437718438866624512
*
* BigDecimal provides similar support for very large or very accurate floating
* point numbers.
*
* Decimal arithmetic is also useful for general calculation, because it
* provides the correct answers people expect--whereas normal binary floating
* point arithmetic often introduces subtle errors because of the conversion
* between base 10 and base 2. For example, try:
*
* sum = 0
* for i in (1..10000)
* sum = sum + 0.0001
* end
* print sum
*
* and contrast with the output from:
*
* require 'bigdecimal'
*
* sum = BigDecimal.new("0")
* for i in (1..10000)
* sum = sum + BigDecimal.new("0.0001")
* end
* print sum
*
* Similarly:
*
* (BigDecimal.new("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") -> true
*
* (1.2 - 1.0) == 0.2 -> false
*
* = Special features of accurate decimal arithmetic
*
* Because BigDecimal is more accurate than normal binary floating point
* arithmetic, it requires some special values.
*
* == Infinity
*
* BigDecimal sometimes needs to return infinity, for example if you divide
* a value by zero.
*
* BigDecimal.new("1.0") / BigDecimal.new("0.0") -> infinity
*
* BigDecimal.new("-1.0") / BigDecimal.new("0.0") -> -infinity
*
* You can represent infinite numbers to BigDecimal using the strings
* 'Infinity', '+Infinity' and '-Infinity' (case-sensitive)
*
* == Not a Number
*
* When a computation results in an undefined value, the special value NaN
* (for 'not a number') is returned.
*
* Example:
*
* BigDecimal.new("0.0") / BigDecimal.new("0.0") -> NaN
*
* You can also create undefined values. NaN is never considered to be the
* same as any other value, even NaN itself:
*
* n = BigDecimal.new('NaN')
*
* n == 0.0 -> nil
*
* n == n -> nil
*
* == Positive and negative zero
*
* If a computation results in a value which is too small to be represented as
* a BigDecimal within the currently specified limits of precision, zero must
* be returned.
*
* If the value which is too small to be represented is negative, a BigDecimal
* value of negative zero is returned. If the value is positive, a value of
* positive zero is returned.
*
* BigDecimal.new("1.0") / BigDecimal.new("-Infinity") -> -0.0
*
* BigDecimal.new("1.0") / BigDecimal.new("Infinity") -> 0.0
*
* (See BigDecimal.mode for how to specify limits of precision.)
*
* Note that -0.0 and 0.0 are considered to be the same for the purposes of
* comparison.
*
* Note also that in mathematics, there is no particular concept of negative
* or positive zero; true mathematical zero has no sign.
*/
void
Init_BigDecimal()
{
/* This is a #if-ed out function to fool Rdoc into documenting the class. */
/* The real init function is Init_bigdecimal() further down. */
}
#endif
void
/*
* **** BigDecimal version ****
* Returns the BigDecimal version number.
*
* Ruby 1.8.0 returns 1.0.0.
* Ruby 1.8.1 thru 1.8.3 return 1.0.1.
*/
static VALUE
BigDecimal_version(VALUE self)
@ -132,12 +249,28 @@ SomeOneMayDoIt:
return NULL; /* NULL means to coerce */
}
/* call-seq:
* BigDecimal.double_fig
*
* The BigDecimal.double_fig class method returns the number of digits a
* Float number is allowed to have. The result depends upon the CPU and OS
* in use.
*/
static VALUE
BigDecimal_double_fig(VALUE self)
{
return INT2FIX(VpDblFig());
}
/* call-seq:
* precs
*
* Returns an Array of two Integer values.
*
* The first value is the current number of significant digits in the
* BigDecimal. The second value is the maximum number of significant digits
* for the BigDecimal.
*/
static VALUE
BigDecimal_prec(VALUE self)
{
@ -188,6 +321,9 @@ BigDecimal_dump(int argc, VALUE *argv, VALUE self)
return rb_str_new2(psz);
}
/*
* Internal method used to provide marshalling support. See the Marshal module.
*/
static VALUE
BigDecimal_load(VALUE self, VALUE str)
{
@ -213,6 +349,44 @@ BigDecimal_load(VALUE self, VALUE str)
return ToValue(pv);
}
/* call-seq:
* BigDecimal.mode(mode, value)
*
* Controls handling of arithmetic exceptions and rounding. If no value
* is supplied, the current value is returned.
*
* Six values of the mode parameter control the handling of arithmetic
* exceptions:
*
* BigDecimal::EXCEPTION_NaN
* BigDecimal::EXCEPTION_INFINITY
* BigDecimal::EXCEPTION_UNDERFLOW
* BigDecimal::EXCEPTION_OVERFLOW
* BigDecimal::EXCEPTION_ZERODIVIDE
* BigDecimal::EXCEPTION_ALL
*
* For each mode parameter above, if the value set is false, computation
* continues after an arithmetic exception of the appropriate type.
* When computation continues, results are as follows:
*
* EXCEPTION_NaN:: NaN
* EXCEPTION_INFINITY:: +infinity or -infinity
* EXCEPTION_UNDERFLOW:: 0
* EXCEPTION_OVERFLOW:: +infinity or -infinity
* EXCEPTION_ZERODIVIDE:: +infinity or -infinity
*
* One value of the mode parameter controls the rounding of numeric values:
* BigDecimal::ROUND_MODE. The values it can take are:
*
* ROUND_UP:: round away from zero
* ROUND_DOWN:: round towards zero (truncate)
* ROUND_HALF_UP:: round up if the appropriate digit >= 5, otherwise truncate (default)
* ROUND_HALF_DOWN:: round up if the appropriate digit >= 6, otherwise truncate
* ROUND_HALF_EVEN:: round towards the even neighbor (Banker's rounding)
* ROUND_CEILING:: round towards positive infinity (ceil)
* ROUND_FLOOR:: round towards negative infinity (floor)
*
*/
static VALUE
BigDecimal_mode(int argc, VALUE *argv, VALUE self)
{
@ -309,7 +483,7 @@ VpCreateRbObject(U_LONG mx, const char *str)
return pv;
}
/* Returns True if the value is Not a Number */
static VALUE
BigDecimal_IsNaN(VALUE self)
{
@ -318,6 +492,7 @@ BigDecimal_IsNaN(VALUE self)
return Qfalse;
}
/* Returns True if the value is infinite */
static VALUE
BigDecimal_IsInfinite(VALUE self)
{
@ -327,6 +502,7 @@ BigDecimal_IsInfinite(VALUE self)
return Qnil;
}
/* Returns True if the value is finite (not NaN or infinite) */
static VALUE
BigDecimal_IsFinite(VALUE self)
{
@ -336,6 +512,10 @@ BigDecimal_IsFinite(VALUE self)
return Qtrue;
}
/* Returns the value as an integer (Fixnum or Bignum).
*
* If the BigNumber is infinity or NaN, returns nil.
*/
static VALUE
BigDecimal_to_i(VALUE self)
{
@ -399,6 +579,10 @@ BigDecimal_induced_from(VALUE self, VALUE x)
return p->obj;
}
/* Returns a new Float object having approximately the same value as the
* BigDecimal number. Normal accuracy limits and built-in errors of binary
* Float arithmetic apply.
*/
static VALUE
BigDecimal_to_f(VALUE self)
{
@ -419,6 +603,20 @@ BigDecimal_to_f(VALUE self)
return rb_float_new(d*d2);
}
/* The coerce method provides support for Ruby type coercion. It is not
* enabled by default.
*
* This means that binary operations like + * / or - can often be performed
* on a BigDecimal and an object of another type, if the other object can
* be coerced into a BigDecimal value.
*
* e.g.
* a = BigDecimal.new("1.0")
* b = a / 2.0 -> 0.5
*
* Note that coercing a String to a BigDecimal is not supported by default;
* it requires a special compile-time option when building Ruby.
*/
static VALUE
BigDecimal_coerce(VALUE self, VALUE other)
{
@ -440,6 +638,17 @@ BigDecimal_uplus(VALUE self)
return self;
}
/* call-seq:
* add(value, digits)
*
* Add the specified value.
*
* e.g.
* c = a.add(b,n)
* c = a + b
*
* digits:: If specified and less than the number of significant digits of the result, the result is rounded to that number of digits, according to BigDecimal.mode.
*/
static VALUE
BigDecimal_add(VALUE self, VALUE r)
{
@ -467,6 +676,17 @@ BigDecimal_add(VALUE self, VALUE r)
return ToValue(c);
}
/* call-seq:
* sub(value, digits)
*
* Subtract the specified value.
*
* e.g.
* c = a.sub(b,n)
* c = a - b
*
* digits:: If specified and less than the number of significant digits of the result, the result is rounded to that number of digits, according to BigDecimal.mode.
*/
static VALUE
BigDecimal_sub(VALUE self, VALUE r)
{
@ -522,6 +742,7 @@ BigDecimalCmp(VALUE self, VALUE r,char op)
rb_bug("Undefined operation in BigDecimalCmp()");
}
/* Returns True if the value is zero. */
static VALUE
BigDecimal_zero(VALUE self)
{
@ -529,6 +750,7 @@ BigDecimal_zero(VALUE self)
return VpIsZero(a) ? Qtrue : Qfalse;
}
/* Returns True if the value is non-zero. */
static VALUE
BigDecimal_nonzero(VALUE self)
{
@ -536,42 +758,84 @@ BigDecimal_nonzero(VALUE self)
return VpIsZero(a) ? Qnil : self;
}
/* The comparison operator.
* a <=> b is 0 if a == b, 1 if a > b, -1 if a < b.
*/
static VALUE
BigDecimal_comp(VALUE self, VALUE r)
{
return BigDecimalCmp(self, r, '*');
}
/*
* Tests for value equality; returns true if the values are equal.
*
* The == and === operators and the eql? method have the same implementation
* for BigDecimal.
*
* Values may be coerced to perform the comparison:
*
* BigDecimal.new('1.0') == 1.0 -> true
*/
static VALUE
BigDecimal_eq(VALUE self, VALUE r)
{
return BigDecimalCmp(self, r, '=');
}
/* Returns true if the values are not equal in value. Values may be coerced
* to perform the comparison:
*
* BigDecimal.new('1.0') != 1.0 -> false
*/
static VALUE
BigDecimal_ne(VALUE self, VALUE r)
{
return BigDecimalCmp(self, r, '!');
}
/* call-seq:
* a < b
*
* Returns true if a is less than b. Values may be coerced to perform the
* comparison (see ==, coerce).
*/
static VALUE
BigDecimal_lt(VALUE self, VALUE r)
{
return BigDecimalCmp(self, r, '<');
}
/* call-seq:
* a <= b
*
* Returns true if a is less than or equal to b. Values may be coerced to
* perform the comparison (see ==, coerce).
*/
static VALUE
BigDecimal_le(VALUE self, VALUE r)
{
return BigDecimalCmp(self, r, 'L');
}
/* call-seq:
* a > b
*
* Returns true if a is greater than b. Values may be coerced to
* perform the comparison (see ==, coerce).
*/
static VALUE
BigDecimal_gt(VALUE self, VALUE r)
{
return BigDecimalCmp(self, r, '>');
}
/* call-seq:
* a >= b
*
* Returns true if a is greater than or equal to b. Values may be coerced to
* perform the comparison (see ==, coerce)
*/
static VALUE
BigDecimal_ge(VALUE self, VALUE r)
{
@ -589,6 +853,17 @@ BigDecimal_neg(VALUE self)
return ToValue(c);
}
/* call-seq:
* mult(value, digits)
*
* Multiply by the specified value.
*
* e.g.
* c = a.mult(b,n)
* c = a * b
*
* digits:: If specified and less than the number of significant digits of the result, the result is rounded to that number of digits, according to BigDecimal.mode.
*/
static VALUE
BigDecimal_mult(VALUE self, VALUE r)
{
@ -627,6 +902,23 @@ BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r)
return (VALUE)0;
}
/* call-seq:
* div(value, digits)
* quo(value)
*
* Divide by the specified value.
*
* e.g.
* c = a.div(b,n)
*
* digits:: If specified and less than the number of significant digits of the result, the result is rounded to that number of digits, according to BigDecimal.mode.
*
* If digits is 0, the result is the same as the / operator. If not, the
* result is an integer BigDecimal, by analogy with Float#div.
*
* The alias quo is provided since div(value, 0) is the same as computing
* the quotient; see divmod.
*/
static VALUE
BigDecimal_div(VALUE self, VALUE r)
/* For c = self/r: with round operation */
@ -705,6 +997,12 @@ NaN:
return (VALUE)0;
}
/* call-seq:
* a % b
* a.modulo(b)
*
* Returns the modulus from dividing by b. See divmod.
*/
static VALUE
BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */
{
@ -755,6 +1053,13 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
return (VALUE)0;
}
/* Returns the remainder from dividing by the value.
*
* If the values divided are of the same sign, the remainder is the same as
* the modulus (see divmod).
*
* Otherwise, the remainder is the modulus minus the value divided by.
*/
static VALUE
BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
{
@ -765,6 +1070,25 @@ BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
return ToValue(rv);
}
/* Divides by the specified value, and returns the quotient and modulus
* as BigDecimal numbers. The quotient is rounded towards negative infinity.
*
* For example:
*
* require 'bigdecimal'
*
* a = BigDecimal.new("42")
* b = BigDecimal.new("9")
*
* q,m = a.divmod(b)
*
* c = q * b + m
*
* a == c -> true
*
* The quotient q is (a/b).floor, and the modulus is the amount that must be
* added to q * b to get a.
*/
static VALUE
BigDecimal_divmod(VALUE self, VALUE r)
{
@ -866,6 +1190,12 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
}
}
/* Returns the absolute value.
*
* BigDecimal('5').abs -> 5
*
* BigDecimal('-3').abs -> 3
*/
static VALUE
BigDecimal_abs(VALUE self)
{
@ -881,6 +1211,13 @@ BigDecimal_abs(VALUE self)
return ToValue(c);
}
/* call-seq:
* sqrt(n)
*
* Returns the square root of the value.
*
* If n is specified, returns at least that many significant digits.
*/
static VALUE
BigDecimal_sqrt(VALUE self, VALUE nFig)
{
@ -898,6 +1235,8 @@ BigDecimal_sqrt(VALUE self, VALUE nFig)
return ToValue(c);
}
/* Return the integer part of the number.
*/
static VALUE
BigDecimal_fix(VALUE self)
{
@ -912,6 +1251,28 @@ BigDecimal_fix(VALUE self)
return ToValue(c);
}
/* call-seq:
* round(n,mode)
*
* Round to the nearest 1 (by default), returning the result as a BigDecimal.
*
* BigDecimal('3.14159').round -> 3
*
* BigDecimal('8.7').round -> 9
*
* If n is specified and positive, the fractional part of the result has no
* more than that many digits.
*
* If n is specified and negative, at least that many digits to the left of the
* decimal point will be 0 in the result.
*
* BigDecimal('3.14159').round(3) -> 3.142
*
* BigDecimal('13345.234').round(-2) -> 13300.0
*
* The value of the optional mode argument can be used to determine how
* rounding is performed; see BigDecimal.mode.
*/
static VALUE
BigDecimal_round(int argc, VALUE *argv, VALUE self)
{
@ -955,6 +1316,25 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
return ToValue(c);
}
/* call-seq:
* truncate(n)
*
* Truncate to the nearest 1, returning the result as a BigDecimal.
*
* BigDecimal('3.14159').truncate -> 3
*
* BigDecimal('8.7').truncate -> 8
*
* If n is specified and positive, the fractional part of the result has no
* more than that many digits.
*
* If n is specified and negative, at least that many digits to the left of the
* decimal point will be 0 in the result.
*
* BigDecimal('3.14159').truncate(3) -> 3.141
*
* BigDecimal('13345.234').truncate(-2) -> 13300.0
*/
static VALUE
BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
{
@ -980,6 +1360,8 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
return ToValue(c);
}
/* Return the fractional part of the number.
*/
static VALUE
BigDecimal_frac(VALUE self)
{
@ -994,6 +1376,25 @@ BigDecimal_frac(VALUE self)
return ToValue(c);
}
/* call-seq:
* floor(n)
*
* Return the largest integer less than or equal to the value, as a BigDecimal.
*
* BigDecimal('3.14159').floor -> 3
*
* BigDecimal('-9.1').floor -> -10
*
* If n is specified and positive, the fractional part of the result has no
* more than that many digits.
*
* If n is specified and negative, at least that
* many digits to the left of the decimal point will be 0 in the result.
*
* BigDecimal('3.14159').floor(3) -> 3.141
*
* BigDecimal('13345.234').floor(-2) -> 13300.0
*/
static VALUE
BigDecimal_floor(int argc, VALUE *argv, VALUE self)
{
@ -1019,6 +1420,25 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
return ToValue(c);
}
/* call-seq:
* ceil(n)
*
* Return the smallest integer greater than or equal to the value, as a BigDecimal.
*
* BigDecimal('3.14159').ceil -> 4
*
* BigDecimal('-9.1').ceil -> -9
*
* If n is specified and positive, the fractional part of the result has no
* more than that many digits.
*
* If n is specified and negative, at least that
* many digits to the left of the decimal point will be 0 in the result.
*
* BigDecimal('3.14159').ceil(3) -> 3.142
*
* BigDecimal('13345.234').ceil(-2) -> 13400.0
*/
static VALUE
BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
{
@ -1044,6 +1464,36 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
return ToValue(c);
}
/* call-seq:
* to_s(s)
*
* Converts the value to a string.
*
* The default format looks like 0.xxxxEnn.
*
* The optional parameter s consists of either an integer; or an optional '+'
* or ' ', followed by an optional number, followed by an optional 'E' or 'F'.
*
* If there is a '+' at the start of s, positive values are returned with
* a leading '+'.
*
* A space at the start of s returns positive values with a leading space.
*
* If s contains a number, a space is inserted after each group of that many
* fractional digits.
*
* If s ends with an 'E', engineering notation (0.xxxxEnn) is used.
*
* If s ends with an 'F', conventional floating point notation is used.
*
* Examples:
*
* BigDecimal.new('-123.45678901234567890').to_s('5F') -> '-123.45678 90123 45678 9'
*
* BigDecimal.new('123.45678901234567890').to_s('+8F') -> '+123.45678901 23456789'
*
* BigDecimal.new('123.45678901234567890').to_s(' F') -> ' 123.4567890123456789'
*/
static VALUE
BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
{
@ -1097,6 +1547,30 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
return rb_str_new2(psz);
}
/* Splits a BigDecimal number into four parts, returned as an array of values.
*
* The first value represents the sign of the BigDecimal, and is -1 or 1, or 0
* if the BigDecimal is Not a Number.
*
* The second value is a string representing the significant digits of the
* BigDecimal, with no leading zeros.
*
* The third value is the base used for arithmetic (currently always 10) as an
* Integer.
*
* The fourth value is an Integer exponent.
*
* If the BigDecimal can be represented as 0.xxxxxx*10**n, then xxxxxx is the
* string of significant digits with no leading zeros, and n is the exponent.
*
* From these values, you can translate a BigDecimal to a float as follows:
*
* sign, significant_digits, base, exponent = a.split
* f = sign * "0.#{significant_digits}".to_f * (base ** exponent)
*
* (Note that the to_f method is provided as a more convenient way to translate
* a BigDecimal to a Float.)
*/
static VALUE
BigDecimal_split(VALUE self)
{
@ -1125,6 +1599,11 @@ BigDecimal_split(VALUE self)
return obj;
}
/* Returns the exponent of the BigDecimal number, as an Integer.
*
* If the number can be represented as 0.xxxxxx*10**n where xxxxxx is a string
* of digits with no leading zeros, then n is the exponent.
*/
static VALUE
BigDecimal_exponent(VALUE self)
{
@ -1132,6 +1611,16 @@ BigDecimal_exponent(VALUE self)
return INT2NUM(e);
}
/* Returns debugging information about the value as a string of comma-separated
* values in angle brackets with a leading #:
*
* BigDecimal.new("1234.5678").inspect ->
* "#<BigDecimal:b7ea1130,'0.12345678E4',8(12)>"
*
* The first part is the address, the second is the value as a string, and
* the final part ss(mm) is the current number of significant digits and the
* maximum number of significant digits, respectively.
*/
static VALUE
BigDecimal_inspect(VALUE self)
{
@ -1154,6 +1643,13 @@ BigDecimal_inspect(VALUE self)
return obj;
}
/* call-seq:
* power(n)
*
* Returns the value raised to the power of n. Note that n must be an Integer.
*
* Also available as the operator **
*/
static VALUE
BigDecimal_power(VALUE self, VALUE p)
{
@ -1197,6 +1693,18 @@ BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
return ToValue(pv);
}
/* call-seq:
* new(initial, digits)
*
* Create a new BigDecimal object.
*
* initial:: The initial value, as a String. Spaces are ignored, unrecognized characters terminate the value.
*
* digits:: The number of significant digits, as a Fixnum. If omitted or 0, the number of significant digits is determined from the initial value.
*
* The actual number of significant digits used in computation is usually
* larger than the specified number.
*/
static VALUE
BigDecimal_new(int argc, VALUE *argv, VALUE self)
{
@ -1216,6 +1724,18 @@ BigDecimal_new(int argc, VALUE *argv, VALUE self)
return ToValue(pv);
}
/* call-seq:
* BigDecimal.limit(digits)
*
* Limit the number of significant digits in newly created BigDecimal
* numbers to the specified value. Rounding is performed as necessary,
* as specified by BigDecimal.mode.
*
* A limit of 0, the default, means no upper limit.
*
* The limit specified by this method takes priority over any limit
* specified to instance methods such as ceil, floor, truncate, or round.
*/
static VALUE
BigDecimal_limit(int argc, VALUE *argv, VALUE self)
{
@ -1235,6 +1755,22 @@ BigDecimal_limit(int argc, VALUE *argv, VALUE self)
return nCur;
}
/* Returns the sign of the value.
*
* Returns a positive value if > 0, a negative value if < 0, and a
* zero if == 0.
*
* The specific value returned indicates the type and sign of the BigDecimal,
* as follows:
*
* BigDecimal::SIGN_NaN:: value is Not a Number
* BigDecimal::SIGN_POSITIVE_ZERO:: value is +0
* BigDecimal::SIGN_NEGATIVE_ZERO:: value is -0
* BigDecimal::SIGN_POSITIVE_INFINITE:: value is +infinity
* BigDecimal::SIGN_NEGATIVE_INFINITE:: value is -infinity
* BigDecimal::SIGN_POSITIVE_FINITE:: value is positive
* BigDecimal::SIGN_NEGATIVE_FINITE:: value is negative
*/
static VALUE
BigDecimal_sign(VALUE self)
{ /* sign */
@ -1264,37 +1800,94 @@ Init_bigdecimal(void)
rb_define_singleton_method(rb_cBigDecimal, "ver", BigDecimal_version, 0);
/* Constants definition */
/*
* Base value used in internal calculations. On a 32 bit system, BASE
* is 10000, indicating that calculation is done in groups of 4 digits.
* (If it were larger, BASE**2 wouldn't fit in 32 bits, so you couldn't
* guarantee that two groups could always be multiplied together without
* overflow.)
*/
rb_define_const(rb_cBigDecimal, "BASE", INT2FIX((S_INT)VpBaseVal()));
/* Exceptions */
/*
* Determines whether overflow, underflow or zero divide result in
* an exception being thrown. See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_ALL",INT2FIX(VP_EXCEPTION_ALL));
/*
* Determines what happens when the result of a computation is not a
* number (NaN). See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_NaN",INT2FIX(VP_EXCEPTION_NaN));
/*
* Determines what happens when the result of a computation is infinity.
* See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_INFINITY",INT2FIX(VP_EXCEPTION_INFINITY));
/*
* Determines what happens when the result of a computation is an underflow
* (a result too small to be represented). See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_UNDERFLOW",INT2FIX(VP_EXCEPTION_UNDERFLOW));
/*
* Determines what happens when the result of a computation is an underflow
* (a result too large to be represented). See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW",INT2FIX(VP_EXCEPTION_OVERFLOW));
/*
* Determines what happens when a division by zero is performed.
* See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE",INT2FIX(VP_EXCEPTION_ZERODIVIDE));
/* Computation mode */
/*
* Determines what happens when a result must be rounded in order to
* fit in the appropriate number of significant digits. See
* BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "ROUND_MODE",INT2FIX(VP_ROUND_MODE));
/* Indicates that values should be rounded away from zero. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_UP",INT2FIX(VP_ROUND_UP));
/* Indicates that values should be rounded towards zero. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_DOWN",INT2FIX(VP_ROUND_DOWN));
/* Indicates that digits >= 5 should be rounded up, others rounded down. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_HALF_UP",INT2FIX(VP_ROUND_HALF_UP));
/* Indicates that digits >= 6 should be rounded up, others rounded down. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_HALF_DOWN",INT2FIX(VP_ROUND_HALF_DOWN));
/* Round towards +infinity. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_CEILING",INT2FIX(VP_ROUND_CEIL));
/* Round towards -infinity. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_FLOOR",INT2FIX(VP_ROUND_FLOOR));
/* Round towards the even neighbor. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_HALF_EVEN",INT2FIX(VP_ROUND_HALF_EVEN));
/* Constants for sign value */
/* Indicates that a value is not a number. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NaN",INT2FIX(VP_SIGN_NaN));
/* Indicates that a value is +0. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_ZERO",INT2FIX(VP_SIGN_POSITIVE_ZERO));
/* Indicates that a value is -0. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_ZERO",INT2FIX(VP_SIGN_NEGATIVE_ZERO));
/* Indicates that a value is positive and finite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_FINITE",INT2FIX(VP_SIGN_POSITIVE_FINITE));
/* Indicates that a value is negative and finite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_FINITE",INT2FIX(VP_SIGN_NEGATIVE_FINITE));
/* Indicates that a value is positive and infinite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_INFINITE",INT2FIX(VP_SIGN_POSITIVE_INFINITE));
/* Indicates that a value is negative and infinite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE",INT2FIX(VP_SIGN_NEGATIVE_INFINITE));
/* instance methods */
rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
rb_define_method(rb_cBigDecimal, "sub", BigDecimal_sub2, 2);
rb_define_method(rb_cBigDecimal, "mult", BigDecimal_mult2, 2);

View file

@ -1,9 +1,27 @@
#
# jacobian.rb
# require 'bigdecimal/jacobian'
#
# Computes Jacobian matrix of f at x
# Provides methods to compute the Jacobian matrix of a set of equations at a
# point x. In the methods below:
#
# f is an Object which is used to compute the Jacobian matrix of the equations.
# It must provide the following methods:
#
# f.values(x):: returns the values of all functions at x
#
# f.zero:: returns 0.0
# f.one:: returns 1.0
# f.two:: returns 1.0
# f.ten:: returns 10.0
#
# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal.
#
# x is the point at which to compute the Jacobian.
#
# fx is f.values(x).
#
module Jacobian
#--
def isEqual(a,b,zero=0.0,e=1.0e-8)
aa = a.abs
bb = b.abs
@ -17,7 +35,10 @@ module Jacobian
end
end
end
#++
# Computes the derivative of f[i] at x[i].
# fx is the value of f at x.
def dfdxi(f,fx,x,i)
nRetry = 0
n = x.size
@ -49,6 +70,7 @@ module Jacobian
deriv
end
# Computes the Jacobian of f at x. fx is the value of f at x.
def jacobian(f,fx,x)
n = x.size
dfdx = Array::new(n*n)

View file

@ -1,7 +1,8 @@
#
# ludcmp.rb
# Solves a*x = b for x, using LU decomposition.
#
module LUSolve
# Performs LU decomposition of the n by n matrix a.
def ludecomp(a,n,zero=0,one=1)
prec = BigDecimal.limit(nil)
ps = []
@ -52,6 +53,12 @@ module LUSolve
ps
end
# Solves a*x = b for x, using LU decomposition.
#
# a is a matrix, b is a constant vector, x is the solution vector.
#
# ps is the pivot, a vector which indicates the permutation of rows performed
# during LU decomposition.
def lusolve(a,b,ps,zero=0.0)
prec = BigDecimal.limit(nil)
n = ps.size

View file

@ -1,4 +1,5 @@
#
#--
# Contents:
# sqrt(x, prec)
# sin (x, prec)
@ -13,19 +14,35 @@
# x ... BigDecimal number to be computed.
# |x| must be small enough to get convergence.
# prec ... Number of digits to be obtained.
#++
#
# Provides mathematical functions.
#
# Example:
#
# Usage:
# require "bigdecimal"
# require "bigdecimal/math.rb"
# require "bigdecimal/math"
#
# include BigMath
#
# a = BigDecimal((PI(100)/2).to_s)
# puts sin(a,100) # => 0.10000000000000000000......E1
# puts sin(a,100) # -> 0.10000000000000000000......E1
#
module BigMath
# Computes the square root of x to the specified number of digits of
# precision.
#
# BigDecimal.new('2').sqrt(16).to_s
# -> "0.14142135623730950488016887242096975E1"
#
def sqrt(x,prec)
x.sqrt(prec)
end
# Computes the sine of x to the specified number of digits of precision.
#
# If x is infinite or NaN, returns NaN.
def sin(x, prec)
raise ArgumentError, "Zero or negative precision for sin" if prec <= 0
return BigDecimal("NaN") if x.infinite? || x.nan?
@ -51,6 +68,9 @@ module BigMath
y
end
# Computes the cosine of x to the specified number of digits of precision.
#
# If x is infinite or NaN, returns NaN.
def cos(x, prec)
raise ArgumentError, "Zero or negative precision for cos" if prec <= 0
return BigDecimal("NaN") if x.infinite? || x.nan?
@ -76,6 +96,10 @@ module BigMath
y
end
# Computes the arctangent of x to the specified number of digits of precision.
#
# If x is infinite or NaN, returns NaN.
# Raises an argument error if x > 1.
def atan(x, prec)
raise ArgumentError, "Zero or negative precision for atan" if prec <= 0
return BigDecimal("NaN") if x.infinite? || x.nan?
@ -96,6 +120,13 @@ module BigMath
y
end
# Computes the value of e (the base of natural logarithms) raised to the
# power of x, to the specified number of digits of precision.
#
# If x is infinite or NaN, returns NaN.
#
# BigMath::exp(BigDecimal.new('1'), 10).to_s
# -> "0.271828182845904523536028752390026306410273E1"
def exp(x, prec)
raise ArgumentError, "Zero or negative precision for exp" if prec <= 0
return BigDecimal("NaN") if x.infinite? || x.nan?
@ -117,6 +148,11 @@ module BigMath
y
end
# Computes the natural logarithm of x to the specified number of digits
# of precision.
#
# Returns x if x is infinite or NaN.
#
def log(x, prec)
raise ArgumentError, "Zero or negative argument for log" if x <= 0 || prec <= 0
return x if x.infinite? || x.nan?
@ -138,6 +174,7 @@ module BigMath
y*two
end
# Computes the value of pi to the specified number of digits of precision.
def PI(prec)
raise ArgumentError, "Zero or negative argument for PI" if prec <= 0
n = prec + BigDecimal.double_fig
@ -176,6 +213,8 @@ module BigMath
pi
end
# Computes e (the base of natural logarithms) to the specified number of
# digits of precision.
def E(prec)
raise ArgumentError, "Zero or negative precision for E" if prec <= 0
n = prec + BigDecimal.double_fig

View file

@ -1,24 +1,26 @@
#
# newton.rb
#
# Solves nonlinear algebraic equation system f = 0 by Newton's method.
# (This program is not dependent on BigDecimal)
# Solves the nonlinear algebraic equation system f = 0 by Newton's method.
# This program is not dependent on BigDecimal.
#
# To call:
# n = nlsolve(f,x)
# where n is the number of iterations required.
# x is the solution vector.
# f is the object to be solved which must have following methods.
# where n is the number of iterations required,
# x is the initial value vector
# f is an Object which is used to compute the values of the equations to be solved.
# It must provide the following methods:
#
# f ... Object to compute Jacobian matrix of the equation systems.
# [Methods required for f]
# f.values(x) returns values of all functions at x.
# f.zero returns 0.0
# f.one returns 1.0
# f.two returns 1.0
# f.ten returns 10.0
# f.eps convergence criterion
# x ... initial values
# f.values(x):: returns the values of all functions at x
#
# f.zero:: returns 0.0
# f.one:: returns 1.0
# f.two:: returns 1.0
# f.ten:: returns 10.0
#
# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal.
#
# On exit, x is the solution vector.
#
require "bigdecimal/ludcmp"
require "bigdecimal/jacobian"

View file

@ -1,19 +1,17 @@
#
# BigDecimal utility library.
# ----------------------------------------------------------------------
# Contents:
#
# String#
# to_d ... to BigDecimal
# To use these functions, require 'bigdecimal/util'
#
# Float#
# to_d ... to BigDecimal
# The following methods are provided to convert other types to BigDecimals:
#
# BigDecimal#
# to_r ... to Rational
# String#to_d -> BigDecimal
# Float#to_d -> BigDecimal
# Rational#to_d -> BigDecimal
#
# Rational#
# to_d ... to BigDecimal
# The following method is provided to convert BigDecimals to other types:
#
# BigDecimal#to_r -> Rational
#
# ----------------------------------------------------------------------
#
@ -30,8 +28,8 @@ class String
end
class BigDecimal < Numeric
# to "nnnnnn.mmm" form digit string
# Use BigDecimal#to_s("F") instead.
# Converts a BigDecimal to a String of the form "nnnnnn.mmm".
# This method is deprecated; use BigDecimal#to_s("F") instead.
def to_digits
if self.nan? || self.infinite? || self.zero?
self.to_s
@ -42,7 +40,7 @@ class BigDecimal < Numeric
end
end
# Convert BigDecimal to Rational
# Converts a BigDecimal to a Rational.
def to_r
sign,digits,base,power = self.split
numerator = sign*digits.to_i
@ -57,7 +55,7 @@ class BigDecimal < Numeric
end
class Rational < Numeric
# Convert Rational to BigDecimal
# Converts a Rational to a BigDecimal
def to_d(nFig=0)
num = self.numerator.to_s
if nFig<=0