summaryrefslogtreecommitdiff
path: root/ext/bigdecimal
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2006-06-29 09:09:33 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2006-06-29 09:09:33 +0000
commit60bf66e0cd2c9f519f7dfb27eca134b86ea5dd8b (patch)
treedcc53a834964d3813864acd28a1cecd6777d74d2 /ext/bigdecimal
parent0c11152794d4f07970a5c36981e95eb176d5fdc8 (diff)
* 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
Diffstat (limited to 'ext/bigdecimal')
-rw-r--r--ext/bigdecimal/bigdecimal.c601
-rw-r--r--ext/bigdecimal/lib/bigdecimal/jacobian.rb26
-rw-r--r--ext/bigdecimal/lib/bigdecimal/ludcmp.rb9
-rw-r--r--ext/bigdecimal/lib/bigdecimal/math.rb45
-rw-r--r--ext/bigdecimal/lib/bigdecimal/newton.rb30
-rw-r--r--ext/bigdecimal/lib/bigdecimal/util.rb26
6 files changed, 699 insertions, 38 deletions
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 97a9c63e72..bb2f05b350 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -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);
diff --git a/ext/bigdecimal/lib/bigdecimal/jacobian.rb b/ext/bigdecimal/lib/bigdecimal/jacobian.rb
index 34a60ae67a..d80eeab901 100644
--- a/ext/bigdecimal/lib/bigdecimal/jacobian.rb
+++ b/ext/bigdecimal/lib/bigdecimal/jacobian.rb
@@ -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)
diff --git a/ext/bigdecimal/lib/bigdecimal/ludcmp.rb b/ext/bigdecimal/lib/bigdecimal/ludcmp.rb
index 1d5d3170cc..8f4888725e 100644
--- a/ext/bigdecimal/lib/bigdecimal/ludcmp.rb
+++ b/ext/bigdecimal/lib/bigdecimal/ludcmp.rb
@@ -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
diff --git a/ext/bigdecimal/lib/bigdecimal/math.rb b/ext/bigdecimal/lib/bigdecimal/math.rb
index 7b3f46ed1a..f3248a3c5c 100644
--- a/ext/bigdecimal/lib/bigdecimal/math.rb
+++ b/ext/bigdecimal/lib/bigdecimal/math.rb
@@ -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
diff --git a/ext/bigdecimal/lib/bigdecimal/newton.rb b/ext/bigdecimal/lib/bigdecimal/newton.rb
index f1a55da789..59ac0f7f04 100644
--- a/ext/bigdecimal/lib/bigdecimal/newton.rb
+++ b/ext/bigdecimal/lib/bigdecimal/newton.rb
@@ -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"
diff --git a/ext/bigdecimal/lib/bigdecimal/util.rb b/ext/bigdecimal/lib/bigdecimal/util.rb
index 1f8d6c7a49..2c17aa6b8e 100644
--- a/ext/bigdecimal/lib/bigdecimal/util.rb
+++ b/ext/bigdecimal/lib/bigdecimal/util.rb
@@ -1,19 +1,17 @@
#
# BigDecimal utility library.
-# ----------------------------------------------------------------------
-# Contents:
#
-# String#
-# to_d ... to BigDecimal
+# To use these functions, require 'bigdecimal/util'
+#
+# The following methods are provided to convert other types to BigDecimals:
#
-# Float#
-# to_d ... to BigDecimal
+# String#to_d -> BigDecimal
+# Float#to_d -> BigDecimal
+# Rational#to_d -> BigDecimal
#
-# BigDecimal#
-# to_r ... to Rational
+# The following method is provided to convert BigDecimals to other types:
#
-# Rational#
-# to_d ... to BigDecimal
+# 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