From 60bf66e0cd2c9f519f7dfb27eca134b86ea5dd8b Mon Sep 17 00:00:00 2001 From: matz Date: Thu, 29 Jun 2006 09:09:33 +0000 Subject: * ext/bigdecimal/bigdecimal.c: add RDoc document. a patch from mathew . [ruby-core:07050] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10428 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/bigdecimal/bigdecimal.c | 601 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 597 insertions(+), 4 deletions(-) (limited to 'ext/bigdecimal/bigdecimal.c') 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 . + * 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 . + * + * = 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 -> + * "#" + * + * 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); -- cgit v1.2.3