diff --git a/.gitignore b/.gitignore index 7a53e6ec2a..acdf76c27b 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,4 @@ tests/*.trs cscope.in.out cscope.out cscope.po.out +jq.dSYM diff --git a/COPYING b/COPYING index 7222ff0be7..3e1dd1fa6c 100644 --- a/COPYING +++ b/COPYING @@ -68,3 +68,41 @@ WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + + +jq uses parts of the open source C library "decNumber", which is distribured +under the following license: + + +ICU License - ICU 1.8.1 and later + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1995-2005 International Business Machines Corporation and others +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, provided that the above +copyright notice(s) and this permission notice appear in all copies of +the Software and that both the above copyright notice(s) and this +permission notice appear in supporting documentation. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL +INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING +FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + diff --git a/Makefile.am b/Makefile.am index dcdb0be543..97701363cc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,6 +11,8 @@ LIBJQ_SRC = src/builtin.c src/bytecode.c src/compile.c src/execute.c \ src/jq_test.c src/jv.c src/jv_alloc.c src/jv_aux.c \ src/jv_dtoa.c src/jv_file.c src/jv_parse.c src/jv_print.c \ src/jv_unicode.c src/linker.c src/locfile.c src/util.c \ + src/decNumber/decContext.c src/decNumber/decNumber.c \ + src/jv_dtoa_tsd.c \ ${LIBJQ_INCS} ### C build options @@ -186,9 +188,13 @@ EXTRA_DIST = $(DOC_FILES) $(man_MANS) $(TESTS) $(TEST_LOG_COMPILER) \ tests/modules/test_bind_order.jq \ tests/modules/test_bind_order0.jq \ tests/modules/test_bind_order1.jq \ - tests/modules/test_bind_order2.jq tests/onig.supp \ - tests/onig.test tests/optional.test tests/setup \ - tests/torture/input0.json tests/utf8-truncate.jq + tests/modules/test_bind_order2.jq \ + tests/onig.supp tests/local.supp \ + tests/onig.test tests/setup tests/torture/input0.json \ + tests/optional.test tests/optionaltest \ + tests/utf8-truncate.jq tests/utf8test \ + tests/base64.test tests/base64test \ + tests/jq-f-test.sh tests/shtest # README.md is expected in Github projects, good stuff in it, so we'll # distribute it and install it with the package in the doc directory. diff --git a/configure.ac b/configure.ac index 4710269730..7d2355b2ab 100644 --- a/configure.ac +++ b/configure.ac @@ -110,6 +110,14 @@ EOF fi ]) +dnl Disable decNumber support +AC_ARG_ENABLE([decnum], + AC_HELP_STRING([--disable-decnum], [disable decnum support])) + +AS_IF([test "x$enable_decnum" != "xno"],[ + AC_DEFINE([USE_DECNUM],1) +]) + AM_CONDITIONAL([ENABLE_VALGRIND], [test "x$enable_valgrind" != xno]) AM_CONDITIONAL([ENABLE_ASAN], [test "x$enable_asan" = xyes]) AM_CONDITIONAL([ENABLE_UBSAN], [test "x$enable_ubsan" = xyes]) @@ -136,17 +144,9 @@ AC_CHECK_MEMBER([struct tm.tm_gmtoff], [AC_DEFINE([HAVE_TM_TM_GMT_OFF],1,[Define AC_CHECK_MEMBER([struct tm.__tm_gmtoff], [AC_DEFINE([HAVE_TM___TM_GMT_OFF],1,[Define to 1 if the system has the __tm_gmt_off field in struct tm])], [], [[#include ]]) -AC_ARG_ENABLE([pthread-tls], - [AC_HELP_STRING([--enable-pthread-tls], - [Enable use of pthread thread local storage])], - [], - [enable_pthread_tls=no]) - -if test $enable_pthread_tls = yes; then - AC_FIND_FUNC([pthread_key_create], [pthread], [#include ], [NULL, NULL]) - AC_FIND_FUNC([pthread_once], [pthread], [#include ], [NULL, NULL]) - AC_FIND_FUNC([atexit], [pthread], [#include ], [NULL]) -fi +AC_FIND_FUNC([pthread_key_create], [pthread], [#include ], [NULL, NULL]) +AC_FIND_FUNC([pthread_once], [pthread], [#include ], [NULL, NULL]) +AC_FIND_FUNC([atexit], [pthread], [#include ], [NULL]) dnl libm math.h functions AC_CHECK_MATH_FUNC(acos) diff --git a/docs/content/download/default.yml b/docs/content/download/default.yml index cfea1f092f..261b15ed3c 100644 --- a/docs/content/download/default.yml +++ b/docs/content/download/default.yml @@ -13,6 +13,10 @@ body: jq is licensed under the MIT license. For all of the gory details, read the file `COPYING` in the source distribution. + jq uses a C library for decimal number support. This is an ICU 1.8.1 + licensed code obtained from the ICU downloads archive + http://download.icu-project.org/files/decNumber/decNumber-icu-368.zip. + ### Linux diff --git a/docs/content/manual/v1.6/manual.yml b/docs/content/manual/v1.6/manual.yml index 554d5802dc..fe2b11af67 100644 --- a/docs/content/manual/v1.6/manual.yml +++ b/docs/content/manual/v1.6/manual.yml @@ -292,11 +292,37 @@ sections: program can be a useful way of formatting JSON output from, say, `curl`. + An important point about the identity filter is that it + guarantees to preserve the literal decimal representation + of values. This is particularly important when dealing with numbers + which can't be losslessly converted to an IEEE754 double precision + representation. + + jq doesn't truncate the literal numbers to double unless there + is a need to make arithmetic operations with the number. + Comparisions are carried out over the untruncated big decimal + representation of the number. + + jq will also try to maintain the original decimal precision of the provided + number literal. See below for examples. + examples: - program: '.' input: '"Hello, world!"' output: ['"Hello, world!"'] + - program: '. | tojson' + input: '12345678909876543212345' + output: ['"12345678909876543212345"'] + + - program: 'map([., . == 1]) | tojson' + input: '[1, 1.000, 1.0, 100e-2]' + output: ['"[[1,true],[1.000,true],[1.0,true],[1.00,true]]"'] + + - program: '. as $big | [$big, $big + 1] | map(. > 10000000000000000000000000000000)' + input: '10000000000000000000000000000001' + output: ['[true, false]'] + - title: "Object Identifier-Index: `.foo`, `.foo.bar`" body: | @@ -511,6 +537,16 @@ sections: expression that takes an input, ignores it, and returns 42 instead. + Numbers in jq are internally represented by their IEEE754 double + precision approximation. Any arithmetic operation with numbers, + whether they are literals or results of previous filters, will + produce a double precision floating point result. + + However, when parsing a literal jq will store the original literal + string. If no mutation is applied to this value then it will make + to the output in its original form, even if conversion to double + would result in a loss. + entries: - title: "Array construction: `[]`" body: | @@ -629,6 +665,18 @@ sections: try to add a string to an object you'll get an error message and no result. + Please note that all numbers are converted to IEEE754 double precision + floating point representation. Arithmetic and logical operators are working + with these converted doubles. Results of all such operations are also limited + to the double precision. + + The only exception to this behaviour of number is a snapshot of original number + literal. When a number which originally was provided as a literal is never + mutated until the end of the program then it is printed to the output in its + original literal form. This also includes cases when the original literal + would be truncated when converted to the IEEE754 double precision floating point + number. + entries: - title: "Addition: `+`" body: | diff --git a/src/builtin.c b/src/builtin.c index f52f56e208..b67f9c8d0e 100644 --- a/src/builtin.c +++ b/src/builtin.c @@ -90,8 +90,11 @@ static jv f_plus(jq_state *jq, jv input, jv a, jv b) { jv_free(b); return a; } else if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) { - return jv_number(jv_number_value(a) + + jv r = jv_number(jv_number_value(a) + jv_number_value(b)); + jv_free(a); + jv_free(b); + return r; } else if (jv_get_kind(a) == JV_KIND_STRING && jv_get_kind(b) == JV_KIND_STRING) { return jv_string_concat(a, b); } else if (jv_get_kind(a) == JV_KIND_ARRAY && jv_get_kind(b) == JV_KIND_ARRAY) { @@ -274,7 +277,10 @@ static jv f_rtrimstr(jq_state *jq, jv input, jv right) { static jv f_minus(jq_state *jq, jv input, jv a, jv b) { jv_free(input); if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) { - return jv_number(jv_number_value(a) - jv_number_value(b)); + jv r = jv_number(jv_number_value(a) - jv_number_value(b)); + jv_free(a); + jv_free(b); + return r; } else if (jv_get_kind(a) == JV_KIND_ARRAY && jv_get_kind(b) == JV_KIND_ARRAY) { jv out = jv_array(); jv_array_foreach(a, i, x) { @@ -302,7 +308,10 @@ static jv f_multiply(jq_state *jq, jv input, jv a, jv b) { jv_kind bk = jv_get_kind(b); jv_free(input); if (ak == JV_KIND_NUMBER && bk == JV_KIND_NUMBER) { - return jv_number(jv_number_value(a) * jv_number_value(b)); + jv r = jv_number(jv_number_value(a) * jv_number_value(b)); + jv_free(a); + jv_free(b); + return r; } else if ((ak == JV_KIND_STRING && bk == JV_KIND_NUMBER) || (ak == JV_KIND_NUMBER && bk == JV_KIND_STRING)) { jv str = a; @@ -336,7 +345,10 @@ static jv f_divide(jq_state *jq, jv input, jv a, jv b) { if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) { if (jv_number_value(b) == 0.0) return type_error2(a, b, "cannot be divided because the divisor is zero"); - return jv_number(jv_number_value(a) / jv_number_value(b)); + jv r = jv_number(jv_number_value(a) / jv_number_value(b)); + jv_free(a); + jv_free(b); + return r; } else if (jv_get_kind(a) == JV_KIND_STRING && jv_get_kind(b) == JV_KIND_STRING) { return jv_string_split(a, b); } else { @@ -349,7 +361,10 @@ static jv f_mod(jq_state *jq, jv input, jv a, jv b) { if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) { if ((intmax_t)jv_number_value(b) == 0) return type_error2(a, b, "cannot be divided (remainder) because the divisor is zero"); - return jv_number((intmax_t)jv_number_value(a) % (intmax_t)jv_number_value(b)); + jv r = jv_number((intmax_t)jv_number_value(a) % (intmax_t)jv_number_value(b)); + jv_free(a); + jv_free(b); + return r; } else { return type_error2(a, b, "cannot be divided (remainder)"); } @@ -440,7 +455,9 @@ static jv f_length(jq_state *jq, jv input) { } else if (jv_get_kind(input) == JV_KIND_STRING) { return jv_number(jv_string_length_codepoints(input)); } else if (jv_get_kind(input) == JV_KIND_NUMBER) { - return jv_number(fabs(jv_number_value(input))); + jv r = jv_number(fabs(jv_number_value(input))); + jv_free(input); + return r; } else if (jv_get_kind(input) == JV_KIND_NULL) { jv_free(input); return jv_number(0); diff --git a/src/decNumber/ICU-license.html b/src/decNumber/ICU-license.html new file mode 100644 index 0000000000..bc99e8bfcc --- /dev/null +++ b/src/decNumber/ICU-license.html @@ -0,0 +1,45 @@ + + + + +ICU License - ICU 1.8.1 and later + + + +

ICU License - ICU 1.8.1 and later

+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 1995-2005 International Business Machines Corporation and others
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+--------------------------------------------------------------------------------
+All trademarks and registered trademarks mentioned herein are the property of their respective owners.
+
+ + diff --git a/src/decNumber/decBasic.c b/src/decNumber/decBasic.c new file mode 100644 index 0000000000..1f680c4a2c --- /dev/null +++ b/src/decNumber/decBasic.c @@ -0,0 +1,3908 @@ +/* ------------------------------------------------------------------ */ +/* decBasic.c -- common base code for Basic decimal types */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is included in the package as decNumber.pdf. This */ +/* document is also available in HTML, together with specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ +/* This module comprises code that is shared between decDouble and */ +/* decQuad (but not decSingle). The main arithmetic operations are */ +/* here (Add, Subtract, Multiply, FMA, and Division operators). */ +/* */ +/* Unlike decNumber, parameterization takes place at compile time */ +/* rather than at runtime. The parameters are set in the decDouble.c */ +/* (etc.) files, which then include this one to produce the compiled */ +/* code. The functions here, therefore, are code shared between */ +/* multiple formats. */ +/* */ +/* This must be included after decCommon.c. */ +/* ------------------------------------------------------------------ */ +// Names here refer to decFloat rather than to decDouble, etc., and +// the functions are in strict alphabetical order. + +// The compile-time flags SINGLE, DOUBLE, and QUAD are set up in +// decCommon.c +#if !defined(QUAD) + #error decBasic.c must be included after decCommon.c +#endif +#if SINGLE + #error Routines in decBasic.c are for decDouble and decQuad only +#endif + +/* Private constants */ +#define DIVIDE 0x80000000 // Divide operations [as flags] +#define REMAINDER 0x40000000 // .. +#define DIVIDEINT 0x20000000 // .. +#define REMNEAR 0x10000000 // .. + +/* Private functions (local, used only by routines in this module) */ +static decFloat *decDivide(decFloat *, const decFloat *, + const decFloat *, decContext *, uInt); +static decFloat *decCanonical(decFloat *, const decFloat *); +static void decFiniteMultiply(bcdnum *, uByte *, const decFloat *, + const decFloat *); +static decFloat *decInfinity(decFloat *, const decFloat *); +static decFloat *decInvalid(decFloat *, decContext *); +static decFloat *decNaNs(decFloat *, const decFloat *, const decFloat *, + decContext *); +static Int decNumCompare(const decFloat *, const decFloat *, Flag); +static decFloat *decToIntegral(decFloat *, const decFloat *, decContext *, + enum rounding, Flag); +static uInt decToInt32(const decFloat *, decContext *, enum rounding, + Flag, Flag); + +/* ------------------------------------------------------------------ */ +/* decCanonical -- copy a decFloat, making canonical */ +/* */ +/* result gets the canonicalized df */ +/* df is the decFloat to copy and make canonical */ +/* returns result */ +/* */ +/* This is exposed via decFloatCanonical for Double and Quad only. */ +/* This works on specials, too; no error or exception is possible. */ +/* ------------------------------------------------------------------ */ +static decFloat * decCanonical(decFloat *result, const decFloat *df) { + uInt encode, precode, dpd; // work + uInt inword, uoff, canon; // .. + Int n; // counter (down) + if (df!=result) *result=*df; // effect copy if needed + if (DFISSPECIAL(result)) { + if (DFISINF(result)) return decInfinity(result, df); // clean Infinity + // is a NaN + DFWORD(result, 0)&=~ECONNANMASK; // clear ECON except selector + if (DFISCCZERO(df)) return result; // coefficient continuation is 0 + // drop through to check payload + } + // return quickly if the coefficient continuation is canonical + { // declare block + #if DOUBLE + uInt sourhi=DFWORD(df, 0); + uInt sourlo=DFWORD(df, 1); + if (CANONDPDOFF(sourhi, 8) + && CANONDPDTWO(sourhi, sourlo, 30) + && CANONDPDOFF(sourlo, 20) + && CANONDPDOFF(sourlo, 10) + && CANONDPDOFF(sourlo, 0)) return result; + #elif QUAD + uInt sourhi=DFWORD(df, 0); + uInt sourmh=DFWORD(df, 1); + uInt sourml=DFWORD(df, 2); + uInt sourlo=DFWORD(df, 3); + if (CANONDPDOFF(sourhi, 4) + && CANONDPDTWO(sourhi, sourmh, 26) + && CANONDPDOFF(sourmh, 16) + && CANONDPDOFF(sourmh, 6) + && CANONDPDTWO(sourmh, sourml, 28) + && CANONDPDOFF(sourml, 18) + && CANONDPDOFF(sourml, 8) + && CANONDPDTWO(sourml, sourlo, 30) + && CANONDPDOFF(sourlo, 20) + && CANONDPDOFF(sourlo, 10) + && CANONDPDOFF(sourlo, 0)) return result; + #endif + } // block + + // Loop to repair a non-canonical coefficent, as needed + inword=DECWORDS-1; // current input word + uoff=0; // bit offset of declet + encode=DFWORD(result, inword); + for (n=DECLETS-1; n>=0; n--) { // count down declets of 10 bits + dpd=encode>>uoff; + uoff+=10; + if (uoff>32) { // crossed uInt boundary + inword--; + encode=DFWORD(result, inword); + uoff-=32; + dpd|=encode<<(10-uoff); // get pending bits + } + dpd&=0x3ff; // clear uninteresting bits + if (dpd<0x16e) continue; // must be canonical + canon=BIN2DPD[DPD2BIN[dpd]]; // determine canonical declet + if (canon==dpd) continue; // have canonical declet + // need to replace declet + if (uoff>=10) { // all within current word + encode&=~(0x3ff<<(uoff-10)); // clear the 10 bits ready for replace + encode|=canon<<(uoff-10); // insert the canonical form + DFWORD(result, inword)=encode; // .. and save + continue; + } + // straddled words + precode=DFWORD(result, inword+1); // get previous + precode&=0xffffffff>>(10-uoff); // clear top bits + DFWORD(result, inword+1)=precode|(canon<<(32-(10-uoff))); + encode&=0xffffffff<>(10-uoff); // insert canonical + DFWORD(result, inword)=encode; // .. and save + } // n + return result; + } // decCanonical + +/* ------------------------------------------------------------------ */ +/* decDivide -- divide operations */ +/* */ +/* result gets the result of dividing dfl by dfr: */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* op is the operation selector */ +/* returns result */ +/* */ +/* op is one of DIVIDE, REMAINDER, DIVIDEINT, or REMNEAR. */ +/* ------------------------------------------------------------------ */ +#define DIVCOUNT 0 // 1 to instrument subtractions counter +#define DIVBASE ((uInt)BILLION) // the base used for divide +#define DIVOPLEN DECPMAX9 // operand length ('digits' base 10**9) +#define DIVACCLEN (DIVOPLEN*3) // accumulator length (ditto) +static decFloat * decDivide(decFloat *result, const decFloat *dfl, + const decFloat *dfr, decContext *set, uInt op) { + decFloat quotient; // for remainders + bcdnum num; // for final conversion + uInt acc[DIVACCLEN]; // coefficent in base-billion .. + uInt div[DIVOPLEN]; // divisor in base-billion .. + uInt quo[DIVOPLEN+1]; // quotient in base-billion .. + uByte bcdacc[(DIVOPLEN+1)*9+2]; // for quotient in BCD, +1, +1 + uInt *msua, *msud, *msuq; // -> msu of acc, div, and quo + Int divunits, accunits; // lengths + Int quodigits; // digits in quotient + uInt *lsua, *lsuq; // -> current acc and quo lsus + Int length, multiplier; // work + uInt carry, sign; // .. + uInt *ua, *ud, *uq; // .. + uByte *ub; // .. + uInt uiwork; // for macros + uInt divtop; // top unit of div adjusted for estimating + #if DIVCOUNT + static uInt maxcount=0; // worst-seen subtractions count + uInt divcount=0; // subtractions count [this divide] + #endif + + // calculate sign + num.sign=(DFWORD(dfl, 0)^DFWORD(dfr, 0)) & DECFLOAT_Sign; + + if (DFISSPECIAL(dfl) || DFISSPECIAL(dfr)) { // either is special? + // NaNs are handled as usual + if (DFISNAN(dfl) || DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set); + // one or two infinities + if (DFISINF(dfl)) { + if (DFISINF(dfr)) return decInvalid(result, set); // Two infinities bad + if (op&(REMAINDER|REMNEAR)) return decInvalid(result, set); // as is rem + // Infinity/x is infinite and quiet, even if x=0 + DFWORD(result, 0)=num.sign; + return decInfinity(result, result); + } + // must be x/Infinity -- remainders are lhs + if (op&(REMAINDER|REMNEAR)) return decCanonical(result, dfl); + // divides: return zero with correct sign and exponent depending + // on op (Etiny for divide, 0 for divideInt) + decFloatZero(result); + if (op==DIVIDEINT) DFWORD(result, 0)|=num.sign; // add sign + else DFWORD(result, 0)=num.sign; // zeros the exponent, too + return result; + } + // next, handle zero operands (x/0 and 0/x) + if (DFISZERO(dfr)) { // x/0 + if (DFISZERO(dfl)) { // 0/0 is undefined + decFloatZero(result); + DFWORD(result, 0)=DECFLOAT_qNaN; + set->status|=DEC_Division_undefined; + return result; + } + if (op&(REMAINDER|REMNEAR)) return decInvalid(result, set); // bad rem + set->status|=DEC_Division_by_zero; + DFWORD(result, 0)=num.sign; + return decInfinity(result, result); // x/0 -> signed Infinity + } + num.exponent=GETEXPUN(dfl)-GETEXPUN(dfr); // ideal exponent + if (DFISZERO(dfl)) { // 0/x (x!=0) + // if divide, result is 0 with ideal exponent; divideInt has + // exponent=0, remainders give zero with lower exponent + if (op&DIVIDEINT) { + decFloatZero(result); + DFWORD(result, 0)|=num.sign; // add sign + return result; + } + if (!(op&DIVIDE)) { // a remainder + // exponent is the minimum of the operands + num.exponent=MINI(GETEXPUN(dfl), GETEXPUN(dfr)); + // if the result is zero the sign shall be sign of dfl + num.sign=DFWORD(dfl, 0)&DECFLOAT_Sign; + } + bcdacc[0]=0; + num.msd=bcdacc; // -> 0 + num.lsd=bcdacc; // .. + return decFinalize(result, &num, set); // [divide may clamp exponent] + } // 0/x + // [here, both operands are known to be finite and non-zero] + + // extract the operand coefficents into 'units' which are + // base-billion; the lhs is high-aligned in acc and the msu of both + // acc and div is at the right-hand end of array (offset length-1); + // the quotient can need one more unit than the operands as digits + // in it are not necessarily aligned neatly; further, the quotient + // may not start accumulating until after the end of the initial + // operand in acc if that is small (e.g., 1) so the accumulator + // must have at least that number of units extra (at the ls end) + GETCOEFFBILL(dfl, acc+DIVACCLEN-DIVOPLEN); + GETCOEFFBILL(dfr, div); + // zero the low uInts of acc + acc[0]=0; + acc[1]=0; + acc[2]=0; + acc[3]=0; + #if DOUBLE + #if DIVOPLEN!=2 + #error Unexpected Double DIVOPLEN + #endif + #elif QUAD + acc[4]=0; + acc[5]=0; + acc[6]=0; + acc[7]=0; + #if DIVOPLEN!=4 + #error Unexpected Quad DIVOPLEN + #endif + #endif + + // set msu and lsu pointers + msua=acc+DIVACCLEN-1; // [leading zeros removed below] + msuq=quo+DIVOPLEN; + //[loop for div will terminate because operands are non-zero] + for (msud=div+DIVOPLEN-1; *msud==0;) msud--; + // the initial least-significant unit of acc is set so acc appears + // to have the same length as div. + // This moves one position towards the least possible for each + // iteration + divunits=(Int)(msud-div+1); // precalculate + lsua=msua-divunits+1; // initial working lsu of acc + lsuq=msuq; // and of quo + + // set up the estimator for the multiplier; this is the msu of div, + // plus two bits from the unit below (if any) rounded up by one if + // there are any non-zero bits or units below that [the extra two + // bits makes for a much better estimate when the top unit is small] + divtop=*msud<<2; + if (divunits>1) { + uInt *um=msud-1; + uInt d=*um; + if (d>=750000000) {divtop+=3; d-=750000000;} + else if (d>=500000000) {divtop+=2; d-=500000000;} + else if (d>=250000000) {divtop++; d-=250000000;} + if (d) divtop++; + else for (um--; um>=div; um--) if (*um) { + divtop++; + break; + } + } // >1 unit + + #if DECTRACE + {Int i; + printf("----- div="); + for (i=divunits-1; i>=0; i--) printf("%09ld ", (LI)div[i]); + printf("\n");} + #endif + + // now collect up to DECPMAX+1 digits in the quotient (this may + // need OPLEN+1 uInts if unaligned) + quodigits=0; // no digits yet + for (;; lsua--) { // outer loop -- each input position + #if DECCHECK + if (lsua=lsua;) msua--; + accunits=(Int)(msua-lsua+1); // [maybe 0] + // subtraction is only necessary and possible if there are as + // least as many units remaining in acc for this iteration as + // there are in div + if (accunitsdiv: subtraction necessary at this position + for (ud=msud, ua=msua; ud>div; ud--, ua--) if (*ud!=*ua) break; + // [now at first mismatch or lsu] + if (*ud>*ua) break; // next time... + if (*ud==*ua) { // all compared equal + *lsuq+=1; // increment result + msua=lsua; // collapse acc units + *msua=0; // .. to a zero + break; + } + + // subtraction necessary; estimate multiplier [see above] + // if both *msud and *msua are small it is cost-effective to + // bring in part of the following units (if any) to get a + // better estimate (assume some other non-zero in div) + #define DIVLO 1000000U + #define DIVHI (DIVBASE/DIVLO) + #if DECUSE64 + if (divunits>1) { + // there cannot be a *(msud-2) for DECDOUBLE so next is + // an exact calculation unless DECQUAD (which needs to + // assume bits out there if divunits>2) + uLong mul=(uLong)*msua * DIVBASE + *(msua-1); + uLong div=(uLong)*msud * DIVBASE + *(msud-1); + #if QUAD + if (divunits>2) div++; + #endif + mul/=div; + multiplier=(Int)mul; + } + else multiplier=*msua/(*msud); + #else + if (divunits>1 && *msuadivunits + // msud is one unit 'lower' than msua, so estimate differently + #if DECUSE64 + uLong mul; + // as before, bring in extra digits if possible + if (divunits>1 && *msua>DIVSHIFTA); + carry=(uInt)(((uLong)hop*DIVMAGIC)>>DIVSHIFTB); + // the estimate is now in hi; now calculate sub-hi*10**9 + // to get the remainder (which will be =DIVBASE) { + lo-=DIVBASE; // correct by +1 + carry++; + } + } + #else // 32-bit + uInt hi; + // calculate multiplier*(*ud) into hi and lo + LONGMUL32HI(hi, *ud, multiplier); // get the high word + lo=multiplier*(*ud); // .. and the low + lo+=carry; // add the old hi + carry=hi+(lo=DIVBASE) { // split is needed + hop=(carry<<3)+(lo>>DIVSHIFTA); // hi:lo/2**29 + LONGMUL32HI(carry, hop, DIVMAGIC); // only need the high word + // [DIVSHIFTB is 32, so carry can be used directly] + // the estimate is now in carry; now calculate hi:lo-est*10**9; + // happily the top word of the result is irrelevant because it + // will always be zero so this needs only one multiplication + lo-=(carry*DIVBASE); + // the correction here will be at most +1; do it + if (lo>=DIVBASE) { + lo-=DIVBASE; + carry++; + } + } + #endif + if (lo>*ua) { // borrow needed + *ua+=DIVBASE; + carry++; + } + *ua-=lo; + } // ud loop + if (carry) *ua-=carry; // accdigits>divdigits [cannot borrow] + } // inner loop + + // the outer loop terminates when there is either an exact result + // or enough digits; first update the quotient digit count and + // pointer (if any significant digits) + #if DECTRACE + if (*lsuq || quodigits) printf("*lsuq=%09ld\n", (LI)*lsuq); + #endif + if (quodigits) { + quodigits+=9; // had leading unit earlier + lsuq--; + if (quodigits>DECPMAX+1) break; // have enough + } + else if (*lsuq) { // first quotient digits + const uInt *pow; + for (pow=DECPOWERS; *lsuq>=*pow; pow++) quodigits++; + lsuq--; + // [cannot have >DECPMAX+1 on first unit] + } + + if (*msua!=0) continue; // not an exact result + // acc is zero iff used all of original units and zero down to lsua + // (must also continue to original lsu for correct quotient length) + if (lsua>acc+DIVACCLEN-DIVOPLEN) continue; + for (; msua>lsua && *msua==0;) msua--; + if (*msua==0 && msua==lsua) break; + } // outer loop + + // all of the original operand in acc has been covered at this point + // quotient now has at least DECPMAX+2 digits + // *msua is now non-0 if inexact and sticky bits + // lsuq is one below the last uint of the quotient + lsuq++; // set -> true lsu of quo + if (*msua) *lsuq|=1; // apply sticky bit + + // quo now holds the (unrounded) quotient in base-billion; one + // base-billion 'digit' per uInt. + #if DECTRACE + printf("DivQuo:"); + for (uq=msuq; uq>=lsuq; uq--) printf(" %09ld", (LI)*uq); + printf("\n"); + #endif + + // Now convert to BCD for rounding and cleanup, starting from the + // most significant end [offset by one into bcdacc to leave room + // for a possible carry digit if rounding for REMNEAR is needed] + for (uq=msuq, ub=bcdacc+1; uq>=lsuq; uq--, ub+=9) { + uInt top, mid, rem; // work + if (*uq==0) { // no split needed + UBFROMUI(ub, 0); // clear 9 BCD8s + UBFROMUI(ub+4, 0); // .. + *(ub+8)=0; // .. + continue; + } + // *uq is non-zero -- split the base-billion digit into + // hi, mid, and low three-digits + #define divsplit9 1000000 // divisor + #define divsplit6 1000 // divisor + // The splitting is done by simple divides and remainders, + // assuming the compiler will optimize these [GCC does] + top=*uq/divsplit9; + rem=*uq%divsplit9; + mid=rem/divsplit6; + rem=rem%divsplit6; + // lay out the nine BCD digits (plus one unwanted byte) + UBFROMUI(ub, UBTOUI(&BIN2BCD8[top*4])); + UBFROMUI(ub+3, UBTOUI(&BIN2BCD8[mid*4])); + UBFROMUI(ub+6, UBTOUI(&BIN2BCD8[rem*4])); + } // BCD conversion loop + ub--; // -> lsu + + // complete the bcdnum; quodigits is correct, so the position of + // the first non-zero is known + num.msd=bcdacc+1+(msuq-lsuq+1)*9-quodigits; + num.lsd=ub; + + // make exponent adjustments, etc + if (lsuamaxcount) { // new high-water nark + maxcount=divcount; + printf("DivNewMaxCount: %ld\n", (LI)maxcount); + } + #endif + + if (op&DIVIDE) return decFinalize(result, &num, set); // all done + + // Is DIVIDEINT or a remainder; there is more to do -- first form + // the integer (this is done 'after the fact', unlike as in + // decNumber, so as not to tax DIVIDE) + + // The first non-zero digit will be in the first 9 digits, known + // from quodigits and num.msd, so there is always space for DECPMAX + // digits + + length=(Int)(num.lsd-num.msd+1); + //printf("Length exp: %ld %ld\n", (LI)length, (LI)num.exponent); + + if (length+num.exponent>DECPMAX) { // cannot fit + decFloatZero(result); + DFWORD(result, 0)=DECFLOAT_qNaN; + set->status|=DEC_Division_impossible; + return result; + } + + if (num.exponent>=0) { // already an int, or need pad zeros + for (ub=num.lsd+1; ub<=num.lsd+num.exponent; ub++) *ub=0; + num.lsd+=num.exponent; + } + else { // too long: round or truncate needed + Int drop=-num.exponent; + if (!(op&REMNEAR)) { // simple truncate + num.lsd-=drop; + if (num.lsd re-round digit + uByte reround; // reround value + *(num.msd-1)=0; // in case of left carry, or make 0 + if (drop 0] + reround=*roundat; + for (ub=roundat+1; ub<=num.lsd; ub++) { + if (*ub!=0) { + reround=DECSTICKYTAB[reround]; + break; + } + } // check stickies + if (roundat>num.msd) num.lsd=roundat-1; + else { + num.msd--; // use the 0 .. + num.lsd=num.msd; // .. at the new MSD place + } + if (reround!=0) { // discarding non-zero + uInt bump=0; + // rounding is DEC_ROUND_HALF_EVEN always + if (reround>5) bump=1; // >0.5 goes up + else if (reround==5) // exactly 0.5000 .. + bump=*(num.lsd) & 0x01; // .. up iff [new] lsd is odd + if (bump!=0) { // need increment + // increment the coefficient; this might end up with 1000... + ub=num.lsd; + for (; UBTOUI(ub-3)==0x09090909; ub-=4) UBFROMUI(ub-3, 0); + for (; *ub==9; ub--) *ub=0; // at most 3 more + *ub+=1; + if (ub9 + #error Exponent may overflow when doubled for Multiply +#endif +#if MULACCLEN!=(MULACCLEN/4)*4 + // This assumption is used below only for initialization + #error MULACCLEN is not a multiple of 4 +#endif + +static void decFiniteMultiply(bcdnum *num, uByte *bcdacc, + const decFloat *dfl, const decFloat *dfr) { + uInt bufl[MULOPLEN]; // left coefficient (base-billion) + uInt bufr[MULOPLEN]; // right coefficient (base-billion) + uInt *ui, *uj; // work + uByte *ub; // .. + uInt uiwork; // for macros + + #if DECUSE64 + uLong accl[MULACCLEN]; // lazy accumulator (base-billion+) + uLong *pl; // work -> lazy accumulator + uInt acc[MULACCLEN]; // coefficent in base-billion .. + #else + uInt acc[MULACCLEN*2]; // accumulator in base-billion .. + #endif + uInt *pa; // work -> accumulator + //printf("Base10**9: OpLen=%d MulAcclen=%d\n", OPLEN, MULACCLEN); + + /* Calculate sign and exponent */ + num->sign=(DFWORD(dfl, 0)^DFWORD(dfr, 0)) & DECFLOAT_Sign; + num->exponent=GETEXPUN(dfl)+GETEXPUN(dfr); // [see assertion above] + + /* Extract the coefficients and prepare the accumulator */ + // the coefficients of the operands are decoded into base-billion + // numbers in uInt arrays (bufl and bufr, LSD at offset 0) of the + // appropriate size. + GETCOEFFBILL(dfl, bufl); + GETCOEFFBILL(dfr, bufr); + #if DECTRACE && 0 + printf("CoeffbL:"); + for (ui=bufl+MULOPLEN-1; ui>=bufl; ui--) printf(" %08lx", (LI)*ui); + printf("\n"); + printf("CoeffbR:"); + for (uj=bufr+MULOPLEN-1; uj>=bufr; uj--) printf(" %08lx", (LI)*uj); + printf("\n"); + #endif + + // start the 64-bit/32-bit differing paths... +#if DECUSE64 + + // zero the accumulator + #if MULACCLEN==4 + accl[0]=0; accl[1]=0; accl[2]=0; accl[3]=0; + #else // use a loop + // MULACCLEN is a multiple of four, asserted above + for (pl=accl; pl1 may be + // needed. Values of A and B are chosen to satisfy the constraints + // just mentioned while minimizing the maximum error (and hence the + // maximum correction), as shown in the following table: + // + // Type OPLEN A B maxX maxError maxCorrection + // --------------------------------------------------------- + // DOUBLE 2 29 32 <2*10**18 0.63 1 + // QUAD 4 30 31 <4*10**18 1.17 2 + // + // In the OPLEN==2 case there is most choice, but the value for B + // of 32 has a big advantage as then the calculation of the + // estimate requires no shifting; the compiler can extract the high + // word directly after multiplying magic*hop. + #define MULMAGIC 2305843009U // 2**61/10**9 [both cases] + #if DOUBLE + #define MULSHIFTA 29 + #define MULSHIFTB 32 + #elif QUAD + #define MULSHIFTA 30 + #define MULSHIFTB 31 + #else + #error Unexpected type + #endif + + #if DECTRACE + printf("MulAccl:"); + for (pl=accl+MULACCLEN-1; pl>=accl; pl--) + printf(" %08lx:%08lx", (LI)(*pl>>32), (LI)(*pl&0xffffffff)); + printf("\n"); + #endif + + for (pl=accl, pa=acc; pl=MULTBASE) { + // *pl holds a binary number which needs to be split + hop=(uInt)(*pl>>MULSHIFTA); + est=(uInt)(((uLong)hop*MULMAGIC)>>MULSHIFTB); + // the estimate is now in est; now calculate hi:lo-est*10**9; + // happily the top word of the result is irrelevant because it + // will always be zero so this needs only one multiplication + lo=(uInt)(*pl-((uLong)est*MULTBASE)); // low word of result + // If QUAD, the correction here could be +2 + if (lo>=MULTBASE) { + lo-=MULTBASE; // correct by +1 + est++; + #if QUAD + // may need to correct by +2 + if (lo>=MULTBASE) { + lo-=MULTBASE; + est++; + } + #endif + } + // finally place lo as the new coefficient 'digit' and add est to + // the next place up [this is safe because this path is never + // taken on the final iteration as *pl will fit] + *pa=lo; + *(pl+1)+=est; + } // *pl needed split + else { // *pl1 may be + // needed. Values of A and B are chosen to satisfy the constraints + // just mentioned while minimizing the maximum error (and hence the + // maximum correction), as shown in the following table: + // + // Type OPLEN A B maxX maxError maxCorrection + // --------------------------------------------------------- + // DOUBLE 2 29 32 <2*10**18 0.63 1 + // QUAD 4 30 31 <4*10**18 1.17 2 + // + // In the OPLEN==2 case there is most choice, but the value for B + // of 32 has a big advantage as then the calculation of the + // estimate requires no shifting; the high word is simply + // calculated from multiplying magic*hop. + #define MULMAGIC 2305843009U // 2**61/10**9 [both cases] + #if DOUBLE + #define MULSHIFTA 29 + #define MULSHIFTB 32 + #elif QUAD + #define MULSHIFTA 30 + #define MULSHIFTB 31 + #else + #error Unexpected type + #endif + + #if DECTRACE + printf("MulHiLo:"); + for (pa=acc+MULACCLEN-1; pa>=acc; pa--) + printf(" %08lx:%08lx", (LI)*(pa+MULACCLEN), (LI)*pa); + printf("\n"); + #endif + + for (pa=acc;; pa++) { // each low uInt + uInt hi, lo; // words of exact multiply result + uInt hop, estlo; // work + #if QUAD + uInt esthi; // .. + #endif + + lo=*pa; + hi=*(pa+MULACCLEN); // top 32 bits + // hi and lo now hold a binary number which needs to be split + + #if DOUBLE + hop=(hi<<3)+(lo>>MULSHIFTA); // hi:lo/2**29 + LONGMUL32HI(estlo, hop, MULMAGIC);// only need the high word + // [MULSHIFTB is 32, so estlo can be used directly] + // the estimate is now in estlo; now calculate hi:lo-est*10**9; + // happily the top word of the result is irrelevant because it + // will always be zero so this needs only one multiplication + lo-=(estlo*MULTBASE); + // esthi=0; // high word is ignored below + // the correction here will be at most +1; do it + if (lo>=MULTBASE) { + lo-=MULTBASE; + estlo++; + } + #elif QUAD + hop=(hi<<2)+(lo>>MULSHIFTA); // hi:lo/2**30 + LONGMUL32HI(esthi, hop, MULMAGIC);// shift will be 31 .. + estlo=hop*MULMAGIC; // .. so low word needed + estlo=(esthi<<1)+(estlo>>MULSHIFTB); // [just the top bit] + // esthi=0; // high word is ignored below + lo-=(estlo*MULTBASE); // as above + // the correction here could be +1 or +2 + if (lo>=MULTBASE) { + lo-=MULTBASE; + estlo++; + } + if (lo>=MULTBASE) { + lo-=MULTBASE; + estlo++; + } + #else + #error Unexpected type + #endif + + // finally place lo as the new accumulator digit and add est to + // the next place up; this latter add could cause a carry of 1 + // to the high word of the next place + *pa=lo; + *(pa+1)+=estlo; + // esthi is always 0 for DOUBLE and QUAD so this is skipped + // *(pa+1+MULACCLEN)+=esthi; + if (*(pa+1)=acc; pa--) printf(" %09ld", (LI)*pa); + printf("\n"); + #endif + + // Now convert to BCD for rounding and cleanup, starting from the + // most significant end + pa=acc+MULACCLEN-1; + if (*pa!=0) num->msd=bcdacc+LEADZEROS;// drop known lead zeros + else { // >=1 word of leading zeros + num->msd=bcdacc; // known leading zeros are gone + pa--; // skip first word .. + for (; *pa==0; pa--) if (pa==acc) break; // .. and any more leading 0s + } + for (ub=bcdacc;; pa--, ub+=9) { + if (*pa!=0) { // split(s) needed + uInt top, mid, rem; // work + // *pa is non-zero -- split the base-billion acc digit into + // hi, mid, and low three-digits + #define mulsplit9 1000000 // divisor + #define mulsplit6 1000 // divisor + // The splitting is done by simple divides and remainders, + // assuming the compiler will optimize these where useful + // [GCC does] + top=*pa/mulsplit9; + rem=*pa%mulsplit9; + mid=rem/mulsplit6; + rem=rem%mulsplit6; + // lay out the nine BCD digits (plus one unwanted byte) + UBFROMUI(ub, UBTOUI(&BIN2BCD8[top*4])); + UBFROMUI(ub+3, UBTOUI(&BIN2BCD8[mid*4])); + UBFROMUI(ub+6, UBTOUI(&BIN2BCD8[rem*4])); + } + else { // *pa==0 + UBFROMUI(ub, 0); // clear 9 BCD8s + UBFROMUI(ub+4, 0); // .. + *(ub+8)=0; // .. + } + if (pa==acc) break; + } // BCD conversion loop + + num->lsd=ub+8; // complete the bcdnum .. + + #if DECTRACE + decShowNum(num, "postmult"); + decFloatShow(dfl, "dfl"); + decFloatShow(dfr, "dfr"); + #endif + return; + } // decFiniteMultiply + +/* ------------------------------------------------------------------ */ +/* decFloatAbs -- absolute value, heeding NaNs, etc. */ +/* */ +/* result gets the canonicalized df with sign 0 */ +/* df is the decFloat to abs */ +/* set is the context */ +/* returns result */ +/* */ +/* This has the same effect as decFloatPlus unless df is negative, */ +/* in which case it has the same effect as decFloatMinus. The */ +/* effect is also the same as decFloatCopyAbs except that NaNs are */ +/* handled normally (the sign of a NaN is not affected, and an sNaN */ +/* will signal) and the result will be canonical. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatAbs(decFloat *result, const decFloat *df, + decContext *set) { + if (DFISNAN(df)) return decNaNs(result, df, NULL, set); + decCanonical(result, df); // copy and check + DFBYTE(result, 0)&=~0x80; // zero sign bit + return result; + } // decFloatAbs + +/* ------------------------------------------------------------------ */ +/* decFloatAdd -- add two decFloats */ +/* */ +/* result gets the result of adding dfl and dfr: */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result */ +/* */ +/* ------------------------------------------------------------------ */ +#if QUAD +// Table for testing MSDs for fastpath elimination; returns the MSD of +// a decDouble or decQuad (top 6 bits tested) ignoring the sign. +// Infinities return -32 and NaNs return -128 so that summing the two +// MSDs also allows rapid tests for the Specials (see code below). +const Int DECTESTMSD[64]={ + 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 8, 9, -32, -128, + 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 8, 9, -32, -128}; +#else +// The table for testing MSDs is shared between the modules +extern const Int DECTESTMSD[64]; +#endif + +decFloat * decFloatAdd(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + bcdnum num; // for final conversion + Int bexpl, bexpr; // left and right biased exponents + uByte *ub, *us, *ut; // work + uInt uiwork; // for macros + #if QUAD + uShort uswork; // .. + #endif + + uInt sourhil, sourhir; // top words from source decFloats + // [valid only through end of + // fastpath code -- before swap] + uInt diffsign; // non-zero if signs differ + uInt carry; // carry: 0 or 1 before add loop + Int overlap; // coefficient overlap (if full) + Int summ; // sum of the MSDs + // the following buffers hold coefficients with various alignments + // (see commentary and diagrams below) + uByte acc[4+2+DECPMAX*3+8]; + uByte buf[4+2+DECPMAX*2]; + uByte *umsd, *ulsd; // local MSD and LSD pointers + + #if DECLITEND + #define CARRYPAT 0x01000000 // carry=1 pattern + #else + #define CARRYPAT 0x00000001 // carry=1 pattern + #endif + + /* Start decoding the arguments */ + // The initial exponents are placed into the opposite Ints to + // that which might be expected; there are two sets of data to + // keep track of (each decFloat and the corresponding exponent), + // and this scheme means that at the swap point (after comparing + // exponents) only one pair of words needs to be swapped + // whichever path is taken (thereby minimising worst-case path). + // The calculated exponents will be nonsense when the arguments are + // Special, but are not used in that path + sourhil=DFWORD(dfl, 0); // LHS top word + summ=DECTESTMSD[sourhil>>26]; // get first MSD for testing + bexpr=DECCOMBEXP[sourhil>>26]; // get exponent high bits (in place) + bexpr+=GETECON(dfl); // .. + continuation + + sourhir=DFWORD(dfr, 0); // RHS top word + summ+=DECTESTMSD[sourhir>>26]; // sum MSDs for testing + bexpl=DECCOMBEXP[sourhir>>26]; + bexpl+=GETECON(dfr); + + // here bexpr has biased exponent from lhs, and vice versa + + diffsign=(sourhil^sourhir)&DECFLOAT_Sign; + + // now determine whether to take a fast path or the full-function + // slow path. The slow path must be taken when: + // -- both numbers are finite, and: + // the exponents are different, or + // the signs are different, or + // the sum of the MSDs is >8 (hence might overflow) + // specialness and the sum of the MSDs can be tested at once using + // the summ value just calculated, so the test for specials is no + // longer on the worst-case path (as of 3.60) + + if (summ<=8) { // MSD+MSD is good, or there is a special + if (summ<0) { // there is a special + // Inf+Inf would give -64; Inf+finite is -32 or higher + if (summ<-64) return decNaNs(result, dfl, dfr, set); // one or two NaNs + // two infinities with different signs is invalid + if (summ==-64 && diffsign) return decInvalid(result, set); + if (DFISINF(dfl)) return decInfinity(result, dfl); // LHS is infinite + return decInfinity(result, dfr); // RHS must be Inf + } + // Here when both arguments are finite; fast path is possible + // (currently only for aligned and same-sign) + if (bexpr==bexpl && !diffsign) { + uInt tac[DECLETS+1]; // base-1000 coefficient + uInt encode; // work + + // Get one coefficient as base-1000 and add the other + GETCOEFFTHOU(dfl, tac); // least-significant goes to [0] + ADDCOEFFTHOU(dfr, tac); + // here the sum of the MSDs (plus any carry) will be <10 due to + // the fastpath test earlier + + // construct the result; low word is the same for both formats + encode =BIN2DPD[tac[0]]; + encode|=BIN2DPD[tac[1]]<<10; + encode|=BIN2DPD[tac[2]]<<20; + encode|=BIN2DPD[tac[3]]<<30; + DFWORD(result, (DECBYTES/4)-1)=encode; + + // collect next two declets (all that remains, for Double) + encode =BIN2DPD[tac[3]]>>2; + encode|=BIN2DPD[tac[4]]<<8; + + #if QUAD + // complete and lay out middling words + encode|=BIN2DPD[tac[5]]<<18; + encode|=BIN2DPD[tac[6]]<<28; + DFWORD(result, 2)=encode; + + encode =BIN2DPD[tac[6]]>>4; + encode|=BIN2DPD[tac[7]]<<6; + encode|=BIN2DPD[tac[8]]<<16; + encode|=BIN2DPD[tac[9]]<<26; + DFWORD(result, 1)=encode; + + // and final two declets + encode =BIN2DPD[tac[9]]>>6; + encode|=BIN2DPD[tac[10]]<<4; + #endif + + // add exponent continuation and sign (from either argument) + encode|=sourhil & (ECONMASK | DECFLOAT_Sign); + + // create lookup index = MSD + top two bits of biased exponent <<4 + tac[DECLETS]|=(bexpl>>DECECONL)<<4; + encode|=DECCOMBFROM[tac[DECLETS]]; // add constructed combination field + DFWORD(result, 0)=encode; // complete + + // decFloatShow(result, ">"); + return result; + } // fast path OK + // drop through to slow path + } // low sum or Special(s) + + /* Slow path required -- arguments are finite and might overflow, */ + /* or require alignment, or might have different signs */ + + // now swap either exponents or argument pointers + if (bexpl<=bexpr) { + // original left is bigger + Int bexpswap=bexpl; + bexpl=bexpr; + bexpr=bexpswap; + // printf("left bigger\n"); + } + else { + const decFloat *dfswap=dfl; + dfl=dfr; + dfr=dfswap; + // printf("right bigger\n"); + } + // [here dfl and bexpl refer to the datum with the larger exponent, + // of if the exponents are equal then the original LHS argument] + + // if lhs is zero then result will be the rhs (now known to have + // the smaller exponent), which also may need to be tested for zero + // for the weird IEEE 754 sign rules + if (DFISZERO(dfl)) { + decCanonical(result, dfr); // clean copy + // "When the sum of two operands with opposite signs is + // exactly zero, the sign of that sum shall be '+' in all + // rounding modes except round toward -Infinity, in which + // mode that sign shall be '-'." + if (diffsign && DFISZERO(result)) { + DFWORD(result, 0)&=~DECFLOAT_Sign; // assume sign 0 + if (set->round==DEC_ROUND_FLOOR) DFWORD(result, 0)|=DECFLOAT_Sign; + } + return result; + } // numfl is zero + // [here, LHS is non-zero; code below assumes that] + + // Coefficients layout during the calculations to follow: + // + // Overlap case: + // +------------------------------------------------+ + // acc: |0000| coeffa | tail B | | + // +------------------------------------------------+ + // buf: |0000| pad0s | coeffb | | + // +------------------------------------------------+ + // + // Touching coefficients or gap: + // +------------------------------------------------+ + // acc: |0000| coeffa | gap | coeffb | + // +------------------------------------------------+ + // [buf not used or needed; gap clamped to Pmax] + + // lay out lhs coefficient into accumulator; this starts at acc+4 + // for decDouble or acc+6 for decQuad so the LSD is word- + // aligned; the top word gap is there only in case a carry digit + // is prefixed after the add -- it does not need to be zeroed + #if DOUBLE + #define COFF 4 // offset into acc + #elif QUAD + UBFROMUS(acc+4, 0); // prefix 00 + #define COFF 6 // offset into acc + #endif + + GETCOEFF(dfl, acc+COFF); // decode from decFloat + ulsd=acc+COFF+DECPMAX-1; + umsd=acc+4; // [having this here avoids + + #if DECTRACE + {bcdnum tum; + tum.msd=umsd; + tum.lsd=ulsd; + tum.exponent=bexpl-DECBIAS; + tum.sign=DFWORD(dfl, 0) & DECFLOAT_Sign; + decShowNum(&tum, "dflx");} + #endif + + // if signs differ, take ten's complement of lhs (here the + // coefficient is subtracted from all-nines; the 1 is added during + // the later add cycle -- zeros to the right do not matter because + // the complement of zero is zero); these are fixed-length inverts + // where the lsd is known to be at a 4-byte boundary (so no borrow + // possible) + carry=0; // assume no carry + if (diffsign) { + carry=CARRYPAT; // for +1 during add + UBFROMUI(acc+ 4, 0x09090909-UBTOUI(acc+ 4)); + UBFROMUI(acc+ 8, 0x09090909-UBTOUI(acc+ 8)); + UBFROMUI(acc+12, 0x09090909-UBTOUI(acc+12)); + UBFROMUI(acc+16, 0x09090909-UBTOUI(acc+16)); + #if QUAD + UBFROMUI(acc+20, 0x09090909-UBTOUI(acc+20)); + UBFROMUI(acc+24, 0x09090909-UBTOUI(acc+24)); + UBFROMUI(acc+28, 0x09090909-UBTOUI(acc+28)); + UBFROMUI(acc+32, 0x09090909-UBTOUI(acc+32)); + UBFROMUI(acc+36, 0x09090909-UBTOUI(acc+36)); + #endif + } // diffsign + + // now process the rhs coefficient; if it cannot overlap lhs then + // it can be put straight into acc (with an appropriate gap, if + // needed) because no actual addition will be needed (except + // possibly to complete ten's complement) + overlap=DECPMAX-(bexpl-bexpr); + #if DECTRACE + printf("exps: %ld %ld\n", (LI)(bexpl-DECBIAS), (LI)(bexpr-DECBIAS)); + printf("Overlap=%ld carry=%08lx\n", (LI)overlap, (LI)carry); + #endif + + if (overlap<=0) { // no overlap possible + uInt gap; // local work + // since a full addition is not needed, a ten's complement + // calculation started above may need to be completed + if (carry) { + for (ub=ulsd; *ub==9; ub--) *ub=0; + *ub+=1; + carry=0; // taken care of + } + // up to DECPMAX-1 digits of the final result can extend down + // below the LSD of the lhs, so if the gap is >DECPMAX then the + // rhs will be simply sticky bits. In this case the gap is + // clamped to DECPMAX and the exponent adjusted to suit [this is + // safe because the lhs is non-zero]. + gap=-overlap; + if (gap>DECPMAX) { + bexpr+=gap-1; + gap=DECPMAX; + } + ub=ulsd+gap+1; // where MSD will go + // Fill the gap with 0s; note that there is no addition to do + ut=acc+COFF+DECPMAX; // start of gap + for (; ut DECPMAX + *ub=(uByte)(!DFISZERO(dfr)); // make sticky digit + } + else { // need full coefficient + GETCOEFF(dfr, ub); // decode from decFloat + ub+=DECPMAX-1; // new LSD... + } + ulsd=ub; // save new LSD + } // no overlap possible + + else { // overlap>0 + // coefficients overlap (perhaps completely, although also + // perhaps only where zeros) + if (overlap==DECPMAX) { // aligned + ub=buf+COFF; // where msd will go + #if QUAD + UBFROMUS(buf+4, 0); // clear quad's 00 + #endif + GETCOEFF(dfr, ub); // decode from decFloat + } + else { // unaligned + ub=buf+COFF+DECPMAX-overlap; // where MSD will go + // Fill the prefix gap with 0s; 8 will cover most common + // unalignments, so start with direct assignments (a loop is + // then used for any remaining -- the loop (and the one in a + // moment) is not then on the critical path because the number + // of additions is reduced by (at least) two in this case) + UBFROMUI(buf+4, 0); // [clears decQuad 00 too] + UBFROMUI(buf+8, 0); + if (ub>buf+12) { + ut=buf+12; // start any remaining + for (; ut=acc+4; ut-=4, us-=4) { // big-endian add loop + // bcd8 add + carry+=UBTOUI(us); // rhs + carry + if (carry==0) continue; // no-op + carry+=UBTOUI(ut); // lhs + // Big-endian BCD adjust (uses internal carry) + carry+=0x76f6f6f6; // note top nibble not all bits + // apply BCD adjust and save + UBFROMUI(ut, (carry & 0x0f0f0f0f) - ((carry & 0x60606060)>>4)); + carry>>=31; // true carry was at far left + } // add loop + #else + for (; ut>=acc+4; ut-=4, us-=4) { // little-endian add loop + // bcd8 add + carry+=UBTOUI(us); // rhs + carry + if (carry==0) continue; // no-op [common if unaligned] + carry+=UBTOUI(ut); // lhs + // Little-endian BCD adjust; inter-digit carry must be manual + // because the lsb from the array will be in the most-significant + // byte of carry + carry+=0x76767676; // note no inter-byte carries + carry+=(carry & 0x80000000)>>15; + carry+=(carry & 0x00800000)>>15; + carry+=(carry & 0x00008000)>>15; + carry-=(carry & 0x60606060)>>4; // BCD adjust back + UBFROMUI(ut, carry & 0x0f0f0f0f); // clear debris and save + // here, final carry-out bit is at 0x00000080; move it ready + // for next word-add (i.e., to 0x01000000) + carry=(carry & 0x00000080)<<17; + } // add loop + #endif + + #if DECTRACE + {bcdnum tum; + printf("Add done, carry=%08lx, diffsign=%ld\n", (LI)carry, (LI)diffsign); + tum.msd=umsd; // acc+4; + tum.lsd=ulsd; + tum.exponent=0; + tum.sign=0; + decShowNum(&tum, "dfadd");} + #endif + } // overlap possible + + // ordering here is a little strange in order to have slowest path + // first in GCC asm listing + if (diffsign) { // subtraction + if (!carry) { // no carry out means RHS=umsd+BNEXT) { // unaligned + // eight will handle most unaligments for Double; 16 for Quad + UBFROMUI(umsd+BNEXT, 0x09090909-UBTOUI(umsd+BNEXT)); + UBFROMUI(umsd+BNEXT+4, 0x09090909-UBTOUI(umsd+BNEXT+4)); + #if DOUBLE + #define BNEXTY (BNEXT+8) + #elif QUAD + UBFROMUI(umsd+BNEXT+8, 0x09090909-UBTOUI(umsd+BNEXT+8)); + UBFROMUI(umsd+BNEXT+12, 0x09090909-UBTOUI(umsd+BNEXT+12)); + #define BNEXTY (BNEXT+16) + #endif + if (ulsd>=umsd+BNEXTY) { // very unaligned + ut=umsd+BNEXTY; // -> continue + for (;;ut+=4) { + UBFROMUI(ut, 0x09090909-UBTOUI(ut)); // invert four digits + if (ut>=ulsd-3) break; // all done + } + } + } + // complete the ten's complement by adding 1 + for (ub=ulsd; *ub==9; ub--) *ub=0; + *ub+=1; + } // borrowed + + else { // carry out means RHS>=LHS + num.sign=DFWORD(dfr, 0) & DECFLOAT_Sign; + // all done except for the special IEEE 754 exact-zero-result + // rule (see above); while testing for zero, strip leading + // zeros (which will save decFinalize doing it) (this is in + // diffsign path, so carry impossible and true umsd is + // acc+COFF) + + // Check the initial coefficient area using the fast macro; + // this will often be all that needs to be done (as on the + // worst-case path when the subtraction was aligned and + // full-length) + if (ISCOEFFZERO(acc+COFF)) { + umsd=acc+COFF+DECPMAX-1; // so far, so zero + if (ulsd>umsd) { // more to check + umsd++; // to align after checked area + for (; UBTOUI(umsd)==0 && umsd+3round==DEC_ROUND_FLOOR) num.sign=DECFLOAT_Sign; + } + } + // [else was not zero, might still have leading zeros] + } // subtraction gave positive result + } // diffsign + + else { // same-sign addition + num.sign=DFWORD(dfl, 0)&DECFLOAT_Sign; + #if DOUBLE + if (carry) { // only possible with decDouble + *(acc+3)=1; // [Quad has leading 00] + umsd=acc+3; + } + #endif + } // same sign + + num.msd=umsd; // set MSD .. + num.lsd=ulsd; // .. and LSD + num.exponent=bexpr-DECBIAS; // set exponent to smaller, unbiassed + + #if DECTRACE + decFloatShow(dfl, "dfl"); + decFloatShow(dfr, "dfr"); + decShowNum(&num, "postadd"); + #endif + return decFinalize(result, &num, set); // round, check, and lay out + } // decFloatAdd + +/* ------------------------------------------------------------------ */ +/* decFloatAnd -- logical digitwise AND of two decFloats */ +/* */ +/* result gets the result of ANDing dfl and dfr */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result, which will be canonical with sign=0 */ +/* */ +/* The operands must be positive, finite with exponent q=0, and */ +/* comprise just zeros and ones; if not, Invalid operation results. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatAnd(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + if (!DFISUINT01(dfl) || !DFISUINT01(dfr) + || !DFISCC01(dfl) || !DFISCC01(dfr)) return decInvalid(result, set); + // the operands are positive finite integers (q=0) with just 0s and 1s + #if DOUBLE + DFWORD(result, 0)=ZEROWORD + |((DFWORD(dfl, 0) & DFWORD(dfr, 0))&0x04009124); + DFWORD(result, 1)=(DFWORD(dfl, 1) & DFWORD(dfr, 1))&0x49124491; + #elif QUAD + DFWORD(result, 0)=ZEROWORD + |((DFWORD(dfl, 0) & DFWORD(dfr, 0))&0x04000912); + DFWORD(result, 1)=(DFWORD(dfl, 1) & DFWORD(dfr, 1))&0x44912449; + DFWORD(result, 2)=(DFWORD(dfl, 2) & DFWORD(dfr, 2))&0x12449124; + DFWORD(result, 3)=(DFWORD(dfl, 3) & DFWORD(dfr, 3))&0x49124491; + #endif + return result; + } // decFloatAnd + +/* ------------------------------------------------------------------ */ +/* decFloatCanonical -- copy a decFloat, making canonical */ +/* */ +/* result gets the canonicalized df */ +/* df is the decFloat to copy and make canonical */ +/* returns result */ +/* */ +/* This works on specials, too; no error or exception is possible. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatCanonical(decFloat *result, const decFloat *df) { + return decCanonical(result, df); + } // decFloatCanonical + +/* ------------------------------------------------------------------ */ +/* decFloatClass -- return the class of a decFloat */ +/* */ +/* df is the decFloat to test */ +/* returns the decClass that df falls into */ +/* ------------------------------------------------------------------ */ +enum decClass decFloatClass(const decFloat *df) { + Int exp; // exponent + if (DFISSPECIAL(df)) { + if (DFISQNAN(df)) return DEC_CLASS_QNAN; + if (DFISSNAN(df)) return DEC_CLASS_SNAN; + // must be an infinity + if (DFISSIGNED(df)) return DEC_CLASS_NEG_INF; + return DEC_CLASS_POS_INF; + } + if (DFISZERO(df)) { // quite common + if (DFISSIGNED(df)) return DEC_CLASS_NEG_ZERO; + return DEC_CLASS_POS_ZERO; + } + // is finite and non-zero; similar code to decFloatIsNormal, here + // [this could be speeded up slightly by in-lining decFloatDigits] + exp=GETEXPUN(df) // get unbiased exponent .. + +decFloatDigits(df)-1; // .. and make adjusted exponent + if (exp>=DECEMIN) { // is normal + if (DFISSIGNED(df)) return DEC_CLASS_NEG_NORMAL; + return DEC_CLASS_POS_NORMAL; + } + // is subnormal + if (DFISSIGNED(df)) return DEC_CLASS_NEG_SUBNORMAL; + return DEC_CLASS_POS_SUBNORMAL; + } // decFloatClass + +/* ------------------------------------------------------------------ */ +/* decFloatClassString -- return the class of a decFloat as a string */ +/* */ +/* df is the decFloat to test */ +/* returns a constant string describing the class df falls into */ +/* ------------------------------------------------------------------ */ +const char *decFloatClassString(const decFloat *df) { + enum decClass eclass=decFloatClass(df); + if (eclass==DEC_CLASS_POS_NORMAL) return DEC_ClassString_PN; + if (eclass==DEC_CLASS_NEG_NORMAL) return DEC_ClassString_NN; + if (eclass==DEC_CLASS_POS_ZERO) return DEC_ClassString_PZ; + if (eclass==DEC_CLASS_NEG_ZERO) return DEC_ClassString_NZ; + if (eclass==DEC_CLASS_POS_SUBNORMAL) return DEC_ClassString_PS; + if (eclass==DEC_CLASS_NEG_SUBNORMAL) return DEC_ClassString_NS; + if (eclass==DEC_CLASS_POS_INF) return DEC_ClassString_PI; + if (eclass==DEC_CLASS_NEG_INF) return DEC_ClassString_NI; + if (eclass==DEC_CLASS_QNAN) return DEC_ClassString_QN; + if (eclass==DEC_CLASS_SNAN) return DEC_ClassString_SN; + return DEC_ClassString_UN; // Unknown + } // decFloatClassString + +/* ------------------------------------------------------------------ */ +/* decFloatCompare -- compare two decFloats; quiet NaNs allowed */ +/* */ +/* result gets the result of comparing dfl and dfr */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result, which may be -1, 0, 1, or NaN (Unordered) */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatCompare(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + Int comp; // work + // NaNs are handled as usual + if (DFISNAN(dfl) || DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set); + // numeric comparison needed + comp=decNumCompare(dfl, dfr, 0); + decFloatZero(result); + if (comp==0) return result; + DFBYTE(result, DECBYTES-1)=0x01; // LSD=1 + if (comp<0) DFBYTE(result, 0)|=0x80; // set sign bit + return result; + } // decFloatCompare + +/* ------------------------------------------------------------------ */ +/* decFloatCompareSignal -- compare two decFloats; all NaNs signal */ +/* */ +/* result gets the result of comparing dfl and dfr */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result, which may be -1, 0, 1, or NaN (Unordered) */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatCompareSignal(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + Int comp; // work + // NaNs are handled as usual, except that all NaNs signal + if (DFISNAN(dfl) || DFISNAN(dfr)) { + set->status|=DEC_Invalid_operation; + return decNaNs(result, dfl, dfr, set); + } + // numeric comparison needed + comp=decNumCompare(dfl, dfr, 0); + decFloatZero(result); + if (comp==0) return result; + DFBYTE(result, DECBYTES-1)=0x01; // LSD=1 + if (comp<0) DFBYTE(result, 0)|=0x80; // set sign bit + return result; + } // decFloatCompareSignal + +/* ------------------------------------------------------------------ */ +/* decFloatCompareTotal -- compare two decFloats with total ordering */ +/* */ +/* result gets the result of comparing dfl and dfr */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* returns result, which may be -1, 0, or 1 */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatCompareTotal(decFloat *result, + const decFloat *dfl, const decFloat *dfr) { + Int comp; // work + uInt uiwork; // for macros + #if QUAD + uShort uswork; // .. + #endif + if (DFISNAN(dfl) || DFISNAN(dfr)) { + Int nanl, nanr; // work + // morph NaNs to +/- 1 or 2, leave numbers as 0 + nanl=DFISSNAN(dfl)+DFISQNAN(dfl)*2; // quiet > signalling + if (DFISSIGNED(dfl)) nanl=-nanl; + nanr=DFISSNAN(dfr)+DFISQNAN(dfr)*2; + if (DFISSIGNED(dfr)) nanr=-nanr; + if (nanl>nanr) comp=+1; + else if (nanl*uc) comp=sigl; // difference found + else comp=-sigl; // .. + break; + } + } + } // same NaN type and sign + } + else { + // numeric comparison needed + comp=decNumCompare(dfl, dfr, 1); // total ordering + } + decFloatZero(result); + if (comp==0) return result; + DFBYTE(result, DECBYTES-1)=0x01; // LSD=1 + if (comp<0) DFBYTE(result, 0)|=0x80; // set sign bit + return result; + } // decFloatCompareTotal + +/* ------------------------------------------------------------------ */ +/* decFloatCompareTotalMag -- compare magnitudes with total ordering */ +/* */ +/* result gets the result of comparing abs(dfl) and abs(dfr) */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* returns result, which may be -1, 0, or 1 */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatCompareTotalMag(decFloat *result, + const decFloat *dfl, const decFloat *dfr) { + decFloat a, b; // for copy if needed + // copy and redirect signed operand(s) + if (DFISSIGNED(dfl)) { + decFloatCopyAbs(&a, dfl); + dfl=&a; + } + if (DFISSIGNED(dfr)) { + decFloatCopyAbs(&b, dfr); + dfr=&b; + } + return decFloatCompareTotal(result, dfl, dfr); + } // decFloatCompareTotalMag + +/* ------------------------------------------------------------------ */ +/* decFloatCopy -- copy a decFloat as-is */ +/* */ +/* result gets the copy of dfl */ +/* dfl is the decFloat to copy */ +/* returns result */ +/* */ +/* This is a bitwise operation; no errors or exceptions are possible. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatCopy(decFloat *result, const decFloat *dfl) { + if (dfl!=result) *result=*dfl; // copy needed + return result; + } // decFloatCopy + +/* ------------------------------------------------------------------ */ +/* decFloatCopyAbs -- copy a decFloat as-is and set sign bit to 0 */ +/* */ +/* result gets the copy of dfl with sign bit 0 */ +/* dfl is the decFloat to copy */ +/* returns result */ +/* */ +/* This is a bitwise operation; no errors or exceptions are possible. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatCopyAbs(decFloat *result, const decFloat *dfl) { + if (dfl!=result) *result=*dfl; // copy needed + DFBYTE(result, 0)&=~0x80; // zero sign bit + return result; + } // decFloatCopyAbs + +/* ------------------------------------------------------------------ */ +/* decFloatCopyNegate -- copy a decFloat as-is with inverted sign bit */ +/* */ +/* result gets the copy of dfl with sign bit inverted */ +/* dfl is the decFloat to copy */ +/* returns result */ +/* */ +/* This is a bitwise operation; no errors or exceptions are possible. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatCopyNegate(decFloat *result, const decFloat *dfl) { + if (dfl!=result) *result=*dfl; // copy needed + DFBYTE(result, 0)^=0x80; // invert sign bit + return result; + } // decFloatCopyNegate + +/* ------------------------------------------------------------------ */ +/* decFloatCopySign -- copy a decFloat with the sign of another */ +/* */ +/* result gets the result of copying dfl with the sign of dfr */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* returns result */ +/* */ +/* This is a bitwise operation; no errors or exceptions are possible. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatCopySign(decFloat *result, + const decFloat *dfl, const decFloat *dfr) { + uByte sign=(uByte)(DFBYTE(dfr, 0)&0x80); // save sign bit + if (dfl!=result) *result=*dfl; // copy needed + DFBYTE(result, 0)&=~0x80; // clear sign .. + DFBYTE(result, 0)=(uByte)(DFBYTE(result, 0)|sign); // .. and set saved + return result; + } // decFloatCopySign + +/* ------------------------------------------------------------------ */ +/* decFloatDigits -- return the number of digits in a decFloat */ +/* */ +/* df is the decFloat to investigate */ +/* returns the number of significant digits in the decFloat; a */ +/* zero coefficient returns 1 as does an infinity (a NaN returns */ +/* the number of digits in the payload) */ +/* ------------------------------------------------------------------ */ +// private macro to extract a declet according to provided formula +// (form), and if it is non-zero then return the calculated digits +// depending on the declet number (n), where n=0 for the most +// significant declet; uses uInt dpd for work +#define dpdlenchk(n, form) dpd=(form)&0x3ff; \ + if (dpd) return (DECPMAX-1-3*(n))-(3-DPD2BCD8[dpd*4+3]) +// next one is used when it is known that the declet must be +// non-zero, or is the final zero declet +#define dpdlendun(n, form) dpd=(form)&0x3ff; \ + if (dpd==0) return 1; \ + return (DECPMAX-1-3*(n))-(3-DPD2BCD8[dpd*4+3]) + +uInt decFloatDigits(const decFloat *df) { + uInt dpd; // work + uInt sourhi=DFWORD(df, 0); // top word from source decFloat + #if QUAD + uInt sourmh, sourml; + #endif + uInt sourlo; + + if (DFISINF(df)) return 1; + // A NaN effectively has an MSD of 0; otherwise if non-zero MSD + // then the coefficient is full-length + if (!DFISNAN(df) && DECCOMBMSD[sourhi>>26]) return DECPMAX; + + #if DOUBLE + if (sourhi&0x0003ffff) { // ends in first + dpdlenchk(0, sourhi>>8); + sourlo=DFWORD(df, 1); + dpdlendun(1, (sourhi<<2) | (sourlo>>30)); + } // [cannot drop through] + sourlo=DFWORD(df, 1); // sourhi not involved now + if (sourlo&0xfff00000) { // in one of first two + dpdlenchk(1, sourlo>>30); // very rare + dpdlendun(2, sourlo>>20); + } // [cannot drop through] + dpdlenchk(3, sourlo>>10); + dpdlendun(4, sourlo); + // [cannot drop through] + + #elif QUAD + if (sourhi&0x00003fff) { // ends in first + dpdlenchk(0, sourhi>>4); + sourmh=DFWORD(df, 1); + dpdlendun(1, ((sourhi)<<6) | (sourmh>>26)); + } // [cannot drop through] + sourmh=DFWORD(df, 1); + if (sourmh) { + dpdlenchk(1, sourmh>>26); + dpdlenchk(2, sourmh>>16); + dpdlenchk(3, sourmh>>6); + sourml=DFWORD(df, 2); + dpdlendun(4, ((sourmh)<<4) | (sourml>>28)); + } // [cannot drop through] + sourml=DFWORD(df, 2); + if (sourml) { + dpdlenchk(4, sourml>>28); + dpdlenchk(5, sourml>>18); + dpdlenchk(6, sourml>>8); + sourlo=DFWORD(df, 3); + dpdlendun(7, ((sourml)<<2) | (sourlo>>30)); + } // [cannot drop through] + sourlo=DFWORD(df, 3); + if (sourlo&0xfff00000) { // in one of first two + dpdlenchk(7, sourlo>>30); // very rare + dpdlendun(8, sourlo>>20); + } // [cannot drop through] + dpdlenchk(9, sourlo>>10); + dpdlendun(10, sourlo); + // [cannot drop through] + #endif + } // decFloatDigits + +/* ------------------------------------------------------------------ */ +/* decFloatDivide -- divide a decFloat by another */ +/* */ +/* result gets the result of dividing dfl by dfr: */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result */ +/* */ +/* ------------------------------------------------------------------ */ +// This is just a wrapper. +decFloat * decFloatDivide(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + return decDivide(result, dfl, dfr, set, DIVIDE); + } // decFloatDivide + +/* ------------------------------------------------------------------ */ +/* decFloatDivideInteger -- integer divide a decFloat by another */ +/* */ +/* result gets the result of dividing dfl by dfr: */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result */ +/* */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatDivideInteger(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + return decDivide(result, dfl, dfr, set, DIVIDEINT); + } // decFloatDivideInteger + +/* ------------------------------------------------------------------ */ +/* decFloatFMA -- multiply and add three decFloats, fused */ +/* */ +/* result gets the result of (dfl*dfr)+dff with a single rounding */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* dff is the final decFloat (fhs) */ +/* set is the context */ +/* returns result */ +/* */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatFMA(decFloat *result, const decFloat *dfl, + const decFloat *dfr, const decFloat *dff, + decContext *set) { + + // The accumulator has the bytes needed for FiniteMultiply, plus + // one byte to the left in case of carry, plus DECPMAX+2 to the + // right for the final addition (up to full fhs + round & sticky) + #define FMALEN (ROUNDUP4(1+ (DECPMAX9*18+1) +DECPMAX+2)) + uByte acc[FMALEN]; // for multiplied coefficient in BCD + // .. and for final result + bcdnum mul; // for multiplication result + bcdnum fin; // for final operand, expanded + uByte coe[ROUNDUP4(DECPMAX)]; // dff coefficient in BCD + bcdnum *hi, *lo; // bcdnum with higher/lower exponent + uInt diffsign; // non-zero if signs differ + uInt hipad; // pad digit for hi if needed + Int padding; // excess exponent + uInt carry; // +1 for ten's complement and during add + uByte *ub, *uh, *ul; // work + uInt uiwork; // for macros + + // handle all the special values [any special operand leads to a + // special result] + if (DFISSPECIAL(dfl) || DFISSPECIAL(dfr) || DFISSPECIAL(dff)) { + decFloat proxy; // multiplication result proxy + // NaNs are handled as usual, giving priority to sNaNs + if (DFISSNAN(dfl) || DFISSNAN(dfr)) return decNaNs(result, dfl, dfr, set); + if (DFISSNAN(dff)) return decNaNs(result, dff, NULL, set); + if (DFISNAN(dfl) || DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set); + if (DFISNAN(dff)) return decNaNs(result, dff, NULL, set); + // One or more of the three is infinite + // infinity times zero is bad + decFloatZero(&proxy); + if (DFISINF(dfl)) { + if (DFISZERO(dfr)) return decInvalid(result, set); + decInfinity(&proxy, &proxy); + } + else if (DFISINF(dfr)) { + if (DFISZERO(dfl)) return decInvalid(result, set); + decInfinity(&proxy, &proxy); + } + // compute sign of multiplication and place in proxy + DFWORD(&proxy, 0)|=(DFWORD(dfl, 0)^DFWORD(dfr, 0))&DECFLOAT_Sign; + if (!DFISINF(dff)) return decFloatCopy(result, &proxy); + // dff is Infinite + if (!DFISINF(&proxy)) return decInfinity(result, dff); + // both sides of addition are infinite; different sign is bad + if ((DFWORD(dff, 0)&DECFLOAT_Sign)!=(DFWORD(&proxy, 0)&DECFLOAT_Sign)) + return decInvalid(result, set); + return decFloatCopy(result, &proxy); + } + + /* Here when all operands are finite */ + + // First multiply dfl*dfr + decFiniteMultiply(&mul, acc+1, dfl, dfr); + // The multiply is complete, exact and unbounded, and described in + // mul with the coefficient held in acc[1...] + + // now add in dff; the algorithm is essentially the same as + // decFloatAdd, but the code is different because the code there + // is highly optimized for adding two numbers of the same size + fin.exponent=GETEXPUN(dff); // get dff exponent and sign + fin.sign=DFWORD(dff, 0)&DECFLOAT_Sign; + diffsign=mul.sign^fin.sign; // note if signs differ + fin.msd=coe; + fin.lsd=coe+DECPMAX-1; + GETCOEFF(dff, coe); // extract the coefficient + + // now set hi and lo so that hi points to whichever of mul and fin + // has the higher exponent and lo points to the other [don't care, + // if the same]. One coefficient will be in acc, the other in coe. + if (mul.exponent>=fin.exponent) { + hi=&mul; + lo=&fin; + } + else { + hi=&fin; + lo=&mul; + } + + // remove leading zeros on both operands; this will save time later + // and make testing for zero trivial (tests are safe because acc + // and coe are rounded up to uInts) + for (; UBTOUI(hi->msd)==0 && hi->msd+3lsd;) hi->msd+=4; + for (; *hi->msd==0 && hi->msdlsd;) hi->msd++; + for (; UBTOUI(lo->msd)==0 && lo->msd+3lsd;) lo->msd+=4; + for (; *lo->msd==0 && lo->msdlsd;) lo->msd++; + + // if hi is zero then result will be lo (which has the smaller + // exponent), which also may need to be tested for zero for the + // weird IEEE 754 sign rules + if (*hi->msd==0) { // hi is zero + // "When the sum of two operands with opposite signs is + // exactly zero, the sign of that sum shall be '+' in all + // rounding modes except round toward -Infinity, in which + // mode that sign shall be '-'." + if (diffsign) { + if (*lo->msd==0) { // lo is zero + lo->sign=0; + if (set->round==DEC_ROUND_FLOOR) lo->sign=DECFLOAT_Sign; + } // diffsign && lo=0 + } // diffsign + return decFinalize(result, lo, set); // may need clamping + } // numfl is zero + // [here, both are minimal length and hi is non-zero] + // (if lo is zero then padding with zeros may be needed, below) + + // if signs differ, take the ten's complement of hi (zeros to the + // right do not matter because the complement of zero is zero); the + // +1 is done later, as part of the addition, inserted at the + // correct digit + hipad=0; + carry=0; + if (diffsign) { + hipad=9; + carry=1; + // exactly the correct number of digits must be inverted + for (uh=hi->msd; uhlsd-3; uh+=4) UBFROMUI(uh, 0x09090909-UBTOUI(uh)); + for (; uh<=hi->lsd; uh++) *uh=(uByte)(0x09-*uh); + } + + // ready to add; note that hi has no leading zeros so gap + // calculation does not have to be as pessimistic as in decFloatAdd + // (this is much more like the arbitrary-precision algorithm in + // Rexx and decNumber) + + // padding is the number of zeros that would need to be added to hi + // for its lsd to be aligned with the lsd of lo + padding=hi->exponent-lo->exponent; + // printf("FMA pad %ld\n", (LI)padding); + + // the result of the addition will be built into the accumulator, + // starting from the far right; this could be either hi or lo, and + // will be aligned + ub=acc+FMALEN-1; // where lsd of result will go + ul=lo->lsd; // lsd of rhs + + if (padding!=0) { // unaligned + // if the msd of lo is more than DECPMAX+2 digits to the right of + // the original msd of hi then it can be reduced to a single + // digit at the right place, as it stays clear of hi digits + // [it must be DECPMAX+2 because during a subtraction the msd + // could become 0 after a borrow from 1.000 to 0.9999...] + + Int hilen=(Int)(hi->lsd-hi->msd+1); // length of hi + Int lolen=(Int)(lo->lsd-lo->msd+1); // and of lo + + if (hilen+padding-lolen > DECPMAX+2) { // can reduce lo to single + // make sure it is virtually at least DECPMAX from hi->msd, at + // least to right of hi->lsd (in case of destructive subtract), + // and separated by at least two digits from either of those + // (the tricky DOUBLE case is when hi is a 1 that will become a + // 0.9999... by subtraction: + // hi: 1 E+16 + // lo: .................1000000000000000 E-16 + // which for the addition pads to: + // hi: 1000000000000000000 E-16 + // lo: .................1000000000000000 E-16 + Int newexp=MINI(hi->exponent, hi->exponent+hilen-DECPMAX)-3; + + // printf("FMA reduce: %ld\n", (LI)reduce); + lo->lsd=lo->msd; // to single digit [maybe 0] + lo->exponent=newexp; // new lowest exponent + padding=hi->exponent-lo->exponent; // recalculate + ul=lo->lsd; // .. and repoint + } + + // padding is still > 0, but will fit in acc (less leading carry slot) + #if DECCHECK + if (padding<=0) printf("FMA low padding: %ld\n", (LI)padding); + if (hilen+padding+1>FMALEN) + printf("FMA excess hilen+padding: %ld+%ld \n", (LI)hilen, (LI)padding); + // printf("FMA padding: %ld\n", (LI)padding); + #endif + + // padding digits can now be set in the result; one or more of + // these will come from lo; others will be zeros in the gap + for (; ul-3>=lo->msd && padding>3; padding-=4, ul-=4, ub-=4) { + UBFROMUI(ub-3, UBTOUI(ul-3)); // [cannot overlap] + } + for (; ul>=lo->msd && padding>0; padding--, ul--, ub--) *ub=*ul; + for (;padding>0; padding--, ub--) *ub=0; // mind the gap + } + + // addition now complete to the right of the rightmost digit of hi + uh=hi->lsd; + + // dow do the add from hi->lsd to the left + // [bytewise, because either operand can run out at any time] + // carry was set up depending on ten's complement above + // first assume both operands have some digits + for (;; ub--) { + if (uhmsd || ulmsd) break; + *ub=(uByte)(carry+(*uh--)+(*ul--)); + carry=0; + if (*ub<10) continue; + *ub-=10; + carry=1; + } // both loop + + if (ulmsd) { // to left of lo + for (;; ub--) { + if (uhmsd) break; + *ub=(uByte)(carry+(*uh--)); // [+0] + carry=0; + if (*ub<10) continue; + *ub-=10; + carry=1; + } // hi loop + } + else { // to left of hi + for (;; ub--) { + if (ulmsd) break; + *ub=(uByte)(carry+hipad+(*ul--)); + carry=0; + if (*ub<10) continue; + *ub-=10; + carry=1; + } // lo loop + } + + // addition complete -- now handle carry, borrow, etc. + // use lo to set up the num (its exponent is already correct, and + // sign usually is) + lo->msd=ub+1; + lo->lsd=acc+FMALEN-1; + // decShowNum(lo, "lo"); + if (!diffsign) { // same-sign addition + if (carry) { // carry out + *ub=1; // place the 1 .. + lo->msd--; // .. and update + } + } // same sign + else { // signs differed (subtraction) + if (!carry) { // no carry out means hisign=hi->sign; // sign is lhs sign + for (ul=lo->msd; ullsd-3; ul+=4) UBFROMUI(ul, 0x09090909-UBTOUI(ul)); + for (; ul<=lo->lsd; ul++) *ul=(uByte)(0x09-*ul); // [leaves ul at lsd+1] + // complete the ten's complement by adding 1 [cannot overrun] + for (ul--; *ul==9; ul--) *ul=0; + *ul+=1; + } // borrowed + else { // carry out means hi>=lo + // sign to use is lo->sign + // all done except for the special IEEE 754 exact-zero-result + // rule (see above); while testing for zero, strip leading + // zeros (which will save decFinalize doing it) + for (; UBTOUI(lo->msd)==0 && lo->msd+3lsd;) lo->msd+=4; + for (; *lo->msd==0 && lo->msdlsd;) lo->msd++; + if (*lo->msd==0) { // must be true zero (and diffsign) + lo->sign=0; // assume + + if (set->round==DEC_ROUND_FLOOR) lo->sign=DECFLOAT_Sign; + } + // [else was not zero, might still have leading zeros] + } // subtraction gave positive result + } // diffsign + + #if DECCHECK + // assert no left underrun + if (lo->msdmsd)); + } + #endif + + return decFinalize(result, lo, set); // round, check, and lay out + } // decFloatFMA + +/* ------------------------------------------------------------------ */ +/* decFloatFromInt -- initialise a decFloat from an Int */ +/* */ +/* result gets the converted Int */ +/* n is the Int to convert */ +/* returns result */ +/* */ +/* The result is Exact; no errors or exceptions are possible. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatFromInt32(decFloat *result, Int n) { + uInt u=(uInt)n; // copy as bits + uInt encode; // work + DFWORD(result, 0)=ZEROWORD; // always + #if QUAD + DFWORD(result, 1)=0; + DFWORD(result, 2)=0; + #endif + if (n<0) { // handle -n with care + // [This can be done without the test, but is then slightly slower] + u=(~u)+1; + DFWORD(result, 0)|=DECFLOAT_Sign; + } + // Since the maximum value of u now is 2**31, only the low word of + // result is affected + encode=BIN2DPD[u%1000]; + u/=1000; + encode|=BIN2DPD[u%1000]<<10; + u/=1000; + encode|=BIN2DPD[u%1000]<<20; + u/=1000; // now 0, 1, or 2 + encode|=u<<30; + DFWORD(result, DECWORDS-1)=encode; + return result; + } // decFloatFromInt32 + +/* ------------------------------------------------------------------ */ +/* decFloatFromUInt -- initialise a decFloat from a uInt */ +/* */ +/* result gets the converted uInt */ +/* n is the uInt to convert */ +/* returns result */ +/* */ +/* The result is Exact; no errors or exceptions are possible. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatFromUInt32(decFloat *result, uInt u) { + uInt encode; // work + DFWORD(result, 0)=ZEROWORD; // always + #if QUAD + DFWORD(result, 1)=0; + DFWORD(result, 2)=0; + #endif + encode=BIN2DPD[u%1000]; + u/=1000; + encode|=BIN2DPD[u%1000]<<10; + u/=1000; + encode|=BIN2DPD[u%1000]<<20; + u/=1000; // now 0 -> 4 + encode|=u<<30; + DFWORD(result, DECWORDS-1)=encode; + DFWORD(result, DECWORDS-2)|=u>>2; // rarely non-zero + return result; + } // decFloatFromUInt32 + +/* ------------------------------------------------------------------ */ +/* decFloatInvert -- logical digitwise INVERT of a decFloat */ +/* */ +/* result gets the result of INVERTing df */ +/* df is the decFloat to invert */ +/* set is the context */ +/* returns result, which will be canonical with sign=0 */ +/* */ +/* The operand must be positive, finite with exponent q=0, and */ +/* comprise just zeros and ones; if not, Invalid operation results. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatInvert(decFloat *result, const decFloat *df, + decContext *set) { + uInt sourhi=DFWORD(df, 0); // top word of dfs + + if (!DFISUINT01(df) || !DFISCC01(df)) return decInvalid(result, set); + // the operand is a finite integer (q=0) + #if DOUBLE + DFWORD(result, 0)=ZEROWORD|((~sourhi)&0x04009124); + DFWORD(result, 1)=(~DFWORD(df, 1)) &0x49124491; + #elif QUAD + DFWORD(result, 0)=ZEROWORD|((~sourhi)&0x04000912); + DFWORD(result, 1)=(~DFWORD(df, 1)) &0x44912449; + DFWORD(result, 2)=(~DFWORD(df, 2)) &0x12449124; + DFWORD(result, 3)=(~DFWORD(df, 3)) &0x49124491; + #endif + return result; + } // decFloatInvert + +/* ------------------------------------------------------------------ */ +/* decFloatIs -- decFloat tests (IsSigned, etc.) */ +/* */ +/* df is the decFloat to test */ +/* returns 0 or 1 in a uInt */ +/* */ +/* Many of these could be macros, but having them as real functions */ +/* is a little cleaner (and they can be referred to here by the */ +/* generic names) */ +/* ------------------------------------------------------------------ */ +uInt decFloatIsCanonical(const decFloat *df) { + if (DFISSPECIAL(df)) { + if (DFISINF(df)) { + if (DFWORD(df, 0)&ECONMASK) return 0; // exponent continuation + if (!DFISCCZERO(df)) return 0; // coefficient continuation + return 1; + } + // is a NaN + if (DFWORD(df, 0)&ECONNANMASK) return 0; // exponent continuation + if (DFISCCZERO(df)) return 1; // coefficient continuation + // drop through to check payload + } + { // declare block + #if DOUBLE + uInt sourhi=DFWORD(df, 0); + uInt sourlo=DFWORD(df, 1); + if (CANONDPDOFF(sourhi, 8) + && CANONDPDTWO(sourhi, sourlo, 30) + && CANONDPDOFF(sourlo, 20) + && CANONDPDOFF(sourlo, 10) + && CANONDPDOFF(sourlo, 0)) return 1; + #elif QUAD + uInt sourhi=DFWORD(df, 0); + uInt sourmh=DFWORD(df, 1); + uInt sourml=DFWORD(df, 2); + uInt sourlo=DFWORD(df, 3); + if (CANONDPDOFF(sourhi, 4) + && CANONDPDTWO(sourhi, sourmh, 26) + && CANONDPDOFF(sourmh, 16) + && CANONDPDOFF(sourmh, 6) + && CANONDPDTWO(sourmh, sourml, 28) + && CANONDPDOFF(sourml, 18) + && CANONDPDOFF(sourml, 8) + && CANONDPDTWO(sourml, sourlo, 30) + && CANONDPDOFF(sourlo, 20) + && CANONDPDOFF(sourlo, 10) + && CANONDPDOFF(sourlo, 0)) return 1; + #endif + } // block + return 0; // a declet is non-canonical + } + +uInt decFloatIsFinite(const decFloat *df) { + return !DFISSPECIAL(df); + } +uInt decFloatIsInfinite(const decFloat *df) { + return DFISINF(df); + } +uInt decFloatIsInteger(const decFloat *df) { + return DFISINT(df); + } +uInt decFloatIsLogical(const decFloat *df) { + return DFISUINT01(df) & DFISCC01(df); + } +uInt decFloatIsNaN(const decFloat *df) { + return DFISNAN(df); + } +uInt decFloatIsNegative(const decFloat *df) { + return DFISSIGNED(df) && !DFISZERO(df) && !DFISNAN(df); + } +uInt decFloatIsNormal(const decFloat *df) { + Int exp; // exponent + if (DFISSPECIAL(df)) return 0; + if (DFISZERO(df)) return 0; + // is finite and non-zero + exp=GETEXPUN(df) // get unbiased exponent .. + +decFloatDigits(df)-1; // .. and make adjusted exponent + return (exp>=DECEMIN); // < DECEMIN is subnormal + } +uInt decFloatIsPositive(const decFloat *df) { + return !DFISSIGNED(df) && !DFISZERO(df) && !DFISNAN(df); + } +uInt decFloatIsSignaling(const decFloat *df) { + return DFISSNAN(df); + } +uInt decFloatIsSignalling(const decFloat *df) { + return DFISSNAN(df); + } +uInt decFloatIsSigned(const decFloat *df) { + return DFISSIGNED(df); + } +uInt decFloatIsSubnormal(const decFloat *df) { + if (DFISSPECIAL(df)) return 0; + // is finite + if (decFloatIsNormal(df)) return 0; + // it is Use |A| */ +/* A=0 -> -Infinity (Division by zero) */ +/* A=Infinite -> +Infinity (Exact) */ +/* A=1 exactly -> 0 (Exact) */ +/* NaNs are propagated as usual */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatLogB(decFloat *result, const decFloat *df, + decContext *set) { + Int ae; // adjusted exponent + if (DFISNAN(df)) return decNaNs(result, df, NULL, set); + if (DFISINF(df)) { + DFWORD(result, 0)=0; // need +ve + return decInfinity(result, result); // canonical +Infinity + } + if (DFISZERO(df)) { + set->status|=DEC_Division_by_zero; // as per 754 + DFWORD(result, 0)=DECFLOAT_Sign; // make negative + return decInfinity(result, result); // canonical -Infinity + } + ae=GETEXPUN(df) // get unbiased exponent .. + +decFloatDigits(df)-1; // .. and make adjusted exponent + // ae has limited range (3 digits for DOUBLE and 4 for QUAD), so + // it is worth using a special case of decFloatFromInt32 + DFWORD(result, 0)=ZEROWORD; // always + if (ae<0) { + DFWORD(result, 0)|=DECFLOAT_Sign; // -0 so far + ae=-ae; + } + #if DOUBLE + DFWORD(result, 1)=BIN2DPD[ae]; // a single declet + #elif QUAD + DFWORD(result, 1)=0; + DFWORD(result, 2)=0; + DFWORD(result, 3)=(ae/1000)<<10; // is <10, so need no DPD encode + DFWORD(result, 3)|=BIN2DPD[ae%1000]; + #endif + return result; + } // decFloatLogB + +/* ------------------------------------------------------------------ */ +/* decFloatMax -- return maxnum of two operands */ +/* */ +/* result gets the chosen decFloat */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result */ +/* */ +/* If just one operand is a quiet NaN it is ignored. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatMax(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + Int comp; + if (DFISNAN(dfl)) { + // sNaN or both NaNs leads to normal NaN processing + if (DFISNAN(dfr) || DFISSNAN(dfl)) return decNaNs(result, dfl, dfr, set); + return decCanonical(result, dfr); // RHS is numeric + } + if (DFISNAN(dfr)) { + // sNaN leads to normal NaN processing (both NaN handled above) + if (DFISSNAN(dfr)) return decNaNs(result, dfl, dfr, set); + return decCanonical(result, dfl); // LHS is numeric + } + // Both operands are numeric; numeric comparison needed -- use + // total order for a well-defined choice (and +0 > -0) + comp=decNumCompare(dfl, dfr, 1); + if (comp>=0) return decCanonical(result, dfl); + return decCanonical(result, dfr); + } // decFloatMax + +/* ------------------------------------------------------------------ */ +/* decFloatMaxMag -- return maxnummag of two operands */ +/* */ +/* result gets the chosen decFloat */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result */ +/* */ +/* Returns according to the magnitude comparisons if both numeric and */ +/* unequal, otherwise returns maxnum */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatMaxMag(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + Int comp; + decFloat absl, absr; + if (DFISNAN(dfl) || DFISNAN(dfr)) return decFloatMax(result, dfl, dfr, set); + + decFloatCopyAbs(&absl, dfl); + decFloatCopyAbs(&absr, dfr); + comp=decNumCompare(&absl, &absr, 0); + if (comp>0) return decCanonical(result, dfl); + if (comp<0) return decCanonical(result, dfr); + return decFloatMax(result, dfl, dfr, set); + } // decFloatMaxMag + +/* ------------------------------------------------------------------ */ +/* decFloatMin -- return minnum of two operands */ +/* */ +/* result gets the chosen decFloat */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result */ +/* */ +/* If just one operand is a quiet NaN it is ignored. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatMin(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + Int comp; + if (DFISNAN(dfl)) { + // sNaN or both NaNs leads to normal NaN processing + if (DFISNAN(dfr) || DFISSNAN(dfl)) return decNaNs(result, dfl, dfr, set); + return decCanonical(result, dfr); // RHS is numeric + } + if (DFISNAN(dfr)) { + // sNaN leads to normal NaN processing (both NaN handled above) + if (DFISSNAN(dfr)) return decNaNs(result, dfl, dfr, set); + return decCanonical(result, dfl); // LHS is numeric + } + // Both operands are numeric; numeric comparison needed -- use + // total order for a well-defined choice (and +0 > -0) + comp=decNumCompare(dfl, dfr, 1); + if (comp<=0) return decCanonical(result, dfl); + return decCanonical(result, dfr); + } // decFloatMin + +/* ------------------------------------------------------------------ */ +/* decFloatMinMag -- return minnummag of two operands */ +/* */ +/* result gets the chosen decFloat */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result */ +/* */ +/* Returns according to the magnitude comparisons if both numeric and */ +/* unequal, otherwise returns minnum */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatMinMag(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + Int comp; + decFloat absl, absr; + if (DFISNAN(dfl) || DFISNAN(dfr)) return decFloatMin(result, dfl, dfr, set); + + decFloatCopyAbs(&absl, dfl); + decFloatCopyAbs(&absr, dfr); + comp=decNumCompare(&absl, &absr, 0); + if (comp<0) return decCanonical(result, dfl); + if (comp>0) return decCanonical(result, dfr); + return decFloatMin(result, dfl, dfr, set); + } // decFloatMinMag + +/* ------------------------------------------------------------------ */ +/* decFloatMinus -- negate value, heeding NaNs, etc. */ +/* */ +/* result gets the canonicalized 0-df */ +/* df is the decFloat to minus */ +/* set is the context */ +/* returns result */ +/* */ +/* This has the same effect as 0-df where the exponent of the zero is */ +/* the same as that of df (if df is finite). */ +/* The effect is also the same as decFloatCopyNegate except that NaNs */ +/* are handled normally (the sign of a NaN is not affected, and an */ +/* sNaN will signal), the result is canonical, and zero gets sign 0. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatMinus(decFloat *result, const decFloat *df, + decContext *set) { + if (DFISNAN(df)) return decNaNs(result, df, NULL, set); + decCanonical(result, df); // copy and check + if (DFISZERO(df)) DFBYTE(result, 0)&=~0x80; // turn off sign bit + else DFBYTE(result, 0)^=0x80; // flip sign bit + return result; + } // decFloatMinus + +/* ------------------------------------------------------------------ */ +/* decFloatMultiply -- multiply two decFloats */ +/* */ +/* result gets the result of multiplying dfl and dfr: */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result */ +/* */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatMultiply(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + bcdnum num; // for final conversion + uByte bcdacc[DECPMAX9*18+1]; // for coefficent in BCD + + if (DFISSPECIAL(dfl) || DFISSPECIAL(dfr)) { // either is special? + // NaNs are handled as usual + if (DFISNAN(dfl) || DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set); + // infinity times zero is bad + if (DFISINF(dfl) && DFISZERO(dfr)) return decInvalid(result, set); + if (DFISINF(dfr) && DFISZERO(dfl)) return decInvalid(result, set); + // both infinite; return canonical infinity with computed sign + DFWORD(result, 0)=DFWORD(dfl, 0)^DFWORD(dfr, 0); // compute sign + return decInfinity(result, result); + } + + /* Here when both operands are finite */ + decFiniteMultiply(&num, bcdacc, dfl, dfr); + return decFinalize(result, &num, set); // round, check, and lay out + } // decFloatMultiply + +/* ------------------------------------------------------------------ */ +/* decFloatNextMinus -- next towards -Infinity */ +/* */ +/* result gets the next lesser decFloat */ +/* dfl is the decFloat to start with */ +/* set is the context */ +/* returns result */ +/* */ +/* This is 754 nextdown; Invalid is the only status possible (from */ +/* an sNaN). */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatNextMinus(decFloat *result, const decFloat *dfl, + decContext *set) { + decFloat delta; // tiny increment + uInt savestat; // saves status + enum rounding saveround; // .. and mode + + // +Infinity is the special case + if (DFISINF(dfl) && !DFISSIGNED(dfl)) { + DFSETNMAX(result); + return result; // [no status to set] + } + // other cases are effected by sutracting a tiny delta -- this + // should be done in a wider format as the delta is unrepresentable + // here (but can be done with normal add if the sign of zero is + // treated carefully, because no Inexactitude is interesting); + // rounding to -Infinity then pushes the result to next below + decFloatZero(&delta); // set up tiny delta + DFWORD(&delta, DECWORDS-1)=1; // coefficient=1 + DFWORD(&delta, 0)=DECFLOAT_Sign; // Sign=1 + biased exponent=0 + // set up for the directional round + saveround=set->round; // save mode + set->round=DEC_ROUND_FLOOR; // .. round towards -Infinity + savestat=set->status; // save status + decFloatAdd(result, dfl, &delta, set); + // Add rules mess up the sign when going from +Ntiny to 0 + if (DFISZERO(result)) DFWORD(result, 0)^=DECFLOAT_Sign; // correct + set->status&=DEC_Invalid_operation; // preserve only sNaN status + set->status|=savestat; // restore pending flags + set->round=saveround; // .. and mode + return result; + } // decFloatNextMinus + +/* ------------------------------------------------------------------ */ +/* decFloatNextPlus -- next towards +Infinity */ +/* */ +/* result gets the next larger decFloat */ +/* dfl is the decFloat to start with */ +/* set is the context */ +/* returns result */ +/* */ +/* This is 754 nextup; Invalid is the only status possible (from */ +/* an sNaN). */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatNextPlus(decFloat *result, const decFloat *dfl, + decContext *set) { + uInt savestat; // saves status + enum rounding saveround; // .. and mode + decFloat delta; // tiny increment + + // -Infinity is the special case + if (DFISINF(dfl) && DFISSIGNED(dfl)) { + DFSETNMAX(result); + DFWORD(result, 0)|=DECFLOAT_Sign; // make negative + return result; // [no status to set] + } + // other cases are effected by sutracting a tiny delta -- this + // should be done in a wider format as the delta is unrepresentable + // here (but can be done with normal add if the sign of zero is + // treated carefully, because no Inexactitude is interesting); + // rounding to +Infinity then pushes the result to next above + decFloatZero(&delta); // set up tiny delta + DFWORD(&delta, DECWORDS-1)=1; // coefficient=1 + DFWORD(&delta, 0)=0; // Sign=0 + biased exponent=0 + // set up for the directional round + saveround=set->round; // save mode + set->round=DEC_ROUND_CEILING; // .. round towards +Infinity + savestat=set->status; // save status + decFloatAdd(result, dfl, &delta, set); + // Add rules mess up the sign when going from -Ntiny to -0 + if (DFISZERO(result)) DFWORD(result, 0)^=DECFLOAT_Sign; // correct + set->status&=DEC_Invalid_operation; // preserve only sNaN status + set->status|=savestat; // restore pending flags + set->round=saveround; // .. and mode + return result; + } // decFloatNextPlus + +/* ------------------------------------------------------------------ */ +/* decFloatNextToward -- next towards a decFloat */ +/* */ +/* result gets the next decFloat */ +/* dfl is the decFloat to start with */ +/* dfr is the decFloat to move toward */ +/* set is the context */ +/* returns result */ +/* */ +/* This is 754-1985 nextafter, as modified during revision (dropped */ +/* from 754-2008); status may be set unless the result is a normal */ +/* number. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatNextToward(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + decFloat delta; // tiny increment or decrement + decFloat pointone; // 1e-1 + uInt savestat; // saves status + enum rounding saveround; // .. and mode + uInt deltatop; // top word for delta + Int comp; // work + + if (DFISNAN(dfl) || DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set); + // Both are numeric, so Invalid no longer a possibility + comp=decNumCompare(dfl, dfr, 0); + if (comp==0) return decFloatCopySign(result, dfl, dfr); // equal + // unequal; do NextPlus or NextMinus but with different status rules + + if (comp<0) { // lhsround; // save mode + set->round=DEC_ROUND_CEILING; // .. round towards +Infinity + deltatop=0; // positive delta + } + else { // lhs>rhs, do NextMinus, see above for commentary + if (DFISINF(dfl) && !DFISSIGNED(dfl)) { // +Infinity special case + DFSETNMAX(result); + return result; + } + saveround=set->round; // save mode + set->round=DEC_ROUND_FLOOR; // .. round towards -Infinity + deltatop=DECFLOAT_Sign; // negative delta + } + savestat=set->status; // save status + // Here, Inexact is needed where appropriate (and hence Underflow, + // etc.). Therefore the tiny delta which is otherwise + // unrepresentable (see NextPlus and NextMinus) is constructed + // using the multiplication of FMA. + decFloatZero(&delta); // set up tiny delta + DFWORD(&delta, DECWORDS-1)=1; // coefficient=1 + DFWORD(&delta, 0)=deltatop; // Sign + biased exponent=0 + decFloatFromString(&pointone, "1E-1", set); // set up multiplier + decFloatFMA(result, &delta, &pointone, dfl, set); + // [Delta is truly tiny, so no need to correct sign of zero] + // use new status unless the result is normal + if (decFloatIsNormal(result)) set->status=savestat; // else goes forward + set->round=saveround; // restore mode + return result; + } // decFloatNextToward + +/* ------------------------------------------------------------------ */ +/* decFloatOr -- logical digitwise OR of two decFloats */ +/* */ +/* result gets the result of ORing dfl and dfr */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result, which will be canonical with sign=0 */ +/* */ +/* The operands must be positive, finite with exponent q=0, and */ +/* comprise just zeros and ones; if not, Invalid operation results. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatOr(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + if (!DFISUINT01(dfl) || !DFISUINT01(dfr) + || !DFISCC01(dfl) || !DFISCC01(dfr)) return decInvalid(result, set); + // the operands are positive finite integers (q=0) with just 0s and 1s + #if DOUBLE + DFWORD(result, 0)=ZEROWORD + |((DFWORD(dfl, 0) | DFWORD(dfr, 0))&0x04009124); + DFWORD(result, 1)=(DFWORD(dfl, 1) | DFWORD(dfr, 1))&0x49124491; + #elif QUAD + DFWORD(result, 0)=ZEROWORD + |((DFWORD(dfl, 0) | DFWORD(dfr, 0))&0x04000912); + DFWORD(result, 1)=(DFWORD(dfl, 1) | DFWORD(dfr, 1))&0x44912449; + DFWORD(result, 2)=(DFWORD(dfl, 2) | DFWORD(dfr, 2))&0x12449124; + DFWORD(result, 3)=(DFWORD(dfl, 3) | DFWORD(dfr, 3))&0x49124491; + #endif + return result; + } // decFloatOr + +/* ------------------------------------------------------------------ */ +/* decFloatPlus -- add value to 0, heeding NaNs, etc. */ +/* */ +/* result gets the canonicalized 0+df */ +/* df is the decFloat to plus */ +/* set is the context */ +/* returns result */ +/* */ +/* This has the same effect as 0+df where the exponent of the zero is */ +/* the same as that of df (if df is finite). */ +/* The effect is also the same as decFloatCopy except that NaNs */ +/* are handled normally (the sign of a NaN is not affected, and an */ +/* sNaN will signal), the result is canonical, and zero gets sign 0. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatPlus(decFloat *result, const decFloat *df, + decContext *set) { + if (DFISNAN(df)) return decNaNs(result, df, NULL, set); + decCanonical(result, df); // copy and check + if (DFISZERO(df)) DFBYTE(result, 0)&=~0x80; // turn off sign bit + return result; + } // decFloatPlus + +/* ------------------------------------------------------------------ */ +/* decFloatQuantize -- quantize a decFloat */ +/* */ +/* result gets the result of quantizing dfl to match dfr */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs), which sets the exponent */ +/* set is the context */ +/* returns result */ +/* */ +/* Unless there is an error or the result is infinite, the exponent */ +/* of result is guaranteed to be the same as that of dfr. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatQuantize(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + Int explb, exprb; // left and right biased exponents + uByte *ulsd; // local LSD pointer + uByte *ub, *uc; // work + Int drop; // .. + uInt dpd; // .. + uInt encode; // encoding accumulator + uInt sourhil, sourhir; // top words from source decFloats + uInt uiwork; // for macros + #if QUAD + uShort uswork; // .. + #endif + // the following buffer holds the coefficient for manipulation + uByte buf[4+DECPMAX*3+2*QUAD]; // + space for zeros to left or right + #if DECTRACE + bcdnum num; // for trace displays + #endif + + /* Start decoding the arguments */ + sourhil=DFWORD(dfl, 0); // LHS top word + explb=DECCOMBEXP[sourhil>>26]; // get exponent high bits (in place) + sourhir=DFWORD(dfr, 0); // RHS top word + exprb=DECCOMBEXP[sourhir>>26]; + + if (EXPISSPECIAL(explb | exprb)) { // either is special? + // NaNs are handled as usual + if (DFISNAN(dfl) || DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set); + // one infinity but not both is bad + if (DFISINF(dfl)!=DFISINF(dfr)) return decInvalid(result, set); + // both infinite; return canonical infinity with sign of LHS + return decInfinity(result, dfl); + } + + /* Here when both arguments are finite */ + // complete extraction of the exponents [no need to unbias] + explb+=GETECON(dfl); // + continuation + exprb+=GETECON(dfr); // .. + + // calculate the number of digits to drop from the coefficient + drop=exprb-explb; // 0 if nothing to do + if (drop==0) return decCanonical(result, dfl); // return canonical + + // the coefficient is needed; lay it out into buf, offset so zeros + // can be added before or after as needed -- an extra heading is + // added so can safely pad Quad DECPMAX-1 zeros to the left by + // fours + #define BUFOFF (buf+4+DECPMAX) + GETCOEFF(dfl, BUFOFF); // decode from decFloat + // [now the msd is at BUFOFF and the lsd is at BUFOFF+DECPMAX-1] + + #if DECTRACE + num.msd=BUFOFF; + num.lsd=BUFOFF+DECPMAX-1; + num.exponent=explb-DECBIAS; + num.sign=sourhil & DECFLOAT_Sign; + decShowNum(&num, "dfl"); + #endif + + if (drop>0) { // [most common case] + // (this code is very similar to that in decFloatFinalize, but + // has many differences so is duplicated here -- so any changes + // may need to be made there, too) + uByte *roundat; // -> re-round digit + uByte reround; // reround value + // printf("Rounding; drop=%ld\n", (LI)drop); + + // there is at least one zero needed to the left, in all but one + // exceptional (all-nines) case, so place four zeros now; this is + // needed almost always and makes rounding all-nines by fours safe + UBFROMUI(BUFOFF-4, 0); + + // Three cases here: + // 1. new LSD is in coefficient (almost always) + // 2. new LSD is digit to left of coefficient (so MSD is + // round-for-reround digit) + // 3. new LSD is to left of case 2 (whole coefficient is sticky) + // Note that leading zeros can safely be treated as useful digits + + // [duplicate check-stickies code to save a test] + // [by-digit check for stickies as runs of zeros are rare] + if (dropstatus|=DEC_Inexact; + + // next decide whether to increment the coefficient + if (set->round==DEC_ROUND_HALF_EVEN) { // fastpath slowest case + if (reround>5) bump=1; // >0.5 goes up + else if (reround==5) // exactly 0.5000 .. + bump=*ulsd & 0x01; // .. up iff [new] lsd is odd + } // r-h-e + else switch (set->round) { + case DEC_ROUND_DOWN: { + // no change + break;} // r-d + case DEC_ROUND_HALF_DOWN: { + if (reround>5) bump=1; + break;} // r-h-d + case DEC_ROUND_HALF_UP: { + if (reround>=5) bump=1; + break;} // r-h-u + case DEC_ROUND_UP: { + if (reround>0) bump=1; + break;} // r-u + case DEC_ROUND_CEILING: { + // same as _UP for positive numbers, and as _DOWN for negatives + if (!(sourhil&DECFLOAT_Sign) && reround>0) bump=1; + break;} // r-c + case DEC_ROUND_FLOOR: { + // same as _UP for negative numbers, and as _DOWN for positive + // [negative reround cannot occur on 0] + if (sourhil&DECFLOAT_Sign && reround>0) bump=1; + break;} // r-f + case DEC_ROUND_05UP: { + if (reround>0) { // anything out there is 'sticky' + // bump iff lsd=0 or 5; this cannot carry so it could be + // effected immediately with no bump -- but the code + // is clearer if this is done the same way as the others + if (*ulsd==0 || *ulsd==5) bump=1; + } + break;} // r-r + default: { // e.g., DEC_ROUND_MAX + set->status|=DEC_Invalid_context; + #if DECCHECK + printf("Unknown rounding mode: %ld\n", (LI)set->round); + #endif + break;} + } // switch (not r-h-e) + // printf("ReRound: %ld bump: %ld\n", (LI)reround, (LI)bump); + + if (bump!=0) { // need increment + // increment the coefficient; this could give 1000... (after + // the all nines case) + ub=ulsd; + for (; UBTOUI(ub-3)==0x09090909; ub-=4) UBFROMUI(ub-3, 0); + // now at most 3 digits left to non-9 (usually just the one) + for (; *ub==9; ub--) *ub=0; + *ub+=1; + // [the all-nines case will have carried one digit to the + // left of the original MSD -- just where it is needed] + } // bump needed + } // inexact rounding + + // now clear zeros to the left so exactly DECPMAX digits will be + // available in the coefficent -- the first word to the left was + // cleared earlier for safe carry; now add any more needed + if (drop>4) { + UBFROMUI(BUFOFF-8, 0); // must be at least 5 + for (uc=BUFOFF-12; uc>ulsd-DECPMAX-3; uc-=4) UBFROMUI(uc, 0); + } + } // need round (drop>0) + + else { // drop<0; padding with -drop digits is needed + // This is the case where an error can occur if the padded + // coefficient will not fit; checking for this can be done in the + // same loop as padding for zeros if the no-hope and zero cases + // are checked first + if (-drop>DECPMAX-1) { // cannot fit unless 0 + if (!ISCOEFFZERO(BUFOFF)) return decInvalid(result, set); + // a zero can have any exponent; just drop through and use it + ulsd=BUFOFF+DECPMAX-1; + } + else { // padding will fit (but may still be too long) + // final-word mask depends on endianess + #if DECLITEND + static const uInt dmask[]={0, 0x000000ff, 0x0000ffff, 0x00ffffff}; + #else + static const uInt dmask[]={0, 0xff000000, 0xffff0000, 0xffffff00}; + #endif + // note that here zeros to the right are added by fours, so in + // the Quad case this could write 36 zeros if the coefficient has + // fewer than three significant digits (hence the +2*QUAD for buf) + for (uc=BUFOFF+DECPMAX;; uc+=4) { + UBFROMUI(uc, 0); + if (UBTOUI(uc-DECPMAX)!=0) { // could be bad + // if all four digits should be zero, definitely bad + if (uc<=BUFOFF+DECPMAX+(-drop)-4) + return decInvalid(result, set); + // must be a 1- to 3-digit sequence; check more carefully + if ((UBTOUI(uc-DECPMAX)&dmask[(-drop)%4])!=0) + return decInvalid(result, set); + break; // no need for loop end test + } + if (uc>=BUFOFF+DECPMAX+(-drop)-4) break; // done + } + ulsd=BUFOFF+DECPMAX+(-drop)-1; + } // pad and check leading zeros + } // drop<0 + + #if DECTRACE + num.msd=ulsd-DECPMAX+1; + num.lsd=ulsd; + num.exponent=explb-DECBIAS; + num.sign=sourhil & DECFLOAT_Sign; + decShowNum(&num, "res"); + #endif + + /*------------------------------------------------------------------*/ + /* At this point the result is DECPMAX digits, ending at ulsd, so */ + /* fits the encoding exactly; there is no possibility of error */ + /*------------------------------------------------------------------*/ + encode=((exprb>>DECECONL)<<4) + *(ulsd-DECPMAX+1); // make index + encode=DECCOMBFROM[encode]; // indexed by (0-2)*16+msd + // the exponent continuation can be extracted from the original RHS + encode|=sourhir & ECONMASK; + encode|=sourhil&DECFLOAT_Sign; // add the sign from LHS + + // finally encode the coefficient + // private macro to encode a declet; this version can be used + // because all coefficient digits exist + #define getDPD3q(dpd, n) ub=ulsd-(3*(n))-2; \ + dpd=BCD2DPD[(*ub*256)+(*(ub+1)*16)+*(ub+2)]; + + #if DOUBLE + getDPD3q(dpd, 4); encode|=dpd<<8; + getDPD3q(dpd, 3); encode|=dpd>>2; + DFWORD(result, 0)=encode; + encode=dpd<<30; + getDPD3q(dpd, 2); encode|=dpd<<20; + getDPD3q(dpd, 1); encode|=dpd<<10; + getDPD3q(dpd, 0); encode|=dpd; + DFWORD(result, 1)=encode; + + #elif QUAD + getDPD3q(dpd,10); encode|=dpd<<4; + getDPD3q(dpd, 9); encode|=dpd>>6; + DFWORD(result, 0)=encode; + encode=dpd<<26; + getDPD3q(dpd, 8); encode|=dpd<<16; + getDPD3q(dpd, 7); encode|=dpd<<6; + getDPD3q(dpd, 6); encode|=dpd>>4; + DFWORD(result, 1)=encode; + encode=dpd<<28; + getDPD3q(dpd, 5); encode|=dpd<<18; + getDPD3q(dpd, 4); encode|=dpd<<8; + getDPD3q(dpd, 3); encode|=dpd>>2; + DFWORD(result, 2)=encode; + encode=dpd<<30; + getDPD3q(dpd, 2); encode|=dpd<<20; + getDPD3q(dpd, 1); encode|=dpd<<10; + getDPD3q(dpd, 0); encode|=dpd; + DFWORD(result, 3)=encode; + #endif + return result; + } // decFloatQuantize + +/* ------------------------------------------------------------------ */ +/* decFloatReduce -- reduce finite coefficient to minimum length */ +/* */ +/* result gets the reduced decFloat */ +/* df is the source decFloat */ +/* set is the context */ +/* returns result, which will be canonical */ +/* */ +/* This removes all possible trailing zeros from the coefficient; */ +/* some may remain when the number is very close to Nmax. */ +/* Special values are unchanged and no status is set unless df=sNaN. */ +/* Reduced zero has an exponent q=0. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatReduce(decFloat *result, const decFloat *df, + decContext *set) { + bcdnum num; // work + uByte buf[DECPMAX], *ub; // coefficient and pointer + if (df!=result) *result=*df; // copy, if needed + if (DFISNAN(df)) return decNaNs(result, df, NULL, set); // sNaN + // zeros and infinites propagate too + if (DFISINF(df)) return decInfinity(result, df); // canonical + if (DFISZERO(df)) { + uInt sign=DFWORD(df, 0)&DECFLOAT_Sign; + decFloatZero(result); + DFWORD(result, 0)|=sign; + return result; // exponent dropped, sign OK + } + // non-zero finite + GETCOEFF(df, buf); + ub=buf+DECPMAX-1; // -> lsd + if (*ub) return result; // no trailing zeros + for (ub--; *ub==0;) ub--; // terminates because non-zero + // *ub is the first non-zero from the right + num.sign=DFWORD(df, 0)&DECFLOAT_Sign; // set up number... + num.exponent=GETEXPUN(df)+(Int)(buf+DECPMAX-1-ub); // adjusted exponent + num.msd=buf; + num.lsd=ub; + return decFinalize(result, &num, set); + } // decFloatReduce + +/* ------------------------------------------------------------------ */ +/* decFloatRemainder -- integer divide and return remainder */ +/* */ +/* result gets the remainder of dividing dfl by dfr: */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result */ +/* */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatRemainder(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + return decDivide(result, dfl, dfr, set, REMAINDER); + } // decFloatRemainder + +/* ------------------------------------------------------------------ */ +/* decFloatRemainderNear -- integer divide to nearest and remainder */ +/* */ +/* result gets the remainder of dividing dfl by dfr: */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result */ +/* */ +/* This is the IEEE remainder, where the nearest integer is used. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatRemainderNear(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + return decDivide(result, dfl, dfr, set, REMNEAR); + } // decFloatRemainderNear + +/* ------------------------------------------------------------------ */ +/* decFloatRotate -- rotate the coefficient of a decFloat left/right */ +/* */ +/* result gets the result of rotating dfl */ +/* dfl is the source decFloat to rotate */ +/* dfr is the count of digits to rotate, an integer (with q=0) */ +/* set is the context */ +/* returns result */ +/* */ +/* The digits of the coefficient of dfl are rotated to the left (if */ +/* dfr is positive) or to the right (if dfr is negative) without */ +/* adjusting the exponent or the sign of dfl. */ +/* */ +/* dfr must be in the range -DECPMAX through +DECPMAX. */ +/* NaNs are propagated as usual. An infinite dfl is unaffected (but */ +/* dfr must be valid). No status is set unless dfr is invalid or an */ +/* operand is an sNaN. The result is canonical. */ +/* ------------------------------------------------------------------ */ +#define PHALF (ROUNDUP(DECPMAX/2, 4)) // half length, rounded up +decFloat * decFloatRotate(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + Int rotate; // dfr as an Int + uByte buf[DECPMAX+PHALF]; // coefficient + half + uInt digits, savestat; // work + bcdnum num; // .. + uByte *ub; // .. + + if (DFISNAN(dfl)||DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set); + if (!DFISINT(dfr)) return decInvalid(result, set); + digits=decFloatDigits(dfr); // calculate digits + if (digits>2) return decInvalid(result, set); // definitely out of range + rotate=DPD2BIN[DFWORD(dfr, DECWORDS-1)&0x3ff]; // is in bottom declet + if (rotate>DECPMAX) return decInvalid(result, set); // too big + // [from here on no error or status change is possible] + if (DFISINF(dfl)) return decInfinity(result, dfl); // canonical + // handle no-rotate cases + if (rotate==0 || rotate==DECPMAX) return decCanonical(result, dfl); + // a real rotate is needed: 0 < rotate < DECPMAX + // reduce the rotation to no more than half to reduce copying later + // (for QUAD in fact half + 2 digits) + if (DFISSIGNED(dfr)) rotate=-rotate; + if (abs(rotate)>PHALF) { + if (rotate<0) rotate=DECPMAX+rotate; + else rotate=rotate-DECPMAX; + } + // now lay out the coefficient, leaving room to the right or the + // left depending on the direction of rotation + ub=buf; + if (rotate<0) ub+=PHALF; // rotate right, so space to left + GETCOEFF(dfl, ub); + // copy half the digits to left or right, and set num.msd + if (rotate<0) { + memcpy(buf, buf+DECPMAX, PHALF); + num.msd=buf+PHALF+rotate; + } + else { + memcpy(buf+DECPMAX, buf, PHALF); + num.msd=buf+rotate; + } + // fill in rest of num + num.lsd=num.msd+DECPMAX-1; + num.sign=DFWORD(dfl, 0)&DECFLOAT_Sign; + num.exponent=GETEXPUN(dfl); + savestat=set->status; // record + decFinalize(result, &num, set); + set->status=savestat; // restore + return result; + } // decFloatRotate + +/* ------------------------------------------------------------------ */ +/* decFloatSameQuantum -- test decFloats for same quantum */ +/* */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* returns 1 if the operands have the same quantum, 0 otherwise */ +/* */ +/* No error is possible and no status results. */ +/* ------------------------------------------------------------------ */ +uInt decFloatSameQuantum(const decFloat *dfl, const decFloat *dfr) { + if (DFISSPECIAL(dfl) || DFISSPECIAL(dfr)) { + if (DFISNAN(dfl) && DFISNAN(dfr)) return 1; + if (DFISINF(dfl) && DFISINF(dfr)) return 1; + return 0; // any other special mixture gives false + } + if (GETEXP(dfl)==GETEXP(dfr)) return 1; // biased exponents match + return 0; + } // decFloatSameQuantum + +/* ------------------------------------------------------------------ */ +/* decFloatScaleB -- multiply by a power of 10, as per 754 */ +/* */ +/* result gets the result of the operation */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs), am integer (with q=0) */ +/* set is the context */ +/* returns result */ +/* */ +/* This computes result=dfl x 10**dfr where dfr is an integer in the */ +/* range +/-2*(emax+pmax), typically resulting from LogB. */ +/* Underflow and Overflow (with Inexact) may occur. NaNs propagate */ +/* as usual. */ +/* ------------------------------------------------------------------ */ +#define SCALEBMAX 2*(DECEMAX+DECPMAX) // D=800, Q=12356 +decFloat * decFloatScaleB(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + uInt digits; // work + Int expr; // dfr as an Int + + if (DFISNAN(dfl)||DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set); + if (!DFISINT(dfr)) return decInvalid(result, set); + digits=decFloatDigits(dfr); // calculate digits + + #if DOUBLE + if (digits>3) return decInvalid(result, set); // definitely out of range + expr=DPD2BIN[DFWORD(dfr, 1)&0x3ff]; // must be in bottom declet + #elif QUAD + if (digits>5) return decInvalid(result, set); // definitely out of range + expr=DPD2BIN[DFWORD(dfr, 3)&0x3ff] // in bottom 2 declets .. + +DPD2BIN[(DFWORD(dfr, 3)>>10)&0x3ff]*1000; // .. + #endif + if (expr>SCALEBMAX) return decInvalid(result, set); // oops + // [from now on no error possible] + if (DFISINF(dfl)) return decInfinity(result, dfl); // canonical + if (DFISSIGNED(dfr)) expr=-expr; + // dfl is finite and expr is valid + *result=*dfl; // copy to target + return decFloatSetExponent(result, set, GETEXPUN(result)+expr); + } // decFloatScaleB + +/* ------------------------------------------------------------------ */ +/* decFloatShift -- shift the coefficient of a decFloat left or right */ +/* */ +/* result gets the result of shifting dfl */ +/* dfl is the source decFloat to shift */ +/* dfr is the count of digits to shift, an integer (with q=0) */ +/* set is the context */ +/* returns result */ +/* */ +/* The digits of the coefficient of dfl are shifted to the left (if */ +/* dfr is positive) or to the right (if dfr is negative) without */ +/* adjusting the exponent or the sign of dfl. */ +/* */ +/* dfr must be in the range -DECPMAX through +DECPMAX. */ +/* NaNs are propagated as usual. An infinite dfl is unaffected (but */ +/* dfr must be valid). No status is set unless dfr is invalid or an */ +/* operand is an sNaN. The result is canonical. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatShift(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + Int shift; // dfr as an Int + uByte buf[DECPMAX*2]; // coefficient + padding + uInt digits, savestat; // work + bcdnum num; // .. + uInt uiwork; // for macros + + if (DFISNAN(dfl)||DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set); + if (!DFISINT(dfr)) return decInvalid(result, set); + digits=decFloatDigits(dfr); // calculate digits + if (digits>2) return decInvalid(result, set); // definitely out of range + shift=DPD2BIN[DFWORD(dfr, DECWORDS-1)&0x3ff]; // is in bottom declet + if (shift>DECPMAX) return decInvalid(result, set); // too big + // [from here on no error or status change is possible] + + if (DFISINF(dfl)) return decInfinity(result, dfl); // canonical + // handle no-shift and all-shift (clear to zero) cases + if (shift==0) return decCanonical(result, dfl); + if (shift==DECPMAX) { // zero with sign + uByte sign=(uByte)(DFBYTE(dfl, 0)&0x80); // save sign bit + decFloatZero(result); // make +0 + DFBYTE(result, 0)=(uByte)(DFBYTE(result, 0)|sign); // and set sign + // [cannot safely use CopySign] + return result; + } + // a real shift is needed: 0 < shift < DECPMAX + num.sign=DFWORD(dfl, 0)&DECFLOAT_Sign; + num.exponent=GETEXPUN(dfl); + num.msd=buf; + GETCOEFF(dfl, buf); + if (DFISSIGNED(dfr)) { // shift right + // edge cases are taken care of, so this is easy + num.lsd=buf+DECPMAX-shift-1; + } + else { // shift left -- zero padding needed to right + UBFROMUI(buf+DECPMAX, 0); // 8 will handle most cases + UBFROMUI(buf+DECPMAX+4, 0); // .. + if (shift>8) memset(buf+DECPMAX+8, 0, 8+QUAD*18); // all other cases + num.msd+=shift; + num.lsd=num.msd+DECPMAX-1; + } + savestat=set->status; // record + decFinalize(result, &num, set); + set->status=savestat; // restore + return result; + } // decFloatShift + +/* ------------------------------------------------------------------ */ +/* decFloatSubtract -- subtract a decFloat from another */ +/* */ +/* result gets the result of subtracting dfr from dfl: */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result */ +/* */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatSubtract(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + decFloat temp; + // NaNs must propagate without sign change + if (DFISNAN(dfr)) return decFloatAdd(result, dfl, dfr, set); + temp=*dfr; // make a copy + DFBYTE(&temp, 0)^=0x80; // flip sign + return decFloatAdd(result, dfl, &temp, set); // and add to the lhs + } // decFloatSubtract + +/* ------------------------------------------------------------------ */ +/* decFloatToInt -- round to 32-bit binary integer (4 flavours) */ +/* */ +/* df is the decFloat to round */ +/* set is the context */ +/* round is the rounding mode to use */ +/* returns a uInt or an Int, rounded according to the name */ +/* */ +/* Invalid will always be signaled if df is a NaN, is Infinite, or is */ +/* outside the range of the target; Inexact will not be signaled for */ +/* simple rounding unless 'Exact' appears in the name. */ +/* ------------------------------------------------------------------ */ +uInt decFloatToUInt32(const decFloat *df, decContext *set, + enum rounding round) { + return decToInt32(df, set, round, 0, 1);} + +uInt decFloatToUInt32Exact(const decFloat *df, decContext *set, + enum rounding round) { + return decToInt32(df, set, round, 1, 1);} + +Int decFloatToInt32(const decFloat *df, decContext *set, + enum rounding round) { + return (Int)decToInt32(df, set, round, 0, 0);} + +Int decFloatToInt32Exact(const decFloat *df, decContext *set, + enum rounding round) { + return (Int)decToInt32(df, set, round, 1, 0);} + +/* ------------------------------------------------------------------ */ +/* decFloatToIntegral -- round to integral value (two flavours) */ +/* */ +/* result gets the result */ +/* df is the decFloat to round */ +/* set is the context */ +/* round is the rounding mode to use */ +/* returns result */ +/* */ +/* No exceptions, even Inexact, are raised except for sNaN input, or */ +/* if 'Exact' appears in the name. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatToIntegralValue(decFloat *result, const decFloat *df, + decContext *set, enum rounding round) { + return decToIntegral(result, df, set, round, 0);} + +decFloat * decFloatToIntegralExact(decFloat *result, const decFloat *df, + decContext *set) { + return decToIntegral(result, df, set, set->round, 1);} + +/* ------------------------------------------------------------------ */ +/* decFloatXor -- logical digitwise XOR of two decFloats */ +/* */ +/* result gets the result of XORing dfl and dfr */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) */ +/* set is the context */ +/* returns result, which will be canonical with sign=0 */ +/* */ +/* The operands must be positive, finite with exponent q=0, and */ +/* comprise just zeros and ones; if not, Invalid operation results. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatXor(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + if (!DFISUINT01(dfl) || !DFISUINT01(dfr) + || !DFISCC01(dfl) || !DFISCC01(dfr)) return decInvalid(result, set); + // the operands are positive finite integers (q=0) with just 0s and 1s + #if DOUBLE + DFWORD(result, 0)=ZEROWORD + |((DFWORD(dfl, 0) ^ DFWORD(dfr, 0))&0x04009124); + DFWORD(result, 1)=(DFWORD(dfl, 1) ^ DFWORD(dfr, 1))&0x49124491; + #elif QUAD + DFWORD(result, 0)=ZEROWORD + |((DFWORD(dfl, 0) ^ DFWORD(dfr, 0))&0x04000912); + DFWORD(result, 1)=(DFWORD(dfl, 1) ^ DFWORD(dfr, 1))&0x44912449; + DFWORD(result, 2)=(DFWORD(dfl, 2) ^ DFWORD(dfr, 2))&0x12449124; + DFWORD(result, 3)=(DFWORD(dfl, 3) ^ DFWORD(dfr, 3))&0x49124491; + #endif + return result; + } // decFloatXor + +/* ------------------------------------------------------------------ */ +/* decInvalid -- set Invalid_operation result */ +/* */ +/* result gets a canonical NaN */ +/* set is the context */ +/* returns result */ +/* */ +/* status has Invalid_operation added */ +/* ------------------------------------------------------------------ */ +static decFloat *decInvalid(decFloat *result, decContext *set) { + decFloatZero(result); + DFWORD(result, 0)=DECFLOAT_qNaN; + set->status|=DEC_Invalid_operation; + return result; + } // decInvalid + +/* ------------------------------------------------------------------ */ +/* decInfinity -- set canonical Infinity with sign from a decFloat */ +/* */ +/* result gets a canonical Infinity */ +/* df is source decFloat (only the sign is used) */ +/* returns result */ +/* */ +/* df may be the same as result */ +/* ------------------------------------------------------------------ */ +static decFloat *decInfinity(decFloat *result, const decFloat *df) { + uInt sign=DFWORD(df, 0); // save source signword + decFloatZero(result); // clear everything + DFWORD(result, 0)=DECFLOAT_Inf | (sign & DECFLOAT_Sign); + return result; + } // decInfinity + +/* ------------------------------------------------------------------ */ +/* decNaNs -- handle NaN argument(s) */ +/* */ +/* result gets the result of handling dfl and dfr, one or both of */ +/* which is a NaN */ +/* dfl is the first decFloat (lhs) */ +/* dfr is the second decFloat (rhs) -- may be NULL for a single- */ +/* operand operation */ +/* set is the context */ +/* returns result */ +/* */ +/* Called when one or both operands is a NaN, and propagates the */ +/* appropriate result to res. When an sNaN is found, it is changed */ +/* to a qNaN and Invalid operation is set. */ +/* ------------------------------------------------------------------ */ +static decFloat *decNaNs(decFloat *result, + const decFloat *dfl, const decFloat *dfr, + decContext *set) { + // handle sNaNs first + if (dfr!=NULL && DFISSNAN(dfr) && !DFISSNAN(dfl)) dfl=dfr; // use RHS + if (DFISSNAN(dfl)) { + decCanonical(result, dfl); // propagate canonical sNaN + DFWORD(result, 0)&=~(DECFLOAT_qNaN ^ DECFLOAT_sNaN); // quiet + set->status|=DEC_Invalid_operation; + return result; + } + // one or both is a quiet NaN + if (!DFISNAN(dfl)) dfl=dfr; // RHS must be NaN, use it + return decCanonical(result, dfl); // propagate canonical qNaN + } // decNaNs + +/* ------------------------------------------------------------------ */ +/* decNumCompare -- numeric comparison of two decFloats */ +/* */ +/* dfl is the left-hand decFloat, which is not a NaN */ +/* dfr is the right-hand decFloat, which is not a NaN */ +/* tot is 1 for total order compare, 0 for simple numeric */ +/* returns -1, 0, or +1 for dfldfr */ +/* */ +/* No error is possible; status and mode are unchanged. */ +/* ------------------------------------------------------------------ */ +static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) { + Int sigl, sigr; // LHS and RHS non-0 signums + Int shift; // shift needed to align operands + uByte *ub, *uc; // work + uInt uiwork; // for macros + // buffers +2 if Quad (36 digits), need double plus 4 for safe padding + uByte bufl[DECPMAX*2+QUAD*2+4]; // for LHS coefficient + padding + uByte bufr[DECPMAX*2+QUAD*2+4]; // for RHS coefficient + padding + + sigl=1; + if (DFISSIGNED(dfl)) { + if (!DFISSIGNED(dfr)) { // -LHS +RHS + if (DFISZERO(dfl) && DFISZERO(dfr) && !tot) return 0; + return -1; // RHS wins + } + sigl=-1; + } + if (DFISSIGNED(dfr)) { + if (!DFISSIGNED(dfl)) { // +LHS -RHS + if (DFISZERO(dfl) && DFISZERO(dfr) && !tot) return 0; + return +1; // LHS wins + } + } + + // signs are the same; operand(s) could be zero + sigr=-sigl; // sign to return if abs(RHS) wins + + if (DFISINF(dfl)) { + if (DFISINF(dfr)) return 0; // both infinite & same sign + return sigl; // inf > n + } + if (DFISINF(dfr)) return sigr; // n < inf [dfl is finite] + + // here, both are same sign and finite; calculate their offset + shift=GETEXP(dfl)-GETEXP(dfr); // [0 means aligned] + // [bias can be ignored -- the absolute exponent is not relevant] + + if (DFISZERO(dfl)) { + if (!DFISZERO(dfr)) return sigr; // LHS=0, RHS!=0 + // both are zero, return 0 if both same exponent or numeric compare + if (shift==0 || !tot) return 0; + if (shift>0) return sigl; + return sigr; // [shift<0] + } + else { // LHS!=0 + if (DFISZERO(dfr)) return sigl; // LHS!=0, RHS=0 + } + // both are known to be non-zero at this point + + // if the exponents are so different that the coefficients do not + // overlap (by even one digit) then a full comparison is not needed + if (abs(shift)>=DECPMAX) { // no overlap + // coefficients are known to be non-zero + if (shift>0) return sigl; + return sigr; // [shift<0] + } + + // decode the coefficients + // (shift both right two if Quad to make a multiple of four) + #if QUAD + UBFROMUI(bufl, 0); + UBFROMUI(bufr, 0); + #endif + GETCOEFF(dfl, bufl+QUAD*2); // decode from decFloat + GETCOEFF(dfr, bufr+QUAD*2); // .. + if (shift==0) { // aligned; common and easy + // all multiples of four, here + for (ub=bufl, uc=bufr; ub*uc) return sigl; // difference found + if (*ub<*uc) return sigr; // .. + } + } + } // aligned + else if (shift>0) { // lhs to left + ub=bufl; // RHS pointer + // pad bufl so right-aligned; most shifts will fit in 8 + UBFROMUI(bufl+DECPMAX+QUAD*2, 0); // add eight zeros + UBFROMUI(bufl+DECPMAX+QUAD*2+4, 0); // .. + if (shift>8) { + // more than eight; fill the rest, and also worth doing the + // lead-in by fours + uByte *up; // work + uByte *upend=bufl+DECPMAX+QUAD*2+shift; + for (up=bufl+DECPMAX+QUAD*2+8; upbufl+shift-4) break; + } + } + // check remaining leading digits + for (; ub*uc) return sigl; // difference found + if (*ub<*uc) return sigr; // .. + } + } // mismatch + if (uc==bufr+QUAD*2+DECPMAX-4) break; // all checked + } + } // shift>0 + + else { // shift<0) .. RHS is to left of LHS; mirror shift>0 + uc=bufr; // RHS pointer + // pad bufr so right-aligned; most shifts will fit in 8 + UBFROMUI(bufr+DECPMAX+QUAD*2, 0); // add eight zeros + UBFROMUI(bufr+DECPMAX+QUAD*2+4, 0); // .. + if (shift<-8) { + // more than eight; fill the rest, and also worth doing the + // lead-in by fours + uByte *up; // work + uByte *upend=bufr+DECPMAX+QUAD*2-shift; + for (up=bufr+DECPMAX+QUAD*2+8; upbufr-shift-4) break; + } + } + // check remaining leading digits + for (; uc*uc) return sigl; // difference found + if (*ub<*uc) return sigr; // .. + } + } // mismatch + if (ub==bufl+QUAD*2+DECPMAX-4) break; // all checked + } + } // shift<0 + + // Here when compare equal + if (!tot) return 0; // numerically equal + // total ordering .. exponent matters + if (shift>0) return sigl; // total order by exponent + if (shift<0) return sigr; // .. + return 0; + } // decNumCompare + +/* ------------------------------------------------------------------ */ +/* decToInt32 -- local routine to effect ToInteger conversions */ +/* */ +/* df is the decFloat to convert */ +/* set is the context */ +/* rmode is the rounding mode to use */ +/* exact is 1 if Inexact should be signalled */ +/* unsign is 1 if the result a uInt, 0 if an Int (cast to uInt) */ +/* returns 32-bit result as a uInt */ +/* */ +/* Invalid is set is df is a NaN, is infinite, or is out-of-range; in */ +/* these cases 0 is returned. */ +/* ------------------------------------------------------------------ */ +static uInt decToInt32(const decFloat *df, decContext *set, + enum rounding rmode, Flag exact, Flag unsign) { + Int exp; // exponent + uInt sourhi, sourpen, sourlo; // top word from source decFloat .. + uInt hi, lo; // .. penultimate, least, etc. + decFloat zero, result; // work + Int i; // .. + + /* Start decoding the argument */ + sourhi=DFWORD(df, 0); // top word + exp=DECCOMBEXP[sourhi>>26]; // get exponent high bits (in place) + if (EXPISSPECIAL(exp)) { // is special? + set->status|=DEC_Invalid_operation; // signal + return 0; + } + + /* Here when the argument is finite */ + if (GETEXPUN(df)==0) result=*df; // already a true integer + else { // need to round to integer + enum rounding saveround; // saver + uInt savestatus; // .. + saveround=set->round; // save rounding mode .. + savestatus=set->status; // .. and status + set->round=rmode; // set mode + decFloatZero(&zero); // make 0E+0 + set->status=0; // clear + decFloatQuantize(&result, df, &zero, set); // [this may fail] + set->round=saveround; // restore rounding mode .. + if (exact) set->status|=savestatus; // include Inexact + else set->status=savestatus; // .. or just original status + } + + // only the last four declets of the coefficient can contain + // non-zero; check for others (and also NaN or Infinity from the + // Quantize) first (see DFISZERO for explanation): + // decFloatShow(&result, "sofar"); + #if DOUBLE + if ((DFWORD(&result, 0)&0x1c03ff00)!=0 + || (DFWORD(&result, 0)&0x60000000)==0x60000000) { + #elif QUAD + if ((DFWORD(&result, 2)&0xffffff00)!=0 + || DFWORD(&result, 1)!=0 + || (DFWORD(&result, 0)&0x1c003fff)!=0 + || (DFWORD(&result, 0)&0x60000000)==0x60000000) { + #endif + set->status|=DEC_Invalid_operation; // Invalid or out of range + return 0; + } + // get last twelve digits of the coefficent into hi & ho, base + // 10**9 (see GETCOEFFBILL): + sourlo=DFWORD(&result, DECWORDS-1); + lo=DPD2BIN0[sourlo&0x3ff] + +DPD2BINK[(sourlo>>10)&0x3ff] + +DPD2BINM[(sourlo>>20)&0x3ff]; + sourpen=DFWORD(&result, DECWORDS-2); + hi=DPD2BIN0[((sourpen<<2) | (sourlo>>30))&0x3ff]; + + // according to request, check range carefully + if (unsign) { + if (hi>4 || (hi==4 && lo>294967295) || (hi+lo!=0 && DFISSIGNED(&result))) { + set->status|=DEC_Invalid_operation; // out of range + return 0; + } + return hi*BILLION+lo; + } + // signed + if (hi>2 || (hi==2 && lo>147483647)) { + // handle the usual edge case + if (lo==147483648 && hi==2 && DFISSIGNED(&result)) return 0x80000000; + set->status|=DEC_Invalid_operation; // truly out of range + return 0; + } + i=hi*BILLION+lo; + if (DFISSIGNED(&result)) i=-i; + return (uInt)i; + } // decToInt32 + +/* ------------------------------------------------------------------ */ +/* decToIntegral -- local routine to effect ToIntegral value */ +/* */ +/* result gets the result */ +/* df is the decFloat to round */ +/* set is the context */ +/* rmode is the rounding mode to use */ +/* exact is 1 if Inexact should be signalled */ +/* returns result */ +/* ------------------------------------------------------------------ */ +static decFloat * decToIntegral(decFloat *result, const decFloat *df, + decContext *set, enum rounding rmode, + Flag exact) { + Int exp; // exponent + uInt sourhi; // top word from source decFloat + enum rounding saveround; // saver + uInt savestatus; // .. + decFloat zero; // work + + /* Start decoding the argument */ + sourhi=DFWORD(df, 0); // top word + exp=DECCOMBEXP[sourhi>>26]; // get exponent high bits (in place) + + if (EXPISSPECIAL(exp)) { // is special? + // NaNs are handled as usual + if (DFISNAN(df)) return decNaNs(result, df, NULL, set); + // must be infinite; return canonical infinity with sign of df + return decInfinity(result, df); + } + + /* Here when the argument is finite */ + // complete extraction of the exponent + exp+=GETECON(df)-DECBIAS; // .. + continuation and unbias + + if (exp>=0) return decCanonical(result, df); // already integral + + saveround=set->round; // save rounding mode .. + savestatus=set->status; // .. and status + set->round=rmode; // set mode + decFloatZero(&zero); // make 0E+0 + decFloatQuantize(result, df, &zero, set); // 'integrate'; cannot fail + set->round=saveround; // restore rounding mode .. + if (!exact) set->status=savestatus; // .. and status, unless exact + return result; + } // decToIntegral diff --git a/src/decNumber/decCommon.c b/src/decNumber/decCommon.c new file mode 100644 index 0000000000..0825781bb1 --- /dev/null +++ b/src/decNumber/decCommon.c @@ -0,0 +1,1835 @@ +/* ------------------------------------------------------------------ */ +/* decCommon.c -- common code for all three fixed-size types */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is included in the package as decNumber.pdf. This */ +/* document is also available in HTML, together with specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ +/* This module comprises code that is shared between all the formats */ +/* (decSingle, decDouble, and decQuad); it includes set and extract */ +/* of format components, widening, narrowing, and string conversions. */ +/* */ +/* Unlike decNumber, parameterization takes place at compile time */ +/* rather than at runtime. The parameters are set in the decDouble.c */ +/* (etc.) files, which then include this one to produce the compiled */ +/* code. The functions here, therefore, are code shared between */ +/* multiple formats. */ +/* ------------------------------------------------------------------ */ +// Names here refer to decFloat rather than to decDouble, etc., and +// the functions are in strict alphabetical order. +// Constants, tables, and debug function(s) are included only for QUAD +// (which will always be compiled if DOUBLE or SINGLE are used). +// +// Whenever a decContext is used, only the status may be set (using +// OR) or the rounding mode read; all other fields are ignored and +// untouched. + +// names for simpler testing and default context +#if DECPMAX==7 + #define SINGLE 1 + #define DOUBLE 0 + #define QUAD 0 + #define DEFCONTEXT DEC_INIT_DECIMAL32 +#elif DECPMAX==16 + #define SINGLE 0 + #define DOUBLE 1 + #define QUAD 0 + #define DEFCONTEXT DEC_INIT_DECIMAL64 +#elif DECPMAX==34 + #define SINGLE 0 + #define DOUBLE 0 + #define QUAD 1 + #define DEFCONTEXT DEC_INIT_DECIMAL128 +#else + #error Unexpected DECPMAX value +#endif + +/* Assertions */ + +#if DECPMAX!=7 && DECPMAX!=16 && DECPMAX!=34 + #error Unexpected Pmax (DECPMAX) value for this module +#endif + +// Assert facts about digit characters, etc. +#if ('9'&0x0f)!=9 + #error This module assumes characters are of the form 0b....nnnn + // where .... are don't care 4 bits and nnnn is 0000 through 1001 +#endif +#if ('9'&0xf0)==('.'&0xf0) + #error This module assumes '.' has a different mask than a digit +#endif + +// Assert ToString lay-out conditions +#if DECSTRING DECSTRING + #error Exponent form can be too long for ToString to lay out safely +#endif +#if DECEMAXD > 4 + #error Exponent form is too long for ToString to lay out + // Note: code for up to 9 digits exists in archives [decOct] +#endif + +/* Private functions used here and possibly in decBasic.c, etc. */ +static decFloat * decFinalize(decFloat *, bcdnum *, decContext *); +static Flag decBiStr(const char *, const char *, const char *); + +/* Macros and private tables; those which are not format-dependent */ +/* are only included if decQuad is being built. */ + +/* ------------------------------------------------------------------ */ +/* Combination field lookup tables (uInts to save measurable work) */ +/* */ +/* DECCOMBEXP - 2 most-significant-bits of exponent (00, 01, or */ +/* 10), shifted left for format, or DECFLOAT_Inf/NaN */ +/* DECCOMBWEXP - The same, for the next-wider format (unless QUAD) */ +/* DECCOMBMSD - 4-bit most-significant-digit */ +/* [0 if the index is a special (Infinity or NaN)] */ +/* DECCOMBFROM - 5-bit combination field from EXP top bits and MSD */ +/* (placed in uInt so no shift is needed) */ +/* */ +/* DECCOMBEXP, DECCOMBWEXP, and DECCOMBMSD are indexed by the sign */ +/* and 5-bit combination field (0-63, the second half of the table */ +/* identical to the first half) */ +/* DECCOMBFROM is indexed by expTopTwoBits*16 + msd */ +/* */ +/* DECCOMBMSD and DECCOMBFROM are not format-dependent and so are */ +/* only included once, when QUAD is being built */ +/* ------------------------------------------------------------------ */ +static const uInt DECCOMBEXP[64]={ + 0, 0, 0, 0, 0, 0, 0, 0, + 1< DPD +#define DEC_BIN2DPD 1 // 0-999 -> DPD +#define DEC_BIN2BCD8 1 // 0-999 -> ddd, len +#define DEC_DPD2BCD8 1 // DPD -> ddd, len +#define DEC_DPD2BIN 1 // DPD -> 0-999 +#define DEC_DPD2BINK 1 // DPD -> 0-999000 +#define DEC_DPD2BINM 1 // DPD -> 0-999000000 +#include "decDPD.h" // source of the lookup tables + +#endif + +/* ----------------------------------------------------------------- */ +/* decBiStr -- compare string with pairwise options */ +/* */ +/* targ is the string to compare */ +/* str1 is one of the strings to compare against (length may be 0) */ +/* str2 is the other; it must be the same length as str1 */ +/* */ +/* returns 1 if strings compare equal, (that is, targ is the same */ +/* length as str1 and str2, and each character of targ is in one */ +/* of str1 or str2 in the corresponding position), or 0 otherwise */ +/* */ +/* This is used for generic caseless compare, including the awkward */ +/* case of the Turkish dotted and dotless Is. Use as (for example): */ +/* if (decBiStr(test, "mike", "MIKE")) ... */ +/* ----------------------------------------------------------------- */ +static Flag decBiStr(const char *targ, const char *str1, const char *str2) { + for (;;targ++, str1++, str2++) { + if (*targ!=*str1 && *targ!=*str2) return 0; + // *targ has a match in one (or both, if terminator) + if (*targ=='\0') break; + } // forever + return 1; + } // decBiStr + +/* ------------------------------------------------------------------ */ +/* decFinalize -- adjust and store a final result */ +/* */ +/* df is the decFloat format number which gets the final result */ +/* num is the descriptor of the number to be checked and encoded */ +/* [its values, including the coefficient, may be modified] */ +/* set is the context to use */ +/* returns df */ +/* */ +/* The num descriptor may point to a bcd8 string of any length; this */ +/* string may have leading insignificant zeros. If it has more than */ +/* DECPMAX digits then the final digit can be a round-for-reround */ +/* digit (i.e., it may include a sticky bit residue). */ +/* */ +/* The exponent (q) may be one of the codes for a special value and */ +/* can be up to 999999999 for conversion from string. */ +/* */ +/* No error is possible, but Inexact, Underflow, and/or Overflow may */ +/* be set. */ +/* ------------------------------------------------------------------ */ +// Constant whose size varies with format; also the check for surprises +static uByte allnines[DECPMAX]= +#if SINGLE + {9, 9, 9, 9, 9, 9, 9}; +#elif DOUBLE + {9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}; +#elif QUAD + {9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}; +#endif + +static decFloat * decFinalize(decFloat *df, bcdnum *num, + decContext *set) { + uByte *ub; // work + uInt dpd; // .. + uInt uiwork; // for macros + uByte *umsd=num->msd; // local copy + uByte *ulsd=num->lsd; // .. + uInt encode; // encoding accumulator + Int length; // coefficient length + + #if DECCHECK + Int clen=ulsd-umsd+1; + #if QUAD + #define COEXTRA 2 // extra-long coefficent + #else + #define COEXTRA 0 + #endif + if (clen<1 || clen>DECPMAX*3+2+COEXTRA) + printf("decFinalize: suspect coefficient [length=%ld]\n", (LI)clen); + if (num->sign!=0 && num->sign!=DECFLOAT_Sign) + printf("decFinalize: bad sign [%08lx]\n", (LI)num->sign); + if (!EXPISSPECIAL(num->exponent) + && (num->exponent>1999999999 || num->exponent<-1999999999)) + printf("decFinalize: improbable exponent [%ld]\n", (LI)num->exponent); + // decShowNum(num, "final"); + #endif + + // A special will have an 'exponent' which is very positive and a + // coefficient < DECPMAX + length=(uInt)(ulsd-umsd+1); // coefficient length + + if (!NUMISSPECIAL(num)) { + Int drop; // digits to be dropped + // skip leading insignificant zeros to calculate an exact length + // [this is quite expensive] + if (*umsd==0) { + for (; umsd+3exponent); + // drop can now be > digits for bottom-clamp (subnormal) cases + if (drop>0) { // rounding needed + // (decFloatQuantize has very similar code to this, so any + // changes may need to be made there, too) + uByte *roundat; // -> re-round digit + uByte reround; // reround value + // printf("Rounding; drop=%ld\n", (LI)drop); + + num->exponent+=drop; // always update exponent + + // Three cases here: + // 1. new LSD is in coefficient (almost always) + // 2. new LSD is digit to left of coefficient (so MSD is + // round-for-reround digit) + // 3. new LSD is to left of case 2 (whole coefficient is sticky) + // [duplicate check-stickies code to save a test] + // [by-digit check for stickies as runs of zeros are rare] + if (dropstatus|=DEC_Inexact; + // if adjusted exponent [exp+digits-1] is < EMIN then num is + // subnormal -- so raise Underflow + if (num->exponentexponent+(ulsd-umsd+1)-1)status|=DEC_Underflow; + + // next decide whether increment of the coefficient is needed + if (set->round==DEC_ROUND_HALF_EVEN) { // fastpath slowest case + if (reround>5) bump=1; // >0.5 goes up + else if (reround==5) // exactly 0.5000 .. + bump=*ulsd & 0x01; // .. up iff [new] lsd is odd + } // r-h-e + else switch (set->round) { + case DEC_ROUND_DOWN: { + // no change + break;} // r-d + case DEC_ROUND_HALF_DOWN: { + if (reround>5) bump=1; + break;} // r-h-d + case DEC_ROUND_HALF_UP: { + if (reround>=5) bump=1; + break;} // r-h-u + case DEC_ROUND_UP: { + if (reround>0) bump=1; + break;} // r-u + case DEC_ROUND_CEILING: { + // same as _UP for positive numbers, and as _DOWN for negatives + if (!num->sign && reround>0) bump=1; + break;} // r-c + case DEC_ROUND_FLOOR: { + // same as _UP for negative numbers, and as _DOWN for positive + // [negative reround cannot occur on 0] + if (num->sign && reround>0) bump=1; + break;} // r-f + case DEC_ROUND_05UP: { + if (reround>0) { // anything out there is 'sticky' + // bump iff lsd=0 or 5; this cannot carry so it could be + // effected immediately with no bump -- but the code + // is clearer if this is done the same way as the others + if (*ulsd==0 || *ulsd==5) bump=1; + } + break;} // r-r + default: { // e.g., DEC_ROUND_MAX + set->status|=DEC_Invalid_context; + #if DECCHECK + printf("Unknown rounding mode: %ld\n", (LI)set->round); + #endif + break;} + } // switch (not r-h-e) + // printf("ReRound: %ld bump: %ld\n", (LI)reround, (LI)bump); + + if (bump!=0) { // need increment + // increment the coefficient; this might end up with 1000... + // (after the all nines case) + ub=ulsd; + for(; ub-3>=umsd && UBTOUI(ub-3)==0x09090909; ub-=4) { + UBFROMUI(ub-3, 0); // to 00000000 + } + // [note ub could now be to left of msd, and it is not safe + // to write to the the left of the msd] + // now at most 3 digits left to non-9 (usually just the one) + for (; ub>=umsd; *ub=0, ub--) { + if (*ub==9) continue; // carry + *ub+=1; + break; + } + if (ubexponent++; + } + else { + // if coefficient is shorter than Pmax then num is + // subnormal, so extend it; this is safe as drop>0 + // (or, if the coefficient was supplied above, it could + // not be 9); this may make the result normal. + ulsd++; + *ulsd=0; + // [exponent unchanged] + #if DECCHECK + if (num->exponent!=DECQTINY) // sanity check + printf("decFinalize: bad all-nines extend [^%ld, %ld]\n", + (LI)num->exponent, (LI)(ulsd-umsd+1)); + #endif + } // subnormal extend + } // had all-nines + } // bump needed + } // inexact rounding + + length=ulsd-umsd+1; // recalculate (may be 0) + + // The coefficient will now fit and has final length unless overflow + // decShowNum(num, "rounded"); + + // if exponent is >=emax may have to clamp, overflow, or fold-down + if (num->exponent>DECEMAX-(DECPMAX-1)) { // is edge case + // printf("overflow checks...\n"); + if (*ulsd==0 && ulsd==umsd) { // have zero + num->exponent=DECEMAX-(DECPMAX-1); // clamp to max + } + else if ((num->exponent+length-1)>DECEMAX) { // > Nmax + // Overflow -- these could go straight to encoding, here, but + // instead num is adjusted to keep the code cleaner + Flag needmax=0; // 1 for finite result + set->status|=(DEC_Overflow | DEC_Inexact); + switch (set->round) { + case DEC_ROUND_DOWN: { + needmax=1; // never Infinity + break;} // r-d + case DEC_ROUND_05UP: { + needmax=1; // never Infinity + break;} // r-05 + case DEC_ROUND_CEILING: { + if (num->sign) needmax=1; // Infinity iff non-negative + break;} // r-c + case DEC_ROUND_FLOOR: { + if (!num->sign) needmax=1; // Infinity iff negative + break;} // r-f + default: break; // Infinity in all other cases + } + if (!needmax) { // easy .. set Infinity + num->exponent=DECFLOAT_Inf; + *umsd=0; // be clean: coefficient to 0 + ulsd=umsd; // .. + } + else { // return Nmax + umsd=allnines; // use constant array + ulsd=allnines+DECPMAX-1; + num->exponent=DECEMAX-(DECPMAX-1); + } + } + else { // no overflow but non-zero and may have to fold-down + Int shift=num->exponent-(DECEMAX-(DECPMAX-1)); + if (shift>0) { // fold-down needed + // fold down needed; must copy to buffer in order to pad + // with zeros safely; fortunately this is not the worst case + // path because cannot have had a round + uByte buffer[ROUNDUP(DECPMAX+3, 4)]; // [+3 allows uInt padding] + uByte *s=umsd; // source + uByte *t=buffer; // safe target + uByte *tlsd=buffer+(ulsd-umsd)+shift; // target LSD + // printf("folddown shift=%ld\n", (LI)shift); + for (; s<=ulsd; s+=4, t+=4) UBFROMUI(t, UBTOUI(s)); + for (t=tlsd-shift+1; t<=tlsd; t+=4) UBFROMUI(t, 0); // pad 0s + num->exponent-=shift; + umsd=buffer; + ulsd=tlsd; + } + } // fold-down? + length=ulsd-umsd+1; // recalculate length + } // high-end edge case + } // finite number + + /*------------------------------------------------------------------*/ + /* At this point the result will properly fit the decFloat */ + /* encoding, and it can be encoded with no possibility of error */ + /*------------------------------------------------------------------*/ + // Following code does not alter coefficient (could be allnines array) + + // fast path possible when DECPMAX digits + if (length==DECPMAX) { + return decFloatFromBCD(df, num->exponent, umsd, num->sign); + } // full-length + + // slower path when not a full-length number; must care about length + // [coefficient length here will be < DECPMAX] + if (!NUMISSPECIAL(num)) { // is still finite + // encode the combination field and exponent continuation + uInt uexp=(uInt)(num->exponent+DECBIAS); // biased exponent + uInt code=(uexp>>DECECONL)<<4; // top two bits of exp + // [msd==0] + // look up the combination field and make high word + encode=DECCOMBFROM[code]; // indexed by (0-2)*16+msd + encode|=(uexp<<(32-6-DECECONL)) & 0x03ffffff; // exponent continuation + } + else encode=num->exponent; // special [already in word] + encode|=num->sign; // add sign + + // private macro to extract a declet, n (where 0<=n=umsd) dpd=BCD2DPD[(*ub*256)+(*(ub+1)*16)+*(ub+2)]; \ + else {dpd=*(ub+2); if (ub+1==umsd) dpd+=*(ub+1)*16; dpd=BCD2DPD[dpd];} + + // place the declets in the encoding words and copy to result (df), + // according to endianness; in all cases complete the sign word + // first + #if DECPMAX==7 + getDPDt(dpd, 1); + encode|=dpd<<10; + getDPDt(dpd, 0); + encode|=dpd; + DFWORD(df, 0)=encode; // just the one word + + #elif DECPMAX==16 + getDPDt(dpd, 4); encode|=dpd<<8; + getDPDt(dpd, 3); encode|=dpd>>2; + DFWORD(df, 0)=encode; + encode=dpd<<30; + getDPDt(dpd, 2); encode|=dpd<<20; + getDPDt(dpd, 1); encode|=dpd<<10; + getDPDt(dpd, 0); encode|=dpd; + DFWORD(df, 1)=encode; + + #elif DECPMAX==34 + getDPDt(dpd,10); encode|=dpd<<4; + getDPDt(dpd, 9); encode|=dpd>>6; + DFWORD(df, 0)=encode; + + encode=dpd<<26; + getDPDt(dpd, 8); encode|=dpd<<16; + getDPDt(dpd, 7); encode|=dpd<<6; + getDPDt(dpd, 6); encode|=dpd>>4; + DFWORD(df, 1)=encode; + + encode=dpd<<28; + getDPDt(dpd, 5); encode|=dpd<<18; + getDPDt(dpd, 4); encode|=dpd<<8; + getDPDt(dpd, 3); encode|=dpd>>2; + DFWORD(df, 2)=encode; + + encode=dpd<<30; + getDPDt(dpd, 2); encode|=dpd<<20; + getDPDt(dpd, 1); encode|=dpd<<10; + getDPDt(dpd, 0); encode|=dpd; + DFWORD(df, 3)=encode; + #endif + + // printf("Status: %08lx\n", (LI)set->status); + // decFloatShow(df, "final2"); + return df; + } // decFinalize + +/* ------------------------------------------------------------------ */ +/* decFloatFromBCD -- set decFloat from exponent, BCD8, and sign */ +/* */ +/* df is the target decFloat */ +/* exp is the in-range unbiased exponent, q, or a special value in */ +/* the form returned by decFloatGetExponent */ +/* bcdar holds DECPMAX digits to set the coefficient from, one */ +/* digit in each byte (BCD8 encoding); the first (MSD) is ignored */ +/* if df is a NaN; all are ignored if df is infinite. */ +/* All bytes must be in 0-9; results are undefined otherwise. */ +/* sig is DECFLOAT_Sign to set the sign bit, 0 otherwise */ +/* returns df, which will be canonical */ +/* */ +/* No error is possible, and no status will be set. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatFromBCD(decFloat *df, Int exp, const uByte *bcdar, + Int sig) { + uInt encode, dpd; // work + const uByte *ub; // .. + + if (EXPISSPECIAL(exp)) encode=exp|sig;// specials already encoded + else { // is finite + // encode the combination field and exponent continuation + uInt uexp=(uInt)(exp+DECBIAS); // biased exponent + uInt code=(uexp>>DECECONL)<<4; // top two bits of exp + code+=bcdar[0]; // add msd + // look up the combination field and make high word + encode=DECCOMBFROM[code]|sig; // indexed by (0-2)*16+msd + encode|=(uexp<<(32-6-DECECONL)) & 0x03ffffff; // exponent continuation + } + + // private macro to extract a declet, n (where 0<=n>2; + DFWORD(df, 0)=encode; + encode=dpd<<30; + getDPDb(dpd, 2); encode|=dpd<<20; + getDPDb(dpd, 1); encode|=dpd<<10; + getDPDb(dpd, 0); encode|=dpd; + DFWORD(df, 1)=encode; + + #elif DECPMAX==34 + getDPDb(dpd,10); encode|=dpd<<4; + getDPDb(dpd, 9); encode|=dpd>>6; + DFWORD(df, 0)=encode; + + encode=dpd<<26; + getDPDb(dpd, 8); encode|=dpd<<16; + getDPDb(dpd, 7); encode|=dpd<<6; + getDPDb(dpd, 6); encode|=dpd>>4; + DFWORD(df, 1)=encode; + + encode=dpd<<28; + getDPDb(dpd, 5); encode|=dpd<<18; + getDPDb(dpd, 4); encode|=dpd<<8; + getDPDb(dpd, 3); encode|=dpd>>2; + DFWORD(df, 2)=encode; + + encode=dpd<<30; + getDPDb(dpd, 2); encode|=dpd<<20; + getDPDb(dpd, 1); encode|=dpd<<10; + getDPDb(dpd, 0); encode|=dpd; + DFWORD(df, 3)=encode; + #endif + // decFloatShow(df, "fromB"); + return df; + } // decFloatFromBCD + +/* ------------------------------------------------------------------ */ +/* decFloatFromPacked -- set decFloat from exponent and packed BCD */ +/* */ +/* df is the target decFloat */ +/* exp is the in-range unbiased exponent, q, or a special value in */ +/* the form returned by decFloatGetExponent */ +/* packed holds DECPMAX packed decimal digits plus a sign nibble */ +/* (all 6 codes are OK); the first (MSD) is ignored if df is a NaN */ +/* and all except sign are ignored if df is infinite. For DOUBLE */ +/* and QUAD the first (pad) nibble is also ignored in all cases. */ +/* All coefficient nibbles must be in 0-9 and sign in A-F; results */ +/* are undefined otherwise. */ +/* returns df, which will be canonical */ +/* */ +/* No error is possible, and no status will be set. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatFromPacked(decFloat *df, Int exp, const uByte *packed) { + uByte bcdar[DECPMAX+2]; // work [+1 for pad, +1 for sign] + const uByte *ip; // .. + uByte *op; // .. + Int sig=0; // sign + + // expand coefficient and sign to BCDAR + #if SINGLE + op=bcdar+1; // no pad digit + #else + op=bcdar; // first (pad) digit ignored + #endif + for (ip=packed; ip>4; + *op++=(uByte)(*ip&0x0f); // [final nibble is sign] + } + op--; // -> sign byte + if (*op==DECPMINUS || *op==DECPMINUSALT) sig=DECFLOAT_Sign; + + if (EXPISSPECIAL(exp)) { // Infinity or NaN + if (!EXPISINF(exp)) bcdar[1]=0; // a NaN: ignore MSD + else memset(bcdar+1, 0, DECPMAX); // Infinite: coefficient to 0 + } + return decFloatFromBCD(df, exp, bcdar+1, sig); + } // decFloatFromPacked + +/* ------------------------------------------------------------------ */ +/* decFloatFromPackedChecked -- set from exponent and packed; checked */ +/* */ +/* df is the target decFloat */ +/* exp is the in-range unbiased exponent, q, or a special value in */ +/* the form returned by decFloatGetExponent */ +/* packed holds DECPMAX packed decimal digits plus a sign nibble */ +/* (all 6 codes are OK); the first (MSD) must be 0 if df is a NaN */ +/* and all digits must be 0 if df is infinite. For DOUBLE and */ +/* QUAD the first (pad) nibble must be 0. */ +/* All coefficient nibbles must be in 0-9 and sign in A-F. */ +/* returns df, which will be canonical or NULL if any of the */ +/* requirements are not met (if this case df is unchanged); that */ +/* is, the input data must be as returned by decFloatToPacked, */ +/* except that all six sign codes are acccepted. */ +/* */ +/* No status will be set. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatFromPackedChecked(decFloat *df, Int exp, + const uByte *packed) { + uByte bcdar[DECPMAX+2]; // work [+1 for pad, +1 for sign] + const uByte *ip; // .. + uByte *op; // .. + Int sig=0; // sign + + // expand coefficient and sign to BCDAR + #if SINGLE + op=bcdar+1; // no pad digit + #else + op=bcdar; // first (pad) digit here + #endif + for (ip=packed; ip>4; + if (*op>9) return NULL; + op++; + *op=(uByte)(*ip&0x0f); // [final nibble is sign] + if (*op>9 && ip sign byte + if (*op<=9) return NULL; // bad sign + if (*op==DECPMINUS || *op==DECPMINUSALT) sig=DECFLOAT_Sign; + + #if !SINGLE + if (bcdar[0]!=0) return NULL; // bad pad nibble + #endif + + if (EXPISNAN(exp)) { // a NaN + if (bcdar[1]!=0) return NULL; // bad msd + } // NaN + else if (EXPISINF(exp)) { // is infinite + Int i; + for (i=0; iDECEMAX-DECPMAX+1) return NULL; + if (exp first character of decimal part + const char *c; // work + uByte *ub; // .. + uInt uiwork; // for macros + bcdnum num; // collects data for finishing + uInt error=DEC_Conversion_syntax; // assume the worst + uByte buffer[ROUNDUP(DECSTRING+11, 8)]; // room for most coefficents, + // some common rounding, +3, & pad + #if DECTRACE + // printf("FromString %s ...\n", string); + #endif + + for(;;) { // once-only 'loop' + num.sign=0; // assume non-negative + num.msd=buffer; // MSD is here always + + // detect and validate the coefficient, including any leading, + // trailing, or embedded '.' + // [could test four-at-a-time here (saving 10% for decQuads), + // but that risks storage violation because the position of the + // terminator is unknown] + for (c=string;; c++) { // -> input character + if (((unsigned)(*c-'0'))<=9) continue; // '0' through '9' is good + if (*c=='\0') break; // most common non-digit + if (*c=='.') { + if (dotchar!=NULL) break; // not first '.' + dotchar=c; // record offset into decimal part + continue;} + if (c==string) { // first in string... + if (*c=='-') { // valid - sign + cfirst++; + num.sign=DECFLOAT_Sign; + continue;} + if (*c=='+') { // valid + sign + cfirst++; + continue;} + } + // *c is not a digit, terminator, or a valid +, -, or '.' + break; + } // c loop + + digits=(uInt)(c-cfirst); // digits (+1 if a dot) + + if (digits>0) { // had digits and/or dot + const char *clast=c-1; // note last coefficient char position + Int exp=0; // exponent accumulator + if (*c!='\0') { // something follows the coefficient + uInt edig; // unsigned work + // had some digits and more to come; expect E[+|-]nnn now + const char *firstexp; // exponent first non-zero + if (*c!='E' && *c!='e') break; + c++; // to (optional) sign + if (*c=='-' || *c=='+') c++; // step over sign (c=clast+2) + if (*c=='\0') break; // no digits! (e.g., '1.2E') + for (; *c=='0';) c++; // skip leading zeros [even last] + firstexp=c; // remember start [maybe '\0'] + // gather exponent digits + edig=(uInt)*c-(uInt)'0'; + if (edig<=9) { // [check not bad or terminator] + exp+=edig; // avoid initial X10 + c++; + for (;; c++) { + edig=(uInt)*c-(uInt)'0'; + if (edig>9) break; + exp=exp*10+edig; + } + } + // if not now on the '\0', *c must not be a digit + if (*c!='\0') break; + + // (this next test must be after the syntax checks) + // if definitely more than the possible digits for format then + // the exponent may have wrapped, so simply set it to a certain + // over/underflow value + if (c>firstexp+DECEMAXD) exp=DECEMAX*2; + if (*(clast+2)=='-') exp=-exp; // was negative + } // exponent part + + if (dotchar!=NULL) { // had a '.' + digits--; // remove from digits count + if (digits==0) break; // was dot alone: bad syntax + exp-=(Int)(clast-dotchar); // adjust exponent + // [the '.' can now be ignored] + } + num.exponent=exp; // exponent is good; store it + + // Here when whole string has been inspected and syntax is good + // cfirst->first digit or dot, clast->last digit or dot + error=0; // no error possible now + + // if the number of digits in the coefficient will fit in buffer + // then it can simply be converted to bcd8 and copied -- decFinalize + // will take care of leading zeros and rounding; the buffer is big + // enough for all canonical coefficients, including 0.00000nn... + ub=buffer; + if (digits<=(Int)(sizeof(buffer)-3)) { // [-3 allows by-4s copy] + c=cfirst; + if (dotchar!=NULL) { // a dot to worry about + if (*(c+1)=='.') { // common canonical case + *ub++=(uByte)(*c-'0'); // copy leading digit + c+=2; // prepare to handle rest + } + else for (; c<=clast;) { // '.' could be anywhere + // as usual, go by fours when safe; NB it has been asserted + // that a '.' does not have the same mask as a digit + if (c<=clast-3 // safe for four + && (UBTOUI(c)&0xf0f0f0f0)==CHARMASK) { // test four + UBFROMUI(ub, UBTOUI(c)&0x0f0f0f0f); // to BCD8 + ub+=4; + c+=4; + continue; + } + if (*c=='.') { // found the dot + c++; // step over it .. + break; // .. and handle the rest + } + *ub++=(uByte)(*c++-'0'); + } + } // had dot + // Now no dot; do this by fours (where safe) + for (; c<=clast-3; c+=4, ub+=4) UBFROMUI(ub, UBTOUI(c)&0x0f0f0f0f); + for (; c<=clast; c++, ub++) *ub=(uByte)(*c-'0'); + num.lsd=buffer+digits-1; // record new LSD + } // fits + + else { // too long for buffer + // [This is a rare and unusual case; arbitrary-length input] + // strip leading zeros [but leave final 0 if all 0's] + if (*cfirst=='.') cfirst++; // step past dot at start + if (*cfirst=='0') { // [cfirst always -> digit] + for (; cfirst LSD + for (; c<=clast; c++) { // inspect remaining chars + if (*c!='0') { // sticky bit needed + if (*c=='.') continue; // [ignore] + *ub=DECSTICKYTAB[*ub]; // update round-for-reround + break; // no need to look at more + } + } + num.lsd=ub; // record LSD + // adjust exponent for dropped digits + num.exponent+=digits-(Int)(ub-buffer+1); + } // too long for buffer + } // digits and/or dot + + else { // no digits or dot were found + // only Infinities and NaNs are allowed, here + if (*c=='\0') break; // nothing there is bad + buffer[0]=0; // default a coefficient of 0 + num.lsd=buffer; // .. + if (decBiStr(c, "infinity", "INFINITY") + || decBiStr(c, "inf", "INF")) num.exponent=DECFLOAT_Inf; + else { // should be a NaN + num.exponent=DECFLOAT_qNaN; // assume quiet NaN + if (*c=='s' || *c=='S') { // probably an sNaN + num.exponent=DECFLOAT_sNaN; // effect the 's' + c++; // and step over it + } + if (*c!='N' && *c!='n') break; // check caseless "NaN" + c++; + if (*c!='a' && *c!='A') break; // .. + c++; + if (*c!='N' && *c!='n') break; // .. + c++; + // now either nothing, or nnnn payload (no dots), expected + // -> start of integer, and skip leading 0s [including plain 0] + for (cfirst=c; *cfirst=='0';) cfirst++; + if (*cfirst!='\0') { // not empty or all-0, payload + // payload found; check all valid digits and copy to buffer as bcd8 + ub=buffer; + for (c=cfirst;; c++, ub++) { + if ((unsigned)(*c-'0')>9) break; // quit if not 0-9 + if (c-cfirst==DECPMAX-1) break; // too many digits + *ub=(uByte)(*c-'0'); // good bcd8 + } + if (*c!='\0') break; // not all digits, or too many + num.lsd=ub-1; // record new LSD + } + } // NaN or sNaN + error=0; // syntax is OK + } // digits=0 (special expected) + break; // drop out + } // [for(;;) once-loop] + + // decShowNum(&num, "fromStr"); + + if (error!=0) { + set->status|=error; + num.exponent=DECFLOAT_qNaN; // set up quiet NaN + num.sign=0; // .. with 0 sign + buffer[0]=0; // .. and coefficient + num.lsd=buffer; // .. + // decShowNum(&num, "oops"); + } + + // decShowNum(&num, "dffs"); + decFinalize(result, &num, set); // round, check, and lay out + // decFloatShow(result, "fromString"); + return result; + } // decFloatFromString + +/* ------------------------------------------------------------------ */ +/* decFloatFromWider -- conversion from next-wider format */ +/* */ +/* result is the decFloat format number which gets the result of */ +/* the conversion */ +/* wider is the decFloatWider format number which will be narrowed */ +/* set is the context */ +/* returns result */ +/* */ +/* Narrowing can cause rounding, overflow, etc., but not Invalid */ +/* operation (sNaNs are copied and do not signal). */ +/* ------------------------------------------------------------------ */ +// narrow-to is not possible for decQuad format numbers; simply omit +#if !QUAD +decFloat * decFloatFromWider(decFloat *result, const decFloatWider *wider, + decContext *set) { + bcdnum num; // collects data for finishing + uByte bcdar[DECWPMAX]; // room for wider coefficient + uInt widerhi=DFWWORD(wider, 0); // top word + Int exp; + + GETWCOEFF(wider, bcdar); + + num.msd=bcdar; // MSD is here always + num.lsd=bcdar+DECWPMAX-1; // LSD is here always + num.sign=widerhi&0x80000000; // extract sign [DECFLOAT_Sign=Neg] + + // decode the wider combination field to exponent + exp=DECCOMBWEXP[widerhi>>26]; // decode from wider combination field + // if it is a special there's nothing to do unless sNaN; if it's + // finite then add the (wider) exponent continuation and unbias + if (EXPISSPECIAL(exp)) exp=widerhi&0x7e000000; // include sNaN selector + else exp+=GETWECON(wider)-DECWBIAS; + num.exponent=exp; + + // decShowNum(&num, "dffw"); + return decFinalize(result, &num, set);// round, check, and lay out + } // decFloatFromWider +#endif + +/* ------------------------------------------------------------------ */ +/* decFloatGetCoefficient -- get coefficient as BCD8 */ +/* */ +/* df is the decFloat from which to extract the coefficient */ +/* bcdar is where DECPMAX bytes will be written, one BCD digit in */ +/* each byte (BCD8 encoding); if df is a NaN the first byte will */ +/* be zero, and if it is infinite they will all be zero */ +/* returns the sign of the coefficient (DECFLOAT_Sign if negative, */ +/* 0 otherwise) */ +/* */ +/* No error is possible, and no status will be set. If df is a */ +/* special value the array is set to zeros (for Infinity) or to the */ +/* payload of a qNaN or sNaN. */ +/* ------------------------------------------------------------------ */ +Int decFloatGetCoefficient(const decFloat *df, uByte *bcdar) { + if (DFISINF(df)) memset(bcdar, 0, DECPMAX); + else { + GETCOEFF(df, bcdar); // use macro + if (DFISNAN(df)) bcdar[0]=0; // MSD needs correcting + } + return GETSIGN(df); + } // decFloatGetCoefficient + +/* ------------------------------------------------------------------ */ +/* decFloatGetExponent -- get unbiased exponent */ +/* */ +/* df is the decFloat from which to extract the exponent */ +/* returns the exponent, q. */ +/* */ +/* No error is possible, and no status will be set. If df is a */ +/* special value the first seven bits of the decFloat are returned, */ +/* left adjusted and with the first (sign) bit set to 0 (followed by */ +/* 25 0 bits). e.g., -sNaN would return 0x7e000000 (DECFLOAT_sNaN). */ +/* ------------------------------------------------------------------ */ +Int decFloatGetExponent(const decFloat *df) { + if (DFISSPECIAL(df)) return DFWORD(df, 0)&0x7e000000; + return GETEXPUN(df); + } // decFloatGetExponent + +/* ------------------------------------------------------------------ */ +/* decFloatSetCoefficient -- set coefficient from BCD8 */ +/* */ +/* df is the target decFloat (and source of exponent/special value) */ +/* bcdar holds DECPMAX digits to set the coefficient from, one */ +/* digit in each byte (BCD8 encoding); the first (MSD) is ignored */ +/* if df is a NaN; all are ignored if df is infinite. */ +/* sig is DECFLOAT_Sign to set the sign bit, 0 otherwise */ +/* returns df, which will be canonical */ +/* */ +/* No error is possible, and no status will be set. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatSetCoefficient(decFloat *df, const uByte *bcdar, + Int sig) { + uInt exp; // for exponent + uByte bcdzero[DECPMAX]; // for infinities + + // Exponent/special code is extracted from df + if (DFISSPECIAL(df)) { + exp=DFWORD(df, 0)&0x7e000000; + if (DFISINF(df)) { + memset(bcdzero, 0, DECPMAX); + return decFloatFromBCD(df, exp, bcdzero, sig); + } + } + else exp=GETEXPUN(df); + return decFloatFromBCD(df, exp, bcdar, sig); + } // decFloatSetCoefficient + +/* ------------------------------------------------------------------ */ +/* decFloatSetExponent -- set exponent or special value */ +/* */ +/* df is the target decFloat (and source of coefficient/payload) */ +/* set is the context for reporting status */ +/* exp is the unbiased exponent, q, or a special value in the form */ +/* returned by decFloatGetExponent */ +/* returns df, which will be canonical */ +/* */ +/* No error is possible, but Overflow or Underflow might occur. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatSetExponent(decFloat *df, decContext *set, Int exp) { + uByte bcdcopy[DECPMAX]; // for coefficient + bcdnum num; // work + num.exponent=exp; + num.sign=decFloatGetCoefficient(df, bcdcopy); // extract coefficient + if (DFISSPECIAL(df)) { // MSD or more needs correcting + if (DFISINF(df)) memset(bcdcopy, 0, DECPMAX); + bcdcopy[0]=0; + } + num.msd=bcdcopy; + num.lsd=bcdcopy+DECPMAX-1; + return decFinalize(df, &num, set); + } // decFloatSetExponent + +/* ------------------------------------------------------------------ */ +/* decFloatRadix -- returns the base (10) */ +/* */ +/* df is any decFloat of this format */ +/* ------------------------------------------------------------------ */ +uInt decFloatRadix(const decFloat *df) { + if (df) return 10; // to placate compiler + return 10; + } // decFloatRadix + +/* The following function is not available if DECPRINT=0 */ +#if DECPRINT +/* ------------------------------------------------------------------ */ +/* decFloatShow -- printf a decFloat in hexadecimal and decimal */ +/* df is the decFloat to show */ +/* tag is a tag string displayed with the number */ +/* */ +/* This is a debug aid; the precise format of the string may change. */ +/* ------------------------------------------------------------------ */ +void decFloatShow(const decFloat *df, const char *tag) { + char hexbuf[DECBYTES*2+DECBYTES/4+1]; // NB blank after every fourth + char buff[DECSTRING]; // for value in decimal + Int i, j=0; + + for (i=0; ibytes[DECBYTES-1-i]); + #else + sprintf(&hexbuf[j], "%02x", df->bytes[i]); + #endif + j+=2; + // the next line adds blank (and terminator) after final pair, too + if ((i+1)%4==0) {strcpy(&hexbuf[j], " "); j++;} + } + decFloatToString(df, buff); + printf(">%s> %s [big-endian] %s\n", tag, hexbuf, buff); + return; + } // decFloatShow +#endif + +/* ------------------------------------------------------------------ */ +/* decFloatToBCD -- get sign, exponent, and BCD8 from a decFloat */ +/* */ +/* df is the source decFloat */ +/* exp will be set to the unbiased exponent, q, or to a special */ +/* value in the form returned by decFloatGetExponent */ +/* bcdar is where DECPMAX bytes will be written, one BCD digit in */ +/* each byte (BCD8 encoding); if df is a NaN the first byte will */ +/* be zero, and if it is infinite they will all be zero */ +/* returns the sign of the coefficient (DECFLOAT_Sign if negative, */ +/* 0 otherwise) */ +/* */ +/* No error is possible, and no status will be set. */ +/* ------------------------------------------------------------------ */ +Int decFloatToBCD(const decFloat *df, Int *exp, uByte *bcdar) { + if (DFISINF(df)) { + memset(bcdar, 0, DECPMAX); + *exp=DFWORD(df, 0)&0x7e000000; + } + else { + GETCOEFF(df, bcdar); // use macro + if (DFISNAN(df)) { + bcdar[0]=0; // MSD needs correcting + *exp=DFWORD(df, 0)&0x7e000000; + } + else { // finite + *exp=GETEXPUN(df); + } + } + return GETSIGN(df); + } // decFloatToBCD + +/* ------------------------------------------------------------------ */ +/* decFloatToEngString -- conversion to numeric string, engineering */ +/* */ +/* df is the decFloat format number to convert */ +/* string is the string where the result will be laid out */ +/* */ +/* string must be at least DECPMAX+9 characters (the worst case is */ +/* "-0.00000nnn...nnn\0", which is as long as the exponent form when */ +/* DECEMAXD<=4); this condition is asserted above */ +/* */ +/* No error is possible, and no status will be set */ +/* ------------------------------------------------------------------ */ +char * decFloatToEngString(const decFloat *df, char *string){ + uInt msd; // coefficient MSD + Int exp; // exponent top two bits or full + uInt comb; // combination field + char *cstart; // coefficient start + char *c; // output pointer in string + char *s, *t; // .. (source, target) + Int pre, e; // work + const uByte *u; // .. + uInt uiwork; // for macros [one compiler needs + // volatile here to avoid bug, but + // that doubles execution time] + + // Source words; macro handles endianness + uInt sourhi=DFWORD(df, 0); // word with sign + #if DECPMAX==16 + uInt sourlo=DFWORD(df, 1); + #elif DECPMAX==34 + uInt sourmh=DFWORD(df, 1); + uInt sourml=DFWORD(df, 2); + uInt sourlo=DFWORD(df, 3); + #endif + + c=string; // where result will go + if (((Int)sourhi)<0) *c++='-'; // handle sign + comb=sourhi>>26; // sign+combination field + msd=DECCOMBMSD[comb]; // decode the combination field + exp=DECCOMBEXP[comb]; // .. + + if (EXPISSPECIAL(exp)) { // special + if (exp==DECFLOAT_Inf) { // infinity + strcpy(c, "Inf"); + strcpy(c+3, "inity"); + return string; // easy + } + if (sourhi&0x02000000) *c++='s'; // sNaN + strcpy(c, "NaN"); // complete word + c+=3; // step past + // quick exit if the payload is zero + #if DECPMAX==7 + if ((sourhi&0x000fffff)==0) return string; + #elif DECPMAX==16 + if (sourlo==0 && (sourhi&0x0003ffff)==0) return string; + #elif DECPMAX==34 + if (sourlo==0 && sourml==0 && sourmh==0 + && (sourhi&0x00003fff)==0) return string; + #endif + // otherwise drop through to add integer; set correct exp etc. + exp=0; msd=0; // setup for following code + } + else { // complete exponent; top two bits are in place + exp+=GETECON(df)-DECBIAS; // .. + continuation and unbias + } + + /* convert the digits of the significand to characters */ + cstart=c; // save start of coefficient + if (msd) *c++=(char)('0'+(char)msd); // non-zero most significant digit + + // Decode the declets. After extracting each declet, it is + // decoded to a 4-uByte sequence by table lookup; the four uBytes + // are the three encoded BCD8 digits followed by a 1-byte length + // (significant digits, except that 000 has length 0). This allows + // us to left-align the first declet with non-zero content, then + // the remaining ones are full 3-char length. Fixed-length copies + // are used because variable-length memcpy causes a subroutine call + // in at least two compilers. (The copies are length 4 for speed + // and are safe because the last item in the array is of length + // three and has the length byte following.) + #define dpd2char(dpdin) u=&DPD2BCD8[((dpdin)&0x3ff)*4]; \ + if (c!=cstart) {UBFROMUI(c, UBTOUI(u)|CHARMASK); c+=3;} \ + else if (*(u+3)) { \ + UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); c+=*(u+3);} + + #if DECPMAX==7 + dpd2char(sourhi>>10); // declet 1 + dpd2char(sourhi); // declet 2 + + #elif DECPMAX==16 + dpd2char(sourhi>>8); // declet 1 + dpd2char((sourhi<<2) | (sourlo>>30)); // declet 2 + dpd2char(sourlo>>20); // declet 3 + dpd2char(sourlo>>10); // declet 4 + dpd2char(sourlo); // declet 5 + + #elif DECPMAX==34 + dpd2char(sourhi>>4); // declet 1 + dpd2char((sourhi<<6) | (sourmh>>26)); // declet 2 + dpd2char(sourmh>>16); // declet 3 + dpd2char(sourmh>>6); // declet 4 + dpd2char((sourmh<<4) | (sourml>>28)); // declet 5 + dpd2char(sourml>>18); // declet 6 + dpd2char(sourml>>8); // declet 7 + dpd2char((sourml<<2) | (sourlo>>30)); // declet 8 + dpd2char(sourlo>>20); // declet 9 + dpd2char(sourlo>>10); // declet 10 + dpd2char(sourlo); // declet 11 + #endif + + if (c==cstart) *c++='0'; // all zeros, empty -- make "0" + + if (exp==0) { // integer or NaN case -- easy + *c='\0'; // terminate + return string; + } + /* non-0 exponent */ + + e=0; // assume no E + pre=(Int)(c-cstart)+exp; // length+exp [c->LSD+1] + // [here, pre-exp is the digits count (==1 for zero)] + + if (exp>0 || pre<-5) { // need exponential form + e=pre-1; // calculate E value + pre=1; // assume one digit before '.' + if (e!=0) { // engineering: may need to adjust + Int adj; // adjustment + // The C remainder operator is undefined for negative numbers, so + // a positive remainder calculation must be used here + if (e<0) { + adj=(-e)%3; + if (adj!=0) adj=3-adj; + } + else { // e>0 + adj=e%3; + } + e=e-adj; + // if dealing with zero still produce an exponent which is a + // multiple of three, as expected, but there will only be the + // one zero before the E, still. Otherwise note the padding. + if (!DFISZERO(df)) pre+=adj; + else { // is zero + if (adj!=0) { // 0.00Esnn needed + e=e+3; + pre=-(2-adj); + } + } // zero + } // engineering adjustment + } // exponential form + // printf("e=%ld pre=%ld exp=%ld\n", (LI)e, (LI)pre, (LI)exp); + + /* modify the coefficient, adding 0s, '.', and E+nn as needed */ + if (pre>0) { // ddd.ddd (plain), perhaps with E + // or dd00 padding for engineering + char *dotat=cstart+pre; + if (dotat=dotat; s-=4, t-=4) UBFROMUI(t, UBTOUI(s)); + *dotat='.'; + c++; // length increased by one + } // need dot? + else for (; c0 + else { + /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (may have + E, but only for 0.00E+3 kind of case -- with plenty of spare + space in this case */ + pre=-pre+2; // gap width, including "0." + t=cstart+ROUNDDOWN4(c-cstart)+pre; // preferred first target point + // backoff if too far to the right + if (t>string+DECSTRING-5) t=string+DECSTRING-5; // adjust to fit + // now shift the entire coefficient to the right, being careful not + // to access to the left of string [cannot use memcpy] + for (s=t-pre; s>=string; s-=4, t-=4) UBFROMUI(t, UBTOUI(s)); + // for Quads and Singles there may be a character or two left... + s+=3; // where next would come from + for(; s>=cstart; s--, t--) *(t+3)=*(s); + // now have fill 0. through 0.00000; use overlaps to avoid tests + if (pre>=4) { + memcpy(cstart+pre-4, "0000", 4); + memcpy(cstart, "0.00", 4); + } + else { // 2 or 3 + *(cstart+pre-1)='0'; + memcpy(cstart, "0.", 2); + } + c+=pre; // to end + } + + // finally add the E-part, if needed; it will never be 0, and has + // a maximum length of 3 or 4 digits (asserted above) + if (e!=0) { + memcpy(c, "E+", 2); // starts with E, assume + + c++; + if (e<0) { + *c='-'; // oops, need '-' + e=-e; // uInt, please + } + c++; + // Three-character exponents are easy; 4-character a little trickier + #if DECEMAXD<=3 + u=&BIN2BCD8[e*4]; // -> 3 digits + length byte + // copy fixed 4 characters [is safe], starting at non-zero + // and with character mask to convert BCD to char + UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); + c+=*(u+3); // bump pointer appropriately + #elif DECEMAXD==4 + if (e<1000) { // 3 (or fewer) digits case + u=&BIN2BCD8[e*4]; // -> 3 digits + length byte + UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); // [as above] + c+=*(u+3); // bump pointer appropriately + } + else { // 4-digits + Int thou=((e>>3)*1049)>>17; // e/1000 + Int rem=e-(1000*thou); // e%1000 + *c++=(char)('0'+(char)thou); // the thousands digit + u=&BIN2BCD8[rem*4]; // -> 3 digits + length byte + UBFROMUI(c, UBTOUI(u)|CHARMASK);// copy fixed 3+1 characters [is safe] + c+=3; // bump pointer, always 3 digits + } + #endif + } + *c='\0'; // terminate + //printf("res %s\n", string); + return string; + } // decFloatToEngString + +/* ------------------------------------------------------------------ */ +/* decFloatToPacked -- convert decFloat to Packed decimal + exponent */ +/* */ +/* df is the source decFloat */ +/* exp will be set to the unbiased exponent, q, or to a special */ +/* value in the form returned by decFloatGetExponent */ +/* packed is where DECPMAX nibbles will be written with the sign as */ +/* final nibble (0x0c for +, 0x0d for -); a NaN has a first nibble */ +/* of zero, and an infinity is all zeros. decDouble and decQuad */ +/* have a additional leading zero nibble, leading to result */ +/* lengths of 4, 9, and 18 bytes. */ +/* returns the sign of the coefficient (DECFLOAT_Sign if negative, */ +/* 0 otherwise) */ +/* */ +/* No error is possible, and no status will be set. */ +/* ------------------------------------------------------------------ */ +Int decFloatToPacked(const decFloat *df, Int *exp, uByte *packed) { + uByte bcdar[DECPMAX+2]; // work buffer + uByte *ip=bcdar, *op=packed; // work pointers + if (DFISINF(df)) { + memset(bcdar, 0, DECPMAX+2); + *exp=DECFLOAT_Inf; + } + else { + GETCOEFF(df, bcdar+1); // use macro + if (DFISNAN(df)) { + bcdar[1]=0; // MSD needs clearing + *exp=DFWORD(df, 0)&0x7e000000; + } + else { // finite + *exp=GETEXPUN(df); + } + } + // now pack; coefficient currently at bcdar+1 + #if SINGLE + ip++; // ignore first byte + #else + *ip=0; // need leading zero + #endif + // set final byte to Packed BCD sign value + bcdar[DECPMAX+1]=(DFISSIGNED(df) ? DECPMINUS : DECPPLUS); + // pack an even number of bytes... + for (; op>26; // sign+combination field + msd=DECCOMBMSD[comb]; // decode the combination field + exp=DECCOMBEXP[comb]; // .. + + if (!EXPISSPECIAL(exp)) { // finite + // complete exponent; top two bits are in place + exp+=GETECON(df)-DECBIAS; // .. + continuation and unbias + } + else { // IS special + if (exp==DECFLOAT_Inf) { // infinity + strcpy(c, "Infinity"); + return string; // easy + } + if (sourhi&0x02000000) *c++='s'; // sNaN + strcpy(c, "NaN"); // complete word + c+=3; // step past + // quick exit if the payload is zero + #if DECPMAX==7 + if ((sourhi&0x000fffff)==0) return string; + #elif DECPMAX==16 + if (sourlo==0 && (sourhi&0x0003ffff)==0) return string; + #elif DECPMAX==34 + if (sourlo==0 && sourml==0 && sourmh==0 + && (sourhi&0x00003fff)==0) return string; + #endif + // otherwise drop through to add integer; set correct exp etc. + exp=0; msd=0; // setup for following code + } + + /* convert the digits of the significand to characters */ + cstart=c; // save start of coefficient + if (msd) *c++=(char)('0'+(char)msd); // non-zero most significant digit + + // Decode the declets. After extracting each declet, it is + // decoded to a 4-uByte sequence by table lookup; the four uBytes + // are the three encoded BCD8 digits followed by a 1-byte length + // (significant digits, except that 000 has length 0). This allows + // us to left-align the first declet with non-zero content, then + // the remaining ones are full 3-char length. Fixed-length copies + // are used because variable-length memcpy causes a subroutine call + // in at least two compilers. (The copies are length 4 for speed + // and are safe because the last item in the array is of length + // three and has the length byte following.) + #define dpd2char(dpdin) u=&DPD2BCD8[((dpdin)&0x3ff)*4]; \ + if (c!=cstart) {UBFROMUI(c, UBTOUI(u)|CHARMASK); c+=3;} \ + else if (*(u+3)) { \ + UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); c+=*(u+3);} + + #if DECPMAX==7 + dpd2char(sourhi>>10); // declet 1 + dpd2char(sourhi); // declet 2 + + #elif DECPMAX==16 + dpd2char(sourhi>>8); // declet 1 + dpd2char((sourhi<<2) | (sourlo>>30)); // declet 2 + dpd2char(sourlo>>20); // declet 3 + dpd2char(sourlo>>10); // declet 4 + dpd2char(sourlo); // declet 5 + + #elif DECPMAX==34 + dpd2char(sourhi>>4); // declet 1 + dpd2char((sourhi<<6) | (sourmh>>26)); // declet 2 + dpd2char(sourmh>>16); // declet 3 + dpd2char(sourmh>>6); // declet 4 + dpd2char((sourmh<<4) | (sourml>>28)); // declet 5 + dpd2char(sourml>>18); // declet 6 + dpd2char(sourml>>8); // declet 7 + dpd2char((sourml<<2) | (sourlo>>30)); // declet 8 + dpd2char(sourlo>>20); // declet 9 + dpd2char(sourlo>>10); // declet 10 + dpd2char(sourlo); // declet 11 + #endif + + if (c==cstart) *c++='0'; // all zeros, empty -- make "0" + + //[This fast path is valid but adds 3-5 cycles to worst case length] + //if (exp==0) { // integer or NaN case -- easy + // *c='\0'; // terminate + // return string; + // } + + e=0; // assume no E + pre=(Int)(c-cstart)+exp; // length+exp [c->LSD+1] + // [here, pre-exp is the digits count (==1 for zero)] + + if (exp>0 || pre<-5) { // need exponential form + e=pre-1; // calculate E value + pre=1; // assume one digit before '.' + } // exponential form + + /* modify the coefficient, adding 0s, '.', and E+nn as needed */ + if (pre>0) { // ddd.ddd (plain), perhaps with E + char *dotat=cstart+pre; + if (dotat=dotat; s-=4, t-=4) UBFROMUI(t, UBTOUI(s)); + *dotat='.'; + c++; // length increased by one + } // need dot? + + // finally add the E-part, if needed; it will never be 0, and has + // a maximum length of 3 or 4 digits (asserted above) + if (e!=0) { + memcpy(c, "E+", 2); // starts with E, assume + + c++; + if (e<0) { + *c='-'; // oops, need '-' + e=-e; // uInt, please + } + c++; + // Three-character exponents are easy; 4-character a little trickier + #if DECEMAXD<=3 + u=&BIN2BCD8[e*4]; // -> 3 digits + length byte + // copy fixed 4 characters [is safe], starting at non-zero + // and with character mask to convert BCD to char + UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); + c+=*(u+3); // bump pointer appropriately + #elif DECEMAXD==4 + if (e<1000) { // 3 (or fewer) digits case + u=&BIN2BCD8[e*4]; // -> 3 digits + length byte + UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); // [as above] + c+=*(u+3); // bump pointer appropriately + } + else { // 4-digits + Int thou=((e>>3)*1049)>>17; // e/1000 + Int rem=e-(1000*thou); // e%1000 + *c++=(char)('0'+(char)thou); // the thousands digit + u=&BIN2BCD8[rem*4]; // -> 3 digits + length byte + UBFROMUI(c, UBTOUI(u)|CHARMASK); // copy fixed 3+1 characters [is safe] + c+=3; // bump pointer, always 3 digits + } + #endif + } + *c='\0'; // add terminator + //printf("res %s\n", string); + return string; + } // pre>0 + + /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ + // Surprisingly, this is close to being the worst-case path, so the + // shift is done by fours; this is a little tricky because the + // rightmost character to be written must not be beyond where the + // rightmost terminator could be -- so backoff to not touch + // terminator position if need be (this can make exact alignments + // for full Doubles, but in some cases needs care not to access too + // far to the left) + + pre=-pre+2; // gap width, including "0." + t=cstart+ROUNDDOWN4(c-cstart)+pre; // preferred first target point + // backoff if too far to the right + if (t>string+DECSTRING-5) t=string+DECSTRING-5; // adjust to fit + // now shift the entire coefficient to the right, being careful not + // to access to the left of string [cannot use memcpy] + for (s=t-pre; s>=string; s-=4, t-=4) UBFROMUI(t, UBTOUI(s)); + // for Quads and Singles there may be a character or two left... + s+=3; // where next would come from + for(; s>=cstart; s--, t--) *(t+3)=*(s); + // now have fill 0. through 0.00000; use overlaps to avoid tests + if (pre>=4) { + memcpy(cstart+pre-4, "0000", 4); + memcpy(cstart, "0.00", 4); + } + else { // 2 or 3 + *(cstart+pre-1)='0'; + memcpy(cstart, "0.", 2); + } + *(c+pre)='\0'; // terminate + return string; + } // decFloatToString + +/* ------------------------------------------------------------------ */ +/* decFloatToWider -- conversion to next-wider format */ +/* */ +/* source is the decFloat format number which gets the result of */ +/* the conversion */ +/* wider is the decFloatWider format number which will be narrowed */ +/* returns wider */ +/* */ +/* Widening is always exact; no status is set (sNaNs are copied and */ +/* do not signal). The result will be canonical if the source is, */ +/* and may or may not be if the source is not. */ +/* ------------------------------------------------------------------ */ +// widening is not possible for decQuad format numbers; simply omit +#if !QUAD +decFloatWider * decFloatToWider(const decFloat *source, decFloatWider *wider) { + uInt msd; + + /* Construct and copy the sign word */ + if (DFISSPECIAL(source)) { + // copy sign, combination, and first bit of exponent (sNaN selector) + DFWWORD(wider, 0)=DFWORD(source, 0)&0xfe000000; + msd=0; + } + else { // is finite number + uInt exp=GETEXPUN(source)+DECWBIAS; // get unbiased exponent and rebias + uInt code=(exp>>DECWECONL)<<29; // set two bits of exp [msd=0] + code|=(exp<<(32-6-DECWECONL)) & 0x03ffffff; // add exponent continuation + code|=DFWORD(source, 0)&0x80000000; // add sign + DFWWORD(wider, 0)=code; // .. and place top word in wider + msd=GETMSD(source); // get source coefficient MSD [0-9] + } + /* Copy the coefficient and clear any 'unused' words to left */ + #if SINGLE + DFWWORD(wider, 1)=(DFWORD(source, 0)&0x000fffff)|(msd<<20); + #elif DOUBLE + DFWWORD(wider, 2)=(DFWORD(source, 0)&0x0003ffff)|(msd<<18); + DFWWORD(wider, 3)=DFWORD(source, 1); + DFWWORD(wider, 1)=0; + #endif + return wider; + } // decFloatToWider +#endif + +/* ------------------------------------------------------------------ */ +/* decFloatVersion -- return package version string */ +/* */ +/* returns a constant string describing this package */ +/* ------------------------------------------------------------------ */ +const char *decFloatVersion(void) { + return DECVERSION; + } // decFloatVersion + +/* ------------------------------------------------------------------ */ +/* decFloatZero -- set to canonical (integer) zero */ +/* */ +/* df is the decFloat format number to integer +0 (q=0, c=+0) */ +/* returns df */ +/* */ +/* No error is possible, and no status can be set. */ +/* ------------------------------------------------------------------ */ +decFloat * decFloatZero(decFloat *df){ + DFWORD(df, 0)=ZEROWORD; // set appropriate top word + #if DOUBLE || QUAD + DFWORD(df, 1)=0; + #if QUAD + DFWORD(df, 2)=0; + DFWORD(df, 3)=0; + #endif + #endif + // decFloatShow(df, "zero"); + return df; + } // decFloatZero + +/* ------------------------------------------------------------------ */ +/* Private generic function (not format-specific) for development use */ +/* ------------------------------------------------------------------ */ +// This is included once only, for all to use +#if QUAD && (DECCHECK || DECTRACE) + /* ---------------------------------------------------------------- */ + /* decShowNum -- display bcd8 number in debug form */ + /* */ + /* num is the bcdnum to display */ + /* tag is a string to label the display */ + /* ---------------------------------------------------------------- */ + void decShowNum(const bcdnum *num, const char *tag) { + const char *csign="+"; // sign character + uByte *ub; // work + uInt uiwork; // for macros + if (num->sign==DECFLOAT_Sign) csign="-"; + + printf(">%s> ", tag); + if (num->exponent==DECFLOAT_Inf) printf("%sInfinity", csign); + else if (num->exponent==DECFLOAT_qNaN) printf("%sqNaN", csign); + else if (num->exponent==DECFLOAT_sNaN) printf("%ssNaN", csign); + else { // finite + char qbuf[10]; // for right-aligned q + char *c; // work + const uByte *u; // .. + Int e=num->exponent; // .. exponent + strcpy(qbuf, "q="); + c=&qbuf[2]; // where exponent will go + // lay out the exponent + if (e<0) { + *c++='-'; // add '-' + e=-e; // uInt, please + } + #if DECEMAXD>4 + #error Exponent form is too long for ShowNum to lay out + #endif + if (e==0) *c++='0'; // 0-length case + else if (e<1000) { // 3 (or fewer) digits case + u=&BIN2BCD8[e*4]; // -> 3 digits + length byte + UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); // [as above] + c+=*(u+3); // bump pointer appropriately + } + else { // 4-digits + Int thou=((e>>3)*1049)>>17; // e/1000 + Int rem=e-(1000*thou); // e%1000 + *c++=(char)('0'+(char)thou); // the thousands digit + u=&BIN2BCD8[rem*4]; // -> 3 digits + length byte + UBFROMUI(c, UBTOUI(u)|CHARMASK); // copy fixed 3+1 characters [is safe] + c+=3; // bump pointer, always 3 digits + } + *c='\0'; // add terminator + printf("%7s c=%s", qbuf, csign); + } + + if (!EXPISSPECIAL(num->exponent) || num->msd!=num->lsd || *num->lsd!=0) { + for (ub=num->msd; ub<=num->lsd; ub++) { // coefficient... + printf("%1x", *ub); + if ((num->lsd-ub)%3==0 && ub!=num->lsd) printf(" "); // 4-space + } + } + printf("\n"); + } // decShowNum +#endif diff --git a/src/decNumber/decContext.c b/src/decNumber/decContext.c new file mode 100644 index 0000000000..9f99759336 --- /dev/null +++ b/src/decNumber/decContext.c @@ -0,0 +1,437 @@ +/* ------------------------------------------------------------------ */ +/* Decimal Context module */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2009. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is called decNumber.pdf. This document is */ +/* available, together with arithmetic and format specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ +/* This module comprises the routines for handling arithmetic */ +/* context structures. */ +/* ------------------------------------------------------------------ */ + +#include // for strcmp +#include // for printf if DECCHECK +#include "decContext.h" // context and base types +#include "decNumberLocal.h" // decNumber local types, etc. + +/* compile-time endian tester [assumes sizeof(Int)>1] */ +static const Int mfcone=1; // constant 1 +static const Flag *mfctop=(const Flag *)&mfcone; // -> top byte +#define LITEND *mfctop // named flag; 1=little-endian + +/* ------------------------------------------------------------------ */ +/* round-for-reround digits */ +/* ------------------------------------------------------------------ */ +const uByte DECSTICKYTAB[10]={1,1,2,3,4,6,6,7,8,9}; /* used if sticky */ + +/* ------------------------------------------------------------------ */ +/* Powers of ten (powers[n]==10**n, 0<=n<=9) */ +/* ------------------------------------------------------------------ */ +const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000, + 10000000, 100000000, 1000000000}; + +/* ------------------------------------------------------------------ */ +/* decContextClearStatus -- clear bits in current status */ +/* */ +/* context is the context structure to be queried */ +/* mask indicates the bits to be cleared (the status bit that */ +/* corresponds to each 1 bit in the mask is cleared) */ +/* returns context */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decContext *decContextClearStatus(decContext *context, uInt mask) { + context->status&=~mask; + return context; + } // decContextClearStatus + +/* ------------------------------------------------------------------ */ +/* decContextDefault -- initialize a context structure */ +/* */ +/* context is the structure to be initialized */ +/* kind selects the required set of default values, one of: */ +/* DEC_INIT_BASE -- select ANSI X3-274 defaults */ +/* DEC_INIT_DECIMAL32 -- select IEEE 754 defaults, 32-bit */ +/* DEC_INIT_DECIMAL64 -- select IEEE 754 defaults, 64-bit */ +/* DEC_INIT_DECIMAL128 -- select IEEE 754 defaults, 128-bit */ +/* For any other value a valid context is returned, but with */ +/* Invalid_operation set in the status field. */ +/* returns a context structure with the appropriate initial values. */ +/* ------------------------------------------------------------------ */ +decContext * decContextDefault(decContext *context, Int kind) { + // set defaults... + context->digits=9; // 9 digits + context->emax=DEC_MAX_EMAX; // 9-digit exponents + context->emin=DEC_MIN_EMIN; // .. balanced + context->round=DEC_ROUND_HALF_UP; // 0.5 rises + context->traps=DEC_Errors; // all but informational + context->status=0; // cleared + context->clamp=0; // no clamping + #if DECSUBSET + context->extended=0; // cleared + #endif + switch (kind) { + case DEC_INIT_BASE: + // [use defaults] + break; + case DEC_INIT_DECIMAL32: + context->digits=7; // digits + context->emax=96; // Emax + context->emin=-95; // Emin + context->round=DEC_ROUND_HALF_EVEN; // 0.5 to nearest even + context->traps=0; // no traps set + context->clamp=1; // clamp exponents + #if DECSUBSET + context->extended=1; // set + #endif + break; + case DEC_INIT_DECIMAL64: + context->digits=16; // digits + context->emax=384; // Emax + context->emin=-383; // Emin + context->round=DEC_ROUND_HALF_EVEN; // 0.5 to nearest even + context->traps=0; // no traps set + context->clamp=1; // clamp exponents + #if DECSUBSET + context->extended=1; // set + #endif + break; + case DEC_INIT_DECIMAL128: + context->digits=34; // digits + context->emax=6144; // Emax + context->emin=-6143; // Emin + context->round=DEC_ROUND_HALF_EVEN; // 0.5 to nearest even + context->traps=0; // no traps set + context->clamp=1; // clamp exponents + #if DECSUBSET + context->extended=1; // set + #endif + break; + + default: // invalid Kind + // use defaults, and .. + decContextSetStatus(context, DEC_Invalid_operation); // trap + } + + return context;} // decContextDefault + +/* ------------------------------------------------------------------ */ +/* decContextGetRounding -- return current rounding mode */ +/* */ +/* context is the context structure to be queried */ +/* returns the rounding mode */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +enum rounding decContextGetRounding(decContext *context) { + return context->round; + } // decContextGetRounding + +/* ------------------------------------------------------------------ */ +/* decContextGetStatus -- return current status */ +/* */ +/* context is the context structure to be queried */ +/* returns status */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +uInt decContextGetStatus(decContext *context) { + return context->status; + } // decContextGetStatus + +/* ------------------------------------------------------------------ */ +/* decContextRestoreStatus -- restore bits in current status */ +/* */ +/* context is the context structure to be updated */ +/* newstatus is the source for the bits to be restored */ +/* mask indicates the bits to be restored (the status bit that */ +/* corresponds to each 1 bit in the mask is set to the value of */ +/* the correspnding bit in newstatus) */ +/* returns context */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decContext *decContextRestoreStatus(decContext *context, + uInt newstatus, uInt mask) { + context->status&=~mask; // clear the selected bits + context->status|=(mask&newstatus); // or in the new bits + return context; + } // decContextRestoreStatus + +/* ------------------------------------------------------------------ */ +/* decContextSaveStatus -- save bits in current status */ +/* */ +/* context is the context structure to be queried */ +/* mask indicates the bits to be saved (the status bits that */ +/* correspond to each 1 bit in the mask are saved) */ +/* returns the AND of the mask and the current status */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +uInt decContextSaveStatus(decContext *context, uInt mask) { + return context->status&mask; + } // decContextSaveStatus + +/* ------------------------------------------------------------------ */ +/* decContextSetRounding -- set current rounding mode */ +/* */ +/* context is the context structure to be updated */ +/* newround is the value which will replace the current mode */ +/* returns context */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decContext *decContextSetRounding(decContext *context, + enum rounding newround) { + context->round=newround; + return context; + } // decContextSetRounding + +/* ------------------------------------------------------------------ */ +/* decContextSetStatus -- set status and raise trap if appropriate */ +/* */ +/* context is the context structure to be updated */ +/* status is the DEC_ exception code */ +/* returns the context structure */ +/* */ +/* Control may never return from this routine, if there is a signal */ +/* handler and it takes a long jump. */ +/* ------------------------------------------------------------------ */ +decContext * decContextSetStatus(decContext *context, uInt status) { + context->status|=status; + if (status & context->traps) raise(SIGFPE); + return context;} // decContextSetStatus + +/* ------------------------------------------------------------------ */ +/* decContextSetStatusFromString -- set status from a string + trap */ +/* */ +/* context is the context structure to be updated */ +/* string is a string exactly equal to one that might be returned */ +/* by decContextStatusToString */ +/* */ +/* The status bit corresponding to the string is set, and a trap */ +/* is raised if appropriate. */ +/* */ +/* returns the context structure, unless the string is equal to */ +/* DEC_Condition_MU or is not recognized. In these cases NULL is */ +/* returned. */ +/* ------------------------------------------------------------------ */ +decContext * decContextSetStatusFromString(decContext *context, + const char *string) { + if (strcmp(string, DEC_Condition_CS)==0) + return decContextSetStatus(context, DEC_Conversion_syntax); + if (strcmp(string, DEC_Condition_DZ)==0) + return decContextSetStatus(context, DEC_Division_by_zero); + if (strcmp(string, DEC_Condition_DI)==0) + return decContextSetStatus(context, DEC_Division_impossible); + if (strcmp(string, DEC_Condition_DU)==0) + return decContextSetStatus(context, DEC_Division_undefined); + if (strcmp(string, DEC_Condition_IE)==0) + return decContextSetStatus(context, DEC_Inexact); + if (strcmp(string, DEC_Condition_IS)==0) + return decContextSetStatus(context, DEC_Insufficient_storage); + if (strcmp(string, DEC_Condition_IC)==0) + return decContextSetStatus(context, DEC_Invalid_context); + if (strcmp(string, DEC_Condition_IO)==0) + return decContextSetStatus(context, DEC_Invalid_operation); + #if DECSUBSET + if (strcmp(string, DEC_Condition_LD)==0) + return decContextSetStatus(context, DEC_Lost_digits); + #endif + if (strcmp(string, DEC_Condition_OV)==0) + return decContextSetStatus(context, DEC_Overflow); + if (strcmp(string, DEC_Condition_PA)==0) + return decContextSetStatus(context, DEC_Clamped); + if (strcmp(string, DEC_Condition_RO)==0) + return decContextSetStatus(context, DEC_Rounded); + if (strcmp(string, DEC_Condition_SU)==0) + return decContextSetStatus(context, DEC_Subnormal); + if (strcmp(string, DEC_Condition_UN)==0) + return decContextSetStatus(context, DEC_Underflow); + if (strcmp(string, DEC_Condition_ZE)==0) + return context; + return NULL; // Multiple status, or unknown + } // decContextSetStatusFromString + +/* ------------------------------------------------------------------ */ +/* decContextSetStatusFromStringQuiet -- set status from a string */ +/* */ +/* context is the context structure to be updated */ +/* string is a string exactly equal to one that might be returned */ +/* by decContextStatusToString */ +/* */ +/* The status bit corresponding to the string is set; no trap is */ +/* raised. */ +/* */ +/* returns the context structure, unless the string is equal to */ +/* DEC_Condition_MU or is not recognized. In these cases NULL is */ +/* returned. */ +/* ------------------------------------------------------------------ */ +decContext * decContextSetStatusFromStringQuiet(decContext *context, + const char *string) { + if (strcmp(string, DEC_Condition_CS)==0) + return decContextSetStatusQuiet(context, DEC_Conversion_syntax); + if (strcmp(string, DEC_Condition_DZ)==0) + return decContextSetStatusQuiet(context, DEC_Division_by_zero); + if (strcmp(string, DEC_Condition_DI)==0) + return decContextSetStatusQuiet(context, DEC_Division_impossible); + if (strcmp(string, DEC_Condition_DU)==0) + return decContextSetStatusQuiet(context, DEC_Division_undefined); + if (strcmp(string, DEC_Condition_IE)==0) + return decContextSetStatusQuiet(context, DEC_Inexact); + if (strcmp(string, DEC_Condition_IS)==0) + return decContextSetStatusQuiet(context, DEC_Insufficient_storage); + if (strcmp(string, DEC_Condition_IC)==0) + return decContextSetStatusQuiet(context, DEC_Invalid_context); + if (strcmp(string, DEC_Condition_IO)==0) + return decContextSetStatusQuiet(context, DEC_Invalid_operation); + #if DECSUBSET + if (strcmp(string, DEC_Condition_LD)==0) + return decContextSetStatusQuiet(context, DEC_Lost_digits); + #endif + if (strcmp(string, DEC_Condition_OV)==0) + return decContextSetStatusQuiet(context, DEC_Overflow); + if (strcmp(string, DEC_Condition_PA)==0) + return decContextSetStatusQuiet(context, DEC_Clamped); + if (strcmp(string, DEC_Condition_RO)==0) + return decContextSetStatusQuiet(context, DEC_Rounded); + if (strcmp(string, DEC_Condition_SU)==0) + return decContextSetStatusQuiet(context, DEC_Subnormal); + if (strcmp(string, DEC_Condition_UN)==0) + return decContextSetStatusQuiet(context, DEC_Underflow); + if (strcmp(string, DEC_Condition_ZE)==0) + return context; + return NULL; // Multiple status, or unknown + } // decContextSetStatusFromStringQuiet + +/* ------------------------------------------------------------------ */ +/* decContextSetStatusQuiet -- set status without trap */ +/* */ +/* context is the context structure to be updated */ +/* status is the DEC_ exception code */ +/* returns the context structure */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decContext * decContextSetStatusQuiet(decContext *context, uInt status) { + context->status|=status; + return context;} // decContextSetStatusQuiet + +/* ------------------------------------------------------------------ */ +/* decContextStatusToString -- convert status flags to a string */ +/* */ +/* context is a context with valid status field */ +/* */ +/* returns a constant string describing the condition. If multiple */ +/* (or no) flags are set, a generic constant message is returned. */ +/* ------------------------------------------------------------------ */ +const char *decContextStatusToString(const decContext *context) { + Int status=context->status; + + // test the five IEEE first, as some of the others are ambiguous when + // DECEXTFLAG=0 + if (status==DEC_Invalid_operation ) return DEC_Condition_IO; + if (status==DEC_Division_by_zero ) return DEC_Condition_DZ; + if (status==DEC_Overflow ) return DEC_Condition_OV; + if (status==DEC_Underflow ) return DEC_Condition_UN; + if (status==DEC_Inexact ) return DEC_Condition_IE; + + if (status==DEC_Division_impossible ) return DEC_Condition_DI; + if (status==DEC_Division_undefined ) return DEC_Condition_DU; + if (status==DEC_Rounded ) return DEC_Condition_RO; + if (status==DEC_Clamped ) return DEC_Condition_PA; + if (status==DEC_Subnormal ) return DEC_Condition_SU; + if (status==DEC_Conversion_syntax ) return DEC_Condition_CS; + if (status==DEC_Insufficient_storage ) return DEC_Condition_IS; + if (status==DEC_Invalid_context ) return DEC_Condition_IC; + #if DECSUBSET + if (status==DEC_Lost_digits ) return DEC_Condition_LD; + #endif + if (status==0 ) return DEC_Condition_ZE; + return DEC_Condition_MU; // Multiple errors + } // decContextStatusToString + +/* ------------------------------------------------------------------ */ +/* decContextTestEndian -- test whether DECLITEND is set correctly */ +/* */ +/* quiet is 1 to suppress message; 0 otherwise */ +/* returns 0 if DECLITEND is correct */ +/* 1 if DECLITEND is incorrect and should be 1 */ +/* -1 if DECLITEND is incorrect and should be 0 */ +/* */ +/* A message is displayed if the return value is not 0 and quiet==0. */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +Int decContextTestEndian(Flag quiet) { + Int res=0; // optimist + uInt dle=(uInt)DECLITEND; // unsign + if (dle>1) dle=1; // ensure 0 or 1 + + if (LITEND!=DECLITEND) { + if (!quiet) { // always refer to this + #if DECPRINT + const char *adj; + if (LITEND) adj="little"; + else adj="big"; + printf("Warning: DECLITEND is set to %d, but this computer appears to be %s-endian\n", + DECLITEND, adj); + #endif + } + res=(Int)LITEND-dle; + } + return res; + } // decContextTestEndian + +/* ------------------------------------------------------------------ */ +/* decContextTestSavedStatus -- test bits in saved status */ +/* */ +/* oldstatus is the status word to be tested */ +/* mask indicates the bits to be tested (the oldstatus bits that */ +/* correspond to each 1 bit in the mask are tested) */ +/* returns 1 if any of the tested bits are 1, or 0 otherwise */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +uInt decContextTestSavedStatus(uInt oldstatus, uInt mask) { + return (oldstatus&mask)!=0; + } // decContextTestSavedStatus + +/* ------------------------------------------------------------------ */ +/* decContextTestStatus -- test bits in current status */ +/* */ +/* context is the context structure to be updated */ +/* mask indicates the bits to be tested (the status bits that */ +/* correspond to each 1 bit in the mask are tested) */ +/* returns 1 if any of the tested bits are 1, or 0 otherwise */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +uInt decContextTestStatus(decContext *context, uInt mask) { + return (context->status&mask)!=0; + } // decContextTestStatus + +/* ------------------------------------------------------------------ */ +/* decContextZeroStatus -- clear all status bits */ +/* */ +/* context is the context structure to be updated */ +/* returns context */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decContext *decContextZeroStatus(decContext *context) { + context->status=0; + return context; + } // decContextZeroStatus + diff --git a/src/decNumber/decContext.h b/src/decNumber/decContext.h new file mode 100644 index 0000000000..82e4fcf2db --- /dev/null +++ b/src/decNumber/decContext.h @@ -0,0 +1,254 @@ +/* ------------------------------------------------------------------ */ +/* Decimal Context module header */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is called decNumber.pdf. This document is */ +/* available, together with arithmetic and format specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ +/* */ +/* Context variables must always have valid values: */ +/* */ +/* status -- [any bits may be cleared, but not set, by user] */ +/* round -- must be one of the enumerated rounding modes */ +/* */ +/* The following variables are implied for fixed size formats (i.e., */ +/* they are ignored) but should still be set correctly in case used */ +/* with decNumber functions: */ +/* */ +/* clamp -- must be either 0 or 1 */ +/* digits -- must be in the range 1 through 999999999 */ +/* emax -- must be in the range 0 through 999999999 */ +/* emin -- must be in the range 0 through -999999999 */ +/* extended -- must be either 0 or 1 [present only if DECSUBSET] */ +/* traps -- only defined bits may be set */ +/* */ +/* ------------------------------------------------------------------ */ + +#if !defined(DECCONTEXT) + #define DECCONTEXT + #define DECCNAME "decContext" /* Short name */ + #define DECCFULLNAME "Decimal Context Descriptor" /* Verbose name */ + #define DECCAUTHOR "Mike Cowlishaw" /* Who to blame */ + + #if !defined(int32_t) + #include /* C99 standard integers */ + #endif + #include /* for printf, etc. */ + #include /* for traps */ + + /* Extended flags setting -- set this to 0 to use only IEEE flags */ + #if !defined(DECEXTFLAG) + #define DECEXTFLAG 1 /* 1=enable extended flags */ + #endif + + /* Conditional code flag -- set this to 0 for best performance */ + #if !defined(DECSUBSET) + #define DECSUBSET 0 /* 1=enable subset arithmetic */ + #endif + + /* Context for operations, with associated constants */ + enum rounding { + DEC_ROUND_CEILING, /* round towards +infinity */ + DEC_ROUND_UP, /* round away from 0 */ + DEC_ROUND_HALF_UP, /* 0.5 rounds up */ + DEC_ROUND_HALF_EVEN, /* 0.5 rounds to nearest even */ + DEC_ROUND_HALF_DOWN, /* 0.5 rounds down */ + DEC_ROUND_DOWN, /* round towards 0 (truncate) */ + DEC_ROUND_FLOOR, /* round towards -infinity */ + DEC_ROUND_05UP, /* round for reround */ + DEC_ROUND_MAX /* enum must be less than this */ + }; + #define DEC_ROUND_DEFAULT DEC_ROUND_HALF_EVEN; + + typedef struct { + int32_t digits; /* working precision */ + int32_t emax; /* maximum positive exponent */ + int32_t emin; /* minimum negative exponent */ + enum rounding round; /* rounding mode */ + uint32_t traps; /* trap-enabler flags */ + uint32_t status; /* status flags */ + uint8_t clamp; /* flag: apply IEEE exponent clamp */ + #if DECSUBSET + uint8_t extended; /* flag: special-values allowed */ + #endif + } decContext; + + /* Maxima and Minima for context settings */ + #define DEC_MAX_DIGITS 999999999 + #define DEC_MIN_DIGITS 1 + #define DEC_MAX_EMAX 999999999 + #define DEC_MIN_EMAX 0 + #define DEC_MAX_EMIN 0 + #define DEC_MIN_EMIN -999999999 + #define DEC_MAX_MATH 999999 /* max emax, etc., for math funcs. */ + + /* Classifications for decimal numbers, aligned with 754 (note that */ + /* 'normal' and 'subnormal' are meaningful only with a decContext */ + /* or a fixed size format). */ + enum decClass { + DEC_CLASS_SNAN, + DEC_CLASS_QNAN, + DEC_CLASS_NEG_INF, + DEC_CLASS_NEG_NORMAL, + DEC_CLASS_NEG_SUBNORMAL, + DEC_CLASS_NEG_ZERO, + DEC_CLASS_POS_ZERO, + DEC_CLASS_POS_SUBNORMAL, + DEC_CLASS_POS_NORMAL, + DEC_CLASS_POS_INF + }; + /* Strings for the decClasses */ + #define DEC_ClassString_SN "sNaN" + #define DEC_ClassString_QN "NaN" + #define DEC_ClassString_NI "-Infinity" + #define DEC_ClassString_NN "-Normal" + #define DEC_ClassString_NS "-Subnormal" + #define DEC_ClassString_NZ "-Zero" + #define DEC_ClassString_PZ "+Zero" + #define DEC_ClassString_PS "+Subnormal" + #define DEC_ClassString_PN "+Normal" + #define DEC_ClassString_PI "+Infinity" + #define DEC_ClassString_UN "Invalid" + + /* Trap-enabler and Status flags (exceptional conditions), and */ + /* their names. The top byte is reserved for internal use */ + #if DECEXTFLAG + /* Extended flags */ + #define DEC_Conversion_syntax 0x00000001 + #define DEC_Division_by_zero 0x00000002 + #define DEC_Division_impossible 0x00000004 + #define DEC_Division_undefined 0x00000008 + #define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */ + #define DEC_Inexact 0x00000020 + #define DEC_Invalid_context 0x00000040 + #define DEC_Invalid_operation 0x00000080 + #if DECSUBSET + #define DEC_Lost_digits 0x00000100 + #endif + #define DEC_Overflow 0x00000200 + #define DEC_Clamped 0x00000400 + #define DEC_Rounded 0x00000800 + #define DEC_Subnormal 0x00001000 + #define DEC_Underflow 0x00002000 + #else + /* IEEE flags only */ + #define DEC_Conversion_syntax 0x00000010 + #define DEC_Division_by_zero 0x00000002 + #define DEC_Division_impossible 0x00000010 + #define DEC_Division_undefined 0x00000010 + #define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */ + #define DEC_Inexact 0x00000001 + #define DEC_Invalid_context 0x00000010 + #define DEC_Invalid_operation 0x00000010 + #if DECSUBSET + #define DEC_Lost_digits 0x00000000 + #endif + #define DEC_Overflow 0x00000008 + #define DEC_Clamped 0x00000000 + #define DEC_Rounded 0x00000000 + #define DEC_Subnormal 0x00000000 + #define DEC_Underflow 0x00000004 + #endif + + /* IEEE 754 groupings for the flags */ + /* [DEC_Clamped, DEC_Lost_digits, DEC_Rounded, and DEC_Subnormal */ + /* are not in IEEE 754] */ + #define DEC_IEEE_754_Division_by_zero (DEC_Division_by_zero) + #if DECSUBSET + #define DEC_IEEE_754_Inexact (DEC_Inexact | DEC_Lost_digits) + #else + #define DEC_IEEE_754_Inexact (DEC_Inexact) + #endif + #define DEC_IEEE_754_Invalid_operation (DEC_Conversion_syntax | \ + DEC_Division_impossible | \ + DEC_Division_undefined | \ + DEC_Insufficient_storage | \ + DEC_Invalid_context | \ + DEC_Invalid_operation) + #define DEC_IEEE_754_Overflow (DEC_Overflow) + #define DEC_IEEE_754_Underflow (DEC_Underflow) + + /* flags which are normally errors (result is qNaN, infinite, or 0) */ + #define DEC_Errors (DEC_IEEE_754_Division_by_zero | \ + DEC_IEEE_754_Invalid_operation | \ + DEC_IEEE_754_Overflow | DEC_IEEE_754_Underflow) + /* flags which cause a result to become qNaN */ + #define DEC_NaNs DEC_IEEE_754_Invalid_operation + + /* flags which are normally for information only (finite results) */ + #if DECSUBSET + #define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact \ + | DEC_Lost_digits) + #else + #define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact) + #endif + + /* IEEE 854 names (for compatibility with older decNumber versions) */ + #define DEC_IEEE_854_Division_by_zero DEC_IEEE_754_Division_by_zero + #define DEC_IEEE_854_Inexact DEC_IEEE_754_Inexact + #define DEC_IEEE_854_Invalid_operation DEC_IEEE_754_Invalid_operation + #define DEC_IEEE_854_Overflow DEC_IEEE_754_Overflow + #define DEC_IEEE_854_Underflow DEC_IEEE_754_Underflow + + /* Name strings for the exceptional conditions */ + #define DEC_Condition_CS "Conversion syntax" + #define DEC_Condition_DZ "Division by zero" + #define DEC_Condition_DI "Division impossible" + #define DEC_Condition_DU "Division undefined" + #define DEC_Condition_IE "Inexact" + #define DEC_Condition_IS "Insufficient storage" + #define DEC_Condition_IC "Invalid context" + #define DEC_Condition_IO "Invalid operation" + #if DECSUBSET + #define DEC_Condition_LD "Lost digits" + #endif + #define DEC_Condition_OV "Overflow" + #define DEC_Condition_PA "Clamped" + #define DEC_Condition_RO "Rounded" + #define DEC_Condition_SU "Subnormal" + #define DEC_Condition_UN "Underflow" + #define DEC_Condition_ZE "No status" + #define DEC_Condition_MU "Multiple status" + #define DEC_Condition_Length 21 /* length of the longest string, */ + /* including terminator */ + + /* Initialization descriptors, used by decContextDefault */ + #define DEC_INIT_BASE 0 + #define DEC_INIT_DECIMAL32 32 + #define DEC_INIT_DECIMAL64 64 + #define DEC_INIT_DECIMAL128 128 + /* Synonyms */ + #define DEC_INIT_DECSINGLE DEC_INIT_DECIMAL32 + #define DEC_INIT_DECDOUBLE DEC_INIT_DECIMAL64 + #define DEC_INIT_DECQUAD DEC_INIT_DECIMAL128 + + /* decContext routines */ + extern decContext * decContextClearStatus(decContext *, uint32_t); + extern decContext * decContextDefault(decContext *, int32_t); + extern enum rounding decContextGetRounding(decContext *); + extern uint32_t decContextGetStatus(decContext *); + extern decContext * decContextRestoreStatus(decContext *, uint32_t, uint32_t); + extern uint32_t decContextSaveStatus(decContext *, uint32_t); + extern decContext * decContextSetRounding(decContext *, enum rounding); + extern decContext * decContextSetStatus(decContext *, uint32_t); + extern decContext * decContextSetStatusFromString(decContext *, const char *); + extern decContext * decContextSetStatusFromStringQuiet(decContext *, const char *); + extern decContext * decContextSetStatusQuiet(decContext *, uint32_t); + extern const char * decContextStatusToString(const decContext *); + extern int32_t decContextTestEndian(uint8_t); + extern uint32_t decContextTestSavedStatus(uint32_t, uint32_t); + extern uint32_t decContextTestStatus(decContext *, uint32_t); + extern decContext * decContextZeroStatus(decContext *); + +#endif diff --git a/src/decNumber/decDPD.h b/src/decNumber/decDPD.h new file mode 100644 index 0000000000..e6a80c0e4c --- /dev/null +++ b/src/decNumber/decDPD.h @@ -0,0 +1,1185 @@ +/* ------------------------------------------------------------------------ */ +/* Binary Coded Decimal and Densely Packed Decimal conversion lookup tables */ +/* [Automatically generated -- do not edit. 2008.06.21] */ +/* ------------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2008. All rights reserved. */ +/* ------------------------------------------------------------------------ */ +/* For details, see DPDecimal.html on the General Decimal Arithmetic page. */ +/* */ +/* This include file defines several DPD and BCD conversion tables: */ +/* */ +/* uint16_t BCD2DPD[2458]; -- BCD -> DPD (0x999 => 2457) */ +/* uint16_t BIN2DPD[1000]; -- Bin -> DPD (999 => 2457) */ +/* uint8_t BIN2CHAR[4001]; -- Bin -> CHAR (999 => '\3' '9' '9' '9') */ +/* uint8_t BIN2BCD8[4000]; -- Bin -> bytes (999 => 9 9 9 3) */ +/* uint16_t DPD2BCD[1024]; -- DPD -> BCD (0x3FF => 0x999) */ +/* uint16_t DPD2BIN[1024]; -- DPD -> BIN (0x3FF => 999) */ +/* uint32_t DPD2BINK[1024]; -- DPD -> BIN * 1000 (0x3FF => 999000) */ +/* uint32_t DPD2BINM[1024]; -- DPD -> BIN * 1E+6 (0x3FF => 999000000) */ +/* uint8_t DPD2BCD8[4096]; -- DPD -> bytes (x3FF => 9 9 9 3) */ +/* */ +/* In all cases the result (10 bits or 12 bits, or binary) is right-aligned */ +/* in the table entry. BIN2CHAR entries are a single byte length (0 for */ +/* value 0) followed by three digit characters; a trailing terminator is */ +/* included to allow 4-char moves always. BIN2BCD8 and DPD2BCD8 entries */ +/* are similar with the three BCD8 digits followed by a one-byte length */ +/* (again, length=0 for value 0). */ +/* */ +/* To use a table, its name, prefixed with DEC_, must be defined with a */ +/* value of 1 before this header file is included. For example: */ +/* #define DEC_BCD2DPD 1 */ +/* This mechanism allows software to only include tables that are needed. */ +/* ------------------------------------------------------------------------ */ + +#if defined(DEC_BCD2DPD) && DEC_BCD2DPD==1 && !defined(DECBCD2DPD) +#define DECBCD2DPD + +const uint16_t BCD2DPD[2458]={ 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 0, 0, 0, 0, 0, 0, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 0, 0, 0, 0, 0, + 0, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 0, 0, + 0, 0, 0, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 0, 0, 0, 0, 0, 0, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 0, 0, 0, 0, 0, 0, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 0, 0, 0, 0, 0, 0, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 0, 0, 0, + 0, 0, 0, 10, 11, 42, 43, 74, 75, 106, 107, 78, 79, + 0, 0, 0, 0, 0, 0, 26, 27, 58, 59, 90, 91, 122, + 123, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 0, 0, + 0, 0, 0, 0, 144, 145, 146, 147, 148, 149, 150, 151, 152, + 153, 0, 0, 0, 0, 0, 0, 160, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 0, 0, 0, 0, 0, 0, 176, 177, 178, + 179, 180, 181, 182, 183, 184, 185, 0, 0, 0, 0, 0, 0, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 0, 0, 0, + 0, 0, 0, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, + 0, 0, 0, 0, 0, 0, 224, 225, 226, 227, 228, 229, 230, + 231, 232, 233, 0, 0, 0, 0, 0, 0, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 0, 0, 0, 0, 0, 0, 138, + 139, 170, 171, 202, 203, 234, 235, 206, 207, 0, 0, 0, 0, + 0, 0, 154, 155, 186, 187, 218, 219, 250, 251, 222, 223, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 257, 258, + 259, 260, 261, 262, 263, 264, 265, 0, 0, 0, 0, 0, 0, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 0, 0, 0, + 0, 0, 0, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, + 0, 0, 0, 0, 0, 0, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 0, 0, 0, 0, 0, 0, 320, 321, 322, 323, + 324, 325, 326, 327, 328, 329, 0, 0, 0, 0, 0, 0, 336, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 0, 0, 0, 0, + 0, 0, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 0, 0, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 0, 0, 0, 0, 0, 0, 266, 267, 298, 299, 330, + 331, 362, 363, 334, 335, 0, 0, 0, 0, 0, 0, 282, 283, + 314, 315, 346, 347, 378, 379, 350, 351, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 384, 385, 386, 387, 388, 389, 390, + 391, 392, 393, 0, 0, 0, 0, 0, 0, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 0, 0, 0, 0, 0, 0, 416, + 417, 418, 419, 420, 421, 422, 423, 424, 425, 0, 0, 0, 0, + 0, 0, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 0, + 0, 0, 0, 0, 0, 448, 449, 450, 451, 452, 453, 454, 455, + 456, 457, 0, 0, 0, 0, 0, 0, 464, 465, 466, 467, 468, + 469, 470, 471, 472, 473, 0, 0, 0, 0, 0, 0, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 0, 0, 0, 0, 0, + 0, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 0, 0, + 0, 0, 0, 0, 394, 395, 426, 427, 458, 459, 490, 491, 462, + 463, 0, 0, 0, 0, 0, 0, 410, 411, 442, 443, 474, 475, + 506, 507, 478, 479, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 0, + 0, 0, 0, 0, 0, 528, 529, 530, 531, 532, 533, 534, 535, + 536, 537, 0, 0, 0, 0, 0, 0, 544, 545, 546, 547, 548, + 549, 550, 551, 552, 553, 0, 0, 0, 0, 0, 0, 560, 561, + 562, 563, 564, 565, 566, 567, 568, 569, 0, 0, 0, 0, 0, + 0, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 0, 0, + 0, 0, 0, 0, 592, 593, 594, 595, 596, 597, 598, 599, 600, + 601, 0, 0, 0, 0, 0, 0, 608, 609, 610, 611, 612, 613, + 614, 615, 616, 617, 0, 0, 0, 0, 0, 0, 624, 625, 626, + 627, 628, 629, 630, 631, 632, 633, 0, 0, 0, 0, 0, 0, + 522, 523, 554, 555, 586, 587, 618, 619, 590, 591, 0, 0, 0, + 0, 0, 0, 538, 539, 570, 571, 602, 603, 634, 635, 606, 607, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 640, 641, + 642, 643, 644, 645, 646, 647, 648, 649, 0, 0, 0, 0, 0, + 0, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 0, 0, + 0, 0, 0, 0, 672, 673, 674, 675, 676, 677, 678, 679, 680, + 681, 0, 0, 0, 0, 0, 0, 688, 689, 690, 691, 692, 693, + 694, 695, 696, 697, 0, 0, 0, 0, 0, 0, 704, 705, 706, + 707, 708, 709, 710, 711, 712, 713, 0, 0, 0, 0, 0, 0, + 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 0, 0, 0, + 0, 0, 0, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, + 0, 0, 0, 0, 0, 0, 752, 753, 754, 755, 756, 757, 758, + 759, 760, 761, 0, 0, 0, 0, 0, 0, 650, 651, 682, 683, + 714, 715, 746, 747, 718, 719, 0, 0, 0, 0, 0, 0, 666, + 667, 698, 699, 730, 731, 762, 763, 734, 735, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 768, 769, 770, 771, 772, 773, + 774, 775, 776, 777, 0, 0, 0, 0, 0, 0, 784, 785, 786, + 787, 788, 789, 790, 791, 792, 793, 0, 0, 0, 0, 0, 0, + 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 0, 0, 0, + 0, 0, 0, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, + 0, 0, 0, 0, 0, 0, 832, 833, 834, 835, 836, 837, 838, + 839, 840, 841, 0, 0, 0, 0, 0, 0, 848, 849, 850, 851, + 852, 853, 854, 855, 856, 857, 0, 0, 0, 0, 0, 0, 864, + 865, 866, 867, 868, 869, 870, 871, 872, 873, 0, 0, 0, 0, + 0, 0, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 0, + 0, 0, 0, 0, 0, 778, 779, 810, 811, 842, 843, 874, 875, + 846, 847, 0, 0, 0, 0, 0, 0, 794, 795, 826, 827, 858, + 859, 890, 891, 862, 863, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, + 0, 0, 0, 0, 0, 0, 912, 913, 914, 915, 916, 917, 918, + 919, 920, 921, 0, 0, 0, 0, 0, 0, 928, 929, 930, 931, + 932, 933, 934, 935, 936, 937, 0, 0, 0, 0, 0, 0, 944, + 945, 946, 947, 948, 949, 950, 951, 952, 953, 0, 0, 0, 0, + 0, 0, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 0, + 0, 0, 0, 0, 0, 976, 977, 978, 979, 980, 981, 982, 983, + 984, 985, 0, 0, 0, 0, 0, 0, 992, 993, 994, 995, 996, + 997, 998, 999, 1000, 1001, 0, 0, 0, 0, 0, 0, 1008, 1009, + 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 0, 0, 0, 0, 0, + 0, 906, 907, 938, 939, 970, 971, 1002, 1003, 974, 975, 0, 0, + 0, 0, 0, 0, 922, 923, 954, 955, 986, 987, 1018, 1019, 990, + 991, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 13, 268, 269, 524, 525, 780, 781, 46, 47, 0, 0, 0, 0, + 0, 0, 28, 29, 284, 285, 540, 541, 796, 797, 62, 63, 0, + 0, 0, 0, 0, 0, 44, 45, 300, 301, 556, 557, 812, 813, + 302, 303, 0, 0, 0, 0, 0, 0, 60, 61, 316, 317, 572, + 573, 828, 829, 318, 319, 0, 0, 0, 0, 0, 0, 76, 77, + 332, 333, 588, 589, 844, 845, 558, 559, 0, 0, 0, 0, 0, + 0, 92, 93, 348, 349, 604, 605, 860, 861, 574, 575, 0, 0, + 0, 0, 0, 0, 108, 109, 364, 365, 620, 621, 876, 877, 814, + 815, 0, 0, 0, 0, 0, 0, 124, 125, 380, 381, 636, 637, + 892, 893, 830, 831, 0, 0, 0, 0, 0, 0, 14, 15, 270, + 271, 526, 527, 782, 783, 110, 111, 0, 0, 0, 0, 0, 0, + 30, 31, 286, 287, 542, 543, 798, 799, 126, 127, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 140, 141, 396, 397, 652, + 653, 908, 909, 174, 175, 0, 0, 0, 0, 0, 0, 156, 157, + 412, 413, 668, 669, 924, 925, 190, 191, 0, 0, 0, 0, 0, + 0, 172, 173, 428, 429, 684, 685, 940, 941, 430, 431, 0, 0, + 0, 0, 0, 0, 188, 189, 444, 445, 700, 701, 956, 957, 446, + 447, 0, 0, 0, 0, 0, 0, 204, 205, 460, 461, 716, 717, + 972, 973, 686, 687, 0, 0, 0, 0, 0, 0, 220, 221, 476, + 477, 732, 733, 988, 989, 702, 703, 0, 0, 0, 0, 0, 0, + 236, 237, 492, 493, 748, 749, 1004, 1005, 942, 943, 0, 0, 0, + 0, 0, 0, 252, 253, 508, 509, 764, 765, 1020, 1021, 958, 959, + 0, 0, 0, 0, 0, 0, 142, 143, 398, 399, 654, 655, 910, + 911, 238, 239, 0, 0, 0, 0, 0, 0, 158, 159, 414, 415, + 670, 671, 926, 927, 254, 255}; +#endif + +#if defined(DEC_DPD2BCD) && DEC_DPD2BCD==1 && !defined(DECDPD2BCD) +#define DECDPD2BCD + +const uint16_t DPD2BCD[1024]={ 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 128, 129, 2048, 2049, 2176, 2177, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 144, 145, 2064, 2065, 2192, 2193, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 130, 131, 2080, 2081, 2056, + 2057, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 146, 147, + 2096, 2097, 2072, 2073, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 132, 133, 2112, 2113, 136, 137, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 148, 149, 2128, 2129, 152, 153, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 134, 135, 2144, 2145, 2184, 2185, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 150, 151, 2160, + 2161, 2200, 2201, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 384, 385, 2304, 2305, 2432, 2433, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 400, 401, 2320, 2321, 2448, 2449, 288, 289, 290, 291, + 292, 293, 294, 295, 296, 297, 386, 387, 2336, 2337, 2312, 2313, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 402, 403, 2352, 2353, + 2328, 2329, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 388, + 389, 2368, 2369, 392, 393, 336, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 404, 405, 2384, 2385, 408, 409, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 390, 391, 2400, 2401, 2440, 2441, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 406, 407, 2416, 2417, 2456, + 2457, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 640, 641, + 2050, 2051, 2178, 2179, 528, 529, 530, 531, 532, 533, 534, 535, 536, + 537, 656, 657, 2066, 2067, 2194, 2195, 544, 545, 546, 547, 548, 549, + 550, 551, 552, 553, 642, 643, 2082, 2083, 2088, 2089, 560, 561, 562, + 563, 564, 565, 566, 567, 568, 569, 658, 659, 2098, 2099, 2104, 2105, + 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 644, 645, 2114, + 2115, 648, 649, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, + 660, 661, 2130, 2131, 664, 665, 608, 609, 610, 611, 612, 613, 614, + 615, 616, 617, 646, 647, 2146, 2147, 2184, 2185, 624, 625, 626, 627, + 628, 629, 630, 631, 632, 633, 662, 663, 2162, 2163, 2200, 2201, 768, + 769, 770, 771, 772, 773, 774, 775, 776, 777, 896, 897, 2306, 2307, + 2434, 2435, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 912, + 913, 2322, 2323, 2450, 2451, 800, 801, 802, 803, 804, 805, 806, 807, + 808, 809, 898, 899, 2338, 2339, 2344, 2345, 816, 817, 818, 819, 820, + 821, 822, 823, 824, 825, 914, 915, 2354, 2355, 2360, 2361, 832, 833, + 834, 835, 836, 837, 838, 839, 840, 841, 900, 901, 2370, 2371, 904, + 905, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 916, 917, + 2386, 2387, 920, 921, 864, 865, 866, 867, 868, 869, 870, 871, 872, + 873, 902, 903, 2402, 2403, 2440, 2441, 880, 881, 882, 883, 884, 885, + 886, 887, 888, 889, 918, 919, 2418, 2419, 2456, 2457, 1024, 1025, 1026, + 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1152, 1153, 2052, 2053, 2180, 2181, + 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1168, 1169, 2068, + 2069, 2196, 2197, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, + 1154, 1155, 2084, 2085, 2120, 2121, 1072, 1073, 1074, 1075, 1076, 1077, 1078, + 1079, 1080, 1081, 1170, 1171, 2100, 2101, 2136, 2137, 1088, 1089, 1090, 1091, + 1092, 1093, 1094, 1095, 1096, 1097, 1156, 1157, 2116, 2117, 1160, 1161, 1104, + 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1172, 1173, 2132, 2133, + 1176, 1177, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1158, + 1159, 2148, 2149, 2184, 2185, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, + 1144, 1145, 1174, 1175, 2164, 2165, 2200, 2201, 1280, 1281, 1282, 1283, 1284, + 1285, 1286, 1287, 1288, 1289, 1408, 1409, 2308, 2309, 2436, 2437, 1296, 1297, + 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1424, 1425, 2324, 2325, 2452, + 2453, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1410, 1411, + 2340, 2341, 2376, 2377, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, + 1337, 1426, 1427, 2356, 2357, 2392, 2393, 1344, 1345, 1346, 1347, 1348, 1349, + 1350, 1351, 1352, 1353, 1412, 1413, 2372, 2373, 1416, 1417, 1360, 1361, 1362, + 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1428, 1429, 2388, 2389, 1432, 1433, + 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1414, 1415, 2404, + 2405, 2440, 2441, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, + 1430, 1431, 2420, 2421, 2456, 2457, 1536, 1537, 1538, 1539, 1540, 1541, 1542, + 1543, 1544, 1545, 1664, 1665, 2054, 2055, 2182, 2183, 1552, 1553, 1554, 1555, + 1556, 1557, 1558, 1559, 1560, 1561, 1680, 1681, 2070, 2071, 2198, 2199, 1568, + 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1666, 1667, 2086, 2087, + 2152, 2153, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1682, + 1683, 2102, 2103, 2168, 2169, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, + 1608, 1609, 1668, 1669, 2118, 2119, 1672, 1673, 1616, 1617, 1618, 1619, 1620, + 1621, 1622, 1623, 1624, 1625, 1684, 1685, 2134, 2135, 1688, 1689, 1632, 1633, + 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1670, 1671, 2150, 2151, 2184, + 2185, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1686, 1687, + 2166, 2167, 2200, 2201, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, + 1801, 1920, 1921, 2310, 2311, 2438, 2439, 1808, 1809, 1810, 1811, 1812, 1813, + 1814, 1815, 1816, 1817, 1936, 1937, 2326, 2327, 2454, 2455, 1824, 1825, 1826, + 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1922, 1923, 2342, 2343, 2408, 2409, + 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1938, 1939, 2358, + 2359, 2424, 2425, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, + 1924, 1925, 2374, 2375, 1928, 1929, 1872, 1873, 1874, 1875, 1876, 1877, 1878, + 1879, 1880, 1881, 1940, 1941, 2390, 2391, 1944, 1945, 1888, 1889, 1890, 1891, + 1892, 1893, 1894, 1895, 1896, 1897, 1926, 1927, 2406, 2407, 2440, 2441, 1904, + 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1942, 1943, 2422, 2423, + 2456, 2457}; +#endif + +#if defined(DEC_BIN2DPD) && DEC_BIN2DPD==1 && !defined(DECBIN2DPD) +#define DECBIN2DPD + +const uint16_t BIN2DPD[1000]={ 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 10, 11, 42, 43, 74, 75, + 106, 107, 78, 79, 26, 27, 58, 59, 90, 91, 122, 123, 94, + 95, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 144, 145, + 146, 147, 148, 149, 150, 151, 152, 153, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 208, + 209, 210, 211, 212, 213, 214, 215, 216, 217, 224, 225, 226, 227, + 228, 229, 230, 231, 232, 233, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 138, 139, 170, 171, 202, 203, 234, 235, 206, 207, + 154, 155, 186, 187, 218, 219, 250, 251, 222, 223, 256, 257, 258, + 259, 260, 261, 262, 263, 264, 265, 272, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 288, 289, 290, 291, 292, 293, 294, 295, 296, + 297, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 320, 321, + 322, 323, 324, 325, 326, 327, 328, 329, 336, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 352, 353, 354, 355, 356, 357, 358, 359, + 360, 361, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 266, + 267, 298, 299, 330, 331, 362, 363, 334, 335, 282, 283, 314, 315, + 346, 347, 378, 379, 350, 351, 384, 385, 386, 387, 388, 389, 390, + 391, 392, 393, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 432, 433, 434, + 435, 436, 437, 438, 439, 440, 441, 448, 449, 450, 451, 452, 453, + 454, 455, 456, 457, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 496, 497, + 498, 499, 500, 501, 502, 503, 504, 505, 394, 395, 426, 427, 458, + 459, 490, 491, 462, 463, 410, 411, 442, 443, 474, 475, 506, 507, + 478, 479, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 528, + 529, 530, 531, 532, 533, 534, 535, 536, 537, 544, 545, 546, 547, + 548, 549, 550, 551, 552, 553, 560, 561, 562, 563, 564, 565, 566, + 567, 568, 569, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, + 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 608, 609, 610, + 611, 612, 613, 614, 615, 616, 617, 624, 625, 626, 627, 628, 629, + 630, 631, 632, 633, 522, 523, 554, 555, 586, 587, 618, 619, 590, + 591, 538, 539, 570, 571, 602, 603, 634, 635, 606, 607, 640, 641, + 642, 643, 644, 645, 646, 647, 648, 649, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 672, 673, 674, 675, 676, 677, 678, 679, + 680, 681, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 704, + 705, 706, 707, 708, 709, 710, 711, 712, 713, 720, 721, 722, 723, + 724, 725, 726, 727, 728, 729, 736, 737, 738, 739, 740, 741, 742, + 743, 744, 745, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, + 650, 651, 682, 683, 714, 715, 746, 747, 718, 719, 666, 667, 698, + 699, 730, 731, 762, 763, 734, 735, 768, 769, 770, 771, 772, 773, + 774, 775, 776, 777, 784, 785, 786, 787, 788, 789, 790, 791, 792, + 793, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 816, 817, + 818, 819, 820, 821, 822, 823, 824, 825, 832, 833, 834, 835, 836, + 837, 838, 839, 840, 841, 848, 849, 850, 851, 852, 853, 854, 855, + 856, 857, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 880, + 881, 882, 883, 884, 885, 886, 887, 888, 889, 778, 779, 810, 811, + 842, 843, 874, 875, 846, 847, 794, 795, 826, 827, 858, 859, 890, + 891, 862, 863, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, + 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 928, 929, 930, + 931, 932, 933, 934, 935, 936, 937, 944, 945, 946, 947, 948, 949, + 950, 951, 952, 953, 960, 961, 962, 963, 964, 965, 966, 967, 968, + 969, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 992, 993, + 994, 995, 996, 997, 998, 999, 1000, 1001, 1008, 1009, 1010, 1011, 1012, + 1013, 1014, 1015, 1016, 1017, 906, 907, 938, 939, 970, 971, 1002, 1003, + 974, 975, 922, 923, 954, 955, 986, 987, 1018, 1019, 990, 991, 12, + 13, 268, 269, 524, 525, 780, 781, 46, 47, 28, 29, 284, 285, + 540, 541, 796, 797, 62, 63, 44, 45, 300, 301, 556, 557, 812, + 813, 302, 303, 60, 61, 316, 317, 572, 573, 828, 829, 318, 319, + 76, 77, 332, 333, 588, 589, 844, 845, 558, 559, 92, 93, 348, + 349, 604, 605, 860, 861, 574, 575, 108, 109, 364, 365, 620, 621, + 876, 877, 814, 815, 124, 125, 380, 381, 636, 637, 892, 893, 830, + 831, 14, 15, 270, 271, 526, 527, 782, 783, 110, 111, 30, 31, + 286, 287, 542, 543, 798, 799, 126, 127, 140, 141, 396, 397, 652, + 653, 908, 909, 174, 175, 156, 157, 412, 413, 668, 669, 924, 925, + 190, 191, 172, 173, 428, 429, 684, 685, 940, 941, 430, 431, 188, + 189, 444, 445, 700, 701, 956, 957, 446, 447, 204, 205, 460, 461, + 716, 717, 972, 973, 686, 687, 220, 221, 476, 477, 732, 733, 988, + 989, 702, 703, 236, 237, 492, 493, 748, 749, 1004, 1005, 942, 943, + 252, 253, 508, 509, 764, 765, 1020, 1021, 958, 959, 142, 143, 398, + 399, 654, 655, 910, 911, 238, 239, 158, 159, 414, 415, 670, 671, + 926, 927, 254, 255}; +#endif + +#if defined(DEC_DPD2BIN) && DEC_DPD2BIN==1 && !defined(DECDPD2BIN) +#define DECDPD2BIN + +const uint16_t DPD2BIN[1024]={ 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 80, 81, 800, 801, 880, 881, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 90, 91, 810, 811, 890, 891, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 82, 83, 820, 821, 808, + 809, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 92, 93, + 830, 831, 818, 819, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 84, 85, 840, 841, 88, 89, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 94, 95, 850, 851, 98, 99, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 86, 87, 860, 861, 888, 889, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 96, 97, 870, + 871, 898, 899, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 180, 181, 900, 901, 980, 981, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 190, 191, 910, 911, 990, 991, 120, 121, 122, 123, + 124, 125, 126, 127, 128, 129, 182, 183, 920, 921, 908, 909, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 192, 193, 930, 931, + 918, 919, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 184, + 185, 940, 941, 188, 189, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, 194, 195, 950, 951, 198, 199, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 186, 187, 960, 961, 988, 989, 170, 171, + 172, 173, 174, 175, 176, 177, 178, 179, 196, 197, 970, 971, 998, + 999, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 280, 281, + 802, 803, 882, 883, 210, 211, 212, 213, 214, 215, 216, 217, 218, + 219, 290, 291, 812, 813, 892, 893, 220, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 282, 283, 822, 823, 828, 829, 230, 231, 232, + 233, 234, 235, 236, 237, 238, 239, 292, 293, 832, 833, 838, 839, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 284, 285, 842, + 843, 288, 289, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 294, 295, 852, 853, 298, 299, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 286, 287, 862, 863, 888, 889, 270, 271, 272, 273, + 274, 275, 276, 277, 278, 279, 296, 297, 872, 873, 898, 899, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, 380, 381, 902, 903, + 982, 983, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 390, + 391, 912, 913, 992, 993, 320, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 382, 383, 922, 923, 928, 929, 330, 331, 332, 333, 334, + 335, 336, 337, 338, 339, 392, 393, 932, 933, 938, 939, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, 384, 385, 942, 943, 388, + 389, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 394, 395, + 952, 953, 398, 399, 360, 361, 362, 363, 364, 365, 366, 367, 368, + 369, 386, 387, 962, 963, 988, 989, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 396, 397, 972, 973, 998, 999, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 480, 481, 804, 805, 884, 885, + 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 490, 491, 814, + 815, 894, 895, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, + 482, 483, 824, 825, 848, 849, 430, 431, 432, 433, 434, 435, 436, + 437, 438, 439, 492, 493, 834, 835, 858, 859, 440, 441, 442, 443, + 444, 445, 446, 447, 448, 449, 484, 485, 844, 845, 488, 489, 450, + 451, 452, 453, 454, 455, 456, 457, 458, 459, 494, 495, 854, 855, + 498, 499, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 486, + 487, 864, 865, 888, 889, 470, 471, 472, 473, 474, 475, 476, 477, + 478, 479, 496, 497, 874, 875, 898, 899, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 580, 581, 904, 905, 984, 985, 510, 511, + 512, 513, 514, 515, 516, 517, 518, 519, 590, 591, 914, 915, 994, + 995, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 582, 583, + 924, 925, 948, 949, 530, 531, 532, 533, 534, 535, 536, 537, 538, + 539, 592, 593, 934, 935, 958, 959, 540, 541, 542, 543, 544, 545, + 546, 547, 548, 549, 584, 585, 944, 945, 588, 589, 550, 551, 552, + 553, 554, 555, 556, 557, 558, 559, 594, 595, 954, 955, 598, 599, + 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 586, 587, 964, + 965, 988, 989, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, + 596, 597, 974, 975, 998, 999, 600, 601, 602, 603, 604, 605, 606, + 607, 608, 609, 680, 681, 806, 807, 886, 887, 610, 611, 612, 613, + 614, 615, 616, 617, 618, 619, 690, 691, 816, 817, 896, 897, 620, + 621, 622, 623, 624, 625, 626, 627, 628, 629, 682, 683, 826, 827, + 868, 869, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 692, + 693, 836, 837, 878, 879, 640, 641, 642, 643, 644, 645, 646, 647, + 648, 649, 684, 685, 846, 847, 688, 689, 650, 651, 652, 653, 654, + 655, 656, 657, 658, 659, 694, 695, 856, 857, 698, 699, 660, 661, + 662, 663, 664, 665, 666, 667, 668, 669, 686, 687, 866, 867, 888, + 889, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 696, 697, + 876, 877, 898, 899, 700, 701, 702, 703, 704, 705, 706, 707, 708, + 709, 780, 781, 906, 907, 986, 987, 710, 711, 712, 713, 714, 715, + 716, 717, 718, 719, 790, 791, 916, 917, 996, 997, 720, 721, 722, + 723, 724, 725, 726, 727, 728, 729, 782, 783, 926, 927, 968, 969, + 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 792, 793, 936, + 937, 978, 979, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, + 784, 785, 946, 947, 788, 789, 750, 751, 752, 753, 754, 755, 756, + 757, 758, 759, 794, 795, 956, 957, 798, 799, 760, 761, 762, 763, + 764, 765, 766, 767, 768, 769, 786, 787, 966, 967, 988, 989, 770, + 771, 772, 773, 774, 775, 776, 777, 778, 779, 796, 797, 976, 977, + 998, 999}; +#endif + +#if defined(DEC_DPD2BINK) && DEC_DPD2BINK==1 && !defined(DECDPD2BINK) +#define DECDPD2BINK + +const uint32_t DPD2BINK[1024]={ 0, 1000, 2000, 3000, 4000, 5000, + 6000, 7000, 8000, 9000, 80000, 81000, 800000, 801000, 880000, 881000, + 10000, 11000, 12000, 13000, 14000, 15000, 16000, 17000, 18000, 19000, + 90000, 91000, 810000, 811000, 890000, 891000, 20000, 21000, 22000, 23000, + 24000, 25000, 26000, 27000, 28000, 29000, 82000, 83000, 820000, 821000, + 808000, 809000, 30000, 31000, 32000, 33000, 34000, 35000, 36000, 37000, + 38000, 39000, 92000, 93000, 830000, 831000, 818000, 819000, 40000, 41000, + 42000, 43000, 44000, 45000, 46000, 47000, 48000, 49000, 84000, 85000, + 840000, 841000, 88000, 89000, 50000, 51000, 52000, 53000, 54000, 55000, + 56000, 57000, 58000, 59000, 94000, 95000, 850000, 851000, 98000, 99000, + 60000, 61000, 62000, 63000, 64000, 65000, 66000, 67000, 68000, 69000, + 86000, 87000, 860000, 861000, 888000, 889000, 70000, 71000, 72000, 73000, + 74000, 75000, 76000, 77000, 78000, 79000, 96000, 97000, 870000, 871000, + 898000, 899000, 100000, 101000, 102000, 103000, 104000, 105000, 106000, 107000, + 108000, 109000, 180000, 181000, 900000, 901000, 980000, 981000, 110000, 111000, + 112000, 113000, 114000, 115000, 116000, 117000, 118000, 119000, 190000, 191000, + 910000, 911000, 990000, 991000, 120000, 121000, 122000, 123000, 124000, 125000, + 126000, 127000, 128000, 129000, 182000, 183000, 920000, 921000, 908000, 909000, + 130000, 131000, 132000, 133000, 134000, 135000, 136000, 137000, 138000, 139000, + 192000, 193000, 930000, 931000, 918000, 919000, 140000, 141000, 142000, 143000, + 144000, 145000, 146000, 147000, 148000, 149000, 184000, 185000, 940000, 941000, + 188000, 189000, 150000, 151000, 152000, 153000, 154000, 155000, 156000, 157000, + 158000, 159000, 194000, 195000, 950000, 951000, 198000, 199000, 160000, 161000, + 162000, 163000, 164000, 165000, 166000, 167000, 168000, 169000, 186000, 187000, + 960000, 961000, 988000, 989000, 170000, 171000, 172000, 173000, 174000, 175000, + 176000, 177000, 178000, 179000, 196000, 197000, 970000, 971000, 998000, 999000, + 200000, 201000, 202000, 203000, 204000, 205000, 206000, 207000, 208000, 209000, + 280000, 281000, 802000, 803000, 882000, 883000, 210000, 211000, 212000, 213000, + 214000, 215000, 216000, 217000, 218000, 219000, 290000, 291000, 812000, 813000, + 892000, 893000, 220000, 221000, 222000, 223000, 224000, 225000, 226000, 227000, + 228000, 229000, 282000, 283000, 822000, 823000, 828000, 829000, 230000, 231000, + 232000, 233000, 234000, 235000, 236000, 237000, 238000, 239000, 292000, 293000, + 832000, 833000, 838000, 839000, 240000, 241000, 242000, 243000, 244000, 245000, + 246000, 247000, 248000, 249000, 284000, 285000, 842000, 843000, 288000, 289000, + 250000, 251000, 252000, 253000, 254000, 255000, 256000, 257000, 258000, 259000, + 294000, 295000, 852000, 853000, 298000, 299000, 260000, 261000, 262000, 263000, + 264000, 265000, 266000, 267000, 268000, 269000, 286000, 287000, 862000, 863000, + 888000, 889000, 270000, 271000, 272000, 273000, 274000, 275000, 276000, 277000, + 278000, 279000, 296000, 297000, 872000, 873000, 898000, 899000, 300000, 301000, + 302000, 303000, 304000, 305000, 306000, 307000, 308000, 309000, 380000, 381000, + 902000, 903000, 982000, 983000, 310000, 311000, 312000, 313000, 314000, 315000, + 316000, 317000, 318000, 319000, 390000, 391000, 912000, 913000, 992000, 993000, + 320000, 321000, 322000, 323000, 324000, 325000, 326000, 327000, 328000, 329000, + 382000, 383000, 922000, 923000, 928000, 929000, 330000, 331000, 332000, 333000, + 334000, 335000, 336000, 337000, 338000, 339000, 392000, 393000, 932000, 933000, + 938000, 939000, 340000, 341000, 342000, 343000, 344000, 345000, 346000, 347000, + 348000, 349000, 384000, 385000, 942000, 943000, 388000, 389000, 350000, 351000, + 352000, 353000, 354000, 355000, 356000, 357000, 358000, 359000, 394000, 395000, + 952000, 953000, 398000, 399000, 360000, 361000, 362000, 363000, 364000, 365000, + 366000, 367000, 368000, 369000, 386000, 387000, 962000, 963000, 988000, 989000, + 370000, 371000, 372000, 373000, 374000, 375000, 376000, 377000, 378000, 379000, + 396000, 397000, 972000, 973000, 998000, 999000, 400000, 401000, 402000, 403000, + 404000, 405000, 406000, 407000, 408000, 409000, 480000, 481000, 804000, 805000, + 884000, 885000, 410000, 411000, 412000, 413000, 414000, 415000, 416000, 417000, + 418000, 419000, 490000, 491000, 814000, 815000, 894000, 895000, 420000, 421000, + 422000, 423000, 424000, 425000, 426000, 427000, 428000, 429000, 482000, 483000, + 824000, 825000, 848000, 849000, 430000, 431000, 432000, 433000, 434000, 435000, + 436000, 437000, 438000, 439000, 492000, 493000, 834000, 835000, 858000, 859000, + 440000, 441000, 442000, 443000, 444000, 445000, 446000, 447000, 448000, 449000, + 484000, 485000, 844000, 845000, 488000, 489000, 450000, 451000, 452000, 453000, + 454000, 455000, 456000, 457000, 458000, 459000, 494000, 495000, 854000, 855000, + 498000, 499000, 460000, 461000, 462000, 463000, 464000, 465000, 466000, 467000, + 468000, 469000, 486000, 487000, 864000, 865000, 888000, 889000, 470000, 471000, + 472000, 473000, 474000, 475000, 476000, 477000, 478000, 479000, 496000, 497000, + 874000, 875000, 898000, 899000, 500000, 501000, 502000, 503000, 504000, 505000, + 506000, 507000, 508000, 509000, 580000, 581000, 904000, 905000, 984000, 985000, + 510000, 511000, 512000, 513000, 514000, 515000, 516000, 517000, 518000, 519000, + 590000, 591000, 914000, 915000, 994000, 995000, 520000, 521000, 522000, 523000, + 524000, 525000, 526000, 527000, 528000, 529000, 582000, 583000, 924000, 925000, + 948000, 949000, 530000, 531000, 532000, 533000, 534000, 535000, 536000, 537000, + 538000, 539000, 592000, 593000, 934000, 935000, 958000, 959000, 540000, 541000, + 542000, 543000, 544000, 545000, 546000, 547000, 548000, 549000, 584000, 585000, + 944000, 945000, 588000, 589000, 550000, 551000, 552000, 553000, 554000, 555000, + 556000, 557000, 558000, 559000, 594000, 595000, 954000, 955000, 598000, 599000, + 560000, 561000, 562000, 563000, 564000, 565000, 566000, 567000, 568000, 569000, + 586000, 587000, 964000, 965000, 988000, 989000, 570000, 571000, 572000, 573000, + 574000, 575000, 576000, 577000, 578000, 579000, 596000, 597000, 974000, 975000, + 998000, 999000, 600000, 601000, 602000, 603000, 604000, 605000, 606000, 607000, + 608000, 609000, 680000, 681000, 806000, 807000, 886000, 887000, 610000, 611000, + 612000, 613000, 614000, 615000, 616000, 617000, 618000, 619000, 690000, 691000, + 816000, 817000, 896000, 897000, 620000, 621000, 622000, 623000, 624000, 625000, + 626000, 627000, 628000, 629000, 682000, 683000, 826000, 827000, 868000, 869000, + 630000, 631000, 632000, 633000, 634000, 635000, 636000, 637000, 638000, 639000, + 692000, 693000, 836000, 837000, 878000, 879000, 640000, 641000, 642000, 643000, + 644000, 645000, 646000, 647000, 648000, 649000, 684000, 685000, 846000, 847000, + 688000, 689000, 650000, 651000, 652000, 653000, 654000, 655000, 656000, 657000, + 658000, 659000, 694000, 695000, 856000, 857000, 698000, 699000, 660000, 661000, + 662000, 663000, 664000, 665000, 666000, 667000, 668000, 669000, 686000, 687000, + 866000, 867000, 888000, 889000, 670000, 671000, 672000, 673000, 674000, 675000, + 676000, 677000, 678000, 679000, 696000, 697000, 876000, 877000, 898000, 899000, + 700000, 701000, 702000, 703000, 704000, 705000, 706000, 707000, 708000, 709000, + 780000, 781000, 906000, 907000, 986000, 987000, 710000, 711000, 712000, 713000, + 714000, 715000, 716000, 717000, 718000, 719000, 790000, 791000, 916000, 917000, + 996000, 997000, 720000, 721000, 722000, 723000, 724000, 725000, 726000, 727000, + 728000, 729000, 782000, 783000, 926000, 927000, 968000, 969000, 730000, 731000, + 732000, 733000, 734000, 735000, 736000, 737000, 738000, 739000, 792000, 793000, + 936000, 937000, 978000, 979000, 740000, 741000, 742000, 743000, 744000, 745000, + 746000, 747000, 748000, 749000, 784000, 785000, 946000, 947000, 788000, 789000, + 750000, 751000, 752000, 753000, 754000, 755000, 756000, 757000, 758000, 759000, + 794000, 795000, 956000, 957000, 798000, 799000, 760000, 761000, 762000, 763000, + 764000, 765000, 766000, 767000, 768000, 769000, 786000, 787000, 966000, 967000, + 988000, 989000, 770000, 771000, 772000, 773000, 774000, 775000, 776000, 777000, + 778000, 779000, 796000, 797000, 976000, 977000, 998000, 999000}; +#endif + +#if defined(DEC_DPD2BINM) && DEC_DPD2BINM==1 && !defined(DECDPD2BINM) +#define DECDPD2BINM + +const uint32_t DPD2BINM[1024]={0, 1000000, 2000000, 3000000, 4000000, + 5000000, 6000000, 7000000, 8000000, 9000000, 80000000, 81000000, + 800000000, 801000000, 880000000, 881000000, 10000000, 11000000, 12000000, + 13000000, 14000000, 15000000, 16000000, 17000000, 18000000, 19000000, + 90000000, 91000000, 810000000, 811000000, 890000000, 891000000, 20000000, + 21000000, 22000000, 23000000, 24000000, 25000000, 26000000, 27000000, + 28000000, 29000000, 82000000, 83000000, 820000000, 821000000, 808000000, + 809000000, 30000000, 31000000, 32000000, 33000000, 34000000, 35000000, + 36000000, 37000000, 38000000, 39000000, 92000000, 93000000, 830000000, + 831000000, 818000000, 819000000, 40000000, 41000000, 42000000, 43000000, + 44000000, 45000000, 46000000, 47000000, 48000000, 49000000, 84000000, + 85000000, 840000000, 841000000, 88000000, 89000000, 50000000, 51000000, + 52000000, 53000000, 54000000, 55000000, 56000000, 57000000, 58000000, + 59000000, 94000000, 95000000, 850000000, 851000000, 98000000, 99000000, + 60000000, 61000000, 62000000, 63000000, 64000000, 65000000, 66000000, + 67000000, 68000000, 69000000, 86000000, 87000000, 860000000, 861000000, + 888000000, 889000000, 70000000, 71000000, 72000000, 73000000, 74000000, + 75000000, 76000000, 77000000, 78000000, 79000000, 96000000, 97000000, + 870000000, 871000000, 898000000, 899000000, 100000000, 101000000, 102000000, + 103000000, 104000000, 105000000, 106000000, 107000000, 108000000, 109000000, + 180000000, 181000000, 900000000, 901000000, 980000000, 981000000, 110000000, + 111000000, 112000000, 113000000, 114000000, 115000000, 116000000, 117000000, + 118000000, 119000000, 190000000, 191000000, 910000000, 911000000, 990000000, + 991000000, 120000000, 121000000, 122000000, 123000000, 124000000, 125000000, + 126000000, 127000000, 128000000, 129000000, 182000000, 183000000, 920000000, + 921000000, 908000000, 909000000, 130000000, 131000000, 132000000, 133000000, + 134000000, 135000000, 136000000, 137000000, 138000000, 139000000, 192000000, + 193000000, 930000000, 931000000, 918000000, 919000000, 140000000, 141000000, + 142000000, 143000000, 144000000, 145000000, 146000000, 147000000, 148000000, + 149000000, 184000000, 185000000, 940000000, 941000000, 188000000, 189000000, + 150000000, 151000000, 152000000, 153000000, 154000000, 155000000, 156000000, + 157000000, 158000000, 159000000, 194000000, 195000000, 950000000, 951000000, + 198000000, 199000000, 160000000, 161000000, 162000000, 163000000, 164000000, + 165000000, 166000000, 167000000, 168000000, 169000000, 186000000, 187000000, + 960000000, 961000000, 988000000, 989000000, 170000000, 171000000, 172000000, + 173000000, 174000000, 175000000, 176000000, 177000000, 178000000, 179000000, + 196000000, 197000000, 970000000, 971000000, 998000000, 999000000, 200000000, + 201000000, 202000000, 203000000, 204000000, 205000000, 206000000, 207000000, + 208000000, 209000000, 280000000, 281000000, 802000000, 803000000, 882000000, + 883000000, 210000000, 211000000, 212000000, 213000000, 214000000, 215000000, + 216000000, 217000000, 218000000, 219000000, 290000000, 291000000, 812000000, + 813000000, 892000000, 893000000, 220000000, 221000000, 222000000, 223000000, + 224000000, 225000000, 226000000, 227000000, 228000000, 229000000, 282000000, + 283000000, 822000000, 823000000, 828000000, 829000000, 230000000, 231000000, + 232000000, 233000000, 234000000, 235000000, 236000000, 237000000, 238000000, + 239000000, 292000000, 293000000, 832000000, 833000000, 838000000, 839000000, + 240000000, 241000000, 242000000, 243000000, 244000000, 245000000, 246000000, + 247000000, 248000000, 249000000, 284000000, 285000000, 842000000, 843000000, + 288000000, 289000000, 250000000, 251000000, 252000000, 253000000, 254000000, + 255000000, 256000000, 257000000, 258000000, 259000000, 294000000, 295000000, + 852000000, 853000000, 298000000, 299000000, 260000000, 261000000, 262000000, + 263000000, 264000000, 265000000, 266000000, 267000000, 268000000, 269000000, + 286000000, 287000000, 862000000, 863000000, 888000000, 889000000, 270000000, + 271000000, 272000000, 273000000, 274000000, 275000000, 276000000, 277000000, + 278000000, 279000000, 296000000, 297000000, 872000000, 873000000, 898000000, + 899000000, 300000000, 301000000, 302000000, 303000000, 304000000, 305000000, + 306000000, 307000000, 308000000, 309000000, 380000000, 381000000, 902000000, + 903000000, 982000000, 983000000, 310000000, 311000000, 312000000, 313000000, + 314000000, 315000000, 316000000, 317000000, 318000000, 319000000, 390000000, + 391000000, 912000000, 913000000, 992000000, 993000000, 320000000, 321000000, + 322000000, 323000000, 324000000, 325000000, 326000000, 327000000, 328000000, + 329000000, 382000000, 383000000, 922000000, 923000000, 928000000, 929000000, + 330000000, 331000000, 332000000, 333000000, 334000000, 335000000, 336000000, + 337000000, 338000000, 339000000, 392000000, 393000000, 932000000, 933000000, + 938000000, 939000000, 340000000, 341000000, 342000000, 343000000, 344000000, + 345000000, 346000000, 347000000, 348000000, 349000000, 384000000, 385000000, + 942000000, 943000000, 388000000, 389000000, 350000000, 351000000, 352000000, + 353000000, 354000000, 355000000, 356000000, 357000000, 358000000, 359000000, + 394000000, 395000000, 952000000, 953000000, 398000000, 399000000, 360000000, + 361000000, 362000000, 363000000, 364000000, 365000000, 366000000, 367000000, + 368000000, 369000000, 386000000, 387000000, 962000000, 963000000, 988000000, + 989000000, 370000000, 371000000, 372000000, 373000000, 374000000, 375000000, + 376000000, 377000000, 378000000, 379000000, 396000000, 397000000, 972000000, + 973000000, 998000000, 999000000, 400000000, 401000000, 402000000, 403000000, + 404000000, 405000000, 406000000, 407000000, 408000000, 409000000, 480000000, + 481000000, 804000000, 805000000, 884000000, 885000000, 410000000, 411000000, + 412000000, 413000000, 414000000, 415000000, 416000000, 417000000, 418000000, + 419000000, 490000000, 491000000, 814000000, 815000000, 894000000, 895000000, + 420000000, 421000000, 422000000, 423000000, 424000000, 425000000, 426000000, + 427000000, 428000000, 429000000, 482000000, 483000000, 824000000, 825000000, + 848000000, 849000000, 430000000, 431000000, 432000000, 433000000, 434000000, + 435000000, 436000000, 437000000, 438000000, 439000000, 492000000, 493000000, + 834000000, 835000000, 858000000, 859000000, 440000000, 441000000, 442000000, + 443000000, 444000000, 445000000, 446000000, 447000000, 448000000, 449000000, + 484000000, 485000000, 844000000, 845000000, 488000000, 489000000, 450000000, + 451000000, 452000000, 453000000, 454000000, 455000000, 456000000, 457000000, + 458000000, 459000000, 494000000, 495000000, 854000000, 855000000, 498000000, + 499000000, 460000000, 461000000, 462000000, 463000000, 464000000, 465000000, + 466000000, 467000000, 468000000, 469000000, 486000000, 487000000, 864000000, + 865000000, 888000000, 889000000, 470000000, 471000000, 472000000, 473000000, + 474000000, 475000000, 476000000, 477000000, 478000000, 479000000, 496000000, + 497000000, 874000000, 875000000, 898000000, 899000000, 500000000, 501000000, + 502000000, 503000000, 504000000, 505000000, 506000000, 507000000, 508000000, + 509000000, 580000000, 581000000, 904000000, 905000000, 984000000, 985000000, + 510000000, 511000000, 512000000, 513000000, 514000000, 515000000, 516000000, + 517000000, 518000000, 519000000, 590000000, 591000000, 914000000, 915000000, + 994000000, 995000000, 520000000, 521000000, 522000000, 523000000, 524000000, + 525000000, 526000000, 527000000, 528000000, 529000000, 582000000, 583000000, + 924000000, 925000000, 948000000, 949000000, 530000000, 531000000, 532000000, + 533000000, 534000000, 535000000, 536000000, 537000000, 538000000, 539000000, + 592000000, 593000000, 934000000, 935000000, 958000000, 959000000, 540000000, + 541000000, 542000000, 543000000, 544000000, 545000000, 546000000, 547000000, + 548000000, 549000000, 584000000, 585000000, 944000000, 945000000, 588000000, + 589000000, 550000000, 551000000, 552000000, 553000000, 554000000, 555000000, + 556000000, 557000000, 558000000, 559000000, 594000000, 595000000, 954000000, + 955000000, 598000000, 599000000, 560000000, 561000000, 562000000, 563000000, + 564000000, 565000000, 566000000, 567000000, 568000000, 569000000, 586000000, + 587000000, 964000000, 965000000, 988000000, 989000000, 570000000, 571000000, + 572000000, 573000000, 574000000, 575000000, 576000000, 577000000, 578000000, + 579000000, 596000000, 597000000, 974000000, 975000000, 998000000, 999000000, + 600000000, 601000000, 602000000, 603000000, 604000000, 605000000, 606000000, + 607000000, 608000000, 609000000, 680000000, 681000000, 806000000, 807000000, + 886000000, 887000000, 610000000, 611000000, 612000000, 613000000, 614000000, + 615000000, 616000000, 617000000, 618000000, 619000000, 690000000, 691000000, + 816000000, 817000000, 896000000, 897000000, 620000000, 621000000, 622000000, + 623000000, 624000000, 625000000, 626000000, 627000000, 628000000, 629000000, + 682000000, 683000000, 826000000, 827000000, 868000000, 869000000, 630000000, + 631000000, 632000000, 633000000, 634000000, 635000000, 636000000, 637000000, + 638000000, 639000000, 692000000, 693000000, 836000000, 837000000, 878000000, + 879000000, 640000000, 641000000, 642000000, 643000000, 644000000, 645000000, + 646000000, 647000000, 648000000, 649000000, 684000000, 685000000, 846000000, + 847000000, 688000000, 689000000, 650000000, 651000000, 652000000, 653000000, + 654000000, 655000000, 656000000, 657000000, 658000000, 659000000, 694000000, + 695000000, 856000000, 857000000, 698000000, 699000000, 660000000, 661000000, + 662000000, 663000000, 664000000, 665000000, 666000000, 667000000, 668000000, + 669000000, 686000000, 687000000, 866000000, 867000000, 888000000, 889000000, + 670000000, 671000000, 672000000, 673000000, 674000000, 675000000, 676000000, + 677000000, 678000000, 679000000, 696000000, 697000000, 876000000, 877000000, + 898000000, 899000000, 700000000, 701000000, 702000000, 703000000, 704000000, + 705000000, 706000000, 707000000, 708000000, 709000000, 780000000, 781000000, + 906000000, 907000000, 986000000, 987000000, 710000000, 711000000, 712000000, + 713000000, 714000000, 715000000, 716000000, 717000000, 718000000, 719000000, + 790000000, 791000000, 916000000, 917000000, 996000000, 997000000, 720000000, + 721000000, 722000000, 723000000, 724000000, 725000000, 726000000, 727000000, + 728000000, 729000000, 782000000, 783000000, 926000000, 927000000, 968000000, + 969000000, 730000000, 731000000, 732000000, 733000000, 734000000, 735000000, + 736000000, 737000000, 738000000, 739000000, 792000000, 793000000, 936000000, + 937000000, 978000000, 979000000, 740000000, 741000000, 742000000, 743000000, + 744000000, 745000000, 746000000, 747000000, 748000000, 749000000, 784000000, + 785000000, 946000000, 947000000, 788000000, 789000000, 750000000, 751000000, + 752000000, 753000000, 754000000, 755000000, 756000000, 757000000, 758000000, + 759000000, 794000000, 795000000, 956000000, 957000000, 798000000, 799000000, + 760000000, 761000000, 762000000, 763000000, 764000000, 765000000, 766000000, + 767000000, 768000000, 769000000, 786000000, 787000000, 966000000, 967000000, + 988000000, 989000000, 770000000, 771000000, 772000000, 773000000, 774000000, + 775000000, 776000000, 777000000, 778000000, 779000000, 796000000, 797000000, + 976000000, 977000000, 998000000, 999000000}; +#endif + +#if defined(DEC_BIN2CHAR) && DEC_BIN2CHAR==1 && !defined(DECBIN2CHAR) +#define DECBIN2CHAR + +const uint8_t BIN2CHAR[4001]={ + '\0','0','0','0', '\1','0','0','1', '\1','0','0','2', '\1','0','0','3', '\1','0','0','4', + '\1','0','0','5', '\1','0','0','6', '\1','0','0','7', '\1','0','0','8', '\1','0','0','9', + '\2','0','1','0', '\2','0','1','1', '\2','0','1','2', '\2','0','1','3', '\2','0','1','4', + '\2','0','1','5', '\2','0','1','6', '\2','0','1','7', '\2','0','1','8', '\2','0','1','9', + '\2','0','2','0', '\2','0','2','1', '\2','0','2','2', '\2','0','2','3', '\2','0','2','4', + '\2','0','2','5', '\2','0','2','6', '\2','0','2','7', '\2','0','2','8', '\2','0','2','9', + '\2','0','3','0', '\2','0','3','1', '\2','0','3','2', '\2','0','3','3', '\2','0','3','4', + '\2','0','3','5', '\2','0','3','6', '\2','0','3','7', '\2','0','3','8', '\2','0','3','9', + '\2','0','4','0', '\2','0','4','1', '\2','0','4','2', '\2','0','4','3', '\2','0','4','4', + '\2','0','4','5', '\2','0','4','6', '\2','0','4','7', '\2','0','4','8', '\2','0','4','9', + '\2','0','5','0', '\2','0','5','1', '\2','0','5','2', '\2','0','5','3', '\2','0','5','4', + '\2','0','5','5', '\2','0','5','6', '\2','0','5','7', '\2','0','5','8', '\2','0','5','9', + '\2','0','6','0', '\2','0','6','1', '\2','0','6','2', '\2','0','6','3', '\2','0','6','4', + '\2','0','6','5', '\2','0','6','6', '\2','0','6','7', '\2','0','6','8', '\2','0','6','9', + '\2','0','7','0', '\2','0','7','1', '\2','0','7','2', '\2','0','7','3', '\2','0','7','4', + '\2','0','7','5', '\2','0','7','6', '\2','0','7','7', '\2','0','7','8', '\2','0','7','9', + '\2','0','8','0', '\2','0','8','1', '\2','0','8','2', '\2','0','8','3', '\2','0','8','4', + '\2','0','8','5', '\2','0','8','6', '\2','0','8','7', '\2','0','8','8', '\2','0','8','9', + '\2','0','9','0', '\2','0','9','1', '\2','0','9','2', '\2','0','9','3', '\2','0','9','4', + '\2','0','9','5', '\2','0','9','6', '\2','0','9','7', '\2','0','9','8', '\2','0','9','9', + '\3','1','0','0', '\3','1','0','1', '\3','1','0','2', '\3','1','0','3', '\3','1','0','4', + '\3','1','0','5', '\3','1','0','6', '\3','1','0','7', '\3','1','0','8', '\3','1','0','9', + '\3','1','1','0', '\3','1','1','1', '\3','1','1','2', '\3','1','1','3', '\3','1','1','4', + '\3','1','1','5', '\3','1','1','6', '\3','1','1','7', '\3','1','1','8', '\3','1','1','9', + '\3','1','2','0', '\3','1','2','1', '\3','1','2','2', '\3','1','2','3', '\3','1','2','4', + '\3','1','2','5', '\3','1','2','6', '\3','1','2','7', '\3','1','2','8', '\3','1','2','9', + '\3','1','3','0', '\3','1','3','1', '\3','1','3','2', '\3','1','3','3', '\3','1','3','4', + '\3','1','3','5', '\3','1','3','6', '\3','1','3','7', '\3','1','3','8', '\3','1','3','9', + '\3','1','4','0', '\3','1','4','1', '\3','1','4','2', '\3','1','4','3', '\3','1','4','4', + '\3','1','4','5', '\3','1','4','6', '\3','1','4','7', '\3','1','4','8', '\3','1','4','9', + '\3','1','5','0', '\3','1','5','1', '\3','1','5','2', '\3','1','5','3', '\3','1','5','4', + '\3','1','5','5', '\3','1','5','6', '\3','1','5','7', '\3','1','5','8', '\3','1','5','9', + '\3','1','6','0', '\3','1','6','1', '\3','1','6','2', '\3','1','6','3', '\3','1','6','4', + '\3','1','6','5', '\3','1','6','6', '\3','1','6','7', '\3','1','6','8', '\3','1','6','9', + '\3','1','7','0', '\3','1','7','1', '\3','1','7','2', '\3','1','7','3', '\3','1','7','4', + '\3','1','7','5', '\3','1','7','6', '\3','1','7','7', '\3','1','7','8', '\3','1','7','9', + '\3','1','8','0', '\3','1','8','1', '\3','1','8','2', '\3','1','8','3', '\3','1','8','4', + '\3','1','8','5', '\3','1','8','6', '\3','1','8','7', '\3','1','8','8', '\3','1','8','9', + '\3','1','9','0', '\3','1','9','1', '\3','1','9','2', '\3','1','9','3', '\3','1','9','4', + '\3','1','9','5', '\3','1','9','6', '\3','1','9','7', '\3','1','9','8', '\3','1','9','9', + '\3','2','0','0', '\3','2','0','1', '\3','2','0','2', '\3','2','0','3', '\3','2','0','4', + '\3','2','0','5', '\3','2','0','6', '\3','2','0','7', '\3','2','0','8', '\3','2','0','9', + '\3','2','1','0', '\3','2','1','1', '\3','2','1','2', '\3','2','1','3', '\3','2','1','4', + '\3','2','1','5', '\3','2','1','6', '\3','2','1','7', '\3','2','1','8', '\3','2','1','9', + '\3','2','2','0', '\3','2','2','1', '\3','2','2','2', '\3','2','2','3', '\3','2','2','4', + '\3','2','2','5', '\3','2','2','6', '\3','2','2','7', '\3','2','2','8', '\3','2','2','9', + '\3','2','3','0', '\3','2','3','1', '\3','2','3','2', '\3','2','3','3', '\3','2','3','4', + '\3','2','3','5', '\3','2','3','6', '\3','2','3','7', '\3','2','3','8', '\3','2','3','9', + '\3','2','4','0', '\3','2','4','1', '\3','2','4','2', '\3','2','4','3', '\3','2','4','4', + '\3','2','4','5', '\3','2','4','6', '\3','2','4','7', '\3','2','4','8', '\3','2','4','9', + '\3','2','5','0', '\3','2','5','1', '\3','2','5','2', '\3','2','5','3', '\3','2','5','4', + '\3','2','5','5', '\3','2','5','6', '\3','2','5','7', '\3','2','5','8', '\3','2','5','9', + '\3','2','6','0', '\3','2','6','1', '\3','2','6','2', '\3','2','6','3', '\3','2','6','4', + '\3','2','6','5', '\3','2','6','6', '\3','2','6','7', '\3','2','6','8', '\3','2','6','9', + '\3','2','7','0', '\3','2','7','1', '\3','2','7','2', '\3','2','7','3', '\3','2','7','4', + '\3','2','7','5', '\3','2','7','6', '\3','2','7','7', '\3','2','7','8', '\3','2','7','9', + '\3','2','8','0', '\3','2','8','1', '\3','2','8','2', '\3','2','8','3', '\3','2','8','4', + '\3','2','8','5', '\3','2','8','6', '\3','2','8','7', '\3','2','8','8', '\3','2','8','9', + '\3','2','9','0', '\3','2','9','1', '\3','2','9','2', '\3','2','9','3', '\3','2','9','4', + '\3','2','9','5', '\3','2','9','6', '\3','2','9','7', '\3','2','9','8', '\3','2','9','9', + '\3','3','0','0', '\3','3','0','1', '\3','3','0','2', '\3','3','0','3', '\3','3','0','4', + '\3','3','0','5', '\3','3','0','6', '\3','3','0','7', '\3','3','0','8', '\3','3','0','9', + '\3','3','1','0', '\3','3','1','1', '\3','3','1','2', '\3','3','1','3', '\3','3','1','4', + '\3','3','1','5', '\3','3','1','6', '\3','3','1','7', '\3','3','1','8', '\3','3','1','9', + '\3','3','2','0', '\3','3','2','1', '\3','3','2','2', '\3','3','2','3', '\3','3','2','4', + '\3','3','2','5', '\3','3','2','6', '\3','3','2','7', '\3','3','2','8', '\3','3','2','9', + '\3','3','3','0', '\3','3','3','1', '\3','3','3','2', '\3','3','3','3', '\3','3','3','4', + '\3','3','3','5', '\3','3','3','6', '\3','3','3','7', '\3','3','3','8', '\3','3','3','9', + '\3','3','4','0', '\3','3','4','1', '\3','3','4','2', '\3','3','4','3', '\3','3','4','4', + '\3','3','4','5', '\3','3','4','6', '\3','3','4','7', '\3','3','4','8', '\3','3','4','9', + '\3','3','5','0', '\3','3','5','1', '\3','3','5','2', '\3','3','5','3', '\3','3','5','4', + '\3','3','5','5', '\3','3','5','6', '\3','3','5','7', '\3','3','5','8', '\3','3','5','9', + '\3','3','6','0', '\3','3','6','1', '\3','3','6','2', '\3','3','6','3', '\3','3','6','4', + '\3','3','6','5', '\3','3','6','6', '\3','3','6','7', '\3','3','6','8', '\3','3','6','9', + '\3','3','7','0', '\3','3','7','1', '\3','3','7','2', '\3','3','7','3', '\3','3','7','4', + '\3','3','7','5', '\3','3','7','6', '\3','3','7','7', '\3','3','7','8', '\3','3','7','9', + '\3','3','8','0', '\3','3','8','1', '\3','3','8','2', '\3','3','8','3', '\3','3','8','4', + '\3','3','8','5', '\3','3','8','6', '\3','3','8','7', '\3','3','8','8', '\3','3','8','9', + '\3','3','9','0', '\3','3','9','1', '\3','3','9','2', '\3','3','9','3', '\3','3','9','4', + '\3','3','9','5', '\3','3','9','6', '\3','3','9','7', '\3','3','9','8', '\3','3','9','9', + '\3','4','0','0', '\3','4','0','1', '\3','4','0','2', '\3','4','0','3', '\3','4','0','4', + '\3','4','0','5', '\3','4','0','6', '\3','4','0','7', '\3','4','0','8', '\3','4','0','9', + '\3','4','1','0', '\3','4','1','1', '\3','4','1','2', '\3','4','1','3', '\3','4','1','4', + '\3','4','1','5', '\3','4','1','6', '\3','4','1','7', '\3','4','1','8', '\3','4','1','9', + '\3','4','2','0', '\3','4','2','1', '\3','4','2','2', '\3','4','2','3', '\3','4','2','4', + '\3','4','2','5', '\3','4','2','6', '\3','4','2','7', '\3','4','2','8', '\3','4','2','9', + '\3','4','3','0', '\3','4','3','1', '\3','4','3','2', '\3','4','3','3', '\3','4','3','4', + '\3','4','3','5', '\3','4','3','6', '\3','4','3','7', '\3','4','3','8', '\3','4','3','9', + '\3','4','4','0', '\3','4','4','1', '\3','4','4','2', '\3','4','4','3', '\3','4','4','4', + '\3','4','4','5', '\3','4','4','6', '\3','4','4','7', '\3','4','4','8', '\3','4','4','9', + '\3','4','5','0', '\3','4','5','1', '\3','4','5','2', '\3','4','5','3', '\3','4','5','4', + '\3','4','5','5', '\3','4','5','6', '\3','4','5','7', '\3','4','5','8', '\3','4','5','9', + '\3','4','6','0', '\3','4','6','1', '\3','4','6','2', '\3','4','6','3', '\3','4','6','4', + '\3','4','6','5', '\3','4','6','6', '\3','4','6','7', '\3','4','6','8', '\3','4','6','9', + '\3','4','7','0', '\3','4','7','1', '\3','4','7','2', '\3','4','7','3', '\3','4','7','4', + '\3','4','7','5', '\3','4','7','6', '\3','4','7','7', '\3','4','7','8', '\3','4','7','9', + '\3','4','8','0', '\3','4','8','1', '\3','4','8','2', '\3','4','8','3', '\3','4','8','4', + '\3','4','8','5', '\3','4','8','6', '\3','4','8','7', '\3','4','8','8', '\3','4','8','9', + '\3','4','9','0', '\3','4','9','1', '\3','4','9','2', '\3','4','9','3', '\3','4','9','4', + '\3','4','9','5', '\3','4','9','6', '\3','4','9','7', '\3','4','9','8', '\3','4','9','9', + '\3','5','0','0', '\3','5','0','1', '\3','5','0','2', '\3','5','0','3', '\3','5','0','4', + '\3','5','0','5', '\3','5','0','6', '\3','5','0','7', '\3','5','0','8', '\3','5','0','9', + '\3','5','1','0', '\3','5','1','1', '\3','5','1','2', '\3','5','1','3', '\3','5','1','4', + '\3','5','1','5', '\3','5','1','6', '\3','5','1','7', '\3','5','1','8', '\3','5','1','9', + '\3','5','2','0', '\3','5','2','1', '\3','5','2','2', '\3','5','2','3', '\3','5','2','4', + '\3','5','2','5', '\3','5','2','6', '\3','5','2','7', '\3','5','2','8', '\3','5','2','9', + '\3','5','3','0', '\3','5','3','1', '\3','5','3','2', '\3','5','3','3', '\3','5','3','4', + '\3','5','3','5', '\3','5','3','6', '\3','5','3','7', '\3','5','3','8', '\3','5','3','9', + '\3','5','4','0', '\3','5','4','1', '\3','5','4','2', '\3','5','4','3', '\3','5','4','4', + '\3','5','4','5', '\3','5','4','6', '\3','5','4','7', '\3','5','4','8', '\3','5','4','9', + '\3','5','5','0', '\3','5','5','1', '\3','5','5','2', '\3','5','5','3', '\3','5','5','4', + '\3','5','5','5', '\3','5','5','6', '\3','5','5','7', '\3','5','5','8', '\3','5','5','9', + '\3','5','6','0', '\3','5','6','1', '\3','5','6','2', '\3','5','6','3', '\3','5','6','4', + '\3','5','6','5', '\3','5','6','6', '\3','5','6','7', '\3','5','6','8', '\3','5','6','9', + '\3','5','7','0', '\3','5','7','1', '\3','5','7','2', '\3','5','7','3', '\3','5','7','4', + '\3','5','7','5', '\3','5','7','6', '\3','5','7','7', '\3','5','7','8', '\3','5','7','9', + '\3','5','8','0', '\3','5','8','1', '\3','5','8','2', '\3','5','8','3', '\3','5','8','4', + '\3','5','8','5', '\3','5','8','6', '\3','5','8','7', '\3','5','8','8', '\3','5','8','9', + '\3','5','9','0', '\3','5','9','1', '\3','5','9','2', '\3','5','9','3', '\3','5','9','4', + '\3','5','9','5', '\3','5','9','6', '\3','5','9','7', '\3','5','9','8', '\3','5','9','9', + '\3','6','0','0', '\3','6','0','1', '\3','6','0','2', '\3','6','0','3', '\3','6','0','4', + '\3','6','0','5', '\3','6','0','6', '\3','6','0','7', '\3','6','0','8', '\3','6','0','9', + '\3','6','1','0', '\3','6','1','1', '\3','6','1','2', '\3','6','1','3', '\3','6','1','4', + '\3','6','1','5', '\3','6','1','6', '\3','6','1','7', '\3','6','1','8', '\3','6','1','9', + '\3','6','2','0', '\3','6','2','1', '\3','6','2','2', '\3','6','2','3', '\3','6','2','4', + '\3','6','2','5', '\3','6','2','6', '\3','6','2','7', '\3','6','2','8', '\3','6','2','9', + '\3','6','3','0', '\3','6','3','1', '\3','6','3','2', '\3','6','3','3', '\3','6','3','4', + '\3','6','3','5', '\3','6','3','6', '\3','6','3','7', '\3','6','3','8', '\3','6','3','9', + '\3','6','4','0', '\3','6','4','1', '\3','6','4','2', '\3','6','4','3', '\3','6','4','4', + '\3','6','4','5', '\3','6','4','6', '\3','6','4','7', '\3','6','4','8', '\3','6','4','9', + '\3','6','5','0', '\3','6','5','1', '\3','6','5','2', '\3','6','5','3', '\3','6','5','4', + '\3','6','5','5', '\3','6','5','6', '\3','6','5','7', '\3','6','5','8', '\3','6','5','9', + '\3','6','6','0', '\3','6','6','1', '\3','6','6','2', '\3','6','6','3', '\3','6','6','4', + '\3','6','6','5', '\3','6','6','6', '\3','6','6','7', '\3','6','6','8', '\3','6','6','9', + '\3','6','7','0', '\3','6','7','1', '\3','6','7','2', '\3','6','7','3', '\3','6','7','4', + '\3','6','7','5', '\3','6','7','6', '\3','6','7','7', '\3','6','7','8', '\3','6','7','9', + '\3','6','8','0', '\3','6','8','1', '\3','6','8','2', '\3','6','8','3', '\3','6','8','4', + '\3','6','8','5', '\3','6','8','6', '\3','6','8','7', '\3','6','8','8', '\3','6','8','9', + '\3','6','9','0', '\3','6','9','1', '\3','6','9','2', '\3','6','9','3', '\3','6','9','4', + '\3','6','9','5', '\3','6','9','6', '\3','6','9','7', '\3','6','9','8', '\3','6','9','9', + '\3','7','0','0', '\3','7','0','1', '\3','7','0','2', '\3','7','0','3', '\3','7','0','4', + '\3','7','0','5', '\3','7','0','6', '\3','7','0','7', '\3','7','0','8', '\3','7','0','9', + '\3','7','1','0', '\3','7','1','1', '\3','7','1','2', '\3','7','1','3', '\3','7','1','4', + '\3','7','1','5', '\3','7','1','6', '\3','7','1','7', '\3','7','1','8', '\3','7','1','9', + '\3','7','2','0', '\3','7','2','1', '\3','7','2','2', '\3','7','2','3', '\3','7','2','4', + '\3','7','2','5', '\3','7','2','6', '\3','7','2','7', '\3','7','2','8', '\3','7','2','9', + '\3','7','3','0', '\3','7','3','1', '\3','7','3','2', '\3','7','3','3', '\3','7','3','4', + '\3','7','3','5', '\3','7','3','6', '\3','7','3','7', '\3','7','3','8', '\3','7','3','9', + '\3','7','4','0', '\3','7','4','1', '\3','7','4','2', '\3','7','4','3', '\3','7','4','4', + '\3','7','4','5', '\3','7','4','6', '\3','7','4','7', '\3','7','4','8', '\3','7','4','9', + '\3','7','5','0', '\3','7','5','1', '\3','7','5','2', '\3','7','5','3', '\3','7','5','4', + '\3','7','5','5', '\3','7','5','6', '\3','7','5','7', '\3','7','5','8', '\3','7','5','9', + '\3','7','6','0', '\3','7','6','1', '\3','7','6','2', '\3','7','6','3', '\3','7','6','4', + '\3','7','6','5', '\3','7','6','6', '\3','7','6','7', '\3','7','6','8', '\3','7','6','9', + '\3','7','7','0', '\3','7','7','1', '\3','7','7','2', '\3','7','7','3', '\3','7','7','4', + '\3','7','7','5', '\3','7','7','6', '\3','7','7','7', '\3','7','7','8', '\3','7','7','9', + '\3','7','8','0', '\3','7','8','1', '\3','7','8','2', '\3','7','8','3', '\3','7','8','4', + '\3','7','8','5', '\3','7','8','6', '\3','7','8','7', '\3','7','8','8', '\3','7','8','9', + '\3','7','9','0', '\3','7','9','1', '\3','7','9','2', '\3','7','9','3', '\3','7','9','4', + '\3','7','9','5', '\3','7','9','6', '\3','7','9','7', '\3','7','9','8', '\3','7','9','9', + '\3','8','0','0', '\3','8','0','1', '\3','8','0','2', '\3','8','0','3', '\3','8','0','4', + '\3','8','0','5', '\3','8','0','6', '\3','8','0','7', '\3','8','0','8', '\3','8','0','9', + '\3','8','1','0', '\3','8','1','1', '\3','8','1','2', '\3','8','1','3', '\3','8','1','4', + '\3','8','1','5', '\3','8','1','6', '\3','8','1','7', '\3','8','1','8', '\3','8','1','9', + '\3','8','2','0', '\3','8','2','1', '\3','8','2','2', '\3','8','2','3', '\3','8','2','4', + '\3','8','2','5', '\3','8','2','6', '\3','8','2','7', '\3','8','2','8', '\3','8','2','9', + '\3','8','3','0', '\3','8','3','1', '\3','8','3','2', '\3','8','3','3', '\3','8','3','4', + '\3','8','3','5', '\3','8','3','6', '\3','8','3','7', '\3','8','3','8', '\3','8','3','9', + '\3','8','4','0', '\3','8','4','1', '\3','8','4','2', '\3','8','4','3', '\3','8','4','4', + '\3','8','4','5', '\3','8','4','6', '\3','8','4','7', '\3','8','4','8', '\3','8','4','9', + '\3','8','5','0', '\3','8','5','1', '\3','8','5','2', '\3','8','5','3', '\3','8','5','4', + '\3','8','5','5', '\3','8','5','6', '\3','8','5','7', '\3','8','5','8', '\3','8','5','9', + '\3','8','6','0', '\3','8','6','1', '\3','8','6','2', '\3','8','6','3', '\3','8','6','4', + '\3','8','6','5', '\3','8','6','6', '\3','8','6','7', '\3','8','6','8', '\3','8','6','9', + '\3','8','7','0', '\3','8','7','1', '\3','8','7','2', '\3','8','7','3', '\3','8','7','4', + '\3','8','7','5', '\3','8','7','6', '\3','8','7','7', '\3','8','7','8', '\3','8','7','9', + '\3','8','8','0', '\3','8','8','1', '\3','8','8','2', '\3','8','8','3', '\3','8','8','4', + '\3','8','8','5', '\3','8','8','6', '\3','8','8','7', '\3','8','8','8', '\3','8','8','9', + '\3','8','9','0', '\3','8','9','1', '\3','8','9','2', '\3','8','9','3', '\3','8','9','4', + '\3','8','9','5', '\3','8','9','6', '\3','8','9','7', '\3','8','9','8', '\3','8','9','9', + '\3','9','0','0', '\3','9','0','1', '\3','9','0','2', '\3','9','0','3', '\3','9','0','4', + '\3','9','0','5', '\3','9','0','6', '\3','9','0','7', '\3','9','0','8', '\3','9','0','9', + '\3','9','1','0', '\3','9','1','1', '\3','9','1','2', '\3','9','1','3', '\3','9','1','4', + '\3','9','1','5', '\3','9','1','6', '\3','9','1','7', '\3','9','1','8', '\3','9','1','9', + '\3','9','2','0', '\3','9','2','1', '\3','9','2','2', '\3','9','2','3', '\3','9','2','4', + '\3','9','2','5', '\3','9','2','6', '\3','9','2','7', '\3','9','2','8', '\3','9','2','9', + '\3','9','3','0', '\3','9','3','1', '\3','9','3','2', '\3','9','3','3', '\3','9','3','4', + '\3','9','3','5', '\3','9','3','6', '\3','9','3','7', '\3','9','3','8', '\3','9','3','9', + '\3','9','4','0', '\3','9','4','1', '\3','9','4','2', '\3','9','4','3', '\3','9','4','4', + '\3','9','4','5', '\3','9','4','6', '\3','9','4','7', '\3','9','4','8', '\3','9','4','9', + '\3','9','5','0', '\3','9','5','1', '\3','9','5','2', '\3','9','5','3', '\3','9','5','4', + '\3','9','5','5', '\3','9','5','6', '\3','9','5','7', '\3','9','5','8', '\3','9','5','9', + '\3','9','6','0', '\3','9','6','1', '\3','9','6','2', '\3','9','6','3', '\3','9','6','4', + '\3','9','6','5', '\3','9','6','6', '\3','9','6','7', '\3','9','6','8', '\3','9','6','9', + '\3','9','7','0', '\3','9','7','1', '\3','9','7','2', '\3','9','7','3', '\3','9','7','4', + '\3','9','7','5', '\3','9','7','6', '\3','9','7','7', '\3','9','7','8', '\3','9','7','9', + '\3','9','8','0', '\3','9','8','1', '\3','9','8','2', '\3','9','8','3', '\3','9','8','4', + '\3','9','8','5', '\3','9','8','6', '\3','9','8','7', '\3','9','8','8', '\3','9','8','9', + '\3','9','9','0', '\3','9','9','1', '\3','9','9','2', '\3','9','9','3', '\3','9','9','4', + '\3','9','9','5', '\3','9','9','6', '\3','9','9','7', '\3','9','9','8', '\3','9','9','9', '\0'}; +#endif + +#if defined(DEC_DPD2BCD8) && DEC_DPD2BCD8==1 && !defined(DECDPD2BCD8) +#define DECDPD2BCD8 + +const uint8_t DPD2BCD8[4096]={ + 0,0,0,0, 0,0,1,1, 0,0,2,1, 0,0,3,1, 0,0,4,1, 0,0,5,1, 0,0,6,1, 0,0,7,1, 0,0,8,1, + 0,0,9,1, 0,8,0,2, 0,8,1,2, 8,0,0,3, 8,0,1,3, 8,8,0,3, 8,8,1,3, 0,1,0,2, 0,1,1,2, + 0,1,2,2, 0,1,3,2, 0,1,4,2, 0,1,5,2, 0,1,6,2, 0,1,7,2, 0,1,8,2, 0,1,9,2, 0,9,0,2, + 0,9,1,2, 8,1,0,3, 8,1,1,3, 8,9,0,3, 8,9,1,3, 0,2,0,2, 0,2,1,2, 0,2,2,2, 0,2,3,2, + 0,2,4,2, 0,2,5,2, 0,2,6,2, 0,2,7,2, 0,2,8,2, 0,2,9,2, 0,8,2,2, 0,8,3,2, 8,2,0,3, + 8,2,1,3, 8,0,8,3, 8,0,9,3, 0,3,0,2, 0,3,1,2, 0,3,2,2, 0,3,3,2, 0,3,4,2, 0,3,5,2, + 0,3,6,2, 0,3,7,2, 0,3,8,2, 0,3,9,2, 0,9,2,2, 0,9,3,2, 8,3,0,3, 8,3,1,3, 8,1,8,3, + 8,1,9,3, 0,4,0,2, 0,4,1,2, 0,4,2,2, 0,4,3,2, 0,4,4,2, 0,4,5,2, 0,4,6,2, 0,4,7,2, + 0,4,8,2, 0,4,9,2, 0,8,4,2, 0,8,5,2, 8,4,0,3, 8,4,1,3, 0,8,8,2, 0,8,9,2, 0,5,0,2, + 0,5,1,2, 0,5,2,2, 0,5,3,2, 0,5,4,2, 0,5,5,2, 0,5,6,2, 0,5,7,2, 0,5,8,2, 0,5,9,2, + 0,9,4,2, 0,9,5,2, 8,5,0,3, 8,5,1,3, 0,9,8,2, 0,9,9,2, 0,6,0,2, 0,6,1,2, 0,6,2,2, + 0,6,3,2, 0,6,4,2, 0,6,5,2, 0,6,6,2, 0,6,7,2, 0,6,8,2, 0,6,9,2, 0,8,6,2, 0,8,7,2, + 8,6,0,3, 8,6,1,3, 8,8,8,3, 8,8,9,3, 0,7,0,2, 0,7,1,2, 0,7,2,2, 0,7,3,2, 0,7,4,2, + 0,7,5,2, 0,7,6,2, 0,7,7,2, 0,7,8,2, 0,7,9,2, 0,9,6,2, 0,9,7,2, 8,7,0,3, 8,7,1,3, + 8,9,8,3, 8,9,9,3, 1,0,0,3, 1,0,1,3, 1,0,2,3, 1,0,3,3, 1,0,4,3, 1,0,5,3, 1,0,6,3, + 1,0,7,3, 1,0,8,3, 1,0,9,3, 1,8,0,3, 1,8,1,3, 9,0,0,3, 9,0,1,3, 9,8,0,3, 9,8,1,3, + 1,1,0,3, 1,1,1,3, 1,1,2,3, 1,1,3,3, 1,1,4,3, 1,1,5,3, 1,1,6,3, 1,1,7,3, 1,1,8,3, + 1,1,9,3, 1,9,0,3, 1,9,1,3, 9,1,0,3, 9,1,1,3, 9,9,0,3, 9,9,1,3, 1,2,0,3, 1,2,1,3, + 1,2,2,3, 1,2,3,3, 1,2,4,3, 1,2,5,3, 1,2,6,3, 1,2,7,3, 1,2,8,3, 1,2,9,3, 1,8,2,3, + 1,8,3,3, 9,2,0,3, 9,2,1,3, 9,0,8,3, 9,0,9,3, 1,3,0,3, 1,3,1,3, 1,3,2,3, 1,3,3,3, + 1,3,4,3, 1,3,5,3, 1,3,6,3, 1,3,7,3, 1,3,8,3, 1,3,9,3, 1,9,2,3, 1,9,3,3, 9,3,0,3, + 9,3,1,3, 9,1,8,3, 9,1,9,3, 1,4,0,3, 1,4,1,3, 1,4,2,3, 1,4,3,3, 1,4,4,3, 1,4,5,3, + 1,4,6,3, 1,4,7,3, 1,4,8,3, 1,4,9,3, 1,8,4,3, 1,8,5,3, 9,4,0,3, 9,4,1,3, 1,8,8,3, + 1,8,9,3, 1,5,0,3, 1,5,1,3, 1,5,2,3, 1,5,3,3, 1,5,4,3, 1,5,5,3, 1,5,6,3, 1,5,7,3, + 1,5,8,3, 1,5,9,3, 1,9,4,3, 1,9,5,3, 9,5,0,3, 9,5,1,3, 1,9,8,3, 1,9,9,3, 1,6,0,3, + 1,6,1,3, 1,6,2,3, 1,6,3,3, 1,6,4,3, 1,6,5,3, 1,6,6,3, 1,6,7,3, 1,6,8,3, 1,6,9,3, + 1,8,6,3, 1,8,7,3, 9,6,0,3, 9,6,1,3, 9,8,8,3, 9,8,9,3, 1,7,0,3, 1,7,1,3, 1,7,2,3, + 1,7,3,3, 1,7,4,3, 1,7,5,3, 1,7,6,3, 1,7,7,3, 1,7,8,3, 1,7,9,3, 1,9,6,3, 1,9,7,3, + 9,7,0,3, 9,7,1,3, 9,9,8,3, 9,9,9,3, 2,0,0,3, 2,0,1,3, 2,0,2,3, 2,0,3,3, 2,0,4,3, + 2,0,5,3, 2,0,6,3, 2,0,7,3, 2,0,8,3, 2,0,9,3, 2,8,0,3, 2,8,1,3, 8,0,2,3, 8,0,3,3, + 8,8,2,3, 8,8,3,3, 2,1,0,3, 2,1,1,3, 2,1,2,3, 2,1,3,3, 2,1,4,3, 2,1,5,3, 2,1,6,3, + 2,1,7,3, 2,1,8,3, 2,1,9,3, 2,9,0,3, 2,9,1,3, 8,1,2,3, 8,1,3,3, 8,9,2,3, 8,9,3,3, + 2,2,0,3, 2,2,1,3, 2,2,2,3, 2,2,3,3, 2,2,4,3, 2,2,5,3, 2,2,6,3, 2,2,7,3, 2,2,8,3, + 2,2,9,3, 2,8,2,3, 2,8,3,3, 8,2,2,3, 8,2,3,3, 8,2,8,3, 8,2,9,3, 2,3,0,3, 2,3,1,3, + 2,3,2,3, 2,3,3,3, 2,3,4,3, 2,3,5,3, 2,3,6,3, 2,3,7,3, 2,3,8,3, 2,3,9,3, 2,9,2,3, + 2,9,3,3, 8,3,2,3, 8,3,3,3, 8,3,8,3, 8,3,9,3, 2,4,0,3, 2,4,1,3, 2,4,2,3, 2,4,3,3, + 2,4,4,3, 2,4,5,3, 2,4,6,3, 2,4,7,3, 2,4,8,3, 2,4,9,3, 2,8,4,3, 2,8,5,3, 8,4,2,3, + 8,4,3,3, 2,8,8,3, 2,8,9,3, 2,5,0,3, 2,5,1,3, 2,5,2,3, 2,5,3,3, 2,5,4,3, 2,5,5,3, + 2,5,6,3, 2,5,7,3, 2,5,8,3, 2,5,9,3, 2,9,4,3, 2,9,5,3, 8,5,2,3, 8,5,3,3, 2,9,8,3, + 2,9,9,3, 2,6,0,3, 2,6,1,3, 2,6,2,3, 2,6,3,3, 2,6,4,3, 2,6,5,3, 2,6,6,3, 2,6,7,3, + 2,6,8,3, 2,6,9,3, 2,8,6,3, 2,8,7,3, 8,6,2,3, 8,6,3,3, 8,8,8,3, 8,8,9,3, 2,7,0,3, + 2,7,1,3, 2,7,2,3, 2,7,3,3, 2,7,4,3, 2,7,5,3, 2,7,6,3, 2,7,7,3, 2,7,8,3, 2,7,9,3, + 2,9,6,3, 2,9,7,3, 8,7,2,3, 8,7,3,3, 8,9,8,3, 8,9,9,3, 3,0,0,3, 3,0,1,3, 3,0,2,3, + 3,0,3,3, 3,0,4,3, 3,0,5,3, 3,0,6,3, 3,0,7,3, 3,0,8,3, 3,0,9,3, 3,8,0,3, 3,8,1,3, + 9,0,2,3, 9,0,3,3, 9,8,2,3, 9,8,3,3, 3,1,0,3, 3,1,1,3, 3,1,2,3, 3,1,3,3, 3,1,4,3, + 3,1,5,3, 3,1,6,3, 3,1,7,3, 3,1,8,3, 3,1,9,3, 3,9,0,3, 3,9,1,3, 9,1,2,3, 9,1,3,3, + 9,9,2,3, 9,9,3,3, 3,2,0,3, 3,2,1,3, 3,2,2,3, 3,2,3,3, 3,2,4,3, 3,2,5,3, 3,2,6,3, + 3,2,7,3, 3,2,8,3, 3,2,9,3, 3,8,2,3, 3,8,3,3, 9,2,2,3, 9,2,3,3, 9,2,8,3, 9,2,9,3, + 3,3,0,3, 3,3,1,3, 3,3,2,3, 3,3,3,3, 3,3,4,3, 3,3,5,3, 3,3,6,3, 3,3,7,3, 3,3,8,3, + 3,3,9,3, 3,9,2,3, 3,9,3,3, 9,3,2,3, 9,3,3,3, 9,3,8,3, 9,3,9,3, 3,4,0,3, 3,4,1,3, + 3,4,2,3, 3,4,3,3, 3,4,4,3, 3,4,5,3, 3,4,6,3, 3,4,7,3, 3,4,8,3, 3,4,9,3, 3,8,4,3, + 3,8,5,3, 9,4,2,3, 9,4,3,3, 3,8,8,3, 3,8,9,3, 3,5,0,3, 3,5,1,3, 3,5,2,3, 3,5,3,3, + 3,5,4,3, 3,5,5,3, 3,5,6,3, 3,5,7,3, 3,5,8,3, 3,5,9,3, 3,9,4,3, 3,9,5,3, 9,5,2,3, + 9,5,3,3, 3,9,8,3, 3,9,9,3, 3,6,0,3, 3,6,1,3, 3,6,2,3, 3,6,3,3, 3,6,4,3, 3,6,5,3, + 3,6,6,3, 3,6,7,3, 3,6,8,3, 3,6,9,3, 3,8,6,3, 3,8,7,3, 9,6,2,3, 9,6,3,3, 9,8,8,3, + 9,8,9,3, 3,7,0,3, 3,7,1,3, 3,7,2,3, 3,7,3,3, 3,7,4,3, 3,7,5,3, 3,7,6,3, 3,7,7,3, + 3,7,8,3, 3,7,9,3, 3,9,6,3, 3,9,7,3, 9,7,2,3, 9,7,3,3, 9,9,8,3, 9,9,9,3, 4,0,0,3, + 4,0,1,3, 4,0,2,3, 4,0,3,3, 4,0,4,3, 4,0,5,3, 4,0,6,3, 4,0,7,3, 4,0,8,3, 4,0,9,3, + 4,8,0,3, 4,8,1,3, 8,0,4,3, 8,0,5,3, 8,8,4,3, 8,8,5,3, 4,1,0,3, 4,1,1,3, 4,1,2,3, + 4,1,3,3, 4,1,4,3, 4,1,5,3, 4,1,6,3, 4,1,7,3, 4,1,8,3, 4,1,9,3, 4,9,0,3, 4,9,1,3, + 8,1,4,3, 8,1,5,3, 8,9,4,3, 8,9,5,3, 4,2,0,3, 4,2,1,3, 4,2,2,3, 4,2,3,3, 4,2,4,3, + 4,2,5,3, 4,2,6,3, 4,2,7,3, 4,2,8,3, 4,2,9,3, 4,8,2,3, 4,8,3,3, 8,2,4,3, 8,2,5,3, + 8,4,8,3, 8,4,9,3, 4,3,0,3, 4,3,1,3, 4,3,2,3, 4,3,3,3, 4,3,4,3, 4,3,5,3, 4,3,6,3, + 4,3,7,3, 4,3,8,3, 4,3,9,3, 4,9,2,3, 4,9,3,3, 8,3,4,3, 8,3,5,3, 8,5,8,3, 8,5,9,3, + 4,4,0,3, 4,4,1,3, 4,4,2,3, 4,4,3,3, 4,4,4,3, 4,4,5,3, 4,4,6,3, 4,4,7,3, 4,4,8,3, + 4,4,9,3, 4,8,4,3, 4,8,5,3, 8,4,4,3, 8,4,5,3, 4,8,8,3, 4,8,9,3, 4,5,0,3, 4,5,1,3, + 4,5,2,3, 4,5,3,3, 4,5,4,3, 4,5,5,3, 4,5,6,3, 4,5,7,3, 4,5,8,3, 4,5,9,3, 4,9,4,3, + 4,9,5,3, 8,5,4,3, 8,5,5,3, 4,9,8,3, 4,9,9,3, 4,6,0,3, 4,6,1,3, 4,6,2,3, 4,6,3,3, + 4,6,4,3, 4,6,5,3, 4,6,6,3, 4,6,7,3, 4,6,8,3, 4,6,9,3, 4,8,6,3, 4,8,7,3, 8,6,4,3, + 8,6,5,3, 8,8,8,3, 8,8,9,3, 4,7,0,3, 4,7,1,3, 4,7,2,3, 4,7,3,3, 4,7,4,3, 4,7,5,3, + 4,7,6,3, 4,7,7,3, 4,7,8,3, 4,7,9,3, 4,9,6,3, 4,9,7,3, 8,7,4,3, 8,7,5,3, 8,9,8,3, + 8,9,9,3, 5,0,0,3, 5,0,1,3, 5,0,2,3, 5,0,3,3, 5,0,4,3, 5,0,5,3, 5,0,6,3, 5,0,7,3, + 5,0,8,3, 5,0,9,3, 5,8,0,3, 5,8,1,3, 9,0,4,3, 9,0,5,3, 9,8,4,3, 9,8,5,3, 5,1,0,3, + 5,1,1,3, 5,1,2,3, 5,1,3,3, 5,1,4,3, 5,1,5,3, 5,1,6,3, 5,1,7,3, 5,1,8,3, 5,1,9,3, + 5,9,0,3, 5,9,1,3, 9,1,4,3, 9,1,5,3, 9,9,4,3, 9,9,5,3, 5,2,0,3, 5,2,1,3, 5,2,2,3, + 5,2,3,3, 5,2,4,3, 5,2,5,3, 5,2,6,3, 5,2,7,3, 5,2,8,3, 5,2,9,3, 5,8,2,3, 5,8,3,3, + 9,2,4,3, 9,2,5,3, 9,4,8,3, 9,4,9,3, 5,3,0,3, 5,3,1,3, 5,3,2,3, 5,3,3,3, 5,3,4,3, + 5,3,5,3, 5,3,6,3, 5,3,7,3, 5,3,8,3, 5,3,9,3, 5,9,2,3, 5,9,3,3, 9,3,4,3, 9,3,5,3, + 9,5,8,3, 9,5,9,3, 5,4,0,3, 5,4,1,3, 5,4,2,3, 5,4,3,3, 5,4,4,3, 5,4,5,3, 5,4,6,3, + 5,4,7,3, 5,4,8,3, 5,4,9,3, 5,8,4,3, 5,8,5,3, 9,4,4,3, 9,4,5,3, 5,8,8,3, 5,8,9,3, + 5,5,0,3, 5,5,1,3, 5,5,2,3, 5,5,3,3, 5,5,4,3, 5,5,5,3, 5,5,6,3, 5,5,7,3, 5,5,8,3, + 5,5,9,3, 5,9,4,3, 5,9,5,3, 9,5,4,3, 9,5,5,3, 5,9,8,3, 5,9,9,3, 5,6,0,3, 5,6,1,3, + 5,6,2,3, 5,6,3,3, 5,6,4,3, 5,6,5,3, 5,6,6,3, 5,6,7,3, 5,6,8,3, 5,6,9,3, 5,8,6,3, + 5,8,7,3, 9,6,4,3, 9,6,5,3, 9,8,8,3, 9,8,9,3, 5,7,0,3, 5,7,1,3, 5,7,2,3, 5,7,3,3, + 5,7,4,3, 5,7,5,3, 5,7,6,3, 5,7,7,3, 5,7,8,3, 5,7,9,3, 5,9,6,3, 5,9,7,3, 9,7,4,3, + 9,7,5,3, 9,9,8,3, 9,9,9,3, 6,0,0,3, 6,0,1,3, 6,0,2,3, 6,0,3,3, 6,0,4,3, 6,0,5,3, + 6,0,6,3, 6,0,7,3, 6,0,8,3, 6,0,9,3, 6,8,0,3, 6,8,1,3, 8,0,6,3, 8,0,7,3, 8,8,6,3, + 8,8,7,3, 6,1,0,3, 6,1,1,3, 6,1,2,3, 6,1,3,3, 6,1,4,3, 6,1,5,3, 6,1,6,3, 6,1,7,3, + 6,1,8,3, 6,1,9,3, 6,9,0,3, 6,9,1,3, 8,1,6,3, 8,1,7,3, 8,9,6,3, 8,9,7,3, 6,2,0,3, + 6,2,1,3, 6,2,2,3, 6,2,3,3, 6,2,4,3, 6,2,5,3, 6,2,6,3, 6,2,7,3, 6,2,8,3, 6,2,9,3, + 6,8,2,3, 6,8,3,3, 8,2,6,3, 8,2,7,3, 8,6,8,3, 8,6,9,3, 6,3,0,3, 6,3,1,3, 6,3,2,3, + 6,3,3,3, 6,3,4,3, 6,3,5,3, 6,3,6,3, 6,3,7,3, 6,3,8,3, 6,3,9,3, 6,9,2,3, 6,9,3,3, + 8,3,6,3, 8,3,7,3, 8,7,8,3, 8,7,9,3, 6,4,0,3, 6,4,1,3, 6,4,2,3, 6,4,3,3, 6,4,4,3, + 6,4,5,3, 6,4,6,3, 6,4,7,3, 6,4,8,3, 6,4,9,3, 6,8,4,3, 6,8,5,3, 8,4,6,3, 8,4,7,3, + 6,8,8,3, 6,8,9,3, 6,5,0,3, 6,5,1,3, 6,5,2,3, 6,5,3,3, 6,5,4,3, 6,5,5,3, 6,5,6,3, + 6,5,7,3, 6,5,8,3, 6,5,9,3, 6,9,4,3, 6,9,5,3, 8,5,6,3, 8,5,7,3, 6,9,8,3, 6,9,9,3, + 6,6,0,3, 6,6,1,3, 6,6,2,3, 6,6,3,3, 6,6,4,3, 6,6,5,3, 6,6,6,3, 6,6,7,3, 6,6,8,3, + 6,6,9,3, 6,8,6,3, 6,8,7,3, 8,6,6,3, 8,6,7,3, 8,8,8,3, 8,8,9,3, 6,7,0,3, 6,7,1,3, + 6,7,2,3, 6,7,3,3, 6,7,4,3, 6,7,5,3, 6,7,6,3, 6,7,7,3, 6,7,8,3, 6,7,9,3, 6,9,6,3, + 6,9,7,3, 8,7,6,3, 8,7,7,3, 8,9,8,3, 8,9,9,3, 7,0,0,3, 7,0,1,3, 7,0,2,3, 7,0,3,3, + 7,0,4,3, 7,0,5,3, 7,0,6,3, 7,0,7,3, 7,0,8,3, 7,0,9,3, 7,8,0,3, 7,8,1,3, 9,0,6,3, + 9,0,7,3, 9,8,6,3, 9,8,7,3, 7,1,0,3, 7,1,1,3, 7,1,2,3, 7,1,3,3, 7,1,4,3, 7,1,5,3, + 7,1,6,3, 7,1,7,3, 7,1,8,3, 7,1,9,3, 7,9,0,3, 7,9,1,3, 9,1,6,3, 9,1,7,3, 9,9,6,3, + 9,9,7,3, 7,2,0,3, 7,2,1,3, 7,2,2,3, 7,2,3,3, 7,2,4,3, 7,2,5,3, 7,2,6,3, 7,2,7,3, + 7,2,8,3, 7,2,9,3, 7,8,2,3, 7,8,3,3, 9,2,6,3, 9,2,7,3, 9,6,8,3, 9,6,9,3, 7,3,0,3, + 7,3,1,3, 7,3,2,3, 7,3,3,3, 7,3,4,3, 7,3,5,3, 7,3,6,3, 7,3,7,3, 7,3,8,3, 7,3,9,3, + 7,9,2,3, 7,9,3,3, 9,3,6,3, 9,3,7,3, 9,7,8,3, 9,7,9,3, 7,4,0,3, 7,4,1,3, 7,4,2,3, + 7,4,3,3, 7,4,4,3, 7,4,5,3, 7,4,6,3, 7,4,7,3, 7,4,8,3, 7,4,9,3, 7,8,4,3, 7,8,5,3, + 9,4,6,3, 9,4,7,3, 7,8,8,3, 7,8,9,3, 7,5,0,3, 7,5,1,3, 7,5,2,3, 7,5,3,3, 7,5,4,3, + 7,5,5,3, 7,5,6,3, 7,5,7,3, 7,5,8,3, 7,5,9,3, 7,9,4,3, 7,9,5,3, 9,5,6,3, 9,5,7,3, + 7,9,8,3, 7,9,9,3, 7,6,0,3, 7,6,1,3, 7,6,2,3, 7,6,3,3, 7,6,4,3, 7,6,5,3, 7,6,6,3, + 7,6,7,3, 7,6,8,3, 7,6,9,3, 7,8,6,3, 7,8,7,3, 9,6,6,3, 9,6,7,3, 9,8,8,3, 9,8,9,3, + 7,7,0,3, 7,7,1,3, 7,7,2,3, 7,7,3,3, 7,7,4,3, 7,7,5,3, 7,7,6,3, 7,7,7,3, 7,7,8,3, + 7,7,9,3, 7,9,6,3, 7,9,7,3, 9,7,6,3, 9,7,7,3, 9,9,8,3, 9,9,9,3}; +#endif + +#if defined(DEC_BIN2BCD8) && DEC_BIN2BCD8==1 && !defined(DECBIN2BCD8) +#define DECBIN2BCD8 + +const uint8_t BIN2BCD8[4000]={ + 0,0,0,0, 0,0,1,1, 0,0,2,1, 0,0,3,1, 0,0,4,1, 0,0,5,1, 0,0,6,1, 0,0,7,1, 0,0,8,1, + 0,0,9,1, 0,1,0,2, 0,1,1,2, 0,1,2,2, 0,1,3,2, 0,1,4,2, 0,1,5,2, 0,1,6,2, 0,1,7,2, + 0,1,8,2, 0,1,9,2, 0,2,0,2, 0,2,1,2, 0,2,2,2, 0,2,3,2, 0,2,4,2, 0,2,5,2, 0,2,6,2, + 0,2,7,2, 0,2,8,2, 0,2,9,2, 0,3,0,2, 0,3,1,2, 0,3,2,2, 0,3,3,2, 0,3,4,2, 0,3,5,2, + 0,3,6,2, 0,3,7,2, 0,3,8,2, 0,3,9,2, 0,4,0,2, 0,4,1,2, 0,4,2,2, 0,4,3,2, 0,4,4,2, + 0,4,5,2, 0,4,6,2, 0,4,7,2, 0,4,8,2, 0,4,9,2, 0,5,0,2, 0,5,1,2, 0,5,2,2, 0,5,3,2, + 0,5,4,2, 0,5,5,2, 0,5,6,2, 0,5,7,2, 0,5,8,2, 0,5,9,2, 0,6,0,2, 0,6,1,2, 0,6,2,2, + 0,6,3,2, 0,6,4,2, 0,6,5,2, 0,6,6,2, 0,6,7,2, 0,6,8,2, 0,6,9,2, 0,7,0,2, 0,7,1,2, + 0,7,2,2, 0,7,3,2, 0,7,4,2, 0,7,5,2, 0,7,6,2, 0,7,7,2, 0,7,8,2, 0,7,9,2, 0,8,0,2, + 0,8,1,2, 0,8,2,2, 0,8,3,2, 0,8,4,2, 0,8,5,2, 0,8,6,2, 0,8,7,2, 0,8,8,2, 0,8,9,2, + 0,9,0,2, 0,9,1,2, 0,9,2,2, 0,9,3,2, 0,9,4,2, 0,9,5,2, 0,9,6,2, 0,9,7,2, 0,9,8,2, + 0,9,9,2, 1,0,0,3, 1,0,1,3, 1,0,2,3, 1,0,3,3, 1,0,4,3, 1,0,5,3, 1,0,6,3, 1,0,7,3, + 1,0,8,3, 1,0,9,3, 1,1,0,3, 1,1,1,3, 1,1,2,3, 1,1,3,3, 1,1,4,3, 1,1,5,3, 1,1,6,3, + 1,1,7,3, 1,1,8,3, 1,1,9,3, 1,2,0,3, 1,2,1,3, 1,2,2,3, 1,2,3,3, 1,2,4,3, 1,2,5,3, + 1,2,6,3, 1,2,7,3, 1,2,8,3, 1,2,9,3, 1,3,0,3, 1,3,1,3, 1,3,2,3, 1,3,3,3, 1,3,4,3, + 1,3,5,3, 1,3,6,3, 1,3,7,3, 1,3,8,3, 1,3,9,3, 1,4,0,3, 1,4,1,3, 1,4,2,3, 1,4,3,3, + 1,4,4,3, 1,4,5,3, 1,4,6,3, 1,4,7,3, 1,4,8,3, 1,4,9,3, 1,5,0,3, 1,5,1,3, 1,5,2,3, + 1,5,3,3, 1,5,4,3, 1,5,5,3, 1,5,6,3, 1,5,7,3, 1,5,8,3, 1,5,9,3, 1,6,0,3, 1,6,1,3, + 1,6,2,3, 1,6,3,3, 1,6,4,3, 1,6,5,3, 1,6,6,3, 1,6,7,3, 1,6,8,3, 1,6,9,3, 1,7,0,3, + 1,7,1,3, 1,7,2,3, 1,7,3,3, 1,7,4,3, 1,7,5,3, 1,7,6,3, 1,7,7,3, 1,7,8,3, 1,7,9,3, + 1,8,0,3, 1,8,1,3, 1,8,2,3, 1,8,3,3, 1,8,4,3, 1,8,5,3, 1,8,6,3, 1,8,7,3, 1,8,8,3, + 1,8,9,3, 1,9,0,3, 1,9,1,3, 1,9,2,3, 1,9,3,3, 1,9,4,3, 1,9,5,3, 1,9,6,3, 1,9,7,3, + 1,9,8,3, 1,9,9,3, 2,0,0,3, 2,0,1,3, 2,0,2,3, 2,0,3,3, 2,0,4,3, 2,0,5,3, 2,0,6,3, + 2,0,7,3, 2,0,8,3, 2,0,9,3, 2,1,0,3, 2,1,1,3, 2,1,2,3, 2,1,3,3, 2,1,4,3, 2,1,5,3, + 2,1,6,3, 2,1,7,3, 2,1,8,3, 2,1,9,3, 2,2,0,3, 2,2,1,3, 2,2,2,3, 2,2,3,3, 2,2,4,3, + 2,2,5,3, 2,2,6,3, 2,2,7,3, 2,2,8,3, 2,2,9,3, 2,3,0,3, 2,3,1,3, 2,3,2,3, 2,3,3,3, + 2,3,4,3, 2,3,5,3, 2,3,6,3, 2,3,7,3, 2,3,8,3, 2,3,9,3, 2,4,0,3, 2,4,1,3, 2,4,2,3, + 2,4,3,3, 2,4,4,3, 2,4,5,3, 2,4,6,3, 2,4,7,3, 2,4,8,3, 2,4,9,3, 2,5,0,3, 2,5,1,3, + 2,5,2,3, 2,5,3,3, 2,5,4,3, 2,5,5,3, 2,5,6,3, 2,5,7,3, 2,5,8,3, 2,5,9,3, 2,6,0,3, + 2,6,1,3, 2,6,2,3, 2,6,3,3, 2,6,4,3, 2,6,5,3, 2,6,6,3, 2,6,7,3, 2,6,8,3, 2,6,9,3, + 2,7,0,3, 2,7,1,3, 2,7,2,3, 2,7,3,3, 2,7,4,3, 2,7,5,3, 2,7,6,3, 2,7,7,3, 2,7,8,3, + 2,7,9,3, 2,8,0,3, 2,8,1,3, 2,8,2,3, 2,8,3,3, 2,8,4,3, 2,8,5,3, 2,8,6,3, 2,8,7,3, + 2,8,8,3, 2,8,9,3, 2,9,0,3, 2,9,1,3, 2,9,2,3, 2,9,3,3, 2,9,4,3, 2,9,5,3, 2,9,6,3, + 2,9,7,3, 2,9,8,3, 2,9,9,3, 3,0,0,3, 3,0,1,3, 3,0,2,3, 3,0,3,3, 3,0,4,3, 3,0,5,3, + 3,0,6,3, 3,0,7,3, 3,0,8,3, 3,0,9,3, 3,1,0,3, 3,1,1,3, 3,1,2,3, 3,1,3,3, 3,1,4,3, + 3,1,5,3, 3,1,6,3, 3,1,7,3, 3,1,8,3, 3,1,9,3, 3,2,0,3, 3,2,1,3, 3,2,2,3, 3,2,3,3, + 3,2,4,3, 3,2,5,3, 3,2,6,3, 3,2,7,3, 3,2,8,3, 3,2,9,3, 3,3,0,3, 3,3,1,3, 3,3,2,3, + 3,3,3,3, 3,3,4,3, 3,3,5,3, 3,3,6,3, 3,3,7,3, 3,3,8,3, 3,3,9,3, 3,4,0,3, 3,4,1,3, + 3,4,2,3, 3,4,3,3, 3,4,4,3, 3,4,5,3, 3,4,6,3, 3,4,7,3, 3,4,8,3, 3,4,9,3, 3,5,0,3, + 3,5,1,3, 3,5,2,3, 3,5,3,3, 3,5,4,3, 3,5,5,3, 3,5,6,3, 3,5,7,3, 3,5,8,3, 3,5,9,3, + 3,6,0,3, 3,6,1,3, 3,6,2,3, 3,6,3,3, 3,6,4,3, 3,6,5,3, 3,6,6,3, 3,6,7,3, 3,6,8,3, + 3,6,9,3, 3,7,0,3, 3,7,1,3, 3,7,2,3, 3,7,3,3, 3,7,4,3, 3,7,5,3, 3,7,6,3, 3,7,7,3, + 3,7,8,3, 3,7,9,3, 3,8,0,3, 3,8,1,3, 3,8,2,3, 3,8,3,3, 3,8,4,3, 3,8,5,3, 3,8,6,3, + 3,8,7,3, 3,8,8,3, 3,8,9,3, 3,9,0,3, 3,9,1,3, 3,9,2,3, 3,9,3,3, 3,9,4,3, 3,9,5,3, + 3,9,6,3, 3,9,7,3, 3,9,8,3, 3,9,9,3, 4,0,0,3, 4,0,1,3, 4,0,2,3, 4,0,3,3, 4,0,4,3, + 4,0,5,3, 4,0,6,3, 4,0,7,3, 4,0,8,3, 4,0,9,3, 4,1,0,3, 4,1,1,3, 4,1,2,3, 4,1,3,3, + 4,1,4,3, 4,1,5,3, 4,1,6,3, 4,1,7,3, 4,1,8,3, 4,1,9,3, 4,2,0,3, 4,2,1,3, 4,2,2,3, + 4,2,3,3, 4,2,4,3, 4,2,5,3, 4,2,6,3, 4,2,7,3, 4,2,8,3, 4,2,9,3, 4,3,0,3, 4,3,1,3, + 4,3,2,3, 4,3,3,3, 4,3,4,3, 4,3,5,3, 4,3,6,3, 4,3,7,3, 4,3,8,3, 4,3,9,3, 4,4,0,3, + 4,4,1,3, 4,4,2,3, 4,4,3,3, 4,4,4,3, 4,4,5,3, 4,4,6,3, 4,4,7,3, 4,4,8,3, 4,4,9,3, + 4,5,0,3, 4,5,1,3, 4,5,2,3, 4,5,3,3, 4,5,4,3, 4,5,5,3, 4,5,6,3, 4,5,7,3, 4,5,8,3, + 4,5,9,3, 4,6,0,3, 4,6,1,3, 4,6,2,3, 4,6,3,3, 4,6,4,3, 4,6,5,3, 4,6,6,3, 4,6,7,3, + 4,6,8,3, 4,6,9,3, 4,7,0,3, 4,7,1,3, 4,7,2,3, 4,7,3,3, 4,7,4,3, 4,7,5,3, 4,7,6,3, + 4,7,7,3, 4,7,8,3, 4,7,9,3, 4,8,0,3, 4,8,1,3, 4,8,2,3, 4,8,3,3, 4,8,4,3, 4,8,5,3, + 4,8,6,3, 4,8,7,3, 4,8,8,3, 4,8,9,3, 4,9,0,3, 4,9,1,3, 4,9,2,3, 4,9,3,3, 4,9,4,3, + 4,9,5,3, 4,9,6,3, 4,9,7,3, 4,9,8,3, 4,9,9,3, 5,0,0,3, 5,0,1,3, 5,0,2,3, 5,0,3,3, + 5,0,4,3, 5,0,5,3, 5,0,6,3, 5,0,7,3, 5,0,8,3, 5,0,9,3, 5,1,0,3, 5,1,1,3, 5,1,2,3, + 5,1,3,3, 5,1,4,3, 5,1,5,3, 5,1,6,3, 5,1,7,3, 5,1,8,3, 5,1,9,3, 5,2,0,3, 5,2,1,3, + 5,2,2,3, 5,2,3,3, 5,2,4,3, 5,2,5,3, 5,2,6,3, 5,2,7,3, 5,2,8,3, 5,2,9,3, 5,3,0,3, + 5,3,1,3, 5,3,2,3, 5,3,3,3, 5,3,4,3, 5,3,5,3, 5,3,6,3, 5,3,7,3, 5,3,8,3, 5,3,9,3, + 5,4,0,3, 5,4,1,3, 5,4,2,3, 5,4,3,3, 5,4,4,3, 5,4,5,3, 5,4,6,3, 5,4,7,3, 5,4,8,3, + 5,4,9,3, 5,5,0,3, 5,5,1,3, 5,5,2,3, 5,5,3,3, 5,5,4,3, 5,5,5,3, 5,5,6,3, 5,5,7,3, + 5,5,8,3, 5,5,9,3, 5,6,0,3, 5,6,1,3, 5,6,2,3, 5,6,3,3, 5,6,4,3, 5,6,5,3, 5,6,6,3, + 5,6,7,3, 5,6,8,3, 5,6,9,3, 5,7,0,3, 5,7,1,3, 5,7,2,3, 5,7,3,3, 5,7,4,3, 5,7,5,3, + 5,7,6,3, 5,7,7,3, 5,7,8,3, 5,7,9,3, 5,8,0,3, 5,8,1,3, 5,8,2,3, 5,8,3,3, 5,8,4,3, + 5,8,5,3, 5,8,6,3, 5,8,7,3, 5,8,8,3, 5,8,9,3, 5,9,0,3, 5,9,1,3, 5,9,2,3, 5,9,3,3, + 5,9,4,3, 5,9,5,3, 5,9,6,3, 5,9,7,3, 5,9,8,3, 5,9,9,3, 6,0,0,3, 6,0,1,3, 6,0,2,3, + 6,0,3,3, 6,0,4,3, 6,0,5,3, 6,0,6,3, 6,0,7,3, 6,0,8,3, 6,0,9,3, 6,1,0,3, 6,1,1,3, + 6,1,2,3, 6,1,3,3, 6,1,4,3, 6,1,5,3, 6,1,6,3, 6,1,7,3, 6,1,8,3, 6,1,9,3, 6,2,0,3, + 6,2,1,3, 6,2,2,3, 6,2,3,3, 6,2,4,3, 6,2,5,3, 6,2,6,3, 6,2,7,3, 6,2,8,3, 6,2,9,3, + 6,3,0,3, 6,3,1,3, 6,3,2,3, 6,3,3,3, 6,3,4,3, 6,3,5,3, 6,3,6,3, 6,3,7,3, 6,3,8,3, + 6,3,9,3, 6,4,0,3, 6,4,1,3, 6,4,2,3, 6,4,3,3, 6,4,4,3, 6,4,5,3, 6,4,6,3, 6,4,7,3, + 6,4,8,3, 6,4,9,3, 6,5,0,3, 6,5,1,3, 6,5,2,3, 6,5,3,3, 6,5,4,3, 6,5,5,3, 6,5,6,3, + 6,5,7,3, 6,5,8,3, 6,5,9,3, 6,6,0,3, 6,6,1,3, 6,6,2,3, 6,6,3,3, 6,6,4,3, 6,6,5,3, + 6,6,6,3, 6,6,7,3, 6,6,8,3, 6,6,9,3, 6,7,0,3, 6,7,1,3, 6,7,2,3, 6,7,3,3, 6,7,4,3, + 6,7,5,3, 6,7,6,3, 6,7,7,3, 6,7,8,3, 6,7,9,3, 6,8,0,3, 6,8,1,3, 6,8,2,3, 6,8,3,3, + 6,8,4,3, 6,8,5,3, 6,8,6,3, 6,8,7,3, 6,8,8,3, 6,8,9,3, 6,9,0,3, 6,9,1,3, 6,9,2,3, + 6,9,3,3, 6,9,4,3, 6,9,5,3, 6,9,6,3, 6,9,7,3, 6,9,8,3, 6,9,9,3, 7,0,0,3, 7,0,1,3, + 7,0,2,3, 7,0,3,3, 7,0,4,3, 7,0,5,3, 7,0,6,3, 7,0,7,3, 7,0,8,3, 7,0,9,3, 7,1,0,3, + 7,1,1,3, 7,1,2,3, 7,1,3,3, 7,1,4,3, 7,1,5,3, 7,1,6,3, 7,1,7,3, 7,1,8,3, 7,1,9,3, + 7,2,0,3, 7,2,1,3, 7,2,2,3, 7,2,3,3, 7,2,4,3, 7,2,5,3, 7,2,6,3, 7,2,7,3, 7,2,8,3, + 7,2,9,3, 7,3,0,3, 7,3,1,3, 7,3,2,3, 7,3,3,3, 7,3,4,3, 7,3,5,3, 7,3,6,3, 7,3,7,3, + 7,3,8,3, 7,3,9,3, 7,4,0,3, 7,4,1,3, 7,4,2,3, 7,4,3,3, 7,4,4,3, 7,4,5,3, 7,4,6,3, + 7,4,7,3, 7,4,8,3, 7,4,9,3, 7,5,0,3, 7,5,1,3, 7,5,2,3, 7,5,3,3, 7,5,4,3, 7,5,5,3, + 7,5,6,3, 7,5,7,3, 7,5,8,3, 7,5,9,3, 7,6,0,3, 7,6,1,3, 7,6,2,3, 7,6,3,3, 7,6,4,3, + 7,6,5,3, 7,6,6,3, 7,6,7,3, 7,6,8,3, 7,6,9,3, 7,7,0,3, 7,7,1,3, 7,7,2,3, 7,7,3,3, + 7,7,4,3, 7,7,5,3, 7,7,6,3, 7,7,7,3, 7,7,8,3, 7,7,9,3, 7,8,0,3, 7,8,1,3, 7,8,2,3, + 7,8,3,3, 7,8,4,3, 7,8,5,3, 7,8,6,3, 7,8,7,3, 7,8,8,3, 7,8,9,3, 7,9,0,3, 7,9,1,3, + 7,9,2,3, 7,9,3,3, 7,9,4,3, 7,9,5,3, 7,9,6,3, 7,9,7,3, 7,9,8,3, 7,9,9,3, 8,0,0,3, + 8,0,1,3, 8,0,2,3, 8,0,3,3, 8,0,4,3, 8,0,5,3, 8,0,6,3, 8,0,7,3, 8,0,8,3, 8,0,9,3, + 8,1,0,3, 8,1,1,3, 8,1,2,3, 8,1,3,3, 8,1,4,3, 8,1,5,3, 8,1,6,3, 8,1,7,3, 8,1,8,3, + 8,1,9,3, 8,2,0,3, 8,2,1,3, 8,2,2,3, 8,2,3,3, 8,2,4,3, 8,2,5,3, 8,2,6,3, 8,2,7,3, + 8,2,8,3, 8,2,9,3, 8,3,0,3, 8,3,1,3, 8,3,2,3, 8,3,3,3, 8,3,4,3, 8,3,5,3, 8,3,6,3, + 8,3,7,3, 8,3,8,3, 8,3,9,3, 8,4,0,3, 8,4,1,3, 8,4,2,3, 8,4,3,3, 8,4,4,3, 8,4,5,3, + 8,4,6,3, 8,4,7,3, 8,4,8,3, 8,4,9,3, 8,5,0,3, 8,5,1,3, 8,5,2,3, 8,5,3,3, 8,5,4,3, + 8,5,5,3, 8,5,6,3, 8,5,7,3, 8,5,8,3, 8,5,9,3, 8,6,0,3, 8,6,1,3, 8,6,2,3, 8,6,3,3, + 8,6,4,3, 8,6,5,3, 8,6,6,3, 8,6,7,3, 8,6,8,3, 8,6,9,3, 8,7,0,3, 8,7,1,3, 8,7,2,3, + 8,7,3,3, 8,7,4,3, 8,7,5,3, 8,7,6,3, 8,7,7,3, 8,7,8,3, 8,7,9,3, 8,8,0,3, 8,8,1,3, + 8,8,2,3, 8,8,3,3, 8,8,4,3, 8,8,5,3, 8,8,6,3, 8,8,7,3, 8,8,8,3, 8,8,9,3, 8,9,0,3, + 8,9,1,3, 8,9,2,3, 8,9,3,3, 8,9,4,3, 8,9,5,3, 8,9,6,3, 8,9,7,3, 8,9,8,3, 8,9,9,3, + 9,0,0,3, 9,0,1,3, 9,0,2,3, 9,0,3,3, 9,0,4,3, 9,0,5,3, 9,0,6,3, 9,0,7,3, 9,0,8,3, + 9,0,9,3, 9,1,0,3, 9,1,1,3, 9,1,2,3, 9,1,3,3, 9,1,4,3, 9,1,5,3, 9,1,6,3, 9,1,7,3, + 9,1,8,3, 9,1,9,3, 9,2,0,3, 9,2,1,3, 9,2,2,3, 9,2,3,3, 9,2,4,3, 9,2,5,3, 9,2,6,3, + 9,2,7,3, 9,2,8,3, 9,2,9,3, 9,3,0,3, 9,3,1,3, 9,3,2,3, 9,3,3,3, 9,3,4,3, 9,3,5,3, + 9,3,6,3, 9,3,7,3, 9,3,8,3, 9,3,9,3, 9,4,0,3, 9,4,1,3, 9,4,2,3, 9,4,3,3, 9,4,4,3, + 9,4,5,3, 9,4,6,3, 9,4,7,3, 9,4,8,3, 9,4,9,3, 9,5,0,3, 9,5,1,3, 9,5,2,3, 9,5,3,3, + 9,5,4,3, 9,5,5,3, 9,5,6,3, 9,5,7,3, 9,5,8,3, 9,5,9,3, 9,6,0,3, 9,6,1,3, 9,6,2,3, + 9,6,3,3, 9,6,4,3, 9,6,5,3, 9,6,6,3, 9,6,7,3, 9,6,8,3, 9,6,9,3, 9,7,0,3, 9,7,1,3, + 9,7,2,3, 9,7,3,3, 9,7,4,3, 9,7,5,3, 9,7,6,3, 9,7,7,3, 9,7,8,3, 9,7,9,3, 9,8,0,3, + 9,8,1,3, 9,8,2,3, 9,8,3,3, 9,8,4,3, 9,8,5,3, 9,8,6,3, 9,8,7,3, 9,8,8,3, 9,8,9,3, + 9,9,0,3, 9,9,1,3, 9,9,2,3, 9,9,3,3, 9,9,4,3, 9,9,5,3, 9,9,6,3, 9,9,7,3, 9,9,8,3, + 9,9,9,3}; +#endif + diff --git a/src/decNumber/decDouble.c b/src/decNumber/decDouble.c new file mode 100644 index 0000000000..4f5df5323b --- /dev/null +++ b/src/decNumber/decDouble.c @@ -0,0 +1,140 @@ +/* ------------------------------------------------------------------ */ +/* decDouble.c -- decDouble operations module */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is included in the package as decNumber.pdf. This */ +/* document is also available in HTML, together with specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ +/* This module comprises decDouble operations (including conversions) */ +/* ------------------------------------------------------------------ */ + +#include "decContext.h" // public includes +#include "decDouble.h" // .. + +/* Constant mappings for shared code */ +#define DECPMAX DECDOUBLE_Pmax +#define DECEMIN DECDOUBLE_Emin +#define DECEMAX DECDOUBLE_Emax +#define DECEMAXD DECDOUBLE_EmaxD +#define DECBYTES DECDOUBLE_Bytes +#define DECSTRING DECDOUBLE_String +#define DECECONL DECDOUBLE_EconL +#define DECBIAS DECDOUBLE_Bias +#define DECLETS DECDOUBLE_Declets +#define DECQTINY (-DECDOUBLE_Bias) +// parameters of next-wider format +#define DECWBYTES DECQUAD_Bytes +#define DECWPMAX DECQUAD_Pmax +#define DECWECONL DECQUAD_EconL +#define DECWBIAS DECQUAD_Bias + +/* Type and function mappings for shared code */ +#define decFloat decDouble // Type name +#define decFloatWider decQuad // Type name + +// Utilities and conversions (binary results, extractors, etc.) +#define decFloatFromBCD decDoubleFromBCD +#define decFloatFromInt32 decDoubleFromInt32 +#define decFloatFromPacked decDoubleFromPacked +#define decFloatFromPackedChecked decDoubleFromPackedChecked +#define decFloatFromString decDoubleFromString +#define decFloatFromUInt32 decDoubleFromUInt32 +#define decFloatFromWider decDoubleFromWider +#define decFloatGetCoefficient decDoubleGetCoefficient +#define decFloatGetExponent decDoubleGetExponent +#define decFloatSetCoefficient decDoubleSetCoefficient +#define decFloatSetExponent decDoubleSetExponent +#define decFloatShow decDoubleShow +#define decFloatToBCD decDoubleToBCD +#define decFloatToEngString decDoubleToEngString +#define decFloatToInt32 decDoubleToInt32 +#define decFloatToInt32Exact decDoubleToInt32Exact +#define decFloatToPacked decDoubleToPacked +#define decFloatToString decDoubleToString +#define decFloatToUInt32 decDoubleToUInt32 +#define decFloatToUInt32Exact decDoubleToUInt32Exact +#define decFloatToWider decDoubleToWider +#define decFloatZero decDoubleZero + +// Computational (result is a decFloat) +#define decFloatAbs decDoubleAbs +#define decFloatAdd decDoubleAdd +#define decFloatAnd decDoubleAnd +#define decFloatDivide decDoubleDivide +#define decFloatDivideInteger decDoubleDivideInteger +#define decFloatFMA decDoubleFMA +#define decFloatInvert decDoubleInvert +#define decFloatLogB decDoubleLogB +#define decFloatMax decDoubleMax +#define decFloatMaxMag decDoubleMaxMag +#define decFloatMin decDoubleMin +#define decFloatMinMag decDoubleMinMag +#define decFloatMinus decDoubleMinus +#define decFloatMultiply decDoubleMultiply +#define decFloatNextMinus decDoubleNextMinus +#define decFloatNextPlus decDoubleNextPlus +#define decFloatNextToward decDoubleNextToward +#define decFloatOr decDoubleOr +#define decFloatPlus decDoublePlus +#define decFloatQuantize decDoubleQuantize +#define decFloatReduce decDoubleReduce +#define decFloatRemainder decDoubleRemainder +#define decFloatRemainderNear decDoubleRemainderNear +#define decFloatRotate decDoubleRotate +#define decFloatScaleB decDoubleScaleB +#define decFloatShift decDoubleShift +#define decFloatSubtract decDoubleSubtract +#define decFloatToIntegralValue decDoubleToIntegralValue +#define decFloatToIntegralExact decDoubleToIntegralExact +#define decFloatXor decDoubleXor + +// Comparisons +#define decFloatCompare decDoubleCompare +#define decFloatCompareSignal decDoubleCompareSignal +#define decFloatCompareTotal decDoubleCompareTotal +#define decFloatCompareTotalMag decDoubleCompareTotalMag + +// Copies +#define decFloatCanonical decDoubleCanonical +#define decFloatCopy decDoubleCopy +#define decFloatCopyAbs decDoubleCopyAbs +#define decFloatCopyNegate decDoubleCopyNegate +#define decFloatCopySign decDoubleCopySign + +// Non-computational +#define decFloatClass decDoubleClass +#define decFloatClassString decDoubleClassString +#define decFloatDigits decDoubleDigits +#define decFloatIsCanonical decDoubleIsCanonical +#define decFloatIsFinite decDoubleIsFinite +#define decFloatIsInfinite decDoubleIsInfinite +#define decFloatIsInteger decDoubleIsInteger +#define decFloatIsLogical decDoubleIsLogical +#define decFloatIsNaN decDoubleIsNaN +#define decFloatIsNegative decDoubleIsNegative +#define decFloatIsNormal decDoubleIsNormal +#define decFloatIsPositive decDoubleIsPositive +#define decFloatIsSignaling decDoubleIsSignaling +#define decFloatIsSignalling decDoubleIsSignalling +#define decFloatIsSigned decDoubleIsSigned +#define decFloatIsSubnormal decDoubleIsSubnormal +#define decFloatIsZero decDoubleIsZero +#define decFloatRadix decDoubleRadix +#define decFloatSameQuantum decDoubleSameQuantum +#define decFloatVersion decDoubleVersion + +#include "decNumberLocal.h" // local includes (need DECPMAX) +#include "decCommon.c" // non-arithmetic decFloat routines +#include "decBasic.c" // basic formats routines + diff --git a/src/decNumber/decDouble.h b/src/decNumber/decDouble.h new file mode 100644 index 0000000000..fe9c26dcce --- /dev/null +++ b/src/decNumber/decDouble.h @@ -0,0 +1,155 @@ +/* ------------------------------------------------------------------ */ +/* decDouble.h -- Decimal 64-bit format module header */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is included in the package as decNumber.pdf. This */ +/* document is also available in HTML, together with specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ + +#if !defined(DECDOUBLE) + #define DECDOUBLE + + #define DECDOUBLENAME "decimalDouble" /* Short name */ + #define DECDOUBLETITLE "Decimal 64-bit datum" /* Verbose name */ + #define DECDOUBLEAUTHOR "Mike Cowlishaw" /* Who to blame */ + + /* parameters for decDoubles */ + #define DECDOUBLE_Bytes 8 /* length */ + #define DECDOUBLE_Pmax 16 /* maximum precision (digits) */ + #define DECDOUBLE_Emin -383 /* minimum adjusted exponent */ + #define DECDOUBLE_Emax 384 /* maximum adjusted exponent */ + #define DECDOUBLE_EmaxD 3 /* maximum exponent digits */ + #define DECDOUBLE_Bias 398 /* bias for the exponent */ + #define DECDOUBLE_String 25 /* maximum string length, +1 */ + #define DECDOUBLE_EconL 8 /* exponent continuation length */ + #define DECDOUBLE_Declets 5 /* count of declets */ + /* highest biased exponent (Elimit-1) */ + #define DECDOUBLE_Ehigh (DECDOUBLE_Emax + DECDOUBLE_Bias - (DECDOUBLE_Pmax-1)) + + /* Required includes */ + #include "decContext.h" + #include "decQuad.h" + + /* The decDouble decimal 64-bit type, accessible by all sizes */ + typedef union { + uint8_t bytes[DECDOUBLE_Bytes]; /* fields: 1, 5, 8, 50 bits */ + uint16_t shorts[DECDOUBLE_Bytes/2]; + uint32_t words[DECDOUBLE_Bytes/4]; + #if DECUSE64 + uint64_t longs[DECDOUBLE_Bytes/8]; + #endif + } decDouble; + + /* ---------------------------------------------------------------- */ + /* Routines -- implemented as decFloat routines in common files */ + /* ---------------------------------------------------------------- */ + + /* Utilities and conversions, extractors, etc.) */ + extern decDouble * decDoubleFromBCD(decDouble *, int32_t, const uint8_t *, int32_t); + extern decDouble * decDoubleFromInt32(decDouble *, int32_t); + extern decDouble * decDoubleFromPacked(decDouble *, int32_t, const uint8_t *); + extern decDouble * decDoubleFromPackedChecked(decDouble *, int32_t, const uint8_t *); + extern decDouble * decDoubleFromString(decDouble *, const char *, decContext *); + extern decDouble * decDoubleFromUInt32(decDouble *, uint32_t); + extern decDouble * decDoubleFromWider(decDouble *, const decQuad *, decContext *); + extern int32_t decDoubleGetCoefficient(const decDouble *, uint8_t *); + extern int32_t decDoubleGetExponent(const decDouble *); + extern decDouble * decDoubleSetCoefficient(decDouble *, const uint8_t *, int32_t); + extern decDouble * decDoubleSetExponent(decDouble *, decContext *, int32_t); + extern void decDoubleShow(const decDouble *, const char *); + extern int32_t decDoubleToBCD(const decDouble *, int32_t *, uint8_t *); + extern char * decDoubleToEngString(const decDouble *, char *); + extern int32_t decDoubleToInt32(const decDouble *, decContext *, enum rounding); + extern int32_t decDoubleToInt32Exact(const decDouble *, decContext *, enum rounding); + extern int32_t decDoubleToPacked(const decDouble *, int32_t *, uint8_t *); + extern char * decDoubleToString(const decDouble *, char *); + extern uint32_t decDoubleToUInt32(const decDouble *, decContext *, enum rounding); + extern uint32_t decDoubleToUInt32Exact(const decDouble *, decContext *, enum rounding); + extern decQuad * decDoubleToWider(const decDouble *, decQuad *); + extern decDouble * decDoubleZero(decDouble *); + + /* Computational (result is a decDouble) */ + extern decDouble * decDoubleAbs(decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleAdd(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleAnd(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleDivide(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleDivideInteger(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleFMA(decDouble *, const decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleInvert(decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleLogB(decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleMax(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleMaxMag(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleMin(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleMinMag(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleMinus(decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleMultiply(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleNextMinus(decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleNextPlus(decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleNextToward(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleOr(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoublePlus(decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleQuantize(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleReduce(decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleRemainder(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleRemainderNear(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleRotate(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleScaleB(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleShift(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleSubtract(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleToIntegralValue(decDouble *, const decDouble *, decContext *, enum rounding); + extern decDouble * decDoubleToIntegralExact(decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleXor(decDouble *, const decDouble *, const decDouble *, decContext *); + + /* Comparisons */ + extern decDouble * decDoubleCompare(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleCompareSignal(decDouble *, const decDouble *, const decDouble *, decContext *); + extern decDouble * decDoubleCompareTotal(decDouble *, const decDouble *, const decDouble *); + extern decDouble * decDoubleCompareTotalMag(decDouble *, const decDouble *, const decDouble *); + + /* Copies */ + extern decDouble * decDoubleCanonical(decDouble *, const decDouble *); + extern decDouble * decDoubleCopy(decDouble *, const decDouble *); + extern decDouble * decDoubleCopyAbs(decDouble *, const decDouble *); + extern decDouble * decDoubleCopyNegate(decDouble *, const decDouble *); + extern decDouble * decDoubleCopySign(decDouble *, const decDouble *, const decDouble *); + + /* Non-computational */ + extern enum decClass decDoubleClass(const decDouble *); + extern const char * decDoubleClassString(const decDouble *); + extern uint32_t decDoubleDigits(const decDouble *); + extern uint32_t decDoubleIsCanonical(const decDouble *); + extern uint32_t decDoubleIsFinite(const decDouble *); + extern uint32_t decDoubleIsInfinite(const decDouble *); + extern uint32_t decDoubleIsInteger(const decDouble *); + extern uint32_t decDoubleIsLogical(const decDouble *); + extern uint32_t decDoubleIsNaN(const decDouble *); + extern uint32_t decDoubleIsNegative(const decDouble *); + extern uint32_t decDoubleIsNormal(const decDouble *); + extern uint32_t decDoubleIsPositive(const decDouble *); + extern uint32_t decDoubleIsSignaling(const decDouble *); + extern uint32_t decDoubleIsSignalling(const decDouble *); + extern uint32_t decDoubleIsSigned(const decDouble *); + extern uint32_t decDoubleIsSubnormal(const decDouble *); + extern uint32_t decDoubleIsZero(const decDouble *); + extern uint32_t decDoubleRadix(const decDouble *); + extern uint32_t decDoubleSameQuantum(const decDouble *, const decDouble *); + extern const char * decDoubleVersion(void); + + /* decNumber conversions; these are implemented as macros so as not */ + /* to force a dependency on decimal64 and decNumber in decDouble. */ + /* decDoubleFromNumber returns a decimal64 * to avoid warnings. */ + #define decDoubleToNumber(dq, dn) decimal64ToNumber((decimal64 *)(dq), dn) + #define decDoubleFromNumber(dq, dn, set) decimal64FromNumber((decimal64 *)(dq), dn, set) + +#endif diff --git a/src/decNumber/decNumber.c b/src/decNumber/decNumber.c new file mode 100644 index 0000000000..19230b8957 --- /dev/null +++ b/src/decNumber/decNumber.c @@ -0,0 +1,8141 @@ +/* ------------------------------------------------------------------ */ +/* Decimal Number arithmetic module */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2009. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is called decNumber.pdf. This document is */ +/* available, together with arithmetic and format specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ +/* This module comprises the routines for arbitrary-precision General */ +/* Decimal Arithmetic as defined in the specification which may be */ +/* found on the General Decimal Arithmetic pages. It implements both */ +/* the full ('extended') arithmetic and the simpler ('subset') */ +/* arithmetic. */ +/* */ +/* Usage notes: */ +/* */ +/* 1. This code is ANSI C89 except: */ +/* */ +/* a) C99 line comments (double forward slash) are used. (Most C */ +/* compilers accept these. If yours does not, a simple script */ +/* can be used to convert them to ANSI C comments.) */ +/* */ +/* b) Types from C99 stdint.h are used. If you do not have this */ +/* header file, see the User's Guide section of the decNumber */ +/* documentation; this lists the necessary definitions. */ +/* */ +/* c) If DECDPUN>4 or DECUSE64=1, the C99 64-bit int64_t and */ +/* uint64_t types may be used. To avoid these, set DECUSE64=0 */ +/* and DECDPUN<=4 (see documentation). */ +/* */ +/* The code also conforms to C99 restrictions; in particular, */ +/* strict aliasing rules are observed. */ +/* */ +/* 2. The decNumber format which this library uses is optimized for */ +/* efficient processing of relatively short numbers; in particular */ +/* it allows the use of fixed sized structures and minimizes copy */ +/* and move operations. It does, however, support arbitrary */ +/* precision (up to 999,999,999 digits) and arbitrary exponent */ +/* range (Emax in the range 0 through 999,999,999 and Emin in the */ +/* range -999,999,999 through 0). Mathematical functions (for */ +/* example decNumberExp) as identified below are restricted more */ +/* tightly: digits, emax, and -emin in the context must be <= */ +/* DEC_MAX_MATH (999999), and their operand(s) must be within */ +/* these bounds. */ +/* */ +/* 3. Logical functions are further restricted; their operands must */ +/* be finite, positive, have an exponent of zero, and all digits */ +/* must be either 0 or 1. The result will only contain digits */ +/* which are 0 or 1 (and will have exponent=0 and a sign of 0). */ +/* */ +/* 4. Operands to operator functions are never modified unless they */ +/* are also specified to be the result number (which is always */ +/* permitted). Other than that case, operands must not overlap. */ +/* */ +/* 5. Error handling: the type of the error is ORed into the status */ +/* flags in the current context (decContext structure). The */ +/* SIGFPE signal is then raised if the corresponding trap-enabler */ +/* flag in the decContext is set (is 1). */ +/* */ +/* It is the responsibility of the caller to clear the status */ +/* flags as required. */ +/* */ +/* The result of any routine which returns a number will always */ +/* be a valid number (which may be a special value, such as an */ +/* Infinity or NaN). */ +/* */ +/* 6. The decNumber format is not an exchangeable concrete */ +/* representation as it comprises fields which may be machine- */ +/* dependent (packed or unpacked, or special length, for example). */ +/* Canonical conversions to and from strings are provided; other */ +/* conversions are available in separate modules. */ +/* */ +/* 7. Normally, input operands are assumed to be valid. Set DECCHECK */ +/* to 1 for extended operand checking (including NULL operands). */ +/* Results are undefined if a badly-formed structure (or a NULL */ +/* pointer to a structure) is provided, though with DECCHECK */ +/* enabled the operator routines are protected against exceptions. */ +/* (Except if the result pointer is NULL, which is unrecoverable.) */ +/* */ +/* However, the routines will never cause exceptions if they are */ +/* given well-formed operands, even if the value of the operands */ +/* is inappropriate for the operation and DECCHECK is not set. */ +/* (Except for SIGFPE, as and where documented.) */ +/* */ +/* 8. Subset arithmetic is available only if DECSUBSET is set to 1. */ +/* ------------------------------------------------------------------ */ +/* Implementation notes for maintenance of this module: */ +/* */ +/* 1. Storage leak protection: Routines which use malloc are not */ +/* permitted to use return for fastpath or error exits (i.e., */ +/* they follow strict structured programming conventions). */ +/* Instead they have a do{}while(0); construct surrounding the */ +/* code which is protected -- break may be used to exit this. */ +/* Other routines can safely use the return statement inline. */ +/* */ +/* Storage leak accounting can be enabled using DECALLOC. */ +/* */ +/* 2. All loops use the for(;;) construct. Any do construct does */ +/* not loop; it is for allocation protection as just described. */ +/* */ +/* 3. Setting status in the context must always be the very last */ +/* action in a routine, as non-0 status may raise a trap and hence */ +/* the call to set status may not return (if the handler uses long */ +/* jump). Therefore all cleanup must be done first. In general, */ +/* to achieve this status is accumulated and is only applied just */ +/* before return by calling decContextSetStatus (via decStatus). */ +/* */ +/* Routines which allocate storage cannot, in general, use the */ +/* 'top level' routines which could cause a non-returning */ +/* transfer of control. The decXxxxOp routines are safe (do not */ +/* call decStatus even if traps are set in the context) and should */ +/* be used instead (they are also a little faster). */ +/* */ +/* 4. Exponent checking is minimized by allowing the exponent to */ +/* grow outside its limits during calculations, provided that */ +/* the decFinalize function is called later. Multiplication and */ +/* division, and intermediate calculations in exponentiation, */ +/* require more careful checks because of the risk of 31-bit */ +/* overflow (the most negative valid exponent is -1999999997, for */ +/* a 999999999-digit number with adjusted exponent of -999999999). */ +/* */ +/* 5. Rounding is deferred until finalization of results, with any */ +/* 'off to the right' data being represented as a single digit */ +/* residue (in the range -1 through 9). This avoids any double- */ +/* rounding when more than one shortening takes place (for */ +/* example, when a result is subnormal). */ +/* */ +/* 6. The digits count is allowed to rise to a multiple of DECDPUN */ +/* during many operations, so whole Units are handled and exact */ +/* accounting of digits is not needed. The correct digits value */ +/* is found by decGetDigits, which accounts for leading zeros. */ +/* This must be called before any rounding if the number of digits */ +/* is not known exactly. */ +/* */ +/* 7. The multiply-by-reciprocal 'trick' is used for partitioning */ +/* numbers up to four digits, using appropriate constants. This */ +/* is not useful for longer numbers because overflow of 32 bits */ +/* would lead to 4 multiplies, which is almost as expensive as */ +/* a divide (unless a floating-point or 64-bit multiply is */ +/* assumed to be available). */ +/* */ +/* 8. Unusual abbreviations that may be used in the commentary: */ +/* lhs -- left hand side (operand, of an operation) */ +/* lsd -- least significant digit (of coefficient) */ +/* lsu -- least significant Unit (of coefficient) */ +/* msd -- most significant digit (of coefficient) */ +/* msi -- most significant item (in an array) */ +/* msu -- most significant Unit (of coefficient) */ +/* rhs -- right hand side (operand, of an operation) */ +/* +ve -- positive */ +/* -ve -- negative */ +/* ** -- raise to the power */ +/* ------------------------------------------------------------------ */ + +#include // for malloc, free, etc. +#include // for printf [if needed] +#include // for strcpy +#include // for lower +#include "decNumber.h" // base number library +#include "decNumberLocal.h" // decNumber local types, etc. + +/* Constants */ +// Public lookup table used by the D2U macro +const uByte d2utable[DECMAXD2U+1]=D2UTABLE; + +#define DECVERB 1 // set to 1 for verbose DECCHECK +#define powers DECPOWERS // old internal name + +// Local constants +#define DIVIDE 0x80 // Divide operators +#define REMAINDER 0x40 // .. +#define DIVIDEINT 0x20 // .. +#define REMNEAR 0x10 // .. +#define COMPARE 0x01 // Compare operators +#define COMPMAX 0x02 // .. +#define COMPMIN 0x03 // .. +#define COMPTOTAL 0x04 // .. +#define COMPNAN 0x05 // .. [NaN processing] +#define COMPSIG 0x06 // .. [signaling COMPARE] +#define COMPMAXMAG 0x07 // .. +#define COMPMINMAG 0x08 // .. + +#define DEC_sNaN 0x40000000 // local status: sNaN signal +#define BADINT (Int)0x80000000 // most-negative Int; error indicator +// Next two indicate an integer >= 10**6, and its parity (bottom bit) +#define BIGEVEN (Int)0x80000002 +#define BIGODD (Int)0x80000003 + +static Unit uarrone[1]={1}; // Unit array of 1, used for incrementing + +/* Granularity-dependent code */ +#if DECDPUN<=4 + #define eInt Int // extended integer + #define ueInt uInt // unsigned extended integer + // Constant multipliers for divide-by-power-of five using reciprocal + // multiply, after removing powers of 2 by shifting, and final shift + // of 17 [we only need up to **4] + static const uInt multies[]={131073, 26215, 5243, 1049, 210}; + // QUOT10 -- macro to return the quotient of unit u divided by 10**n + #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17) +#else + // For DECDPUN>4 non-ANSI-89 64-bit types are needed. + #if !DECUSE64 + #error decNumber.c: DECUSE64 must be 1 when DECDPUN>4 + #endif + #define eInt Long // extended integer + #define ueInt uLong // unsigned extended integer +#endif + +/* Local routines */ +static decNumber * decAddOp(decNumber *, const decNumber *, const decNumber *, + decContext *, uByte, uInt *); +static Flag decBiStr(const char *, const char *, const char *); +static uInt decCheckMath(const decNumber *, decContext *, uInt *); +static void decApplyRound(decNumber *, decContext *, Int, uInt *); +static Int decCompare(const decNumber *lhs, const decNumber *rhs, Flag); +static decNumber * decCompareOp(decNumber *, const decNumber *, + const decNumber *, decContext *, + Flag, uInt *); +static void decCopyFit(decNumber *, const decNumber *, decContext *, + Int *, uInt *); +static decNumber * decDecap(decNumber *, Int); +static decNumber * decDivideOp(decNumber *, const decNumber *, + const decNumber *, decContext *, Flag, uInt *); +static decNumber * decExpOp(decNumber *, const decNumber *, + decContext *, uInt *); +static void decFinalize(decNumber *, decContext *, Int *, uInt *); +static Int decGetDigits(Unit *, Int); +static Int decGetInt(const decNumber *); +static decNumber * decLnOp(decNumber *, const decNumber *, + decContext *, uInt *); +static decNumber * decMultiplyOp(decNumber *, const decNumber *, + const decNumber *, decContext *, + uInt *); +static decNumber * decNaNs(decNumber *, const decNumber *, + const decNumber *, decContext *, uInt *); +static decNumber * decQuantizeOp(decNumber *, const decNumber *, + const decNumber *, decContext *, Flag, + uInt *); +static void decReverse(Unit *, Unit *); +static void decSetCoeff(decNumber *, decContext *, const Unit *, + Int, Int *, uInt *); +static void decSetMaxValue(decNumber *, decContext *); +static void decSetOverflow(decNumber *, decContext *, uInt *); +static void decSetSubnormal(decNumber *, decContext *, Int *, uInt *); +static Int decShiftToLeast(Unit *, Int, Int); +static Int decShiftToMost(Unit *, Int, Int); +static void decStatus(decNumber *, uInt, decContext *); +static void decToString(const decNumber *, char[], Flag); +static decNumber * decTrim(decNumber *, decContext *, Flag, Flag, Int *); +static Int decUnitAddSub(const Unit *, Int, const Unit *, Int, Int, + Unit *, Int); +static Int decUnitCompare(const Unit *, Int, const Unit *, Int, Int); + +#if !DECSUBSET +/* decFinish == decFinalize when no subset arithmetic needed */ +#define decFinish(a,b,c,d) decFinalize(a,b,c,d) +#else +static void decFinish(decNumber *, decContext *, Int *, uInt *); +static decNumber * decRoundOperand(const decNumber *, decContext *, uInt *); +#endif + +/* Local macros */ +// masked special-values bits +#define SPECIALARG (rhs->bits & DECSPECIAL) +#define SPECIALARGS ((lhs->bits | rhs->bits) & DECSPECIAL) + +/* Diagnostic macros, etc. */ +#if DECALLOC +// Handle malloc/free accounting. If enabled, our accountable routines +// are used; otherwise the code just goes straight to the system malloc +// and free routines. +#define malloc(a) decMalloc(a) +#define free(a) decFree(a) +#define DECFENCE 0x5a // corruption detector +// 'Our' malloc and free: +static void *decMalloc(size_t); +static void decFree(void *); +uInt decAllocBytes=0; // count of bytes allocated +// Note that DECALLOC code only checks for storage buffer overflow. +// To check for memory leaks, the decAllocBytes variable must be +// checked to be 0 at appropriate times (e.g., after the test +// harness completes a set of tests). This checking may be unreliable +// if the testing is done in a multi-thread environment. +#endif + +#if DECCHECK +// Optional checking routines. Enabling these means that decNumber +// and decContext operands to operator routines are checked for +// correctness. This roughly doubles the execution time of the +// fastest routines (and adds 600+ bytes), so should not normally be +// used in 'production'. +// decCheckInexact is used to check that inexact results have a full +// complement of digits (where appropriate -- this is not the case +// for Quantize, for example) +#define DECUNRESU ((decNumber *)(void *)0xffffffff) +#define DECUNUSED ((const decNumber *)(void *)0xffffffff) +#define DECUNCONT ((decContext *)(void *)(0xffffffff)) +static Flag decCheckOperands(decNumber *, const decNumber *, + const decNumber *, decContext *); +static Flag decCheckNumber(const decNumber *); +static void decCheckInexact(const decNumber *, decContext *); +#endif + +#if DECTRACE || DECCHECK +// Optional trace/debugging routines (may or may not be used) +void decNumberShow(const decNumber *); // displays the components of a number +static void decDumpAr(char, const Unit *, Int); +#endif + +/* ================================================================== */ +/* Conversions */ +/* ================================================================== */ + +/* ------------------------------------------------------------------ */ +/* from-int32 -- conversion from Int or uInt */ +/* */ +/* dn is the decNumber to receive the integer */ +/* in or uin is the integer to be converted */ +/* returns dn */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberFromInt32(decNumber *dn, Int in) { + uInt unsig; + if (in>=0) unsig=in; + else { // negative (possibly BADINT) + if (in==BADINT) unsig=(uInt)1073741824*2; // special case + else unsig=-in; // invert + } + // in is now positive + decNumberFromUInt32(dn, unsig); + if (in<0) dn->bits=DECNEG; // sign needed + return dn; + } // decNumberFromInt32 + +decNumber * decNumberFromUInt32(decNumber *dn, uInt uin) { + Unit *up; // work pointer + decNumberZero(dn); // clean + if (uin==0) return dn; // [or decGetDigits bad call] + for (up=dn->lsu; uin>0; up++) { + *up=(Unit)(uin%(DECDPUNMAX+1)); + uin=uin/(DECDPUNMAX+1); + } + dn->digits=decGetDigits(dn->lsu, up-dn->lsu); + return dn; + } // decNumberFromUInt32 + +/* ------------------------------------------------------------------ */ +/* to-int32 -- conversion to Int or uInt */ +/* */ +/* dn is the decNumber to convert */ +/* set is the context for reporting errors */ +/* returns the converted decNumber, or 0 if Invalid is set */ +/* */ +/* Invalid is set if the decNumber does not have exponent==0 or if */ +/* it is a NaN, Infinite, or out-of-range. */ +/* ------------------------------------------------------------------ */ +Int decNumberToInt32(const decNumber *dn, decContext *set) { + #if DECCHECK + if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0; + #endif + + // special or too many digits, or bad exponent + if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0) ; // bad + else { // is a finite integer with 10 or fewer digits + Int d; // work + const Unit *up; // .. + uInt hi=0, lo; // .. + up=dn->lsu; // -> lsu + lo=*up; // get 1 to 9 digits + #if DECDPUN>1 // split to higher + hi=lo/10; + lo=lo%10; + #endif + up++; + // collect remaining Units, if any, into hi + for (d=DECDPUN; ddigits; up++, d+=DECDPUN) hi+=*up*powers[d-1]; + // now low has the lsd, hi the remainder + if (hi>214748364 || (hi==214748364 && lo>7)) { // out of range? + // most-negative is a reprieve + if (dn->bits&DECNEG && hi==214748364 && lo==8) return 0x80000000; + // bad -- drop through + } + else { // in-range always + Int i=X10(hi)+lo; + if (dn->bits&DECNEG) return -i; + return i; + } + } // integer + decContextSetStatus(set, DEC_Invalid_operation); // [may not return] + return 0; + } // decNumberToInt32 + +uInt decNumberToUInt32(const decNumber *dn, decContext *set) { + #if DECCHECK + if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0; + #endif + // special or too many digits, or bad exponent, or negative (<0) + if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0 + || (dn->bits&DECNEG && !ISZERO(dn))); // bad + else { // is a finite integer with 10 or fewer digits + Int d; // work + const Unit *up; // .. + uInt hi=0, lo; // .. + up=dn->lsu; // -> lsu + lo=*up; // get 1 to 9 digits + #if DECDPUN>1 // split to higher + hi=lo/10; + lo=lo%10; + #endif + up++; + // collect remaining Units, if any, into hi + for (d=DECDPUN; ddigits; up++, d+=DECDPUN) hi+=*up*powers[d-1]; + + // now low has the lsd, hi the remainder + if (hi>429496729 || (hi==429496729 && lo>5)) ; // no reprieve possible + else return X10(hi)+lo; + } // integer + decContextSetStatus(set, DEC_Invalid_operation); // [may not return] + return 0; + } // decNumberToUInt32 + +/* ------------------------------------------------------------------ */ +/* to-scientific-string -- conversion to numeric string */ +/* to-engineering-string -- conversion to numeric string */ +/* */ +/* decNumberToString(dn, string); */ +/* decNumberToEngString(dn, string); */ +/* */ +/* dn is the decNumber to convert */ +/* string is the string where the result will be laid out */ +/* */ +/* string must be at least dn->digits+14 characters long */ +/* */ +/* No error is possible, and no status can be set. */ +/* ------------------------------------------------------------------ */ +char * decNumberToString(const decNumber *dn, char *string){ + decToString(dn, string, 0); + return string; + } // DecNumberToString + +char * decNumberToEngString(const decNumber *dn, char *string){ + decToString(dn, string, 1); + return string; + } // DecNumberToEngString + +/* ------------------------------------------------------------------ */ +/* to-number -- conversion from numeric string */ +/* */ +/* decNumberFromString -- convert string to decNumber */ +/* dn -- the number structure to fill */ +/* chars[] -- the string to convert ('\0' terminated) */ +/* set -- the context used for processing any error, */ +/* determining the maximum precision available */ +/* (set.digits), determining the maximum and minimum */ +/* exponent (set.emax and set.emin), determining if */ +/* extended values are allowed, and checking the */ +/* rounding mode if overflow occurs or rounding is */ +/* needed. */ +/* */ +/* The length of the coefficient and the size of the exponent are */ +/* checked by this routine, so the correct error (Underflow or */ +/* Overflow) can be reported or rounding applied, as necessary. */ +/* */ +/* If bad syntax is detected, the result will be a quiet NaN. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberFromString(decNumber *dn, const char chars[], + decContext *set) { + Int exponent=0; // working exponent [assume 0] + uByte bits=0; // working flags [assume +ve] + Unit *res; // where result will be built + Unit resbuff[SD2U(DECBUFFER+9)];// local buffer in case need temporary + // [+9 allows for ln() constants] + Unit *allocres=NULL; // -> allocated result, iff allocated + Int d=0; // count of digits found in decimal part + const char *dotchar=NULL; // where dot was found + const char *cfirst=chars; // -> first character of decimal part + const char *last=NULL; // -> last digit of decimal part + const char *c; // work + Unit *up; // .. + #if DECDPUN>1 + Int cut, out; // .. + #endif + Int residue; // rounding residue + uInt status=0; // error code + + #if DECCHECK + if (decCheckOperands(DECUNRESU, DECUNUSED, DECUNUSED, set)) + return decNumberZero(dn); + #endif + + do { // status & malloc protection + for (c=chars;; c++) { // -> input character + if (*c>='0' && *c<='9') { // test for Arabic digit + last=c; + d++; // count of real digits + continue; // still in decimal part + } + if (*c=='.' && dotchar==NULL) { // first '.' + dotchar=c; // record offset into decimal part + if (c==cfirst) cfirst++; // first digit must follow + continue;} + if (c==chars) { // first in string... + if (*c=='-') { // valid - sign + cfirst++; + bits=DECNEG; + continue;} + if (*c=='+') { // valid + sign + cfirst++; + continue;} + } + // *c is not a digit, or a valid +, -, or '.' + break; + } // c + + if (last==NULL) { // no digits yet + status=DEC_Conversion_syntax;// assume the worst + if (*c=='\0') break; // and no more to come... + #if DECSUBSET + // if subset then infinities and NaNs are not allowed + if (!set->extended) break; // hopeless + #endif + // Infinities and NaNs are possible, here + if (dotchar!=NULL) break; // .. unless had a dot + decNumberZero(dn); // be optimistic + if (decBiStr(c, "infinity", "INFINITY") + || decBiStr(c, "inf", "INF")) { + dn->bits=bits | DECINF; + status=0; // is OK + break; // all done + } + // a NaN expected + // 2003.09.10 NaNs are now permitted to have a sign + dn->bits=bits | DECNAN; // assume simple NaN + if (*c=='s' || *c=='S') { // looks like an sNaN + c++; + dn->bits=bits | DECSNAN; + } + if (*c!='n' && *c!='N') break; // check caseless "NaN" + c++; + if (*c!='a' && *c!='A') break; // .. + c++; + if (*c!='n' && *c!='N') break; // .. + c++; + // now either nothing, or nnnn payload, expected + // -> start of integer and skip leading 0s [including plain 0] + for (cfirst=c; *cfirst=='0';) cfirst++; + if (*cfirst=='\0') { // "NaN" or "sNaN", maybe with all 0s + status=0; // it's good + break; // .. + } + // something other than 0s; setup last and d as usual [no dots] + for (c=cfirst;; c++, d++) { + if (*c<'0' || *c>'9') break; // test for Arabic digit + last=c; + } + if (*c!='\0') break; // not all digits + if (d>set->digits-1) { + // [NB: payload in a decNumber can be full length unless + // clamped, in which case can only be digits-1] + if (set->clamp) break; + if (d>set->digits) break; + } // too many digits? + // good; drop through to convert the integer to coefficient + status=0; // syntax is OK + bits=dn->bits; // for copy-back + } // last==NULL + + else if (*c!='\0') { // more to process... + // had some digits; exponent is only valid sequence now + Flag nege; // 1=negative exponent + const char *firstexp; // -> first significant exponent digit + status=DEC_Conversion_syntax;// assume the worst + if (*c!='e' && *c!='E') break; + /* Found 'e' or 'E' -- now process explicit exponent */ + // 1998.07.11: sign no longer required + nege=0; + c++; // to (possible) sign + if (*c=='-') {nege=1; c++;} + else if (*c=='+') c++; + if (*c=='\0') break; + + for (; *c=='0' && *(c+1)!='\0';) c++; // strip insignificant zeros + firstexp=c; // save exponent digit place + for (; ;c++) { + if (*c<'0' || *c>'9') break; // not a digit + exponent=X10(exponent)+(Int)*c-(Int)'0'; + } // c + // if not now on a '\0', *c must not be a digit + if (*c!='\0') break; + + // (this next test must be after the syntax checks) + // if it was too long the exponent may have wrapped, so check + // carefully and set it to a certain overflow if wrap possible + if (c>=firstexp+9+1) { + if (c>firstexp+9+1 || *firstexp>'1') exponent=DECNUMMAXE*2; + // [up to 1999999999 is OK, for example 1E-1000000998] + } + if (nege) exponent=-exponent; // was negative + status=0; // is OK + } // stuff after digits + + // Here when whole string has been inspected; syntax is good + // cfirst->first digit (never dot), last->last digit (ditto) + + // strip leading zeros/dot [leave final 0 if all 0's] + if (*cfirst=='0') { // [cfirst has stepped over .] + for (c=cfirst; cextended) { + decNumberZero(dn); // clean result + break; // [could be return] + } + #endif + } // at least one leading 0 + + // Handle decimal point... + if (dotchar!=NULL && dotchardigits) res=dn->lsu; // fits into supplied decNumber + else { // rounding needed + Int needbytes=D2U(d)*sizeof(Unit);// bytes needed + res=resbuff; // assume use local buffer + if (needbytes>(Int)sizeof(resbuff)) { // too big for local + allocres=(Unit *)malloc(needbytes); + if (allocres==NULL) {status|=DEC_Insufficient_storage; break;} + res=allocres; + } + } + // res now -> number lsu, buffer, or allocated storage for Unit array + + // Place the coefficient into the selected Unit array + // [this is often 70% of the cost of this function when DECDPUN>1] + #if DECDPUN>1 + out=0; // accumulator + up=res+D2U(d)-1; // -> msu + cut=d-(up-res)*DECDPUN; // digits in top unit + for (c=cfirst;; c++) { // along the digits + if (*c=='.') continue; // ignore '.' [don't decrement cut] + out=X10(out)+(Int)*c-(Int)'0'; + if (c==last) break; // done [never get to trailing '.'] + cut--; + if (cut>0) continue; // more for this unit + *up=(Unit)out; // write unit + up--; // prepare for unit below.. + cut=DECDPUN; // .. + out=0; // .. + } // c + *up=(Unit)out; // write lsu + + #else + // DECDPUN==1 + up=res; // -> lsu + for (c=last; c>=cfirst; c--) { // over each character, from least + if (*c=='.') continue; // ignore . [don't step up] + *up=(Unit)((Int)*c-(Int)'0'); + up++; + } // c + #endif + + dn->bits=bits; + dn->exponent=exponent; + dn->digits=d; + + // if not in number (too long) shorten into the number + if (d>set->digits) { + residue=0; + decSetCoeff(dn, set, res, d, &residue, &status); + // always check for overflow or subnormal and round as needed + decFinalize(dn, set, &residue, &status); + } + else { // no rounding, but may still have overflow or subnormal + // [these tests are just for performance; finalize repeats them] + if ((dn->exponent-1emin-dn->digits) + || (dn->exponent-1>set->emax-set->digits)) { + residue=0; + decFinalize(dn, set, &residue, &status); + } + } + // decNumberShow(dn); + } while(0); // [for break] + + if (allocres!=NULL) free(allocres); // drop any storage used + if (status!=0) decStatus(dn, status, set); + return dn; + } /* decNumberFromString */ + +/* ================================================================== */ +/* Operators */ +/* ================================================================== */ + +/* ------------------------------------------------------------------ */ +/* decNumberAbs -- absolute value operator */ +/* */ +/* This computes C = abs(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context */ +/* */ +/* See also decNumberCopyAbs for a quiet bitwise version of this. */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +/* This has the same effect as decNumberPlus unless A is negative, */ +/* in which case it has the same effect as decNumberMinus. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberAbs(decNumber *res, const decNumber *rhs, + decContext *set) { + decNumber dzero; // for 0 + uInt status=0; // accumulator + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + decNumberZero(&dzero); // set 0 + dzero.exponent=rhs->exponent; // [no coefficient expansion] + decAddOp(res, &dzero, rhs, set, (uByte)(rhs->bits & DECNEG), &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberAbs + +/* ------------------------------------------------------------------ */ +/* decNumberAdd -- add two Numbers */ +/* */ +/* This computes C = A + B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X+X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +/* This just calls the routine shared with Subtract */ +decNumber * decNumberAdd(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + decAddOp(res, lhs, rhs, set, 0, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberAdd + +/* ------------------------------------------------------------------ */ +/* decNumberAnd -- AND two Numbers, digitwise */ +/* */ +/* This computes C = A & B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X&X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context (used for result length and error report) */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Logical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberAnd(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + const Unit *ua, *ub; // -> operands + const Unit *msua, *msub; // -> operand msus + Unit *uc, *msuc; // -> result and its msu + Int msudigs; // digits in res msu + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs) + || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + + // operands are valid + ua=lhs->lsu; // bottom-up + ub=rhs->lsu; // .. + uc=res->lsu; // .. + msua=ua+D2U(lhs->digits)-1; // -> msu of lhs + msub=ub+D2U(rhs->digits)-1; // -> msu of rhs + msuc=uc+D2U(set->digits)-1; // -> msu of result + msudigs=MSUDIGITS(set->digits); // [faster than remainder] + for (; uc<=msuc; ua++, ub++, uc++) { // Unit loop + Unit a, b; // extract units + if (ua>msua) a=0; + else a=*ua; + if (ub>msub) b=0; + else b=*ub; + *uc=0; // can now write back + if (a|b) { // maybe 1 bits to examine + Int i, j; + *uc=0; // can now write back + // This loop could be unrolled and/or use BIN2BCD tables + for (i=0; i1) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + if (uc==msuc && i==msudigs-1) break; // just did final digit + } // each digit + } // both OK + } // each unit + // [here uc-1 is the msu of the result] + res->digits=decGetDigits(res->lsu, uc-res->lsu); + res->exponent=0; // integer + res->bits=0; // sign=0 + return res; // [no status to set] + } // decNumberAnd + +/* ------------------------------------------------------------------ */ +/* decNumberCompare -- compare two Numbers */ +/* */ +/* This computes C = A ? B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for one digit (or NaN). */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCompare(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + decCompareOp(res, lhs, rhs, set, COMPARE, &status); + if (status!=0) decStatus(res, status, set); + return res; + } // decNumberCompare + +/* ------------------------------------------------------------------ */ +/* decNumberCompareSignal -- compare, signalling on all NaNs */ +/* */ +/* This computes C = A ? B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for one digit (or NaN). */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCompareSignal(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + decCompareOp(res, lhs, rhs, set, COMPSIG, &status); + if (status!=0) decStatus(res, status, set); + return res; + } // decNumberCompareSignal + +/* ------------------------------------------------------------------ */ +/* decNumberCompareTotal -- compare two Numbers, using total ordering */ +/* */ +/* This computes C = A ? B, under total ordering */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for one digit; the result will always be one of */ +/* -1, 0, or 1. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCompareTotal(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status); + if (status!=0) decStatus(res, status, set); + return res; + } // decNumberCompareTotal + +/* ------------------------------------------------------------------ */ +/* decNumberCompareTotalMag -- compare, total ordering of magnitudes */ +/* */ +/* This computes C = |A| ? |B|, under total ordering */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for one digit; the result will always be one of */ +/* -1, 0, or 1. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCompareTotalMag(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + uInt needbytes; // for space calculations + decNumber bufa[D2N(DECBUFFER+1)];// +1 in case DECBUFFER=0 + decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated + decNumber bufb[D2N(DECBUFFER+1)]; + decNumber *allocbufb=NULL; // -> allocated bufb, iff allocated + decNumber *a, *b; // temporary pointers + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + do { // protect allocated storage + // if either is negative, take a copy and absolute + if (decNumberIsNegative(lhs)) { // lhs<0 + a=bufa; + needbytes=sizeof(decNumber)+(D2U(lhs->digits)-1)*sizeof(Unit); + if (needbytes>sizeof(bufa)) { // need malloc space + allocbufa=(decNumber *)malloc(needbytes); + if (allocbufa==NULL) { // hopeless -- abandon + status|=DEC_Insufficient_storage; + break;} + a=allocbufa; // use the allocated space + } + decNumberCopy(a, lhs); // copy content + a->bits&=~DECNEG; // .. and clear the sign + lhs=a; // use copy from here on + } + if (decNumberIsNegative(rhs)) { // rhs<0 + b=bufb; + needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit); + if (needbytes>sizeof(bufb)) { // need malloc space + allocbufb=(decNumber *)malloc(needbytes); + if (allocbufb==NULL) { // hopeless -- abandon + status|=DEC_Insufficient_storage; + break;} + b=allocbufb; // use the allocated space + } + decNumberCopy(b, rhs); // copy content + b->bits&=~DECNEG; // .. and clear the sign + rhs=b; // use copy from here on + } + decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status); + } while(0); // end protected + + if (allocbufa!=NULL) free(allocbufa); // drop any storage used + if (allocbufb!=NULL) free(allocbufb); // .. + if (status!=0) decStatus(res, status, set); + return res; + } // decNumberCompareTotalMag + +/* ------------------------------------------------------------------ */ +/* decNumberDivide -- divide one number by another */ +/* */ +/* This computes C = A / B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X/X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberDivide(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + decDivideOp(res, lhs, rhs, set, DIVIDE, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberDivide + +/* ------------------------------------------------------------------ */ +/* decNumberDivideInteger -- divide and return integer quotient */ +/* */ +/* This computes C = A # B, where # is the integer divide operator */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X#X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberDivideInteger(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + decDivideOp(res, lhs, rhs, set, DIVIDEINT, &status); + if (status!=0) decStatus(res, status, set); + return res; + } // decNumberDivideInteger + +/* ------------------------------------------------------------------ */ +/* decNumberExp -- exponentiation */ +/* */ +/* This computes C = exp(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context; note that rounding mode has no effect */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Mathematical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* */ +/* Finite results will always be full precision and Inexact, except */ +/* when A is a zero or -Infinity (giving 1 or 0 respectively). */ +/* */ +/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */ +/* almost always be correctly rounded, but may be up to 1 ulp in */ +/* error in rare cases. */ +/* ------------------------------------------------------------------ */ +/* This is a wrapper for decExpOp which can handle the slightly wider */ +/* (double) range needed by Ln (which has to be able to calculate */ +/* exp(-a) where a can be the tiniest number (Ntiny). */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberExp(decNumber *res, const decNumber *rhs, + decContext *set) { + uInt status=0; // accumulator + #if DECSUBSET + decNumber *allocrhs=NULL; // non-NULL if rounded rhs allocated + #endif + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + // Check restrictions; these restrictions ensure that if h=8 (see + // decExpOp) then the result will either overflow or underflow to 0. + // Other math functions restrict the input range, too, for inverses. + // If not violated then carry out the operation. + if (!decCheckMath(rhs, set, &status)) do { // protect allocation + #if DECSUBSET + if (!set->extended) { + // reduce operand and set lostDigits status, as needed + if (rhs->digits>set->digits) { + allocrhs=decRoundOperand(rhs, set, &status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + } + #endif + decExpOp(res, rhs, set, &status); + } while(0); // end protected + + #if DECSUBSET + if (allocrhs !=NULL) free(allocrhs); // drop any storage used + #endif + // apply significant status + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberExp + +/* ------------------------------------------------------------------ */ +/* decNumberFMA -- fused multiply add */ +/* */ +/* This computes D = (A * B) + C with only one rounding */ +/* */ +/* res is D, the result. D may be A or B or C (e.g., X=FMA(X,X,X)) */ +/* lhs is A */ +/* rhs is B */ +/* fhs is C [far hand side] */ +/* set is the context */ +/* */ +/* Mathematical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberFMA(decNumber *res, const decNumber *lhs, + const decNumber *rhs, const decNumber *fhs, + decContext *set) { + uInt status=0; // accumulator + decContext dcmul; // context for the multiplication + uInt needbytes; // for space calculations + decNumber bufa[D2N(DECBUFFER*2+1)]; + decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated + decNumber *acc; // accumulator pointer + decNumber dzero; // work + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + if (decCheckOperands(res, fhs, DECUNUSED, set)) return res; + #endif + + do { // protect allocated storage + #if DECSUBSET + if (!set->extended) { // [undefined if subset] + status|=DEC_Invalid_operation; + break;} + #endif + // Check math restrictions [these ensure no overflow or underflow] + if ((!decNumberIsSpecial(lhs) && decCheckMath(lhs, set, &status)) + || (!decNumberIsSpecial(rhs) && decCheckMath(rhs, set, &status)) + || (!decNumberIsSpecial(fhs) && decCheckMath(fhs, set, &status))) break; + // set up context for multiply + dcmul=*set; + dcmul.digits=lhs->digits+rhs->digits; // just enough + // [The above may be an over-estimate for subset arithmetic, but that's OK] + dcmul.emax=DEC_MAX_EMAX; // effectively unbounded .. + dcmul.emin=DEC_MIN_EMIN; // [thanks to Math restrictions] + // set up decNumber space to receive the result of the multiply + acc=bufa; // may fit + needbytes=sizeof(decNumber)+(D2U(dcmul.digits)-1)*sizeof(Unit); + if (needbytes>sizeof(bufa)) { // need malloc space + allocbufa=(decNumber *)malloc(needbytes); + if (allocbufa==NULL) { // hopeless -- abandon + status|=DEC_Insufficient_storage; + break;} + acc=allocbufa; // use the allocated space + } + // multiply with extended range and necessary precision + //printf("emin=%ld\n", dcmul.emin); + decMultiplyOp(acc, lhs, rhs, &dcmul, &status); + // Only Invalid operation (from sNaN or Inf * 0) is possible in + // status; if either is seen than ignore fhs (in case it is + // another sNaN) and set acc to NaN unless we had an sNaN + // [decMultiplyOp leaves that to caller] + // Note sNaN has to go through addOp to shorten payload if + // necessary + if ((status&DEC_Invalid_operation)!=0) { + if (!(status&DEC_sNaN)) { // but be true invalid + decNumberZero(res); // acc not yet set + res->bits=DECNAN; + break; + } + decNumberZero(&dzero); // make 0 (any non-NaN would do) + fhs=&dzero; // use that + } + #if DECCHECK + else { // multiply was OK + if (status!=0) printf("Status=%08lx after FMA multiply\n", (LI)status); + } + #endif + // add the third operand and result -> res, and all is done + decAddOp(res, acc, fhs, set, 0, &status); + } while(0); // end protected + + if (allocbufa!=NULL) free(allocbufa); // drop any storage used + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberFMA + +/* ------------------------------------------------------------------ */ +/* decNumberInvert -- invert a Number, digitwise */ +/* */ +/* This computes C = ~A */ +/* */ +/* res is C, the result. C may be A (e.g., X=~X) */ +/* rhs is A */ +/* set is the context (used for result length and error report) */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Logical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberInvert(decNumber *res, const decNumber *rhs, + decContext *set) { + const Unit *ua, *msua; // -> operand and its msu + Unit *uc, *msuc; // -> result and its msu + Int msudigs; // digits in res msu + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + if (rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + // operand is valid + ua=rhs->lsu; // bottom-up + uc=res->lsu; // .. + msua=ua+D2U(rhs->digits)-1; // -> msu of rhs + msuc=uc+D2U(set->digits)-1; // -> msu of result + msudigs=MSUDIGITS(set->digits); // [faster than remainder] + for (; uc<=msuc; ua++, uc++) { // Unit loop + Unit a; // extract unit + Int i, j; // work + if (ua>msua) a=0; + else a=*ua; + *uc=0; // can now write back + // always need to examine all bits in rhs + // This loop could be unrolled and/or use BIN2BCD tables + for (i=0; i1) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + if (uc==msuc && i==msudigs-1) break; // just did final digit + } // each digit + } // each unit + // [here uc-1 is the msu of the result] + res->digits=decGetDigits(res->lsu, uc-res->lsu); + res->exponent=0; // integer + res->bits=0; // sign=0 + return res; // [no status to set] + } // decNumberInvert + +/* ------------------------------------------------------------------ */ +/* decNumberLn -- natural logarithm */ +/* */ +/* This computes C = ln(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context; note that rounding mode has no effect */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Notable cases: */ +/* A<0 -> Invalid */ +/* A=0 -> -Infinity (Exact) */ +/* A=+Infinity -> +Infinity (Exact) */ +/* A=1 exactly -> 0 (Exact) */ +/* */ +/* Mathematical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* */ +/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */ +/* almost always be correctly rounded, but may be up to 1 ulp in */ +/* error in rare cases. */ +/* ------------------------------------------------------------------ */ +/* This is a wrapper for decLnOp which can handle the slightly wider */ +/* (+11) range needed by Ln, Log10, etc. (which may have to be able */ +/* to calculate at p+e+2). */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberLn(decNumber *res, const decNumber *rhs, + decContext *set) { + uInt status=0; // accumulator + #if DECSUBSET + decNumber *allocrhs=NULL; // non-NULL if rounded rhs allocated + #endif + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + // Check restrictions; this is a math function; if not violated + // then carry out the operation. + if (!decCheckMath(rhs, set, &status)) do { // protect allocation + #if DECSUBSET + if (!set->extended) { + // reduce operand and set lostDigits status, as needed + if (rhs->digits>set->digits) { + allocrhs=decRoundOperand(rhs, set, &status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + // special check in subset for rhs=0 + if (ISZERO(rhs)) { // +/- zeros -> error + status|=DEC_Invalid_operation; + break;} + } // extended=0 + #endif + decLnOp(res, rhs, set, &status); + } while(0); // end protected + + #if DECSUBSET + if (allocrhs !=NULL) free(allocrhs); // drop any storage used + #endif + // apply significant status + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberLn + +/* ------------------------------------------------------------------ */ +/* decNumberLogB - get adjusted exponent, by 754 rules */ +/* */ +/* This computes C = adjustedexponent(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context, used only for digits and status */ +/* */ +/* For an unrounded result, digits may need to be 10 (A might have */ +/* 10**9 digits and an exponent of +999999999, or one digit and an */ +/* exponent of -1999999999). */ +/* */ +/* This returns the adjusted exponent of A after (in theory) padding */ +/* with zeros on the right to set->digits digits while keeping the */ +/* same value. The exponent is not limited by emin/emax. */ +/* */ +/* Notable cases: */ +/* A<0 -> Use |A| */ +/* A=0 -> -Infinity (Division by zero) */ +/* A=Infinite -> +Infinity (Exact) */ +/* A=1 exactly -> 0 (Exact) */ +/* NaNs are propagated as usual */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberLogB(decNumber *res, const decNumber *rhs, + decContext *set) { + uInt status=0; // accumulator + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + // NaNs as usual; Infinities return +Infinity; 0->oops + if (decNumberIsNaN(rhs)) decNaNs(res, rhs, NULL, set, &status); + else if (decNumberIsInfinite(rhs)) decNumberCopyAbs(res, rhs); + else if (decNumberIsZero(rhs)) { + decNumberZero(res); // prepare for Infinity + res->bits=DECNEG|DECINF; // -Infinity + status|=DEC_Division_by_zero; // as per 754 + } + else { // finite non-zero + Int ae=rhs->exponent+rhs->digits-1; // adjusted exponent + if (set->digits>=10) decNumberFromInt32(res, ae); // lay it out + else { + decNumber buft[D2N(10)]; // temporary number + decNumber *t=buft; // .. + decNumberFromInt32(t, ae); // lay it out + decNumberPlus(res, t, set); // round as necessary + } + } + + if (status!=0) decStatus(res, status, set); + return res; + } // decNumberLogB + +/* ------------------------------------------------------------------ */ +/* decNumberLog10 -- logarithm in base 10 */ +/* */ +/* This computes C = log10(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context; note that rounding mode has no effect */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Notable cases: */ +/* A<0 -> Invalid */ +/* A=0 -> -Infinity (Exact) */ +/* A=+Infinity -> +Infinity (Exact) */ +/* A=10**n (if n is an integer) -> n (Exact) */ +/* */ +/* Mathematical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* */ +/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */ +/* almost always be correctly rounded, but may be up to 1 ulp in */ +/* error in rare cases. */ +/* ------------------------------------------------------------------ */ +/* This calculates ln(A)/ln(10) using appropriate precision. For */ +/* ln(A) this is the max(p, rhs->digits + t) + 3, where p is the */ +/* requested digits and t is the number of digits in the exponent */ +/* (maximum 6). For ln(10) it is p + 3; this is often handled by the */ +/* fastpath in decLnOp. The final division is done to the requested */ +/* precision. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberLog10(decNumber *res, const decNumber *rhs, + decContext *set) { + uInt status=0, ignore=0; // status accumulators + uInt needbytes; // for space calculations + Int p; // working precision + Int t; // digits in exponent of A + + // buffers for a and b working decimals + // (adjustment calculator, same size) + decNumber bufa[D2N(DECBUFFER+2)]; + decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated + decNumber *a=bufa; // temporary a + decNumber bufb[D2N(DECBUFFER+2)]; + decNumber *allocbufb=NULL; // -> allocated bufb, iff allocated + decNumber *b=bufb; // temporary b + decNumber bufw[D2N(10)]; // working 2-10 digit number + decNumber *w=bufw; // .. + #if DECSUBSET + decNumber *allocrhs=NULL; // non-NULL if rounded rhs allocated + #endif + + decContext aset; // working context + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + // Check restrictions; this is a math function; if not violated + // then carry out the operation. + if (!decCheckMath(rhs, set, &status)) do { // protect malloc + #if DECSUBSET + if (!set->extended) { + // reduce operand and set lostDigits status, as needed + if (rhs->digits>set->digits) { + allocrhs=decRoundOperand(rhs, set, &status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + // special check in subset for rhs=0 + if (ISZERO(rhs)) { // +/- zeros -> error + status|=DEC_Invalid_operation; + break;} + } // extended=0 + #endif + + decContextDefault(&aset, DEC_INIT_DECIMAL64); // clean context + + // handle exact powers of 10; only check if +ve finite + if (!(rhs->bits&(DECNEG|DECSPECIAL)) && !ISZERO(rhs)) { + Int residue=0; // (no residue) + uInt copystat=0; // clean status + + // round to a single digit... + aset.digits=1; + decCopyFit(w, rhs, &aset, &residue, ©stat); // copy & shorten + // if exact and the digit is 1, rhs is a power of 10 + if (!(copystat&DEC_Inexact) && w->lsu[0]==1) { + // the exponent, conveniently, is the power of 10; making + // this the result needs a little care as it might not fit, + // so first convert it into the working number, and then move + // to res + decNumberFromInt32(w, w->exponent); + residue=0; + decCopyFit(res, w, set, &residue, &status); // copy & round + decFinish(res, set, &residue, &status); // cleanup/set flags + break; + } // not a power of 10 + } // not a candidate for exact + + // simplify the information-content calculation to use 'total + // number of digits in a, including exponent' as compared to the + // requested digits, as increasing this will only rarely cost an + // iteration in ln(a) anyway + t=6; // it can never be >6 + + // allocate space when needed... + p=(rhs->digits+t>set->digits?rhs->digits+t:set->digits)+3; + needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit); + if (needbytes>sizeof(bufa)) { // need malloc space + allocbufa=(decNumber *)malloc(needbytes); + if (allocbufa==NULL) { // hopeless -- abandon + status|=DEC_Insufficient_storage; + break;} + a=allocbufa; // use the allocated space + } + aset.digits=p; // as calculated + aset.emax=DEC_MAX_MATH; // usual bounds + aset.emin=-DEC_MAX_MATH; // .. + aset.clamp=0; // and no concrete format + decLnOp(a, rhs, &aset, &status); // a=ln(rhs) + + // skip the division if the result so far is infinite, NaN, or + // zero, or there was an error; note NaN from sNaN needs copy + if (status&DEC_NaNs && !(status&DEC_sNaN)) break; + if (a->bits&DECSPECIAL || ISZERO(a)) { + decNumberCopy(res, a); // [will fit] + break;} + + // for ln(10) an extra 3 digits of precision are needed + p=set->digits+3; + needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit); + if (needbytes>sizeof(bufb)) { // need malloc space + allocbufb=(decNumber *)malloc(needbytes); + if (allocbufb==NULL) { // hopeless -- abandon + status|=DEC_Insufficient_storage; + break;} + b=allocbufb; // use the allocated space + } + decNumberZero(w); // set up 10... + #if DECDPUN==1 + w->lsu[1]=1; w->lsu[0]=0; // .. + #else + w->lsu[0]=10; // .. + #endif + w->digits=2; // .. + + aset.digits=p; + decLnOp(b, w, &aset, &ignore); // b=ln(10) + + aset.digits=set->digits; // for final divide + decDivideOp(res, a, b, &aset, DIVIDE, &status); // into result + } while(0); // [for break] + + if (allocbufa!=NULL) free(allocbufa); // drop any storage used + if (allocbufb!=NULL) free(allocbufb); // .. + #if DECSUBSET + if (allocrhs !=NULL) free(allocrhs); // .. + #endif + // apply significant status + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberLog10 + +/* ------------------------------------------------------------------ */ +/* decNumberMax -- compare two Numbers and return the maximum */ +/* */ +/* This computes C = A ? B, returning the maximum by 754 rules */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberMax(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + decCompareOp(res, lhs, rhs, set, COMPMAX, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberMax + +/* ------------------------------------------------------------------ */ +/* decNumberMaxMag -- compare and return the maximum by magnitude */ +/* */ +/* This computes C = A ? B, returning the maximum by 754 rules */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberMaxMag(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + decCompareOp(res, lhs, rhs, set, COMPMAXMAG, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberMaxMag + +/* ------------------------------------------------------------------ */ +/* decNumberMin -- compare two Numbers and return the minimum */ +/* */ +/* This computes C = A ? B, returning the minimum by 754 rules */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberMin(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + decCompareOp(res, lhs, rhs, set, COMPMIN, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberMin + +/* ------------------------------------------------------------------ */ +/* decNumberMinMag -- compare and return the minimum by magnitude */ +/* */ +/* This computes C = A ? B, returning the minimum by 754 rules */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberMinMag(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + decCompareOp(res, lhs, rhs, set, COMPMINMAG, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberMinMag + +/* ------------------------------------------------------------------ */ +/* decNumberMinus -- prefix minus operator */ +/* */ +/* This computes C = 0 - A */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context */ +/* */ +/* See also decNumberCopyNegate for a quiet bitwise version of this. */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +/* Simply use AddOp for the subtract, which will do the necessary. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberMinus(decNumber *res, const decNumber *rhs, + decContext *set) { + decNumber dzero; + uInt status=0; // accumulator + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + decNumberZero(&dzero); // make 0 + dzero.exponent=rhs->exponent; // [no coefficient expansion] + decAddOp(res, &dzero, rhs, set, DECNEG, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberMinus + +/* ------------------------------------------------------------------ */ +/* decNumberNextMinus -- next towards -Infinity */ +/* */ +/* This computes C = A - infinitesimal, rounded towards -Infinity */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context */ +/* */ +/* This is a generalization of 754 NextDown. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberNextMinus(decNumber *res, const decNumber *rhs, + decContext *set) { + decNumber dtiny; // constant + decContext workset=*set; // work + uInt status=0; // accumulator + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + // +Infinity is the special case + if ((rhs->bits&(DECINF|DECNEG))==DECINF) { + decSetMaxValue(res, set); // is +ve + // there is no status to set + return res; + } + decNumberZero(&dtiny); // start with 0 + dtiny.lsu[0]=1; // make number that is .. + dtiny.exponent=DEC_MIN_EMIN-1; // .. smaller than tiniest + workset.round=DEC_ROUND_FLOOR; + decAddOp(res, rhs, &dtiny, &workset, DECNEG, &status); + status&=DEC_Invalid_operation|DEC_sNaN; // only sNaN Invalid please + if (status!=0) decStatus(res, status, set); + return res; + } // decNumberNextMinus + +/* ------------------------------------------------------------------ */ +/* decNumberNextPlus -- next towards +Infinity */ +/* */ +/* This computes C = A + infinitesimal, rounded towards +Infinity */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context */ +/* */ +/* This is a generalization of 754 NextUp. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberNextPlus(decNumber *res, const decNumber *rhs, + decContext *set) { + decNumber dtiny; // constant + decContext workset=*set; // work + uInt status=0; // accumulator + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + // -Infinity is the special case + if ((rhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) { + decSetMaxValue(res, set); + res->bits=DECNEG; // negative + // there is no status to set + return res; + } + decNumberZero(&dtiny); // start with 0 + dtiny.lsu[0]=1; // make number that is .. + dtiny.exponent=DEC_MIN_EMIN-1; // .. smaller than tiniest + workset.round=DEC_ROUND_CEILING; + decAddOp(res, rhs, &dtiny, &workset, 0, &status); + status&=DEC_Invalid_operation|DEC_sNaN; // only sNaN Invalid please + if (status!=0) decStatus(res, status, set); + return res; + } // decNumberNextPlus + +/* ------------------------------------------------------------------ */ +/* decNumberNextToward -- next towards rhs */ +/* */ +/* This computes C = A +/- infinitesimal, rounded towards */ +/* +/-Infinity in the direction of B, as per 754-1985 nextafter */ +/* modified during revision but dropped from 754-2008. */ +/* */ +/* res is C, the result. C may be A or B. */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* This is a generalization of 754-1985 NextAfter. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberNextToward(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + decNumber dtiny; // constant + decContext workset=*set; // work + Int result; // .. + uInt status=0; // accumulator + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { + decNaNs(res, lhs, rhs, set, &status); + } + else { // Is numeric, so no chance of sNaN Invalid, etc. + result=decCompare(lhs, rhs, 0); // sign matters + if (result==BADINT) status|=DEC_Insufficient_storage; // rare + else { // valid compare + if (result==0) decNumberCopySign(res, lhs, rhs); // easy + else { // differ: need NextPlus or NextMinus + uByte sub; // add or subtract + if (result<0) { // lhsbits&(DECINF|DECNEG))==(DECINF|DECNEG)) { + decSetMaxValue(res, set); + res->bits=DECNEG; // negative + return res; // there is no status to set + } + workset.round=DEC_ROUND_CEILING; + sub=0; // add, please + } // plus + else { // lhs>rhs, do nextminus + // +Infinity is the special case + if ((lhs->bits&(DECINF|DECNEG))==DECINF) { + decSetMaxValue(res, set); + return res; // there is no status to set + } + workset.round=DEC_ROUND_FLOOR; + sub=DECNEG; // subtract, please + } // minus + decNumberZero(&dtiny); // start with 0 + dtiny.lsu[0]=1; // make number that is .. + dtiny.exponent=DEC_MIN_EMIN-1; // .. smaller than tiniest + decAddOp(res, lhs, &dtiny, &workset, sub, &status); // + or - + // turn off exceptions if the result is a normal number + // (including Nmin), otherwise let all status through + if (decNumberIsNormal(res, set)) status=0; + } // unequal + } // compare OK + } // numeric + if (status!=0) decStatus(res, status, set); + return res; + } // decNumberNextToward + +/* ------------------------------------------------------------------ */ +/* decNumberOr -- OR two Numbers, digitwise */ +/* */ +/* This computes C = A | B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X|X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context (used for result length and error report) */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Logical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberOr(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + const Unit *ua, *ub; // -> operands + const Unit *msua, *msub; // -> operand msus + Unit *uc, *msuc; // -> result and its msu + Int msudigs; // digits in res msu + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs) + || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + // operands are valid + ua=lhs->lsu; // bottom-up + ub=rhs->lsu; // .. + uc=res->lsu; // .. + msua=ua+D2U(lhs->digits)-1; // -> msu of lhs + msub=ub+D2U(rhs->digits)-1; // -> msu of rhs + msuc=uc+D2U(set->digits)-1; // -> msu of result + msudigs=MSUDIGITS(set->digits); // [faster than remainder] + for (; uc<=msuc; ua++, ub++, uc++) { // Unit loop + Unit a, b; // extract units + if (ua>msua) a=0; + else a=*ua; + if (ub>msub) b=0; + else b=*ub; + *uc=0; // can now write back + if (a|b) { // maybe 1 bits to examine + Int i, j; + // This loop could be unrolled and/or use BIN2BCD tables + for (i=0; i1) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + if (uc==msuc && i==msudigs-1) break; // just did final digit + } // each digit + } // non-zero + } // each unit + // [here uc-1 is the msu of the result] + res->digits=decGetDigits(res->lsu, uc-res->lsu); + res->exponent=0; // integer + res->bits=0; // sign=0 + return res; // [no status to set] + } // decNumberOr + +/* ------------------------------------------------------------------ */ +/* decNumberPlus -- prefix plus operator */ +/* */ +/* This computes C = 0 + A */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context */ +/* */ +/* See also decNumberCopy for a quiet bitwise version of this. */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +/* This simply uses AddOp; Add will take fast path after preparing A. */ +/* Performance is a concern here, as this routine is often used to */ +/* check operands and apply rounding and overflow/underflow testing. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberPlus(decNumber *res, const decNumber *rhs, + decContext *set) { + decNumber dzero; + uInt status=0; // accumulator + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + decNumberZero(&dzero); // make 0 + dzero.exponent=rhs->exponent; // [no coefficient expansion] + decAddOp(res, &dzero, rhs, set, 0, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberPlus + +/* ------------------------------------------------------------------ */ +/* decNumberMultiply -- multiply two Numbers */ +/* */ +/* This computes C = A x B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X+X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberMultiply(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + decMultiplyOp(res, lhs, rhs, set, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberMultiply + +/* ------------------------------------------------------------------ */ +/* decNumberPower -- raise a number to a power */ +/* */ +/* This computes C = A ** B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X**X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Mathematical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* */ +/* However, if 1999999997<=B<=999999999 and B is an integer then the */ +/* restrictions on A and the context are relaxed to the usual bounds, */ +/* for compatibility with the earlier (integer power only) version */ +/* of this function. */ +/* */ +/* When B is an integer, the result may be exact, even if rounded. */ +/* */ +/* The final result is rounded according to the context; it will */ +/* almost always be correctly rounded, but may be up to 1 ulp in */ +/* error in rare cases. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberPower(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + #if DECSUBSET + decNumber *alloclhs=NULL; // non-NULL if rounded lhs allocated + decNumber *allocrhs=NULL; // .., rhs + #endif + decNumber *allocdac=NULL; // -> allocated acc buffer, iff used + decNumber *allocinv=NULL; // -> allocated 1/x buffer, iff used + Int reqdigits=set->digits; // requested DIGITS + Int n; // rhs in binary + Flag rhsint=0; // 1 if rhs is an integer + Flag useint=0; // 1 if can use integer calculation + Flag isoddint=0; // 1 if rhs is an integer and odd + Int i; // work + #if DECSUBSET + Int dropped; // .. + #endif + uInt needbytes; // buffer size needed + Flag seenbit; // seen a bit while powering + Int residue=0; // rounding residue + uInt status=0; // accumulators + uByte bits=0; // result sign if errors + decContext aset; // working context + decNumber dnOne; // work value 1... + // local accumulator buffer [a decNumber, with digits+elength+1 digits] + decNumber dacbuff[D2N(DECBUFFER+9)]; + decNumber *dac=dacbuff; // -> result accumulator + // same again for possible 1/lhs calculation + decNumber invbuff[D2N(DECBUFFER+9)]; + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + do { // protect allocated storage + #if DECSUBSET + if (!set->extended) { // reduce operands and set status, as needed + if (lhs->digits>reqdigits) { + alloclhs=decRoundOperand(lhs, set, &status); + if (alloclhs==NULL) break; + lhs=alloclhs; + } + if (rhs->digits>reqdigits) { + allocrhs=decRoundOperand(rhs, set, &status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + } + #endif + // [following code does not require input rounding] + + // handle NaNs and rhs Infinity (lhs infinity is harder) + if (SPECIALARGS) { + if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { // NaNs + decNaNs(res, lhs, rhs, set, &status); + break;} + if (decNumberIsInfinite(rhs)) { // rhs Infinity + Flag rhsneg=rhs->bits&DECNEG; // save rhs sign + if (decNumberIsNegative(lhs) // lhs<0 + && !decNumberIsZero(lhs)) // .. + status|=DEC_Invalid_operation; + else { // lhs >=0 + decNumberZero(&dnOne); // set up 1 + dnOne.lsu[0]=1; + decNumberCompare(dac, lhs, &dnOne, set); // lhs ? 1 + decNumberZero(res); // prepare for 0/1/Infinity + if (decNumberIsNegative(dac)) { // lhs<1 + if (rhsneg) res->bits|=DECINF; // +Infinity [else is +0] + } + else if (dac->lsu[0]==0) { // lhs=1 + // 1**Infinity is inexact, so return fully-padded 1.0000 + Int shift=set->digits-1; + *res->lsu=1; // was 0, make int 1 + res->digits=decShiftToMost(res->lsu, 1, shift); + res->exponent=-shift; // make 1.0000... + status|=DEC_Inexact|DEC_Rounded; // deemed inexact + } + else { // lhs>1 + if (!rhsneg) res->bits|=DECINF; // +Infinity [else is +0] + } + } // lhs>=0 + break;} + // [lhs infinity drops through] + } // specials + + // Original rhs may be an integer that fits and is in range + n=decGetInt(rhs); + if (n!=BADINT) { // it is an integer + rhsint=1; // record the fact for 1**n + isoddint=(Flag)n&1; // [works even if big] + if (n!=BIGEVEN && n!=BIGODD) // can use integer path? + useint=1; // looks good + } + + if (decNumberIsNegative(lhs) // -x .. + && isoddint) bits=DECNEG; // .. to an odd power + + // handle LHS infinity + if (decNumberIsInfinite(lhs)) { // [NaNs already handled] + uByte rbits=rhs->bits; // save + decNumberZero(res); // prepare + if (n==0) *res->lsu=1; // [-]Inf**0 => 1 + else { + // -Inf**nonint -> error + if (!rhsint && decNumberIsNegative(lhs)) { + status|=DEC_Invalid_operation; // -Inf**nonint is error + break;} + if (!(rbits & DECNEG)) bits|=DECINF; // was not a **-n + // [otherwise will be 0 or -0] + res->bits=bits; + } + break;} + + // similarly handle LHS zero + if (decNumberIsZero(lhs)) { + if (n==0) { // 0**0 => Error + #if DECSUBSET + if (!set->extended) { // [unless subset] + decNumberZero(res); + *res->lsu=1; // return 1 + break;} + #endif + status|=DEC_Invalid_operation; + } + else { // 0**x + uByte rbits=rhs->bits; // save + if (rbits & DECNEG) { // was a 0**(-n) + #if DECSUBSET + if (!set->extended) { // [bad if subset] + status|=DEC_Invalid_operation; + break;} + #endif + bits|=DECINF; + } + decNumberZero(res); // prepare + // [otherwise will be 0 or -0] + res->bits=bits; + } + break;} + + // here both lhs and rhs are finite; rhs==0 is handled in the + // integer path. Next handle the non-integer cases + if (!useint) { // non-integral rhs + // any -ve lhs is bad, as is either operand or context out of + // bounds + if (decNumberIsNegative(lhs)) { + status|=DEC_Invalid_operation; + break;} + if (decCheckMath(lhs, set, &status) + || decCheckMath(rhs, set, &status)) break; // variable status + + decContextDefault(&aset, DEC_INIT_DECIMAL64); // clean context + aset.emax=DEC_MAX_MATH; // usual bounds + aset.emin=-DEC_MAX_MATH; // .. + aset.clamp=0; // and no concrete format + + // calculate the result using exp(ln(lhs)*rhs), which can + // all be done into the accumulator, dac. The precision needed + // is enough to contain the full information in the lhs (which + // is the total digits, including exponent), or the requested + // precision, if larger, + 4; 6 is used for the exponent + // maximum length, and this is also used when it is shorter + // than the requested digits as it greatly reduces the >0.5 ulp + // cases at little cost (because Ln doubles digits each + // iteration so a few extra digits rarely causes an extra + // iteration) + aset.digits=MAXI(lhs->digits, set->digits)+6+4; + } // non-integer rhs + + else { // rhs is in-range integer + if (n==0) { // x**0 = 1 + // (0**0 was handled above) + decNumberZero(res); // result=1 + *res->lsu=1; // .. + break;} + // rhs is a non-zero integer + if (n<0) n=-n; // use abs(n) + + aset=*set; // clone the context + aset.round=DEC_ROUND_HALF_EVEN; // internally use balanced + // calculate the working DIGITS + aset.digits=reqdigits+(rhs->digits+rhs->exponent)+2; + #if DECSUBSET + if (!set->extended) aset.digits--; // use classic precision + #endif + // it's an error if this is more than can be handled + if (aset.digits>DECNUMMAXP) {status|=DEC_Invalid_operation; break;} + } // integer path + + // aset.digits is the count of digits for the accumulator needed + // if accumulator is too long for local storage, then allocate + needbytes=sizeof(decNumber)+(D2U(aset.digits)-1)*sizeof(Unit); + // [needbytes also used below if 1/lhs needed] + if (needbytes>sizeof(dacbuff)) { + allocdac=(decNumber *)malloc(needbytes); + if (allocdac==NULL) { // hopeless -- abandon + status|=DEC_Insufficient_storage; + break;} + dac=allocdac; // use the allocated space + } + // here, aset is set up and accumulator is ready for use + + if (!useint) { // non-integral rhs + // x ** y; special-case x=1 here as it will otherwise always + // reduce to integer 1; decLnOp has a fastpath which detects + // the case of x=1 + decLnOp(dac, lhs, &aset, &status); // dac=ln(lhs) + // [no error possible, as lhs 0 already handled] + if (ISZERO(dac)) { // x==1, 1.0, etc. + // need to return fully-padded 1.0000 etc., but rhsint->1 + *dac->lsu=1; // was 0, make int 1 + if (!rhsint) { // add padding + Int shift=set->digits-1; + dac->digits=decShiftToMost(dac->lsu, 1, shift); + dac->exponent=-shift; // make 1.0000... + status|=DEC_Inexact|DEC_Rounded; // deemed inexact + } + } + else { + decMultiplyOp(dac, dac, rhs, &aset, &status); // dac=dac*rhs + decExpOp(dac, dac, &aset, &status); // dac=exp(dac) + } + // and drop through for final rounding + } // non-integer rhs + + else { // carry on with integer + decNumberZero(dac); // acc=1 + *dac->lsu=1; // .. + + // if a negative power the constant 1 is needed, and if not subset + // invert the lhs now rather than inverting the result later + if (decNumberIsNegative(rhs)) { // was a **-n [hence digits>0] + decNumber *inv=invbuff; // asssume use fixed buffer + decNumberCopy(&dnOne, dac); // dnOne=1; [needed now or later] + #if DECSUBSET + if (set->extended) { // need to calculate 1/lhs + #endif + // divide lhs into 1, putting result in dac [dac=1/dac] + decDivideOp(dac, &dnOne, lhs, &aset, DIVIDE, &status); + // now locate or allocate space for the inverted lhs + if (needbytes>sizeof(invbuff)) { + allocinv=(decNumber *)malloc(needbytes); + if (allocinv==NULL) { // hopeless -- abandon + status|=DEC_Insufficient_storage; + break;} + inv=allocinv; // use the allocated space + } + // [inv now points to big-enough buffer or allocated storage] + decNumberCopy(inv, dac); // copy the 1/lhs + decNumberCopy(dac, &dnOne); // restore acc=1 + lhs=inv; // .. and go forward with new lhs + #if DECSUBSET + } + #endif + } + + // Raise-to-the-power loop... + seenbit=0; // set once a 1-bit is encountered + for (i=1;;i++){ // for each bit [top bit ignored] + // abandon if had overflow or terminal underflow + if (status & (DEC_Overflow|DEC_Underflow)) { // interesting? + if (status&DEC_Overflow || ISZERO(dac)) break; + } + // [the following two lines revealed an optimizer bug in a C++ + // compiler, with symptom: 5**3 -> 25, when n=n+n was used] + n=n<<1; // move next bit to testable position + if (n<0) { // top bit is set + seenbit=1; // OK, significant bit seen + decMultiplyOp(dac, dac, lhs, &aset, &status); // dac=dac*x + } + if (i==31) break; // that was the last bit + if (!seenbit) continue; // no need to square 1 + decMultiplyOp(dac, dac, dac, &aset, &status); // dac=dac*dac [square] + } /*i*/ // 32 bits + + // complete internal overflow or underflow processing + if (status & (DEC_Overflow|DEC_Underflow)) { + #if DECSUBSET + // If subset, and power was negative, reverse the kind of -erflow + // [1/x not yet done] + if (!set->extended && decNumberIsNegative(rhs)) { + if (status & DEC_Overflow) + status^=DEC_Overflow | DEC_Underflow | DEC_Subnormal; + else { // trickier -- Underflow may or may not be set + status&=~(DEC_Underflow | DEC_Subnormal); // [one or both] + status|=DEC_Overflow; + } + } + #endif + dac->bits=(dac->bits & ~DECNEG) | bits; // force correct sign + // round subnormals [to set.digits rather than aset.digits] + // or set overflow result similarly as required + decFinalize(dac, set, &residue, &status); + decNumberCopy(res, dac); // copy to result (is now OK length) + break; + } + + #if DECSUBSET + if (!set->extended && // subset math + decNumberIsNegative(rhs)) { // was a **-n [hence digits>0] + // so divide result into 1 [dac=1/dac] + decDivideOp(dac, &dnOne, dac, &aset, DIVIDE, &status); + } + #endif + } // rhs integer path + + // reduce result to the requested length and copy to result + decCopyFit(res, dac, set, &residue, &status); + decFinish(res, set, &residue, &status); // final cleanup + #if DECSUBSET + if (!set->extended) decTrim(res, set, 0, 1, &dropped); // trailing zeros + #endif + } while(0); // end protected + + if (allocdac!=NULL) free(allocdac); // drop any storage used + if (allocinv!=NULL) free(allocinv); // .. + #if DECSUBSET + if (alloclhs!=NULL) free(alloclhs); // .. + if (allocrhs!=NULL) free(allocrhs); // .. + #endif + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberPower + +/* ------------------------------------------------------------------ */ +/* decNumberQuantize -- force exponent to requested value */ +/* */ +/* This computes C = op(A, B), where op adjusts the coefficient */ +/* of C (by rounding or shifting) such that the exponent (-scale) */ +/* of C has exponent of B. The numerical value of C will equal A, */ +/* except for the effects of any rounding that occurred. */ +/* */ +/* res is C, the result. C may be A or B */ +/* lhs is A, the number to adjust */ +/* rhs is B, the number with exponent to match */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Unless there is an error or the result is infinite, the exponent */ +/* after the operation is guaranteed to be equal to that of B. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberQuantize(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + decQuantizeOp(res, lhs, rhs, set, 1, &status); + if (status!=0) decStatus(res, status, set); + return res; + } // decNumberQuantize + +/* ------------------------------------------------------------------ */ +/* decNumberReduce -- remove trailing zeros */ +/* */ +/* This computes C = 0 + A, and normalizes the result */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +// Previously known as Normalize +decNumber * decNumberNormalize(decNumber *res, const decNumber *rhs, + decContext *set) { + return decNumberReduce(res, rhs, set); + } // decNumberNormalize + +decNumber * decNumberReduce(decNumber *res, const decNumber *rhs, + decContext *set) { + #if DECSUBSET + decNumber *allocrhs=NULL; // non-NULL if rounded rhs allocated + #endif + uInt status=0; // as usual + Int residue=0; // as usual + Int dropped; // work + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + do { // protect allocated storage + #if DECSUBSET + if (!set->extended) { + // reduce operand and set lostDigits status, as needed + if (rhs->digits>set->digits) { + allocrhs=decRoundOperand(rhs, set, &status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + } + #endif + // [following code does not require input rounding] + + // Infinities copy through; NaNs need usual treatment + if (decNumberIsNaN(rhs)) { + decNaNs(res, rhs, NULL, set, &status); + break; + } + + // reduce result to the requested length and copy to result + decCopyFit(res, rhs, set, &residue, &status); // copy & round + decFinish(res, set, &residue, &status); // cleanup/set flags + decTrim(res, set, 1, 0, &dropped); // normalize in place + // [may clamp] + } while(0); // end protected + + #if DECSUBSET + if (allocrhs !=NULL) free(allocrhs); // .. + #endif + if (status!=0) decStatus(res, status, set);// then report status + return res; + } // decNumberReduce + +/* ------------------------------------------------------------------ */ +/* decNumberRescale -- force exponent to requested value */ +/* */ +/* This computes C = op(A, B), where op adjusts the coefficient */ +/* of C (by rounding or shifting) such that the exponent (-scale) */ +/* of C has the value B. The numerical value of C will equal A, */ +/* except for the effects of any rounding that occurred. */ +/* */ +/* res is C, the result. C may be A or B */ +/* lhs is A, the number to adjust */ +/* rhs is B, the requested exponent */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Unless there is an error or the result is infinite, the exponent */ +/* after the operation is guaranteed to be equal to B. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberRescale(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + decQuantizeOp(res, lhs, rhs, set, 0, &status); + if (status!=0) decStatus(res, status, set); + return res; + } // decNumberRescale + +/* ------------------------------------------------------------------ */ +/* decNumberRemainder -- divide and return remainder */ +/* */ +/* This computes C = A % B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X%X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberRemainder(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + decDivideOp(res, lhs, rhs, set, REMAINDER, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberRemainder + +/* ------------------------------------------------------------------ */ +/* decNumberRemainderNear -- divide and return remainder from nearest */ +/* */ +/* This computes C = A % B, where % is the IEEE remainder operator */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X%X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberRemainderNear(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + decDivideOp(res, lhs, rhs, set, REMNEAR, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberRemainderNear + +/* ------------------------------------------------------------------ */ +/* decNumberRotate -- rotate the coefficient of a Number left/right */ +/* */ +/* This computes C = A rot B (in base ten and rotating set->digits */ +/* digits). */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=XrotX) */ +/* lhs is A */ +/* rhs is B, the number of digits to rotate (-ve to right) */ +/* set is the context */ +/* */ +/* The digits of the coefficient of A are rotated to the left (if B */ +/* is positive) or to the right (if B is negative) without adjusting */ +/* the exponent or the sign of A. If lhs->digits is less than */ +/* set->digits the coefficient is padded with zeros on the left */ +/* before the rotate. Any leading zeros in the result are removed */ +/* as usual. */ +/* */ +/* B must be an integer (q=0) and in the range -set->digits through */ +/* +set->digits. */ +/* C must have space for set->digits digits. */ +/* NaNs are propagated as usual. Infinities are unaffected (but */ +/* B must be valid). No status is set unless B is invalid or an */ +/* operand is an sNaN. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberRotate(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + Int rotate; // rhs as an Int + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + // NaNs propagate as normal + if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) + decNaNs(res, lhs, rhs, set, &status); + // rhs must be an integer + else if (decNumberIsInfinite(rhs) || rhs->exponent!=0) + status=DEC_Invalid_operation; + else { // both numeric, rhs is an integer + rotate=decGetInt(rhs); // [cannot fail] + if (rotate==BADINT // something bad .. + || rotate==BIGODD || rotate==BIGEVEN // .. very big .. + || abs(rotate)>set->digits) // .. or out of range + status=DEC_Invalid_operation; + else { // rhs is OK + decNumberCopy(res, lhs); + // convert -ve rotate to equivalent positive rotation + if (rotate<0) rotate=set->digits+rotate; + if (rotate!=0 && rotate!=set->digits // zero or full rotation + && !decNumberIsInfinite(res)) { // lhs was infinite + // left-rotate to do; 0 < rotate < set->digits + uInt units, shift; // work + uInt msudigits; // digits in result msu + Unit *msu=res->lsu+D2U(res->digits)-1; // current msu + Unit *msumax=res->lsu+D2U(set->digits)-1; // rotation msu + for (msu++; msu<=msumax; msu++) *msu=0; // ensure high units=0 + res->digits=set->digits; // now full-length + msudigits=MSUDIGITS(res->digits); // actual digits in msu + + // rotation here is done in-place, in three steps + // 1. shift all to least up to one unit to unit-align final + // lsd [any digits shifted out are rotated to the left, + // abutted to the original msd (which may require split)] + // + // [if there are no whole units left to rotate, the + // rotation is now complete] + // + // 2. shift to least, from below the split point only, so that + // the final msd is in the right place in its Unit [any + // digits shifted out will fit exactly in the current msu, + // left aligned, no split required] + // + // 3. rotate all the units by reversing left part, right + // part, and then whole + // + // example: rotate right 8 digits (2 units + 2), DECDPUN=3. + // + // start: 00a bcd efg hij klm npq + // + // 1a 000 0ab cde fgh|ijk lmn [pq saved] + // 1b 00p qab cde fgh|ijk lmn + // + // 2a 00p qab cde fgh|00i jkl [mn saved] + // 2b mnp qab cde fgh|00i jkl + // + // 3a fgh cde qab mnp|00i jkl + // 3b fgh cde qab mnp|jkl 00i + // 3c 00i jkl mnp qab cde fgh + + // Step 1: amount to shift is the partial right-rotate count + rotate=set->digits-rotate; // make it right-rotate + units=rotate/DECDPUN; // whole units to rotate + shift=rotate%DECDPUN; // left-over digits count + if (shift>0) { // not an exact number of units + uInt save=res->lsu[0]%powers[shift]; // save low digit(s) + decShiftToLeast(res->lsu, D2U(res->digits), shift); + if (shift>msudigits) { // msumax-1 needs >0 digits + uInt rem=save%powers[shift-msudigits];// split save + *msumax=(Unit)(save/powers[shift-msudigits]); // and insert + *(msumax-1)=*(msumax-1) + +(Unit)(rem*powers[DECDPUN-(shift-msudigits)]); // .. + } + else { // all fits in msumax + *msumax=*msumax+(Unit)(save*powers[msudigits-shift]); // [maybe *1] + } + } // digits shift needed + + // If whole units to rotate... + if (units>0) { // some to do + // Step 2: the units to touch are the whole ones in rotate, + // if any, and the shift is DECDPUN-msudigits (which may be + // 0, again) + shift=DECDPUN-msudigits; + if (shift>0) { // not an exact number of units + uInt save=res->lsu[0]%powers[shift]; // save low digit(s) + decShiftToLeast(res->lsu, units, shift); + *msumax=*msumax+(Unit)(save*powers[msudigits]); + } // partial shift needed + + // Step 3: rotate the units array using triple reverse + // (reversing is easy and fast) + decReverse(res->lsu+units, msumax); // left part + decReverse(res->lsu, res->lsu+units-1); // right part + decReverse(res->lsu, msumax); // whole + } // whole units to rotate + // the rotation may have left an undetermined number of zeros + // on the left, so true length needs to be calculated + res->digits=decGetDigits(res->lsu, msumax-res->lsu+1); + } // rotate needed + } // rhs OK + } // numerics + if (status!=0) decStatus(res, status, set); + return res; + } // decNumberRotate + +/* ------------------------------------------------------------------ */ +/* decNumberSameQuantum -- test for equal exponents */ +/* */ +/* res is the result number, which will contain either 0 or 1 */ +/* lhs is a number to test */ +/* rhs is the second (usually a pattern) */ +/* */ +/* No errors are possible and no context is needed. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberSameQuantum(decNumber *res, const decNumber *lhs, + const decNumber *rhs) { + Unit ret=0; // return value + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, DECUNCONT)) return res; + #endif + + if (SPECIALARGS) { + if (decNumberIsNaN(lhs) && decNumberIsNaN(rhs)) ret=1; + else if (decNumberIsInfinite(lhs) && decNumberIsInfinite(rhs)) ret=1; + // [anything else with a special gives 0] + } + else if (lhs->exponent==rhs->exponent) ret=1; + + decNumberZero(res); // OK to overwrite an operand now + *res->lsu=ret; + return res; + } // decNumberSameQuantum + +/* ------------------------------------------------------------------ */ +/* decNumberScaleB -- multiply by a power of 10 */ +/* */ +/* This computes C = A x 10**B where B is an integer (q=0) with */ +/* maximum magnitude 2*(emax+digits) */ +/* */ +/* res is C, the result. C may be A or B */ +/* lhs is A, the number to adjust */ +/* rhs is B, the requested power of ten to use */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* The result may underflow or overflow. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberScaleB(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + Int reqexp; // requested exponent change [B] + uInt status=0; // accumulator + Int residue; // work + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + // Handle special values except lhs infinite + if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) + decNaNs(res, lhs, rhs, set, &status); + // rhs must be an integer + else if (decNumberIsInfinite(rhs) || rhs->exponent!=0) + status=DEC_Invalid_operation; + else { + // lhs is a number; rhs is a finite with q==0 + reqexp=decGetInt(rhs); // [cannot fail] + // maximum range is larger than getInt can handle, so this is + // more restrictive than the specification + if (reqexp==BADINT // something bad .. + || reqexp==BIGODD || reqexp==BIGEVEN // it was huge + || (abs(reqexp)+1)/2>(set->digits+set->emax)) // .. or out of range + status=DEC_Invalid_operation; + else { // rhs is OK + decNumberCopy(res, lhs); // all done if infinite lhs + if (!decNumberIsInfinite(res)) { // prepare to scale + Int exp=res->exponent; // save for overflow test + res->exponent+=reqexp; // adjust the exponent + if (((exp^reqexp)>=0) // same sign ... + && ((exp^res->exponent)<0)) { // .. but result had different + // the calculation overflowed, so force right treatment + if (exp<0) res->exponent=DEC_MIN_EMIN-DEC_MAX_DIGITS; + else res->exponent=DEC_MAX_EMAX+1; + } + residue=0; + decFinalize(res, set, &residue, &status); // final check + } // finite LHS + } // rhs OK + } // rhs finite + if (status!=0) decStatus(res, status, set); + return res; + } // decNumberScaleB + +/* ------------------------------------------------------------------ */ +/* decNumberShift -- shift the coefficient of a Number left or right */ +/* */ +/* This computes C = A << B or C = A >> -B (in base ten). */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X<digits through */ +/* +set->digits. */ +/* C must have space for set->digits digits. */ +/* NaNs are propagated as usual. Infinities are unaffected (but */ +/* B must be valid). No status is set unless B is invalid or an */ +/* operand is an sNaN. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberShift(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + Int shift; // rhs as an Int + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + // NaNs propagate as normal + if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) + decNaNs(res, lhs, rhs, set, &status); + // rhs must be an integer + else if (decNumberIsInfinite(rhs) || rhs->exponent!=0) + status=DEC_Invalid_operation; + else { // both numeric, rhs is an integer + shift=decGetInt(rhs); // [cannot fail] + if (shift==BADINT // something bad .. + || shift==BIGODD || shift==BIGEVEN // .. very big .. + || abs(shift)>set->digits) // .. or out of range + status=DEC_Invalid_operation; + else { // rhs is OK + decNumberCopy(res, lhs); + if (shift!=0 && !decNumberIsInfinite(res)) { // something to do + if (shift>0) { // to left + if (shift==set->digits) { // removing all + *res->lsu=0; // so place 0 + res->digits=1; // .. + } + else { // + // first remove leading digits if necessary + if (res->digits+shift>set->digits) { + decDecap(res, res->digits+shift-set->digits); + // that updated res->digits; may have gone to 1 (for a + // single digit or for zero + } + if (res->digits>1 || *res->lsu) // if non-zero.. + res->digits=decShiftToMost(res->lsu, res->digits, shift); + } // partial left + } // left + else { // to right + if (-shift>=res->digits) { // discarding all + *res->lsu=0; // so place 0 + res->digits=1; // .. + } + else { + decShiftToLeast(res->lsu, D2U(res->digits), -shift); + res->digits-=(-shift); + } + } // to right + } // non-0 non-Inf shift + } // rhs OK + } // numerics + if (status!=0) decStatus(res, status, set); + return res; + } // decNumberShift + +/* ------------------------------------------------------------------ */ +/* decNumberSquareRoot -- square root operator */ +/* */ +/* This computes C = squareroot(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context; note that rounding mode has no effect */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +/* This uses the following varying-precision algorithm in: */ +/* */ +/* Properly Rounded Variable Precision Square Root, T. E. Hull and */ +/* A. Abrham, ACM Transactions on Mathematical Software, Vol 11 #3, */ +/* pp229-237, ACM, September 1985. */ +/* */ +/* The square-root is calculated using Newton's method, after which */ +/* a check is made to ensure the result is correctly rounded. */ +/* */ +/* % [Reformatted original Numerical Turing source code follows.] */ +/* function sqrt(x : real) : real */ +/* % sqrt(x) returns the properly rounded approximation to the square */ +/* % root of x, in the precision of the calling environment, or it */ +/* % fails if x < 0. */ +/* % t e hull and a abrham, august, 1984 */ +/* if x <= 0 then */ +/* if x < 0 then */ +/* assert false */ +/* else */ +/* result 0 */ +/* end if */ +/* end if */ +/* var f := setexp(x, 0) % fraction part of x [0.1 <= x < 1] */ +/* var e := getexp(x) % exponent part of x */ +/* var approx : real */ +/* if e mod 2 = 0 then */ +/* approx := .259 + .819 * f % approx to root of f */ +/* else */ +/* f := f/l0 % adjustments */ +/* e := e + 1 % for odd */ +/* approx := .0819 + 2.59 * f % exponent */ +/* end if */ +/* */ +/* var p:= 3 */ +/* const maxp := currentprecision + 2 */ +/* loop */ +/* p := min(2*p - 2, maxp) % p = 4,6,10, . . . , maxp */ +/* precision p */ +/* approx := .5 * (approx + f/approx) */ +/* exit when p = maxp */ +/* end loop */ +/* */ +/* % approx is now within 1 ulp of the properly rounded square root */ +/* % of f; to ensure proper rounding, compare squares of (approx - */ +/* % l/2 ulp) and (approx + l/2 ulp) with f. */ +/* p := currentprecision */ +/* begin */ +/* precision p + 2 */ +/* const approxsubhalf := approx - setexp(.5, -p) */ +/* if mulru(approxsubhalf, approxsubhalf) > f then */ +/* approx := approx - setexp(.l, -p + 1) */ +/* else */ +/* const approxaddhalf := approx + setexp(.5, -p) */ +/* if mulrd(approxaddhalf, approxaddhalf) < f then */ +/* approx := approx + setexp(.l, -p + 1) */ +/* end if */ +/* end if */ +/* end */ +/* result setexp(approx, e div 2) % fix exponent */ +/* end sqrt */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberSquareRoot(decNumber *res, const decNumber *rhs, + decContext *set) { + decContext workset, approxset; // work contexts + decNumber dzero; // used for constant zero + Int maxp; // largest working precision + Int workp; // working precision + Int residue=0; // rounding residue + uInt status=0, ignore=0; // status accumulators + uInt rstatus; // .. + Int exp; // working exponent + Int ideal; // ideal (preferred) exponent + Int needbytes; // work + Int dropped; // .. + + #if DECSUBSET + decNumber *allocrhs=NULL; // non-NULL if rounded rhs allocated + #endif + // buffer for f [needs +1 in case DECBUFFER 0] + decNumber buff[D2N(DECBUFFER+1)]; + // buffer for a [needs +2 to match likely maxp] + decNumber bufa[D2N(DECBUFFER+2)]; + // buffer for temporary, b [must be same size as a] + decNumber bufb[D2N(DECBUFFER+2)]; + decNumber *allocbuff=NULL; // -> allocated buff, iff allocated + decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated + decNumber *allocbufb=NULL; // -> allocated bufb, iff allocated + decNumber *f=buff; // reduced fraction + decNumber *a=bufa; // approximation to result + decNumber *b=bufb; // intermediate result + // buffer for temporary variable, up to 3 digits + decNumber buft[D2N(3)]; + decNumber *t=buft; // up-to-3-digit constant or work + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + do { // protect allocated storage + #if DECSUBSET + if (!set->extended) { + // reduce operand and set lostDigits status, as needed + if (rhs->digits>set->digits) { + allocrhs=decRoundOperand(rhs, set, &status); + if (allocrhs==NULL) break; + // [Note: 'f' allocation below could reuse this buffer if + // used, but as this is rare they are kept separate for clarity.] + rhs=allocrhs; + } + } + #endif + // [following code does not require input rounding] + + // handle infinities and NaNs + if (SPECIALARG) { + if (decNumberIsInfinite(rhs)) { // an infinity + if (decNumberIsNegative(rhs)) status|=DEC_Invalid_operation; + else decNumberCopy(res, rhs); // +Infinity + } + else decNaNs(res, rhs, NULL, set, &status); // a NaN + break; + } + + // calculate the ideal (preferred) exponent [floor(exp/2)] + // [It would be nicer to write: ideal=rhs->exponent>>1, but this + // generates a compiler warning. Generated code is the same.] + ideal=(rhs->exponent&~1)/2; // target + + // handle zeros + if (ISZERO(rhs)) { + decNumberCopy(res, rhs); // could be 0 or -0 + res->exponent=ideal; // use the ideal [safe] + // use decFinish to clamp any out-of-range exponent, etc. + decFinish(res, set, &residue, &status); + break; + } + + // any other -x is an oops + if (decNumberIsNegative(rhs)) { + status|=DEC_Invalid_operation; + break; + } + + // space is needed for three working variables + // f -- the same precision as the RHS, reduced to 0.01->0.99... + // a -- Hull's approximation -- precision, when assigned, is + // currentprecision+1 or the input argument precision, + // whichever is larger (+2 for use as temporary) + // b -- intermediate temporary result (same size as a) + // if any is too long for local storage, then allocate + workp=MAXI(set->digits+1, rhs->digits); // actual rounding precision + workp=MAXI(workp, 7); // at least 7 for low cases + maxp=workp+2; // largest working precision + + needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit); + if (needbytes>(Int)sizeof(buff)) { + allocbuff=(decNumber *)malloc(needbytes); + if (allocbuff==NULL) { // hopeless -- abandon + status|=DEC_Insufficient_storage; + break;} + f=allocbuff; // use the allocated space + } + // a and b both need to be able to hold a maxp-length number + needbytes=sizeof(decNumber)+(D2U(maxp)-1)*sizeof(Unit); + if (needbytes>(Int)sizeof(bufa)) { // [same applies to b] + allocbufa=(decNumber *)malloc(needbytes); + allocbufb=(decNumber *)malloc(needbytes); + if (allocbufa==NULL || allocbufb==NULL) { // hopeless + status|=DEC_Insufficient_storage; + break;} + a=allocbufa; // use the allocated spaces + b=allocbufb; // .. + } + + // copy rhs -> f, save exponent, and reduce so 0.1 <= f < 1 + decNumberCopy(f, rhs); + exp=f->exponent+f->digits; // adjusted to Hull rules + f->exponent=-(f->digits); // to range + + // set up working context + decContextDefault(&workset, DEC_INIT_DECIMAL64); + workset.emax=DEC_MAX_EMAX; + workset.emin=DEC_MIN_EMIN; + + // [Until further notice, no error is possible and status bits + // (Rounded, etc.) should be ignored, not accumulated.] + + // Calculate initial approximation, and allow for odd exponent + workset.digits=workp; // p for initial calculation + t->bits=0; t->digits=3; + a->bits=0; a->digits=3; + if ((exp & 1)==0) { // even exponent + // Set t=0.259, a=0.819 + t->exponent=-3; + a->exponent=-3; + #if DECDPUN>=3 + t->lsu[0]=259; + a->lsu[0]=819; + #elif DECDPUN==2 + t->lsu[0]=59; t->lsu[1]=2; + a->lsu[0]=19; a->lsu[1]=8; + #else + t->lsu[0]=9; t->lsu[1]=5; t->lsu[2]=2; + a->lsu[0]=9; a->lsu[1]=1; a->lsu[2]=8; + #endif + } + else { // odd exponent + // Set t=0.0819, a=2.59 + f->exponent--; // f=f/10 + exp++; // e=e+1 + t->exponent=-4; + a->exponent=-2; + #if DECDPUN>=3 + t->lsu[0]=819; + a->lsu[0]=259; + #elif DECDPUN==2 + t->lsu[0]=19; t->lsu[1]=8; + a->lsu[0]=59; a->lsu[1]=2; + #else + t->lsu[0]=9; t->lsu[1]=1; t->lsu[2]=8; + a->lsu[0]=9; a->lsu[1]=5; a->lsu[2]=2; + #endif + } + + decMultiplyOp(a, a, f, &workset, &ignore); // a=a*f + decAddOp(a, a, t, &workset, 0, &ignore); // ..+t + // [a is now the initial approximation for sqrt(f), calculated with + // currentprecision, which is also a's precision.] + + // the main calculation loop + decNumberZero(&dzero); // make 0 + decNumberZero(t); // set t = 0.5 + t->lsu[0]=5; // .. + t->exponent=-1; // .. + workset.digits=3; // initial p + for (; workset.digitsexponent+=exp/2; // set correct exponent + rstatus=0; // clear status + residue=0; // .. and accumulator + decCopyFit(a, a, &approxset, &residue, &rstatus); // reduce (if needed) + decFinish(a, &approxset, &residue, &rstatus); // clean and finalize + + // Overflow was possible if the input exponent was out-of-range, + // in which case quit + if (rstatus&DEC_Overflow) { + status=rstatus; // use the status as-is + decNumberCopy(res, a); // copy to result + break; + } + + // Preserve status except Inexact/Rounded + status|=(rstatus & ~(DEC_Rounded|DEC_Inexact)); + + // Carry out the Hull correction + a->exponent-=exp/2; // back to 0.1->1 + + // a is now at final precision and within 1 ulp of the properly + // rounded square root of f; to ensure proper rounding, compare + // squares of (a - l/2 ulp) and (a + l/2 ulp) with f. + // Here workset.digits=maxp and t=0.5, and a->digits determines + // the ulp + workset.digits--; // maxp-1 is OK now + t->exponent=-a->digits-1; // make 0.5 ulp + decAddOp(b, a, t, &workset, DECNEG, &ignore); // b = a - 0.5 ulp + workset.round=DEC_ROUND_UP; + decMultiplyOp(b, b, b, &workset, &ignore); // b = mulru(b, b) + decCompareOp(b, f, b, &workset, COMPARE, &ignore); // b ? f, reversed + if (decNumberIsNegative(b)) { // f < b [i.e., b > f] + // this is the more common adjustment, though both are rare + t->exponent++; // make 1.0 ulp + t->lsu[0]=1; // .. + decAddOp(a, a, t, &workset, DECNEG, &ignore); // a = a - 1 ulp + // assign to approx [round to length] + approxset.emin-=exp/2; // adjust to match a + approxset.emax-=exp/2; + decAddOp(a, &dzero, a, &approxset, 0, &ignore); + } + else { + decAddOp(b, a, t, &workset, 0, &ignore); // b = a + 0.5 ulp + workset.round=DEC_ROUND_DOWN; + decMultiplyOp(b, b, b, &workset, &ignore); // b = mulrd(b, b) + decCompareOp(b, b, f, &workset, COMPARE, &ignore); // b ? f + if (decNumberIsNegative(b)) { // b < f + t->exponent++; // make 1.0 ulp + t->lsu[0]=1; // .. + decAddOp(a, a, t, &workset, 0, &ignore); // a = a + 1 ulp + // assign to approx [round to length] + approxset.emin-=exp/2; // adjust to match a + approxset.emax-=exp/2; + decAddOp(a, &dzero, a, &approxset, 0, &ignore); + } + } + // [no errors are possible in the above, and rounding/inexact during + // estimation are irrelevant, so status was not accumulated] + + // Here, 0.1 <= a < 1 (still), so adjust back + a->exponent+=exp/2; // set correct exponent + + // count droppable zeros [after any subnormal rounding] by + // trimming a copy + decNumberCopy(b, a); + decTrim(b, set, 1, 1, &dropped); // [drops trailing zeros] + + // Set Inexact and Rounded. The answer can only be exact if + // it is short enough so that squaring it could fit in workp + // digits, so this is the only (relatively rare) condition that + // a careful check is needed + if (b->digits*2-1 > workp) { // cannot fit + status|=DEC_Inexact|DEC_Rounded; + } + else { // could be exact/unrounded + uInt mstatus=0; // local status + decMultiplyOp(b, b, b, &workset, &mstatus); // try the multiply + if (mstatus&DEC_Overflow) { // result just won't fit + status|=DEC_Inexact|DEC_Rounded; + } + else { // plausible + decCompareOp(t, b, rhs, &workset, COMPARE, &mstatus); // b ? rhs + if (!ISZERO(t)) status|=DEC_Inexact|DEC_Rounded; // not equal + else { // is Exact + // here, dropped is the count of trailing zeros in 'a' + // use closest exponent to ideal... + Int todrop=ideal-a->exponent; // most that can be dropped + if (todrop<0) status|=DEC_Rounded; // ideally would add 0s + else { // unrounded + // there are some to drop, but emax may not allow all + Int maxexp=set->emax-set->digits+1; + Int maxdrop=maxexp-a->exponent; + if (todrop>maxdrop && set->clamp) { // apply clamping + todrop=maxdrop; + status|=DEC_Clamped; + } + if (dropped0) { // have some to drop + decShiftToLeast(a->lsu, D2U(a->digits), todrop); + a->exponent+=todrop; // maintain numerical value + a->digits-=todrop; // new length + } + } + } + } + } + + // double-check Underflow, as perhaps the result could not have + // been subnormal (initial argument too big), or it is now Exact + if (status&DEC_Underflow) { + Int ae=rhs->exponent+rhs->digits-1; // adjusted exponent + // check if truly subnormal + #if DECEXTFLAG // DEC_Subnormal too + if (ae>=set->emin*2) status&=~(DEC_Subnormal|DEC_Underflow); + #else + if (ae>=set->emin*2) status&=~DEC_Underflow; + #endif + // check if truly inexact + if (!(status&DEC_Inexact)) status&=~DEC_Underflow; + } + + decNumberCopy(res, a); // a is now the result + } while(0); // end protected + + if (allocbuff!=NULL) free(allocbuff); // drop any storage used + if (allocbufa!=NULL) free(allocbufa); // .. + if (allocbufb!=NULL) free(allocbufb); // .. + #if DECSUBSET + if (allocrhs !=NULL) free(allocrhs); // .. + #endif + if (status!=0) decStatus(res, status, set);// then report status + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberSquareRoot + +/* ------------------------------------------------------------------ */ +/* decNumberSubtract -- subtract two Numbers */ +/* */ +/* This computes C = A - B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X-X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberSubtract(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; // accumulator + + decAddOp(res, lhs, rhs, set, DECNEG, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } // decNumberSubtract + +/* ------------------------------------------------------------------ */ +/* decNumberToIntegralExact -- round-to-integral-value with InExact */ +/* decNumberToIntegralValue -- round-to-integral-value */ +/* */ +/* res is the result */ +/* rhs is input number */ +/* set is the context */ +/* */ +/* res must have space for any value of rhs. */ +/* */ +/* This implements the IEEE special operators and therefore treats */ +/* special values as valid. For finite numbers it returns */ +/* rescale(rhs, 0) if rhs->exponent is <0. */ +/* Otherwise the result is rhs (so no error is possible, except for */ +/* sNaN). */ +/* */ +/* The context is used for rounding mode and status after sNaN, but */ +/* the digits setting is ignored. The Exact version will signal */ +/* Inexact if the result differs numerically from rhs; the other */ +/* never signals Inexact. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberToIntegralExact(decNumber *res, const decNumber *rhs, + decContext *set) { + decNumber dn; + decContext workset; // working context + uInt status=0; // accumulator + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + // handle infinities and NaNs + if (SPECIALARG) { + if (decNumberIsInfinite(rhs)) decNumberCopy(res, rhs); // an Infinity + else decNaNs(res, rhs, NULL, set, &status); // a NaN + } + else { // finite + // have a finite number; no error possible (res must be big enough) + if (rhs->exponent>=0) return decNumberCopy(res, rhs); + // that was easy, but if negative exponent there is work to do... + workset=*set; // clone rounding, etc. + workset.digits=rhs->digits; // no length rounding + workset.traps=0; // no traps + decNumberZero(&dn); // make a number with exponent 0 + decNumberQuantize(res, rhs, &dn, &workset); + status|=workset.status; + } + if (status!=0) decStatus(res, status, set); + return res; + } // decNumberToIntegralExact + +decNumber * decNumberToIntegralValue(decNumber *res, const decNumber *rhs, + decContext *set) { + decContext workset=*set; // working context + workset.traps=0; // no traps + decNumberToIntegralExact(res, rhs, &workset); + // this never affects set, except for sNaNs; NaN will have been set + // or propagated already, so no need to call decStatus + set->status|=workset.status&DEC_Invalid_operation; + return res; + } // decNumberToIntegralValue + +/* ------------------------------------------------------------------ */ +/* decNumberXor -- XOR two Numbers, digitwise */ +/* */ +/* This computes C = A ^ B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X^X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context (used for result length and error report) */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Logical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberXor(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + const Unit *ua, *ub; // -> operands + const Unit *msua, *msub; // -> operand msus + Unit *uc, *msuc; // -> result and its msu + Int msudigs; // digits in res msu + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs) + || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + // operands are valid + ua=lhs->lsu; // bottom-up + ub=rhs->lsu; // .. + uc=res->lsu; // .. + msua=ua+D2U(lhs->digits)-1; // -> msu of lhs + msub=ub+D2U(rhs->digits)-1; // -> msu of rhs + msuc=uc+D2U(set->digits)-1; // -> msu of result + msudigs=MSUDIGITS(set->digits); // [faster than remainder] + for (; uc<=msuc; ua++, ub++, uc++) { // Unit loop + Unit a, b; // extract units + if (ua>msua) a=0; + else a=*ua; + if (ub>msub) b=0; + else b=*ub; + *uc=0; // can now write back + if (a|b) { // maybe 1 bits to examine + Int i, j; + // This loop could be unrolled and/or use BIN2BCD tables + for (i=0; i1) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + if (uc==msuc && i==msudigs-1) break; // just did final digit + } // each digit + } // non-zero + } // each unit + // [here uc-1 is the msu of the result] + res->digits=decGetDigits(res->lsu, uc-res->lsu); + res->exponent=0; // integer + res->bits=0; // sign=0 + return res; // [no status to set] + } // decNumberXor + + +/* ================================================================== */ +/* Utility routines */ +/* ================================================================== */ + +/* ------------------------------------------------------------------ */ +/* decNumberClass -- return the decClass of a decNumber */ +/* dn -- the decNumber to test */ +/* set -- the context to use for Emin */ +/* returns the decClass enum */ +/* ------------------------------------------------------------------ */ +enum decClass decNumberClass(const decNumber *dn, decContext *set) { + if (decNumberIsSpecial(dn)) { + if (decNumberIsQNaN(dn)) return DEC_CLASS_QNAN; + if (decNumberIsSNaN(dn)) return DEC_CLASS_SNAN; + // must be an infinity + if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_INF; + return DEC_CLASS_POS_INF; + } + // is finite + if (decNumberIsNormal(dn, set)) { // most common + if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_NORMAL; + return DEC_CLASS_POS_NORMAL; + } + // is subnormal or zero + if (decNumberIsZero(dn)) { // most common + if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_ZERO; + return DEC_CLASS_POS_ZERO; + } + if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_SUBNORMAL; + return DEC_CLASS_POS_SUBNORMAL; + } // decNumberClass + +/* ------------------------------------------------------------------ */ +/* decNumberClassToString -- convert decClass to a string */ +/* */ +/* eclass is a valid decClass */ +/* returns a constant string describing the class (max 13+1 chars) */ +/* ------------------------------------------------------------------ */ +const char *decNumberClassToString(enum decClass eclass) { + if (eclass==DEC_CLASS_POS_NORMAL) return DEC_ClassString_PN; + if (eclass==DEC_CLASS_NEG_NORMAL) return DEC_ClassString_NN; + if (eclass==DEC_CLASS_POS_ZERO) return DEC_ClassString_PZ; + if (eclass==DEC_CLASS_NEG_ZERO) return DEC_ClassString_NZ; + if (eclass==DEC_CLASS_POS_SUBNORMAL) return DEC_ClassString_PS; + if (eclass==DEC_CLASS_NEG_SUBNORMAL) return DEC_ClassString_NS; + if (eclass==DEC_CLASS_POS_INF) return DEC_ClassString_PI; + if (eclass==DEC_CLASS_NEG_INF) return DEC_ClassString_NI; + if (eclass==DEC_CLASS_QNAN) return DEC_ClassString_QN; + if (eclass==DEC_CLASS_SNAN) return DEC_ClassString_SN; + return DEC_ClassString_UN; // Unknown + } // decNumberClassToString + +/* ------------------------------------------------------------------ */ +/* decNumberCopy -- copy a number */ +/* */ +/* dest is the target decNumber */ +/* src is the source decNumber */ +/* returns dest */ +/* */ +/* (dest==src is allowed and is a no-op) */ +/* All fields are updated as required. This is a utility operation, */ +/* so special values are unchanged and no error is possible. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCopy(decNumber *dest, const decNumber *src) { + + #if DECCHECK + if (src==NULL) return decNumberZero(dest); + #endif + + if (dest==src) return dest; // no copy required + + // Use explicit assignments here as structure assignment could copy + // more than just the lsu (for small DECDPUN). This would not affect + // the value of the results, but could disturb test harness spill + // checking. + dest->bits=src->bits; + dest->exponent=src->exponent; + dest->digits=src->digits; + dest->lsu[0]=src->lsu[0]; + if (src->digits>DECDPUN) { // more Units to come + const Unit *smsup, *s; // work + Unit *d; // .. + // memcpy for the remaining Units would be safe as they cannot + // overlap. However, this explicit loop is faster in short cases. + d=dest->lsu+1; // -> first destination + smsup=src->lsu+D2U(src->digits); // -> source msu+1 + for (s=src->lsu+1; sdigits digits. */ +/* No exception or error can occur; this is a quiet bitwise operation.*/ +/* See also decNumberAbs for a checking version of this. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCopyAbs(decNumber *res, const decNumber *rhs) { + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res; + #endif + decNumberCopy(res, rhs); + res->bits&=~DECNEG; // turn off sign + return res; + } // decNumberCopyAbs + +/* ------------------------------------------------------------------ */ +/* decNumberCopyNegate -- quiet negate value operator */ +/* */ +/* This sets C = negate(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* */ +/* C must have space for set->digits digits. */ +/* No exception or error can occur; this is a quiet bitwise operation.*/ +/* See also decNumberMinus for a checking version of this. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCopyNegate(decNumber *res, const decNumber *rhs) { + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res; + #endif + decNumberCopy(res, rhs); + res->bits^=DECNEG; // invert the sign + return res; + } // decNumberCopyNegate + +/* ------------------------------------------------------------------ */ +/* decNumberCopySign -- quiet copy and set sign operator */ +/* */ +/* This sets C = A with the sign of B */ +/* */ +/* res is C, the result. C may be A */ +/* lhs is A */ +/* rhs is B */ +/* */ +/* C must have space for set->digits digits. */ +/* No exception or error can occur; this is a quiet bitwise operation.*/ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCopySign(decNumber *res, const decNumber *lhs, + const decNumber *rhs) { + uByte sign; // rhs sign + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res; + #endif + sign=rhs->bits & DECNEG; // save sign bit + decNumberCopy(res, lhs); + res->bits&=~DECNEG; // clear the sign + res->bits|=sign; // set from rhs + return res; + } // decNumberCopySign + +/* ------------------------------------------------------------------ */ +/* decNumberGetBCD -- get the coefficient in BCD8 */ +/* dn is the source decNumber */ +/* bcd is the uInt array that will receive dn->digits BCD bytes, */ +/* most-significant at offset 0 */ +/* returns bcd */ +/* */ +/* bcd must have at least dn->digits bytes. No error is possible; if */ +/* dn is a NaN or Infinite, digits must be 1 and the coefficient 0. */ +/* ------------------------------------------------------------------ */ +uByte * decNumberGetBCD(const decNumber *dn, uByte *bcd) { + uByte *ub=bcd+dn->digits-1; // -> lsd + const Unit *up=dn->lsu; // Unit pointer, -> lsu + + #if DECDPUN==1 // trivial simple copy + for (; ub>=bcd; ub--, up++) *ub=*up; + #else // chopping needed + uInt u=*up; // work + uInt cut=DECDPUN; // downcounter through unit + for (; ub>=bcd; ub--) { + *ub=(uByte)(u%10); // [*6554 trick inhibits, here] + u=u/10; + cut--; + if (cut>0) continue; // more in this unit + up++; + u=*up; + cut=DECDPUN; + } + #endif + return bcd; + } // decNumberGetBCD + +/* ------------------------------------------------------------------ */ +/* decNumberSetBCD -- set (replace) the coefficient from BCD8 */ +/* dn is the target decNumber */ +/* bcd is the uInt array that will source n BCD bytes, most- */ +/* significant at offset 0 */ +/* n is the number of digits in the source BCD array (bcd) */ +/* returns dn */ +/* */ +/* dn must have space for at least n digits. No error is possible; */ +/* if dn is a NaN, or Infinite, or is to become a zero, n must be 1 */ +/* and bcd[0] zero. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberSetBCD(decNumber *dn, const uByte *bcd, uInt n) { + Unit *up=dn->lsu+D2U(dn->digits)-1; // -> msu [target pointer] + const uByte *ub=bcd; // -> source msd + + #if DECDPUN==1 // trivial simple copy + for (; ub=dn->lsu; up--) { // each Unit from msu + *up=0; // will take <=DECDPUN digits + for (; cut>0; ub++, cut--) *up=X10(*up)+*ub; + cut=DECDPUN; // next Unit has all digits + } + #endif + dn->digits=n; // set digit count + return dn; + } // decNumberSetBCD + +/* ------------------------------------------------------------------ */ +/* decNumberIsNormal -- test normality of a decNumber */ +/* dn is the decNumber to test */ +/* set is the context to use for Emin */ +/* returns 1 if |dn| is finite and >=Nmin, 0 otherwise */ +/* ------------------------------------------------------------------ */ +Int decNumberIsNormal(const decNumber *dn, decContext *set) { + Int ae; // adjusted exponent + #if DECCHECK + if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0; + #endif + + if (decNumberIsSpecial(dn)) return 0; // not finite + if (decNumberIsZero(dn)) return 0; // not non-zero + + ae=dn->exponent+dn->digits-1; // adjusted exponent + if (aeemin) return 0; // is subnormal + return 1; + } // decNumberIsNormal + +/* ------------------------------------------------------------------ */ +/* decNumberIsSubnormal -- test subnormality of a decNumber */ +/* dn is the decNumber to test */ +/* set is the context to use for Emin */ +/* returns 1 if |dn| is finite, non-zero, and exponent+dn->digits-1; // adjusted exponent + if (aeemin) return 1; // is subnormal + return 0; + } // decNumberIsSubnormal + +/* ------------------------------------------------------------------ */ +/* decNumberTrim -- remove insignificant zeros */ +/* */ +/* dn is the number to trim */ +/* returns dn */ +/* */ +/* All fields are updated as required. This is a utility operation, */ +/* so special values are unchanged and no error is possible. The */ +/* zeros are removed unconditionally. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberTrim(decNumber *dn) { + Int dropped; // work + decContext set; // .. + #if DECCHECK + if (decCheckOperands(DECUNRESU, DECUNUSED, dn, DECUNCONT)) return dn; + #endif + decContextDefault(&set, DEC_INIT_BASE); // clamp=0 + return decTrim(dn, &set, 0, 1, &dropped); + } // decNumberTrim + +/* ------------------------------------------------------------------ */ +/* decNumberVersion -- return the name and version of this module */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +const char * decNumberVersion(void) { + return DECVERSION; + } // decNumberVersion + +/* ------------------------------------------------------------------ */ +/* decNumberZero -- set a number to 0 */ +/* */ +/* dn is the number to set, with space for one digit */ +/* returns dn */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +// Memset is not used as it is much slower in some environments. +decNumber * decNumberZero(decNumber *dn) { + + #if DECCHECK + if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn; + #endif + + dn->bits=0; + dn->exponent=0; + dn->digits=1; + dn->lsu[0]=0; + return dn; + } // decNumberZero + +/* ================================================================== */ +/* Local routines */ +/* ================================================================== */ + +/* ------------------------------------------------------------------ */ +/* decToString -- lay out a number into a string */ +/* */ +/* dn is the number to lay out */ +/* string is where to lay out the number */ +/* eng is 1 if Engineering, 0 if Scientific */ +/* */ +/* string must be at least dn->digits+14 characters long */ +/* No error is possible. */ +/* */ +/* Note that this routine can generate a -0 or 0.000. These are */ +/* never generated in subset to-number or arithmetic, but can occur */ +/* in non-subset arithmetic (e.g., -1*0 or 1.234-1.234). */ +/* ------------------------------------------------------------------ */ +// If DECCHECK is enabled the string "?" is returned if a number is +// invalid. +static void decToString(const decNumber *dn, char *string, Flag eng) { + Int exp=dn->exponent; // local copy + Int e; // E-part value + Int pre; // digits before the '.' + Int cut; // for counting digits in a Unit + char *c=string; // work [output pointer] + const Unit *up=dn->lsu+D2U(dn->digits)-1; // -> msu [input pointer] + uInt u, pow; // work + + #if DECCHECK + if (decCheckOperands(DECUNRESU, dn, DECUNUSED, DECUNCONT)) { + strcpy(string, "?"); + return;} + #endif + + if (decNumberIsNegative(dn)) { // Negatives get a minus + *c='-'; + c++; + } + if (dn->bits&DECSPECIAL) { // Is a special value + if (decNumberIsInfinite(dn)) { + strcpy(c, "Inf"); + strcpy(c+3, "inity"); + return;} + // a NaN + if (dn->bits&DECSNAN) { // signalling NaN + *c='s'; + c++; + } + strcpy(c, "NaN"); + c+=3; // step past + // if not a clean non-zero coefficient, that's all there is in a + // NaN string + if (exp!=0 || (*dn->lsu==0 && dn->digits==1)) return; + // [drop through to add integer] + } + + // calculate how many digits in msu, and hence first cut + cut=MSUDIGITS(dn->digits); // [faster than remainder] + cut--; // power of ten for digit + + if (exp==0) { // simple integer [common fastpath] + for (;up>=dn->lsu; up--) { // each Unit from msu + u=*up; // contains DECDPUN digits to lay out + for (; cut>=0; c++, cut--) TODIGIT(u, cut, c, pow); + cut=DECDPUN-1; // next Unit has all digits + } + *c='\0'; // terminate the string + return;} + + /* non-0 exponent -- assume plain form */ + pre=dn->digits+exp; // digits before '.' + e=0; // no E + if ((exp>0) || (pre<-5)) { // need exponential form + e=exp+dn->digits-1; // calculate E value + pre=1; // assume one digit before '.' + if (eng && (e!=0)) { // engineering: may need to adjust + Int adj; // adjustment + // The C remainder operator is undefined for negative numbers, so + // a positive remainder calculation must be used here + if (e<0) { + adj=(-e)%3; + if (adj!=0) adj=3-adj; + } + else { // e>0 + adj=e%3; + } + e=e-adj; + // if dealing with zero still produce an exponent which is a + // multiple of three, as expected, but there will only be the + // one zero before the E, still. Otherwise note the padding. + if (!ISZERO(dn)) pre+=adj; + else { // is zero + if (adj!=0) { // 0.00Esnn needed + e=e+3; + pre=-(2-adj); + } + } // zero + } // eng + } // need exponent + + /* lay out the digits of the coefficient, adding 0s and . as needed */ + u=*up; + if (pre>0) { // xxx.xxx or xx00 (engineering) form + Int n=pre; + for (; pre>0; pre--, c++, cut--) { + if (cut<0) { // need new Unit + if (up==dn->lsu) break; // out of input digits (pre>digits) + up--; + cut=DECDPUN-1; + u=*up; + } + TODIGIT(u, cut, c, pow); + } + if (ndigits) { // more to come, after '.' + *c='.'; c++; + for (;; c++, cut--) { + if (cut<0) { // need new Unit + if (up==dn->lsu) break; // out of input digits + up--; + cut=DECDPUN-1; + u=*up; + } + TODIGIT(u, cut, c, pow); + } + } + else for (; pre>0; pre--, c++) *c='0'; // 0 padding (for engineering) needed + } + else { // 0.xxx or 0.000xxx form + *c='0'; c++; + *c='.'; c++; + for (; pre<0; pre++, c++) *c='0'; // add any 0's after '.' + for (; ; c++, cut--) { + if (cut<0) { // need new Unit + if (up==dn->lsu) break; // out of input digits + up--; + cut=DECDPUN-1; + u=*up; + } + TODIGIT(u, cut, c, pow); + } + } + + /* Finally add the E-part, if needed. It will never be 0, has a + base maximum and minimum of +999999999 through -999999999, but + could range down to -1999999998 for anormal numbers */ + if (e!=0) { + Flag had=0; // 1=had non-zero + *c='E'; c++; + *c='+'; c++; // assume positive + u=e; // .. + if (e<0) { + *(c-1)='-'; // oops, need - + u=-e; // uInt, please + } + // lay out the exponent [_itoa or equivalent is not ANSI C] + for (cut=9; cut>=0; cut--) { + TODIGIT(u, cut, c, pow); + if (*c=='0' && !had) continue; // skip leading zeros + had=1; // had non-0 + c++; // step for next + } // cut + } + *c='\0'; // terminate the string (all paths) + return; + } // decToString + +/* ------------------------------------------------------------------ */ +/* decAddOp -- add/subtract operation */ +/* */ +/* This computes C = A + B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X+X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* negate is DECNEG if rhs should be negated, or 0 otherwise */ +/* status accumulates status for the caller */ +/* */ +/* C must have space for set->digits digits. */ +/* Inexact in status must be 0 for correct Exact zero sign in result */ +/* ------------------------------------------------------------------ */ +/* If possible, the coefficient is calculated directly into C. */ +/* However, if: */ +/* -- a digits+1 calculation is needed because the numbers are */ +/* unaligned and span more than set->digits digits */ +/* -- a carry to digits+1 digits looks possible */ +/* -- C is the same as A or B, and the result would destructively */ +/* overlap the A or B coefficient */ +/* then the result must be calculated into a temporary buffer. In */ +/* this case a local (stack) buffer is used if possible, and only if */ +/* too long for that does malloc become the final resort. */ +/* */ +/* Misalignment is handled as follows: */ +/* Apad: (AExp>BExp) Swap operands and proceed as for BExp>AExp. */ +/* BPad: Apply the padding by a combination of shifting (whole */ +/* units) and multiplication (part units). */ +/* */ +/* Addition, especially x=x+1, is speed-critical. */ +/* The static buffer is larger than might be expected to allow for */ +/* calls from higher-level funtions (notable exp). */ +/* ------------------------------------------------------------------ */ +static decNumber * decAddOp(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set, + uByte negate, uInt *status) { + #if DECSUBSET + decNumber *alloclhs=NULL; // non-NULL if rounded lhs allocated + decNumber *allocrhs=NULL; // .., rhs + #endif + Int rhsshift; // working shift (in Units) + Int maxdigits; // longest logical length + Int mult; // multiplier + Int residue; // rounding accumulator + uByte bits; // result bits + Flag diffsign; // non-0 if arguments have different sign + Unit *acc; // accumulator for result + Unit accbuff[SD2U(DECBUFFER*2+20)]; // local buffer [*2+20 reduces many + // allocations when called from + // other operations, notable exp] + Unit *allocacc=NULL; // -> allocated acc buffer, iff allocated + Int reqdigits=set->digits; // local copy; requested DIGITS + Int padding; // work + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + do { // protect allocated storage + #if DECSUBSET + if (!set->extended) { + // reduce operands and set lostDigits status, as needed + if (lhs->digits>reqdigits) { + alloclhs=decRoundOperand(lhs, set, status); + if (alloclhs==NULL) break; + lhs=alloclhs; + } + if (rhs->digits>reqdigits) { + allocrhs=decRoundOperand(rhs, set, status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + } + #endif + // [following code does not require input rounding] + + // note whether signs differ [used all paths] + diffsign=(Flag)((lhs->bits^rhs->bits^negate)&DECNEG); + + // handle infinities and NaNs + if (SPECIALARGS) { // a special bit set + if (SPECIALARGS & (DECSNAN | DECNAN)) // a NaN + decNaNs(res, lhs, rhs, set, status); + else { // one or two infinities + if (decNumberIsInfinite(lhs)) { // LHS is infinity + // two infinities with different signs is invalid + if (decNumberIsInfinite(rhs) && diffsign) { + *status|=DEC_Invalid_operation; + break; + } + bits=lhs->bits & DECNEG; // get sign from LHS + } + else bits=(rhs->bits^negate) & DECNEG;// RHS must be Infinity + bits|=DECINF; + decNumberZero(res); + res->bits=bits; // set +/- infinity + } // an infinity + break; + } + + // Quick exit for add 0s; return the non-0, modified as need be + if (ISZERO(lhs)) { + Int adjust; // work + Int lexp=lhs->exponent; // save in case LHS==RES + bits=lhs->bits; // .. + residue=0; // clear accumulator + decCopyFit(res, rhs, set, &residue, status); // copy (as needed) + res->bits^=negate; // flip if rhs was negated + #if DECSUBSET + if (set->extended) { // exponents on zeros count + #endif + // exponent will be the lower of the two + adjust=lexp-res->exponent; // adjustment needed [if -ve] + if (ISZERO(res)) { // both 0: special IEEE 754 rules + if (adjust<0) res->exponent=lexp; // set exponent + // 0-0 gives +0 unless rounding to -infinity, and -0-0 gives -0 + if (diffsign) { + if (set->round!=DEC_ROUND_FLOOR) res->bits=0; + else res->bits=DECNEG; // preserve 0 sign + } + } + else { // non-0 res + if (adjust<0) { // 0-padding needed + if ((res->digits-adjust)>set->digits) { + adjust=res->digits-set->digits; // to fit exactly + *status|=DEC_Rounded; // [but exact] + } + res->digits=decShiftToMost(res->lsu, res->digits, -adjust); + res->exponent+=adjust; // set the exponent. + } + } // non-0 res + #if DECSUBSET + } // extended + #endif + decFinish(res, set, &residue, status); // clean and finalize + break;} + + if (ISZERO(rhs)) { // [lhs is non-zero] + Int adjust; // work + Int rexp=rhs->exponent; // save in case RHS==RES + bits=rhs->bits; // be clean + residue=0; // clear accumulator + decCopyFit(res, lhs, set, &residue, status); // copy (as needed) + #if DECSUBSET + if (set->extended) { // exponents on zeros count + #endif + // exponent will be the lower of the two + // [0-0 case handled above] + adjust=rexp-res->exponent; // adjustment needed [if -ve] + if (adjust<0) { // 0-padding needed + if ((res->digits-adjust)>set->digits) { + adjust=res->digits-set->digits; // to fit exactly + *status|=DEC_Rounded; // [but exact] + } + res->digits=decShiftToMost(res->lsu, res->digits, -adjust); + res->exponent+=adjust; // set the exponent. + } + #if DECSUBSET + } // extended + #endif + decFinish(res, set, &residue, status); // clean and finalize + break;} + + // [NB: both fastpath and mainpath code below assume these cases + // (notably 0-0) have already been handled] + + // calculate the padding needed to align the operands + padding=rhs->exponent-lhs->exponent; + + // Fastpath cases where the numbers are aligned and normal, the RHS + // is all in one unit, no operand rounding is needed, and no carry, + // lengthening, or borrow is needed + if (padding==0 + && rhs->digits<=DECDPUN + && rhs->exponent>=set->emin // [some normals drop through] + && rhs->exponent<=set->emax-set->digits+1 // [could clamp] + && rhs->digits<=reqdigits + && lhs->digits<=reqdigits) { + Int partial=*lhs->lsu; + if (!diffsign) { // adding + partial+=*rhs->lsu; + if ((partial<=DECDPUNMAX) // result fits in unit + && (lhs->digits>=DECDPUN || // .. and no digits-count change + partial<(Int)powers[lhs->digits])) { // .. + if (res!=lhs) decNumberCopy(res, lhs); // not in place + *res->lsu=(Unit)partial; // [copy could have overwritten RHS] + break; + } + // else drop out for careful add + } + else { // signs differ + partial-=*rhs->lsu; + if (partial>0) { // no borrow needed, and non-0 result + if (res!=lhs) decNumberCopy(res, lhs); // not in place + *res->lsu=(Unit)partial; + // this could have reduced digits [but result>0] + res->digits=decGetDigits(res->lsu, D2U(res->digits)); + break; + } + // else drop out for careful subtract + } + } + + // Now align (pad) the lhs or rhs so they can be added or + // subtracted, as necessary. If one number is much larger than + // the other (that is, if in plain form there is a least one + // digit between the lowest digit of one and the highest of the + // other) padding with up to DIGITS-1 trailing zeros may be + // needed; then apply rounding (as exotic rounding modes may be + // affected by the residue). + rhsshift=0; // rhs shift to left (padding) in Units + bits=lhs->bits; // assume sign is that of LHS + mult=1; // likely multiplier + + // [if padding==0 the operands are aligned; no padding is needed] + if (padding!=0) { + // some padding needed; always pad the RHS, as any required + // padding can then be effected by a simple combination of + // shifts and a multiply + Flag swapped=0; + if (padding<0) { // LHS needs the padding + const decNumber *t; + padding=-padding; // will be +ve + bits=(uByte)(rhs->bits^negate); // assumed sign is now that of RHS + t=lhs; lhs=rhs; rhs=t; + swapped=1; + } + + // If, after pad, rhs would be longer than lhs by digits+1 or + // more then lhs cannot affect the answer, except as a residue, + // so only need to pad up to a length of DIGITS+1. + if (rhs->digits+padding > lhs->digits+reqdigits+1) { + // The RHS is sufficient + // for residue use the relative sign indication... + Int shift=reqdigits-rhs->digits; // left shift needed + residue=1; // residue for rounding + if (diffsign) residue=-residue; // signs differ + // copy, shortening if necessary + decCopyFit(res, rhs, set, &residue, status); + // if it was already shorter, then need to pad with zeros + if (shift>0) { + res->digits=decShiftToMost(res->lsu, res->digits, shift); + res->exponent-=shift; // adjust the exponent. + } + // flip the result sign if unswapped and rhs was negated + if (!swapped) res->bits^=negate; + decFinish(res, set, &residue, status); // done + break;} + + // LHS digits may affect result + rhsshift=D2U(padding+1)-1; // this much by Unit shift .. + mult=powers[padding-(rhsshift*DECDPUN)]; // .. this by multiplication + } // padding needed + + if (diffsign) mult=-mult; // signs differ + + // determine the longer operand + maxdigits=rhs->digits+padding; // virtual length of RHS + if (lhs->digits>maxdigits) maxdigits=lhs->digits; + + // Decide on the result buffer to use; if possible place directly + // into result. + acc=res->lsu; // assume add direct to result + // If destructive overlap, or the number is too long, or a carry or + // borrow to DIGITS+1 might be possible, a buffer must be used. + // [Might be worth more sophisticated tests when maxdigits==reqdigits] + if ((maxdigits>=reqdigits) // is, or could be, too large + || (res==rhs && rhsshift>0)) { // destructive overlap + // buffer needed, choose it; units for maxdigits digits will be + // needed, +1 Unit for carry or borrow + Int need=D2U(maxdigits)+1; + acc=accbuff; // assume use local buffer + if (need*sizeof(Unit)>sizeof(accbuff)) { + // printf("malloc add %ld %ld\n", need, sizeof(accbuff)); + allocacc=(Unit *)malloc(need*sizeof(Unit)); + if (allocacc==NULL) { // hopeless -- abandon + *status|=DEC_Insufficient_storage; + break;} + acc=allocacc; + } + } + + res->bits=(uByte)(bits&DECNEG); // it's now safe to overwrite.. + res->exponent=lhs->exponent; // .. operands (even if aliased) + + #if DECTRACE + decDumpAr('A', lhs->lsu, D2U(lhs->digits)); + decDumpAr('B', rhs->lsu, D2U(rhs->digits)); + printf(" :h: %ld %ld\n", rhsshift, mult); + #endif + + // add [A+B*m] or subtract [A+B*(-m)] + res->digits=decUnitAddSub(lhs->lsu, D2U(lhs->digits), + rhs->lsu, D2U(rhs->digits), + rhsshift, acc, mult) + *DECDPUN; // [units -> digits] + if (res->digits<0) { // borrowed... + res->digits=-res->digits; + res->bits^=DECNEG; // flip the sign + } + #if DECTRACE + decDumpAr('+', acc, D2U(res->digits)); + #endif + + // If a buffer was used the result must be copied back, possibly + // shortening. (If no buffer was used then the result must have + // fit, so can't need rounding and residue must be 0.) + residue=0; // clear accumulator + if (acc!=res->lsu) { + #if DECSUBSET + if (set->extended) { // round from first significant digit + #endif + // remove leading zeros that were added due to rounding up to + // integral Units -- before the test for rounding. + if (res->digits>reqdigits) + res->digits=decGetDigits(acc, D2U(res->digits)); + decSetCoeff(res, set, acc, res->digits, &residue, status); + #if DECSUBSET + } + else { // subset arithmetic rounds from original significant digit + // May have an underestimate. This only occurs when both + // numbers fit in DECDPUN digits and are padding with a + // negative multiple (-10, -100...) and the top digit(s) become + // 0. (This only matters when using X3.274 rules where the + // leading zero could be included in the rounding.) + if (res->digitsdigits))=0; // ensure leading 0 is there + res->digits=maxdigits; + } + else { + // remove leading zeros that added due to rounding up to + // integral Units (but only those in excess of the original + // maxdigits length, unless extended) before test for rounding. + if (res->digits>reqdigits) { + res->digits=decGetDigits(acc, D2U(res->digits)); + if (res->digitsdigits=maxdigits; + } + } + decSetCoeff(res, set, acc, res->digits, &residue, status); + // Now apply rounding if needed before removing leading zeros. + // This is safe because subnormals are not a possibility + if (residue!=0) { + decApplyRound(res, set, residue, status); + residue=0; // did what needed to be done + } + } // subset + #endif + } // used buffer + + // strip leading zeros [these were left on in case of subset subtract] + res->digits=decGetDigits(res->lsu, D2U(res->digits)); + + // apply checks and rounding + decFinish(res, set, &residue, status); + + // "When the sum of two operands with opposite signs is exactly + // zero, the sign of that sum shall be '+' in all rounding modes + // except round toward -Infinity, in which mode that sign shall be + // '-'." [Subset zeros also never have '-', set by decFinish.] + if (ISZERO(res) && diffsign + #if DECSUBSET + && set->extended + #endif + && (*status&DEC_Inexact)==0) { + if (set->round==DEC_ROUND_FLOOR) res->bits|=DECNEG; // sign - + else res->bits&=~DECNEG; // sign + + } + } while(0); // end protected + + if (allocacc!=NULL) free(allocacc); // drop any storage used + #if DECSUBSET + if (allocrhs!=NULL) free(allocrhs); // .. + if (alloclhs!=NULL) free(alloclhs); // .. + #endif + return res; + } // decAddOp + +/* ------------------------------------------------------------------ */ +/* decDivideOp -- division operation */ +/* */ +/* This routine performs the calculations for all four division */ +/* operators (divide, divideInteger, remainder, remainderNear). */ +/* */ +/* C=A op B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X/X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* op is DIVIDE, DIVIDEINT, REMAINDER, or REMNEAR respectively. */ +/* status is the usual accumulator */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* ------------------------------------------------------------------ */ +/* The underlying algorithm of this routine is the same as in the */ +/* 1981 S/370 implementation, that is, non-restoring long division */ +/* with bi-unit (rather than bi-digit) estimation for each unit */ +/* multiplier. In this pseudocode overview, complications for the */ +/* Remainder operators and division residues for exact rounding are */ +/* omitted for clarity. */ +/* */ +/* Prepare operands and handle special values */ +/* Test for x/0 and then 0/x */ +/* Exp =Exp1 - Exp2 */ +/* Exp =Exp +len(var1) -len(var2) */ +/* Sign=Sign1 * Sign2 */ +/* Pad accumulator (Var1) to double-length with 0's (pad1) */ +/* Pad Var2 to same length as Var1 */ +/* msu2pair/plus=1st 2 or 1 units of var2, +1 to allow for round */ +/* have=0 */ +/* Do until (have=digits+1 OR residue=0) */ +/* if exp<0 then if integer divide/residue then leave */ +/* this_unit=0 */ +/* Do forever */ +/* compare numbers */ +/* if <0 then leave inner_loop */ +/* if =0 then (* quick exit without subtract *) do */ +/* this_unit=this_unit+1; output this_unit */ +/* leave outer_loop; end */ +/* Compare lengths of numbers (mantissae): */ +/* If same then tops2=msu2pair -- {units 1&2 of var2} */ +/* else tops2=msu2plus -- {0, unit 1 of var2} */ +/* tops1=first_unit_of_Var1*10**DECDPUN +second_unit_of_var1 */ +/* mult=tops1/tops2 -- Good and safe guess at divisor */ +/* if mult=0 then mult=1 */ +/* this_unit=this_unit+mult */ +/* subtract */ +/* end inner_loop */ +/* if have\=0 | this_unit\=0 then do */ +/* output this_unit */ +/* have=have+1; end */ +/* var2=var2/10 */ +/* exp=exp-1 */ +/* end outer_loop */ +/* exp=exp+1 -- set the proper exponent */ +/* if have=0 then generate answer=0 */ +/* Return (Result is defined by Var1) */ +/* */ +/* ------------------------------------------------------------------ */ +/* Two working buffers are needed during the division; one (digits+ */ +/* 1) to accumulate the result, and the other (up to 2*digits+1) for */ +/* long subtractions. These are acc and var1 respectively. */ +/* var1 is a copy of the lhs coefficient, var2 is the rhs coefficient.*/ +/* The static buffers may be larger than might be expected to allow */ +/* for calls from higher-level funtions (notable exp). */ +/* ------------------------------------------------------------------ */ +static decNumber * decDivideOp(decNumber *res, + const decNumber *lhs, const decNumber *rhs, + decContext *set, Flag op, uInt *status) { + #if DECSUBSET + decNumber *alloclhs=NULL; // non-NULL if rounded lhs allocated + decNumber *allocrhs=NULL; // .., rhs + #endif + Unit accbuff[SD2U(DECBUFFER+DECDPUN+10)]; // local buffer + Unit *acc=accbuff; // -> accumulator array for result + Unit *allocacc=NULL; // -> allocated buffer, iff allocated + Unit *accnext; // -> where next digit will go + Int acclength; // length of acc needed [Units] + Int accunits; // count of units accumulated + Int accdigits; // count of digits accumulated + + Unit varbuff[SD2U(DECBUFFER*2+DECDPUN)]; // buffer for var1 + Unit *var1=varbuff; // -> var1 array for long subtraction + Unit *varalloc=NULL; // -> allocated buffer, iff used + Unit *msu1; // -> msu of var1 + + const Unit *var2; // -> var2 array + const Unit *msu2; // -> msu of var2 + Int msu2plus; // msu2 plus one [does not vary] + eInt msu2pair; // msu2 pair plus one [does not vary] + + Int var1units, var2units; // actual lengths + Int var2ulen; // logical length (units) + Int var1initpad=0; // var1 initial padding (digits) + Int maxdigits; // longest LHS or required acc length + Int mult; // multiplier for subtraction + Unit thisunit; // current unit being accumulated + Int residue; // for rounding + Int reqdigits=set->digits; // requested DIGITS + Int exponent; // working exponent + Int maxexponent=0; // DIVIDE maximum exponent if unrounded + uByte bits; // working sign + Unit *target; // work + const Unit *source; // .. + uInt const *pow; // .. + Int shift, cut; // .. + #if DECSUBSET + Int dropped; // work + #endif + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + do { // protect allocated storage + #if DECSUBSET + if (!set->extended) { + // reduce operands and set lostDigits status, as needed + if (lhs->digits>reqdigits) { + alloclhs=decRoundOperand(lhs, set, status); + if (alloclhs==NULL) break; + lhs=alloclhs; + } + if (rhs->digits>reqdigits) { + allocrhs=decRoundOperand(rhs, set, status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + } + #endif + // [following code does not require input rounding] + + bits=(lhs->bits^rhs->bits)&DECNEG; // assumed sign for divisions + + // handle infinities and NaNs + if (SPECIALARGS) { // a special bit set + if (SPECIALARGS & (DECSNAN | DECNAN)) { // one or two NaNs + decNaNs(res, lhs, rhs, set, status); + break; + } + // one or two infinities + if (decNumberIsInfinite(lhs)) { // LHS (dividend) is infinite + if (decNumberIsInfinite(rhs) || // two infinities are invalid .. + op & (REMAINDER | REMNEAR)) { // as is remainder of infinity + *status|=DEC_Invalid_operation; + break; + } + // [Note that infinity/0 raises no exceptions] + decNumberZero(res); + res->bits=bits|DECINF; // set +/- infinity + break; + } + else { // RHS (divisor) is infinite + residue=0; + if (op&(REMAINDER|REMNEAR)) { + // result is [finished clone of] lhs + decCopyFit(res, lhs, set, &residue, status); + } + else { // a division + decNumberZero(res); + res->bits=bits; // set +/- zero + // for DIVIDEINT the exponent is always 0. For DIVIDE, result + // is a 0 with infinitely negative exponent, clamped to minimum + if (op&DIVIDE) { + res->exponent=set->emin-set->digits+1; + *status|=DEC_Clamped; + } + } + decFinish(res, set, &residue, status); + break; + } + } + + // handle 0 rhs (x/0) + if (ISZERO(rhs)) { // x/0 is always exceptional + if (ISZERO(lhs)) { + decNumberZero(res); // [after lhs test] + *status|=DEC_Division_undefined;// 0/0 will become NaN + } + else { + decNumberZero(res); + if (op&(REMAINDER|REMNEAR)) *status|=DEC_Invalid_operation; + else { + *status|=DEC_Division_by_zero; // x/0 + res->bits=bits|DECINF; // .. is +/- Infinity + } + } + break;} + + // handle 0 lhs (0/x) + if (ISZERO(lhs)) { // 0/x [x!=0] + #if DECSUBSET + if (!set->extended) decNumberZero(res); + else { + #endif + if (op&DIVIDE) { + residue=0; + exponent=lhs->exponent-rhs->exponent; // ideal exponent + decNumberCopy(res, lhs); // [zeros always fit] + res->bits=bits; // sign as computed + res->exponent=exponent; // exponent, too + decFinalize(res, set, &residue, status); // check exponent + } + else if (op&DIVIDEINT) { + decNumberZero(res); // integer 0 + res->bits=bits; // sign as computed + } + else { // a remainder + exponent=rhs->exponent; // [save in case overwrite] + decNumberCopy(res, lhs); // [zeros always fit] + if (exponentexponent) res->exponent=exponent; // use lower + } + #if DECSUBSET + } + #endif + break;} + + // Precalculate exponent. This starts off adjusted (and hence fits + // in 31 bits) and becomes the usual unadjusted exponent as the + // division proceeds. The order of evaluation is important, here, + // to avoid wrap. + exponent=(lhs->exponent+lhs->digits)-(rhs->exponent+rhs->digits); + + // If the working exponent is -ve, then some quick exits are + // possible because the quotient is known to be <1 + // [for REMNEAR, it needs to be < -1, as -0.5 could need work] + if (exponent<0 && !(op==DIVIDE)) { + if (op&DIVIDEINT) { + decNumberZero(res); // integer part is 0 + #if DECSUBSET + if (set->extended) + #endif + res->bits=bits; // set +/- zero + break;} + // fastpath remainders so long as the lhs has the smaller + // (or equal) exponent + if (lhs->exponent<=rhs->exponent) { + if (op&REMAINDER || exponent<-1) { + // It is REMAINDER or safe REMNEAR; result is [finished + // clone of] lhs (r = x - 0*y) + residue=0; + decCopyFit(res, lhs, set, &residue, status); + decFinish(res, set, &residue, status); + break; + } + // [unsafe REMNEAR drops through] + } + } // fastpaths + + /* Long (slow) division is needed; roll up the sleeves... */ + + // The accumulator will hold the quotient of the division. + // If it needs to be too long for stack storage, then allocate. + acclength=D2U(reqdigits+DECDPUN); // in Units + if (acclength*sizeof(Unit)>sizeof(accbuff)) { + // printf("malloc dvacc %ld units\n", acclength); + allocacc=(Unit *)malloc(acclength*sizeof(Unit)); + if (allocacc==NULL) { // hopeless -- abandon + *status|=DEC_Insufficient_storage; + break;} + acc=allocacc; // use the allocated space + } + + // var1 is the padded LHS ready for subtractions. + // If it needs to be too long for stack storage, then allocate. + // The maximum units needed for var1 (long subtraction) is: + // Enough for + // (rhs->digits+reqdigits-1) -- to allow full slide to right + // or (lhs->digits) -- to allow for long lhs + // whichever is larger + // +1 -- for rounding of slide to right + // +1 -- for leading 0s + // +1 -- for pre-adjust if a remainder or DIVIDEINT + // [Note: unused units do not participate in decUnitAddSub data] + maxdigits=rhs->digits+reqdigits-1; + if (lhs->digits>maxdigits) maxdigits=lhs->digits; + var1units=D2U(maxdigits)+2; + // allocate a guard unit above msu1 for REMAINDERNEAR + if (!(op&DIVIDE)) var1units++; + if ((var1units+1)*sizeof(Unit)>sizeof(varbuff)) { + // printf("malloc dvvar %ld units\n", var1units+1); + varalloc=(Unit *)malloc((var1units+1)*sizeof(Unit)); + if (varalloc==NULL) { // hopeless -- abandon + *status|=DEC_Insufficient_storage; + break;} + var1=varalloc; // use the allocated space + } + + // Extend the lhs and rhs to full long subtraction length. The lhs + // is truly extended into the var1 buffer, with 0 padding, so a + // subtract in place is always possible. The rhs (var2) has + // virtual padding (implemented by decUnitAddSub). + // One guard unit was allocated above msu1 for rem=rem+rem in + // REMAINDERNEAR. + msu1=var1+var1units-1; // msu of var1 + source=lhs->lsu+D2U(lhs->digits)-1; // msu of input array + for (target=msu1; source>=lhs->lsu; source--, target--) *target=*source; + for (; target>=var1; target--) *target=0; + + // rhs (var2) is left-aligned with var1 at the start + var2ulen=var1units; // rhs logical length (units) + var2units=D2U(rhs->digits); // rhs actual length (units) + var2=rhs->lsu; // -> rhs array + msu2=var2+var2units-1; // -> msu of var2 [never changes] + // now set up the variables which will be used for estimating the + // multiplication factor. If these variables are not exact, add + // 1 to make sure that the multiplier is never overestimated. + msu2plus=*msu2; // it's value .. + if (var2units>1) msu2plus++; // .. +1 if any more + msu2pair=(eInt)*msu2*(DECDPUNMAX+1);// top two pair .. + if (var2units>1) { // .. [else treat 2nd as 0] + msu2pair+=*(msu2-1); // .. + if (var2units>2) msu2pair++; // .. +1 if any more + } + + // The calculation is working in units, which may have leading zeros, + // but the exponent was calculated on the assumption that they are + // both left-aligned. Adjust the exponent to compensate: add the + // number of leading zeros in var1 msu and subtract those in var2 msu. + // [This is actually done by counting the digits and negating, as + // lead1=DECDPUN-digits1, and similarly for lead2.] + for (pow=&powers[1]; *msu1>=*pow; pow++) exponent--; + for (pow=&powers[1]; *msu2>=*pow; pow++) exponent++; + + // Now, if doing an integer divide or remainder, ensure that + // the result will be Unit-aligned. To do this, shift the var1 + // accumulator towards least if need be. (It's much easier to + // do this now than to reassemble the residue afterwards, if + // doing a remainder.) Also ensure the exponent is not negative. + if (!(op&DIVIDE)) { + Unit *u; // work + // save the initial 'false' padding of var1, in digits + var1initpad=(var1units-D2U(lhs->digits))*DECDPUN; + // Determine the shift to do. + if (exponent<0) cut=-exponent; + else cut=DECDPUN-exponent%DECDPUN; + decShiftToLeast(var1, var1units, cut); + exponent+=cut; // maintain numerical value + var1initpad-=cut; // .. and reduce padding + // clean any most-significant units which were just emptied + for (u=msu1; cut>=DECDPUN; cut-=DECDPUN, u--) *u=0; + } // align + else { // is DIVIDE + maxexponent=lhs->exponent-rhs->exponent; // save + // optimization: if the first iteration will just produce 0, + // preadjust to skip it [valid for DIVIDE only] + if (*msu1<*msu2) { + var2ulen--; // shift down + exponent-=DECDPUN; // update the exponent + } + } + + // ---- start the long-division loops ------------------------------ + accunits=0; // no units accumulated yet + accdigits=0; // .. or digits + accnext=acc+acclength-1; // -> msu of acc [NB: allows digits+1] + for (;;) { // outer forever loop + thisunit=0; // current unit assumed 0 + // find the next unit + for (;;) { // inner forever loop + // strip leading zero units [from either pre-adjust or from + // subtract last time around]. Leave at least one unit. + for (; *msu1==0 && msu1>var1; msu1--) var1units--; + + if (var1units msu + for (pv1=msu1; ; pv1--, pv2--) { + // v1=*pv1 -- always OK + v2=0; // assume in padding + if (pv2>=var2) v2=*pv2; // in range + if (*pv1!=v2) break; // no longer the same + if (pv1==var1) break; // done; leave pv1 as is + } + // here when all inspected or a difference seen + if (*pv1v2. Prepare for real subtraction; the lengths are equal + // Estimate the multiplier (there's always a msu1-1)... + // Bring in two units of var2 to provide a good estimate. + mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2pair); + } // lengths the same + else { // var1units > var2ulen, so subtraction is safe + // The var2 msu is one unit towards the lsu of the var1 msu, + // so only one unit for var2 can be used. + mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2plus); + } + if (mult==0) mult=1; // must always be at least 1 + // subtraction needed; var1 is > var2 + thisunit=(Unit)(thisunit+mult); // accumulate + // subtract var1-var2, into var1; only the overlap needs + // processing, as this is an in-place calculation + shift=var2ulen-var2units; + #if DECTRACE + decDumpAr('1', &var1[shift], var1units-shift); + decDumpAr('2', var2, var2units); + printf("m=%ld\n", -mult); + #endif + decUnitAddSub(&var1[shift], var1units-shift, + var2, var2units, 0, + &var1[shift], -mult); + #if DECTRACE + decDumpAr('#', &var1[shift], var1units-shift); + #endif + // var1 now probably has leading zeros; these are removed at the + // top of the inner loop. + } // inner loop + + // The next unit has been calculated in full; unless it's a + // leading zero, add to acc + if (accunits!=0 || thisunit!=0) { // is first or non-zero + *accnext=thisunit; // store in accumulator + // account exactly for the new digits + if (accunits==0) { + accdigits++; // at least one + for (pow=&powers[1]; thisunit>=*pow; pow++) accdigits++; + } + else accdigits+=DECDPUN; + accunits++; // update count + accnext--; // ready for next + if (accdigits>reqdigits) break; // have enough digits + } + + // if the residue is zero, the operation is done (unless divide + // or divideInteger and still not enough digits yet) + if (*var1==0 && var1units==1) { // residue is 0 + if (op&(REMAINDER|REMNEAR)) break; + if ((op&DIVIDE) && (exponent<=maxexponent)) break; + // [drop through if divideInteger] + } + // also done enough if calculating remainder or integer + // divide and just did the last ('units') unit + if (exponent==0 && !(op&DIVIDE)) break; + + // to get here, var1 is less than var2, so divide var2 by the per- + // Unit power of ten and go for the next digit + var2ulen--; // shift down + exponent-=DECDPUN; // update the exponent + } // outer loop + + // ---- division is complete --------------------------------------- + // here: acc has at least reqdigits+1 of good results (or fewer + // if early stop), starting at accnext+1 (its lsu) + // var1 has any residue at the stopping point + // accunits is the number of digits collected in acc + if (accunits==0) { // acc is 0 + accunits=1; // show have a unit .. + accdigits=1; // .. + *accnext=0; // .. whose value is 0 + } + else accnext++; // back to last placed + // accnext now -> lowest unit of result + + residue=0; // assume no residue + if (op&DIVIDE) { + // record the presence of any residue, for rounding + if (*var1!=0 || var1units>1) residue=1; + else { // no residue + // Had an exact division; clean up spurious trailing 0s. + // There will be at most DECDPUN-1, from the final multiply, + // and then only if the result is non-0 (and even) and the + // exponent is 'loose'. + #if DECDPUN>1 + Unit lsu=*accnext; + if (!(lsu&0x01) && (lsu!=0)) { + // count the trailing zeros + Int drop=0; + for (;; drop++) { // [will terminate because lsu!=0] + if (exponent>=maxexponent) break; // don't chop real 0s + #if DECDPUN<=4 + if ((lsu-QUOT10(lsu, drop+1) + *powers[drop+1])!=0) break; // found non-0 digit + #else + if (lsu%powers[drop+1]!=0) break; // found non-0 digit + #endif + exponent++; + } + if (drop>0) { + accunits=decShiftToLeast(accnext, accunits, drop); + accdigits=decGetDigits(accnext, accunits); + accunits=D2U(accdigits); + // [exponent was adjusted in the loop] + } + } // neither odd nor 0 + #endif + } // exact divide + } // divide + else /* op!=DIVIDE */ { + // check for coefficient overflow + if (accdigits+exponent>reqdigits) { + *status|=DEC_Division_impossible; + break; + } + if (op & (REMAINDER|REMNEAR)) { + // [Here, the exponent will be 0, because var1 was adjusted + // appropriately.] + Int postshift; // work + Flag wasodd=0; // integer was odd + Unit *quotlsu; // for save + Int quotdigits; // .. + + bits=lhs->bits; // remainder sign is always as lhs + + // Fastpath when residue is truly 0 is worthwhile [and + // simplifies the code below] + if (*var1==0 && var1units==1) { // residue is 0 + Int exp=lhs->exponent; // save min(exponents) + if (rhs->exponentexponent; + decNumberZero(res); // 0 coefficient + #if DECSUBSET + if (set->extended) + #endif + res->exponent=exp; // .. with proper exponent + res->bits=(uByte)(bits&DECNEG); // [cleaned] + decFinish(res, set, &residue, status); // might clamp + break; + } + // note if the quotient was odd + if (*accnext & 0x01) wasodd=1; // acc is odd + quotlsu=accnext; // save in case need to reinspect + quotdigits=accdigits; // .. + + // treat the residue, in var1, as the value to return, via acc + // calculate the unused zero digits. This is the smaller of: + // var1 initial padding (saved above) + // var2 residual padding, which happens to be given by: + postshift=var1initpad+exponent-lhs->exponent+rhs->exponent; + // [the 'exponent' term accounts for the shifts during divide] + if (var1initpadexponent; // exponent is smaller of lhs & rhs + if (rhs->exponentexponent; + + // Now correct the result if doing remainderNear; if it + // (looking just at coefficients) is > rhs/2, or == rhs/2 and + // the integer was odd then the result should be rem-rhs. + if (op&REMNEAR) { + Int compare, tarunits; // work + Unit *up; // .. + // calculate remainder*2 into the var1 buffer (which has + // 'headroom' of an extra unit and hence enough space) + // [a dedicated 'double' loop would be faster, here] + tarunits=decUnitAddSub(accnext, accunits, accnext, accunits, + 0, accnext, 1); + // decDumpAr('r', accnext, tarunits); + + // Here, accnext (var1) holds tarunits Units with twice the + // remainder's coefficient, which must now be compared to the + // RHS. The remainder's exponent may be smaller than the RHS's. + compare=decUnitCompare(accnext, tarunits, rhs->lsu, D2U(rhs->digits), + rhs->exponent-exponent); + if (compare==BADINT) { // deep trouble + *status|=DEC_Insufficient_storage; + break;} + + // now restore the remainder by dividing by two; the lsu + // is known to be even. + for (up=accnext; up0 || (compare==0 && wasodd)) { // adjustment needed + Int exp, expunits, exprem; // work + // This is effectively causing round-up of the quotient, + // so if it was the rare case where it was full and all + // nines, it would overflow and hence division-impossible + // should be raised + Flag allnines=0; // 1 if quotient all nines + if (quotdigits==reqdigits) { // could be borderline + for (up=quotlsu; ; up++) { + if (quotdigits>DECDPUN) { + if (*up!=DECDPUNMAX) break;// non-nines + } + else { // this is the last Unit + if (*up==powers[quotdigits]-1) allnines=1; + break; + } + quotdigits-=DECDPUN; // checked those digits + } // up + } // borderline check + if (allnines) { + *status|=DEC_Division_impossible; + break;} + + // rem-rhs is needed; the sign will invert. Again, var1 + // can safely be used for the working Units array. + exp=rhs->exponent-exponent; // RHS padding needed + // Calculate units and remainder from exponent. + expunits=exp/DECDPUN; + exprem=exp%DECDPUN; + // subtract [A+B*(-m)]; the result will always be negative + accunits=-decUnitAddSub(accnext, accunits, + rhs->lsu, D2U(rhs->digits), + expunits, accnext, -(Int)powers[exprem]); + accdigits=decGetDigits(accnext, accunits); // count digits exactly + accunits=D2U(accdigits); // and recalculate the units for copy + // [exponent is as for original remainder] + bits^=DECNEG; // flip the sign + } + } // REMNEAR + } // REMAINDER or REMNEAR + } // not DIVIDE + + // Set exponent and bits + res->exponent=exponent; + res->bits=(uByte)(bits&DECNEG); // [cleaned] + + // Now the coefficient. + decSetCoeff(res, set, accnext, accdigits, &residue, status); + + decFinish(res, set, &residue, status); // final cleanup + + #if DECSUBSET + // If a divide then strip trailing zeros if subset [after round] + if (!set->extended && (op==DIVIDE)) decTrim(res, set, 0, 1, &dropped); + #endif + } while(0); // end protected + + if (varalloc!=NULL) free(varalloc); // drop any storage used + if (allocacc!=NULL) free(allocacc); // .. + #if DECSUBSET + if (allocrhs!=NULL) free(allocrhs); // .. + if (alloclhs!=NULL) free(alloclhs); // .. + #endif + return res; + } // decDivideOp + +/* ------------------------------------------------------------------ */ +/* decMultiplyOp -- multiplication operation */ +/* */ +/* This routine performs the multiplication C=A x B. */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X*X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* status is the usual accumulator */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* ------------------------------------------------------------------ */ +/* 'Classic' multiplication is used rather than Karatsuba, as the */ +/* latter would give only a minor improvement for the short numbers */ +/* expected to be handled most (and uses much more memory). */ +/* */ +/* There are two major paths here: the general-purpose ('old code') */ +/* path which handles all DECDPUN values, and a fastpath version */ +/* which is used if 64-bit ints are available, DECDPUN<=4, and more */ +/* than two calls to decUnitAddSub would be made. */ +/* */ +/* The fastpath version lumps units together into 8-digit or 9-digit */ +/* chunks, and also uses a lazy carry strategy to minimise expensive */ +/* 64-bit divisions. The chunks are then broken apart again into */ +/* units for continuing processing. Despite this overhead, the */ +/* fastpath can speed up some 16-digit operations by 10x (and much */ +/* more for higher-precision calculations). */ +/* */ +/* A buffer always has to be used for the accumulator; in the */ +/* fastpath, buffers are also always needed for the chunked copies of */ +/* of the operand coefficients. */ +/* Static buffers are larger than needed just for multiply, to allow */ +/* for calls from other operations (notably exp). */ +/* ------------------------------------------------------------------ */ +#define FASTMUL (DECUSE64 && DECDPUN<5) +static decNumber * decMultiplyOp(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set, + uInt *status) { + Int accunits; // Units of accumulator in use + Int exponent; // work + Int residue=0; // rounding residue + uByte bits; // result sign + Unit *acc; // -> accumulator Unit array + Int needbytes; // size calculator + void *allocacc=NULL; // -> allocated accumulator, iff allocated + Unit accbuff[SD2U(DECBUFFER*4+1)]; // buffer (+1 for DECBUFFER==0, + // *4 for calls from other operations) + const Unit *mer, *mermsup; // work + Int madlength; // Units in multiplicand + Int shift; // Units to shift multiplicand by + + #if FASTMUL + // if DECDPUN is 1 or 3 work in base 10**9, otherwise + // (DECDPUN is 2 or 4) then work in base 10**8 + #if DECDPUN & 1 // odd + #define FASTBASE 1000000000 // base + #define FASTDIGS 9 // digits in base + #define FASTLAZY 18 // carry resolution point [1->18] + #else + #define FASTBASE 100000000 + #define FASTDIGS 8 + #define FASTLAZY 1844 // carry resolution point [1->1844] + #endif + // three buffers are used, two for chunked copies of the operands + // (base 10**8 or base 10**9) and one base 2**64 accumulator with + // lazy carry evaluation + uInt zlhibuff[(DECBUFFER*2+1)/8+1]; // buffer (+1 for DECBUFFER==0) + uInt *zlhi=zlhibuff; // -> lhs array + uInt *alloclhi=NULL; // -> allocated buffer, iff allocated + uInt zrhibuff[(DECBUFFER*2+1)/8+1]; // buffer (+1 for DECBUFFER==0) + uInt *zrhi=zrhibuff; // -> rhs array + uInt *allocrhi=NULL; // -> allocated buffer, iff allocated + uLong zaccbuff[(DECBUFFER*2+1)/4+2]; // buffer (+1 for DECBUFFER==0) + // [allocacc is shared for both paths, as only one will run] + uLong *zacc=zaccbuff; // -> accumulator array for exact result + #if DECDPUN==1 + Int zoff; // accumulator offset + #endif + uInt *lip, *rip; // item pointers + uInt *lmsi, *rmsi; // most significant items + Int ilhs, irhs, iacc; // item counts in the arrays + Int lazy; // lazy carry counter + uLong lcarry; // uLong carry + uInt carry; // carry (NB not uLong) + Int count; // work + const Unit *cup; // .. + Unit *up; // .. + uLong *lp; // .. + Int p; // .. + #endif + + #if DECSUBSET + decNumber *alloclhs=NULL; // -> allocated buffer, iff allocated + decNumber *allocrhs=NULL; // -> allocated buffer, iff allocated + #endif + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + // precalculate result sign + bits=(uByte)((lhs->bits^rhs->bits)&DECNEG); + + // handle infinities and NaNs + if (SPECIALARGS) { // a special bit set + if (SPECIALARGS & (DECSNAN | DECNAN)) { // one or two NaNs + decNaNs(res, lhs, rhs, set, status); + return res;} + // one or two infinities; Infinity * 0 is invalid + if (((lhs->bits & DECINF)==0 && ISZERO(lhs)) + ||((rhs->bits & DECINF)==0 && ISZERO(rhs))) { + *status|=DEC_Invalid_operation; + return res;} + decNumberZero(res); + res->bits=bits|DECINF; // infinity + return res;} + + // For best speed, as in DMSRCN [the original Rexx numerics + // module], use the shorter number as the multiplier (rhs) and + // the longer as the multiplicand (lhs) to minimise the number of + // adds (partial products) + if (lhs->digitsdigits) { // swap... + const decNumber *hold=lhs; + lhs=rhs; + rhs=hold; + } + + do { // protect allocated storage + #if DECSUBSET + if (!set->extended) { + // reduce operands and set lostDigits status, as needed + if (lhs->digits>set->digits) { + alloclhs=decRoundOperand(lhs, set, status); + if (alloclhs==NULL) break; + lhs=alloclhs; + } + if (rhs->digits>set->digits) { + allocrhs=decRoundOperand(rhs, set, status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + } + #endif + // [following code does not require input rounding] + + #if FASTMUL // fastpath can be used + // use the fast path if there are enough digits in the shorter + // operand to make the setup and takedown worthwhile + #define NEEDTWO (DECDPUN*2) // within two decUnitAddSub calls + if (rhs->digits>NEEDTWO) { // use fastpath... + // calculate the number of elements in each array + ilhs=(lhs->digits+FASTDIGS-1)/FASTDIGS; // [ceiling] + irhs=(rhs->digits+FASTDIGS-1)/FASTDIGS; // .. + iacc=ilhs+irhs; + + // allocate buffers if required, as usual + needbytes=ilhs*sizeof(uInt); + if (needbytes>(Int)sizeof(zlhibuff)) { + alloclhi=(uInt *)malloc(needbytes); + zlhi=alloclhi;} + needbytes=irhs*sizeof(uInt); + if (needbytes>(Int)sizeof(zrhibuff)) { + allocrhi=(uInt *)malloc(needbytes); + zrhi=allocrhi;} + + // Allocating the accumulator space needs a special case when + // DECDPUN=1 because when converting the accumulator to Units + // after the multiplication each 8-byte item becomes 9 1-byte + // units. Therefore iacc extra bytes are needed at the front + // (rounded up to a multiple of 8 bytes), and the uLong + // accumulator starts offset the appropriate number of units + // to the right to avoid overwrite during the unchunking. + needbytes=iacc*sizeof(uLong); + #if DECDPUN==1 + zoff=(iacc+7)/8; // items to offset by + needbytes+=zoff*8; + #endif + if (needbytes>(Int)sizeof(zaccbuff)) { + allocacc=(uLong *)malloc(needbytes); + zacc=(uLong *)allocacc;} + if (zlhi==NULL||zrhi==NULL||zacc==NULL) { + *status|=DEC_Insufficient_storage; + break;} + + acc=(Unit *)zacc; // -> target Unit array + #if DECDPUN==1 + zacc+=zoff; // start uLong accumulator to right + #endif + + // assemble the chunked copies of the left and right sides + for (count=lhs->digits, cup=lhs->lsu, lip=zlhi; count>0; lip++) + for (p=0, *lip=0; p0; + p+=DECDPUN, cup++, count-=DECDPUN) + *lip+=*cup*powers[p]; + lmsi=lip-1; // save -> msi + for (count=rhs->digits, cup=rhs->lsu, rip=zrhi; count>0; rip++) + for (p=0, *rip=0; p0; + p+=DECDPUN, cup++, count-=DECDPUN) + *rip+=*cup*powers[p]; + rmsi=rip-1; // save -> msi + + // zero the accumulator + for (lp=zacc; lp0 && rip!=rmsi) continue; + lazy=FASTLAZY; // reset delay count + // spin up the accumulator resolving overflows + for (lp=zacc; lp assume buffer for accumulator + needbytes=(D2U(lhs->digits)+D2U(rhs->digits))*sizeof(Unit); + if (needbytes>(Int)sizeof(accbuff)) { + allocacc=(Unit *)malloc(needbytes); + if (allocacc==NULL) {*status|=DEC_Insufficient_storage; break;} + acc=(Unit *)allocacc; // use the allocated space + } + + /* Now the main long multiplication loop */ + // Unlike the equivalent in the IBM Java implementation, there + // is no advantage in calculating from msu to lsu. So, do it + // by the book, as it were. + // Each iteration calculates ACC=ACC+MULTAND*MULT + accunits=1; // accumulator starts at '0' + *acc=0; // .. (lsu=0) + shift=0; // no multiplicand shift at first + madlength=D2U(lhs->digits); // this won't change + mermsup=rhs->lsu+D2U(rhs->digits); // -> msu+1 of multiplier + + for (mer=rhs->lsu; merlsu, madlength, 0, + &acc[shift], *mer) + + shift; + else { // extend acc with a 0; it will be used shortly + *(acc+accunits)=0; // [this avoids length of <=0 later] + accunits++; + } + // multiply multiplicand by 10**DECDPUN for next Unit to left + shift++; // add this for 'logical length' + } // n + #if FASTMUL + } // unchunked units + #endif + // common end-path + #if DECTRACE + decDumpAr('*', acc, accunits); // Show exact result + #endif + + // acc now contains the exact result of the multiplication, + // possibly with a leading zero unit; build the decNumber from + // it, noting if any residue + res->bits=bits; // set sign + res->digits=decGetDigits(acc, accunits); // count digits exactly + + // There can be a 31-bit wrap in calculating the exponent. + // This can only happen if both input exponents are negative and + // both their magnitudes are large. If there was a wrap, set a + // safe very negative exponent, from which decFinalize() will + // raise a hard underflow shortly. + exponent=lhs->exponent+rhs->exponent; // calculate exponent + if (lhs->exponent<0 && rhs->exponent<0 && exponent>0) + exponent=-2*DECNUMMAXE; // force underflow + res->exponent=exponent; // OK to overwrite now + + + // Set the coefficient. If any rounding, residue records + decSetCoeff(res, set, acc, res->digits, &residue, status); + decFinish(res, set, &residue, status); // final cleanup + } while(0); // end protected + + if (allocacc!=NULL) free(allocacc); // drop any storage used + #if DECSUBSET + if (allocrhs!=NULL) free(allocrhs); // .. + if (alloclhs!=NULL) free(alloclhs); // .. + #endif + #if FASTMUL + if (allocrhi!=NULL) free(allocrhi); // .. + if (alloclhi!=NULL) free(alloclhi); // .. + #endif + return res; + } // decMultiplyOp + +/* ------------------------------------------------------------------ */ +/* decExpOp -- effect exponentiation */ +/* */ +/* This computes C = exp(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context; note that rounding mode has no effect */ +/* */ +/* C must have space for set->digits digits. status is updated but */ +/* not set. */ +/* */ +/* Restrictions: */ +/* */ +/* digits, emax, and -emin in the context must be less than */ +/* 2*DEC_MAX_MATH (1999998), and the rhs must be within these */ +/* bounds or a zero. This is an internal routine, so these */ +/* restrictions are contractual and not enforced. */ +/* */ +/* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */ +/* almost always be correctly rounded, but may be up to 1 ulp in */ +/* error in rare cases. */ +/* */ +/* Finite results will always be full precision and Inexact, except */ +/* when A is a zero or -Infinity (giving 1 or 0 respectively). */ +/* ------------------------------------------------------------------ */ +/* This approach used here is similar to the algorithm described in */ +/* */ +/* Variable Precision Exponential Function, T. E. Hull and */ +/* A. Abrham, ACM Transactions on Mathematical Software, Vol 12 #2, */ +/* pp79-91, ACM, June 1986. */ +/* */ +/* with the main difference being that the iterations in the series */ +/* evaluation are terminated dynamically (which does not require the */ +/* extra variable-precision variables which are expensive in this */ +/* context). */ +/* */ +/* The error analysis in Hull & Abrham's paper applies except for the */ +/* round-off error accumulation during the series evaluation. This */ +/* code does not precalculate the number of iterations and so cannot */ +/* use Horner's scheme. Instead, the accumulation is done at double- */ +/* precision, which ensures that the additions of the terms are exact */ +/* and do not accumulate round-off (and any round-off errors in the */ +/* terms themselves move 'to the right' faster than they can */ +/* accumulate). This code also extends the calculation by allowing, */ +/* in the spirit of other decNumber operators, the input to be more */ +/* precise than the result (the precision used is based on the more */ +/* precise of the input or requested result). */ +/* */ +/* Implementation notes: */ +/* */ +/* 1. This is separated out as decExpOp so it can be called from */ +/* other Mathematical functions (notably Ln) with a wider range */ +/* than normal. In particular, it can handle the slightly wider */ +/* (double) range needed by Ln (which has to be able to calculate */ +/* exp(-x) where x can be the tiniest number (Ntiny). */ +/* */ +/* 2. Normalizing x to be <=0.1 (instead of <=1) reduces loop */ +/* iterations by appoximately a third with additional (although */ +/* diminishing) returns as the range is reduced to even smaller */ +/* fractions. However, h (the power of 10 used to correct the */ +/* result at the end, see below) must be kept <=8 as otherwise */ +/* the final result cannot be computed. Hence the leverage is a */ +/* sliding value (8-h), where potentially the range is reduced */ +/* more for smaller values. */ +/* */ +/* The leverage that can be applied in this way is severely */ +/* limited by the cost of the raise-to-the power at the end, */ +/* which dominates when the number of iterations is small (less */ +/* than ten) or when rhs is short. As an example, the adjustment */ +/* x**10,000,000 needs 31 multiplications, all but one full-width. */ +/* */ +/* 3. The restrictions (especially precision) could be raised with */ +/* care, but the full decNumber range seems very hard within the */ +/* 32-bit limits. */ +/* */ +/* 4. The working precisions for the static buffers are twice the */ +/* obvious size to allow for calls from decNumberPower. */ +/* ------------------------------------------------------------------ */ +decNumber * decExpOp(decNumber *res, const decNumber *rhs, + decContext *set, uInt *status) { + uInt ignore=0; // working status + Int h; // adjusted exponent for 0.xxxx + Int p; // working precision + Int residue; // rounding residue + uInt needbytes; // for space calculations + const decNumber *x=rhs; // (may point to safe copy later) + decContext aset, tset, dset; // working contexts + Int comp; // work + + // the argument is often copied to normalize it, so (unusually) it + // is treated like other buffers, using DECBUFFER, +1 in case + // DECBUFFER is 0 + decNumber bufr[D2N(DECBUFFER*2+1)]; + decNumber *allocrhs=NULL; // non-NULL if rhs buffer allocated + + // the working precision will be no more than set->digits+8+1 + // so for on-stack buffers DECBUFFER+9 is used, +1 in case DECBUFFER + // is 0 (and twice that for the accumulator) + + // buffer for t, term (working precision plus) + decNumber buft[D2N(DECBUFFER*2+9+1)]; + decNumber *allocbuft=NULL; // -> allocated buft, iff allocated + decNumber *t=buft; // term + // buffer for a, accumulator (working precision * 2), at least 9 + decNumber bufa[D2N(DECBUFFER*4+18+1)]; + decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated + decNumber *a=bufa; // accumulator + // decNumber for the divisor term; this needs at most 9 digits + // and so can be fixed size [16 so can use standard context] + decNumber bufd[D2N(16)]; + decNumber *d=bufd; // divisor + decNumber numone; // constant 1 + + #if DECCHECK + Int iterations=0; // for later sanity check + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + do { // protect allocated storage + if (SPECIALARG) { // handle infinities and NaNs + if (decNumberIsInfinite(rhs)) { // an infinity + if (decNumberIsNegative(rhs)) // -Infinity -> +0 + decNumberZero(res); + else decNumberCopy(res, rhs); // +Infinity -> self + } + else decNaNs(res, rhs, NULL, set, status); // a NaN + break;} + + if (ISZERO(rhs)) { // zeros -> exact 1 + decNumberZero(res); // make clean 1 + *res->lsu=1; // .. + break;} // [no status to set] + + // e**x when 0 < x < 0.66 is < 1+3x/2, hence can fast-path + // positive and negative tiny cases which will result in inexact + // 1. This also allows the later add-accumulate to always be + // exact (because its length will never be more than twice the + // working precision). + // The comparator (tiny) needs just one digit, so use the + // decNumber d for it (reused as the divisor, etc., below); its + // exponent is such that if x is positive it will have + // set->digits-1 zeros between the decimal point and the digit, + // which is 4, and if x is negative one more zero there as the + // more precise result will be of the form 0.9999999 rather than + // 1.0000001. Hence, tiny will be 0.0000004 if digits=7 and x>0 + // or 0.00000004 if digits=7 and x<0. If RHS not larger than + // this then the result will be 1.000000 + decNumberZero(d); // clean + *d->lsu=4; // set 4 .. + d->exponent=-set->digits; // * 10**(-d) + if (decNumberIsNegative(rhs)) d->exponent--; // negative case + comp=decCompare(d, rhs, 1); // signless compare + if (comp==BADINT) { + *status|=DEC_Insufficient_storage; + break;} + if (comp>=0) { // rhs < d + Int shift=set->digits-1; + decNumberZero(res); // set 1 + *res->lsu=1; // .. + res->digits=decShiftToMost(res->lsu, 1, shift); + res->exponent=-shift; // make 1.0000... + *status|=DEC_Inexact | DEC_Rounded; // .. inexactly + break;} // tiny + + // set up the context to be used for calculating a, as this is + // used on both paths below + decContextDefault(&aset, DEC_INIT_DECIMAL64); + // accumulator bounds are as requested (could underflow) + aset.emax=set->emax; // usual bounds + aset.emin=set->emin; // .. + aset.clamp=0; // and no concrete format + + // calculate the adjusted (Hull & Abrham) exponent (where the + // decimal point is just to the left of the coefficient msd) + h=rhs->exponent+rhs->digits; + // if h>8 then 10**h cannot be calculated safely; however, when + // h=8 then exp(|rhs|) will be at least exp(1E+7) which is at + // least 6.59E+4342944, so (due to the restriction on Emax/Emin) + // overflow (or underflow to 0) is guaranteed -- so this case can + // be handled by simply forcing the appropriate excess + if (h>8) { // overflow/underflow + // set up here so Power call below will over or underflow to + // zero; set accumulator to either 2 or 0.02 + // [stack buffer for a is always big enough for this] + decNumberZero(a); + *a->lsu=2; // not 1 but < exp(1) + if (decNumberIsNegative(rhs)) a->exponent=-2; // make 0.02 + h=8; // clamp so 10**h computable + p=9; // set a working precision + } + else { // h<=8 + Int maxlever=(rhs->digits>8?1:0); + // [could/should increase this for precisions >40 or so, too] + + // if h is 8, cannot normalize to a lower upper limit because + // the final result will not be computable (see notes above), + // but leverage can be applied whenever h is less than 8. + // Apply as much as possible, up to a MAXLEVER digits, which + // sets the tradeoff against the cost of the later a**(10**h). + // As h is increased, the working precision below also + // increases to compensate for the "constant digits at the + // front" effect. + Int lever=MINI(8-h, maxlever); // leverage attainable + Int use=-rhs->digits-lever; // exponent to use for RHS + h+=lever; // apply leverage selected + if (h<0) { // clamp + use+=h; // [may end up subnormal] + h=0; + } + // Take a copy of RHS if it needs normalization (true whenever x>=1) + if (rhs->exponent!=use) { + decNumber *newrhs=bufr; // assume will fit on stack + needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit); + if (needbytes>sizeof(bufr)) { // need malloc space + allocrhs=(decNumber *)malloc(needbytes); + if (allocrhs==NULL) { // hopeless -- abandon + *status|=DEC_Insufficient_storage; + break;} + newrhs=allocrhs; // use the allocated space + } + decNumberCopy(newrhs, rhs); // copy to safe space + newrhs->exponent=use; // normalize; now <1 + x=newrhs; // ready for use + // decNumberShow(x); + } + + // Now use the usual power series to evaluate exp(x). The + // series starts as 1 + x + x^2/2 ... so prime ready for the + // third term by setting the term variable t=x, the accumulator + // a=1, and the divisor d=2. + + // First determine the working precision. From Hull & Abrham + // this is set->digits+h+2. However, if x is 'over-precise' we + // need to allow for all its digits to potentially participate + // (consider an x where all the excess digits are 9s) so in + // this case use x->digits+h+2 + p=MAXI(x->digits, set->digits)+h+2; // [h<=8] + + // a and t are variable precision, and depend on p, so space + // must be allocated for them if necessary + + // the accumulator needs to be able to hold 2p digits so that + // the additions on the second and subsequent iterations are + // sufficiently exact. + needbytes=sizeof(decNumber)+(D2U(p*2)-1)*sizeof(Unit); + if (needbytes>sizeof(bufa)) { // need malloc space + allocbufa=(decNumber *)malloc(needbytes); + if (allocbufa==NULL) { // hopeless -- abandon + *status|=DEC_Insufficient_storage; + break;} + a=allocbufa; // use the allocated space + } + // the term needs to be able to hold p digits (which is + // guaranteed to be larger than x->digits, so the initial copy + // is safe); it may also be used for the raise-to-power + // calculation below, which needs an extra two digits + needbytes=sizeof(decNumber)+(D2U(p+2)-1)*sizeof(Unit); + if (needbytes>sizeof(buft)) { // need malloc space + allocbuft=(decNumber *)malloc(needbytes); + if (allocbuft==NULL) { // hopeless -- abandon + *status|=DEC_Insufficient_storage; + break;} + t=allocbuft; // use the allocated space + } + + decNumberCopy(t, x); // term=x + decNumberZero(a); *a->lsu=1; // accumulator=1 + decNumberZero(d); *d->lsu=2; // divisor=2 + decNumberZero(&numone); *numone.lsu=1; // constant 1 for increment + + // set up the contexts for calculating a, t, and d + decContextDefault(&tset, DEC_INIT_DECIMAL64); + dset=tset; + // accumulator bounds are set above, set precision now + aset.digits=p*2; // double + // term bounds avoid any underflow or overflow + tset.digits=p; + tset.emin=DEC_MIN_EMIN; // [emax is plenty] + // [dset.digits=16, etc., are sufficient] + + // finally ready to roll + for (;;) { + #if DECCHECK + iterations++; + #endif + // only the status from the accumulation is interesting + // [but it should remain unchanged after first add] + decAddOp(a, a, t, &aset, 0, status); // a=a+t + decMultiplyOp(t, t, x, &tset, &ignore); // t=t*x + decDivideOp(t, t, d, &tset, DIVIDE, &ignore); // t=t/d + // the iteration ends when the term cannot affect the result, + // if rounded to p digits, which is when its value is smaller + // than the accumulator by p+1 digits. There must also be + // full precision in a. + if (((a->digits+a->exponent)>=(t->digits+t->exponent+p+1)) + && (a->digits>=p)) break; + decAddOp(d, d, &numone, &dset, 0, &ignore); // d=d+1 + } // iterate + + #if DECCHECK + // just a sanity check; comment out test to show always + if (iterations>p+3) + printf("Exp iterations=%ld, status=%08lx, p=%ld, d=%ld\n", + (LI)iterations, (LI)*status, (LI)p, (LI)x->digits); + #endif + } // h<=8 + + // apply postconditioning: a=a**(10**h) -- this is calculated + // at a slightly higher precision than Hull & Abrham suggest + if (h>0) { + Int seenbit=0; // set once a 1-bit is seen + Int i; // counter + Int n=powers[h]; // always positive + aset.digits=p+2; // sufficient precision + // avoid the overhead and many extra digits of decNumberPower + // as all that is needed is the short 'multipliers' loop; here + // accumulate the answer into t + decNumberZero(t); *t->lsu=1; // acc=1 + for (i=1;;i++){ // for each bit [top bit ignored] + // abandon if have had overflow or terminal underflow + if (*status & (DEC_Overflow|DEC_Underflow)) { // interesting? + if (*status&DEC_Overflow || ISZERO(t)) break;} + n=n<<1; // move next bit to testable position + if (n<0) { // top bit is set + seenbit=1; // OK, have a significant bit + decMultiplyOp(t, t, a, &aset, status); // acc=acc*x + } + if (i==31) break; // that was the last bit + if (!seenbit) continue; // no need to square 1 + decMultiplyOp(t, t, t, &aset, status); // acc=acc*acc [square] + } /*i*/ // 32 bits + // decNumberShow(t); + a=t; // and carry on using t instead of a + } + + // Copy and round the result to res + residue=1; // indicate dirt to right .. + if (ISZERO(a)) residue=0; // .. unless underflowed to 0 + aset.digits=set->digits; // [use default rounding] + decCopyFit(res, a, &aset, &residue, status); // copy & shorten + decFinish(res, set, &residue, status); // cleanup/set flags + } while(0); // end protected + + if (allocrhs !=NULL) free(allocrhs); // drop any storage used + if (allocbufa!=NULL) free(allocbufa); // .. + if (allocbuft!=NULL) free(allocbuft); // .. + // [status is handled by caller] + return res; + } // decExpOp + +/* ------------------------------------------------------------------ */ +/* Initial-estimate natural logarithm table */ +/* */ +/* LNnn -- 90-entry 16-bit table for values from .10 through .99. */ +/* The result is a 4-digit encode of the coefficient (c=the */ +/* top 14 bits encoding 0-9999) and a 2-digit encode of the */ +/* exponent (e=the bottom 2 bits encoding 0-3) */ +/* */ +/* The resulting value is given by: */ +/* */ +/* v = -c * 10**(-e-3) */ +/* */ +/* where e and c are extracted from entry k = LNnn[x-10] */ +/* where x is truncated (NB) into the range 10 through 99, */ +/* and then c = k>>2 and e = k&3. */ +/* ------------------------------------------------------------------ */ +const uShort LNnn[90]={9016, 8652, 8316, 8008, 7724, 7456, 7208, + 6972, 6748, 6540, 6340, 6148, 5968, 5792, 5628, 5464, 5312, + 5164, 5020, 4884, 4748, 4620, 4496, 4376, 4256, 4144, 4032, + 39233, 38181, 37157, 36157, 35181, 34229, 33297, 32389, 31501, 30629, + 29777, 28945, 28129, 27329, 26545, 25777, 25021, 24281, 23553, 22837, + 22137, 21445, 20769, 20101, 19445, 18801, 18165, 17541, 16925, 16321, + 15721, 15133, 14553, 13985, 13421, 12865, 12317, 11777, 11241, 10717, + 10197, 9685, 9177, 8677, 8185, 7697, 7213, 6737, 6269, 5801, + 5341, 4889, 4437, 39930, 35534, 31186, 26886, 22630, 18418, 14254, + 10130, 6046, 20055}; + +/* ------------------------------------------------------------------ */ +/* decLnOp -- effect natural logarithm */ +/* */ +/* This computes C = ln(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context; note that rounding mode has no effect */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Notable cases: */ +/* A<0 -> Invalid */ +/* A=0 -> -Infinity (Exact) */ +/* A=+Infinity -> +Infinity (Exact) */ +/* A=1 exactly -> 0 (Exact) */ +/* */ +/* Restrictions (as for Exp): */ +/* */ +/* digits, emax, and -emin in the context must be less than */ +/* DEC_MAX_MATH+11 (1000010), and the rhs must be within these */ +/* bounds or a zero. This is an internal routine, so these */ +/* restrictions are contractual and not enforced. */ +/* */ +/* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */ +/* almost always be correctly rounded, but may be up to 1 ulp in */ +/* error in rare cases. */ +/* ------------------------------------------------------------------ */ +/* The result is calculated using Newton's method, with each */ +/* iteration calculating a' = a + x * exp(-a) - 1. See, for example, */ +/* Epperson 1989. */ +/* */ +/* The iteration ends when the adjustment x*exp(-a)-1 is tiny enough. */ +/* This has to be calculated at the sum of the precision of x and the */ +/* working precision. */ +/* */ +/* Implementation notes: */ +/* */ +/* 1. This is separated out as decLnOp so it can be called from */ +/* other Mathematical functions (e.g., Log 10) with a wider range */ +/* than normal. In particular, it can handle the slightly wider */ +/* (+9+2) range needed by a power function. */ +/* */ +/* 2. The speed of this function is about 10x slower than exp, as */ +/* it typically needs 4-6 iterations for short numbers, and the */ +/* extra precision needed adds a squaring effect, twice. */ +/* */ +/* 3. Fastpaths are included for ln(10) and ln(2), up to length 40, */ +/* as these are common requests. ln(10) is used by log10(x). */ +/* */ +/* 4. An iteration might be saved by widening the LNnn table, and */ +/* would certainly save at least one if it were made ten times */ +/* bigger, too (for truncated fractions 0.100 through 0.999). */ +/* However, for most practical evaluations, at least four or five */ +/* iterations will be neede -- so this would only speed up by */ +/* 20-25% and that probably does not justify increasing the table */ +/* size. */ +/* */ +/* 5. The static buffers are larger than might be expected to allow */ +/* for calls from decNumberPower. */ +/* ------------------------------------------------------------------ */ +decNumber * decLnOp(decNumber *res, const decNumber *rhs, + decContext *set, uInt *status) { + uInt ignore=0; // working status accumulator + uInt needbytes; // for space calculations + Int residue; // rounding residue + Int r; // rhs=f*10**r [see below] + Int p; // working precision + Int pp; // precision for iteration + Int t; // work + + // buffers for a (accumulator, typically precision+2) and b + // (adjustment calculator, same size) + decNumber bufa[D2N(DECBUFFER+12)]; + decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated + decNumber *a=bufa; // accumulator/work + decNumber bufb[D2N(DECBUFFER*2+2)]; + decNumber *allocbufb=NULL; // -> allocated bufa, iff allocated + decNumber *b=bufb; // adjustment/work + + decNumber numone; // constant 1 + decNumber cmp; // work + decContext aset, bset; // working contexts + + #if DECCHECK + Int iterations=0; // for later sanity check + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + do { // protect allocated storage + if (SPECIALARG) { // handle infinities and NaNs + if (decNumberIsInfinite(rhs)) { // an infinity + if (decNumberIsNegative(rhs)) // -Infinity -> error + *status|=DEC_Invalid_operation; + else decNumberCopy(res, rhs); // +Infinity -> self + } + else decNaNs(res, rhs, NULL, set, status); // a NaN + break;} + + if (ISZERO(rhs)) { // +/- zeros -> -Infinity + decNumberZero(res); // make clean + res->bits=DECINF|DECNEG; // set - infinity + break;} // [no status to set] + + // Non-zero negatives are bad... + if (decNumberIsNegative(rhs)) { // -x -> error + *status|=DEC_Invalid_operation; + break;} + + // Here, rhs is positive, finite, and in range + + // lookaside fastpath code for ln(2) and ln(10) at common lengths + if (rhs->exponent==0 && set->digits<=40) { + #if DECDPUN==1 + if (rhs->lsu[0]==0 && rhs->lsu[1]==1 && rhs->digits==2) { // ln(10) + #else + if (rhs->lsu[0]==10 && rhs->digits==2) { // ln(10) + #endif + aset=*set; aset.round=DEC_ROUND_HALF_EVEN; + #define LN10 "2.302585092994045684017991454684364207601" + decNumberFromString(res, LN10, &aset); + *status|=(DEC_Inexact | DEC_Rounded); // is inexact + break;} + if (rhs->lsu[0]==2 && rhs->digits==1) { // ln(2) + aset=*set; aset.round=DEC_ROUND_HALF_EVEN; + #define LN2 "0.6931471805599453094172321214581765680755" + decNumberFromString(res, LN2, &aset); + *status|=(DEC_Inexact | DEC_Rounded); + break;} + } // integer and short + + // Determine the working precision. This is normally the + // requested precision + 2, with a minimum of 9. However, if + // the rhs is 'over-precise' then allow for all its digits to + // potentially participate (consider an rhs where all the excess + // digits are 9s) so in this case use rhs->digits+2. + p=MAXI(rhs->digits, MAXI(set->digits, 7))+2; + + // Allocate space for the accumulator and the high-precision + // adjustment calculator, if necessary. The accumulator must + // be able to hold p digits, and the adjustment up to + // rhs->digits+p digits. They are also made big enough for 16 + // digits so that they can be used for calculating the initial + // estimate. + needbytes=sizeof(decNumber)+(D2U(MAXI(p,16))-1)*sizeof(Unit); + if (needbytes>sizeof(bufa)) { // need malloc space + allocbufa=(decNumber *)malloc(needbytes); + if (allocbufa==NULL) { // hopeless -- abandon + *status|=DEC_Insufficient_storage; + break;} + a=allocbufa; // use the allocated space + } + pp=p+rhs->digits; + needbytes=sizeof(decNumber)+(D2U(MAXI(pp,16))-1)*sizeof(Unit); + if (needbytes>sizeof(bufb)) { // need malloc space + allocbufb=(decNumber *)malloc(needbytes); + if (allocbufb==NULL) { // hopeless -- abandon + *status|=DEC_Insufficient_storage; + break;} + b=allocbufb; // use the allocated space + } + + // Prepare an initial estimate in acc. Calculate this by + // considering the coefficient of x to be a normalized fraction, + // f, with the decimal point at far left and multiplied by + // 10**r. Then, rhs=f*10**r and 0.1<=f<1, and + // ln(x) = ln(f) + ln(10)*r + // Get the initial estimate for ln(f) from a small lookup + // table (see above) indexed by the first two digits of f, + // truncated. + + decContextDefault(&aset, DEC_INIT_DECIMAL64); // 16-digit extended + r=rhs->exponent+rhs->digits; // 'normalised' exponent + decNumberFromInt32(a, r); // a=r + decNumberFromInt32(b, 2302585); // b=ln(10) (2.302585) + b->exponent=-6; // .. + decMultiplyOp(a, a, b, &aset, &ignore); // a=a*b + // now get top two digits of rhs into b by simple truncate and + // force to integer + residue=0; // (no residue) + aset.digits=2; aset.round=DEC_ROUND_DOWN; + decCopyFit(b, rhs, &aset, &residue, &ignore); // copy & shorten + b->exponent=0; // make integer + t=decGetInt(b); // [cannot fail] + if (t<10) t=X10(t); // adjust single-digit b + t=LNnn[t-10]; // look up ln(b) + decNumberFromInt32(b, t>>2); // b=ln(b) coefficient + b->exponent=-(t&3)-3; // set exponent + b->bits=DECNEG; // ln(0.10)->ln(0.99) always -ve + aset.digits=16; aset.round=DEC_ROUND_HALF_EVEN; // restore + decAddOp(a, a, b, &aset, 0, &ignore); // acc=a+b + // the initial estimate is now in a, with up to 4 digits correct. + // When rhs is at or near Nmax the estimate will be low, so we + // will approach it from below, avoiding overflow when calling exp. + + decNumberZero(&numone); *numone.lsu=1; // constant 1 for adjustment + + // accumulator bounds are as requested (could underflow, but + // cannot overflow) + aset.emax=set->emax; + aset.emin=set->emin; + aset.clamp=0; // no concrete format + // set up a context to be used for the multiply and subtract + bset=aset; + bset.emax=DEC_MAX_MATH*2; // use double bounds for the + bset.emin=-DEC_MAX_MATH*2; // adjustment calculation + // [see decExpOp call below] + // for each iteration double the number of digits to calculate, + // up to a maximum of p + pp=9; // initial precision + // [initially 9 as then the sequence starts 7+2, 16+2, and + // 34+2, which is ideal for standard-sized numbers] + aset.digits=pp; // working context + bset.digits=pp+rhs->digits; // wider context + for (;;) { // iterate + #if DECCHECK + iterations++; + if (iterations>24) break; // consider 9 * 2**24 + #endif + // calculate the adjustment (exp(-a)*x-1) into b. This is a + // catastrophic subtraction but it really is the difference + // from 1 that is of interest. + // Use the internal entry point to Exp as it allows the double + // range for calculating exp(-a) when a is the tiniest subnormal. + a->bits^=DECNEG; // make -a + decExpOp(b, a, &bset, &ignore); // b=exp(-a) + a->bits^=DECNEG; // restore sign of a + // now multiply by rhs and subtract 1, at the wider precision + decMultiplyOp(b, b, rhs, &bset, &ignore); // b=b*rhs + decAddOp(b, b, &numone, &bset, DECNEG, &ignore); // b=b-1 + + // the iteration ends when the adjustment cannot affect the + // result by >=0.5 ulp (at the requested digits), which + // is when its value is smaller than the accumulator by + // set->digits+1 digits (or it is zero) -- this is a looser + // requirement than for Exp because all that happens to the + // accumulator after this is the final rounding (but note that + // there must also be full precision in a, or a=0). + + if (decNumberIsZero(b) || + (a->digits+a->exponent)>=(b->digits+b->exponent+set->digits+1)) { + if (a->digits==p) break; + if (decNumberIsZero(a)) { + decCompareOp(&cmp, rhs, &numone, &aset, COMPARE, &ignore); // rhs=1 ? + if (cmp.lsu[0]==0) a->exponent=0; // yes, exact 0 + else *status|=(DEC_Inexact | DEC_Rounded); // no, inexact + break; + } + // force padding if adjustment has gone to 0 before full length + if (decNumberIsZero(b)) b->exponent=a->exponent-p; + } + + // not done yet ... + decAddOp(a, a, b, &aset, 0, &ignore); // a=a+b for next estimate + if (pp==p) continue; // precision is at maximum + // lengthen the next calculation + pp=pp*2; // double precision + if (pp>p) pp=p; // clamp to maximum + aset.digits=pp; // working context + bset.digits=pp+rhs->digits; // wider context + } // Newton's iteration + + #if DECCHECK + // just a sanity check; remove the test to show always + if (iterations>24) + printf("Ln iterations=%ld, status=%08lx, p=%ld, d=%ld\n", + (LI)iterations, (LI)*status, (LI)p, (LI)rhs->digits); + #endif + + // Copy and round the result to res + residue=1; // indicate dirt to right + if (ISZERO(a)) residue=0; // .. unless underflowed to 0 + aset.digits=set->digits; // [use default rounding] + decCopyFit(res, a, &aset, &residue, status); // copy & shorten + decFinish(res, set, &residue, status); // cleanup/set flags + } while(0); // end protected + + if (allocbufa!=NULL) free(allocbufa); // drop any storage used + if (allocbufb!=NULL) free(allocbufb); // .. + // [status is handled by caller] + return res; + } // decLnOp + +/* ------------------------------------------------------------------ */ +/* decQuantizeOp -- force exponent to requested value */ +/* */ +/* This computes C = op(A, B), where op adjusts the coefficient */ +/* of C (by rounding or shifting) such that the exponent (-scale) */ +/* of C has the value B or matches the exponent of B. */ +/* The numerical value of C will equal A, except for the effects of */ +/* any rounding that occurred. */ +/* */ +/* res is C, the result. C may be A or B */ +/* lhs is A, the number to adjust */ +/* rhs is B, the requested exponent */ +/* set is the context */ +/* quant is 1 for quantize or 0 for rescale */ +/* status is the status accumulator (this can be called without */ +/* risk of control loss) */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Unless there is an error or the result is infinite, the exponent */ +/* after the operation is guaranteed to be that requested. */ +/* ------------------------------------------------------------------ */ +static decNumber * decQuantizeOp(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set, + Flag quant, uInt *status) { + #if DECSUBSET + decNumber *alloclhs=NULL; // non-NULL if rounded lhs allocated + decNumber *allocrhs=NULL; // .., rhs + #endif + const decNumber *inrhs=rhs; // save original rhs + Int reqdigits=set->digits; // requested DIGITS + Int reqexp; // requested exponent [-scale] + Int residue=0; // rounding residue + Int etiny=set->emin-(reqdigits-1); + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + do { // protect allocated storage + #if DECSUBSET + if (!set->extended) { + // reduce operands and set lostDigits status, as needed + if (lhs->digits>reqdigits) { + alloclhs=decRoundOperand(lhs, set, status); + if (alloclhs==NULL) break; + lhs=alloclhs; + } + if (rhs->digits>reqdigits) { // [this only checks lostDigits] + allocrhs=decRoundOperand(rhs, set, status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + } + #endif + // [following code does not require input rounding] + + // Handle special values + if (SPECIALARGS) { + // NaNs get usual processing + if (SPECIALARGS & (DECSNAN | DECNAN)) + decNaNs(res, lhs, rhs, set, status); + // one infinity but not both is bad + else if ((lhs->bits ^ rhs->bits) & DECINF) + *status|=DEC_Invalid_operation; + // both infinity: return lhs + else decNumberCopy(res, lhs); // [nop if in place] + break; + } + + // set requested exponent + if (quant) reqexp=inrhs->exponent; // quantize -- match exponents + else { // rescale -- use value of rhs + // Original rhs must be an integer that fits and is in range, + // which could be from -1999999997 to +999999999, thanks to + // subnormals + reqexp=decGetInt(inrhs); // [cannot fail] + } + + #if DECSUBSET + if (!set->extended) etiny=set->emin; // no subnormals + #endif + + if (reqexp==BADINT // bad (rescale only) or .. + || reqexp==BIGODD || reqexp==BIGEVEN // very big (ditto) or .. + || (reqexpset->emax)) { // > emax + *status|=DEC_Invalid_operation; + break;} + + // the RHS has been processed, so it can be overwritten now if necessary + if (ISZERO(lhs)) { // zero coefficient unchanged + decNumberCopy(res, lhs); // [nop if in place] + res->exponent=reqexp; // .. just set exponent + #if DECSUBSET + if (!set->extended) res->bits=0; // subset specification; no -0 + #endif + } + else { // non-zero lhs + Int adjust=reqexp-lhs->exponent; // digit adjustment needed + // if adjusted coefficient will definitely not fit, give up now + if ((lhs->digits-adjust)>reqdigits) { + *status|=DEC_Invalid_operation; + break; + } + + if (adjust>0) { // increasing exponent + // this will decrease the length of the coefficient by adjust + // digits, and must round as it does so + decContext workset; // work + workset=*set; // clone rounding, etc. + workset.digits=lhs->digits-adjust; // set requested length + // [note that the latter can be <1, here] + decCopyFit(res, lhs, &workset, &residue, status); // fit to result + decApplyRound(res, &workset, residue, status); // .. and round + residue=0; // [used] + // If just rounded a 999s case, exponent will be off by one; + // adjust back (after checking space), if so. + if (res->exponent>reqexp) { + // re-check needed, e.g., for quantize(0.9999, 0.001) under + // set->digits==3 + if (res->digits==reqdigits) { // cannot shift by 1 + *status&=~(DEC_Inexact | DEC_Rounded); // [clean these] + *status|=DEC_Invalid_operation; + break; + } + res->digits=decShiftToMost(res->lsu, res->digits, 1); // shift + res->exponent--; // (re)adjust the exponent. + } + #if DECSUBSET + if (ISZERO(res) && !set->extended) res->bits=0; // subset; no -0 + #endif + } // increase + else /* adjust<=0 */ { // decreasing or = exponent + // this will increase the length of the coefficient by -adjust + // digits, by adding zero or more trailing zeros; this is + // already checked for fit, above + decNumberCopy(res, lhs); // [it will fit] + // if padding needed (adjust<0), add it now... + if (adjust<0) { + res->digits=decShiftToMost(res->lsu, res->digits, -adjust); + res->exponent+=adjust; // adjust the exponent + } + } // decrease + } // non-zero + + // Check for overflow [do not use Finalize in this case, as an + // overflow here is a "don't fit" situation] + if (res->exponent>set->emax-res->digits+1) { // too big + *status|=DEC_Invalid_operation; + break; + } + else { + decFinalize(res, set, &residue, status); // set subnormal flags + *status&=~DEC_Underflow; // suppress Underflow [as per 754] + } + } while(0); // end protected + + #if DECSUBSET + if (allocrhs!=NULL) free(allocrhs); // drop any storage used + if (alloclhs!=NULL) free(alloclhs); // .. + #endif + return res; + } // decQuantizeOp + +/* ------------------------------------------------------------------ */ +/* decCompareOp -- compare, min, or max two Numbers */ +/* */ +/* This computes C = A ? B and carries out one of four operations: */ +/* COMPARE -- returns the signum (as a number) giving the */ +/* result of a comparison unless one or both */ +/* operands is a NaN (in which case a NaN results) */ +/* COMPSIG -- as COMPARE except that a quiet NaN raises */ +/* Invalid operation. */ +/* COMPMAX -- returns the larger of the operands, using the */ +/* 754 maxnum operation */ +/* COMPMAXMAG -- ditto, comparing absolute values */ +/* COMPMIN -- the 754 minnum operation */ +/* COMPMINMAG -- ditto, comparing absolute values */ +/* COMTOTAL -- returns the signum (as a number) giving the */ +/* result of a comparison using 754 total ordering */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* op is the operation flag */ +/* status is the usual accumulator */ +/* */ +/* C must have space for one digit for COMPARE or set->digits for */ +/* COMPMAX, COMPMIN, COMPMAXMAG, or COMPMINMAG. */ +/* ------------------------------------------------------------------ */ +/* The emphasis here is on speed for common cases, and avoiding */ +/* coefficient comparison if possible. */ +/* ------------------------------------------------------------------ */ +decNumber * decCompareOp(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set, + Flag op, uInt *status) { + #if DECSUBSET + decNumber *alloclhs=NULL; // non-NULL if rounded lhs allocated + decNumber *allocrhs=NULL; // .., rhs + #endif + Int result=0; // default result value + uByte merged; // work + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + do { // protect allocated storage + #if DECSUBSET + if (!set->extended) { + // reduce operands and set lostDigits status, as needed + if (lhs->digits>set->digits) { + alloclhs=decRoundOperand(lhs, set, status); + if (alloclhs==NULL) {result=BADINT; break;} + lhs=alloclhs; + } + if (rhs->digits>set->digits) { + allocrhs=decRoundOperand(rhs, set, status); + if (allocrhs==NULL) {result=BADINT; break;} + rhs=allocrhs; + } + } + #endif + // [following code does not require input rounding] + + // If total ordering then handle differing signs 'up front' + if (op==COMPTOTAL) { // total ordering + if (decNumberIsNegative(lhs) & !decNumberIsNegative(rhs)) { + result=-1; + break; + } + if (!decNumberIsNegative(lhs) & decNumberIsNegative(rhs)) { + result=+1; + break; + } + } + + // handle NaNs specially; let infinities drop through + // This assumes sNaN (even just one) leads to NaN. + merged=(lhs->bits | rhs->bits) & (DECSNAN | DECNAN); + if (merged) { // a NaN bit set + if (op==COMPARE); // result will be NaN + else if (op==COMPSIG) // treat qNaN as sNaN + *status|=DEC_Invalid_operation | DEC_sNaN; + else if (op==COMPTOTAL) { // total ordering, always finite + // signs are known to be the same; compute the ordering here + // as if the signs are both positive, then invert for negatives + if (!decNumberIsNaN(lhs)) result=-1; + else if (!decNumberIsNaN(rhs)) result=+1; + // here if both NaNs + else if (decNumberIsSNaN(lhs) && decNumberIsQNaN(rhs)) result=-1; + else if (decNumberIsQNaN(lhs) && decNumberIsSNaN(rhs)) result=+1; + else { // both NaN or both sNaN + // now it just depends on the payload + result=decUnitCompare(lhs->lsu, D2U(lhs->digits), + rhs->lsu, D2U(rhs->digits), 0); + // [Error not possible, as these are 'aligned'] + } // both same NaNs + if (decNumberIsNegative(lhs)) result=-result; + break; + } // total order + + else if (merged & DECSNAN); // sNaN -> qNaN + else { // here if MIN or MAX and one or two quiet NaNs + // min or max -- 754 rules ignore single NaN + if (!decNumberIsNaN(lhs) || !decNumberIsNaN(rhs)) { + // just one NaN; force choice to be the non-NaN operand + op=COMPMAX; + if (lhs->bits & DECNAN) result=-1; // pick rhs + else result=+1; // pick lhs + break; + } + } // max or min + op=COMPNAN; // use special path + decNaNs(res, lhs, rhs, set, status); // propagate NaN + break; + } + // have numbers + if (op==COMPMAXMAG || op==COMPMINMAG) result=decCompare(lhs, rhs, 1); + else result=decCompare(lhs, rhs, 0); // sign matters + } while(0); // end protected + + if (result==BADINT) *status|=DEC_Insufficient_storage; // rare + else { + if (op==COMPARE || op==COMPSIG ||op==COMPTOTAL) { // returning signum + if (op==COMPTOTAL && result==0) { + // operands are numerically equal or same NaN (and same sign, + // tested first); if identical, leave result 0 + if (lhs->exponent!=rhs->exponent) { + if (lhs->exponentexponent) result=-1; + else result=+1; + if (decNumberIsNegative(lhs)) result=-result; + } // lexp!=rexp + } // total-order by exponent + decNumberZero(res); // [always a valid result] + if (result!=0) { // must be -1 or +1 + *res->lsu=1; + if (result<0) res->bits=DECNEG; + } + } + else if (op==COMPNAN); // special, drop through + else { // MAX or MIN, non-NaN result + Int residue=0; // rounding accumulator + // choose the operand for the result + const decNumber *choice; + if (result==0) { // operands are numerically equal + // choose according to sign then exponent (see 754) + uByte slhs=(lhs->bits & DECNEG); + uByte srhs=(rhs->bits & DECNEG); + #if DECSUBSET + if (!set->extended) { // subset: force left-hand + op=COMPMAX; + result=+1; + } + else + #endif + if (slhs!=srhs) { // signs differ + if (slhs) result=-1; // rhs is max + else result=+1; // lhs is max + } + else if (slhs && srhs) { // both negative + if (lhs->exponentexponent) result=+1; + else result=-1; + // [if equal, use lhs, technically identical] + } + else { // both positive + if (lhs->exponent>rhs->exponent) result=+1; + else result=-1; + // [ditto] + } + } // numerically equal + // here result will be non-0; reverse if looking for MIN + if (op==COMPMIN || op==COMPMINMAG) result=-result; + choice=(result>0 ? lhs : rhs); // choose + // copy chosen to result, rounding if need be + decCopyFit(res, choice, set, &residue, status); + decFinish(res, set, &residue, status); + } + } + #if DECSUBSET + if (allocrhs!=NULL) free(allocrhs); // free any storage used + if (alloclhs!=NULL) free(alloclhs); // .. + #endif + return res; + } // decCompareOp + +/* ------------------------------------------------------------------ */ +/* decCompare -- compare two decNumbers by numerical value */ +/* */ +/* This routine compares A ? B without altering them. */ +/* */ +/* Arg1 is A, a decNumber which is not a NaN */ +/* Arg2 is B, a decNumber which is not a NaN */ +/* Arg3 is 1 for a sign-independent compare, 0 otherwise */ +/* */ +/* returns -1, 0, or 1 for AB, or BADINT if failure */ +/* (the only possible failure is an allocation error) */ +/* ------------------------------------------------------------------ */ +static Int decCompare(const decNumber *lhs, const decNumber *rhs, + Flag abs) { + Int result; // result value + Int sigr; // rhs signum + Int compare; // work + + result=1; // assume signum(lhs) + if (ISZERO(lhs)) result=0; + if (abs) { + if (ISZERO(rhs)) return result; // LHS wins or both 0 + // RHS is non-zero + if (result==0) return -1; // LHS is 0; RHS wins + // [here, both non-zero, result=1] + } + else { // signs matter + if (result && decNumberIsNegative(lhs)) result=-1; + sigr=1; // compute signum(rhs) + if (ISZERO(rhs)) sigr=0; + else if (decNumberIsNegative(rhs)) sigr=-1; + if (result > sigr) return +1; // L > R, return 1 + if (result < sigr) return -1; // L < R, return -1 + if (result==0) return 0; // both 0 + } + + // signums are the same; both are non-zero + if ((lhs->bits | rhs->bits) & DECINF) { // one or more infinities + if (decNumberIsInfinite(rhs)) { + if (decNumberIsInfinite(lhs)) result=0;// both infinite + else result=-result; // only rhs infinite + } + return result; + } + // must compare the coefficients, allowing for exponents + if (lhs->exponent>rhs->exponent) { // LHS exponent larger + // swap sides, and sign + const decNumber *temp=lhs; + lhs=rhs; + rhs=temp; + result=-result; + } + compare=decUnitCompare(lhs->lsu, D2U(lhs->digits), + rhs->lsu, D2U(rhs->digits), + rhs->exponent-lhs->exponent); + if (compare!=BADINT) compare*=result; // comparison succeeded + return compare; + } // decCompare + +/* ------------------------------------------------------------------ */ +/* decUnitCompare -- compare two >=0 integers in Unit arrays */ +/* */ +/* This routine compares A ? B*10**E where A and B are unit arrays */ +/* A is a plain integer */ +/* B has an exponent of E (which must be non-negative) */ +/* */ +/* Arg1 is A first Unit (lsu) */ +/* Arg2 is A length in Units */ +/* Arg3 is B first Unit (lsu) */ +/* Arg4 is B length in Units */ +/* Arg5 is E (0 if the units are aligned) */ +/* */ +/* returns -1, 0, or 1 for AB, or BADINT if failure */ +/* (the only possible failure is an allocation error, which can */ +/* only occur if E!=0) */ +/* ------------------------------------------------------------------ */ +static Int decUnitCompare(const Unit *a, Int alength, + const Unit *b, Int blength, Int exp) { + Unit *acc; // accumulator for result + Unit accbuff[SD2U(DECBUFFER*2+1)]; // local buffer + Unit *allocacc=NULL; // -> allocated acc buffer, iff allocated + Int accunits, need; // units in use or needed for acc + const Unit *l, *r, *u; // work + Int expunits, exprem, result; // .. + + if (exp==0) { // aligned; fastpath + if (alength>blength) return 1; + if (alength=a; l--, r--) { + if (*l>*r) return 1; + if (*l<*r) return -1; + } + return 0; // all units match + } // aligned + + // Unaligned. If one is >1 unit longer than the other, padded + // approximately, then can return easily + if (alength>blength+(Int)D2U(exp)) return 1; + if (alength+1sizeof(accbuff)) { + allocacc=(Unit *)malloc(need*sizeof(Unit)); + if (allocacc==NULL) return BADINT; // hopeless -- abandon + acc=allocacc; + } + // Calculate units and remainder from exponent. + expunits=exp/DECDPUN; + exprem=exp%DECDPUN; + // subtract [A+B*(-m)] + accunits=decUnitAddSub(a, alength, b, blength, expunits, acc, + -(Int)powers[exprem]); + // [UnitAddSub result may have leading zeros, even on zero] + if (accunits<0) result=-1; // negative result + else { // non-negative result + // check units of the result before freeing any storage + for (u=acc; u=0 integers in Unit arrays */ +/* */ +/* This routine performs the calculation: */ +/* */ +/* C=A+(B*M) */ +/* */ +/* Where M is in the range -DECDPUNMAX through +DECDPUNMAX. */ +/* */ +/* A may be shorter or longer than B. */ +/* */ +/* Leading zeros are not removed after a calculation. The result is */ +/* either the same length as the longer of A and B (adding any */ +/* shift), or one Unit longer than that (if a Unit carry occurred). */ +/* */ +/* A and B content are not altered unless C is also A or B. */ +/* C may be the same array as A or B, but only if no zero padding is */ +/* requested (that is, C may be B only if bshift==0). */ +/* C is filled from the lsu; only those units necessary to complete */ +/* the calculation are referenced. */ +/* */ +/* Arg1 is A first Unit (lsu) */ +/* Arg2 is A length in Units */ +/* Arg3 is B first Unit (lsu) */ +/* Arg4 is B length in Units */ +/* Arg5 is B shift in Units (>=0; pads with 0 units if positive) */ +/* Arg6 is C first Unit (lsu) */ +/* Arg7 is M, the multiplier */ +/* */ +/* returns the count of Units written to C, which will be non-zero */ +/* and negated if the result is negative. That is, the sign of the */ +/* returned Int is the sign of the result (positive for zero) and */ +/* the absolute value of the Int is the count of Units. */ +/* */ +/* It is the caller's responsibility to make sure that C size is */ +/* safe, allowing space if necessary for a one-Unit carry. */ +/* */ +/* This routine is severely performance-critical; *any* change here */ +/* must be measured (timed) to assure no performance degradation. */ +/* In particular, trickery here tends to be counter-productive, as */ +/* increased complexity of code hurts register optimizations on */ +/* register-poor architectures. Avoiding divisions is nearly */ +/* always a Good Idea, however. */ +/* */ +/* Special thanks to Rick McGuire (IBM Cambridge, MA) and Dave Clark */ +/* (IBM Warwick, UK) for some of the ideas used in this routine. */ +/* ------------------------------------------------------------------ */ +static Int decUnitAddSub(const Unit *a, Int alength, + const Unit *b, Int blength, Int bshift, + Unit *c, Int m) { + const Unit *alsu=a; // A lsu [need to remember it] + Unit *clsu=c; // C ditto + Unit *minC; // low water mark for C + Unit *maxC; // high water mark for C + eInt carry=0; // carry integer (could be Long) + Int add; // work + #if DECDPUN<=4 // myriadal, millenary, etc. + Int est; // estimated quotient + #endif + + #if DECTRACE + if (alength<1 || blength<1) + printf("decUnitAddSub: alen blen m %ld %ld [%ld]\n", alength, blength, m); + #endif + + maxC=c+alength; // A is usually the longer + minC=c+blength; // .. and B the shorter + if (bshift!=0) { // B is shifted; low As copy across + minC+=bshift; + // if in place [common], skip copy unless there's a gap [rare] + if (a==c && bshift<=alength) { + c+=bshift; + a+=bshift; + } + else for (; cmaxC) { // swap + Unit *hold=minC; + minC=maxC; + maxC=hold; + } + + // For speed, do the addition as two loops; the first where both A + // and B contribute, and the second (if necessary) where only one or + // other of the numbers contribute. + // Carry handling is the same (i.e., duplicated) in each case. + for (; c=0) { + est=(((ueInt)carry>>11)*53687)>>18; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder + carry=est; // likely quotient [89%] + if (*c>11)*53687)>>18; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); + carry=est-(DECDPUNMAX+1); // correctly negative + if (*c=0) { + est=(((ueInt)carry>>3)*16777)>>21; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder + carry=est; // likely quotient [99%] + if (*c>3)*16777)>>21; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); + carry=est-(DECDPUNMAX+1); // correctly negative + if (*c=0) { + est=QUOT10(carry, DECDPUN); + *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder + carry=est; // quotient + continue; + } + // negative case + carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive + est=QUOT10(carry, DECDPUN); + *c=(Unit)(carry-est*(DECDPUNMAX+1)); + carry=est-(DECDPUNMAX+1); // correctly negative + #else + // remainder operator is undefined if negative, so must test + if ((ueInt)carry<(DECDPUNMAX+1)*2) { // fastpath carry +1 + *c=(Unit)(carry-(DECDPUNMAX+1)); // [helps additions] + carry=1; + continue; + } + if (carry>=0) { + *c=(Unit)(carry%(DECDPUNMAX+1)); + carry=carry/(DECDPUNMAX+1); + continue; + } + // negative case + carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive + *c=(Unit)(carry%(DECDPUNMAX+1)); + carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1); + #endif + } // c + + // now may have one or other to complete + // [pretest to avoid loop setup/shutdown] + if (cDECDPUNMAX + #if DECDPUN==4 // use divide-by-multiply + if (carry>=0) { + est=(((ueInt)carry>>11)*53687)>>18; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder + carry=est; // likely quotient [79.7%] + if (*c>11)*53687)>>18; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); + carry=est-(DECDPUNMAX+1); // correctly negative + if (*c=0) { + est=(((ueInt)carry>>3)*16777)>>21; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder + carry=est; // likely quotient [99%] + if (*c>3)*16777)>>21; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); + carry=est-(DECDPUNMAX+1); // correctly negative + if (*c=0) { + est=QUOT10(carry, DECDPUN); + *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder + carry=est; // quotient + continue; + } + // negative case + carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive + est=QUOT10(carry, DECDPUN); + *c=(Unit)(carry-est*(DECDPUNMAX+1)); + carry=est-(DECDPUNMAX+1); // correctly negative + #else + if ((ueInt)carry<(DECDPUNMAX+1)*2){ // fastpath carry 1 + *c=(Unit)(carry-(DECDPUNMAX+1)); + carry=1; + continue; + } + // remainder operator is undefined if negative, so must test + if (carry>=0) { + *c=(Unit)(carry%(DECDPUNMAX+1)); + carry=carry/(DECDPUNMAX+1); + continue; + } + // negative case + carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive + *c=(Unit)(carry%(DECDPUNMAX+1)); + carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1); + #endif + } // c + + // OK, all A and B processed; might still have carry or borrow + // return number of Units in the result, negated if a borrow + if (carry==0) return c-clsu; // no carry, so no more to do + if (carry>0) { // positive carry + *c=(Unit)carry; // place as new unit + c++; // .. + return c-clsu; + } + // -ve carry: it's a borrow; complement needed + add=1; // temporary carry... + for (c=clsu; c current Unit + + #if DECCHECK + if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn; + #endif + + *dropped=0; // assume no zeros dropped + if ((dn->bits & DECSPECIAL) // fast exit if special .. + || (*dn->lsu & 0x01)) return dn; // .. or odd + if (ISZERO(dn)) { // .. or 0 + dn->exponent=0; // (sign is preserved) + return dn; + } + + // have a finite number which is even + exp=dn->exponent; + cut=1; // digit (1-DECDPUN) in Unit + up=dn->lsu; // -> current Unit + for (d=0; ddigits-1; d++) { // [don't strip the final digit] + // slice by powers + #if DECDPUN<=4 + uInt quot=QUOT10(*up, cut); + if ((*up-quot*powers[cut])!=0) break; // found non-0 digit + #else + if (*up%powers[cut]!=0) break; // found non-0 digit + #endif + // have a trailing 0 + if (!all) { // trimming + // [if exp>0 then all trailing 0s are significant for trim] + if (exp<=0) { // if digit might be significant + if (exp==0) break; // then quit + exp++; // next digit might be significant + } + } + cut++; // next power + if (cut>DECDPUN) { // need new Unit + up++; + cut=1; + } + } // d + if (d==0) return dn; // none to drop + + // may need to limit drop if clamping + if (set->clamp && !noclamp) { + Int maxd=set->emax-set->digits+1-dn->exponent; + if (maxd<=0) return dn; // nothing possible + if (d>maxd) d=maxd; + } + + // effect the drop + decShiftToLeast(dn->lsu, D2U(dn->digits), d); + dn->exponent+=d; // maintain numerical value + dn->digits-=d; // new length + *dropped=d; // report the count + return dn; + } // decTrim + +/* ------------------------------------------------------------------ */ +/* decReverse -- reverse a Unit array in place */ +/* */ +/* ulo is the start of the array */ +/* uhi is the end of the array (highest Unit to include) */ +/* */ +/* The units ulo through uhi are reversed in place (if the number */ +/* of units is odd, the middle one is untouched). Note that the */ +/* digit(s) in each unit are unaffected. */ +/* ------------------------------------------------------------------ */ +static void decReverse(Unit *ulo, Unit *uhi) { + Unit temp; + for (; ulo=uar; source--, target--) *target=*source; + } + else { + first=uar+D2U(digits+shift)-1; // where msu of source will end up + for (; source>=uar; source--, target--) { + // split the source Unit and accumulate remainder for next + #if DECDPUN<=4 + uInt quot=QUOT10(*source, cut); + uInt rem=*source-quot*powers[cut]; + next+=quot; + #else + uInt rem=*source%powers[cut]; + next+=*source/powers[cut]; + #endif + if (target<=first) *target=(Unit)next; // write to target iff valid + next=rem*powers[DECDPUN-cut]; // save remainder for next Unit + } + } // shift-move + + // propagate any partial unit to one below and clear the rest + for (; target>=uar; target--) { + *target=(Unit)next; + next=0; + } + return digits+shift; + } // decShiftToMost + +/* ------------------------------------------------------------------ */ +/* decShiftToLeast -- shift digits in array towards least significant */ +/* */ +/* uar is the array */ +/* units is length of the array, in units */ +/* shift is the number of digits to remove from the lsu end; it */ +/* must be zero or positive and <= than units*DECDPUN. */ +/* */ +/* returns the new length of the integer in the array, in units */ +/* */ +/* Removed digits are discarded (lost). Units not required to hold */ +/* the final result are unchanged. */ +/* ------------------------------------------------------------------ */ +static Int decShiftToLeast(Unit *uar, Int units, Int shift) { + Unit *target, *up; // work + Int cut, count; // work + Int quot, rem; // for division + + if (shift==0) return units; // [fastpath] nothing to do + if (shift==units*DECDPUN) { // [fastpath] little to do + *uar=0; // all digits cleared gives zero + return 1; // leaves just the one + } + + target=uar; // both paths + cut=MSUDIGITS(shift); + if (cut==DECDPUN) { // unit-boundary case; easy + up=uar+D2U(shift); + for (; updigits is > set->digits) */ +/* set is the relevant context */ +/* status is the status accumulator */ +/* */ +/* returns an allocated decNumber with the rounded result. */ +/* */ +/* lostDigits and other status may be set by this. */ +/* */ +/* Since the input is an operand, it must not be modified. */ +/* Instead, return an allocated decNumber, rounded as required. */ +/* It is the caller's responsibility to free the allocated storage. */ +/* */ +/* If no storage is available then the result cannot be used, so NULL */ +/* is returned. */ +/* ------------------------------------------------------------------ */ +static decNumber *decRoundOperand(const decNumber *dn, decContext *set, + uInt *status) { + decNumber *res; // result structure + uInt newstatus=0; // status from round + Int residue=0; // rounding accumulator + + // Allocate storage for the returned decNumber, big enough for the + // length specified by the context + res=(decNumber *)malloc(sizeof(decNumber) + +(D2U(set->digits)-1)*sizeof(Unit)); + if (res==NULL) { + *status|=DEC_Insufficient_storage; + return NULL; + } + decCopyFit(res, dn, set, &residue, &newstatus); + decApplyRound(res, set, residue, &newstatus); + + // If that set Inexact then "lost digits" is raised... + if (newstatus & DEC_Inexact) newstatus|=DEC_Lost_digits; + *status|=newstatus; + return res; + } // decRoundOperand +#endif + +/* ------------------------------------------------------------------ */ +/* decCopyFit -- copy a number, truncating the coefficient if needed */ +/* */ +/* dest is the target decNumber */ +/* src is the source decNumber */ +/* set is the context [used for length (digits) and rounding mode] */ +/* residue is the residue accumulator */ +/* status contains the current status to be updated */ +/* */ +/* (dest==src is allowed and will be a no-op if fits) */ +/* All fields are updated as required. */ +/* ------------------------------------------------------------------ */ +static void decCopyFit(decNumber *dest, const decNumber *src, + decContext *set, Int *residue, uInt *status) { + dest->bits=src->bits; + dest->exponent=src->exponent; + decSetCoeff(dest, set, src->lsu, src->digits, residue, status); + } // decCopyFit + +/* ------------------------------------------------------------------ */ +/* decSetCoeff -- set the coefficient of a number */ +/* */ +/* dn is the number whose coefficient array is to be set. */ +/* It must have space for set->digits digits */ +/* set is the context [for size] */ +/* lsu -> lsu of the source coefficient [may be dn->lsu] */ +/* len is digits in the source coefficient [may be dn->digits] */ +/* residue is the residue accumulator. This has values as in */ +/* decApplyRound, and will be unchanged unless the */ +/* target size is less than len. In this case, the */ +/* coefficient is truncated and the residue is updated to */ +/* reflect the previous residue and the dropped digits. */ +/* status is the status accumulator, as usual */ +/* */ +/* The coefficient may already be in the number, or it can be an */ +/* external intermediate array. If it is in the number, lsu must == */ +/* dn->lsu and len must == dn->digits. */ +/* */ +/* Note that the coefficient length (len) may be < set->digits, and */ +/* in this case this merely copies the coefficient (or is a no-op */ +/* if dn->lsu==lsu). */ +/* */ +/* Note also that (only internally, from decQuantizeOp and */ +/* decSetSubnormal) the value of set->digits may be less than one, */ +/* indicating a round to left. This routine handles that case */ +/* correctly; caller ensures space. */ +/* */ +/* dn->digits, dn->lsu (and as required), and dn->exponent are */ +/* updated as necessary. dn->bits (sign) is unchanged. */ +/* */ +/* DEC_Rounded status is set if any digits are discarded. */ +/* DEC_Inexact status is set if any non-zero digits are discarded, or */ +/* incoming residue was non-0 (implies rounded) */ +/* ------------------------------------------------------------------ */ +// mapping array: maps 0-9 to canonical residues, so that a residue +// can be adjusted in the range [-1, +1] and achieve correct rounding +// 0 1 2 3 4 5 6 7 8 9 +static const uByte resmap[10]={0, 3, 3, 3, 3, 5, 7, 7, 7, 7}; +static void decSetCoeff(decNumber *dn, decContext *set, const Unit *lsu, + Int len, Int *residue, uInt *status) { + Int discard; // number of digits to discard + uInt cut; // cut point in Unit + const Unit *up; // work + Unit *target; // .. + Int count; // .. + #if DECDPUN<=4 + uInt temp; // .. + #endif + + discard=len-set->digits; // digits to discard + if (discard<=0) { // no digits are being discarded + if (dn->lsu!=lsu) { // copy needed + // copy the coefficient array to the result number; no shift needed + count=len; // avoids D2U + up=lsu; + for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN) + *target=*up; + dn->digits=len; // set the new length + } + // dn->exponent and residue are unchanged, record any inexactitude + if (*residue!=0) *status|=(DEC_Inexact | DEC_Rounded); + return; + } + + // some digits must be discarded ... + dn->exponent+=discard; // maintain numerical value + *status|=DEC_Rounded; // accumulate Rounded status + if (*residue>1) *residue=1; // previous residue now to right, so reduce + + if (discard>len) { // everything, +1, is being discarded + // guard digit is 0 + // residue is all the number [NB could be all 0s] + if (*residue<=0) { // not already positive + count=len; // avoids D2U + for (up=lsu; count>0; up++, count-=DECDPUN) if (*up!=0) { // found non-0 + *residue=1; + break; // no need to check any others + } + } + if (*residue!=0) *status|=DEC_Inexact; // record inexactitude + *dn->lsu=0; // coefficient will now be 0 + dn->digits=1; // .. + return; + } // total discard + + // partial discard [most common case] + // here, at least the first (most significant) discarded digit exists + + // spin up the number, noting residue during the spin, until get to + // the Unit with the first discarded digit. When reach it, extract + // it and remember its position + count=0; + for (up=lsu;; up++) { + count+=DECDPUN; + if (count>=discard) break; // full ones all checked + if (*up!=0) *residue=1; + } // up + + // here up -> Unit with first discarded digit + cut=discard-(count-DECDPUN)-1; + if (cut==DECDPUN-1) { // unit-boundary case (fast) + Unit half=(Unit)powers[DECDPUN]>>1; + // set residue directly + if (*up>=half) { + if (*up>half) *residue=7; + else *residue+=5; // add sticky bit + } + else { // digits<=0) { // special for Quantize/Subnormal :-( + *dn->lsu=0; // .. result is 0 + dn->digits=1; // .. + } + else { // shift to least + count=set->digits; // now digits to end up with + dn->digits=count; // set the new length + up++; // move to next + // on unit boundary, so shift-down copy loop is simple + for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN) + *target=*up; + } + } // unit-boundary case + + else { // discard digit is in low digit(s), and not top digit + uInt discard1; // first discarded digit + uInt quot, rem; // for divisions + if (cut==0) quot=*up; // is at bottom of unit + else /* cut>0 */ { // it's not at bottom of unit + #if DECDPUN<=4 + quot=QUOT10(*up, cut); + rem=*up-quot*powers[cut]; + #else + rem=*up%powers[cut]; + quot=*up/powers[cut]; + #endif + if (rem!=0) *residue=1; + } + // discard digit is now at bottom of quot + #if DECDPUN<=4 + temp=(quot*6554)>>16; // fast /10 + // Vowels algorithm here not a win (9 instructions) + discard1=quot-X10(temp); + quot=temp; + #else + discard1=quot%10; + quot=quot/10; + #endif + // here, discard1 is the guard digit, and residue is everything + // else [use mapping array to accumulate residue safely] + *residue+=resmap[discard1]; + cut++; // update cut + // here: up -> Unit of the array with bottom digit + // cut is the division point for each Unit + // quot holds the uncut high-order digits for the current unit + if (set->digits<=0) { // special for Quantize/Subnormal :-( + *dn->lsu=0; // .. result is 0 + dn->digits=1; // .. + } + else { // shift to least needed + count=set->digits; // now digits to end up with + dn->digits=count; // set the new length + // shift-copy the coefficient array to the result number + for (target=dn->lsu; ; target++) { + *target=(Unit)quot; + count-=(DECDPUN-cut); + if (count<=0) break; + up++; + quot=*up; + #if DECDPUN<=4 + quot=QUOT10(quot, cut); + rem=*up-quot*powers[cut]; + #else + rem=quot%powers[cut]; + quot=quot/powers[cut]; + #endif + *target=(Unit)(*target+rem*powers[DECDPUN-cut]); + count-=cut; + if (count<=0) break; + } // shift-copy loop + } // shift to least + } // not unit boundary + + if (*residue!=0) *status|=DEC_Inexact; // record inexactitude + return; + } // decSetCoeff + +/* ------------------------------------------------------------------ */ +/* decApplyRound -- apply pending rounding to a number */ +/* */ +/* dn is the number, with space for set->digits digits */ +/* set is the context [for size and rounding mode] */ +/* residue indicates pending rounding, being any accumulated */ +/* guard and sticky information. It may be: */ +/* 6-9: rounding digit is >5 */ +/* 5: rounding digit is exactly half-way */ +/* 1-4: rounding digit is <5 and >0 */ +/* 0: the coefficient is exact */ +/* -1: as 1, but the hidden digits are subtractive, that */ +/* is, of the opposite sign to dn. In this case the */ +/* coefficient must be non-0. This case occurs when */ +/* subtracting a small number (which can be reduced to */ +/* a sticky bit); see decAddOp. */ +/* status is the status accumulator, as usual */ +/* */ +/* This routine applies rounding while keeping the length of the */ +/* coefficient constant. The exponent and status are unchanged */ +/* except if: */ +/* */ +/* -- the coefficient was increased and is all nines (in which */ +/* case Overflow could occur, and is handled directly here so */ +/* the caller does not need to re-test for overflow) */ +/* */ +/* -- the coefficient was decreased and becomes all nines (in which */ +/* case Underflow could occur, and is also handled directly). */ +/* */ +/* All fields in dn are updated as required. */ +/* */ +/* ------------------------------------------------------------------ */ +static void decApplyRound(decNumber *dn, decContext *set, Int residue, + uInt *status) { + Int bump; // 1 if coefficient needs to be incremented + // -1 if coefficient needs to be decremented + + if (residue==0) return; // nothing to apply + + bump=0; // assume a smooth ride + + // now decide whether, and how, to round, depending on mode + switch (set->round) { + case DEC_ROUND_05UP: { // round zero or five up (for reround) + // This is the same as DEC_ROUND_DOWN unless there is a + // positive residue and the lsd of dn is 0 or 5, in which case + // it is bumped; when residue is <0, the number is therefore + // bumped down unless the final digit was 1 or 6 (in which + // case it is bumped down and then up -- a no-op) + Int lsd5=*dn->lsu%5; // get lsd and quintate + if (residue<0 && lsd5!=1) bump=-1; + else if (residue>0 && lsd5==0) bump=1; + // [bump==1 could be applied directly; use common path for clarity] + break;} // r-05 + + case DEC_ROUND_DOWN: { + // no change, except if negative residue + if (residue<0) bump=-1; + break;} // r-d + + case DEC_ROUND_HALF_DOWN: { + if (residue>5) bump=1; + break;} // r-h-d + + case DEC_ROUND_HALF_EVEN: { + if (residue>5) bump=1; // >0.5 goes up + else if (residue==5) { // exactly 0.5000... + // 0.5 goes up iff [new] lsd is odd + if (*dn->lsu & 0x01) bump=1; + } + break;} // r-h-e + + case DEC_ROUND_HALF_UP: { + if (residue>=5) bump=1; + break;} // r-h-u + + case DEC_ROUND_UP: { + if (residue>0) bump=1; + break;} // r-u + + case DEC_ROUND_CEILING: { + // same as _UP for positive numbers, and as _DOWN for negatives + // [negative residue cannot occur on 0] + if (decNumberIsNegative(dn)) { + if (residue<0) bump=-1; + } + else { + if (residue>0) bump=1; + } + break;} // r-c + + case DEC_ROUND_FLOOR: { + // same as _UP for negative numbers, and as _DOWN for positive + // [negative residue cannot occur on 0] + if (!decNumberIsNegative(dn)) { + if (residue<0) bump=-1; + } + else { + if (residue>0) bump=1; + } + break;} // r-f + + default: { // e.g., DEC_ROUND_MAX + *status|=DEC_Invalid_context; + #if DECTRACE || (DECCHECK && DECVERB) + printf("Unknown rounding mode: %d\n", set->round); + #endif + break;} + } // switch + + // now bump the number, up or down, if need be + if (bump==0) return; // no action required + + // Simply use decUnitAddSub unless bumping up and the number is + // all nines. In this special case set to 100... explicitly + // and adjust the exponent by one (as otherwise could overflow + // the array) + // Similarly handle all-nines result if bumping down. + if (bump>0) { + Unit *up; // work + uInt count=dn->digits; // digits to be checked + for (up=dn->lsu; ; up++) { + if (count<=DECDPUN) { + // this is the last Unit (the msu) + if (*up!=powers[count]-1) break; // not still 9s + // here if it, too, is all nines + *up=(Unit)powers[count-1]; // here 999 -> 100 etc. + for (up=up-1; up>=dn->lsu; up--) *up=0; // others all to 0 + dn->exponent++; // and bump exponent + // [which, very rarely, could cause Overflow...] + if ((dn->exponent+dn->digits)>set->emax+1) { + decSetOverflow(dn, set, status); + } + return; // done + } + // a full unit to check, with more to come + if (*up!=DECDPUNMAX) break; // not still 9s + count-=DECDPUN; + } // up + } // bump>0 + else { // -1 + // here checking for a pre-bump of 1000... (leading 1, all + // other digits zero) + Unit *up, *sup; // work + uInt count=dn->digits; // digits to be checked + for (up=dn->lsu; ; up++) { + if (count<=DECDPUN) { + // this is the last Unit (the msu) + if (*up!=powers[count-1]) break; // not 100.. + // here if have the 1000... case + sup=up; // save msu pointer + *up=(Unit)powers[count]-1; // here 100 in msu -> 999 + // others all to all-nines, too + for (up=up-1; up>=dn->lsu; up--) *up=(Unit)powers[DECDPUN]-1; + dn->exponent--; // and bump exponent + + // iff the number was at the subnormal boundary (exponent=etiny) + // then the exponent is now out of range, so it will in fact get + // clamped to etiny and the final 9 dropped. + // printf(">> emin=%d exp=%d sdig=%d\n", set->emin, + // dn->exponent, set->digits); + if (dn->exponent+1==set->emin-set->digits+1) { + if (count==1 && dn->digits==1) *sup=0; // here 9 -> 0[.9] + else { + *sup=(Unit)powers[count-1]-1; // here 999.. in msu -> 99.. + dn->digits--; + } + dn->exponent++; + *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded; + } + return; // done + } + + // a full unit to check, with more to come + if (*up!=0) break; // not still 0s + count-=DECDPUN; + } // up + + } // bump<0 + + // Actual bump needed. Do it. + decUnitAddSub(dn->lsu, D2U(dn->digits), uarrone, 1, 0, dn->lsu, bump); + } // decApplyRound + +#if DECSUBSET +/* ------------------------------------------------------------------ */ +/* decFinish -- finish processing a number */ +/* */ +/* dn is the number */ +/* set is the context */ +/* residue is the rounding accumulator (as in decApplyRound) */ +/* status is the accumulator */ +/* */ +/* This finishes off the current number by: */ +/* 1. If not extended: */ +/* a. Converting a zero result to clean '0' */ +/* b. Reducing positive exponents to 0, if would fit in digits */ +/* 2. Checking for overflow and subnormals (always) */ +/* Note this is just Finalize when no subset arithmetic. */ +/* All fields are updated as required. */ +/* ------------------------------------------------------------------ */ +static void decFinish(decNumber *dn, decContext *set, Int *residue, + uInt *status) { + if (!set->extended) { + if ISZERO(dn) { // value is zero + dn->exponent=0; // clean exponent .. + dn->bits=0; // .. and sign + return; // no error possible + } + if (dn->exponent>=0) { // non-negative exponent + // >0; reduce to integer if possible + if (set->digits >= (dn->exponent+dn->digits)) { + dn->digits=decShiftToMost(dn->lsu, dn->digits, dn->exponent); + dn->exponent=0; + } + } + } // !extended + + decFinalize(dn, set, residue, status); + } // decFinish +#endif + +/* ------------------------------------------------------------------ */ +/* decFinalize -- final check, clamp, and round of a number */ +/* */ +/* dn is the number */ +/* set is the context */ +/* residue is the rounding accumulator (as in decApplyRound) */ +/* status is the status accumulator */ +/* */ +/* This finishes off the current number by checking for subnormal */ +/* results, applying any pending rounding, checking for overflow, */ +/* and applying any clamping. */ +/* Underflow and overflow conditions are raised as appropriate. */ +/* All fields are updated as required. */ +/* ------------------------------------------------------------------ */ +static void decFinalize(decNumber *dn, decContext *set, Int *residue, + uInt *status) { + Int shift; // shift needed if clamping + Int tinyexp=set->emin-dn->digits+1; // precalculate subnormal boundary + + // Must be careful, here, when checking the exponent as the + // adjusted exponent could overflow 31 bits [because it may already + // be up to twice the expected]. + + // First test for subnormal. This must be done before any final + // round as the result could be rounded to Nmin or 0. + if (dn->exponent<=tinyexp) { // prefilter + Int comp; + decNumber nmin; + // A very nasty case here is dn == Nmin and residue<0 + if (dn->exponentemin; + comp=decCompare(dn, &nmin, 1); // (signless compare) + if (comp==BADINT) { // oops + *status|=DEC_Insufficient_storage; // abandon... + return; + } + if (*residue<0 && comp==0) { // neg residue and dn==Nmin + decApplyRound(dn, set, *residue, status); // might force down + decSetSubnormal(dn, set, residue, status); + return; + } + } + + // now apply any pending round (this could raise overflow). + if (*residue!=0) decApplyRound(dn, set, *residue, status); + + // Check for overflow [redundant in the 'rare' case] or clamp + if (dn->exponent<=set->emax-set->digits+1) return; // neither needed + + + // here when might have an overflow or clamp to do + if (dn->exponent>set->emax-dn->digits+1) { // too big + decSetOverflow(dn, set, status); + return; + } + // here when the result is normal but in clamp range + if (!set->clamp) return; + + // here when need to apply the IEEE exponent clamp (fold-down) + shift=dn->exponent-(set->emax-set->digits+1); + + // shift coefficient (if non-zero) + if (!ISZERO(dn)) { + dn->digits=decShiftToMost(dn->lsu, dn->digits, shift); + } + dn->exponent-=shift; // adjust the exponent to match + *status|=DEC_Clamped; // and record the dirty deed + return; + } // decFinalize + +/* ------------------------------------------------------------------ */ +/* decSetOverflow -- set number to proper overflow value */ +/* */ +/* dn is the number (used for sign [only] and result) */ +/* set is the context [used for the rounding mode, etc.] */ +/* status contains the current status to be updated */ +/* */ +/* This sets the sign of a number and sets its value to either */ +/* Infinity or the maximum finite value, depending on the sign of */ +/* dn and the rounding mode, following IEEE 754 rules. */ +/* ------------------------------------------------------------------ */ +static void decSetOverflow(decNumber *dn, decContext *set, uInt *status) { + Flag needmax=0; // result is maximum finite value + uByte sign=dn->bits&DECNEG; // clean and save sign bit + + if (ISZERO(dn)) { // zero does not overflow magnitude + Int emax=set->emax; // limit value + if (set->clamp) emax-=set->digits-1; // lower if clamping + if (dn->exponent>emax) { // clamp required + dn->exponent=emax; + *status|=DEC_Clamped; + } + return; + } + + decNumberZero(dn); + switch (set->round) { + case DEC_ROUND_DOWN: { + needmax=1; // never Infinity + break;} // r-d + case DEC_ROUND_05UP: { + needmax=1; // never Infinity + break;} // r-05 + case DEC_ROUND_CEILING: { + if (sign) needmax=1; // Infinity if non-negative + break;} // r-c + case DEC_ROUND_FLOOR: { + if (!sign) needmax=1; // Infinity if negative + break;} // r-f + default: break; // Infinity in all other cases + } + if (needmax) { + decSetMaxValue(dn, set); + dn->bits=sign; // set sign + } + else dn->bits=sign|DECINF; // Value is +/-Infinity + *status|=DEC_Overflow | DEC_Inexact | DEC_Rounded; + } // decSetOverflow + +/* ------------------------------------------------------------------ */ +/* decSetMaxValue -- set number to +Nmax (maximum normal value) */ +/* */ +/* dn is the number to set */ +/* set is the context [used for digits and emax] */ +/* */ +/* This sets the number to the maximum positive value. */ +/* ------------------------------------------------------------------ */ +static void decSetMaxValue(decNumber *dn, decContext *set) { + Unit *up; // work + Int count=set->digits; // nines to add + dn->digits=count; + // fill in all nines to set maximum value + for (up=dn->lsu; ; up++) { + if (count>DECDPUN) *up=DECDPUNMAX; // unit full o'nines + else { // this is the msu + *up=(Unit)(powers[count]-1); + break; + } + count-=DECDPUN; // filled those digits + } // up + dn->bits=0; // + sign + dn->exponent=set->emax-set->digits+1; + } // decSetMaxValue + +/* ------------------------------------------------------------------ */ +/* decSetSubnormal -- process value whose exponent is extended) { + decNumberZero(dn); + // always full overflow + *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded; + return; + } + #endif + + // Full arithmetic -- allow subnormals, rounded to minimum exponent + // (Etiny) if needed + etiny=set->emin-(set->digits-1); // smallest allowed exponent + + if ISZERO(dn) { // value is zero + // residue can never be non-zero here + #if DECCHECK + if (*residue!=0) { + printf("++ Subnormal 0 residue %ld\n", (LI)*residue); + *status|=DEC_Invalid_operation; + } + #endif + if (dn->exponentexponent=etiny; + *status|=DEC_Clamped; + } + return; + } + + *status|=DEC_Subnormal; // have a non-zero subnormal + adjust=etiny-dn->exponent; // calculate digits to remove + if (adjust<=0) { // not out of range; unrounded + // residue can never be non-zero here, except in the Nmin-residue + // case (which is a subnormal result), so can take fast-path here + // it may already be inexact (from setting the coefficient) + if (*status&DEC_Inexact) *status|=DEC_Underflow; + return; + } + + // adjust>0, so need to rescale the result so exponent becomes Etiny + // [this code is similar to that in rescale] + workset=*set; // clone rounding, etc. + workset.digits=dn->digits-adjust; // set requested length + workset.emin-=adjust; // and adjust emin to match + // [note that the latter can be <1, here, similar to Rescale case] + decSetCoeff(dn, &workset, dn->lsu, dn->digits, residue, status); + decApplyRound(dn, &workset, *residue, status); + + // Use 754 default rule: Underflow is set iff Inexact + // [independent of whether trapped] + if (*status&DEC_Inexact) *status|=DEC_Underflow; + + // if rounded up a 999s case, exponent will be off by one; adjust + // back if so [it will fit, because it was shortened earlier] + if (dn->exponent>etiny) { + dn->digits=decShiftToMost(dn->lsu, dn->digits, 1); + dn->exponent--; // (re)adjust the exponent. + } + + // if rounded to zero, it is by definition clamped... + if (ISZERO(dn)) *status|=DEC_Clamped; + } // decSetSubnormal + +/* ------------------------------------------------------------------ */ +/* decCheckMath - check entry conditions for a math function */ +/* */ +/* This checks the context and the operand */ +/* */ +/* rhs is the operand to check */ +/* set is the context to check */ +/* status is unchanged if both are good */ +/* */ +/* returns non-zero if status is changed, 0 otherwise */ +/* */ +/* Restrictions enforced: */ +/* */ +/* digits, emax, and -emin in the context must be less than */ +/* DEC_MAX_MATH (999999), and A must be within these bounds if */ +/* non-zero. Invalid_operation is set in the status if a */ +/* restriction is violated. */ +/* ------------------------------------------------------------------ */ +static uInt decCheckMath(const decNumber *rhs, decContext *set, + uInt *status) { + uInt save=*status; // record + if (set->digits>DEC_MAX_MATH + || set->emax>DEC_MAX_MATH + || -set->emin>DEC_MAX_MATH) *status|=DEC_Invalid_context; + else if ((rhs->digits>DEC_MAX_MATH + || rhs->exponent+rhs->digits>DEC_MAX_MATH+1 + || rhs->exponent+rhs->digits<2*(1-DEC_MAX_MATH)) + && !ISZERO(rhs)) *status|=DEC_Invalid_operation; + return (*status!=save); + } // decCheckMath + +/* ------------------------------------------------------------------ */ +/* decGetInt -- get integer from a number */ +/* */ +/* dn is the number [which will not be altered] */ +/* */ +/* returns one of: */ +/* BADINT if there is a non-zero fraction */ +/* the converted integer */ +/* BIGEVEN if the integer is even and magnitude > 2*10**9 */ +/* BIGODD if the integer is odd and magnitude > 2*10**9 */ +/* */ +/* This checks and gets a whole number from the input decNumber. */ +/* The sign can be determined from dn by the caller when BIGEVEN or */ +/* BIGODD is returned. */ +/* ------------------------------------------------------------------ */ +static Int decGetInt(const decNumber *dn) { + Int theInt; // result accumulator + const Unit *up; // work + Int got; // digits (real or not) processed + Int ilength=dn->digits+dn->exponent; // integral length + Flag neg=decNumberIsNegative(dn); // 1 if -ve + + // The number must be an integer that fits in 10 digits + // Assert, here, that 10 is enough for any rescale Etiny + #if DEC_MAX_EMAX > 999999999 + #error GetInt may need updating [for Emax] + #endif + #if DEC_MIN_EMIN < -999999999 + #error GetInt may need updating [for Emin] + #endif + if (ISZERO(dn)) return 0; // zeros are OK, with any exponent + + up=dn->lsu; // ready for lsu + theInt=0; // ready to accumulate + if (dn->exponent>=0) { // relatively easy + // no fractional part [usual]; allow for positive exponent + got=dn->exponent; + } + else { // -ve exponent; some fractional part to check and discard + Int count=-dn->exponent; // digits to discard + // spin up whole units until reach the Unit with the unit digit + for (; count>=DECDPUN; up++) { + if (*up!=0) return BADINT; // non-zero Unit to discard + count-=DECDPUN; + } + if (count==0) got=0; // [a multiple of DECDPUN] + else { // [not multiple of DECDPUN] + Int rem; // work + // slice off fraction digits and check for non-zero + #if DECDPUN<=4 + theInt=QUOT10(*up, count); + rem=*up-theInt*powers[count]; + #else + rem=*up%powers[count]; // slice off discards + theInt=*up/powers[count]; + #endif + if (rem!=0) return BADINT; // non-zero fraction + // it looks good + got=DECDPUN-count; // number of digits so far + up++; // ready for next + } + } + // now it's known there's no fractional part + + // tricky code now, to accumulate up to 9.3 digits + if (got==0) {theInt=*up; got+=DECDPUN; up++;} // ensure lsu is there + + if (ilength<11) { + Int save=theInt; + // collect any remaining unit(s) + for (; got1999999997) ilength=11; + else if (!neg && theInt>999999999) ilength=11; + if (ilength==11) theInt=save; // restore correct low bit + } + } + + if (ilength>10) { // too big + if (theInt&1) return BIGODD; // bottom bit 1 + return BIGEVEN; // bottom bit 0 + } + + if (neg) theInt=-theInt; // apply sign + return theInt; + } // decGetInt + +/* ------------------------------------------------------------------ */ +/* decDecap -- decapitate the coefficient of a number */ +/* */ +/* dn is the number to be decapitated */ +/* drop is the number of digits to be removed from the left of dn; */ +/* this must be <= dn->digits (if equal, the coefficient is */ +/* set to 0) */ +/* */ +/* Returns dn; dn->digits will be <= the initial digits less drop */ +/* (after removing drop digits there may be leading zero digits */ +/* which will also be removed). Only dn->lsu and dn->digits change. */ +/* ------------------------------------------------------------------ */ +static decNumber *decDecap(decNumber *dn, Int drop) { + Unit *msu; // -> target cut point + Int cut; // work + if (drop>=dn->digits) { // losing the whole thing + #if DECCHECK + if (drop>dn->digits) + printf("decDecap called with drop>digits [%ld>%ld]\n", + (LI)drop, (LI)dn->digits); + #endif + dn->lsu[0]=0; + dn->digits=1; + return dn; + } + msu=dn->lsu+D2U(dn->digits-drop)-1; // -> likely msu + cut=MSUDIGITS(dn->digits-drop); // digits to be in use in msu + if (cut!=DECDPUN) *msu%=powers[cut]; // clear left digits + // that may have left leading zero digits, so do a proper count... + dn->digits=decGetDigits(dn->lsu, msu-dn->lsu+1); + return dn; + } // decDecap + +/* ------------------------------------------------------------------ */ +/* decBiStr -- compare string with pairwise options */ +/* */ +/* targ is the string to compare */ +/* str1 is one of the strings to compare against (length may be 0) */ +/* str2 is the other; it must be the same length as str1 */ +/* */ +/* returns 1 if strings compare equal, (that is, it is the same */ +/* length as str1 and str2, and each character of targ is in either */ +/* str1 or str2 in the corresponding position), or 0 otherwise */ +/* */ +/* This is used for generic caseless compare, including the awkward */ +/* case of the Turkish dotted and dotless Is. Use as (for example): */ +/* if (decBiStr(test, "mike", "MIKE")) ... */ +/* ------------------------------------------------------------------ */ +static Flag decBiStr(const char *targ, const char *str1, const char *str2) { + for (;;targ++, str1++, str2++) { + if (*targ!=*str1 && *targ!=*str2) return 0; + // *targ has a match in one (or both, if terminator) + if (*targ=='\0') break; + } // forever + return 1; + } // decBiStr + +/* ------------------------------------------------------------------ */ +/* decNaNs -- handle NaN operand or operands */ +/* */ +/* res is the result number */ +/* lhs is the first operand */ +/* rhs is the second operand, or NULL if none */ +/* context is used to limit payload length */ +/* status contains the current status */ +/* returns res in case convenient */ +/* */ +/* Called when one or both operands is a NaN, and propagates the */ +/* appropriate result to res. When an sNaN is found, it is changed */ +/* to a qNaN and Invalid operation is set. */ +/* ------------------------------------------------------------------ */ +static decNumber * decNaNs(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set, + uInt *status) { + // This decision tree ends up with LHS being the source pointer, + // and status updated if need be + if (lhs->bits & DECSNAN) + *status|=DEC_Invalid_operation | DEC_sNaN; + else if (rhs==NULL); + else if (rhs->bits & DECSNAN) { + lhs=rhs; + *status|=DEC_Invalid_operation | DEC_sNaN; + } + else if (lhs->bits & DECNAN); + else lhs=rhs; + + // propagate the payload + if (lhs->digits<=set->digits) decNumberCopy(res, lhs); // easy + else { // too long + const Unit *ul; + Unit *ur, *uresp1; + // copy safe number of units, then decapitate + res->bits=lhs->bits; // need sign etc. + uresp1=res->lsu+D2U(set->digits); + for (ur=res->lsu, ul=lhs->lsu; urdigits=D2U(set->digits)*DECDPUN; + // maybe still too long + if (res->digits>set->digits) decDecap(res, res->digits-set->digits); + } + + res->bits&=~DECSNAN; // convert any sNaN to NaN, while + res->bits|=DECNAN; // .. preserving sign + res->exponent=0; // clean exponent + // [coefficient was copied/decapitated] + return res; + } // decNaNs + +/* ------------------------------------------------------------------ */ +/* decStatus -- apply non-zero status */ +/* */ +/* dn is the number to set if error */ +/* status contains the current status (not yet in context) */ +/* set is the context */ +/* */ +/* If the status is an error status, the number is set to a NaN, */ +/* unless the error was an overflow, divide-by-zero, or underflow, */ +/* in which case the number will have already been set. */ +/* */ +/* The context status is then updated with the new status. Note that */ +/* this may raise a signal, so control may never return from this */ +/* routine (hence resources must be recovered before it is called). */ +/* ------------------------------------------------------------------ */ +static void decStatus(decNumber *dn, uInt status, decContext *set) { + if (status & DEC_NaNs) { // error status -> NaN + // if cause was an sNaN, clear and propagate [NaN is already set up] + if (status & DEC_sNaN) status&=~DEC_sNaN; + else { + decNumberZero(dn); // other error: clean throughout + dn->bits=DECNAN; // and make a quiet NaN + } + } + decContextSetStatus(set, status); // [may not return] + return; + } // decStatus + +/* ------------------------------------------------------------------ */ +/* decGetDigits -- count digits in a Units array */ +/* */ +/* uar is the Unit array holding the number (this is often an */ +/* accumulator of some sort) */ +/* len is the length of the array in units [>=1] */ +/* */ +/* returns the number of (significant) digits in the array */ +/* */ +/* All leading zeros are excluded, except the last if the array has */ +/* only zero Units. */ +/* ------------------------------------------------------------------ */ +// This may be called twice during some operations. +static Int decGetDigits(Unit *uar, Int len) { + Unit *up=uar+(len-1); // -> msu + Int digits=(len-1)*DECDPUN+1; // possible digits excluding msu + #if DECDPUN>4 + uInt const *pow; // work + #endif + // (at least 1 in final msu) + #if DECCHECK + if (len<1) printf("decGetDigits called with len<1 [%ld]\n", (LI)len); + #endif + + for (; up>=uar; up--) { + if (*up==0) { // unit is all 0s + if (digits==1) break; // a zero has one digit + digits-=DECDPUN; // adjust for 0 unit + continue;} + // found the first (most significant) non-zero Unit + #if DECDPUN>1 // not done yet + if (*up<10) break; // is 1-9 + digits++; + #if DECDPUN>2 // not done yet + if (*up<100) break; // is 10-99 + digits++; + #if DECDPUN>3 // not done yet + if (*up<1000) break; // is 100-999 + digits++; + #if DECDPUN>4 // count the rest ... + for (pow=&powers[4]; *up>=*pow; pow++) digits++; + #endif + #endif + #endif + #endif + break; + } // up + return digits; + } // decGetDigits + +#if DECTRACE | DECCHECK +/* ------------------------------------------------------------------ */ +/* decNumberShow -- display a number [debug aid] */ +/* dn is the number to show */ +/* */ +/* Shows: sign, exponent, coefficient (msu first), digits */ +/* or: sign, special-value */ +/* ------------------------------------------------------------------ */ +// this is public so other modules can use it +void decNumberShow(const decNumber *dn) { + const Unit *up; // work + uInt u, d; // .. + Int cut; // .. + char isign='+'; // main sign + if (dn==NULL) { + printf("NULL\n"); + return;} + if (decNumberIsNegative(dn)) isign='-'; + printf(" >> %c ", isign); + if (dn->bits&DECSPECIAL) { // Is a special value + if (decNumberIsInfinite(dn)) printf("Infinity"); + else { // a NaN + if (dn->bits&DECSNAN) printf("sNaN"); // signalling NaN + else printf("NaN"); + } + // if coefficient and exponent are 0, no more to do + if (dn->exponent==0 && dn->digits==1 && *dn->lsu==0) { + printf("\n"); + return;} + // drop through to report other information + printf(" "); + } + + // now carefully display the coefficient + up=dn->lsu+D2U(dn->digits)-1; // msu + printf("%ld", (LI)*up); + for (up=up-1; up>=dn->lsu; up--) { + u=*up; + printf(":"); + for (cut=DECDPUN-1; cut>=0; cut--) { + d=u/powers[cut]; + u-=d*powers[cut]; + printf("%ld", (LI)d); + } // cut + } // up + if (dn->exponent!=0) { + char esign='+'; + if (dn->exponent<0) esign='-'; + printf(" E%c%ld", esign, (LI)abs(dn->exponent)); + } + printf(" [%ld]\n", (LI)dn->digits); + } // decNumberShow +#endif + +#if DECTRACE || DECCHECK +/* ------------------------------------------------------------------ */ +/* decDumpAr -- display a unit array [debug/check aid] */ +/* name is a single-character tag name */ +/* ar is the array to display */ +/* len is the length of the array in Units */ +/* ------------------------------------------------------------------ */ +static void decDumpAr(char name, const Unit *ar, Int len) { + Int i; + const char *spec; + #if DECDPUN==9 + spec="%09d "; + #elif DECDPUN==8 + spec="%08d "; + #elif DECDPUN==7 + spec="%07d "; + #elif DECDPUN==6 + spec="%06d "; + #elif DECDPUN==5 + spec="%05d "; + #elif DECDPUN==4 + spec="%04d "; + #elif DECDPUN==3 + spec="%03d "; + #elif DECDPUN==2 + spec="%02d "; + #else + spec="%d "; + #endif + printf(" :%c: ", name); + for (i=len-1; i>=0; i--) { + if (i==len-1) printf("%ld ", (LI)ar[i]); + else printf(spec, ar[i]); + } + printf("\n"); + return;} +#endif + +#if DECCHECK +/* ------------------------------------------------------------------ */ +/* decCheckOperands -- check operand(s) to a routine */ +/* res is the result structure (not checked; it will be set to */ +/* quiet NaN if error found (and it is not NULL)) */ +/* lhs is the first operand (may be DECUNRESU) */ +/* rhs is the second (may be DECUNUSED) */ +/* set is the context (may be DECUNCONT) */ +/* returns 0 if both operands, and the context are clean, or 1 */ +/* otherwise (in which case the context will show an error, */ +/* unless NULL). Note that res is not cleaned; caller should */ +/* handle this so res=NULL case is safe. */ +/* The caller is expected to abandon immediately if 1 is returned. */ +/* ------------------------------------------------------------------ */ +static Flag decCheckOperands(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + Flag bad=0; + if (set==NULL) { // oops; hopeless + #if DECTRACE || DECVERB + printf("Reference to context is NULL.\n"); + #endif + bad=1; + return 1;} + else if (set!=DECUNCONT + && (set->digits<1 || set->round>=DEC_ROUND_MAX)) { + bad=1; + #if DECTRACE || DECVERB + printf("Bad context [digits=%ld round=%ld].\n", + (LI)set->digits, (LI)set->round); + #endif + } + else { + if (res==NULL) { + bad=1; + #if DECTRACE + // this one not DECVERB as standard tests include NULL + printf("Reference to result is NULL.\n"); + #endif + } + if (!bad && lhs!=DECUNUSED) bad=(decCheckNumber(lhs)); + if (!bad && rhs!=DECUNUSED) bad=(decCheckNumber(rhs)); + } + if (bad) { + if (set!=DECUNCONT) decContextSetStatus(set, DEC_Invalid_operation); + if (res!=DECUNRESU && res!=NULL) { + decNumberZero(res); + res->bits=DECNAN; // qNaN + } + } + return bad; + } // decCheckOperands + +/* ------------------------------------------------------------------ */ +/* decCheckNumber -- check a number */ +/* dn is the number to check */ +/* returns 0 if the number is clean, or 1 otherwise */ +/* */ +/* The number is considered valid if it could be a result from some */ +/* operation in some valid context. */ +/* ------------------------------------------------------------------ */ +static Flag decCheckNumber(const decNumber *dn) { + const Unit *up; // work + uInt maxuint; // .. + Int ae, d, digits; // .. + Int emin, emax; // .. + + if (dn==NULL) { // hopeless + #if DECTRACE + // this one not DECVERB as standard tests include NULL + printf("Reference to decNumber is NULL.\n"); + #endif + return 1;} + + // check special values + if (dn->bits & DECSPECIAL) { + if (dn->exponent!=0) { + #if DECTRACE || DECVERB + printf("Exponent %ld (not 0) for a special value [%02x].\n", + (LI)dn->exponent, dn->bits); + #endif + return 1;} + + // 2003.09.08: NaNs may now have coefficients, so next tests Inf only + if (decNumberIsInfinite(dn)) { + if (dn->digits!=1) { + #if DECTRACE || DECVERB + printf("Digits %ld (not 1) for an infinity.\n", (LI)dn->digits); + #endif + return 1;} + if (*dn->lsu!=0) { + #if DECTRACE || DECVERB + printf("LSU %ld (not 0) for an infinity.\n", (LI)*dn->lsu); + #endif + decDumpAr('I', dn->lsu, D2U(dn->digits)); + return 1;} + } // Inf + // 2002.12.26: negative NaNs can now appear through proposed IEEE + // concrete formats (decimal64, etc.). + return 0; + } + + // check the coefficient + if (dn->digits<1 || dn->digits>DECNUMMAXP) { + #if DECTRACE || DECVERB + printf("Digits %ld in number.\n", (LI)dn->digits); + #endif + return 1;} + + d=dn->digits; + + for (up=dn->lsu; d>0; up++) { + if (d>DECDPUN) maxuint=DECDPUNMAX; + else { // reached the msu + maxuint=powers[d]-1; + if (dn->digits>1 && *upmaxuint) { + #if DECTRACE || DECVERB + printf("Bad Unit [%08lx] in %ld-digit number at offset %ld [maxuint %ld].\n", + (LI)*up, (LI)dn->digits, (LI)(up-dn->lsu), (LI)maxuint); + #endif + return 1;} + d-=DECDPUN; + } + + // check the exponent. Note that input operands can have exponents + // which are out of the set->emin/set->emax and set->digits range + // (just as they can have more digits than set->digits). + ae=dn->exponent+dn->digits-1; // adjusted exponent + emax=DECNUMMAXE; + emin=DECNUMMINE; + digits=DECNUMMAXP; + if (ae+emax) { + #if DECTRACE || DECVERB + printf("Adjusted exponent overflow [%ld].\n", (LI)ae); + decNumberShow(dn); + #endif + return 1;} + + return 0; // it's OK + } // decCheckNumber + +/* ------------------------------------------------------------------ */ +/* decCheckInexact -- check a normal finite inexact result has digits */ +/* dn is the number to check */ +/* set is the context (for status and precision) */ +/* sets Invalid operation, etc., if some digits are missing */ +/* [this check is not made for DECSUBSET compilation or when */ +/* subnormal is not set] */ +/* ------------------------------------------------------------------ */ +static void decCheckInexact(const decNumber *dn, decContext *set) { + #if !DECSUBSET && DECEXTFLAG + if ((set->status & (DEC_Inexact|DEC_Subnormal))==DEC_Inexact + && (set->digits!=dn->digits) && !(dn->bits & DECSPECIAL)) { + #if DECTRACE || DECVERB + printf("Insufficient digits [%ld] on normal Inexact result.\n", + (LI)dn->digits); + decNumberShow(dn); + #endif + decContextSetStatus(set, DEC_Invalid_operation); + } + #else + // next is a noop for quiet compiler + if (dn!=NULL && dn->digits==0) set->status|=DEC_Invalid_operation; + #endif + return; + } // decCheckInexact +#endif + +#if DECALLOC +#undef malloc +#undef free +/* ------------------------------------------------------------------ */ +/* decMalloc -- accountable allocation routine */ +/* n is the number of bytes to allocate */ +/* */ +/* Semantics is the same as the stdlib malloc routine, but bytes */ +/* allocated are accounted for globally, and corruption fences are */ +/* added before and after the 'actual' storage. */ +/* ------------------------------------------------------------------ */ +/* This routine allocates storage with an extra twelve bytes; 8 are */ +/* at the start and hold: */ +/* 0-3 the original length requested */ +/* 4-7 buffer corruption detection fence (DECFENCE, x4) */ +/* The 4 bytes at the end also hold a corruption fence (DECFENCE, x4) */ +/* ------------------------------------------------------------------ */ +static void *decMalloc(size_t n) { + uInt size=n+12; // true size + void *alloc; // -> allocated storage + uByte *b, *b0; // work + uInt uiwork; // for macros + + alloc=malloc(size); // -> allocated storage + if (alloc==NULL) return NULL; // out of strorage + b0=(uByte *)alloc; // as bytes + decAllocBytes+=n; // account for storage + UBFROMUI(alloc, n); // save n + // printf(" alloc ++ dAB: %ld (%ld)\n", (LI)decAllocBytes, (LI)n); + for (b=b0+4; b play area + } // decMalloc + +/* ------------------------------------------------------------------ */ +/* decFree -- accountable free routine */ +/* alloc is the storage to free */ +/* */ +/* Semantics is the same as the stdlib malloc routine, except that */ +/* the global storage accounting is updated and the fences are */ +/* checked to ensure that no routine has written 'out of bounds'. */ +/* ------------------------------------------------------------------ */ +/* This routine first checks that the fences have not been corrupted. */ +/* It then frees the storage using the 'truw' storage address (that */ +/* is, offset by 8). */ +/* ------------------------------------------------------------------ */ +static void decFree(void *alloc) { + uInt n; // original length + uByte *b, *b0; // work + uInt uiwork; // for macros + + if (alloc==NULL) return; // allowed; it's a nop + b0=(uByte *)alloc; // as bytes + b0-=8; // -> true start of storage + n=UBTOUI(b0); // lift length + for (b=b0+4; b0 */ + /* and <10; 3 or powers of 2 are best]. */ + + /* DECNUMDIGITS is the default number of digits that can be held in */ + /* the structure. If undefined, 1 is assumed and it is assumed */ + /* that the structure will be immediately followed by extra space, */ + /* as required. DECNUMDIGITS is always >0. */ + #if !defined(DECNUMDIGITS) + #define DECNUMDIGITS 1 + #endif + + /* The size (integer data type) of each unit is determined by the */ + /* number of digits it will hold. */ + #if DECDPUN<=2 + #define decNumberUnit uint8_t + #elif DECDPUN<=4 + #define decNumberUnit uint16_t + #else + #define decNumberUnit uint32_t + #endif + /* The number of units needed is ceil(DECNUMDIGITS/DECDPUN) */ + #define DECNUMUNITS ((DECNUMDIGITS+DECDPUN-1)/DECDPUN) + + /* The data structure... */ + typedef struct { + int32_t digits; /* Count of digits in the coefficient; >0 */ + int32_t exponent; /* Unadjusted exponent, unbiased, in */ + /* range: -1999999997 through 999999999 */ + uint8_t bits; /* Indicator bits (see above) */ + /* Coefficient, from least significant unit */ + decNumberUnit lsu[DECNUMUNITS]; + } decNumber; + + /* Notes: */ + /* 1. If digits is > DECDPUN then there will one or more */ + /* decNumberUnits immediately following the first element of lsu.*/ + /* These contain the remaining (more significant) digits of the */ + /* number, and may be in the lsu array, or may be guaranteed by */ + /* some other mechanism (such as being contained in another */ + /* structure, or being overlaid on dynamically allocated */ + /* storage). */ + /* */ + /* Each integer of the coefficient (except potentially the last) */ + /* contains DECDPUN digits (e.g., a value in the range 0 through */ + /* 99999999 if DECDPUN is 8, or 0 through 999 if DECDPUN is 3). */ + /* */ + /* 2. A decNumber converted to a string may need up to digits+14 */ + /* characters. The worst cases (non-exponential and exponential */ + /* formats) are -0.00000{9...}# and -9.{9...}E+999999999# */ + /* (where # is '\0') */ + + + /* ---------------------------------------------------------------- */ + /* decNumber public functions and macros */ + /* ---------------------------------------------------------------- */ + /* Conversions */ + decNumber * decNumberFromInt32(decNumber *, int32_t); + decNumber * decNumberFromUInt32(decNumber *, uint32_t); + decNumber * decNumberFromString(decNumber *, const char *, decContext *); + char * decNumberToString(const decNumber *, char *); + char * decNumberToEngString(const decNumber *, char *); + uint32_t decNumberToUInt32(const decNumber *, decContext *); + int32_t decNumberToInt32(const decNumber *, decContext *); + uint8_t * decNumberGetBCD(const decNumber *, uint8_t *); + decNumber * decNumberSetBCD(decNumber *, const uint8_t *, uint32_t); + + /* Operators and elementary functions */ + decNumber * decNumberAbs(decNumber *, const decNumber *, decContext *); + decNumber * decNumberAdd(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberAnd(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberCompare(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberCompareSignal(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberCompareTotal(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberCompareTotalMag(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberDivide(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberDivideInteger(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberExp(decNumber *, const decNumber *, decContext *); + decNumber * decNumberFMA(decNumber *, const decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberInvert(decNumber *, const decNumber *, decContext *); + decNumber * decNumberLn(decNumber *, const decNumber *, decContext *); + decNumber * decNumberLogB(decNumber *, const decNumber *, decContext *); + decNumber * decNumberLog10(decNumber *, const decNumber *, decContext *); + decNumber * decNumberMax(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberMaxMag(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberMin(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberMinMag(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberMinus(decNumber *, const decNumber *, decContext *); + decNumber * decNumberMultiply(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberNormalize(decNumber *, const decNumber *, decContext *); + decNumber * decNumberOr(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberPlus(decNumber *, const decNumber *, decContext *); + decNumber * decNumberPower(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberQuantize(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberReduce(decNumber *, const decNumber *, decContext *); + decNumber * decNumberRemainder(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberRemainderNear(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberRescale(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberRotate(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberSameQuantum(decNumber *, const decNumber *, const decNumber *); + decNumber * decNumberScaleB(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberShift(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberSquareRoot(decNumber *, const decNumber *, decContext *); + decNumber * decNumberSubtract(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberToIntegralExact(decNumber *, const decNumber *, decContext *); + decNumber * decNumberToIntegralValue(decNumber *, const decNumber *, decContext *); + decNumber * decNumberXor(decNumber *, const decNumber *, const decNumber *, decContext *); + + /* Utilities */ + enum decClass decNumberClass(const decNumber *, decContext *); + const char * decNumberClassToString(enum decClass); + decNumber * decNumberCopy(decNumber *, const decNumber *); + decNumber * decNumberCopyAbs(decNumber *, const decNumber *); + decNumber * decNumberCopyNegate(decNumber *, const decNumber *); + decNumber * decNumberCopySign(decNumber *, const decNumber *, const decNumber *); + decNumber * decNumberNextMinus(decNumber *, const decNumber *, decContext *); + decNumber * decNumberNextPlus(decNumber *, const decNumber *, decContext *); + decNumber * decNumberNextToward(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberTrim(decNumber *); + const char * decNumberVersion(void); + decNumber * decNumberZero(decNumber *); + + /* Functions for testing decNumbers (normality depends on context) */ + int32_t decNumberIsNormal(const decNumber *, decContext *); + int32_t decNumberIsSubnormal(const decNumber *, decContext *); + + /* Macros for testing decNumber *dn */ + #define decNumberIsCanonical(dn) (1) /* All decNumbers are saintly */ + #define decNumberIsFinite(dn) (((dn)->bits&DECSPECIAL)==0) + #define decNumberIsInfinite(dn) (((dn)->bits&DECINF)!=0) + #define decNumberIsNaN(dn) (((dn)->bits&(DECNAN|DECSNAN))!=0) + #define decNumberIsNegative(dn) (((dn)->bits&DECNEG)!=0) + #define decNumberIsQNaN(dn) (((dn)->bits&(DECNAN))!=0) + #define decNumberIsSNaN(dn) (((dn)->bits&(DECSNAN))!=0) + #define decNumberIsSpecial(dn) (((dn)->bits&DECSPECIAL)!=0) + #define decNumberIsZero(dn) (*(dn)->lsu==0 \ + && (dn)->digits==1 \ + && (((dn)->bits&DECSPECIAL)==0)) + #define decNumberRadix(dn) (10) + +#endif diff --git a/src/decNumber/decNumberLocal.h b/src/decNumber/decNumberLocal.h new file mode 100644 index 0000000000..5c88a5eaaf --- /dev/null +++ b/src/decNumber/decNumberLocal.h @@ -0,0 +1,757 @@ +/* ------------------------------------------------------------------ */ +/* decNumber package local type, tuning, and macro definitions */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is called decNumber.pdf. This document is */ +/* available, together with arithmetic and format specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ +/* This header file is included by all modules in the decNumber */ +/* library, and contains local type definitions, tuning parameters, */ +/* etc. It should not need to be used by application programs. */ +/* decNumber.h or one of decDouble (etc.) must be included first. */ +/* ------------------------------------------------------------------ */ + +#if !defined(DECNUMBERLOC) + #define DECNUMBERLOC + #define DECVERSION "decNumber 3.68" /* Package Version [16 max.] */ + #define DECNLAUTHOR "Mike Cowlishaw" /* Who to blame */ + + #include /* for abs */ + #include /* for memset, strcpy */ + + /* Conditional code flag -- set this to match hardware platform */ + #if !defined(DECLITEND) + #define DECLITEND 1 /* 1=little-endian, 0=big-endian */ + #endif + + /* Conditional code flag -- set this to 1 for best performance */ + #if !defined(DECUSE64) + #define DECUSE64 1 /* 1=use int64s, 0=int32 & smaller only */ + #endif + + /* Conditional code flag -- set this to 0 to exclude printf calls */ + #if !defined(DECPRINT) + #define DECPRINT 1 /* 1=allow printf calls; 0=no printf */ + #endif + + /* Conditional check flags -- set these to 0 for best performance */ + #if !defined(DECCHECK) + #define DECCHECK 0 /* 1 to enable robust checking */ + #endif + #if !defined(DECALLOC) + #define DECALLOC 0 /* 1 to enable memory accounting */ + #endif + #if !defined(DECTRACE) + #define DECTRACE 0 /* 1 to trace certain internals, etc. */ + #endif + + /* Tuning parameter for decNumber (arbitrary precision) module */ + #if !defined(DECBUFFER) + #define DECBUFFER 36 /* Size basis for local buffers. This */ + /* should be a common maximum precision */ + /* rounded up to a multiple of 4; must */ + /* be zero or positive. */ + #endif + + + /* ---------------------------------------------------------------- */ + /* Check parameter dependencies */ + /* ---------------------------------------------------------------- */ + #if DECCHECK & !DECPRINT + #error DECCHECK needs DECPRINT to be useful + #endif + #if DECALLOC & !DECPRINT + #error DECALLOC needs DECPRINT to be useful + #endif + #if DECTRACE & !DECPRINT + #error DECTRACE needs DECPRINT to be useful + #endif + + /* ---------------------------------------------------------------- */ + /* Definitions for all modules (general-purpose) */ + /* ---------------------------------------------------------------- */ + + /* Local names for common types -- for safety, decNumber modules do */ + /* not use int or long directly. */ + #define Flag uint8_t + #define Byte int8_t + #define uByte uint8_t + #define Short int16_t + #define uShort uint16_t + #define Int int32_t + #define uInt uint32_t + #define Unit decNumberUnit + #if DECUSE64 + #define Long int64_t + #define uLong uint64_t + #endif + + /* Development-use definitions */ + typedef long int LI; /* for printf arguments only */ + #define DECNOINT 0 /* 1 to check no internal use of 'int' */ + /* or stdint types */ + #if DECNOINT + /* if these interfere with your C includes, do not set DECNOINT */ + #define int ? /* enable to ensure that plain C 'int' */ + #define long ?? /* .. or 'long' types are not used */ + #endif + + /* Shared lookup tables */ + extern const uByte DECSTICKYTAB[10]; /* re-round digits if sticky */ + extern const uInt DECPOWERS[10]; /* powers of ten table */ + /* The following are included from decDPD.h */ + extern const uShort DPD2BIN[1024]; /* DPD -> 0-999 */ + extern const uShort BIN2DPD[1000]; /* 0-999 -> DPD */ + extern const uInt DPD2BINK[1024]; /* DPD -> 0-999000 */ + extern const uInt DPD2BINM[1024]; /* DPD -> 0-999000000 */ + extern const uByte DPD2BCD8[4096]; /* DPD -> ddd + len */ + extern const uByte BIN2BCD8[4000]; /* 0-999 -> ddd + len */ + extern const uShort BCD2DPD[2458]; /* 0-0x999 -> DPD (0x999=2457)*/ + + /* LONGMUL32HI -- set w=(u*v)>>32, where w, u, and v are uInts */ + /* (that is, sets w to be the high-order word of the 64-bit result; */ + /* the low-order word is simply u*v.) */ + /* This version is derived from Knuth via Hacker's Delight; */ + /* it seems to optimize better than some others tried */ + #define LONGMUL32HI(w, u, v) { \ + uInt u0, u1, v0, v1, w0, w1, w2, t; \ + u0=u & 0xffff; u1=u>>16; \ + v0=v & 0xffff; v1=v>>16; \ + w0=u0*v0; \ + t=u1*v0 + (w0>>16); \ + w1=t & 0xffff; w2=t>>16; \ + w1=u0*v1 + w1; \ + (w)=u1*v1 + w2 + (w1>>16);} + + /* ROUNDUP -- round an integer up to a multiple of n */ + #define ROUNDUP(i, n) ((((i)+(n)-1)/n)*n) + #define ROUNDUP4(i) (((i)+3)&~3) /* special for n=4 */ + + /* ROUNDDOWN -- round an integer down to a multiple of n */ + #define ROUNDDOWN(i, n) (((i)/n)*n) + #define ROUNDDOWN4(i) ((i)&~3) /* special for n=4 */ + + /* References to multi-byte sequences under different sizes; these */ + /* require locally declared variables, but do not violate strict */ + /* aliasing or alignment (as did the UINTAT simple cast to uInt). */ + /* Variables needed are uswork, uiwork, etc. [so do not use at same */ + /* level in an expression, e.g., UBTOUI(x)==UBTOUI(y) may fail]. */ + + /* Return a uInt, etc., from bytes starting at a char* or uByte* */ + #define UBTOUS(b) (memcpy((void *)&uswork, b, 2), uswork) + #define UBTOUI(b) (memcpy((void *)&uiwork, b, 4), uiwork) + + /* Store a uInt, etc., into bytes starting at a char* or uByte*. */ + /* Returns i, evaluated, for convenience; has to use uiwork because */ + /* i may be an expression. */ + #define UBFROMUS(b, i) (uswork=(i), memcpy(b, (void *)&uswork, 2), uswork) + #define UBFROMUI(b, i) (uiwork=(i), memcpy(b, (void *)&uiwork, 4), uiwork) + + /* X10 and X100 -- multiply integer i by 10 or 100 */ + /* [shifts are usually faster than multiply; could be conditional] */ + #define X10(i) (((i)<<1)+((i)<<3)) + #define X100(i) (((i)<<2)+((i)<<5)+((i)<<6)) + + /* MAXI and MINI -- general max & min (not in ANSI) for integers */ + #define MAXI(x,y) ((x)<(y)?(y):(x)) + #define MINI(x,y) ((x)>(y)?(y):(x)) + + /* Useful constants */ + #define BILLION 1000000000 /* 10**9 */ + /* CHARMASK: 0x30303030 for ASCII/UTF8; 0xF0F0F0F0 for EBCDIC */ + #define CHARMASK ((((((((uInt)'0')<<8)+'0')<<8)+'0')<<8)+'0') + + + /* ---------------------------------------------------------------- */ + /* Definitions for arbitary-precision modules (only valid after */ + /* decNumber.h has been included) */ + /* ---------------------------------------------------------------- */ + + /* Limits and constants */ + #define DECNUMMAXP 999999999 /* maximum precision code can handle */ + #define DECNUMMAXE 999999999 /* maximum adjusted exponent ditto */ + #define DECNUMMINE -999999999 /* minimum adjusted exponent ditto */ + #if (DECNUMMAXP != DEC_MAX_DIGITS) + #error Maximum digits mismatch + #endif + #if (DECNUMMAXE != DEC_MAX_EMAX) + #error Maximum exponent mismatch + #endif + #if (DECNUMMINE != DEC_MIN_EMIN) + #error Minimum exponent mismatch + #endif + + /* Set DECDPUNMAX -- the maximum integer that fits in DECDPUN */ + /* digits, and D2UTABLE -- the initializer for the D2U table */ + #if DECDPUN==1 + #define DECDPUNMAX 9 + #define D2UTABLE {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17, \ + 18,19,20,21,22,23,24,25,26,27,28,29,30,31,32, \ + 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, \ + 48,49} + #elif DECDPUN==2 + #define DECDPUNMAX 99 + #define D2UTABLE {0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10, \ + 11,11,12,12,13,13,14,14,15,15,16,16,17,17,18, \ + 18,19,19,20,20,21,21,22,22,23,23,24,24,25} + #elif DECDPUN==3 + #define DECDPUNMAX 999 + #define D2UTABLE {0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7, \ + 8,8,8,9,9,9,10,10,10,11,11,11,12,12,12,13,13, \ + 13,14,14,14,15,15,15,16,16,16,17} + #elif DECDPUN==4 + #define DECDPUNMAX 9999 + #define D2UTABLE {0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6, \ + 6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,11, \ + 11,11,11,12,12,12,12,13} + #elif DECDPUN==5 + #define DECDPUNMAX 99999 + #define D2UTABLE {0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5, \ + 5,5,5,5,6,6,6,6,6,7,7,7,7,7,8,8,8,8,8,9,9,9, \ + 9,9,10,10,10,10} + #elif DECDPUN==6 + #define DECDPUNMAX 999999 + #define D2UTABLE {0,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4, \ + 4,4,4,5,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,8, \ + 8,8,8,8,8,9} + #elif DECDPUN==7 + #define DECDPUNMAX 9999999 + #define D2UTABLE {0,1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,3, \ + 4,4,4,4,4,4,4,5,5,5,5,5,5,5,6,6,6,6,6,6,6,7, \ + 7,7,7,7,7,7} + #elif DECDPUN==8 + #define DECDPUNMAX 99999999 + #define D2UTABLE {0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3, \ + 3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6, \ + 6,6,6,6,6,7} + #elif DECDPUN==9 + #define DECDPUNMAX 999999999 + #define D2UTABLE {0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3, \ + 3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5, \ + 5,5,6,6,6,6} + #elif defined(DECDPUN) + #error DECDPUN must be in the range 1-9 + #endif + + /* ----- Shared data (in decNumber.c) ----- */ + /* Public lookup table used by the D2U macro (see below) */ + #define DECMAXD2U 49 + extern const uByte d2utable[DECMAXD2U+1]; + + /* ----- Macros ----- */ + /* ISZERO -- return true if decNumber dn is a zero */ + /* [performance-critical in some situations] */ + #define ISZERO(dn) decNumberIsZero(dn) /* now just a local name */ + + /* D2U -- return the number of Units needed to hold d digits */ + /* (runtime version, with table lookaside for small d) */ + #if DECDPUN==8 + #define D2U(d) ((unsigned)((d)<=DECMAXD2U?d2utable[d]:((d)+7)>>3)) + #elif DECDPUN==4 + #define D2U(d) ((unsigned)((d)<=DECMAXD2U?d2utable[d]:((d)+3)>>2)) + #else + #define D2U(d) ((d)<=DECMAXD2U?d2utable[d]:((d)+DECDPUN-1)/DECDPUN) + #endif + /* SD2U -- static D2U macro (for compile-time calculation) */ + #define SD2U(d) (((d)+DECDPUN-1)/DECDPUN) + + /* MSUDIGITS -- returns digits in msu, from digits, calculated */ + /* using D2U */ + #define MSUDIGITS(d) ((d)-(D2U(d)-1)*DECDPUN) + + /* D2N -- return the number of decNumber structs that would be */ + /* needed to contain that number of digits (and the initial */ + /* decNumber struct) safely. Note that one Unit is included in the */ + /* initial structure. Used for allocating space that is aligned on */ + /* a decNumber struct boundary. */ + #define D2N(d) \ + ((((SD2U(d)-1)*sizeof(Unit))+sizeof(decNumber)*2-1)/sizeof(decNumber)) + + /* TODIGIT -- macro to remove the leading digit from the unsigned */ + /* integer u at column cut (counting from the right, LSD=0) and */ + /* place it as an ASCII character into the character pointed to by */ + /* c. Note that cut must be <= 9, and the maximum value for u is */ + /* 2,000,000,000 (as is needed for negative exponents of */ + /* subnormals). The unsigned integer pow is used as a temporary */ + /* variable. */ + #define TODIGIT(u, cut, c, pow) { \ + *(c)='0'; \ + pow=DECPOWERS[cut]*2; \ + if ((u)>pow) { \ + pow*=4; \ + if ((u)>=pow) {(u)-=pow; *(c)+=8;} \ + pow/=2; \ + if ((u)>=pow) {(u)-=pow; *(c)+=4;} \ + pow/=2; \ + } \ + if ((u)>=pow) {(u)-=pow; *(c)+=2;} \ + pow/=2; \ + if ((u)>=pow) {(u)-=pow; *(c)+=1;} \ + } + + /* ---------------------------------------------------------------- */ + /* Definitions for fixed-precision modules (only valid after */ + /* decSingle.h, decDouble.h, or decQuad.h has been included) */ + /* ---------------------------------------------------------------- */ + + /* bcdnum -- a structure describing a format-independent finite */ + /* number, whose coefficient is a string of bcd8 uBytes */ + typedef struct { + uByte *msd; /* -> most significant digit */ + uByte *lsd; /* -> least ditto */ + uInt sign; /* 0=positive, DECFLOAT_Sign=negative */ + Int exponent; /* Unadjusted signed exponent (q), or */ + /* DECFLOAT_NaN etc. for a special */ + } bcdnum; + + /* Test if exponent or bcdnum exponent must be a special, etc. */ + #define EXPISSPECIAL(exp) ((exp)>=DECFLOAT_MinSp) + #define EXPISINF(exp) (exp==DECFLOAT_Inf) + #define EXPISNAN(exp) (exp==DECFLOAT_qNaN || exp==DECFLOAT_sNaN) + #define NUMISSPECIAL(num) (EXPISSPECIAL((num)->exponent)) + + /* Refer to a 32-bit word or byte in a decFloat (df) by big-endian */ + /* (array) notation (the 0 word or byte contains the sign bit), */ + /* automatically adjusting for endianness; similarly address a word */ + /* in the next-wider format (decFloatWider, or dfw) */ + #define DECWORDS (DECBYTES/4) + #define DECWWORDS (DECWBYTES/4) + #if DECLITEND + #define DFBYTE(df, off) ((df)->bytes[DECBYTES-1-(off)]) + #define DFWORD(df, off) ((df)->words[DECWORDS-1-(off)]) + #define DFWWORD(dfw, off) ((dfw)->words[DECWWORDS-1-(off)]) + #else + #define DFBYTE(df, off) ((df)->bytes[off]) + #define DFWORD(df, off) ((df)->words[off]) + #define DFWWORD(dfw, off) ((dfw)->words[off]) + #endif + + /* Tests for sign or specials, directly on DECFLOATs */ + #define DFISSIGNED(df) ((DFWORD(df, 0)&0x80000000)!=0) + #define DFISSPECIAL(df) ((DFWORD(df, 0)&0x78000000)==0x78000000) + #define DFISINF(df) ((DFWORD(df, 0)&0x7c000000)==0x78000000) + #define DFISNAN(df) ((DFWORD(df, 0)&0x7c000000)==0x7c000000) + #define DFISQNAN(df) ((DFWORD(df, 0)&0x7e000000)==0x7c000000) + #define DFISSNAN(df) ((DFWORD(df, 0)&0x7e000000)==0x7e000000) + + /* Shared lookup tables */ + extern const uInt DECCOMBMSD[64]; /* Combination field -> MSD */ + extern const uInt DECCOMBFROM[48]; /* exp+msd -> Combination */ + + /* Private generic (utility) routine */ + #if DECCHECK || DECTRACE + extern void decShowNum(const bcdnum *, const char *); + #endif + + /* Format-dependent macros and constants */ + #if defined(DECPMAX) + + /* Useful constants */ + #define DECPMAX9 (ROUNDUP(DECPMAX, 9)/9) /* 'Pmax' in 10**9s */ + /* Top words for a zero */ + #define SINGLEZERO 0x22500000 + #define DOUBLEZERO 0x22380000 + #define QUADZERO 0x22080000 + /* [ZEROWORD is defined to be one of these in the DFISZERO macro] */ + + /* Format-dependent common tests: */ + /* DFISZERO -- test for (any) zero */ + /* DFISCCZERO -- test for coefficient continuation being zero */ + /* DFISCC01 -- test for coefficient contains only 0s and 1s */ + /* DFISINT -- test for finite and exponent q=0 */ + /* DFISUINT01 -- test for sign=0, finite, exponent q=0, and */ + /* MSD=0 or 1 */ + /* ZEROWORD is also defined here. */ + /* */ + /* In DFISZERO the first test checks the least-significant word */ + /* (most likely to be non-zero); the penultimate tests MSD and */ + /* DPDs in the signword, and the final test excludes specials and */ + /* MSD>7. DFISINT similarly has to allow for the two forms of */ + /* MSD codes. DFISUINT01 only has to allow for one form of MSD */ + /* code. */ + #if DECPMAX==7 + #define ZEROWORD SINGLEZERO + /* [test macros not needed except for Zero] */ + #define DFISZERO(df) ((DFWORD(df, 0)&0x1c0fffff)==0 \ + && (DFWORD(df, 0)&0x60000000)!=0x60000000) + #elif DECPMAX==16 + #define ZEROWORD DOUBLEZERO + #define DFISZERO(df) ((DFWORD(df, 1)==0 \ + && (DFWORD(df, 0)&0x1c03ffff)==0 \ + && (DFWORD(df, 0)&0x60000000)!=0x60000000)) + #define DFISINT(df) ((DFWORD(df, 0)&0x63fc0000)==0x22380000 \ + ||(DFWORD(df, 0)&0x7bfc0000)==0x6a380000) + #define DFISUINT01(df) ((DFWORD(df, 0)&0xfbfc0000)==0x22380000) + #define DFISCCZERO(df) (DFWORD(df, 1)==0 \ + && (DFWORD(df, 0)&0x0003ffff)==0) + #define DFISCC01(df) ((DFWORD(df, 0)&~0xfffc9124)==0 \ + && (DFWORD(df, 1)&~0x49124491)==0) + #elif DECPMAX==34 + #define ZEROWORD QUADZERO + #define DFISZERO(df) ((DFWORD(df, 3)==0 \ + && DFWORD(df, 2)==0 \ + && DFWORD(df, 1)==0 \ + && (DFWORD(df, 0)&0x1c003fff)==0 \ + && (DFWORD(df, 0)&0x60000000)!=0x60000000)) + #define DFISINT(df) ((DFWORD(df, 0)&0x63ffc000)==0x22080000 \ + ||(DFWORD(df, 0)&0x7bffc000)==0x6a080000) + #define DFISUINT01(df) ((DFWORD(df, 0)&0xfbffc000)==0x22080000) + #define DFISCCZERO(df) (DFWORD(df, 3)==0 \ + && DFWORD(df, 2)==0 \ + && DFWORD(df, 1)==0 \ + && (DFWORD(df, 0)&0x00003fff)==0) + + #define DFISCC01(df) ((DFWORD(df, 0)&~0xffffc912)==0 \ + && (DFWORD(df, 1)&~0x44912449)==0 \ + && (DFWORD(df, 2)&~0x12449124)==0 \ + && (DFWORD(df, 3)&~0x49124491)==0) + #endif + + /* Macros to test if a certain 10 bits of a uInt or pair of uInts */ + /* are a canonical declet [higher or lower bits are ignored]. */ + /* declet is at offset 0 (from the right) in a uInt: */ + #define CANONDPD(dpd) (((dpd)&0x300)==0 || ((dpd)&0x6e)!=0x6e) + /* declet is at offset k (a multiple of 2) in a uInt: */ + #define CANONDPDOFF(dpd, k) (((dpd)&(0x300<<(k)))==0 \ + || ((dpd)&(((uInt)0x6e)<<(k)))!=(((uInt)0x6e)<<(k))) + /* declet is at offset k (a multiple of 2) in a pair of uInts: */ + /* [the top 2 bits will always be in the more-significant uInt] */ + #define CANONDPDTWO(hi, lo, k) (((hi)&(0x300>>(32-(k))))==0 \ + || ((hi)&(0x6e>>(32-(k))))!=(0x6e>>(32-(k))) \ + || ((lo)&(((uInt)0x6e)<<(k)))!=(((uInt)0x6e)<<(k))) + + /* Macro to test whether a full-length (length DECPMAX) BCD8 */ + /* coefficient, starting at uByte u, is all zeros */ + /* Test just the LSWord first, then the remainder as a sequence */ + /* of tests in order to avoid same-level use of UBTOUI */ + #if DECPMAX==7 + #define ISCOEFFZERO(u) ( \ + UBTOUI((u)+DECPMAX-4)==0 \ + && UBTOUS((u)+DECPMAX-6)==0 \ + && *(u)==0) + #elif DECPMAX==16 + #define ISCOEFFZERO(u) ( \ + UBTOUI((u)+DECPMAX-4)==0 \ + && UBTOUI((u)+DECPMAX-8)==0 \ + && UBTOUI((u)+DECPMAX-12)==0 \ + && UBTOUI(u)==0) + #elif DECPMAX==34 + #define ISCOEFFZERO(u) ( \ + UBTOUI((u)+DECPMAX-4)==0 \ + && UBTOUI((u)+DECPMAX-8)==0 \ + && UBTOUI((u)+DECPMAX-12)==0 \ + && UBTOUI((u)+DECPMAX-16)==0 \ + && UBTOUI((u)+DECPMAX-20)==0 \ + && UBTOUI((u)+DECPMAX-24)==0 \ + && UBTOUI((u)+DECPMAX-28)==0 \ + && UBTOUI((u)+DECPMAX-32)==0 \ + && UBTOUS(u)==0) + #endif + + /* Macros and masks for the sign, exponent continuation, and MSD */ + /* Get the sign as DECFLOAT_Sign or 0 */ + #define GETSIGN(df) (DFWORD(df, 0)&0x80000000) + /* Get the exponent continuation from a decFloat *df as an Int */ + #define GETECON(df) ((Int)((DFWORD((df), 0)&0x03ffffff)>>(32-6-DECECONL))) + /* Ditto, from the next-wider format */ + #define GETWECON(df) ((Int)((DFWWORD((df), 0)&0x03ffffff)>>(32-6-DECWECONL))) + /* Get the biased exponent similarly */ + #define GETEXP(df) ((Int)(DECCOMBEXP[DFWORD((df), 0)>>26]+GETECON(df))) + /* Get the unbiased exponent similarly */ + #define GETEXPUN(df) ((Int)GETEXP(df)-DECBIAS) + /* Get the MSD similarly (as uInt) */ + #define GETMSD(df) (DECCOMBMSD[DFWORD((df), 0)>>26]) + + /* Compile-time computes of the exponent continuation field masks */ + /* full exponent continuation field: */ + #define ECONMASK ((0x03ffffff>>(32-6-DECECONL))<<(32-6-DECECONL)) + /* same, not including its first digit (the qNaN/sNaN selector): */ + #define ECONNANMASK ((0x01ffffff>>(32-6-DECECONL))<<(32-6-DECECONL)) + + /* Macros to decode the coefficient in a finite decFloat *df into */ + /* a BCD string (uByte *bcdin) of length DECPMAX uBytes. */ + + /* In-line sequence to convert least significant 10 bits of uInt */ + /* dpd to three BCD8 digits starting at uByte u. Note that an */ + /* extra byte is written to the right of the three digits because */ + /* four bytes are moved at a time for speed; the alternative */ + /* macro moves exactly three bytes (usually slower). */ + #define dpd2bcd8(u, dpd) memcpy(u, &DPD2BCD8[((dpd)&0x3ff)*4], 4) + #define dpd2bcd83(u, dpd) memcpy(u, &DPD2BCD8[((dpd)&0x3ff)*4], 3) + + /* Decode the declets. After extracting each one, it is decoded */ + /* to BCD8 using a table lookup (also used for variable-length */ + /* decode). Each DPD decode is 3 bytes BCD8 plus a one-byte */ + /* length which is not used, here). Fixed-length 4-byte moves */ + /* are fast, however, almost everywhere, and so are used except */ + /* for the final three bytes (to avoid overrun). The code below */ + /* is 36 instructions for Doubles and about 70 for Quads, even */ + /* on IA32. */ + + /* Two macros are defined for each format: */ + /* GETCOEFF extracts the coefficient of the current format */ + /* GETWCOEFF extracts the coefficient of the next-wider format. */ + /* The latter is a copy of the next-wider GETCOEFF using DFWWORD. */ + + #if DECPMAX==7 + #define GETCOEFF(df, bcd) { \ + uInt sourhi=DFWORD(df, 0); \ + *(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \ + dpd2bcd8(bcd+1, sourhi>>10); \ + dpd2bcd83(bcd+4, sourhi);} + #define GETWCOEFF(df, bcd) { \ + uInt sourhi=DFWWORD(df, 0); \ + uInt sourlo=DFWWORD(df, 1); \ + *(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \ + dpd2bcd8(bcd+1, sourhi>>8); \ + dpd2bcd8(bcd+4, (sourhi<<2) | (sourlo>>30)); \ + dpd2bcd8(bcd+7, sourlo>>20); \ + dpd2bcd8(bcd+10, sourlo>>10); \ + dpd2bcd83(bcd+13, sourlo);} + + #elif DECPMAX==16 + #define GETCOEFF(df, bcd) { \ + uInt sourhi=DFWORD(df, 0); \ + uInt sourlo=DFWORD(df, 1); \ + *(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \ + dpd2bcd8(bcd+1, sourhi>>8); \ + dpd2bcd8(bcd+4, (sourhi<<2) | (sourlo>>30)); \ + dpd2bcd8(bcd+7, sourlo>>20); \ + dpd2bcd8(bcd+10, sourlo>>10); \ + dpd2bcd83(bcd+13, sourlo);} + #define GETWCOEFF(df, bcd) { \ + uInt sourhi=DFWWORD(df, 0); \ + uInt sourmh=DFWWORD(df, 1); \ + uInt sourml=DFWWORD(df, 2); \ + uInt sourlo=DFWWORD(df, 3); \ + *(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \ + dpd2bcd8(bcd+1, sourhi>>4); \ + dpd2bcd8(bcd+4, ((sourhi)<<6) | (sourmh>>26)); \ + dpd2bcd8(bcd+7, sourmh>>16); \ + dpd2bcd8(bcd+10, sourmh>>6); \ + dpd2bcd8(bcd+13, ((sourmh)<<4) | (sourml>>28)); \ + dpd2bcd8(bcd+16, sourml>>18); \ + dpd2bcd8(bcd+19, sourml>>8); \ + dpd2bcd8(bcd+22, ((sourml)<<2) | (sourlo>>30)); \ + dpd2bcd8(bcd+25, sourlo>>20); \ + dpd2bcd8(bcd+28, sourlo>>10); \ + dpd2bcd83(bcd+31, sourlo);} + + #elif DECPMAX==34 + #define GETCOEFF(df, bcd) { \ + uInt sourhi=DFWORD(df, 0); \ + uInt sourmh=DFWORD(df, 1); \ + uInt sourml=DFWORD(df, 2); \ + uInt sourlo=DFWORD(df, 3); \ + *(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \ + dpd2bcd8(bcd+1, sourhi>>4); \ + dpd2bcd8(bcd+4, ((sourhi)<<6) | (sourmh>>26)); \ + dpd2bcd8(bcd+7, sourmh>>16); \ + dpd2bcd8(bcd+10, sourmh>>6); \ + dpd2bcd8(bcd+13, ((sourmh)<<4) | (sourml>>28)); \ + dpd2bcd8(bcd+16, sourml>>18); \ + dpd2bcd8(bcd+19, sourml>>8); \ + dpd2bcd8(bcd+22, ((sourml)<<2) | (sourlo>>30)); \ + dpd2bcd8(bcd+25, sourlo>>20); \ + dpd2bcd8(bcd+28, sourlo>>10); \ + dpd2bcd83(bcd+31, sourlo);} + + #define GETWCOEFF(df, bcd) {??} /* [should never be used] */ + #endif + + /* Macros to decode the coefficient in a finite decFloat *df into */ + /* a base-billion uInt array, with the least-significant */ + /* 0-999999999 'digit' at offset 0. */ + + /* Decode the declets. After extracting each one, it is decoded */ + /* to binary using a table lookup. Three tables are used; one */ + /* the usual DPD to binary, the other two pre-multiplied by 1000 */ + /* and 1000000 to avoid multiplication during decode. These */ + /* tables can also be used for multiplying up the MSD as the DPD */ + /* code for 0 through 9 is the identity. */ + #define DPD2BIN0 DPD2BIN /* for prettier code */ + + #if DECPMAX==7 + #define GETCOEFFBILL(df, buf) { \ + uInt sourhi=DFWORD(df, 0); \ + (buf)[0]=DPD2BIN0[sourhi&0x3ff] \ + +DPD2BINK[(sourhi>>10)&0x3ff] \ + +DPD2BINM[DECCOMBMSD[sourhi>>26]];} + + #elif DECPMAX==16 + #define GETCOEFFBILL(df, buf) { \ + uInt sourhi, sourlo; \ + sourlo=DFWORD(df, 1); \ + (buf)[0]=DPD2BIN0[sourlo&0x3ff] \ + +DPD2BINK[(sourlo>>10)&0x3ff] \ + +DPD2BINM[(sourlo>>20)&0x3ff]; \ + sourhi=DFWORD(df, 0); \ + (buf)[1]=DPD2BIN0[((sourhi<<2) | (sourlo>>30))&0x3ff] \ + +DPD2BINK[(sourhi>>8)&0x3ff] \ + +DPD2BINM[DECCOMBMSD[sourhi>>26]];} + + #elif DECPMAX==34 + #define GETCOEFFBILL(df, buf) { \ + uInt sourhi, sourmh, sourml, sourlo; \ + sourlo=DFWORD(df, 3); \ + (buf)[0]=DPD2BIN0[sourlo&0x3ff] \ + +DPD2BINK[(sourlo>>10)&0x3ff] \ + +DPD2BINM[(sourlo>>20)&0x3ff]; \ + sourml=DFWORD(df, 2); \ + (buf)[1]=DPD2BIN0[((sourml<<2) | (sourlo>>30))&0x3ff] \ + +DPD2BINK[(sourml>>8)&0x3ff] \ + +DPD2BINM[(sourml>>18)&0x3ff]; \ + sourmh=DFWORD(df, 1); \ + (buf)[2]=DPD2BIN0[((sourmh<<4) | (sourml>>28))&0x3ff] \ + +DPD2BINK[(sourmh>>6)&0x3ff] \ + +DPD2BINM[(sourmh>>16)&0x3ff]; \ + sourhi=DFWORD(df, 0); \ + (buf)[3]=DPD2BIN0[((sourhi<<6) | (sourmh>>26))&0x3ff] \ + +DPD2BINK[(sourhi>>4)&0x3ff] \ + +DPD2BINM[DECCOMBMSD[sourhi>>26]];} + + #endif + + /* Macros to decode the coefficient in a finite decFloat *df into */ + /* a base-thousand uInt array (of size DECLETS+1, to allow for */ + /* the MSD), with the least-significant 0-999 'digit' at offset 0.*/ + + /* Decode the declets. After extracting each one, it is decoded */ + /* to binary using a table lookup. */ + #if DECPMAX==7 + #define GETCOEFFTHOU(df, buf) { \ + uInt sourhi=DFWORD(df, 0); \ + (buf)[0]=DPD2BIN[sourhi&0x3ff]; \ + (buf)[1]=DPD2BIN[(sourhi>>10)&0x3ff]; \ + (buf)[2]=DECCOMBMSD[sourhi>>26];} + + #elif DECPMAX==16 + #define GETCOEFFTHOU(df, buf) { \ + uInt sourhi, sourlo; \ + sourlo=DFWORD(df, 1); \ + (buf)[0]=DPD2BIN[sourlo&0x3ff]; \ + (buf)[1]=DPD2BIN[(sourlo>>10)&0x3ff]; \ + (buf)[2]=DPD2BIN[(sourlo>>20)&0x3ff]; \ + sourhi=DFWORD(df, 0); \ + (buf)[3]=DPD2BIN[((sourhi<<2) | (sourlo>>30))&0x3ff]; \ + (buf)[4]=DPD2BIN[(sourhi>>8)&0x3ff]; \ + (buf)[5]=DECCOMBMSD[sourhi>>26];} + + #elif DECPMAX==34 + #define GETCOEFFTHOU(df, buf) { \ + uInt sourhi, sourmh, sourml, sourlo; \ + sourlo=DFWORD(df, 3); \ + (buf)[0]=DPD2BIN[sourlo&0x3ff]; \ + (buf)[1]=DPD2BIN[(sourlo>>10)&0x3ff]; \ + (buf)[2]=DPD2BIN[(sourlo>>20)&0x3ff]; \ + sourml=DFWORD(df, 2); \ + (buf)[3]=DPD2BIN[((sourml<<2) | (sourlo>>30))&0x3ff]; \ + (buf)[4]=DPD2BIN[(sourml>>8)&0x3ff]; \ + (buf)[5]=DPD2BIN[(sourml>>18)&0x3ff]; \ + sourmh=DFWORD(df, 1); \ + (buf)[6]=DPD2BIN[((sourmh<<4) | (sourml>>28))&0x3ff]; \ + (buf)[7]=DPD2BIN[(sourmh>>6)&0x3ff]; \ + (buf)[8]=DPD2BIN[(sourmh>>16)&0x3ff]; \ + sourhi=DFWORD(df, 0); \ + (buf)[9]=DPD2BIN[((sourhi<<6) | (sourmh>>26))&0x3ff]; \ + (buf)[10]=DPD2BIN[(sourhi>>4)&0x3ff]; \ + (buf)[11]=DECCOMBMSD[sourhi>>26];} + #endif + + + /* Macros to decode the coefficient in a finite decFloat *df and */ + /* add to a base-thousand uInt array (as for GETCOEFFTHOU). */ + /* After the addition then most significant 'digit' in the array */ + /* might have a value larger then 10 (with a maximum of 19). */ + #if DECPMAX==7 + #define ADDCOEFFTHOU(df, buf) { \ + uInt sourhi=DFWORD(df, 0); \ + (buf)[0]+=DPD2BIN[sourhi&0x3ff]; \ + if (buf[0]>999) {buf[0]-=1000; buf[1]++;} \ + (buf)[1]+=DPD2BIN[(sourhi>>10)&0x3ff]; \ + if (buf[1]>999) {buf[1]-=1000; buf[2]++;} \ + (buf)[2]+=DECCOMBMSD[sourhi>>26];} + + #elif DECPMAX==16 + #define ADDCOEFFTHOU(df, buf) { \ + uInt sourhi, sourlo; \ + sourlo=DFWORD(df, 1); \ + (buf)[0]+=DPD2BIN[sourlo&0x3ff]; \ + if (buf[0]>999) {buf[0]-=1000; buf[1]++;} \ + (buf)[1]+=DPD2BIN[(sourlo>>10)&0x3ff]; \ + if (buf[1]>999) {buf[1]-=1000; buf[2]++;} \ + (buf)[2]+=DPD2BIN[(sourlo>>20)&0x3ff]; \ + if (buf[2]>999) {buf[2]-=1000; buf[3]++;} \ + sourhi=DFWORD(df, 0); \ + (buf)[3]+=DPD2BIN[((sourhi<<2) | (sourlo>>30))&0x3ff]; \ + if (buf[3]>999) {buf[3]-=1000; buf[4]++;} \ + (buf)[4]+=DPD2BIN[(sourhi>>8)&0x3ff]; \ + if (buf[4]>999) {buf[4]-=1000; buf[5]++;} \ + (buf)[5]+=DECCOMBMSD[sourhi>>26];} + + #elif DECPMAX==34 + #define ADDCOEFFTHOU(df, buf) { \ + uInt sourhi, sourmh, sourml, sourlo; \ + sourlo=DFWORD(df, 3); \ + (buf)[0]+=DPD2BIN[sourlo&0x3ff]; \ + if (buf[0]>999) {buf[0]-=1000; buf[1]++;} \ + (buf)[1]+=DPD2BIN[(sourlo>>10)&0x3ff]; \ + if (buf[1]>999) {buf[1]-=1000; buf[2]++;} \ + (buf)[2]+=DPD2BIN[(sourlo>>20)&0x3ff]; \ + if (buf[2]>999) {buf[2]-=1000; buf[3]++;} \ + sourml=DFWORD(df, 2); \ + (buf)[3]+=DPD2BIN[((sourml<<2) | (sourlo>>30))&0x3ff]; \ + if (buf[3]>999) {buf[3]-=1000; buf[4]++;} \ + (buf)[4]+=DPD2BIN[(sourml>>8)&0x3ff]; \ + if (buf[4]>999) {buf[4]-=1000; buf[5]++;} \ + (buf)[5]+=DPD2BIN[(sourml>>18)&0x3ff]; \ + if (buf[5]>999) {buf[5]-=1000; buf[6]++;} \ + sourmh=DFWORD(df, 1); \ + (buf)[6]+=DPD2BIN[((sourmh<<4) | (sourml>>28))&0x3ff]; \ + if (buf[6]>999) {buf[6]-=1000; buf[7]++;} \ + (buf)[7]+=DPD2BIN[(sourmh>>6)&0x3ff]; \ + if (buf[7]>999) {buf[7]-=1000; buf[8]++;} \ + (buf)[8]+=DPD2BIN[(sourmh>>16)&0x3ff]; \ + if (buf[8]>999) {buf[8]-=1000; buf[9]++;} \ + sourhi=DFWORD(df, 0); \ + (buf)[9]+=DPD2BIN[((sourhi<<6) | (sourmh>>26))&0x3ff]; \ + if (buf[9]>999) {buf[9]-=1000; buf[10]++;} \ + (buf)[10]+=DPD2BIN[(sourhi>>4)&0x3ff]; \ + if (buf[10]>999) {buf[10]-=1000; buf[11]++;} \ + (buf)[11]+=DECCOMBMSD[sourhi>>26];} + #endif + + + /* Set a decFloat to the maximum positive finite number (Nmax) */ + #if DECPMAX==7 + #define DFSETNMAX(df) \ + {DFWORD(df, 0)=0x77f3fcff;} + #elif DECPMAX==16 + #define DFSETNMAX(df) \ + {DFWORD(df, 0)=0x77fcff3f; \ + DFWORD(df, 1)=0xcff3fcff;} + #elif DECPMAX==34 + #define DFSETNMAX(df) \ + {DFWORD(df, 0)=0x77ffcff3; \ + DFWORD(df, 1)=0xfcff3fcf; \ + DFWORD(df, 2)=0xf3fcff3f; \ + DFWORD(df, 3)=0xcff3fcff;} + #endif + + /* [end of format-dependent macros and constants] */ + #endif + +#else + #error decNumberLocal included more than once +#endif diff --git a/src/decNumber/decPacked.c b/src/decNumber/decPacked.c new file mode 100644 index 0000000000..9881139de2 --- /dev/null +++ b/src/decNumber/decPacked.c @@ -0,0 +1,220 @@ +/* ------------------------------------------------------------------ */ +/* Packed Decimal conversion module */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2002. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is called decNumber.pdf. This document is */ +/* available, together with arithmetic and format specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ +/* This module comprises the routines for Packed Decimal format */ +/* numbers. Conversions are supplied to and from decNumber, which in */ +/* turn supports: */ +/* conversions to and from string */ +/* arithmetic routines */ +/* utilities. */ +/* Conversions from decNumber to and from densely packed decimal */ +/* formats are provided by the decimal32 through decimal128 modules. */ +/* ------------------------------------------------------------------ */ + +#include // for NULL +#include "decNumber.h" // base number library +#include "decPacked.h" // packed decimal +#include "decNumberLocal.h" // decNumber local types, etc. + +/* ------------------------------------------------------------------ */ +/* decPackedFromNumber -- convert decNumber to BCD Packed Decimal */ +/* */ +/* bcd is the BCD bytes */ +/* length is the length of the BCD array */ +/* scale is the scale result */ +/* dn is the decNumber */ +/* returns bcd, or NULL if error */ +/* */ +/* The number is converted to a BCD packed decimal byte array, */ +/* right aligned in the bcd array, whose length is indicated by the */ +/* second parameter. The final 4-bit nibble in the array will be a */ +/* sign nibble, C (1100) for + and D (1101) for -. Unused bytes and */ +/* nibbles to the left of the number are set to 0. */ +/* */ +/* scale is set to the scale of the number (this is the exponent, */ +/* negated). To force the number to a specified scale, first use the */ +/* decNumberRescale routine, which will round and change the exponent */ +/* as necessary. */ +/* */ +/* If there is an error (that is, the decNumber has too many digits */ +/* to fit in length bytes, or it is a NaN or Infinity), NULL is */ +/* returned and the bcd and scale results are unchanged. Otherwise */ +/* bcd is returned. */ +/* ------------------------------------------------------------------ */ +uByte * decPackedFromNumber(uByte *bcd, Int length, Int *scale, + const decNumber *dn) { + const Unit *up=dn->lsu; // Unit array pointer + uByte obyte, *out; // current output byte, and where it goes + Int indigs=dn->digits; // digits processed + uInt cut=DECDPUN; // downcounter per Unit + uInt u=*up; // work + uInt nib; // .. + #if DECDPUN<=4 + uInt temp; // .. + #endif + + if (dn->digits>length*2-1 // too long .. + ||(dn->bits & DECSPECIAL)) return NULL; // .. or special -- hopeless + + if (dn->bits&DECNEG) obyte=DECPMINUS; // set the sign .. + else obyte=DECPPLUS; + *scale=-dn->exponent; // .. and scale + + // loop from lowest (rightmost) byte + out=bcd+length-1; // -> final byte + for (; out>=bcd; out--) { + if (indigs>0) { + if (cut==0) { + up++; + u=*up; + cut=DECDPUN; + } + #if DECDPUN<=4 + temp=(u*6554)>>16; // fast /10 + nib=u-X10(temp); + u=temp; + #else + nib=u%10; // cannot use *6554 trick :-( + u=u/10; + #endif + obyte|=(nib<<4); + indigs--; + cut--; + } + *out=obyte; + obyte=0; // assume 0 + if (indigs>0) { + if (cut==0) { + up++; + u=*up; + cut=DECDPUN; + } + #if DECDPUN<=4 + temp=(u*6554)>>16; // as above + obyte=(uByte)(u-X10(temp)); + u=temp; + #else + obyte=(uByte)(u%10); + u=u/10; + #endif + indigs--; + cut--; + } + } // loop + + return bcd; + } // decPackedFromNumber + +/* ------------------------------------------------------------------ */ +/* decPackedToNumber -- convert BCD Packed Decimal to a decNumber */ +/* */ +/* bcd is the BCD bytes */ +/* length is the length of the BCD array */ +/* scale is the scale associated with the BCD integer */ +/* dn is the decNumber [with space for length*2 digits] */ +/* returns dn, or NULL if error */ +/* */ +/* The BCD packed decimal byte array, together with an associated */ +/* scale, is converted to a decNumber. The BCD array is assumed full */ +/* of digits, and must be ended by a 4-bit sign nibble in the least */ +/* significant four bits of the final byte. */ +/* */ +/* The scale is used (negated) as the exponent of the decNumber. */ +/* Note that zeros may have a sign and/or a scale. */ +/* */ +/* The decNumber structure is assumed to have sufficient space to */ +/* hold the converted number (that is, up to length*2-1 digits), so */ +/* no error is possible unless the adjusted exponent is out of range, */ +/* no sign nibble was found, or a sign nibble was found before the */ +/* final nibble. In these error cases, NULL is returned and the */ +/* decNumber will be 0. */ +/* ------------------------------------------------------------------ */ +decNumber * decPackedToNumber(const uByte *bcd, Int length, + const Int *scale, decNumber *dn) { + const uByte *last=bcd+length-1; // -> last byte + const uByte *first; // -> first non-zero byte + uInt nib; // work nibble + Unit *up=dn->lsu; // output pointer + Int digits; // digits count + Int cut=0; // phase of output + + decNumberZero(dn); // default result + last=&bcd[length-1]; + nib=*last & 0x0f; // get the sign + if (nib==DECPMINUS || nib==DECPMINUSALT) dn->bits=DECNEG; + else if (nib<=9) return NULL; // not a sign nibble + + // skip leading zero bytes [final byte is always non-zero, due to sign] + for (first=bcd; *first==0;) first++; + digits=(last-first)*2+1; // calculate digits .. + if ((*first & 0xf0)==0) digits--; // adjust for leading zero nibble + if (digits!=0) dn->digits=digits; // count of actual digits [if 0, + // leave as 1] + + // check the adjusted exponent; note that scale could be unbounded + dn->exponent=-*scale; // set the exponent + if (*scale>=0) { // usual case + if ((dn->digits-*scale-1)<-DECNUMMAXE) { // underflow + decNumberZero(dn); + return NULL;} + } + else { // -ve scale; +ve exponent + // need to be careful to avoid wrap, here, also BADINT case + if ((*scale<-DECNUMMAXE) // overflow even without digits + || ((dn->digits-*scale-1)>DECNUMMAXE)) { // overflow + decNumberZero(dn); + return NULL;} + } + if (digits==0) return dn; // result was zero + + // copy the digits to the number's units, starting at the lsu + // [unrolled] + for (;;) { // forever + // left nibble first + nib=(unsigned)(*last & 0xf0)>>4; + // got a digit, in nib + if (nib>9) {decNumberZero(dn); return NULL;} + + if (cut==0) *up=(Unit)nib; + else *up=(Unit)(*up+nib*DECPOWERS[cut]); + digits--; + if (digits==0) break; // got them all + cut++; + if (cut==DECDPUN) { + up++; + cut=0; + } + last--; // ready for next + nib=*last & 0x0f; // get right nibble + if (nib>9) {decNumberZero(dn); return NULL;} + + // got a digit, in nib + if (cut==0) *up=(Unit)nib; + else *up=(Unit)(*up+nib*DECPOWERS[cut]); + digits--; + if (digits==0) break; // got them all + cut++; + if (cut==DECDPUN) { + up++; + cut=0; + } + } // forever + + return dn; + } // decPackedToNumber + diff --git a/src/decNumber/decPacked.h b/src/decNumber/decPacked.h new file mode 100644 index 0000000000..320d53faca --- /dev/null +++ b/src/decNumber/decPacked.h @@ -0,0 +1,52 @@ +/* ------------------------------------------------------------------ */ +/* Packed Decimal conversion module header */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is called decNumber.pdf. This document is */ +/* available, together with arithmetic and format specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ + +#if !defined(DECPACKED) + #define DECPACKED + #define DECPNAME "decPacked" /* Short name */ + #define DECPFULLNAME "Packed Decimal conversions" /* Verbose name */ + #define DECPAUTHOR "Mike Cowlishaw" /* Who to blame */ + + #define DECPACKED_DefP 32 /* default precision */ + + #ifndef DECNUMDIGITS + #define DECNUMDIGITS DECPACKED_DefP /* size if not already defined*/ + #endif + #include "decNumber.h" /* context and number library */ + + /* Sign nibble constants */ + #if !defined(DECPPLUSALT) + #define DECPPLUSALT 0x0A /* alternate plus nibble */ + #define DECPMINUSALT 0x0B /* alternate minus nibble */ + #define DECPPLUS 0x0C /* preferred plus nibble */ + #define DECPMINUS 0x0D /* preferred minus nibble */ + #define DECPPLUSALT2 0x0E /* alternate plus nibble */ + #define DECPUNSIGNED 0x0F /* alternate plus nibble (unsigned) */ + #endif + + /* ---------------------------------------------------------------- */ + /* decPacked public routines */ + /* ---------------------------------------------------------------- */ + /* Conversions */ + uint8_t * decPackedFromNumber(uint8_t *, int32_t, int32_t *, + const decNumber *); + decNumber * decPackedToNumber(const uint8_t *, int32_t, const int32_t *, + decNumber *); + +#endif diff --git a/src/decNumber/decQuad.c b/src/decNumber/decQuad.c new file mode 100644 index 0000000000..ba0fd0aa52 --- /dev/null +++ b/src/decNumber/decQuad.c @@ -0,0 +1,135 @@ +/* ------------------------------------------------------------------ */ +/* decQuad.c -- decQuad operations module */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is included in the package as decNumber.pdf. This */ +/* document is also available in HTML, together with specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ +/* This module comprises decQuad operations (including conversions) */ +/* ------------------------------------------------------------------ */ + + +/* Constant mappings for shared code */ +#define DECPMAX DECQUAD_Pmax +#define DECEMIN DECQUAD_Emin +#define DECEMAX DECQUAD_Emax +#define DECEMAXD DECQUAD_EmaxD +#define DECBYTES DECQUAD_Bytes +#define DECSTRING DECQUAD_String +#define DECECONL DECQUAD_EconL +#define DECBIAS DECQUAD_Bias +#define DECLETS DECQUAD_Declets +#define DECQTINY (-DECQUAD_Bias) + +/* Type and function mappings for shared code */ +#define decFloat decQuad // Type name + +// Utilities and conversions (binary results, extractors, etc.) +#define decFloatFromBCD decQuadFromBCD +#define decFloatFromInt32 decQuadFromInt32 +#define decFloatFromPacked decQuadFromPacked +#define decFloatFromPackedChecked decQuadFromPackedChecked +#define decFloatFromString decQuadFromString +#define decFloatFromUInt32 decQuadFromUInt32 +#define decFloatFromWider decQuadFromWider +#define decFloatGetCoefficient decQuadGetCoefficient +#define decFloatGetExponent decQuadGetExponent +#define decFloatSetCoefficient decQuadSetCoefficient +#define decFloatSetExponent decQuadSetExponent +#define decFloatShow decQuadShow +#define decFloatToBCD decQuadToBCD +#define decFloatToEngString decQuadToEngString +#define decFloatToInt32 decQuadToInt32 +#define decFloatToInt32Exact decQuadToInt32Exact +#define decFloatToPacked decQuadToPacked +#define decFloatToString decQuadToString +#define decFloatToUInt32 decQuadToUInt32 +#define decFloatToUInt32Exact decQuadToUInt32Exact +#define decFloatToWider decQuadToWider +#define decFloatZero decQuadZero + +// Computational (result is a decFloat) +#define decFloatAbs decQuadAbs +#define decFloatAdd decQuadAdd +#define decFloatAnd decQuadAnd +#define decFloatDivide decQuadDivide +#define decFloatDivideInteger decQuadDivideInteger +#define decFloatFMA decQuadFMA +#define decFloatInvert decQuadInvert +#define decFloatLogB decQuadLogB +#define decFloatMax decQuadMax +#define decFloatMaxMag decQuadMaxMag +#define decFloatMin decQuadMin +#define decFloatMinMag decQuadMinMag +#define decFloatMinus decQuadMinus +#define decFloatMultiply decQuadMultiply +#define decFloatNextMinus decQuadNextMinus +#define decFloatNextPlus decQuadNextPlus +#define decFloatNextToward decQuadNextToward +#define decFloatOr decQuadOr +#define decFloatPlus decQuadPlus +#define decFloatQuantize decQuadQuantize +#define decFloatReduce decQuadReduce +#define decFloatRemainder decQuadRemainder +#define decFloatRemainderNear decQuadRemainderNear +#define decFloatRotate decQuadRotate +#define decFloatScaleB decQuadScaleB +#define decFloatShift decQuadShift +#define decFloatSubtract decQuadSubtract +#define decFloatToIntegralValue decQuadToIntegralValue +#define decFloatToIntegralExact decQuadToIntegralExact +#define decFloatXor decQuadXor + +// Comparisons +#define decFloatCompare decQuadCompare +#define decFloatCompareSignal decQuadCompareSignal +#define decFloatCompareTotal decQuadCompareTotal +#define decFloatCompareTotalMag decQuadCompareTotalMag + +// Copies +#define decFloatCanonical decQuadCanonical +#define decFloatCopy decQuadCopy +#define decFloatCopyAbs decQuadCopyAbs +#define decFloatCopyNegate decQuadCopyNegate +#define decFloatCopySign decQuadCopySign + +// Non-computational +#define decFloatClass decQuadClass +#define decFloatClassString decQuadClassString +#define decFloatDigits decQuadDigits +#define decFloatIsCanonical decQuadIsCanonical +#define decFloatIsFinite decQuadIsFinite +#define decFloatIsInfinite decQuadIsInfinite +#define decFloatIsInteger decQuadIsInteger +#define decFloatIsLogical decQuadIsLogical +#define decFloatIsNaN decQuadIsNaN +#define decFloatIsNegative decQuadIsNegative +#define decFloatIsNormal decQuadIsNormal +#define decFloatIsPositive decQuadIsPositive +#define decFloatIsSignaling decQuadIsSignaling +#define decFloatIsSignalling decQuadIsSignalling +#define decFloatIsSigned decQuadIsSigned +#define decFloatIsSubnormal decQuadIsSubnormal +#define decFloatIsZero decQuadIsZero +#define decFloatRadix decQuadRadix +#define decFloatSameQuantum decQuadSameQuantum +#define decFloatVersion decQuadVersion + +/* And now the code itself */ +#include "decContext.h" // public includes +#include "decQuad.h" // .. +#include "decNumberLocal.h" // local includes (need DECPMAX) +#include "decCommon.c" // non-arithmetic decFloat routines +#include "decBasic.c" // basic formats routines + diff --git a/src/decNumber/decQuad.h b/src/decNumber/decQuad.h new file mode 100644 index 0000000000..4eb7017b89 --- /dev/null +++ b/src/decNumber/decQuad.h @@ -0,0 +1,177 @@ +/* ------------------------------------------------------------------ */ +/* decQuad.h -- Decimal 128-bit format module header */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is included in the package as decNumber.pdf. This */ +/* document is also available in HTML, together with specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ +/* This include file is always included by decSingle and decDouble, */ +/* and therefore also holds useful constants used by all three. */ + +#if !defined(DECQUAD) + #define DECQUAD + + #define DECQUADNAME "decimalQuad" /* Short name */ + #define DECQUADTITLE "Decimal 128-bit datum" /* Verbose name */ + #define DECQUADAUTHOR "Mike Cowlishaw" /* Who to blame */ + + /* parameters for decQuads */ + #define DECQUAD_Bytes 16 /* length */ + #define DECQUAD_Pmax 34 /* maximum precision (digits) */ + #define DECQUAD_Emin -6143 /* minimum adjusted exponent */ + #define DECQUAD_Emax 6144 /* maximum adjusted exponent */ + #define DECQUAD_EmaxD 4 /* maximum exponent digits */ + #define DECQUAD_Bias 6176 /* bias for the exponent */ + #define DECQUAD_String 43 /* maximum string length, +1 */ + #define DECQUAD_EconL 12 /* exponent continuation length */ + #define DECQUAD_Declets 11 /* count of declets */ + /* highest biased exponent (Elimit-1) */ + #define DECQUAD_Ehigh (DECQUAD_Emax + DECQUAD_Bias - (DECQUAD_Pmax-1)) + + /* Required include */ + #include "decContext.h" + + /* The decQuad decimal 128-bit type, accessible by all sizes */ + typedef union { + uint8_t bytes[DECQUAD_Bytes]; /* fields: 1, 5, 12, 110 bits */ + uint16_t shorts[DECQUAD_Bytes/2]; + uint32_t words[DECQUAD_Bytes/4]; + #if DECUSE64 + uint64_t longs[DECQUAD_Bytes/8]; + #endif + } decQuad; + + /* ---------------------------------------------------------------- */ + /* Shared constants */ + /* ---------------------------------------------------------------- */ + + /* sign and special values [top 32-bits; last two bits are don't-care + for Infinity on input, last bit don't-care for NaNs] */ + #define DECFLOAT_Sign 0x80000000 /* 1 00000 00 Sign */ + #define DECFLOAT_NaN 0x7c000000 /* 0 11111 00 NaN generic */ + #define DECFLOAT_qNaN 0x7c000000 /* 0 11111 00 qNaN */ + #define DECFLOAT_sNaN 0x7e000000 /* 0 11111 10 sNaN */ + #define DECFLOAT_Inf 0x78000000 /* 0 11110 00 Infinity */ + #define DECFLOAT_MinSp 0x78000000 /* minimum special value */ + /* [specials are all >=MinSp] */ + /* Sign nibble constants */ + #if !defined(DECPPLUSALT) + #define DECPPLUSALT 0x0A /* alternate plus nibble */ + #define DECPMINUSALT 0x0B /* alternate minus nibble */ + #define DECPPLUS 0x0C /* preferred plus nibble */ + #define DECPMINUS 0x0D /* preferred minus nibble */ + #define DECPPLUSALT2 0x0E /* alternate plus nibble */ + #define DECPUNSIGNED 0x0F /* alternate plus nibble (unsigned) */ + #endif + + /* ---------------------------------------------------------------- */ + /* Routines -- implemented as decFloat routines in common files */ + /* ---------------------------------------------------------------- */ + + /* Utilities and conversions, extractors, etc.) */ + extern decQuad * decQuadFromBCD(decQuad *, int32_t, const uint8_t *, int32_t); + extern decQuad * decQuadFromInt32(decQuad *, int32_t); + extern decQuad * decQuadFromPacked(decQuad *, int32_t, const uint8_t *); + extern decQuad * decQuadFromPackedChecked(decQuad *, int32_t, const uint8_t *); + extern decQuad * decQuadFromString(decQuad *, const char *, decContext *); + extern decQuad * decQuadFromUInt32(decQuad *, uint32_t); + extern int32_t decQuadGetCoefficient(const decQuad *, uint8_t *); + extern int32_t decQuadGetExponent(const decQuad *); + extern decQuad * decQuadSetCoefficient(decQuad *, const uint8_t *, int32_t); + extern decQuad * decQuadSetExponent(decQuad *, decContext *, int32_t); + extern void decQuadShow(const decQuad *, const char *); + extern int32_t decQuadToBCD(const decQuad *, int32_t *, uint8_t *); + extern char * decQuadToEngString(const decQuad *, char *); + extern int32_t decQuadToInt32(const decQuad *, decContext *, enum rounding); + extern int32_t decQuadToInt32Exact(const decQuad *, decContext *, enum rounding); + extern int32_t decQuadToPacked(const decQuad *, int32_t *, uint8_t *); + extern char * decQuadToString(const decQuad *, char *); + extern uint32_t decQuadToUInt32(const decQuad *, decContext *, enum rounding); + extern uint32_t decQuadToUInt32Exact(const decQuad *, decContext *, enum rounding); + extern decQuad * decQuadZero(decQuad *); + + /* Computational (result is a decQuad) */ + extern decQuad * decQuadAbs(decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadAdd(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadAnd(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadDivide(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadDivideInteger(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadFMA(decQuad *, const decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadInvert(decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadLogB(decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadMax(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadMaxMag(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadMin(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadMinMag(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadMinus(decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadMultiply(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadNextMinus(decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadNextPlus(decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadNextToward(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadOr(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadPlus(decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadQuantize(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadReduce(decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadRemainder(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadRemainderNear(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadRotate(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadScaleB(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadShift(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadSubtract(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadToIntegralValue(decQuad *, const decQuad *, decContext *, enum rounding); + extern decQuad * decQuadToIntegralExact(decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadXor(decQuad *, const decQuad *, const decQuad *, decContext *); + + /* Comparisons */ + extern decQuad * decQuadCompare(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadCompareSignal(decQuad *, const decQuad *, const decQuad *, decContext *); + extern decQuad * decQuadCompareTotal(decQuad *, const decQuad *, const decQuad *); + extern decQuad * decQuadCompareTotalMag(decQuad *, const decQuad *, const decQuad *); + + /* Copies */ + extern decQuad * decQuadCanonical(decQuad *, const decQuad *); + extern decQuad * decQuadCopy(decQuad *, const decQuad *); + extern decQuad * decQuadCopyAbs(decQuad *, const decQuad *); + extern decQuad * decQuadCopyNegate(decQuad *, const decQuad *); + extern decQuad * decQuadCopySign(decQuad *, const decQuad *, const decQuad *); + + /* Non-computational */ + extern enum decClass decQuadClass(const decQuad *); + extern const char * decQuadClassString(const decQuad *); + extern uint32_t decQuadDigits(const decQuad *); + extern uint32_t decQuadIsCanonical(const decQuad *); + extern uint32_t decQuadIsFinite(const decQuad *); + extern uint32_t decQuadIsInteger(const decQuad *); + extern uint32_t decQuadIsLogical(const decQuad *); + extern uint32_t decQuadIsInfinite(const decQuad *); + extern uint32_t decQuadIsNaN(const decQuad *); + extern uint32_t decQuadIsNegative(const decQuad *); + extern uint32_t decQuadIsNormal(const decQuad *); + extern uint32_t decQuadIsPositive(const decQuad *); + extern uint32_t decQuadIsSignaling(const decQuad *); + extern uint32_t decQuadIsSignalling(const decQuad *); + extern uint32_t decQuadIsSigned(const decQuad *); + extern uint32_t decQuadIsSubnormal(const decQuad *); + extern uint32_t decQuadIsZero(const decQuad *); + extern uint32_t decQuadRadix(const decQuad *); + extern uint32_t decQuadSameQuantum(const decQuad *, const decQuad *); + extern const char * decQuadVersion(void); + + /* decNumber conversions; these are implemented as macros so as not */ + /* to force a dependency on decimal128 and decNumber in decQuad. */ + /* decQuadFromNumber returns a decimal128 * to avoid warnings. */ + #define decQuadToNumber(dq, dn) decimal128ToNumber((decimal128 *)(dq), dn) + #define decQuadFromNumber(dq, dn, set) decimal128FromNumber((decimal128 *)(dq), dn, set) + +#endif diff --git a/src/decNumber/decSingle.c b/src/decNumber/decSingle.c new file mode 100644 index 0000000000..bb69970b42 --- /dev/null +++ b/src/decNumber/decSingle.c @@ -0,0 +1,71 @@ +/* ------------------------------------------------------------------ */ +/* decSingle.c -- decSingle operations module */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2008. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is included in the package as decNumber.pdf. This */ +/* document is also available in HTML, together with specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ +/* This module comprises decSingle operations (including conversions) */ +/* ------------------------------------------------------------------ */ + +#include "decContext.h" // public includes +#include "decSingle.h" // public includes + +/* Constant mappings for shared code */ +#define DECPMAX DECSINGLE_Pmax +#define DECEMIN DECSINGLE_Emin +#define DECEMAX DECSINGLE_Emax +#define DECEMAXD DECSINGLE_EmaxD +#define DECBYTES DECSINGLE_Bytes +#define DECSTRING DECSINGLE_String +#define DECECONL DECSINGLE_EconL +#define DECBIAS DECSINGLE_Bias +#define DECLETS DECSINGLE_Declets +#define DECQTINY (-DECSINGLE_Bias) +// parameters of next-wider format +#define DECWBYTES DECDOUBLE_Bytes +#define DECWPMAX DECDOUBLE_Pmax +#define DECWECONL DECDOUBLE_EconL +#define DECWBIAS DECDOUBLE_Bias + +/* Type and function mappings for shared code */ +#define decFloat decSingle // Type name +#define decFloatWider decDouble // Type name + +// Utility (binary results, extractors, etc.) +#define decFloatFromBCD decSingleFromBCD +#define decFloatFromPacked decSingleFromPacked +#define decFloatFromPackedChecked decSingleFromPackedChecked +#define decFloatFromString decSingleFromString +#define decFloatFromWider decSingleFromWider +#define decFloatGetCoefficient decSingleGetCoefficient +#define decFloatGetExponent decSingleGetExponent +#define decFloatSetCoefficient decSingleSetCoefficient +#define decFloatSetExponent decSingleSetExponent +#define decFloatShow decSingleShow +#define decFloatToBCD decSingleToBCD +#define decFloatToEngString decSingleToEngString +#define decFloatToPacked decSingleToPacked +#define decFloatToString decSingleToString +#define decFloatToWider decSingleToWider +#define decFloatZero decSingleZero + +// Non-computational +#define decFloatRadix decSingleRadix +#define decFloatVersion decSingleVersion + +#include "decNumberLocal.h" // local includes (need DECPMAX) +#include "decCommon.c" // non-basic decFloat routines +// [Do not include decBasic.c for decimal32] + diff --git a/src/decNumber/decSingle.h b/src/decNumber/decSingle.h new file mode 100644 index 0000000000..0691f7af00 --- /dev/null +++ b/src/decNumber/decSingle.h @@ -0,0 +1,86 @@ +/* ------------------------------------------------------------------ */ +/* decSingle.h -- Decimal 32-bit format module header */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2008. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is included in the package as decNumber.pdf. This */ +/* document is also available in HTML, together with specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ + +#if !defined(DECSINGLE) + #define DECSINGLE + + #define DECSINGLENAME "decSingle" /* Short name */ + #define DECSINGLETITLE "Decimal 32-bit datum" /* Verbose name */ + #define DECSINGLEAUTHOR "Mike Cowlishaw" /* Who to blame */ + + /* parameters for decSingles */ + #define DECSINGLE_Bytes 4 /* length */ + #define DECSINGLE_Pmax 7 /* maximum precision (digits) */ + #define DECSINGLE_Emin -95 /* minimum adjusted exponent */ + #define DECSINGLE_Emax 96 /* maximum adjusted exponent */ + #define DECSINGLE_EmaxD 3 /* maximum exponent digits */ + #define DECSINGLE_Bias 101 /* bias for the exponent */ + #define DECSINGLE_String 16 /* maximum string length, +1 */ + #define DECSINGLE_EconL 6 /* exponent continuation length */ + #define DECSINGLE_Declets 2 /* count of declets */ + /* highest biased exponent (Elimit-1) */ + #define DECSINGLE_Ehigh (DECSINGLE_Emax + DECSINGLE_Bias - (DECSINGLE_Pmax-1)) + + /* Required includes */ + #include "decContext.h" + #include "decQuad.h" + #include "decDouble.h" + + /* The decSingle decimal 32-bit type, accessible by all sizes */ + typedef union { + uint8_t bytes[DECSINGLE_Bytes]; /* fields: 1, 5, 6, 20 bits */ + uint16_t shorts[DECSINGLE_Bytes/2]; + uint32_t words[DECSINGLE_Bytes/4]; + } decSingle; + + /* ---------------------------------------------------------------- */ + /* Routines -- implemented as decFloat routines in common files */ + /* ---------------------------------------------------------------- */ + + /* Utilities (binary argument(s) or result, extractors, etc.) */ + extern decSingle * decSingleFromBCD(decSingle *, int32_t, const uint8_t *, int32_t); + extern decSingle * decSingleFromPacked(decSingle *, int32_t, const uint8_t *); + extern decSingle * decSingleFromPackedChecked(decSingle *, int32_t, const uint8_t *); + extern decSingle * decSingleFromString(decSingle *, const char *, decContext *); + extern decSingle * decSingleFromWider(decSingle *, const decDouble *, decContext *); + extern int32_t decSingleGetCoefficient(const decSingle *, uint8_t *); + extern int32_t decSingleGetExponent(const decSingle *); + extern decSingle * decSingleSetCoefficient(decSingle *, const uint8_t *, int32_t); + extern decSingle * decSingleSetExponent(decSingle *, decContext *, int32_t); + extern void decSingleShow(const decSingle *, const char *); + extern int32_t decSingleToBCD(const decSingle *, int32_t *, uint8_t *); + extern char * decSingleToEngString(const decSingle *, char *); + extern int32_t decSingleToPacked(const decSingle *, int32_t *, uint8_t *); + extern char * decSingleToString(const decSingle *, char *); + extern decDouble * decSingleToWider(const decSingle *, decDouble *); + extern decSingle * decSingleZero(decSingle *); + + /* (No Arithmetic routines for decSingle) */ + + /* Non-computational */ + extern uint32_t decSingleRadix(const decSingle *); + extern const char * decSingleVersion(void); + + /* decNumber conversions; these are implemented as macros so as not */ + /* to force a dependency on decimal32 and decNumber in decSingle. */ + /* decSingleFromNumber returns a decimal32 * to avoid warnings. */ + #define decSingleToNumber(dq, dn) decimal32ToNumber((decimal32 *)(dq), dn) + #define decSingleFromNumber(dq, dn, set) decimal32FromNumber((decimal32 *)(dq), dn, set) + +#endif diff --git a/src/decNumber/decimal128.c b/src/decNumber/decimal128.c new file mode 100644 index 0000000000..e5fa45b960 --- /dev/null +++ b/src/decNumber/decimal128.c @@ -0,0 +1,553 @@ +/* ------------------------------------------------------------------ */ +/* Decimal 128-bit format module */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2008. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is called decNumber.pdf. This document is */ +/* available, together with arithmetic and format specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ +/* This module comprises the routines for decimal128 format numbers. */ +/* Conversions are supplied to and from decNumber and String. */ +/* */ +/* This is used when decNumber provides operations, either for all */ +/* operations or as a proxy between decNumber and decSingle. */ +/* */ +/* Error handling is the same as decNumber (qv.). */ +/* ------------------------------------------------------------------ */ +#include // [for memset/memcpy] +#include // [for printf] + +#define DECNUMDIGITS 34 // make decNumbers with space for 34 +#include "decNumber.h" // base number library +#include "decNumberLocal.h" // decNumber local types, etc. +#include "decimal128.h" // our primary include + +/* Utility routines and tables [in decimal64.c] */ +// DPD2BIN and the reverse are renamed to prevent link-time conflict +// if decQuad is also built in the same executable +#define DPD2BIN DPD2BINx +#define BIN2DPD BIN2DPDx +extern const uInt COMBEXP[32], COMBMSD[32]; +extern const uShort DPD2BIN[1024]; +extern const uShort BIN2DPD[1000]; // [not used] +extern const uByte BIN2CHAR[4001]; + +extern void decDigitsFromDPD(decNumber *, const uInt *, Int); +extern void decDigitsToDPD(const decNumber *, uInt *, Int); + +#if DECTRACE || DECCHECK +void decimal128Show(const decimal128 *); // for debug +extern void decNumberShow(const decNumber *); // .. +#endif + +/* Useful macro */ +// Clear a structure (e.g., a decNumber) +#define DEC_clear(d) memset(d, 0, sizeof(*d)) + +/* ------------------------------------------------------------------ */ +/* decimal128FromNumber -- convert decNumber to decimal128 */ +/* */ +/* ds is the target decimal128 */ +/* dn is the source number (assumed valid) */ +/* set is the context, used only for reporting errors */ +/* */ +/* The set argument is used only for status reporting and for the */ +/* rounding mode (used if the coefficient is more than DECIMAL128_Pmax*/ +/* digits or an overflow is detected). If the exponent is out of the */ +/* valid range then Overflow or Underflow will be raised. */ +/* After Underflow a subnormal result is possible. */ +/* */ +/* DEC_Clamped is set if the number has to be 'folded down' to fit, */ +/* by reducing its exponent and multiplying the coefficient by a */ +/* power of ten, or if the exponent on a zero had to be clamped. */ +/* ------------------------------------------------------------------ */ +decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn, + decContext *set) { + uInt status=0; // status accumulator + Int ae; // adjusted exponent + decNumber dw; // work + decContext dc; // .. + uInt comb, exp; // .. + uInt uiwork; // for macros + uInt targar[4]={0,0,0,0}; // target 128-bit + #define targhi targar[3] // name the word with the sign + #define targmh targar[2] // name the words + #define targml targar[1] // .. + #define targlo targar[0] // .. + + // If the number has too many digits, or the exponent could be + // out of range then reduce the number under the appropriate + // constraints. This could push the number to Infinity or zero, + // so this check and rounding must be done before generating the + // decimal128] + ae=dn->exponent+dn->digits-1; // [0 if special] + if (dn->digits>DECIMAL128_Pmax // too many digits + || ae>DECIMAL128_Emax // likely overflow + || aeround; // use supplied rounding + decNumberPlus(&dw, dn, &dc); // (round and check) + // [this changes -0 to 0, so enforce the sign...] + dw.bits|=dn->bits&DECNEG; + status=dc.status; // save status + dn=&dw; // use the work number + } // maybe out of range + + if (dn->bits&DECSPECIAL) { // a special value + if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24; + else { // sNaN or qNaN + if ((*dn->lsu!=0 || dn->digits>1) // non-zero coefficient + && (dn->digitsbits&DECNAN) targhi|=DECIMAL_NaN<<24; + else targhi|=DECIMAL_sNaN<<24; + } // a NaN + } // special + + else { // is finite + if (decNumberIsZero(dn)) { // is a zero + // set and clamp exponent + if (dn->exponent<-DECIMAL128_Bias) { + exp=0; // low clamp + status|=DEC_Clamped; + } + else { + exp=dn->exponent+DECIMAL128_Bias; // bias exponent + if (exp>DECIMAL128_Ehigh) { // top clamp + exp=DECIMAL128_Ehigh; + status|=DEC_Clamped; + } + } + comb=(exp>>9) & 0x18; // msd=0, exp top 2 bits .. + } + else { // non-zero finite number + uInt msd; // work + Int pad=0; // coefficient pad digits + + // the dn is known to fit, but it may need to be padded + exp=(uInt)(dn->exponent+DECIMAL128_Bias); // bias exponent + if (exp>DECIMAL128_Ehigh) { // fold-down case + pad=exp-DECIMAL128_Ehigh; + exp=DECIMAL128_Ehigh; // [to maximum] + status|=DEC_Clamped; + } + + // [fastpath for common case is not a win, here] + decDigitsToDPD(dn, targar, pad); + // save and clear the top digit + msd=targhi>>14; + targhi&=0x00003fff; + + // create the combination field + if (msd>=8) comb=0x18 | ((exp>>11) & 0x06) | (msd & 0x01); + else comb=((exp>>9) & 0x18) | msd; + } + targhi|=comb<<26; // add combination field .. + targhi|=(exp&0xfff)<<14; // .. and exponent continuation + } // finite + + if (dn->bits&DECNEG) targhi|=0x80000000; // add sign bit + + // now write to storage; this is endian + if (DECLITEND) { + // lo -> hi + UBFROMUI(d128->bytes, targlo); + UBFROMUI(d128->bytes+4, targml); + UBFROMUI(d128->bytes+8, targmh); + UBFROMUI(d128->bytes+12, targhi); + } + else { + // hi -> lo + UBFROMUI(d128->bytes, targhi); + UBFROMUI(d128->bytes+4, targmh); + UBFROMUI(d128->bytes+8, targml); + UBFROMUI(d128->bytes+12, targlo); + } + + if (status!=0) decContextSetStatus(set, status); // pass on status + // decimal128Show(d128); + return d128; + } // decimal128FromNumber + +/* ------------------------------------------------------------------ */ +/* decimal128ToNumber -- convert decimal128 to decNumber */ +/* d128 is the source decimal128 */ +/* dn is the target number, with appropriate space */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) { + uInt msd; // coefficient MSD + uInt exp; // exponent top two bits + uInt comb; // combination field + Int need; // work + uInt uiwork; // for macros + uInt sourar[4]; // source 128-bit + #define sourhi sourar[3] // name the word with the sign + #define sourmh sourar[2] // and the mid-high word + #define sourml sourar[1] // and the mod-low word + #define sourlo sourar[0] // and the lowest word + + // load source from storage; this is endian + if (DECLITEND) { + sourlo=UBTOUI(d128->bytes ); // directly load the low int + sourml=UBTOUI(d128->bytes+4 ); // then the mid-low + sourmh=UBTOUI(d128->bytes+8 ); // then the mid-high + sourhi=UBTOUI(d128->bytes+12); // then the high int + } + else { + sourhi=UBTOUI(d128->bytes ); // directly load the high int + sourmh=UBTOUI(d128->bytes+4 ); // then the mid-high + sourml=UBTOUI(d128->bytes+8 ); // then the mid-low + sourlo=UBTOUI(d128->bytes+12); // then the low int + } + + comb=(sourhi>>26)&0x1f; // combination field + + decNumberZero(dn); // clean number + if (sourhi&0x80000000) dn->bits=DECNEG; // set sign if negative + + msd=COMBMSD[comb]; // decode the combination field + exp=COMBEXP[comb]; // .. + + if (exp==3) { // is a special + if (msd==0) { + dn->bits|=DECINF; + return dn; // no coefficient needed + } + else if (sourhi&0x02000000) dn->bits|=DECSNAN; + else dn->bits|=DECNAN; + msd=0; // no top digit + } + else { // is a finite number + dn->exponent=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; // unbiased + } + + // get the coefficient + sourhi&=0x00003fff; // clean coefficient continuation + if (msd) { // non-zero msd + sourhi|=msd<<14; // prefix to coefficient + need=12; // process 12 declets + } + else { // msd=0 + if (sourhi) need=11; // declets to process + else if (sourmh) need=10; + else if (sourml) need=7; + else if (sourlo) need=4; + else return dn; // easy: coefficient is 0 + } //msd=0 + + decDigitsFromDPD(dn, sourar, need); // process declets + // decNumberShow(dn); + return dn; + } // decimal128ToNumber + +/* ------------------------------------------------------------------ */ +/* to-scientific-string -- conversion to numeric string */ +/* to-engineering-string -- conversion to numeric string */ +/* */ +/* decimal128ToString(d128, string); */ +/* decimal128ToEngString(d128, string); */ +/* */ +/* d128 is the decimal128 format number to convert */ +/* string is the string where the result will be laid out */ +/* */ +/* string must be at least 24 characters */ +/* */ +/* No error is possible, and no status can be set. */ +/* ------------------------------------------------------------------ */ +char * decimal128ToEngString(const decimal128 *d128, char *string){ + decNumber dn; // work + decimal128ToNumber(d128, &dn); + decNumberToEngString(&dn, string); + return string; + } // decimal128ToEngString + +char * decimal128ToString(const decimal128 *d128, char *string){ + uInt msd; // coefficient MSD + Int exp; // exponent top two bits or full + uInt comb; // combination field + char *cstart; // coefficient start + char *c; // output pointer in string + const uByte *u; // work + char *s, *t; // .. (source, target) + Int dpd; // .. + Int pre, e; // .. + uInt uiwork; // for macros + + uInt sourar[4]; // source 128-bit + #define sourhi sourar[3] // name the word with the sign + #define sourmh sourar[2] // and the mid-high word + #define sourml sourar[1] // and the mod-low word + #define sourlo sourar[0] // and the lowest word + + // load source from storage; this is endian + if (DECLITEND) { + sourlo=UBTOUI(d128->bytes ); // directly load the low int + sourml=UBTOUI(d128->bytes+4 ); // then the mid-low + sourmh=UBTOUI(d128->bytes+8 ); // then the mid-high + sourhi=UBTOUI(d128->bytes+12); // then the high int + } + else { + sourhi=UBTOUI(d128->bytes ); // directly load the high int + sourmh=UBTOUI(d128->bytes+4 ); // then the mid-high + sourml=UBTOUI(d128->bytes+8 ); // then the mid-low + sourlo=UBTOUI(d128->bytes+12); // then the low int + } + + c=string; // where result will go + if (((Int)sourhi)<0) *c++='-'; // handle sign + + comb=(sourhi>>26)&0x1f; // combination field + msd=COMBMSD[comb]; // decode the combination field + exp=COMBEXP[comb]; // .. + + if (exp==3) { + if (msd==0) { // infinity + strcpy(c, "Inf"); + strcpy(c+3, "inity"); + return string; // easy + } + if (sourhi&0x02000000) *c++='s'; // sNaN + strcpy(c, "NaN"); // complete word + c+=3; // step past + if (sourlo==0 && sourml==0 && sourmh==0 + && (sourhi&0x0003ffff)==0) return string; // zero payload + // otherwise drop through to add integer; set correct exp + exp=0; msd=0; // setup for following code + } + else exp=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; // unbiased + + // convert 34 digits of significand to characters + cstart=c; // save start of coefficient + if (msd) *c++='0'+(char)msd; // non-zero most significant digit + + // Now decode the declets. After extracting each one, it is + // decoded to binary and then to a 4-char sequence by table lookup; + // the 4-chars are a 1-char length (significant digits, except 000 + // has length 0). This allows us to left-align the first declet + // with non-zero content, then remaining ones are full 3-char + // length. We use fixed-length memcpys because variable-length + // causes a subroutine call in GCC. (These are length 4 for speed + // and are safe because the array has an extra terminator byte.) + #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \ + if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ + else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} + dpd=(sourhi>>4)&0x3ff; // declet 1 + dpd2char; + dpd=((sourhi&0xf)<<6) | (sourmh>>26); // declet 2 + dpd2char; + dpd=(sourmh>>16)&0x3ff; // declet 3 + dpd2char; + dpd=(sourmh>>6)&0x3ff; // declet 4 + dpd2char; + dpd=((sourmh&0x3f)<<4) | (sourml>>28); // declet 5 + dpd2char; + dpd=(sourml>>18)&0x3ff; // declet 6 + dpd2char; + dpd=(sourml>>8)&0x3ff; // declet 7 + dpd2char; + dpd=((sourml&0xff)<<2) | (sourlo>>30); // declet 8 + dpd2char; + dpd=(sourlo>>20)&0x3ff; // declet 9 + dpd2char; + dpd=(sourlo>>10)&0x3ff; // declet 10 + dpd2char; + dpd=(sourlo)&0x3ff; // declet 11 + dpd2char; + + if (c==cstart) *c++='0'; // all zeros -- make 0 + + if (exp==0) { // integer or NaN case -- easy + *c='\0'; // terminate + return string; + } + + /* non-0 exponent */ + e=0; // assume no E + pre=c-cstart+exp; + // [here, pre-exp is the digits count (==1 for zero)] + if (exp>0 || pre<-5) { // need exponential form + e=pre-1; // calculate E value + pre=1; // assume one digit before '.' + } // exponential form + + /* modify the coefficient, adding 0s, '.', and E+nn as needed */ + s=c-1; // source (LSD) + if (pre>0) { // ddd.ddd (plain), perhaps with E + char *dotat=cstart+pre; + if (dotat=dotat; s--, t--) *t=*s; // open the gap; leave t at gap + *t='.'; // insert the dot + c++; // length increased by one + } + + // finally add the E-part, if needed; it will never be 0, and has + // a maximum length of 4 digits + if (e!=0) { + *c++='E'; // starts with E + *c++='+'; // assume positive + if (e<0) { + *(c-1)='-'; // oops, need '-' + e=-e; // uInt, please + } + if (e<1000) { // 3 (or fewer) digits case + u=&BIN2CHAR[e*4]; // -> length byte + memcpy(c, u+4-*u, 4); // copy fixed 4 characters [is safe] + c+=*u; // bump pointer appropriately + } + else { // 4-digits + Int thou=((e>>3)*1049)>>17; // e/1000 + Int rem=e-(1000*thou); // e%1000 + *c++='0'+(char)thou; + u=&BIN2CHAR[rem*4]; // -> length byte + memcpy(c, u+1, 4); // copy fixed 3+1 characters [is safe] + c+=3; // bump pointer, always 3 digits + } + } + *c='\0'; // add terminator + //printf("res %s\n", string); + return string; + } // pre>0 + + /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ + t=c+1-pre; + *(t+1)='\0'; // can add terminator now + for (; s>=cstart; s--, t--) *t=*s; // shift whole coefficient right + c=cstart; + *c++='0'; // always starts with 0. + *c++='.'; + for (; pre<0; pre++) *c++='0'; // add any 0's after '.' + //printf("res %s\n", string); + return string; + } // decimal128ToString + +/* ------------------------------------------------------------------ */ +/* to-number -- conversion from numeric string */ +/* */ +/* decimal128FromString(result, string, set); */ +/* */ +/* result is the decimal128 format number which gets the result of */ +/* the conversion */ +/* *string is the character string which should contain a valid */ +/* number (which may be a special value) */ +/* set is the context */ +/* */ +/* The context is supplied to this routine is used for error handling */ +/* (setting of status and traps) and for the rounding mode, only. */ +/* If an error occurs, the result will be a valid decimal128 NaN. */ +/* ------------------------------------------------------------------ */ +decimal128 * decimal128FromString(decimal128 *result, const char *string, + decContext *set) { + decContext dc; // work + decNumber dn; // .. + + decContextDefault(&dc, DEC_INIT_DECIMAL128); // no traps, please + dc.round=set->round; // use supplied rounding + + decNumberFromString(&dn, string, &dc); // will round if needed + decimal128FromNumber(result, &dn, &dc); + if (dc.status!=0) { // something happened + decContextSetStatus(set, dc.status); // .. pass it on + } + return result; + } // decimal128FromString + +/* ------------------------------------------------------------------ */ +/* decimal128IsCanonical -- test whether encoding is canonical */ +/* d128 is the source decimal128 */ +/* returns 1 if the encoding of d128 is canonical, 0 otherwise */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +uInt decimal128IsCanonical(const decimal128 *d128) { + decNumber dn; // work + decimal128 canon; // .. + decContext dc; // .. + decContextDefault(&dc, DEC_INIT_DECIMAL128); + decimal128ToNumber(d128, &dn); + decimal128FromNumber(&canon, &dn, &dc);// canon will now be canonical + return memcmp(d128, &canon, DECIMAL128_Bytes)==0; + } // decimal128IsCanonical + +/* ------------------------------------------------------------------ */ +/* decimal128Canonical -- copy an encoding, ensuring it is canonical */ +/* d128 is the source decimal128 */ +/* result is the target (may be the same decimal128) */ +/* returns result */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) { + decNumber dn; // work + decContext dc; // .. + decContextDefault(&dc, DEC_INIT_DECIMAL128); + decimal128ToNumber(d128, &dn); + decimal128FromNumber(result, &dn, &dc);// result will now be canonical + return result; + } // decimal128Canonical + +#if DECTRACE || DECCHECK +/* Macros for accessing decimal128 fields. These assume the argument + is a reference (pointer) to the decimal128 structure, and the + decimal128 is in network byte order (big-endian) */ +// Get sign +#define decimal128Sign(d) ((unsigned)(d)->bytes[0]>>7) + +// Get combination field +#define decimal128Comb(d) (((d)->bytes[0] & 0x7c)>>2) + +// Get exponent continuation [does not remove bias] +#define decimal128ExpCon(d) ((((d)->bytes[0] & 0x03)<<10) \ + | ((unsigned)(d)->bytes[1]<<2) \ + | ((unsigned)(d)->bytes[2]>>6)) + +// Set sign [this assumes sign previously 0] +#define decimal128SetSign(d, b) { \ + (d)->bytes[0]|=((unsigned)(b)<<7);} + +// Set exponent continuation [does not apply bias] +// This assumes range has been checked and exponent previously 0; +// type of exponent must be unsigned +#define decimal128SetExpCon(d, e) { \ + (d)->bytes[0]|=(uByte)((e)>>10); \ + (d)->bytes[1] =(uByte)(((e)&0x3fc)>>2); \ + (d)->bytes[2]|=(uByte)(((e)&0x03)<<6);} + +/* ------------------------------------------------------------------ */ +/* decimal128Show -- display a decimal128 in hexadecimal [debug aid] */ +/* d128 -- the number to show */ +/* ------------------------------------------------------------------ */ +// Also shows sign/cob/expconfields extracted +void decimal128Show(const decimal128 *d128) { + char buf[DECIMAL128_Bytes*2+1]; + Int i, j=0; + + if (DECLITEND) { + for (i=0; ibytes[15-i]); + } + printf(" D128> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf, + d128->bytes[15]>>7, (d128->bytes[15]>>2)&0x1f, + ((d128->bytes[15]&0x3)<<10)|(d128->bytes[14]<<2)| + (d128->bytes[13]>>6)); + } + else { + for (i=0; ibytes[i]); + } + printf(" D128> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf, + decimal128Sign(d128), decimal128Comb(d128), + decimal128ExpCon(d128)); + } + } // decimal128Show +#endif diff --git a/src/decNumber/decimal128.h b/src/decNumber/decimal128.h new file mode 100644 index 0000000000..47d2f8e6a2 --- /dev/null +++ b/src/decNumber/decimal128.h @@ -0,0 +1,81 @@ +/* ------------------------------------------------------------------ */ +/* Decimal 128-bit format module header */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is called decNumber.pdf. This document is */ +/* available, together with arithmetic and format specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ + +#if !defined(DECIMAL128) + #define DECIMAL128 + #define DEC128NAME "decimal128" /* Short name */ + #define DEC128FULLNAME "Decimal 128-bit Number" /* Verbose name */ + #define DEC128AUTHOR "Mike Cowlishaw" /* Who to blame */ + + /* parameters for decimal128s */ + #define DECIMAL128_Bytes 16 /* length */ + #define DECIMAL128_Pmax 34 /* maximum precision (digits) */ + #define DECIMAL128_Emax 6144 /* maximum adjusted exponent */ + #define DECIMAL128_Emin -6143 /* minimum adjusted exponent */ + #define DECIMAL128_Bias 6176 /* bias for the exponent */ + #define DECIMAL128_String 43 /* maximum string length, +1 */ + #define DECIMAL128_EconL 12 /* exp. continuation length */ + /* highest biased exponent (Elimit-1) */ + #define DECIMAL128_Ehigh (DECIMAL128_Emax+DECIMAL128_Bias-DECIMAL128_Pmax+1) + + /* check enough digits, if pre-defined */ + #if defined(DECNUMDIGITS) + #if (DECNUMDIGITS=34 for safe use + #endif + #endif + + #ifndef DECNUMDIGITS + #define DECNUMDIGITS DECIMAL128_Pmax /* size if not already defined*/ + #endif + #ifndef DECNUMBER + #include "decNumber.h" /* context and number library */ + #endif + + /* Decimal 128-bit type, accessible by bytes */ + typedef struct { + uint8_t bytes[DECIMAL128_Bytes]; /* decimal128: 1, 5, 12, 110 bits*/ + } decimal128; + + /* special values [top byte excluding sign bit; last two bits are */ + /* don't-care for Infinity on input, last bit don't-care for NaN] */ + #if !defined(DECIMAL_NaN) + #define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */ + #define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */ + #define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */ + #endif + + /* ---------------------------------------------------------------- */ + /* Routines */ + /* ---------------------------------------------------------------- */ + /* String conversions */ + decimal128 * decimal128FromString(decimal128 *, const char *, decContext *); + char * decimal128ToString(const decimal128 *, char *); + char * decimal128ToEngString(const decimal128 *, char *); + + /* decNumber conversions */ + decimal128 * decimal128FromNumber(decimal128 *, const decNumber *, + decContext *); + decNumber * decimal128ToNumber(const decimal128 *, decNumber *); + + /* Format-dependent utilities */ + uint32_t decimal128IsCanonical(const decimal128 *); + decimal128 * decimal128Canonical(decimal128 *, const decimal128 *); + +#endif diff --git a/src/decNumber/decimal32.c b/src/decNumber/decimal32.c new file mode 100644 index 0000000000..775cffd2cc --- /dev/null +++ b/src/decNumber/decimal32.c @@ -0,0 +1,476 @@ +/* ------------------------------------------------------------------ */ +/* Decimal 32-bit format module */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2008. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is called decNumber.pdf. This document is */ +/* available, together with arithmetic and format specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ +/* This module comprises the routines for decimal32 format numbers. */ +/* Conversions are supplied to and from decNumber and String. */ +/* */ +/* This is used when decNumber provides operations, either for all */ +/* operations or as a proxy between decNumber and decSingle. */ +/* */ +/* Error handling is the same as decNumber (qv.). */ +/* ------------------------------------------------------------------ */ +#include // [for memset/memcpy] +#include // [for printf] + +#define DECNUMDIGITS 7 // make decNumbers with space for 7 +#include "decNumber.h" // base number library +#include "decNumberLocal.h" // decNumber local types, etc. +#include "decimal32.h" // our primary include + +/* Utility tables and routines [in decimal64.c] */ +// DPD2BIN and the reverse are renamed to prevent link-time conflict +// if decQuad is also built in the same executable +#define DPD2BIN DPD2BINx +#define BIN2DPD BIN2DPDx +extern const uInt COMBEXP[32], COMBMSD[32]; +extern const uShort DPD2BIN[1024]; +extern const uShort BIN2DPD[1000]; +extern const uByte BIN2CHAR[4001]; + +extern void decDigitsToDPD(const decNumber *, uInt *, Int); +extern void decDigitsFromDPD(decNumber *, const uInt *, Int); + +#if DECTRACE || DECCHECK +void decimal32Show(const decimal32 *); // for debug +extern void decNumberShow(const decNumber *); // .. +#endif + +/* Useful macro */ +// Clear a structure (e.g., a decNumber) +#define DEC_clear(d) memset(d, 0, sizeof(*d)) + +/* ------------------------------------------------------------------ */ +/* decimal32FromNumber -- convert decNumber to decimal32 */ +/* */ +/* ds is the target decimal32 */ +/* dn is the source number (assumed valid) */ +/* set is the context, used only for reporting errors */ +/* */ +/* The set argument is used only for status reporting and for the */ +/* rounding mode (used if the coefficient is more than DECIMAL32_Pmax */ +/* digits or an overflow is detected). If the exponent is out of the */ +/* valid range then Overflow or Underflow will be raised. */ +/* After Underflow a subnormal result is possible. */ +/* */ +/* DEC_Clamped is set if the number has to be 'folded down' to fit, */ +/* by reducing its exponent and multiplying the coefficient by a */ +/* power of ten, or if the exponent on a zero had to be clamped. */ +/* ------------------------------------------------------------------ */ +decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn, + decContext *set) { + uInt status=0; // status accumulator + Int ae; // adjusted exponent + decNumber dw; // work + decContext dc; // .. + uInt comb, exp; // .. + uInt uiwork; // for macros + uInt targ=0; // target 32-bit + + // If the number has too many digits, or the exponent could be + // out of range then reduce the number under the appropriate + // constraints. This could push the number to Infinity or zero, + // so this check and rounding must be done before generating the + // decimal32] + ae=dn->exponent+dn->digits-1; // [0 if special] + if (dn->digits>DECIMAL32_Pmax // too many digits + || ae>DECIMAL32_Emax // likely overflow + || aeround; // use supplied rounding + decNumberPlus(&dw, dn, &dc); // (round and check) + // [this changes -0 to 0, so enforce the sign...] + dw.bits|=dn->bits&DECNEG; + status=dc.status; // save status + dn=&dw; // use the work number + } // maybe out of range + + if (dn->bits&DECSPECIAL) { // a special value + if (dn->bits&DECINF) targ=DECIMAL_Inf<<24; + else { // sNaN or qNaN + if ((*dn->lsu!=0 || dn->digits>1) // non-zero coefficient + && (dn->digitsbits&DECNAN) targ|=DECIMAL_NaN<<24; + else targ|=DECIMAL_sNaN<<24; + } // a NaN + } // special + + else { // is finite + if (decNumberIsZero(dn)) { // is a zero + // set and clamp exponent + if (dn->exponent<-DECIMAL32_Bias) { + exp=0; // low clamp + status|=DEC_Clamped; + } + else { + exp=dn->exponent+DECIMAL32_Bias; // bias exponent + if (exp>DECIMAL32_Ehigh) { // top clamp + exp=DECIMAL32_Ehigh; + status|=DEC_Clamped; + } + } + comb=(exp>>3) & 0x18; // msd=0, exp top 2 bits .. + } + else { // non-zero finite number + uInt msd; // work + Int pad=0; // coefficient pad digits + + // the dn is known to fit, but it may need to be padded + exp=(uInt)(dn->exponent+DECIMAL32_Bias); // bias exponent + if (exp>DECIMAL32_Ehigh) { // fold-down case + pad=exp-DECIMAL32_Ehigh; + exp=DECIMAL32_Ehigh; // [to maximum] + status|=DEC_Clamped; + } + + // fastpath common case + if (DECDPUN==3 && pad==0) { + targ=BIN2DPD[dn->lsu[0]]; + if (dn->digits>3) targ|=(uInt)(BIN2DPD[dn->lsu[1]])<<10; + msd=(dn->digits==7 ? dn->lsu[2] : 0); + } + else { // general case + decDigitsToDPD(dn, &targ, pad); + // save and clear the top digit + msd=targ>>20; + targ&=0x000fffff; + } + + // create the combination field + if (msd>=8) comb=0x18 | ((exp>>5) & 0x06) | (msd & 0x01); + else comb=((exp>>3) & 0x18) | msd; + } + targ|=comb<<26; // add combination field .. + targ|=(exp&0x3f)<<20; // .. and exponent continuation + } // finite + + if (dn->bits&DECNEG) targ|=0x80000000; // add sign bit + + // now write to storage; this is endian + UBFROMUI(d32->bytes, targ); // directly store the int + + if (status!=0) decContextSetStatus(set, status); // pass on status + // decimal32Show(d32); + return d32; + } // decimal32FromNumber + +/* ------------------------------------------------------------------ */ +/* decimal32ToNumber -- convert decimal32 to decNumber */ +/* d32 is the source decimal32 */ +/* dn is the target number, with appropriate space */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) { + uInt msd; // coefficient MSD + uInt exp; // exponent top two bits + uInt comb; // combination field + uInt sour; // source 32-bit + uInt uiwork; // for macros + + // load source from storage; this is endian + sour=UBTOUI(d32->bytes); // directly load the int + + comb=(sour>>26)&0x1f; // combination field + + decNumberZero(dn); // clean number + if (sour&0x80000000) dn->bits=DECNEG; // set sign if negative + + msd=COMBMSD[comb]; // decode the combination field + exp=COMBEXP[comb]; // .. + + if (exp==3) { // is a special + if (msd==0) { + dn->bits|=DECINF; + return dn; // no coefficient needed + } + else if (sour&0x02000000) dn->bits|=DECSNAN; + else dn->bits|=DECNAN; + msd=0; // no top digit + } + else { // is a finite number + dn->exponent=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; // unbiased + } + + // get the coefficient + sour&=0x000fffff; // clean coefficient continuation + if (msd) { // non-zero msd + sour|=msd<<20; // prefix to coefficient + decDigitsFromDPD(dn, &sour, 3); // process 3 declets + return dn; + } + // msd=0 + if (!sour) return dn; // easy: coefficient is 0 + if (sour&0x000ffc00) // need 2 declets? + decDigitsFromDPD(dn, &sour, 2); // process 2 declets + else + decDigitsFromDPD(dn, &sour, 1); // process 1 declet + return dn; + } // decimal32ToNumber + +/* ------------------------------------------------------------------ */ +/* to-scientific-string -- conversion to numeric string */ +/* to-engineering-string -- conversion to numeric string */ +/* */ +/* decimal32ToString(d32, string); */ +/* decimal32ToEngString(d32, string); */ +/* */ +/* d32 is the decimal32 format number to convert */ +/* string is the string where the result will be laid out */ +/* */ +/* string must be at least 24 characters */ +/* */ +/* No error is possible, and no status can be set. */ +/* ------------------------------------------------------------------ */ +char * decimal32ToEngString(const decimal32 *d32, char *string){ + decNumber dn; // work + decimal32ToNumber(d32, &dn); + decNumberToEngString(&dn, string); + return string; + } // decimal32ToEngString + +char * decimal32ToString(const decimal32 *d32, char *string){ + uInt msd; // coefficient MSD + Int exp; // exponent top two bits or full + uInt comb; // combination field + char *cstart; // coefficient start + char *c; // output pointer in string + const uByte *u; // work + char *s, *t; // .. (source, target) + Int dpd; // .. + Int pre, e; // .. + uInt uiwork; // for macros + uInt sour; // source 32-bit + + // load source from storage; this is endian + sour=UBTOUI(d32->bytes); // directly load the int + + c=string; // where result will go + if (((Int)sour)<0) *c++='-'; // handle sign + + comb=(sour>>26)&0x1f; // combination field + msd=COMBMSD[comb]; // decode the combination field + exp=COMBEXP[comb]; // .. + + if (exp==3) { + if (msd==0) { // infinity + strcpy(c, "Inf"); + strcpy(c+3, "inity"); + return string; // easy + } + if (sour&0x02000000) *c++='s'; // sNaN + strcpy(c, "NaN"); // complete word + c+=3; // step past + if ((sour&0x000fffff)==0) return string; // zero payload + // otherwise drop through to add integer; set correct exp + exp=0; msd=0; // setup for following code + } + else exp=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; // unbiased + + // convert 7 digits of significand to characters + cstart=c; // save start of coefficient + if (msd) *c++='0'+(char)msd; // non-zero most significant digit + + // Now decode the declets. After extracting each one, it is + // decoded to binary and then to a 4-char sequence by table lookup; + // the 4-chars are a 1-char length (significant digits, except 000 + // has length 0). This allows us to left-align the first declet + // with non-zero content, then remaining ones are full 3-char + // length. We use fixed-length memcpys because variable-length + // causes a subroutine call in GCC. (These are length 4 for speed + // and are safe because the array has an extra terminator byte.) + #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \ + if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ + else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} + + dpd=(sour>>10)&0x3ff; // declet 1 + dpd2char; + dpd=(sour)&0x3ff; // declet 2 + dpd2char; + + if (c==cstart) *c++='0'; // all zeros -- make 0 + + if (exp==0) { // integer or NaN case -- easy + *c='\0'; // terminate + return string; + } + + /* non-0 exponent */ + e=0; // assume no E + pre=c-cstart+exp; + // [here, pre-exp is the digits count (==1 for zero)] + if (exp>0 || pre<-5) { // need exponential form + e=pre-1; // calculate E value + pre=1; // assume one digit before '.' + } // exponential form + + /* modify the coefficient, adding 0s, '.', and E+nn as needed */ + s=c-1; // source (LSD) + if (pre>0) { // ddd.ddd (plain), perhaps with E + char *dotat=cstart+pre; + if (dotat=dotat; s--, t--) *t=*s; // open the gap; leave t at gap + *t='.'; // insert the dot + c++; // length increased by one + } + + // finally add the E-part, if needed; it will never be 0, and has + // a maximum length of 3 digits (E-101 case) + if (e!=0) { + *c++='E'; // starts with E + *c++='+'; // assume positive + if (e<0) { + *(c-1)='-'; // oops, need '-' + e=-e; // uInt, please + } + u=&BIN2CHAR[e*4]; // -> length byte + memcpy(c, u+4-*u, 4); // copy fixed 4 characters [is safe] + c+=*u; // bump pointer appropriately + } + *c='\0'; // add terminator + //printf("res %s\n", string); + return string; + } // pre>0 + + /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ + t=c+1-pre; + *(t+1)='\0'; // can add terminator now + for (; s>=cstart; s--, t--) *t=*s; // shift whole coefficient right + c=cstart; + *c++='0'; // always starts with 0. + *c++='.'; + for (; pre<0; pre++) *c++='0'; // add any 0's after '.' + //printf("res %s\n", string); + return string; + } // decimal32ToString + +/* ------------------------------------------------------------------ */ +/* to-number -- conversion from numeric string */ +/* */ +/* decimal32FromString(result, string, set); */ +/* */ +/* result is the decimal32 format number which gets the result of */ +/* the conversion */ +/* *string is the character string which should contain a valid */ +/* number (which may be a special value) */ +/* set is the context */ +/* */ +/* The context is supplied to this routine is used for error handling */ +/* (setting of status and traps) and for the rounding mode, only. */ +/* If an error occurs, the result will be a valid decimal32 NaN. */ +/* ------------------------------------------------------------------ */ +decimal32 * decimal32FromString(decimal32 *result, const char *string, + decContext *set) { + decContext dc; // work + decNumber dn; // .. + + decContextDefault(&dc, DEC_INIT_DECIMAL32); // no traps, please + dc.round=set->round; // use supplied rounding + + decNumberFromString(&dn, string, &dc); // will round if needed + decimal32FromNumber(result, &dn, &dc); + if (dc.status!=0) { // something happened + decContextSetStatus(set, dc.status); // .. pass it on + } + return result; + } // decimal32FromString + +/* ------------------------------------------------------------------ */ +/* decimal32IsCanonical -- test whether encoding is canonical */ +/* d32 is the source decimal32 */ +/* returns 1 if the encoding of d32 is canonical, 0 otherwise */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +uInt decimal32IsCanonical(const decimal32 *d32) { + decNumber dn; // work + decimal32 canon; // .. + decContext dc; // .. + decContextDefault(&dc, DEC_INIT_DECIMAL32); + decimal32ToNumber(d32, &dn); + decimal32FromNumber(&canon, &dn, &dc);// canon will now be canonical + return memcmp(d32, &canon, DECIMAL32_Bytes)==0; + } // decimal32IsCanonical + +/* ------------------------------------------------------------------ */ +/* decimal32Canonical -- copy an encoding, ensuring it is canonical */ +/* d32 is the source decimal32 */ +/* result is the target (may be the same decimal32) */ +/* returns result */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) { + decNumber dn; // work + decContext dc; // .. + decContextDefault(&dc, DEC_INIT_DECIMAL32); + decimal32ToNumber(d32, &dn); + decimal32FromNumber(result, &dn, &dc);// result will now be canonical + return result; + } // decimal32Canonical + +#if DECTRACE || DECCHECK +/* Macros for accessing decimal32 fields. These assume the argument + is a reference (pointer) to the decimal32 structure, and the + decimal32 is in network byte order (big-endian) */ +// Get sign +#define decimal32Sign(d) ((unsigned)(d)->bytes[0]>>7) + +// Get combination field +#define decimal32Comb(d) (((d)->bytes[0] & 0x7c)>>2) + +// Get exponent continuation [does not remove bias] +#define decimal32ExpCon(d) ((((d)->bytes[0] & 0x03)<<4) \ + | ((unsigned)(d)->bytes[1]>>4)) + +// Set sign [this assumes sign previously 0] +#define decimal32SetSign(d, b) { \ + (d)->bytes[0]|=((unsigned)(b)<<7);} + +// Set exponent continuation [does not apply bias] +// This assumes range has been checked and exponent previously 0; +// type of exponent must be unsigned +#define decimal32SetExpCon(d, e) { \ + (d)->bytes[0]|=(uByte)((e)>>4); \ + (d)->bytes[1]|=(uByte)(((e)&0x0F)<<4);} + +/* ------------------------------------------------------------------ */ +/* decimal32Show -- display a decimal32 in hexadecimal [debug aid] */ +/* d32 -- the number to show */ +/* ------------------------------------------------------------------ */ +// Also shows sign/cob/expconfields extracted - valid bigendian only +void decimal32Show(const decimal32 *d32) { + char buf[DECIMAL32_Bytes*2+1]; + Int i, j=0; + + if (DECLITEND) { + for (i=0; ibytes[3-i]); + } + printf(" D32> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf, + d32->bytes[3]>>7, (d32->bytes[3]>>2)&0x1f, + ((d32->bytes[3]&0x3)<<4)| (d32->bytes[2]>>4)); + } + else { + for (i=0; ibytes[i]); + } + printf(" D32> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf, + decimal32Sign(d32), decimal32Comb(d32), decimal32ExpCon(d32)); + } + } // decimal32Show +#endif diff --git a/src/decNumber/decimal32.h b/src/decNumber/decimal32.h new file mode 100644 index 0000000000..060640e66f --- /dev/null +++ b/src/decNumber/decimal32.h @@ -0,0 +1,81 @@ +/* ------------------------------------------------------------------ */ +/* Decimal 32-bit format module header */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2006. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is called decNumber.pdf. This document is */ +/* available, together with arithmetic and format specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ + +#if !defined(DECIMAL32) + #define DECIMAL32 + #define DEC32NAME "decimal32" /* Short name */ + #define DEC32FULLNAME "Decimal 32-bit Number" /* Verbose name */ + #define DEC32AUTHOR "Mike Cowlishaw" /* Who to blame */ + + /* parameters for decimal32s */ + #define DECIMAL32_Bytes 4 /* length */ + #define DECIMAL32_Pmax 7 /* maximum precision (digits) */ + #define DECIMAL32_Emax 96 /* maximum adjusted exponent */ + #define DECIMAL32_Emin -95 /* minimum adjusted exponent */ + #define DECIMAL32_Bias 101 /* bias for the exponent */ + #define DECIMAL32_String 15 /* maximum string length, +1 */ + #define DECIMAL32_EconL 6 /* exp. continuation length */ + /* highest biased exponent (Elimit-1) */ + #define DECIMAL32_Ehigh (DECIMAL32_Emax+DECIMAL32_Bias-DECIMAL32_Pmax+1) + + /* check enough digits, if pre-defined */ + #if defined(DECNUMDIGITS) + #if (DECNUMDIGITS=7 for safe use + #endif + #endif + + #ifndef DECNUMDIGITS + #define DECNUMDIGITS DECIMAL32_Pmax /* size if not already defined*/ + #endif + #ifndef DECNUMBER + #include "decNumber.h" /* context and number library */ + #endif + + /* Decimal 32-bit type, accessible by bytes */ + typedef struct { + uint8_t bytes[DECIMAL32_Bytes]; /* decimal32: 1, 5, 6, 20 bits*/ + } decimal32; + + /* special values [top byte excluding sign bit; last two bits are */ + /* don't-care for Infinity on input, last bit don't-care for NaN] */ + #if !defined(DECIMAL_NaN) + #define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */ + #define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */ + #define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */ + #endif + + /* ---------------------------------------------------------------- */ + /* Routines */ + /* ---------------------------------------------------------------- */ + /* String conversions */ + decimal32 * decimal32FromString(decimal32 *, const char *, decContext *); + char * decimal32ToString(const decimal32 *, char *); + char * decimal32ToEngString(const decimal32 *, char *); + + /* decNumber conversions */ + decimal32 * decimal32FromNumber(decimal32 *, const decNumber *, + decContext *); + decNumber * decimal32ToNumber(const decimal32 *, decNumber *); + + /* Format-dependent utilities */ + uint32_t decimal32IsCanonical(const decimal32 *); + decimal32 * decimal32Canonical(decimal32 *, const decimal32 *); + +#endif diff --git a/src/decNumber/decimal64.c b/src/decNumber/decimal64.c new file mode 100644 index 0000000000..a21f42fbe3 --- /dev/null +++ b/src/decNumber/decimal64.c @@ -0,0 +1,839 @@ +/* ------------------------------------------------------------------ */ +/* Decimal 64-bit format module */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2009. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is called decNumber.pdf. This document is */ +/* available, together with arithmetic and format specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ +/* This module comprises the routines for decimal64 format numbers. */ +/* Conversions are supplied to and from decNumber and String. */ +/* */ +/* This is used when decNumber provides operations, either for all */ +/* operations or as a proxy between decNumber and decSingle. */ +/* */ +/* Error handling is the same as decNumber (qv.). */ +/* ------------------------------------------------------------------ */ +#include // [for memset/memcpy] +#include // [for printf] + +#define DECNUMDIGITS 16 // make decNumbers with space for 16 +#include "decNumber.h" // base number library +#include "decNumberLocal.h" // decNumber local types, etc. +#include "decimal64.h" // our primary include + +/* Utility routines and tables [in decimal64.c]; externs for C++ */ +// DPD2BIN and the reverse are renamed to prevent link-time conflict +// if decQuad is also built in the same executable +#define DPD2BIN DPD2BINx +#define BIN2DPD BIN2DPDx +extern const uInt COMBEXP[32], COMBMSD[32]; +extern const uShort DPD2BIN[1024]; +extern const uShort BIN2DPD[1000]; +extern const uByte BIN2CHAR[4001]; + +extern void decDigitsFromDPD(decNumber *, const uInt *, Int); +extern void decDigitsToDPD(const decNumber *, uInt *, Int); + +#if DECTRACE || DECCHECK +void decimal64Show(const decimal64 *); // for debug +extern void decNumberShow(const decNumber *); // .. +#endif + +/* Useful macro */ +// Clear a structure (e.g., a decNumber) +#define DEC_clear(d) memset(d, 0, sizeof(*d)) + +/* define and include the tables to use for conversions */ +#define DEC_BIN2CHAR 1 +#define DEC_DPD2BIN 1 +#define DEC_BIN2DPD 1 // used for all sizes +#include "decDPD.h" // lookup tables + +/* ------------------------------------------------------------------ */ +/* decimal64FromNumber -- convert decNumber to decimal64 */ +/* */ +/* ds is the target decimal64 */ +/* dn is the source number (assumed valid) */ +/* set is the context, used only for reporting errors */ +/* */ +/* The set argument is used only for status reporting and for the */ +/* rounding mode (used if the coefficient is more than DECIMAL64_Pmax */ +/* digits or an overflow is detected). If the exponent is out of the */ +/* valid range then Overflow or Underflow will be raised. */ +/* After Underflow a subnormal result is possible. */ +/* */ +/* DEC_Clamped is set if the number has to be 'folded down' to fit, */ +/* by reducing its exponent and multiplying the coefficient by a */ +/* power of ten, or if the exponent on a zero had to be clamped. */ +/* ------------------------------------------------------------------ */ +decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn, + decContext *set) { + uInt status=0; // status accumulator + Int ae; // adjusted exponent + decNumber dw; // work + decContext dc; // .. + uInt comb, exp; // .. + uInt uiwork; // for macros + uInt targar[2]={0, 0}; // target 64-bit + #define targhi targar[1] // name the word with the sign + #define targlo targar[0] // and the other + + // If the number has too many digits, or the exponent could be + // out of range then reduce the number under the appropriate + // constraints. This could push the number to Infinity or zero, + // so this check and rounding must be done before generating the + // decimal64] + ae=dn->exponent+dn->digits-1; // [0 if special] + if (dn->digits>DECIMAL64_Pmax // too many digits + || ae>DECIMAL64_Emax // likely overflow + || aeround; // use supplied rounding + decNumberPlus(&dw, dn, &dc); // (round and check) + // [this changes -0 to 0, so enforce the sign...] + dw.bits|=dn->bits&DECNEG; + status=dc.status; // save status + dn=&dw; // use the work number + } // maybe out of range + + if (dn->bits&DECSPECIAL) { // a special value + if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24; + else { // sNaN or qNaN + if ((*dn->lsu!=0 || dn->digits>1) // non-zero coefficient + && (dn->digitsbits&DECNAN) targhi|=DECIMAL_NaN<<24; + else targhi|=DECIMAL_sNaN<<24; + } // a NaN + } // special + + else { // is finite + if (decNumberIsZero(dn)) { // is a zero + // set and clamp exponent + if (dn->exponent<-DECIMAL64_Bias) { + exp=0; // low clamp + status|=DEC_Clamped; + } + else { + exp=dn->exponent+DECIMAL64_Bias; // bias exponent + if (exp>DECIMAL64_Ehigh) { // top clamp + exp=DECIMAL64_Ehigh; + status|=DEC_Clamped; + } + } + comb=(exp>>5) & 0x18; // msd=0, exp top 2 bits .. + } + else { // non-zero finite number + uInt msd; // work + Int pad=0; // coefficient pad digits + + // the dn is known to fit, but it may need to be padded + exp=(uInt)(dn->exponent+DECIMAL64_Bias); // bias exponent + if (exp>DECIMAL64_Ehigh) { // fold-down case + pad=exp-DECIMAL64_Ehigh; + exp=DECIMAL64_Ehigh; // [to maximum] + status|=DEC_Clamped; + } + + // fastpath common case + if (DECDPUN==3 && pad==0) { + uInt dpd[6]={0,0,0,0,0,0}; + uInt i; + Int d=dn->digits; + for (i=0; d>0; i++, d-=3) dpd[i]=BIN2DPD[dn->lsu[i]]; + targlo =dpd[0]; + targlo|=dpd[1]<<10; + targlo|=dpd[2]<<20; + if (dn->digits>6) { + targlo|=dpd[3]<<30; + targhi =dpd[3]>>2; + targhi|=dpd[4]<<8; + } + msd=dpd[5]; // [did not really need conversion] + } + else { // general case + decDigitsToDPD(dn, targar, pad); + // save and clear the top digit + msd=targhi>>18; + targhi&=0x0003ffff; + } + + // create the combination field + if (msd>=8) comb=0x18 | ((exp>>7) & 0x06) | (msd & 0x01); + else comb=((exp>>5) & 0x18) | msd; + } + targhi|=comb<<26; // add combination field .. + targhi|=(exp&0xff)<<18; // .. and exponent continuation + } // finite + + if (dn->bits&DECNEG) targhi|=0x80000000; // add sign bit + + // now write to storage; this is now always endian + if (DECLITEND) { + // lo int then hi + UBFROMUI(d64->bytes, targar[0]); + UBFROMUI(d64->bytes+4, targar[1]); + } + else { + // hi int then lo + UBFROMUI(d64->bytes, targar[1]); + UBFROMUI(d64->bytes+4, targar[0]); + } + + if (status!=0) decContextSetStatus(set, status); // pass on status + // decimal64Show(d64); + return d64; + } // decimal64FromNumber + +/* ------------------------------------------------------------------ */ +/* decimal64ToNumber -- convert decimal64 to decNumber */ +/* d64 is the source decimal64 */ +/* dn is the target number, with appropriate space */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) { + uInt msd; // coefficient MSD + uInt exp; // exponent top two bits + uInt comb; // combination field + Int need; // work + uInt uiwork; // for macros + uInt sourar[2]; // source 64-bit + #define sourhi sourar[1] // name the word with the sign + #define sourlo sourar[0] // and the lower word + + // load source from storage; this is endian + if (DECLITEND) { + sourlo=UBTOUI(d64->bytes ); // directly load the low int + sourhi=UBTOUI(d64->bytes+4); // then the high int + } + else { + sourhi=UBTOUI(d64->bytes ); // directly load the high int + sourlo=UBTOUI(d64->bytes+4); // then the low int + } + + comb=(sourhi>>26)&0x1f; // combination field + + decNumberZero(dn); // clean number + if (sourhi&0x80000000) dn->bits=DECNEG; // set sign if negative + + msd=COMBMSD[comb]; // decode the combination field + exp=COMBEXP[comb]; // .. + + if (exp==3) { // is a special + if (msd==0) { + dn->bits|=DECINF; + return dn; // no coefficient needed + } + else if (sourhi&0x02000000) dn->bits|=DECSNAN; + else dn->bits|=DECNAN; + msd=0; // no top digit + } + else { // is a finite number + dn->exponent=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; // unbiased + } + + // get the coefficient + sourhi&=0x0003ffff; // clean coefficient continuation + if (msd) { // non-zero msd + sourhi|=msd<<18; // prefix to coefficient + need=6; // process 6 declets + } + else { // msd=0 + if (!sourhi) { // top word 0 + if (!sourlo) return dn; // easy: coefficient is 0 + need=3; // process at least 3 declets + if (sourlo&0xc0000000) need++; // process 4 declets + // [could reduce some more, here] + } + else { // some bits in top word, msd=0 + need=4; // process at least 4 declets + if (sourhi&0x0003ff00) need++; // top declet!=0, process 5 + } + } //msd=0 + + decDigitsFromDPD(dn, sourar, need); // process declets + return dn; + } // decimal64ToNumber + + +/* ------------------------------------------------------------------ */ +/* to-scientific-string -- conversion to numeric string */ +/* to-engineering-string -- conversion to numeric string */ +/* */ +/* decimal64ToString(d64, string); */ +/* decimal64ToEngString(d64, string); */ +/* */ +/* d64 is the decimal64 format number to convert */ +/* string is the string where the result will be laid out */ +/* */ +/* string must be at least 24 characters */ +/* */ +/* No error is possible, and no status can be set. */ +/* ------------------------------------------------------------------ */ +char * decimal64ToEngString(const decimal64 *d64, char *string){ + decNumber dn; // work + decimal64ToNumber(d64, &dn); + decNumberToEngString(&dn, string); + return string; + } // decimal64ToEngString + +char * decimal64ToString(const decimal64 *d64, char *string){ + uInt msd; // coefficient MSD + Int exp; // exponent top two bits or full + uInt comb; // combination field + char *cstart; // coefficient start + char *c; // output pointer in string + const uByte *u; // work + char *s, *t; // .. (source, target) + Int dpd; // .. + Int pre, e; // .. + uInt uiwork; // for macros + + uInt sourar[2]; // source 64-bit + #define sourhi sourar[1] // name the word with the sign + #define sourlo sourar[0] // and the lower word + + // load source from storage; this is endian + if (DECLITEND) { + sourlo=UBTOUI(d64->bytes ); // directly load the low int + sourhi=UBTOUI(d64->bytes+4); // then the high int + } + else { + sourhi=UBTOUI(d64->bytes ); // directly load the high int + sourlo=UBTOUI(d64->bytes+4); // then the low int + } + + c=string; // where result will go + if (((Int)sourhi)<0) *c++='-'; // handle sign + + comb=(sourhi>>26)&0x1f; // combination field + msd=COMBMSD[comb]; // decode the combination field + exp=COMBEXP[comb]; // .. + + if (exp==3) { + if (msd==0) { // infinity + strcpy(c, "Inf"); + strcpy(c+3, "inity"); + return string; // easy + } + if (sourhi&0x02000000) *c++='s'; // sNaN + strcpy(c, "NaN"); // complete word + c+=3; // step past + if (sourlo==0 && (sourhi&0x0003ffff)==0) return string; // zero payload + // otherwise drop through to add integer; set correct exp + exp=0; msd=0; // setup for following code + } + else exp=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; + + // convert 16 digits of significand to characters + cstart=c; // save start of coefficient + if (msd) *c++='0'+(char)msd; // non-zero most significant digit + + // Now decode the declets. After extracting each one, it is + // decoded to binary and then to a 4-char sequence by table lookup; + // the 4-chars are a 1-char length (significant digits, except 000 + // has length 0). This allows us to left-align the first declet + // with non-zero content, then remaining ones are full 3-char + // length. We use fixed-length memcpys because variable-length + // causes a subroutine call in GCC. (These are length 4 for speed + // and are safe because the array has an extra terminator byte.) + #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \ + if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ + else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} + + dpd=(sourhi>>8)&0x3ff; // declet 1 + dpd2char; + dpd=((sourhi&0xff)<<2) | (sourlo>>30); // declet 2 + dpd2char; + dpd=(sourlo>>20)&0x3ff; // declet 3 + dpd2char; + dpd=(sourlo>>10)&0x3ff; // declet 4 + dpd2char; + dpd=(sourlo)&0x3ff; // declet 5 + dpd2char; + + if (c==cstart) *c++='0'; // all zeros -- make 0 + + if (exp==0) { // integer or NaN case -- easy + *c='\0'; // terminate + return string; + } + + /* non-0 exponent */ + e=0; // assume no E + pre=c-cstart+exp; + // [here, pre-exp is the digits count (==1 for zero)] + if (exp>0 || pre<-5) { // need exponential form + e=pre-1; // calculate E value + pre=1; // assume one digit before '.' + } // exponential form + + /* modify the coefficient, adding 0s, '.', and E+nn as needed */ + s=c-1; // source (LSD) + if (pre>0) { // ddd.ddd (plain), perhaps with E + char *dotat=cstart+pre; + if (dotat=dotat; s--, t--) *t=*s; // open the gap; leave t at gap + *t='.'; // insert the dot + c++; // length increased by one + } + + // finally add the E-part, if needed; it will never be 0, and has + // a maximum length of 3 digits + if (e!=0) { + *c++='E'; // starts with E + *c++='+'; // assume positive + if (e<0) { + *(c-1)='-'; // oops, need '-' + e=-e; // uInt, please + } + u=&BIN2CHAR[e*4]; // -> length byte + memcpy(c, u+4-*u, 4); // copy fixed 4 characters [is safe] + c+=*u; // bump pointer appropriately + } + *c='\0'; // add terminator + //printf("res %s\n", string); + return string; + } // pre>0 + + /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ + t=c+1-pre; + *(t+1)='\0'; // can add terminator now + for (; s>=cstart; s--, t--) *t=*s; // shift whole coefficient right + c=cstart; + *c++='0'; // always starts with 0. + *c++='.'; + for (; pre<0; pre++) *c++='0'; // add any 0's after '.' + //printf("res %s\n", string); + return string; + } // decimal64ToString + +/* ------------------------------------------------------------------ */ +/* to-number -- conversion from numeric string */ +/* */ +/* decimal64FromString(result, string, set); */ +/* */ +/* result is the decimal64 format number which gets the result of */ +/* the conversion */ +/* *string is the character string which should contain a valid */ +/* number (which may be a special value) */ +/* set is the context */ +/* */ +/* The context is supplied to this routine is used for error handling */ +/* (setting of status and traps) and for the rounding mode, only. */ +/* If an error occurs, the result will be a valid decimal64 NaN. */ +/* ------------------------------------------------------------------ */ +decimal64 * decimal64FromString(decimal64 *result, const char *string, + decContext *set) { + decContext dc; // work + decNumber dn; // .. + + decContextDefault(&dc, DEC_INIT_DECIMAL64); // no traps, please + dc.round=set->round; // use supplied rounding + + decNumberFromString(&dn, string, &dc); // will round if needed + + decimal64FromNumber(result, &dn, &dc); + if (dc.status!=0) { // something happened + decContextSetStatus(set, dc.status); // .. pass it on + } + return result; + } // decimal64FromString + +/* ------------------------------------------------------------------ */ +/* decimal64IsCanonical -- test whether encoding is canonical */ +/* d64 is the source decimal64 */ +/* returns 1 if the encoding of d64 is canonical, 0 otherwise */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +uInt decimal64IsCanonical(const decimal64 *d64) { + decNumber dn; // work + decimal64 canon; // .. + decContext dc; // .. + decContextDefault(&dc, DEC_INIT_DECIMAL64); + decimal64ToNumber(d64, &dn); + decimal64FromNumber(&canon, &dn, &dc);// canon will now be canonical + return memcmp(d64, &canon, DECIMAL64_Bytes)==0; + } // decimal64IsCanonical + +/* ------------------------------------------------------------------ */ +/* decimal64Canonical -- copy an encoding, ensuring it is canonical */ +/* d64 is the source decimal64 */ +/* result is the target (may be the same decimal64) */ +/* returns result */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decimal64 * decimal64Canonical(decimal64 *result, const decimal64 *d64) { + decNumber dn; // work + decContext dc; // .. + decContextDefault(&dc, DEC_INIT_DECIMAL64); + decimal64ToNumber(d64, &dn); + decimal64FromNumber(result, &dn, &dc);// result will now be canonical + return result; + } // decimal64Canonical + +#if DECTRACE || DECCHECK +/* Macros for accessing decimal64 fields. These assume the + argument is a reference (pointer) to the decimal64 structure, + and the decimal64 is in network byte order (big-endian) */ +// Get sign +#define decimal64Sign(d) ((unsigned)(d)->bytes[0]>>7) + +// Get combination field +#define decimal64Comb(d) (((d)->bytes[0] & 0x7c)>>2) + +// Get exponent continuation [does not remove bias] +#define decimal64ExpCon(d) ((((d)->bytes[0] & 0x03)<<6) \ + | ((unsigned)(d)->bytes[1]>>2)) + +// Set sign [this assumes sign previously 0] +#define decimal64SetSign(d, b) { \ + (d)->bytes[0]|=((unsigned)(b)<<7);} + +// Set exponent continuation [does not apply bias] +// This assumes range has been checked and exponent previously 0; +// type of exponent must be unsigned +#define decimal64SetExpCon(d, e) { \ + (d)->bytes[0]|=(uByte)((e)>>6); \ + (d)->bytes[1]|=(uByte)(((e)&0x3F)<<2);} + +/* ------------------------------------------------------------------ */ +/* decimal64Show -- display a decimal64 in hexadecimal [debug aid] */ +/* d64 -- the number to show */ +/* ------------------------------------------------------------------ */ +// Also shows sign/cob/expconfields extracted +void decimal64Show(const decimal64 *d64) { + char buf[DECIMAL64_Bytes*2+1]; + Int i, j=0; + + if (DECLITEND) { + for (i=0; ibytes[7-i]); + } + printf(" D64> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf, + d64->bytes[7]>>7, (d64->bytes[7]>>2)&0x1f, + ((d64->bytes[7]&0x3)<<6)| (d64->bytes[6]>>2)); + } + else { // big-endian + for (i=0; ibytes[i]); + } + printf(" D64> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf, + decimal64Sign(d64), decimal64Comb(d64), decimal64ExpCon(d64)); + } + } // decimal64Show +#endif + +/* ================================================================== */ +/* Shared utility routines and tables */ +/* ================================================================== */ +// define and include the conversion tables to use for shared code +#if DECDPUN==3 + #define DEC_DPD2BIN 1 +#else + #define DEC_DPD2BCD 1 +#endif +#include "decDPD.h" // lookup tables + +// The maximum number of decNumberUnits needed for a working copy of +// the units array is the ceiling of digits/DECDPUN, where digits is +// the maximum number of digits in any of the formats for which this +// is used. decimal128.h must not be included in this module, so, as +// a very special case, that number is defined as a literal here. +#define DECMAX754 34 +#define DECMAXUNITS ((DECMAX754+DECDPUN-1)/DECDPUN) + +/* ------------------------------------------------------------------ */ +/* Combination field lookup tables (uInts to save measurable work) */ +/* */ +/* COMBEXP - 2-bit most-significant-bits of exponent */ +/* [11 if an Infinity or NaN] */ +/* COMBMSD - 4-bit most-significant-digit */ +/* [0=Infinity, 1=NaN if COMBEXP=11] */ +/* */ +/* Both are indexed by the 5-bit combination field (0-31) */ +/* ------------------------------------------------------------------ */ +const uInt COMBEXP[32]={0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 1, 1, 2, 2, 3, 3}; +const uInt COMBMSD[32]={0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 8, 9, 8, 9, 0, 1}; + +/* ------------------------------------------------------------------ */ +/* decDigitsToDPD -- pack coefficient into DPD form */ +/* */ +/* dn is the source number (assumed valid, max DECMAX754 digits) */ +/* targ is 1, 2, or 4-element uInt array, which the caller must */ +/* have cleared to zeros */ +/* shift is the number of 0 digits to add on the right (normally 0) */ +/* */ +/* The coefficient must be known small enough to fit. The full */ +/* coefficient is copied, including the leading 'odd' digit. This */ +/* digit is retrieved and packed into the combination field by the */ +/* caller. */ +/* */ +/* The target uInts are altered only as necessary to receive the */ +/* digits of the decNumber. When more than one uInt is needed, they */ +/* are filled from left to right (that is, the uInt at offset 0 will */ +/* end up with the least-significant digits). */ +/* */ +/* shift is used for 'fold-down' padding. */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +#if DECDPUN<=4 +// Constant multipliers for divide-by-power-of five using reciprocal +// multiply, after removing powers of 2 by shifting, and final shift +// of 17 [we only need up to **4] +static const uInt multies[]={131073, 26215, 5243, 1049, 210}; +// QUOT10 -- macro to return the quotient of unit u divided by 10**n +#define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17) +#endif +void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) { + Int cut; // work + Int n; // output bunch counter + Int digits=dn->digits; // digit countdown + uInt dpd; // densely packed decimal value + uInt bin; // binary value 0-999 + uInt *uout=targ; // -> current output uInt + uInt uoff=0; // -> current output offset [from right] + const Unit *inu=dn->lsu; // -> current input unit + Unit uar[DECMAXUNITS]; // working copy of units, iff shifted + #if DECDPUN!=3 // not fast path + Unit in; // current unit + #endif + + if (shift!=0) { // shift towards most significant required + // shift the units array to the left by pad digits and copy + // [this code is a special case of decShiftToMost, which could + // be used instead if exposed and the array were copied first] + const Unit *source; // .. + Unit *target, *first; // .. + uInt next=0; // work + + source=dn->lsu+D2U(digits)-1; // where msu comes from + target=uar+D2U(digits)-1+D2U(shift);// where upper part of first cut goes + cut=DECDPUN-MSUDIGITS(shift); // where to slice + if (cut==0) { // unit-boundary case + for (; source>=dn->lsu; source--, target--) *target=*source; + } + else { + first=uar+D2U(digits+shift)-1; // where msu will end up + for (; source>=dn->lsu; source--, target--) { + // split the source Unit and accumulate remainder for next + #if DECDPUN<=4 + uInt quot=QUOT10(*source, cut); + uInt rem=*source-quot*DECPOWERS[cut]; + next+=quot; + #else + uInt rem=*source%DECPOWERS[cut]; + next+=*source/DECPOWERS[cut]; + #endif + if (target<=first) *target=(Unit)next; // write to target iff valid + next=rem*DECPOWERS[DECDPUN-cut]; // save remainder for next Unit + } + } // shift-move + // propagate remainder to one below and clear the rest + for (; target>=uar; target--) { + *target=(Unit)next; + next=0; + } + digits+=shift; // add count (shift) of zeros added + inu=uar; // use units in working array + } + + /* now densely pack the coefficient into DPD declets */ + + #if DECDPUN!=3 // not fast path + in=*inu; // current unit + cut=0; // at lowest digit + bin=0; // [keep compiler quiet] + #endif + + for(n=0; digits>0; n++) { // each output bunch + #if DECDPUN==3 // fast path, 3-at-a-time + bin=*inu; // 3 digits ready for convert + digits-=3; // [may go negative] + inu++; // may need another + + #else // must collect digit-by-digit + Unit dig; // current digit + Int j; // digit-in-declet count + for (j=0; j<3; j++) { + #if DECDPUN<=4 + Unit temp=(Unit)((uInt)(in*6554)>>16); + dig=(Unit)(in-X10(temp)); + in=temp; + #else + dig=in%10; + in=in/10; + #endif + if (j==0) bin=dig; + else if (j==1) bin+=X10(dig); + else /* j==2 */ bin+=X100(dig); + digits--; + if (digits==0) break; // [also protects *inu below] + cut++; + if (cut==DECDPUN) {inu++; in=*inu; cut=0;} + } + #endif + // here there are 3 digits in bin, or have used all input digits + + dpd=BIN2DPD[bin]; + + // write declet to uInt array + *uout|=dpd<>(10-uoff); // collect top bits + } // n declets + return; + } // decDigitsToDPD + +/* ------------------------------------------------------------------ */ +/* decDigitsFromDPD -- unpack a format's coefficient */ +/* */ +/* dn is the target number, with 7, 16, or 34-digit space. */ +/* sour is a 1, 2, or 4-element uInt array containing only declets */ +/* declets is the number of (right-aligned) declets in sour to */ +/* be processed. This may be 1 more than the obvious number in */ +/* a format, as any top digit is prefixed to the coefficient */ +/* continuation field. It also may be as small as 1, as the */ +/* caller may pre-process leading zero declets. */ +/* */ +/* When doing the 'extra declet' case care is taken to avoid writing */ +/* extra digits when there are leading zeros, as these could overflow */ +/* the units array when DECDPUN is not 3. */ +/* */ +/* The target uInts are used only as necessary to process declets */ +/* declets into the decNumber. When more than one uInt is needed, */ +/* they are used from left to right (that is, the uInt at offset 0 */ +/* provides the least-significant digits). */ +/* */ +/* dn->digits is set, but not the sign or exponent. */ +/* No error is possible [the redundant 888 codes are allowed]. */ +/* ------------------------------------------------------------------ */ +void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) { + + uInt dpd; // collector for 10 bits + Int n; // counter + Unit *uout=dn->lsu; // -> current output unit + Unit *last=uout; // will be unit containing msd + const uInt *uin=sour; // -> current input uInt + uInt uoff=0; // -> current input offset [from right] + + #if DECDPUN!=3 + uInt bcd; // BCD result + uInt nibble; // work + Unit out=0; // accumulator + Int cut=0; // power of ten in current unit + #endif + #if DECDPUN>4 + uInt const *pow; // work + #endif + + // Expand the densely-packed integer, right to left + for (n=declets-1; n>=0; n--) { // count down declets of 10 bits + dpd=*uin>>uoff; + uoff+=10; + if (uoff>32) { // crossed uInt boundary + uin++; + uoff-=32; // [if using this code for wider, check this] + dpd|=*uin<<(10-uoff); // get waiting bits + } + dpd&=0x3ff; // clear uninteresting bits + + #if DECDPUN==3 + if (dpd==0) *uout=0; + else { + *uout=DPD2BIN[dpd]; // convert 10 bits to binary 0-999 + last=uout; // record most significant unit + } + uout++; + } // n + + #else // DECDPUN!=3 + if (dpd==0) { // fastpath [e.g., leading zeros] + // write out three 0 digits (nibbles); out may have digit(s) + cut++; + if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} + if (n==0) break; // [as below, works even if MSD=0] + cut++; + if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} + cut++; + if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} + continue; + } + + bcd=DPD2BCD[dpd]; // convert 10 bits to 12 bits BCD + + // now accumulate the 3 BCD nibbles into units + nibble=bcd & 0x00f; + if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]); + cut++; + if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} + bcd>>=4; + + // if this is the last declet and the remaining nibbles in bcd + // are 00 then process no more nibbles, because this could be + // the 'odd' MSD declet and writing any more Units would then + // overflow the unit array + if (n==0 && !bcd) break; + + nibble=bcd & 0x00f; + if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]); + cut++; + if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} + bcd>>=4; + + nibble=bcd & 0x00f; + if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]); + cut++; + if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} + } // n + if (cut!=0) { // some more left over + *uout=out; // write out final unit + if (out) last=uout; // and note if non-zero + } + #endif + + // here, last points to the most significant unit with digits; + // inspect it to get the final digits count -- this is essentially + // the same code as decGetDigits in decNumber.c + dn->digits=(last-dn->lsu)*DECDPUN+1; // floor of digits, plus + // must be at least 1 digit + #if DECDPUN>1 + if (*last<10) return; // common odd digit or 0 + dn->digits++; // must be 2 at least + #if DECDPUN>2 + if (*last<100) return; // 10-99 + dn->digits++; // must be 3 at least + #if DECDPUN>3 + if (*last<1000) return; // 100-999 + dn->digits++; // must be 4 at least + #if DECDPUN>4 + for (pow=&DECPOWERS[4]; *last>=*pow; pow++) dn->digits++; + #endif + #endif + #endif + #endif + return; + } //decDigitsFromDPD diff --git a/src/decNumber/decimal64.h b/src/decNumber/decimal64.h new file mode 100644 index 0000000000..19a1b5edef --- /dev/null +++ b/src/decNumber/decimal64.h @@ -0,0 +1,83 @@ +/* ------------------------------------------------------------------ */ +/* Decimal 64-bit format module header */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */ +/* */ +/* This software is made available under the terms of the */ +/* ICU License -- ICU 1.8.1 and later. */ +/* */ +/* The description and User's Guide ("The decNumber C Library") for */ +/* this software is called decNumber.pdf. This document is */ +/* available, together with arithmetic and format specifications, */ +/* testcases, and Web links, on the General Decimal Arithmetic page. */ +/* */ +/* Please send comments, suggestions, and corrections to the author: */ +/* mfc@uk.ibm.com */ +/* Mike Cowlishaw, IBM Fellow */ +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ +/* ------------------------------------------------------------------ */ + +#if !defined(DECIMAL64) + #define DECIMAL64 + #define DEC64NAME "decimal64" /* Short name */ + #define DEC64FULLNAME "Decimal 64-bit Number" /* Verbose name */ + #define DEC64AUTHOR "Mike Cowlishaw" /* Who to blame */ + + + /* parameters for decimal64s */ + #define DECIMAL64_Bytes 8 /* length */ + #define DECIMAL64_Pmax 16 /* maximum precision (digits) */ + #define DECIMAL64_Emax 384 /* maximum adjusted exponent */ + #define DECIMAL64_Emin -383 /* minimum adjusted exponent */ + #define DECIMAL64_Bias 398 /* bias for the exponent */ + #define DECIMAL64_String 24 /* maximum string length, +1 */ + #define DECIMAL64_EconL 8 /* exp. continuation length */ + /* highest biased exponent (Elimit-1) */ + #define DECIMAL64_Ehigh (DECIMAL64_Emax+DECIMAL64_Bias-DECIMAL64_Pmax+1) + + /* check enough digits, if pre-defined */ + #if defined(DECNUMDIGITS) + #if (DECNUMDIGITS=16 for safe use + #endif + #endif + + + #ifndef DECNUMDIGITS + #define DECNUMDIGITS DECIMAL64_Pmax /* size if not already defined*/ + #endif + #ifndef DECNUMBER + #include "decNumber.h" /* context and number library */ + #endif + + /* Decimal 64-bit type, accessible by bytes */ + typedef struct { + uint8_t bytes[DECIMAL64_Bytes]; /* decimal64: 1, 5, 8, 50 bits*/ + } decimal64; + + /* special values [top byte excluding sign bit; last two bits are */ + /* don't-care for Infinity on input, last bit don't-care for NaN] */ + #if !defined(DECIMAL_NaN) + #define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */ + #define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */ + #define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */ + #endif + + /* ---------------------------------------------------------------- */ + /* Routines */ + /* ---------------------------------------------------------------- */ + /* String conversions */ + decimal64 * decimal64FromString(decimal64 *, const char *, decContext *); + char * decimal64ToString(const decimal64 *, char *); + char * decimal64ToEngString(const decimal64 *, char *); + + /* decNumber conversions */ + decimal64 * decimal64FromNumber(decimal64 *, const decNumber *, + decContext *); + decNumber * decimal64ToNumber(const decimal64 *, decNumber *); + + /* Format-dependent utilities */ + uint32_t decimal64IsCanonical(const decimal64 *); + decimal64 * decimal64Canonical(decimal64 *, const decimal64 *); + +#endif diff --git a/src/decNumber/decnumber.pdf b/src/decNumber/decnumber.pdf new file mode 100644 index 0000000000..f601105beb Binary files /dev/null and b/src/decNumber/decnumber.pdf differ diff --git a/src/decNumber/example1.c b/src/decNumber/example1.c new file mode 100644 index 0000000000..c204b7ec11 --- /dev/null +++ b/src/decNumber/example1.c @@ -0,0 +1,38 @@ +/* ------------------------------------------------------------------ */ +/* Decimal Number Library Demonstration program */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2001, 2007. All rights reserved. */ +/* ----------------------------------------------------------------+- */ +/* right margin -->| */ + +// example1.c -- convert the first two argument words to decNumber, +// add them together, and display the result + +#define DECNUMDIGITS 34 // work with up to 34 digits +#include "decNumber.h" // base number library +#include // for printf + +int main(int argc, char *argv[]) { + decNumber a, b; // working numbers + decContext set; // working context + char string[DECNUMDIGITS+14]; // conversion buffer + + decContextTestEndian(0); // warn if DECLITEND is wrong + + if (argc<3) { // not enough words + printf("Please supply two numbers to add.\n"); + return 1; + } + decContextDefault(&set, DEC_INIT_BASE); // initialize + set.traps=0; // no traps, thank you + set.digits=DECNUMDIGITS; // set precision + + decNumberFromString(&a, argv[1], &set); + decNumberFromString(&b, argv[2], &set); + + decNumberAdd(&a, &a, &b, &set); // a=a+b + decNumberToString(&a, string); + + printf("%s + %s => %s\n", argv[1], argv[2], string); + return 0; + } // main diff --git a/src/decNumber/example2.c b/src/decNumber/example2.c new file mode 100644 index 0000000000..cb19730417 --- /dev/null +++ b/src/decNumber/example2.c @@ -0,0 +1,52 @@ +/* ------------------------------------------------------------------ */ +/* Decimal Number Library Demonstration program */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2001. All rights reserved. */ +/* ----------------------------------------------------------------+- */ +/* right margin -->| */ + +// example2.c -- calculate compound interest +// Arguments are investment, rate (%), and years + +#define DECNUMDIGITS 38 // work with up to 38 digits +#include "decNumber.h" // base number library +#include // for printf + +int main(int argc, char *argv[]) { + int need=3; + if (argc %s\n", + argv[1], argv[2], argv[3], string); + + } //---------------------------------------------------------------| + return 0; + } // main diff --git a/src/decNumber/example3.c b/src/decNumber/example3.c new file mode 100644 index 0000000000..b84085c011 --- /dev/null +++ b/src/decNumber/example3.c @@ -0,0 +1,64 @@ +/* ------------------------------------------------------------------ */ +/* Decimal Number Library Demonstration program */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2001. All rights reserved. */ +/* ----------------------------------------------------------------+- */ +/* right margin -->| */ + +// example3.c -- calculate compound interest, passive checking +// Arguments are investment, rate (%), and years + +#define DECNUMDIGITS 38 // work with up to 38 digits +#include "decNumber.h" // base number library +#include // for printf + +int main(int argc, char *argv[]) { + int need=3; + if (argc %s\n", + argv[1], argv[2], argv[3], string); + + } //---------------------------------------------------------------| + return 0; + } // main diff --git a/src/decNumber/example4.c b/src/decNumber/example4.c new file mode 100644 index 0000000000..ce8028bd22 --- /dev/null +++ b/src/decNumber/example4.c @@ -0,0 +1,61 @@ +/* ------------------------------------------------------------------ */ +/* Decimal Number Library Demonstration program */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2001. All rights reserved. */ +/* ----------------------------------------------------------------+- */ +/* right margin -->| */ + +// example4.c -- add two numbers, active error handling +// Arguments are two numbers + +#define DECNUMDIGITS 38 // work with up to 38 digits +#include "decNumber.h" // base number library +#include // for printf + +// [snip... +#include // signal handling +#include // setjmp/longjmp + +jmp_buf preserve; // stack snapshot + +void signalHandler(int); // prototype for GCC +void signalHandler(int sig) { + signal(SIGFPE, signalHandler); // re-enable + longjmp(preserve, sig); // branch to preserved point + } +// ...snip] +int main(int argc, char *argv[]) { + decNumber a, b; // working numbers + decContext set; // working context + char string[DECNUMDIGITS+14]; // conversion buffer + int value; // work variable + + if (argc<3) { // not enough words + printf("Please supply two numbers to add.\n"); + return 1; + } + decContextDefault(&set, DEC_INIT_BASE); // initialize + +// [snip... + signal(SIGFPE, signalHandler); // set up signal handler + value=setjmp(preserve); // preserve and test environment + if (value) { // (non-0 after longjmp) + set.status &= DEC_Errors; // keep only errors + printf("Signal trapped [%s].\n", decContextStatusToString(&set)); + return 1; + } +// ...snip] + +// [change from Example 1, here] + // leave traps enabled + set.digits=DECNUMDIGITS; // set precision + + decNumberFromString(&a, argv[1], &set); + decNumberFromString(&b, argv[2], &set); + + decNumberAdd(&a, &a, &b, &set); // A=A+B + decNumberToString(&a, string); + + printf("%s + %s => %s\n", argv[1], argv[2], string); + return 0; + } // main diff --git a/src/decNumber/example5.c b/src/decNumber/example5.c new file mode 100644 index 0000000000..5f89d8c3ad --- /dev/null +++ b/src/decNumber/example5.c @@ -0,0 +1,36 @@ +/* ------------------------------------------------------------------ */ +/* Decimal Number Library Demonstration program */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2001, 2007. All rights reserved. */ +/* ----------------------------------------------------------------+- */ +/* right margin -->| */ + +// example5.c -- decimal64 conversions + +#include "decimal64.h" // decimal64 and decNumber library +#include // for (s)printf + +int main(int argc, char *argv[]) { + decimal64 a; // working decimal64 number + decNumber d; // working number + decContext set; // working context + char string[DECIMAL64_String]; // number->string buffer + char hexes[25]; // decimal64->hex buffer + int i; // counter + + if (argc<2) { // not enough words + printf("Please supply a number.\n"); + return 1; + } + decContextDefault(&set, DEC_INIT_DECIMAL64); // initialize + + decimal64FromString(&a, argv[1], &set); + // lay out the decimal64 as eight hexadecimal pairs + for (i=0; i<8; i++) { + sprintf(&hexes[i*3], "%02x ", a.bytes[i]); + } + decimal64ToNumber(&a, &d); + decNumberToString(&d, string); + printf("%s => %s=> %s\n", argv[1], hexes, string); + return 0; + } // main diff --git a/src/decNumber/example6.c b/src/decNumber/example6.c new file mode 100644 index 0000000000..486b979891 --- /dev/null +++ b/src/decNumber/example6.c @@ -0,0 +1,61 @@ +/* ------------------------------------------------------------------ */ +/* Decimal Number Library Demonstration program */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2001. All rights reserved. */ +/* ----------------------------------------------------------------+- */ +/* right margin -->| */ + +// example6.c -- calculate compound interest, using Packed Decimal +// Values are investment, rate (%), and years + +#include "decPacked.h" // base number library +#include // for printf + +int main(int argc, char *argv[]) { + { // excerpt for User's Guide starts here--------------------------| + decNumber one, mtwo, hundred; // constants + decNumber start, rate, years; // parameters + decNumber total; // result + decContext set; // working context + + uint8_t startpack[]={0x01, 0x00, 0x00, 0x0C}; // investment=100000 + int32_t startscale=0; + uint8_t ratepack[]={0x06, 0x5C}; // rate=6.5% + int32_t ratescale=1; + uint8_t yearspack[]={0x02, 0x0C}; // years=20 + int32_t yearsscale=0; + uint8_t respack[16]; // result, packed + int32_t resscale; // .. + char hexes[49]; // for packed->hex + int i; // counter + + if (argc<0) printf("%s", argv[1]); // noop for warning + + decContextDefault(&set, DEC_INIT_BASE); // initialize + set.traps=0; // no traps + set.digits=25; // precision 25 + decNumberFromString(&one, "1", &set); // set constants + decNumberFromString(&mtwo, "-2", &set); + decNumberFromString(&hundred, "100", &set); + + decPackedToNumber(startpack, sizeof(startpack), &startscale, &start); + decPackedToNumber(ratepack, sizeof(ratepack), &ratescale, &rate); + decPackedToNumber(yearspack, sizeof(yearspack), &yearsscale, &years); + + decNumberDivide(&rate, &rate, &hundred, &set); // rate=rate/100 + decNumberAdd(&rate, &rate, &one, &set); // rate=rate+1 + decNumberPower(&rate, &rate, &years, &set); // rate=rate^years + decNumberMultiply(&total, &rate, &start, &set); // total=rate*start + decNumberRescale(&total, &total, &mtwo, &set); // two digits please + + decPackedFromNumber(respack, sizeof(respack), &resscale, &total); + + // lay out the total as sixteen hexadecimal pairs + for (i=0; i<16; i++) { + sprintf(&hexes[i*3], "%02x ", respack[i]); + } + printf("Result: %s (scale=%ld)\n", hexes, (long int)resscale); + + } //---------------------------------------------------------------| + return 0; + } // main diff --git a/src/decNumber/example7.c b/src/decNumber/example7.c new file mode 100644 index 0000000000..cc933cada4 --- /dev/null +++ b/src/decNumber/example7.c @@ -0,0 +1,35 @@ +/* ------------------------------------------------------------------ */ +/* Decimal Number Library Demonstration program */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2001, 2008. All rights reserved. */ +/* ----------------------------------------------------------------+- */ +/* right margin -->| */ + +// example7.c -- using decQuad to add two numbers together + +// compile: example7.c decContext.c decQuad.c + +#include "decQuad.h" // decQuad library +#include // for printf + +int main(int argc, char *argv[]) { + decQuad a, b; // working decQuads + decContext set; // working context + char string[DECQUAD_String]; // number->string buffer + + decContextTestEndian(0); // warn if DECLITEND is wrong + + if (argc<3) { // not enough words + printf("Please supply two numbers to add.\n"); + return 1; + } + decContextDefault(&set, DEC_INIT_DECQUAD); // initialize + + decQuadFromString(&a, argv[1], &set); + decQuadFromString(&b, argv[2], &set); + decQuadAdd(&a, &a, &b, &set); // a=a+b + decQuadToString(&a, string); + + printf("%s + %s => %s\n", argv[1], argv[2], string); + return 0; + } // main diff --git a/src/decNumber/example8.c b/src/decNumber/example8.c new file mode 100644 index 0000000000..7fe35b95fe --- /dev/null +++ b/src/decNumber/example8.c @@ -0,0 +1,39 @@ +/* ------------------------------------------------------------------ */ +/* Decimal Number Library Demonstration program */ +/* ------------------------------------------------------------------ */ +/* Copyright (c) IBM Corporation, 2001, 2007. All rights reserved. */ +/* ----------------------------------------------------------------+- */ +/* right margin -->| */ + +// example8.c -- using decQuad with the decNumber module + +// compile: example8.c decContext.c decQuad.c +// and: decNumber.c decimal128.c decimal64.c + +#include "decQuad.h" // decQuad library +#include "decimal128.h" // interface to decNumber +#include // for printf + +int main(int argc, char *argv[]) { + decQuad a; // working decQuad + decNumber numa, numb; // working decNumbers + decContext set; // working context + char string[DECQUAD_String]; // number->string buffer + + if (argc<3) { // not enough words + printf("Please supply two numbers for power(2*a, b).\n"); + return 1; + } + decContextDefault(&set, DEC_INIT_DECQUAD); // initialize + + decQuadFromString(&a, argv[1], &set); // get a + decQuadAdd(&a, &a, &a, &set); // double a + decQuadToNumber(&a, &numa); // convert to decNumber + decNumberFromString(&numb, argv[2], &set); + decNumberPower(&numa, &numa, &numb, &set); // numa=numa**numb + decQuadFromNumber(&a, &numa, &set); // back via a Quad + decQuadToString(&a, string); // .. + + printf("power(2*%s, %s) => %s\n", argv[1], argv[2], string); + return 0; + } // main diff --git a/src/decNumber/readme.txt b/src/decNumber/readme.txt new file mode 100644 index 0000000000..375623f343 --- /dev/null +++ b/src/decNumber/readme.txt @@ -0,0 +1,81 @@ +This is the readme.txt for the decNumber package. It includes +instructions for compiling and testing the package; please read them. +--------------------------------------------------------------------- + +decNumber is distributed in two forms; as a complete package from +the International Components for Unicode (ICU) site (under an as-is +license), or as a collection of Open Source files from the GCC source +repository (under the GPL license). + +If you are using the GCC files, you can obtain the documentation, the +example files mentioned below, and this readme from the General +Decimal Arithmetic web page -- http://speleotrove.com/decimal/ (the +URL for the open source files is also linked from there). + + +The ICU package +--------------- + +The ICU package includes the files: + + * readme.txt (this file) + + * ICU-license.html + + * decNumber.pdf (documentation) + + * The .c and .h file for each module in the package (see the + decNumber documentation), together with other included files. + + * The .c files for each of the examples (example1.c through + example8.c). + +The ICU package is made available under the terms of the ICU License +(ICU 1.8.1 and later) included in the package as ICU-license.html. +Your use of that package indicates your acceptance of the terms and +conditions of that Agreement. + + +To use and check decNumber +-------------------------- + + Please read the appropriate license and documentation before using + this package. If you are upgrading an existing use of decNumber + (with version <= 3.37) please read the Changes Appendix for later + versions -- you may need to change the DECLITEND flag. + + 1. Compile and link example1.c, decNumber.c, and decContext.c + For instance, use: + + gcc -o example1 example1.c decNumber.c decContext.c + + Note: If your compiler does not provide stdint.h or if your C + compiler does not handle line comments (// ...), then see the + User's Guide section in the documentation for further information + (including a sample minimal stdint.h). + + The use of compiler optimization is strongly recommended (e.g., + -O3 for GCC or /O2 for Visual Studio). + + 2. Run example1 with two numeric arguments, for example: + + example1 1.23 1.27 + + this should display: + + 1.23 + 1.27 => 2.50 + + 3. Similarly, try the other examples, at will. + + Examples 2->4 require three files to be compiled, like Example 1. + + Example 5 requires decimal64.c in addition to the core modules. + + Example 6 requires decPacked.c in addition to the core modules. + + Example 7 requires only example7.c decContext.c and decQuad.c + + Example 8 requires example8.c, decContext.c, and decQuad.c, plus + decNumber.c, decimal128.c, and decimal64.c (the latter + for shared tables and code) + diff --git a/src/execute.c b/src/execute.c index 65c6bc7766..fd2ab2c7be 100644 --- a/src/execute.c +++ b/src/execute.c @@ -509,21 +509,25 @@ jv jq_next(jq_state *jq) { uint16_t v = *pc++; jv* var = frame_local_var(jq, v, level); jv max = stack_pop(jq); - if (raising) goto do_backtrack; + if (raising) { + jv_free(max); + goto do_backtrack; + } if (jv_get_kind(*var) != JV_KIND_NUMBER || jv_get_kind(max) != JV_KIND_NUMBER) { set_error(jq, jv_invalid_with_msg(jv_string_fmt("Range bounds must be numeric"))); jv_free(max); goto do_backtrack; - } else if (jv_number_value(jv_copy(*var)) >= jv_number_value(jv_copy(max))) { + } else if (jv_number_value(*var) >= jv_number_value(max)) { /* finished iterating */ + jv_free(max); goto do_backtrack; } else { - jv curr = jv_copy(*var); + jv curr = *var; *var = jv_number(jv_number_value(*var) + 1); struct stack_pos spos = stack_get_pos(jq); - stack_push(jq, jv_copy(max)); + stack_push(jq, max); stack_save(jq, pc - 3, spos); stack_push(jq, curr); @@ -1010,6 +1014,9 @@ jq_state *jq_init(void) { jq->attrs = jv_object(); jq->path = jv_null(); jq->value_at_path = jv_null(); + + jq->nomem_handler = NULL; + jq->nomem_handler_data = NULL; return jq; } diff --git a/src/jq_test.c b/src/jq_test.c index 7a396b9435..eed633f43d 100644 --- a/src/jq_test.c +++ b/src/jq_test.c @@ -6,20 +6,32 @@ #include "jq.h" static void jv_test(); -static void run_jq_tests(jv, int, FILE *); +static void run_jq_tests(jv, int, FILE *, int, int); int jq_testsuite(jv libdirs, int verbose, int argc, char* argv[]) { FILE *testdata = stdin; + int skip = -1; + int take = -1; jv_test(); if (argc > 0) { - testdata = fopen(argv[0], "r"); - if (!testdata) { - perror("fopen"); - exit(1); + for(int i = 0; i < argc; i++) { + if (!strcmp(argv[i], "--skip")) { + skip = atoi(argv[i+1]); + i++; + } else if (!strcmp(argv[i], "--take")) { + take = atoi(argv[i+1]); + i++; + } else { + testdata = fopen(argv[i], "r"); + if (!testdata) { + perror("fopen"); + exit(1); + } + } } } - run_jq_tests(libdirs, verbose, testdata); + run_jq_tests(libdirs, verbose, testdata, skip, take); return 0; } @@ -53,7 +65,7 @@ static void test_err_cb(void *data, jv e) { jv_free(e); } -static void run_jq_tests(jv lib_dirs, int verbose, FILE *testdata) { +static void run_jq_tests(jv lib_dirs, int verbose, FILE *testdata, int skip, int take) { char prog[4096]; char buf[4096]; struct err_data err_msg; @@ -63,6 +75,9 @@ static void run_jq_tests(jv lib_dirs, int verbose, FILE *testdata) { int check_msg = 0; jq_state *jq = NULL; + int tests_to_skip = skip > 0 ? skip : 0; + int tests_to_take = take; + jq = jq_init(); assert(jq); if (jv_get_kind(lib_dirs) == JV_KIND_NULL) @@ -80,9 +95,37 @@ static void run_jq_tests(jv lib_dirs, int verbose, FILE *testdata) { continue; } if (prog[strlen(prog)-1] == '\n') prog[strlen(prog)-1] = 0; - printf("Testing '%s' at line number %u\n", prog, lineno); + + if (skip > 0) { + skip--; + + // skip past test data + while (fgets(buf, sizeof(buf), testdata)) { + lineno++; + if (buf[0] == '\n' || (buf[0] == '\r' && buf[1] == '\n')) + break; + } + + must_fail = 0; + check_msg = 0; + + continue; + } else if (skip == 0) { + printf("Skipped %d tests\n", tests_to_skip); + skip = -1; + } + + if (take > 0) { + take--; + } else if (take == 0) { + printf("Hit the number of tests limit (%d), breaking\n", tests_to_take); + take = -1; + break; + } + int pass = 1; tests++; + printf("Test #%d: '%s' at line number %u\n", tests + tests_to_skip, prog, lineno); int compiled = jq_compile(jq, prog); if (must_fail) { @@ -179,7 +222,21 @@ static void run_jq_tests(jv lib_dirs, int verbose, FILE *testdata) { passed+=pass; } jq_teardown(&jq); - printf("%d of %d tests passed (%d malformed)\n", passed,tests,invalid); + + int total_skipped = tests_to_skip; + + if (skip > 0) { + total_skipped = tests_to_skip - skip; + } + + printf("%d of %d tests passed (%d malformed, %d skipped)\n", + passed, tests, invalid, total_skipped); + + if (skip > 0) { + printf("WARN: skipped past the end of file, exiting with status 2\n"); + exit(2); + } + if (passed != tests) exit(1); } diff --git a/src/jv.c b/src/jv.c index 2427b009a9..866dd43e4b 100644 --- a/src/jv.c +++ b/src/jv.c @@ -13,6 +13,15 @@ #include "jv_unicode.h" #include "util.h" +#include "jv_dtoa.h" +#include "jv_dtoa_tsd.h" + +// this means that we will manage the space for the struct +#define DECNUMDIGITS 1 +#include "decNumber/decNumber.h" + +#include "jv_type_private.h" + /* * Internal refcounting helpers */ @@ -37,14 +46,33 @@ static int jvp_refcnt_unshared(jv_refcnt* c) { return c->count == 1; } -/* - * Simple values (true, false, null) - */ +#define KIND_MASK 0xF +#define PFLAGS_MASK 0xF0 +#define PTYPE_MASK 0x70 + +typedef enum { + JVP_PAYLOAD_NONE = 0, + JVP_PAYLOAD_ALLOCATED = 0x80, +} payload_flags; + +#define JVP_MAKE_PFLAGS(ptype, allocated) ((((ptype) << 4) & PTYPE_MASK) | ((allocated) ? JVP_PAYLOAD_ALLOCATED : 0)) +#define JVP_MAKE_FLAGS(kind, pflags) ((kind & KIND_MASK) | (pflags & PFLAGS_MASK)) + +#define JVP_FLAGS(j) ((j).kind_flags) +#define JVP_KIND(j) (JVP_FLAGS(j) & KIND_MASK) -#define KIND_MASK 0xf +#define JVP_HAS_FLAGS(j, flags) (JVP_FLAGS(j) == flags) +#define JVP_HAS_KIND(j, kind) (JVP_KIND(j) == kind) + +#define JVP_IS_ALLOCATED(j) (j.kind_flags & JVP_PAYLOAD_ALLOCATED) + +#define JVP_FLAGS_NULL JVP_MAKE_FLAGS(JV_KIND_NULL, JVP_PAYLOAD_NONE) +#define JVP_FLAGS_INVALID JVP_MAKE_FLAGS(JV_KIND_INVALID, JVP_PAYLOAD_NONE) +#define JVP_FLAGS_FALSE JVP_MAKE_FLAGS(JV_KIND_FALSE, JVP_PAYLOAD_NONE) +#define JVP_FLAGS_TRUE JVP_MAKE_FLAGS(JV_KIND_TRUE, JVP_PAYLOAD_NONE) jv_kind jv_get_kind(jv x) { - return x.kind_flags & KIND_MASK; + return JVP_KIND(x); } const char* jv_kind_name(jv_kind k) { @@ -62,10 +90,10 @@ const char* jv_kind_name(jv_kind k) { return ""; } -static const jv JV_NULL = {JV_KIND_NULL, 0, 0, 0, {0}}; -static const jv JV_INVALID = {JV_KIND_INVALID, 0, 0, 0, {0}}; -static const jv JV_FALSE = {JV_KIND_FALSE, 0, 0, 0, {0}}; -static const jv JV_TRUE = {JV_KIND_TRUE, 0, 0, 0, {0}}; +const jv JV_NULL = {JVP_FLAGS_NULL, 0, 0, 0, {0}}; +const jv JV_INVALID = {JVP_FLAGS_INVALID, 0, 0, 0, {0}}; +const jv JV_FALSE = {JVP_FLAGS_FALSE, 0, 0, 0, {0}}; +const jv JV_TRUE = {JVP_FLAGS_TRUE, 0, 0, 0, {0}}; jv jv_true() { return JV_TRUE; @@ -87,19 +115,21 @@ jv jv_bool(int x) { * Invalid objects, with optional error messages */ +#define JVP_FLAGS_INVALID_MSG JVP_MAKE_FLAGS(JV_KIND_INVALID, JVP_PAYLOAD_ALLOCATED) + typedef struct { jv_refcnt refcnt; jv errmsg; } jvp_invalid; jv jv_invalid_with_msg(jv err) { - if (jv_get_kind(err) == JV_KIND_NULL) + if (JVP_HAS_KIND(err, JV_KIND_NULL)) return JV_INVALID; jvp_invalid* i = jv_mem_alloc(sizeof(jvp_invalid)); i->refcnt = JV_REFCNT_INIT; i->errmsg = err; - jv x = {JV_KIND_INVALID, 0, 0, 0, {&i->refcnt}}; + jv x = {JVP_FLAGS_INVALID_MSG, 0, 0, 0, {&i->refcnt}}; return x; } @@ -108,26 +138,30 @@ jv jv_invalid() { } jv jv_invalid_get_msg(jv inv) { - assert(jv_get_kind(inv) == JV_KIND_INVALID); + assert(JVP_HAS_KIND(inv, JV_KIND_INVALID)); + jv x; - if (inv.u.ptr == 0) - x = jv_null(); - else + if (JVP_HAS_FLAGS(inv, JVP_FLAGS_INVALID_MSG)) { x = jv_copy(((jvp_invalid*)inv.u.ptr)->errmsg); + } + else { + x = jv_null(); + } + jv_free(inv); return x; } int jv_invalid_has_msg(jv inv) { - jv msg = jv_invalid_get_msg(inv); - int r = jv_get_kind(msg) != JV_KIND_NULL; - jv_free(msg); + assert(JVP_HAS_KIND(inv, JV_KIND_INVALID)); + int r = JVP_HAS_FLAGS(inv, JVP_FLAGS_INVALID_MSG); + jv_free(inv); return r; } static void jvp_invalid_free(jv x) { - assert(jv_get_kind(x) == JV_KIND_INVALID); - if (x.u.ptr != 0 && jvp_refcnt_dec(x.u.ptr)) { + assert(JVP_HAS_KIND(x, JV_KIND_INVALID)); + if (JVP_HAS_FLAGS(x, JVP_FLAGS_INVALID_MSG) && jvp_refcnt_dec(x.u.ptr)) { jv_free(((jvp_invalid*)x.u.ptr)->errmsg); jv_mem_free(x.u.ptr); } @@ -137,20 +171,269 @@ static void jvp_invalid_free(jv x) { * Numbers */ +enum { + JVP_NUMBER_NATIVE = 0, + JVP_NUMBER_DECIMAL = 1 +}; + +#define JV_NUMBER_SIZE_INIT (0) +#define JV_NUMBER_SIZE_CONVERTED (1) + +#define JVP_FLAGS_NUMBER_NATIVE JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_NATIVE, 0)) +#define JVP_FLAGS_NUMBER_NATIVE_STR JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_NATIVE, 1)) +#define JVP_FLAGS_NUMBER_LITERAL JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_DECIMAL, 1)) + +#define STR(x) #x +#define XSTR(x) STR(x) +#define DBL_MAX_STR XSTR(DBL_MAX) +#define DBL_MIN_STR "-" XSTR(DBL_MAX) + +// the decimal precision of binary double +#define BIN64_DEC_PRECISION (17) +#define DEC_NUMBER_STRING_GUARD (14) + +#include + +static pthread_key_t dec_ctx_key; +static pthread_key_t dec_ctx_dbl_key; +static pthread_once_t dec_ctx_once = PTHREAD_ONCE_INIT; + +#define DEC_CONTEXT() tsd_dec_ctx_get(&dec_ctx_key) +#define DEC_CONTEXT_TO_DOUBLE() tsd_dec_ctx_get(&dec_ctx_dbl_key) + +// atexit finalizer to clean up the tsd dec contexts if main() exits +// without having called pthread_exit() +static void tsd_dec_ctx_fini() { + jv_mem_free(pthread_getspecific(dec_ctx_key)); + jv_mem_free(pthread_getspecific(dec_ctx_dbl_key)); + pthread_setspecific(dec_ctx_key, NULL); + pthread_setspecific(dec_ctx_dbl_key, NULL); +} + +static void tsd_dec_ctx_init() { + if (pthread_key_create(&dec_ctx_key, jv_mem_free) != 0) { + fprintf(stderr, "error: cannot create thread specific key"); + abort(); + } + if (pthread_key_create(&dec_ctx_dbl_key, jv_mem_free) != 0) { + fprintf(stderr, "error: cannot create thread specific key"); + abort(); + } + atexit(tsd_dec_ctx_fini); +} + +static decContext* tsd_dec_ctx_get(pthread_key_t *key) { + pthread_once(&dec_ctx_once, tsd_dec_ctx_init); // cannot fail + decContext *ctx = (decContext*)pthread_getspecific(*key); + if (ctx) { + return ctx; + } + + decContext _ctx = { + 0, + DEC_MAX_EMAX, + DEC_MIN_EMAX, + DEC_ROUND_HALF_UP, + 0, /*no errors*/ + 0, /*status*/ + 0, /*no clamping*/ + }; + if (key == &dec_ctx_key) { + _ctx.digits = DEC_MAX_DIGITS; + } else if (key == &dec_ctx_dbl_key) { + _ctx.digits = BIN64_DEC_PRECISION; + } + + ctx = malloc(sizeof(decContext)); + if (ctx) { + *ctx = _ctx; + if (pthread_setspecific(*key, ctx) != 0) { + fprintf(stderr, "error: cannot store thread specific data"); + abort(); + } + } + return ctx; +} + +typedef struct { + jv_refcnt refcnt; + double num_double; + char * literal_data; + decNumber num_decimal; // must be the last field in the structure for memory management +} jvp_literal_number; + +typedef struct { + decNumber number; + decNumberUnit units[1]; +} decNumberSingle; + +typedef struct { + decNumber number; + decNumberUnit units[BIN64_DEC_PRECISION]; +} decNumberDoublePrecision; + + +static inline int jvp_number_is_literal(jv n) { + assert(JVP_HAS_KIND(n, JV_KIND_NUMBER)); + return JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL); +} + +static jvp_literal_number* jvp_literal_number_ptr(jv j) { + assert(JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL)); + return (jvp_literal_number*)j.u.ptr; +} + +static decNumber* jvp_dec_number_ptr(jv j) { + assert(JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL)); + return &(((jvp_literal_number*)j.u.ptr)->num_decimal); +} + +static jvp_literal_number* jvp_literal_number_alloc(unsigned literal_length) { + + /* The number of units needed is ceil(DECNUMDIGITS/DECDPUN) */ + int units = ((literal_length+DECDPUN-1)/DECDPUN); + + jvp_literal_number* n = jv_mem_alloc( + sizeof(jvp_literal_number) + + sizeof(decNumberUnit) * units + ); + + return n; +} + +static jv jvp_literal_number_new(const char * literal) { + + jvp_literal_number * n = jvp_literal_number_alloc(strlen(literal)); + + n->refcnt = JV_REFCNT_INIT; + n->literal_data = NULL; + decContext *ctx = DEC_CONTEXT(); + decNumberFromString(&n->num_decimal, literal, ctx); + n->num_double = NAN; + + if (ctx->status & DEC_Conversion_syntax) { + jv_mem_free(n); + return JV_INVALID; + } + + jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, JV_NUMBER_SIZE_INIT, {&n->refcnt}}; + return r; +} + +static double jvp_literal_number_to_double(jv j) { + assert(JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL)); + + decNumber *p_dec_number = jvp_dec_number_ptr(j); + decNumberDoublePrecision dec_double; + char literal[BIN64_DEC_PRECISION + DEC_NUMBER_STRING_GUARD + 1]; + + // reduce the number to the shortest possible form + // while also making sure than no more than BIN64_DEC_PRECISION + // digits are used (dec_context_to_double) + decNumberReduce(&dec_double.number, p_dec_number, DEC_CONTEXT_TO_DOUBLE()); + + decNumberToString(&dec_double.number, literal); + + char *end; + return jvp_strtod(tsd_dtoa_context_get(), literal, &end); +} + + +static int jvp_number_equal(jv a, jv b) { + return jvp_number_cmp(a, b) == 0; +} + +static const char* jvp_literal_number_literal(jv n) { + assert(JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL)); + decNumber *pdec = jvp_dec_number_ptr(n); + jvp_literal_number* plit = jvp_literal_number_ptr(n); + + if (decNumberIsNaN(pdec)) { + return "null"; + } + + if (decNumberIsInfinite(pdec)) { + // For backward compatibiltiy. + if (decNumberIsNegative(pdec)) { + return DBL_MIN_STR; + } else { + return DBL_MAX_STR; + } + } + + if (plit->literal_data == NULL) { + int len = jvp_dec_number_ptr(n)->digits + 14; + plit->literal_data = jv_mem_alloc(len); + + // Preserve the actual precision as we have parsed it + // don't do decNumberTrim(pdec); + + decNumberToString(pdec, plit->literal_data); + } + + return plit->literal_data; +} + +int jv_number_has_literal(jv n) { + assert(JVP_HAS_KIND(n, JV_KIND_NUMBER)); + return JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL); +} + +const char* jv_number_get_literal(jv n) { + assert(JVP_HAS_KIND(n, JV_KIND_NUMBER)); + + if (JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL)) { + return jvp_literal_number_literal(n); + } else { + return NULL; + } +} + +static void jvp_number_free(jv j) { + assert(JVP_HAS_KIND(j, JV_KIND_NUMBER)); + if (JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL) && jvp_refcnt_dec(j.u.ptr)) { + jvp_literal_number* n = jvp_literal_number_ptr(j); + if (n->literal_data) { + jv_mem_free(n->literal_data); + } + jv_mem_free(n); + } +} + +jv jv_number_with_literal(const char * literal) { + return jvp_literal_number_new(literal); +} + jv jv_number(double x) { - jv j = {JV_KIND_NUMBER, 0, 0, 0, {.number = x}}; + jv j = {JVP_FLAGS_NUMBER_NATIVE, 0, 0, 0, {.number = x}}; return j; } double jv_number_value(jv j) { - assert(jv_get_kind(j) == JV_KIND_NUMBER); - return j.u.number; + assert(JVP_HAS_KIND(j, JV_KIND_NUMBER)); +#ifdef USE_DECNUM + if (JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL)) { + jvp_literal_number* n = jvp_literal_number_ptr(j); + + if (j.size != JV_NUMBER_SIZE_CONVERTED) { + n->num_double = jvp_literal_number_to_double(j); + j.size = JV_NUMBER_SIZE_CONVERTED; + } + + return n->num_double; + } else { +#endif + return j.u.number; +#ifdef USE_DECNUM + } +#endif } int jv_is_integer(jv j){ - if(jv_get_kind(j) != JV_KIND_NUMBER){ + if(!JVP_HAS_KIND(j, JV_KIND_NUMBER)){ return 0; } + double x = jv_number_value(j); if(x != x || x > INT_MAX || x < INT_MIN){ return 0; @@ -159,11 +442,53 @@ int jv_is_integer(jv j){ return x == (int)x; } +int jvp_number_is_nan(jv n) { + assert(JVP_HAS_KIND(n, JV_KIND_NUMBER)); + + if (JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL)) { + decNumber *pdec = jvp_dec_number_ptr(n); + return decNumberIsNaN(pdec); + } else { + return n.u.number != n.u.number; + } +} + +int jvp_number_cmp(jv a, jv b) { + assert(JVP_HAS_KIND(a, JV_KIND_NUMBER)); + assert(JVP_HAS_KIND(b, JV_KIND_NUMBER)); + + if(JVP_HAS_FLAGS(a, JVP_FLAGS_NUMBER_LITERAL) && JVP_HAS_FLAGS(b, JVP_FLAGS_NUMBER_LITERAL)) { + decNumberSingle res; + decNumberCompare(&res.number, + jvp_dec_number_ptr(a), + jvp_dec_number_ptr(b), + DEC_CONTEXT() + ); + if (decNumberIsZero(&res.number)) { + return 0; + } else if (decNumberIsNegative(&res.number)) { + return -1; + } else { + return 1; + } + } else { + double da = jv_number_value(a), db = jv_number_value(b); + if (da < db) { + return -1; + } else if (da == db) { + return 0; + } else { + return 1; + } + } +} + /* * Arrays (internal helpers) */ #define ARRAY_SIZE_ROUND_UP(n) (((n)*3)/2) +#define JVP_FLAGS_ARRAY JVP_MAKE_FLAGS(JV_KIND_ARRAY, JVP_PAYLOAD_ALLOCATED) static int imax(int a, int b) { if (a>b) return a; @@ -178,7 +503,7 @@ typedef struct { } jvp_array; static jvp_array* jvp_array_ptr(jv a) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); return (jvp_array*)a.u.ptr; } @@ -191,12 +516,12 @@ static jvp_array* jvp_array_alloc(unsigned size) { } static jv jvp_array_new(unsigned size) { - jv r = {JV_KIND_ARRAY, 0, 0, 0, {&jvp_array_alloc(size)->refcnt}}; + jv r = {JVP_FLAGS_ARRAY, 0, 0, 0, {&jvp_array_alloc(size)->refcnt}}; return r; } static void jvp_array_free(jv a) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); if (jvp_refcnt_dec(a.u.ptr)) { jvp_array* array = jvp_array_ptr(a); for (int i=0; ilength; i++) { @@ -207,17 +532,17 @@ static void jvp_array_free(jv a) { } static int jvp_array_length(jv a) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); return a.size; } static int jvp_array_offset(jv a) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); return a.offset; } static jv* jvp_array_read(jv a, int i) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); if (i >= 0 && i < jvp_array_length(a)) { jvp_array* array = jvp_array_ptr(a); assert(i + jvp_array_offset(a) < array->length); @@ -254,7 +579,7 @@ static jv* jvp_array_write(jv* a, int i) { } new_array->length = new_length; jvp_array_free(*a); - jv new_jv = {JV_KIND_ARRAY, 0, 0, new_length, {&new_array->refcnt}}; + jv new_jv = {JVP_FLAGS_ARRAY, 0, 0, new_length, {&new_array->refcnt}}; *a = new_jv; return &new_array->elements[i]; } @@ -285,8 +610,33 @@ static void jvp_clamp_slice_params(int len, int *pstart, int *pend) if (*pend < *pstart) *pend = *pstart; } + +static int jvp_array_contains(jv a, jv b) { + int r = 1; + jv_array_foreach(b, bi, belem) { + int ri = 0; + jv_array_foreach(a, ai, aelem) { + if (jv_contains(aelem, jv_copy(belem))) { + ri = 1; + break; + } + } + jv_free(belem); + if (!ri) { + r = 0; + break; + } + } + return r; +} + + +/* + * Public + */ + static jv jvp_array_slice(jv a, int start, int end) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); int len = jvp_array_length(a); jvp_clamp_slice_params(len, &start, &end); assert(0 <= start && start <= end && end <= len); @@ -323,14 +673,14 @@ jv jv_array() { } int jv_array_length(jv j) { - assert(jv_get_kind(j) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(j, JV_KIND_ARRAY)); int len = jvp_array_length(j); jv_free(j); return len; } jv jv_array_get(jv j, int idx) { - assert(jv_get_kind(j) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(j, JV_KIND_ARRAY)); jv* slot = jvp_array_read(j, idx); jv val; if (slot) { @@ -343,7 +693,7 @@ jv jv_array_get(jv j, int idx) { } jv jv_array_set(jv j, int idx, jv val) { - assert(jv_get_kind(j) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(j, JV_KIND_ARRAY)); if (idx < 0) idx = jvp_array_length(j) + idx; @@ -365,8 +715,8 @@ jv jv_array_append(jv j, jv val) { } jv jv_array_concat(jv a, jv b) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); - assert(jv_get_kind(b) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); + assert(JVP_HAS_KIND(b, JV_KIND_ARRAY)); // FIXME: could be faster jv_array_foreach(b, i, elem) { @@ -377,44 +727,22 @@ jv jv_array_concat(jv a, jv b) { } jv jv_array_slice(jv a, int start, int end) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); // copy/free of a coalesced return jvp_array_slice(a, start, end); } -int jv_array_contains(jv a, jv b) { - int r = 1; - jv_array_foreach(b, bi, belem) { - int ri = 0; - jv_array_foreach(a, ai, aelem) { - if (jv_contains(aelem, jv_copy(belem))) { - ri = 1; - break; - } - } - jv_free(belem); - if (!ri) { - r = 0; - break; - } - } - jv_free(a); - jv_free(b); - return r; -} - jv jv_array_indexes(jv a, jv b) { jv res = jv_array(); int idx = -1; jv_array_foreach(a, ai, aelem) { + jv_free(aelem); jv_array_foreach(b, bi, belem) { - // quieten compiler warnings about aelem not being used... by - // using it - if ((bi == 0 && !jv_equal(jv_copy(aelem), jv_copy(belem))) || - (bi > 0 && !jv_equal(jv_array_get(jv_copy(a), ai + bi), jv_copy(belem)))) + if (!jv_equal(jv_array_get(jv_copy(a), ai + bi), jv_copy(belem))) idx = -1; else if (bi == 0 && idx == -1) idx = ai; + jv_free(belem); } if (idx > -1) res = jv_array_append(res, jv_number(idx)); @@ -425,11 +753,12 @@ jv jv_array_indexes(jv a, jv b) { return res; } - /* * Strings (internal helpers) */ +#define JVP_FLAGS_STRING JVP_MAKE_FLAGS(JV_KIND_STRING, JVP_PAYLOAD_ALLOCATED) + typedef struct { jv_refcnt refcnt; uint32_t hash; @@ -441,7 +770,7 @@ typedef struct { } jvp_string; static jvp_string* jvp_string_ptr(jv a) { - assert(jv_get_kind(a) == JV_KIND_STRING); + assert(JVP_HAS_KIND(a, JV_KIND_STRING)); return (jvp_string*)a.u.ptr; } @@ -473,7 +802,7 @@ static jv jvp_string_copy_replace_bad(const char* data, uint32_t length) { length = out - s->data; s->data[length] = 0; s->length_hashed = length << 1; - jv r = {JV_KIND_STRING, 0, 0, 0, {&s->refcnt}}; + jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&s->refcnt}}; return r; } @@ -484,7 +813,7 @@ static jv jvp_string_new(const char* data, uint32_t length) { if (data != NULL) memcpy(s->data, data, length); s->data[length] = 0; - jv r = {JV_KIND_STRING, 0, 0, 0, {&s->refcnt}}; + jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&s->refcnt}}; return r; } @@ -492,7 +821,7 @@ static jv jvp_string_empty_new(uint32_t length) { jvp_string* s = jvp_string_alloc(length); s->length_hashed = 0; memset(s->data, 0, length); - jv r = {JV_KIND_STRING, 0, 0, 0, {&s->refcnt}}; + jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&s->refcnt}}; return r; } @@ -535,7 +864,7 @@ static jv jvp_string_append(jv string, const char* data, uint32_t len) { memcpy(news->data + currlen, data, len); news->data[currlen + len] = 0; jvp_string_free(string); - jv r = {JV_KIND_STRING, 0, 0, 0, {&news->refcnt}}; + jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&news->refcnt}}; return r; } } @@ -602,9 +931,10 @@ static uint32_t jvp_string_hash(jv jstr) { return h1; } + static int jvp_string_equal(jv a, jv b) { - assert(jv_get_kind(a) == JV_KIND_STRING); - assert(jv_get_kind(b) == JV_KIND_STRING); + assert(JVP_HAS_KIND(a, JV_KIND_STRING)); + assert(JVP_HAS_KIND(b, JV_KIND_STRING)); jvp_string* stra = jvp_string_ptr(a); jvp_string* strb = jvp_string_ptr(b); if (jvp_string_length(stra) != jvp_string_length(strb)) return 0; @@ -631,14 +961,14 @@ jv jv_string(const char* str) { } int jv_string_length_bytes(jv j) { - assert(jv_get_kind(j) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); int r = jvp_string_length(jvp_string_ptr(j)); jv_free(j); return r; } int jv_string_length_codepoints(jv j) { - assert(jv_get_kind(j) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); const char* i = jv_string_value(j); const char* end = i + jv_string_length_bytes(jv_copy(j)); int c = 0, len = 0; @@ -649,8 +979,8 @@ int jv_string_length_codepoints(jv j) { jv jv_string_indexes(jv j, jv k) { - assert(jv_get_kind(j) == JV_KIND_STRING); - assert(jv_get_kind(k) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); + assert(JVP_HAS_KIND(k, JV_KIND_STRING)); const char *jstr = jv_string_value(j); const char *idxstr = jv_string_value(k); const char *p; @@ -671,8 +1001,8 @@ jv jv_string_indexes(jv j, jv k) { } jv jv_string_split(jv j, jv sep) { - assert(jv_get_kind(j) == JV_KIND_STRING); - assert(jv_get_kind(sep) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); + assert(JVP_HAS_KIND(sep, JV_KIND_STRING)); const char *jstr = jv_string_value(j); const char *jend = jstr + jv_string_length_bytes(jv_copy(j)); const char *sepstr = jv_string_value(sep); @@ -703,7 +1033,7 @@ jv jv_string_split(jv j, jv sep) { } jv jv_string_explode(jv j) { - assert(jv_get_kind(j) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); const char* i = jv_string_value(j); int len = jv_string_length_bytes(jv_copy(j)); const char* end = i + len; @@ -716,7 +1046,7 @@ jv jv_string_explode(jv j) { } jv jv_string_implode(jv j) { - assert(jv_get_kind(j) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(j, JV_KIND_ARRAY)); int len = jv_array_length(jv_copy(j)); jv s = jv_string_empty(len); int i; @@ -725,8 +1055,9 @@ jv jv_string_implode(jv j) { for (i = 0; i < len; i++) { jv n = jv_array_get(jv_copy(j), i); - assert(jv_get_kind(n) == JV_KIND_NUMBER); + assert(JVP_HAS_KIND(n, JV_KIND_NUMBER)); int nv = jv_number_value(n); + jv_free(n); if (nv > 0x10FFFF) nv = 0xFFFD; // U+FFFD REPLACEMENT CHARACTER s = jv_string_append_codepoint(s, nv); @@ -737,19 +1068,19 @@ jv jv_string_implode(jv j) { } unsigned long jv_string_hash(jv j) { - assert(jv_get_kind(j) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); uint32_t hash = jvp_string_hash(j); jv_free(j); return hash; } const char* jv_string_value(jv j) { - assert(jv_get_kind(j) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); return jvp_string_ptr(j)->data; } jv jv_string_slice(jv j, int start, int end) { - assert(jv_get_kind(j) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); const char *s = jv_string_value(j); int len = jv_string_length_bytes(jv_copy(j)); int i; @@ -860,6 +1191,8 @@ jv jv_string_fmt(const char* fmt, ...) { * Objects (internal helpers) */ +#define JVP_FLAGS_OBJECT JVP_MAKE_FLAGS(JV_KIND_OBJECT, JVP_PAYLOAD_ALLOCATED) + struct object_slot { int next; /* next slot with same hash, for collisions */ uint32_t hash; @@ -896,22 +1229,22 @@ static jv jvp_object_new(int size) { for (int i=0; irefcnt}}; + jv r = {JVP_FLAGS_OBJECT, 0, 0, size, {&obj->refcnt}}; return r; } static jvp_object* jvp_object_ptr(jv o) { - assert(jv_get_kind(o) == JV_KIND_OBJECT); + assert(JVP_HAS_KIND(o, JV_KIND_OBJECT)); return (jvp_object*)o.u.ptr; } static uint32_t jvp_object_mask(jv o) { - assert(jv_get_kind(o) == JV_KIND_OBJECT); + assert(JVP_HAS_KIND(o, JV_KIND_OBJECT)); return (o.size * 2) - 1; } static int jvp_object_size(jv o) { - assert(jv_get_kind(o) == JV_KIND_OBJECT); + assert(JVP_HAS_KIND(o, JV_KIND_OBJECT)); return o.size; } @@ -959,7 +1292,7 @@ static struct object_slot* jvp_object_add_slot(jv object, jv key, int* bucket) { } static jv* jvp_object_read(jv object, jv key) { - assert(jv_get_kind(key) == JV_KIND_STRING); + assert(JVP_HAS_KIND(key, JV_KIND_STRING)); int* bucket = jvp_object_find_bucket(object, key); struct object_slot* slot = jvp_object_find_slot(object, key, bucket); if (slot == 0) return 0; @@ -967,7 +1300,7 @@ static jv* jvp_object_read(jv object, jv key) { } static void jvp_object_free(jv o) { - assert(jv_get_kind(o) == JV_KIND_OBJECT); + assert(JVP_HAS_KIND(o, JV_KIND_OBJECT)); if (jvp_refcnt_dec(o.u.ptr)) { for (int i=0; istring; - assert(jv_get_kind(s) == JV_KIND_STRING); + assert(JVP_HAS_KIND(s, JV_KIND_STRING)); return jv_copy(s); } @@ -1242,34 +1572,36 @@ jv jv_object_iter_value(jv object, int iter) { * Memory management */ jv jv_copy(jv j) { - if (jv_get_kind(j) == JV_KIND_ARRAY || - jv_get_kind(j) == JV_KIND_STRING || - jv_get_kind(j) == JV_KIND_OBJECT || - (jv_get_kind(j) == JV_KIND_INVALID && j.u.ptr != 0)) { + if (JVP_IS_ALLOCATED(j)) { jvp_refcnt_inc(j.u.ptr); } return j; } void jv_free(jv j) { - if (jv_get_kind(j) == JV_KIND_ARRAY) { - jvp_array_free(j); - } else if (jv_get_kind(j) == JV_KIND_STRING) { - jvp_string_free(j); - } else if (jv_get_kind(j) == JV_KIND_OBJECT) { - jvp_object_free(j); - } else if (jv_get_kind(j) == JV_KIND_INVALID) { - jvp_invalid_free(j); + switch(JVP_KIND(j)) { + case JV_KIND_ARRAY: + jvp_array_free(j); + break; + case JV_KIND_STRING: + jvp_string_free(j); + break; + case JV_KIND_OBJECT: + jvp_object_free(j); + break; + case JV_KIND_INVALID: + jvp_invalid_free(j); + break; + case JV_KIND_NUMBER: + jvp_number_free(j); + break; } } int jv_get_refcnt(jv j) { - switch (jv_get_kind(j)) { - case JV_KIND_ARRAY: - case JV_KIND_STRING: - case JV_KIND_OBJECT: + if (JVP_IS_ALLOCATED(j)) { return j.u.ptr->count; - default: + } else { return 1; } } @@ -1282,14 +1614,17 @@ int jv_equal(jv a, jv b) { int r; if (jv_get_kind(a) != jv_get_kind(b)) { r = 0; - } else if (jv_get_kind(a) == JV_KIND_NUMBER) { - r = jv_number_value(a) == jv_number_value(b); - } else if (a.kind_flags == b.kind_flags && + } else if (JVP_IS_ALLOCATED(a) && + JVP_IS_ALLOCATED(b) && + a.kind_flags == b.kind_flags && a.size == b.size && a.u.ptr == b.u.ptr) { r = 1; } else { switch (jv_get_kind(a)) { + case JV_KIND_NUMBER: + r = jvp_number_equal(a, b); + break; case JV_KIND_ARRAY: r = jvp_array_equal(a, b); break; @@ -1316,18 +1651,10 @@ int jv_identical(jv a, jv b) { || a.size != b.size) { r = 0; } else { - switch (jv_get_kind(a)) { - case JV_KIND_ARRAY: - case JV_KIND_STRING: - case JV_KIND_OBJECT: + if (JVP_IS_ALLOCATED(a) /* b has the same flags */) { r = a.u.ptr == b.u.ptr; - break; - case JV_KIND_NUMBER: - r = memcmp(&a.u.number, &b.u.number, sizeof(a.u.number)) == 0; - break; - default: - r = 1; - break; + } else { + r = memcmp(&a.u.ptr, &b.u.ptr, sizeof(a.u)) == 0; } } jv_free(a); @@ -1339,11 +1666,11 @@ int jv_contains(jv a, jv b) { int r = 1; if (jv_get_kind(a) != jv_get_kind(b)) { r = 0; - } else if (jv_get_kind(a) == JV_KIND_OBJECT) { - r = jv_object_contains(jv_copy(a), jv_copy(b)); - } else if (jv_get_kind(a) == JV_KIND_ARRAY) { - r = jv_array_contains(jv_copy(a), jv_copy(b)); - } else if (jv_get_kind(a) == JV_KIND_STRING) { + } else if (JVP_HAS_KIND(a, JV_KIND_OBJECT)) { + r = jvp_object_contains(a, b); + } else if (JVP_HAS_KIND(a, JV_KIND_ARRAY)) { + r = jvp_array_contains(a, b); + } else if (JVP_HAS_KIND(a, JV_KIND_STRING)) { int b_len = jv_string_length_bytes(jv_copy(b)); if (b_len != 0) { r = _jq_memmem(jv_string_value(a), jv_string_length_bytes(jv_copy(a)), diff --git a/src/jv.h b/src/jv.h index d111c80b29..8c96f822f0 100644 --- a/src/jv.h +++ b/src/jv.h @@ -54,16 +54,19 @@ jv jv_invalid_with_msg(jv); jv jv_invalid_get_msg(jv); int jv_invalid_has_msg(jv); - jv jv_null(void); jv jv_true(void); jv jv_false(void); jv jv_bool(int); jv jv_number(double); +jv jv_number_with_literal(const char*); double jv_number_value(jv); int jv_is_integer(jv); +int jv_number_has_literal(jv n); +const char* jv_number_get_literal(jv); + jv jv_array(void); jv jv_array_sized(int); int jv_array_length(jv); diff --git a/src/jv_aux.c b/src/jv_aux.c index 129cd043d1..eca2345fec 100644 --- a/src/jv_aux.c +++ b/src/jv_aux.c @@ -2,6 +2,16 @@ #include #include #include "jv_alloc.h" +#include "jv_type_private.h" + +// making this static verbose function here +// until we introduce a less confusing naming scheme +// of jv_* API with regards to the memory management +static double jv_number_get_value_and_consume(jv number) { + double value = jv_number_value(number); + jv_free(number); + return value; +} static int parse_slice(jv j, jv slice, int* pstart, int* pend) { // Array slices @@ -32,6 +42,8 @@ static int parse_slice(jv j, jv slice, int* pstart, int* pend) { } else { double dstart = jv_number_value(start_jv); double dend = jv_number_value(end_jv); + jv_free(start_jv); + jv_free(end_jv); if (dstart < 0) dstart += len; if (dend < 0) dend += len; if (dstart < 0) dstart = 0; @@ -69,6 +81,7 @@ jv jv_get(jv t, jv k) { jv_free(v); v = jv_null(); } + jv_free(k); } else { jv_free(t); jv_free(k); @@ -135,6 +148,7 @@ jv jv_set(jv t, jv k, jv v) { (jv_get_kind(t) == JV_KIND_ARRAY || isnull)) { if (isnull) t = jv_array(); t = jv_array_set(t, (int)jv_number_value(k), v); + jv_free(k); } else if (jv_get_kind(k) == JV_KIND_OBJECT && (jv_get_kind(t) == JV_KIND_ARRAY || isnull)) { if (isnull) t = jv_array(); @@ -202,6 +216,7 @@ jv jv_has(jv t, jv k) { jv_get_kind(k) == JV_KIND_NUMBER) { jv elem = jv_array_get(t, (int)jv_number_value(k)); ret = jv_bool(jv_is_valid(elem)); + jv_free(k); jv_free(elem); } else { ret = jv_invalid_with_msg(jv_string_fmt("Cannot check whether %s has a %s key", @@ -240,6 +255,7 @@ static jv jv_dels(jv t, jv keys) { ends = jv_array_append(ends, jv_number(end)); } else { jv_free(new_array); + jv_free(key); new_array = jv_invalid_with_msg(jv_string_fmt("Start and end indices of an array slice must be numbers")); goto arr_out; } @@ -258,7 +274,7 @@ static jv jv_dels(jv t, jv keys) { jv_array_foreach(t, i, elem) { int del = 0; while (neg_idx < jv_array_length(jv_copy(neg_keys))) { - int delidx = len + (int)jv_number_value(jv_array_get(jv_copy(neg_keys), neg_idx)); + int delidx = len + (int)jv_number_get_value_and_consume(jv_array_get(jv_copy(neg_keys), neg_idx)); if (i == delidx) { del = 1; } @@ -268,7 +284,7 @@ static jv jv_dels(jv t, jv keys) { neg_idx++; } while (nonneg_idx < jv_array_length(jv_copy(nonneg_keys))) { - int delidx = (int)jv_number_value(jv_array_get(jv_copy(nonneg_keys), nonneg_idx)); + int delidx = (int)jv_number_get_value_and_consume(jv_array_get(jv_copy(nonneg_keys), nonneg_idx)); if (i == delidx) { del = 1; } @@ -278,8 +294,8 @@ static jv jv_dels(jv t, jv keys) { nonneg_idx++; } for (int sidx=0; !del && sidx +#include +#include + +#include "jv_dtoa_tsd.h" +#include "jv_dtoa.h" +#include "jv_alloc.h" + + +static pthread_key_t dtoa_ctx_key; +static pthread_once_t dtoa_ctx_once = PTHREAD_ONCE_INIT; + +static void tsd_dtoa_ctx_dtor(struct dtoa_context *ctx) { + if (ctx) { + jvp_dtoa_context_free(ctx); + jv_mem_free(ctx); + } +} + +static void tsd_dtoa_ctx_fini() { + struct dtoa_context *ctx = pthread_getspecific(dtoa_ctx_key); + tsd_dtoa_ctx_dtor(ctx); + pthread_setspecific(dtoa_ctx_key, NULL); +} + +static void tsd_dtoa_ctx_init() { + if (pthread_key_create(&dtoa_ctx_key, tsd_dtoa_ctx_dtor) != 0) { + fprintf(stderr, "error: cannot create thread specific key"); + abort(); + } + atexit(tsd_dtoa_ctx_fini); +} + +inline struct dtoa_context *tsd_dtoa_context_get() { + pthread_once(&dtoa_ctx_once, tsd_dtoa_ctx_init); // cannot fail + struct dtoa_context *ctx = (struct dtoa_context*)pthread_getspecific(dtoa_ctx_key); + if (!ctx) { + ctx = malloc(sizeof(struct dtoa_context)); + jvp_dtoa_context_init(ctx); + if (pthread_setspecific(dtoa_ctx_key, ctx) != 0) { + fprintf(stderr, "error: cannot set thread specific data"); + abort(); + } + } + return ctx; +} \ No newline at end of file diff --git a/src/jv_dtoa_tsd.h b/src/jv_dtoa_tsd.h new file mode 100644 index 0000000000..2431d08e38 --- /dev/null +++ b/src/jv_dtoa_tsd.h @@ -0,0 +1,4 @@ +#ifndef JV_DTOA_TSD_H +#define JV_DTOA_TSD_H +struct dtoa_context *tsd_dtoa_context_get(); +#endif diff --git a/src/jv_parse.c b/src/jv_parse.c index 51ad9f0947..9ced9f6d23 100644 --- a/src/jv_parse.c +++ b/src/jv_parse.c @@ -124,14 +124,19 @@ static void parser_free(struct jv_parser* p) { static pfunc value(struct jv_parser* p, jv val) { if ((p->flags & JV_PARSE_STREAMING)) { - if (jv_is_valid(p->next) || p->last_seen == JV_LAST_VALUE) + if (jv_is_valid(p->next) || p->last_seen == JV_LAST_VALUE) { + jv_free(val); return "Expected separator between values"; + } if (p->stacklen > 0) p->last_seen = JV_LAST_VALUE; else p->last_seen = JV_LAST_NONE; } else { - if (jv_is_valid(p->next)) return "Expected separator between values"; + if (jv_is_valid(p->next)) { + jv_free(val); + return "Expected separator between values"; + } } jv_free(p->next); p->next = val; @@ -256,8 +261,12 @@ static pfunc stream_token(struct jv_parser* p, char ch) { break; case ':': - if (p->stacklen == 0 || jv_get_kind(jv_array_get(jv_copy(p->path), p->stacklen - 1)) == JV_KIND_NUMBER) + last = jv_invalid(); + if (p->stacklen == 0 || jv_get_kind(last = jv_array_get(jv_copy(p->path), p->stacklen - 1)) == JV_KIND_NUMBER) { + jv_free(last); return "':' not as part of an object"; + } + jv_free(last); if (!jv_is_valid(p->next) || p->last_seen == JV_LAST_NONE) return "Expected string key before ':'"; if (jv_get_kind(p->next) != JV_KIND_STRING) @@ -492,11 +501,20 @@ static pfunc check_literal(struct jv_parser* p) { } else { // FIXME: better parser p->tokenbuf[p->tokenpos] = 0; - char* end = 0; +#ifdef USE_DECNUM + jv number = jv_number_with_literal(p->tokenbuf); + if (jv_get_kind(number) == JV_KIND_INVALID) { + return "Invalid numeric literal"; + } + TRY(value(p, number)); +#else + char *end = 0; double d = jvp_strtod(&p->dtoa, p->tokenbuf, &end); - if (end == 0 || *end != 0) + if (end == 0 || *end != 0) { return "Invalid numeric literal"; + } TRY(value(p, jv_number(d))); +#endif } p->tokenpos = 0; return 0; diff --git a/src/jv_print.c b/src/jv_print.c index 5ebc01e628..15532c6938 100644 --- a/src/jv_print.c +++ b/src/jv_print.c @@ -11,8 +11,10 @@ #include "jv.h" #include "jv_dtoa.h" +#include "jv_dtoa_tsd.h" #include "jv_unicode.h" #include "jv_alloc.h" +#include "jv_type_private.h" #ifndef MAX_PRINT_DEPTH #define MAX_PRINT_DEPTH (256) @@ -229,16 +231,29 @@ static void jv_dump_term(struct dtoa_context* C, jv x, int flags, int indent, FI put_str("true", F, S, flags & JV_PRINT_ISATTY); break; case JV_KIND_NUMBER: { - double d = jv_number_value(x); - if (d != d) { - // JSON doesn't have NaN, so we'll render it as "null" - put_str("null", F, S, flags & JV_PRINT_ISATTY); + if (jvp_number_is_nan(x)) { + jv_dump_term(C, jv_null(), flags, indent, F, S); } else { - // Normalise infinities to something we can print in valid JSON - if (d > DBL_MAX) d = DBL_MAX; - if (d < -DBL_MAX) d = -DBL_MAX; - put_str(jvp_dtoa_fmt(C, buf, d), F, S, flags & JV_PRINT_ISATTY); +#ifdef USE_DECNUM + const char * literal_data = jv_number_get_literal(x); + if (literal_data) { + put_str(literal_data, F, S, flags & JV_PRINT_ISATTY); + } else { +#endif + double d = jv_number_value(x); + if (d != d) { + // JSON doesn't have NaN, so we'll render it as "null" + put_str("null", F, S, flags & JV_PRINT_ISATTY); + } else { + // Normalise infinities to something we can print in valid JSON + if (d > DBL_MAX) d = DBL_MAX; + if (d < -DBL_MAX) d = -DBL_MAX; + put_str(jvp_dtoa_fmt(C, buf, d), F, S, flags & JV_PRINT_ISATTY); + } + } +#ifdef USE_DECNUM } +#endif break; } case JV_KIND_STRING: @@ -357,10 +372,7 @@ static void jv_dump_term(struct dtoa_context* C, jv x, int flags, int indent, FI } void jv_dumpf(jv x, FILE *f, int flags) { - struct dtoa_context C; - jvp_dtoa_context_init(&C); - jv_dump_term(&C, x, flags, 0, f, 0); - jvp_dtoa_context_free(&C); + jv_dump_term(tsd_dtoa_context_get(), x, flags, 0, f, 0); } void jv_dump(jv x, int flags) { @@ -376,11 +388,8 @@ void jv_show(jv x, int flags) { } jv jv_dump_string(jv x, int flags) { - struct dtoa_context C; - jvp_dtoa_context_init(&C); jv s = jv_string(""); - jv_dump_term(&C, x, flags, 0, 0, &s); - jvp_dtoa_context_free(&C); + jv_dump_term(tsd_dtoa_context_get(), x, flags, 0, 0, &s); return s; } diff --git a/src/jv_type_private.h b/src/jv_type_private.h new file mode 100644 index 0000000000..5996282ba5 --- /dev/null +++ b/src/jv_type_private.h @@ -0,0 +1,7 @@ +#ifndef JV_TYPE_PRIVATE +#define JV_TYPE_PRIVATE + +int jvp_number_cmp(jv, jv); +int jvp_number_is_nan(jv); + +#endif //JV_TYPE_PRIVATE diff --git a/src/parser.c b/src/parser.c index d9210a980b..b6574e52c8 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.3.2. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,11 +41,14 @@ define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.0.4" +#define YYBISON_VERSION "3.3.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -61,8 +65,8 @@ -/* Copy the first part of user declarations. */ -#line 1 "src/parser.y" /* yacc.c:339 */ +/* First part of user prologue. */ +#line 1 "src/parser.y" /* yacc.c:337 */ #include #include @@ -73,13 +77,16 @@ #define YYMALLOC jv_mem_alloc #define YYFREE jv_mem_free -#line 77 "src/parser.c" /* yacc.c:339 */ - +#line 81 "src/parser.c" /* yacc.c:337 */ # ifndef YY_NULLPTR -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULLPTR nullptr +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif # else -# define YY_NULLPTR 0 +# define YY_NULLPTR ((void*)0) # endif # endif @@ -103,7 +110,7 @@ extern int yydebug; #endif /* "%code requires" blocks. */ -#line 11 "src/parser.y" /* yacc.c:355 */ +#line 11 "src/parser.y" /* yacc.c:352 */ #include "locfile.h" struct lexer_param; @@ -120,7 +127,7 @@ struct lexer_param; } \ } while (0) -#line 124 "src/parser.c" /* yacc.c:355 */ +#line 131 "src/parser.c" /* yacc.c:352 */ /* Token type. */ #ifndef YYTOKENTYPE @@ -226,12 +233,12 @@ struct lexer_param; union YYSTYPE { -#line 31 "src/parser.y" /* yacc.c:355 */ +#line 31 "src/parser.y" /* yacc.c:352 */ jv literal; block blk; -#line 235 "src/parser.c" /* yacc.c:355 */ +#line 242 "src/parser.c" /* yacc.c:352 */ }; typedef union YYSTYPE YYSTYPE; @@ -259,8 +266,8 @@ int yyparse (block* answer, int* errors, struct locfile* locations, struct lexer #endif /* !YY_YY_SRC_PARSER_H_INCLUDED */ -/* Copy the second part of user declarations. */ -#line 124 "src/parser.y" /* yacc.c:358 */ +/* Second part of user prologue. */ +#line 124 "src/parser.y" /* yacc.c:354 */ #include "lexer.h" struct lexer_param { @@ -312,7 +319,7 @@ static jv check_object_key(block k) { char errbuf[15]; return jv_string_fmt("Cannot use %s (%s) as object key", jv_kind_name(block_const_kind(k)), - jv_dump_string_trunc(jv_copy(block_const(k)), errbuf, sizeof(errbuf))); + jv_dump_string_trunc(block_const(k), errbuf, sizeof(errbuf))); } return jv_invalid(); } @@ -356,19 +363,25 @@ static block constant_fold(block a, block b, int op) { jv res = jv_invalid(); if (block_const_kind(a) == JV_KIND_NUMBER) { - double na = jv_number_value(block_const(a)); - double nb = jv_number_value(block_const(b)); + jv jv_a = block_const(a); + jv jv_b = block_const(b); + + double na = jv_number_value(jv_a); + double nb = jv_number_value(jv_b); + + int cmp = jv_cmp(jv_a, jv_b); + switch (op) { case '+': res = jv_number(na + nb); break; case '-': res = jv_number(na - nb); break; case '*': res = jv_number(na * nb); break; case '/': res = jv_number(na / nb); break; - case EQ: res = (na == nb ? jv_true() : jv_false()); break; - case NEQ: res = (na != nb ? jv_true() : jv_false()); break; - case '<': res = (na < nb ? jv_true() : jv_false()); break; - case '>': res = (na > nb ? jv_true() : jv_false()); break; - case LESSEQ: res = (na <= nb ? jv_true() : jv_false()); break; - case GREATEREQ: res = (na >= nb ? jv_true() : jv_false()); break; + case EQ: res = (cmp == 0 ? jv_true() : jv_false()); break; + case NEQ: res = (cmp != 0 ? jv_true() : jv_false()); break; + case '<': res = (cmp < 0 ? jv_true() : jv_false()); break; + case '>': res = (cmp > 0 ? jv_true() : jv_false()); break; + case LESSEQ: res = (cmp <= 0 ? jv_true() : jv_false()); break; + case GREATEREQ: res = (cmp >= 0 ? jv_true() : jv_false()); break; default: break; } } else if (op == '+' && block_const_kind(a) == JV_KIND_STRING) { @@ -434,7 +447,7 @@ static block gen_update(block object, block val, int optype) { } -#line 438 "src/parser.c" /* yacc.c:358 */ +#line 451 "src/parser.c" /* yacc.c:354 */ #ifdef short # undef short @@ -455,13 +468,13 @@ typedef signed char yytype_int8; #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else -typedef unsigned short int yytype_uint16; +typedef unsigned short yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else -typedef short int yytype_int16; +typedef short yytype_int16; #endif #ifndef YYSIZE_T @@ -473,7 +486,7 @@ typedef short int yytype_int16; # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else -# define YYSIZE_T unsigned int +# define YYSIZE_T unsigned # endif #endif @@ -509,15 +522,6 @@ typedef short int yytype_int16; # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) #endif -#if !defined _Noreturn \ - && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) -# if defined _MSC_VER && 1200 <= _MSC_VER -# define _Noreturn __declspec (noreturn) -# else -# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) -# endif -#endif - /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(E) ((void) (E)) @@ -525,7 +529,7 @@ typedef short int yytype_int16; # define YYUSE(E) /* empty */ #endif -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ @@ -689,16 +693,16 @@ union yyalloc /* YYNSTATES -- Number of states. */ #define YYNSTATES 322 -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned - by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 302 +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ #define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, without out-of-bounds checking. */ + as returned by yylex. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -738,23 +742,23 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 300, 300, 303, 308, 311, 322, 325, 330, 333, - 338, 342, 345, 349, 353, 357, 360, 363, 368, 372, - 376, 381, 388, 392, 396, 400, 404, 408, 412, 416, - 420, 424, 428, 432, 436, 440, 444, 448, 452, 458, - 464, 468, 472, 476, 480, 484, 488, 492, 496, 501, - 504, 521, 530, 537, 545, 556, 561, 567, 570, 575, - 579, 583, 590, 590, 594, 594, 601, 604, 607, 613, - 616, 621, 624, 627, 633, 636, 639, 647, 651, 654, - 657, 660, 663, 666, 669, 672, 675, 679, 685, 688, - 691, 694, 697, 700, 703, 706, 709, 712, 715, 718, - 721, 724, 727, 730, 733, 736, 739, 746, 750, 759, - 771, 776, 777, 778, 779, 782, 785, 790, 795, 798, - 803, 806, 811, 815, 818, 823, 826, 831, 834, 839, - 842, 845, 848, 851, 854, 862, 868, 871, 874, 877, - 880, 883, 886, 889, 892, 895, 898, 901, 904, 907, - 910, 913, 916, 919, 922, 927, 930, 931, 932, 935, - 938, 941, 944, 948, 952, 956, 960, 964, 968, 976 + 0, 306, 306, 309, 314, 317, 328, 331, 336, 339, + 344, 348, 351, 355, 359, 363, 366, 369, 374, 378, + 382, 387, 394, 398, 402, 406, 410, 414, 418, 422, + 426, 430, 434, 438, 442, 446, 450, 454, 458, 464, + 470, 474, 478, 482, 486, 490, 494, 498, 502, 507, + 510, 527, 536, 543, 551, 562, 567, 573, 576, 581, + 585, 589, 596, 596, 600, 600, 607, 610, 613, 619, + 622, 627, 630, 633, 639, 642, 645, 653, 657, 660, + 663, 666, 669, 672, 675, 678, 681, 685, 691, 694, + 697, 700, 703, 706, 709, 712, 715, 718, 721, 724, + 727, 730, 733, 736, 739, 742, 745, 752, 756, 765, + 777, 782, 783, 784, 785, 788, 791, 796, 801, 804, + 809, 812, 817, 821, 824, 829, 832, 837, 840, 845, + 848, 851, 854, 857, 860, 868, 874, 877, 880, 883, + 886, 889, 892, 895, 898, 901, 904, 907, 910, 913, + 916, 919, 922, 925, 928, 933, 936, 937, 938, 941, + 944, 947, 950, 954, 958, 962, 966, 970, 974, 982 }; #endif @@ -1455,22 +1459,22 @@ static const yytype_uint8 yyr2[] = #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (&yylloc, answer, errors, locations, lexer_param_ptr, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (0) +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (&yylloc, answer, errors, locations, lexer_param_ptr, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) /* Error token number */ #define YYTERROR 1 @@ -1529,10 +1533,10 @@ do { \ /* Print *YYLOCP on YYO. Private, do not rely on its existence. */ YY_ATTRIBUTE_UNUSED -static unsigned +static int yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) { - unsigned res = 0; + int res = 0; int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; if (0 <= yylocp->first_line) { @@ -1575,15 +1579,15 @@ do { \ } while (0) -/*----------------------------------------. -| Print this symbol's value on YYOUTPUT. | -`----------------------------------------*/ +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, block* answer, int* errors, struct locfile* locations, struct lexer_param* lexer_param_ptr) +yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, block* answer, int* errors, struct locfile* locations, struct lexer_param* lexer_param_ptr) { - FILE *yyo = yyoutput; - YYUSE (yyo); + FILE *yyoutput = yyo; + YYUSE (yyoutput); YYUSE (yylocationp); YYUSE (answer); YYUSE (errors); @@ -1593,26 +1597,26 @@ yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvalue return; # ifdef YYPRINT if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); + YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif YYUSE (yytype); } -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, block* answer, int* errors, struct locfile* locations, struct lexer_param* lexer_param_ptr) +yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, block* answer, int* errors, struct locfile* locations, struct lexer_param* lexer_param_ptr) { - YYFPRINTF (yyoutput, "%s %s (", + YYFPRINTF (yyo, "%s %s (", yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - YY_LOCATION_PRINT (yyoutput, *yylocationp); - YYFPRINTF (yyoutput, ": "); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, answer, errors, locations, lexer_param_ptr); - YYFPRINTF (yyoutput, ")"); + YY_LOCATION_PRINT (yyo, *yylocationp); + YYFPRINTF (yyo, ": "); + yy_symbol_value_print (yyo, yytype, yyvaluep, yylocationp, answer, errors, locations, lexer_param_ptr); + YYFPRINTF (yyo, ")"); } /*------------------------------------------------------------------. @@ -1646,7 +1650,7 @@ do { \ static void yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, block* answer, int* errors, struct locfile* locations, struct lexer_param* lexer_param_ptr) { - unsigned long int yylno = yyrline[yyrule]; + unsigned long yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", @@ -1657,7 +1661,7 @@ yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yystos[yyssp[yyi + 1 - yynrhs]], - &(yyvsp[(yyi + 1) - (yynrhs)]) + &yyvsp[(yyi + 1) - (yynrhs)] , &(yylsp[(yyi + 1) - (yynrhs)]) , answer, errors, locations, lexer_param_ptr); YYFPRINTF (stderr, "\n"); } @@ -1761,7 +1765,10 @@ yytnamerr (char *yyres, const char *yystr) case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; - /* Fall through. */ + else + goto append; + + append: default: if (yyres) yyres[yyn] = *yyp; @@ -1779,7 +1786,7 @@ yytnamerr (char *yyres, const char *yystr) if (! yyres) return yystrlen (yystr); - return yystpcpy (yyres, yystr) - yyres; + return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres); } # endif @@ -1857,10 +1864,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yyarg[yycount++] = yytname[yyx]; { YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } } } @@ -1872,6 +1879,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, case N: \ yyformat = S; \ break + default: /* Avoid compiler warnings. */ YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); @@ -1883,9 +1891,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, { YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } if (*yymsg_alloc < yysize) @@ -1939,193 +1948,192 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocatio YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN switch (yytype) { - case 4: /* IDENT */ + case 4: /* IDENT */ #line 36 "src/parser.y" /* yacc.c:1257 */ { jv_free(((*yyvaluep).literal)); } -#line 1946 "src/parser.c" /* yacc.c:1257 */ +#line 1955 "src/parser.c" /* yacc.c:1257 */ break; case 5: /* FIELD */ #line 36 "src/parser.y" /* yacc.c:1257 */ { jv_free(((*yyvaluep).literal)); } -#line 1952 "src/parser.c" /* yacc.c:1257 */ +#line 1961 "src/parser.c" /* yacc.c:1257 */ break; case 6: /* LITERAL */ #line 36 "src/parser.y" /* yacc.c:1257 */ { jv_free(((*yyvaluep).literal)); } -#line 1958 "src/parser.c" /* yacc.c:1257 */ +#line 1967 "src/parser.c" /* yacc.c:1257 */ break; case 7: /* FORMAT */ #line 36 "src/parser.y" /* yacc.c:1257 */ { jv_free(((*yyvaluep).literal)); } -#line 1964 "src/parser.c" /* yacc.c:1257 */ +#line 1973 "src/parser.c" /* yacc.c:1257 */ break; case 42: /* QQSTRING_TEXT */ #line 36 "src/parser.y" /* yacc.c:1257 */ { jv_free(((*yyvaluep).literal)); } -#line 1970 "src/parser.c" /* yacc.c:1257 */ +#line 1979 "src/parser.c" /* yacc.c:1257 */ break; case 71: /* Module */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 1976 "src/parser.c" /* yacc.c:1257 */ +#line 1985 "src/parser.c" /* yacc.c:1257 */ break; case 72: /* Imports */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 1982 "src/parser.c" /* yacc.c:1257 */ +#line 1991 "src/parser.c" /* yacc.c:1257 */ break; case 73: /* FuncDefs */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 1988 "src/parser.c" /* yacc.c:1257 */ +#line 1997 "src/parser.c" /* yacc.c:1257 */ break; case 74: /* Exp */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 1994 "src/parser.c" /* yacc.c:1257 */ +#line 2003 "src/parser.c" /* yacc.c:1257 */ break; case 75: /* Import */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2000 "src/parser.c" /* yacc.c:1257 */ +#line 2009 "src/parser.c" /* yacc.c:1257 */ break; case 76: /* ImportWhat */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2006 "src/parser.c" /* yacc.c:1257 */ +#line 2015 "src/parser.c" /* yacc.c:1257 */ break; case 77: /* ImportFrom */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2012 "src/parser.c" /* yacc.c:1257 */ +#line 2021 "src/parser.c" /* yacc.c:1257 */ break; case 78: /* FuncDef */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2018 "src/parser.c" /* yacc.c:1257 */ +#line 2027 "src/parser.c" /* yacc.c:1257 */ break; case 79: /* Params */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2024 "src/parser.c" /* yacc.c:1257 */ +#line 2033 "src/parser.c" /* yacc.c:1257 */ break; case 80: /* Param */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2030 "src/parser.c" /* yacc.c:1257 */ +#line 2039 "src/parser.c" /* yacc.c:1257 */ break; case 81: /* String */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2036 "src/parser.c" /* yacc.c:1257 */ +#line 2045 "src/parser.c" /* yacc.c:1257 */ break; case 84: /* QQString */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2042 "src/parser.c" /* yacc.c:1257 */ +#line 2051 "src/parser.c" /* yacc.c:1257 */ break; case 85: /* ElseBody */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2048 "src/parser.c" /* yacc.c:1257 */ +#line 2057 "src/parser.c" /* yacc.c:1257 */ break; case 86: /* ExpD */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2054 "src/parser.c" /* yacc.c:1257 */ +#line 2063 "src/parser.c" /* yacc.c:1257 */ break; case 87: /* Term */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2060 "src/parser.c" /* yacc.c:1257 */ +#line 2069 "src/parser.c" /* yacc.c:1257 */ break; case 88: /* Args */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2066 "src/parser.c" /* yacc.c:1257 */ +#line 2075 "src/parser.c" /* yacc.c:1257 */ break; case 89: /* Arg */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2072 "src/parser.c" /* yacc.c:1257 */ +#line 2081 "src/parser.c" /* yacc.c:1257 */ break; case 90: /* RepPatterns */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2078 "src/parser.c" /* yacc.c:1257 */ +#line 2087 "src/parser.c" /* yacc.c:1257 */ break; case 91: /* Patterns */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2084 "src/parser.c" /* yacc.c:1257 */ +#line 2093 "src/parser.c" /* yacc.c:1257 */ break; case 92: /* Pattern */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2090 "src/parser.c" /* yacc.c:1257 */ +#line 2099 "src/parser.c" /* yacc.c:1257 */ break; case 93: /* ArrayPats */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2096 "src/parser.c" /* yacc.c:1257 */ +#line 2105 "src/parser.c" /* yacc.c:1257 */ break; case 94: /* ObjPats */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2102 "src/parser.c" /* yacc.c:1257 */ +#line 2111 "src/parser.c" /* yacc.c:1257 */ break; case 95: /* ObjPat */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2108 "src/parser.c" /* yacc.c:1257 */ +#line 2117 "src/parser.c" /* yacc.c:1257 */ break; case 96: /* Keyword */ #line 36 "src/parser.y" /* yacc.c:1257 */ { jv_free(((*yyvaluep).literal)); } -#line 2114 "src/parser.c" /* yacc.c:1257 */ +#line 2123 "src/parser.c" /* yacc.c:1257 */ break; case 97: /* MkDict */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2120 "src/parser.c" /* yacc.c:1257 */ +#line 2129 "src/parser.c" /* yacc.c:1257 */ break; case 98: /* MkDictPair */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2126 "src/parser.c" /* yacc.c:1257 */ +#line 2135 "src/parser.c" /* yacc.c:1257 */ break; - default: break; } @@ -2231,23 +2239,31 @@ YYLTYPE yylloc = yyloc_default; yylsp[0] = yylloc; goto yysetstate; + /*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | +| yynewstate -- push a new state, which is found in yystate. | `------------------------------------------------------------*/ - yynewstate: +yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; - yysetstate: - *yyssp = yystate; + +/*--------------------------------------------------------------------. +| yynewstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + *yyssp = (yytype_int16) yystate; if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + goto yyexhaustedlab; +#else { /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; + YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1); -#ifdef yyoverflow +# if defined yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into @@ -2265,15 +2281,11 @@ YYLTYPE yylloc = yyloc_default; &yyvs1, yysize * sizeof (*yyvsp), &yyls1, yysize * sizeof (*yylsp), &yystacksize); - - yyls = yyls1; yyss = yyss1; yyvs = yyvs1; + yyls = yyls1; } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else +# else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; @@ -2290,23 +2302,23 @@ YYLTYPE yylloc = yyloc_default; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); YYSTACK_RELOCATE (yyls_alloc, yyls); -# undef YYSTACK_RELOCATE +# undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif -#endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; yylsp = yyls + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + (unsigned long) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ YYDPRINTF ((stderr, "Entering state %d\n", yystate)); @@ -2315,11 +2327,11 @@ YYLTYPE yylloc = yyloc_default; goto yybackup; + /*-----------. | yybackup. | `-----------*/ yybackup: - /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ @@ -2392,7 +2404,7 @@ YYLTYPE yylloc = yyloc_default; /*-----------------------------. -| yyreduce -- Do a reduction. | +| yyreduce -- do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ @@ -2408,37 +2420,38 @@ YYLTYPE yylloc = yyloc_default; GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; - /* Default location. */ + /* Default location. */ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); + yyerror_range[1] = yyloc; YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: -#line 300 "src/parser.y" /* yacc.c:1646 */ +#line 306 "src/parser.y" /* yacc.c:1667 */ { *answer = BLOCK((yyvsp[-2].blk), (yyvsp[-1].blk), gen_op_simple(TOP), (yyvsp[0].blk)); } -#line 2422 "src/parser.c" /* yacc.c:1646 */ +#line 2435 "src/parser.c" /* yacc.c:1667 */ break; case 3: -#line 303 "src/parser.y" /* yacc.c:1646 */ +#line 309 "src/parser.y" /* yacc.c:1667 */ { *answer = BLOCK((yyvsp[-2].blk), (yyvsp[-1].blk), (yyvsp[0].blk)); } -#line 2430 "src/parser.c" /* yacc.c:1646 */ +#line 2443 "src/parser.c" /* yacc.c:1667 */ break; case 4: -#line 308 "src/parser.y" /* yacc.c:1646 */ +#line 314 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_noop(); } -#line 2438 "src/parser.c" /* yacc.c:1646 */ +#line 2451 "src/parser.c" /* yacc.c:1667 */ break; case 5: -#line 311 "src/parser.y" /* yacc.c:1646 */ +#line 317 "src/parser.y" /* yacc.c:1667 */ { if (!block_is_const((yyvsp[-1].blk))) { FAIL((yyloc), "Module metadata must be constant"); @@ -2448,374 +2461,374 @@ YYLTYPE yylloc = yyloc_default; (yyval.blk) = gen_module((yyvsp[-1].blk)); } } -#line 2452 "src/parser.c" /* yacc.c:1646 */ +#line 2465 "src/parser.c" /* yacc.c:1667 */ break; case 6: -#line 322 "src/parser.y" /* yacc.c:1646 */ +#line 328 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_noop(); } -#line 2460 "src/parser.c" /* yacc.c:1646 */ +#line 2473 "src/parser.c" /* yacc.c:1667 */ break; case 7: -#line 325 "src/parser.y" /* yacc.c:1646 */ +#line 331 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-1].blk), (yyvsp[0].blk)); } -#line 2468 "src/parser.c" /* yacc.c:1646 */ +#line 2481 "src/parser.c" /* yacc.c:1667 */ break; case 8: -#line 330 "src/parser.y" /* yacc.c:1646 */ +#line 336 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_noop(); } -#line 2476 "src/parser.c" /* yacc.c:1646 */ +#line 2489 "src/parser.c" /* yacc.c:1667 */ break; case 9: -#line 333 "src/parser.y" /* yacc.c:1646 */ +#line 339 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = block_join((yyvsp[-1].blk), (yyvsp[0].blk)); } -#line 2484 "src/parser.c" /* yacc.c:1646 */ +#line 2497 "src/parser.c" /* yacc.c:1667 */ break; case 10: -#line 338 "src/parser.y" /* yacc.c:1646 */ +#line 344 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = block_bind_referenced((yyvsp[-1].blk), (yyvsp[0].blk), OP_IS_CALL_PSEUDO); } -#line 2492 "src/parser.c" /* yacc.c:1646 */ +#line 2505 "src/parser.c" /* yacc.c:1667 */ break; case 11: -#line 342 "src/parser.y" /* yacc.c:1646 */ +#line 348 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_destructure((yyvsp[-4].blk), (yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2500 "src/parser.c" /* yacc.c:1646 */ +#line 2513 "src/parser.c" /* yacc.c:1667 */ break; case 12: -#line 345 "src/parser.y" /* yacc.c:1646 */ +#line 351 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_reduce((yyvsp[-7].blk), (yyvsp[-5].blk), (yyvsp[-3].blk), (yyvsp[-1].blk)); } -#line 2508 "src/parser.c" /* yacc.c:1646 */ +#line 2521 "src/parser.c" /* yacc.c:1667 */ break; case 13: -#line 349 "src/parser.y" /* yacc.c:1646 */ +#line 355 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_foreach((yyvsp[-9].blk), (yyvsp[-7].blk), (yyvsp[-5].blk), (yyvsp[-3].blk), (yyvsp[-1].blk)); } -#line 2516 "src/parser.c" /* yacc.c:1646 */ +#line 2529 "src/parser.c" /* yacc.c:1667 */ break; case 14: -#line 353 "src/parser.y" /* yacc.c:1646 */ +#line 359 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_foreach((yyvsp[-7].blk), (yyvsp[-5].blk), (yyvsp[-3].blk), (yyvsp[-1].blk), gen_noop()); } -#line 2524 "src/parser.c" /* yacc.c:1646 */ +#line 2537 "src/parser.c" /* yacc.c:1667 */ break; case 15: -#line 357 "src/parser.y" /* yacc.c:1646 */ +#line 363 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_cond((yyvsp[-3].blk), (yyvsp[-1].blk), (yyvsp[0].blk)); } -#line 2532 "src/parser.c" /* yacc.c:1646 */ +#line 2545 "src/parser.c" /* yacc.c:1667 */ break; case 16: -#line 360 "src/parser.y" /* yacc.c:1646 */ +#line 366 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_cond((yyvsp[-3].blk), (yyvsp[-1].blk), gen_noop()); } -#line 2540 "src/parser.c" /* yacc.c:1646 */ +#line 2553 "src/parser.c" /* yacc.c:1667 */ break; case 17: -#line 363 "src/parser.y" /* yacc.c:1646 */ +#line 369 "src/parser.y" /* yacc.c:1667 */ { FAIL((yyloc), "Possibly unterminated 'if' statement"); (yyval.blk) = (yyvsp[-2].blk); } -#line 2549 "src/parser.c" /* yacc.c:1646 */ +#line 2562 "src/parser.c" /* yacc.c:1667 */ break; case 18: -#line 368 "src/parser.y" /* yacc.c:1646 */ +#line 374 "src/parser.y" /* yacc.c:1667 */ { //$$ = BLOCK(gen_op_target(FORK_OPT, $2), $2, $4); (yyval.blk) = gen_try((yyvsp[-2].blk), gen_try_handler((yyvsp[0].blk))); } -#line 2558 "src/parser.c" /* yacc.c:1646 */ +#line 2571 "src/parser.c" /* yacc.c:1667 */ break; case 19: -#line 372 "src/parser.y" /* yacc.c:1646 */ +#line 378 "src/parser.y" /* yacc.c:1667 */ { //$$ = BLOCK(gen_op_target(FORK_OPT, $2), $2, gen_op_simple(BACKTRACK)); (yyval.blk) = gen_try((yyvsp[0].blk), gen_op_simple(BACKTRACK)); } -#line 2567 "src/parser.c" /* yacc.c:1646 */ +#line 2580 "src/parser.c" /* yacc.c:1667 */ break; case 20: -#line 376 "src/parser.y" /* yacc.c:1646 */ +#line 382 "src/parser.y" /* yacc.c:1667 */ { FAIL((yyloc), "Possibly unterminated 'try' statement"); (yyval.blk) = (yyvsp[-2].blk); } -#line 2576 "src/parser.c" /* yacc.c:1646 */ +#line 2589 "src/parser.c" /* yacc.c:1667 */ break; case 21: -#line 381 "src/parser.y" /* yacc.c:1646 */ +#line 387 "src/parser.y" /* yacc.c:1667 */ { jv v = jv_string_fmt("*label-%s", jv_string_value((yyvsp[-2].literal))); (yyval.blk) = gen_location((yyloc), locations, gen_label(jv_string_value(v), (yyvsp[0].blk))); jv_free((yyvsp[-2].literal)); jv_free(v); } -#line 2587 "src/parser.c" /* yacc.c:1646 */ +#line 2600 "src/parser.c" /* yacc.c:1667 */ break; case 22: -#line 388 "src/parser.y" /* yacc.c:1646 */ +#line 394 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_try((yyvsp[-1].blk), gen_op_simple(BACKTRACK)); } -#line 2595 "src/parser.c" /* yacc.c:1646 */ +#line 2608 "src/parser.c" /* yacc.c:1667 */ break; case 23: -#line 392 "src/parser.y" /* yacc.c:1646 */ +#line 398 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_call("_assign", BLOCK(gen_lambda((yyvsp[-2].blk)), gen_lambda((yyvsp[0].blk)))); } -#line 2603 "src/parser.c" /* yacc.c:1646 */ +#line 2616 "src/parser.c" /* yacc.c:1667 */ break; case 24: -#line 396 "src/parser.y" /* yacc.c:1646 */ +#line 402 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_or((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2611 "src/parser.c" /* yacc.c:1646 */ +#line 2624 "src/parser.c" /* yacc.c:1667 */ break; case 25: -#line 400 "src/parser.y" /* yacc.c:1646 */ +#line 406 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_and((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2619 "src/parser.c" /* yacc.c:1646 */ +#line 2632 "src/parser.c" /* yacc.c:1667 */ break; case 26: -#line 404 "src/parser.y" /* yacc.c:1646 */ +#line 410 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_definedor((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2627 "src/parser.c" /* yacc.c:1646 */ +#line 2640 "src/parser.c" /* yacc.c:1667 */ break; case 27: -#line 408 "src/parser.y" /* yacc.c:1646 */ +#line 414 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_definedor_assign((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2635 "src/parser.c" /* yacc.c:1646 */ +#line 2648 "src/parser.c" /* yacc.c:1667 */ break; case 28: -#line 412 "src/parser.y" /* yacc.c:1646 */ +#line 418 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_call("_modify", BLOCK(gen_lambda((yyvsp[-2].blk)), gen_lambda((yyvsp[0].blk)))); } -#line 2643 "src/parser.c" /* yacc.c:1646 */ +#line 2656 "src/parser.c" /* yacc.c:1667 */ break; case 29: -#line 416 "src/parser.y" /* yacc.c:1646 */ +#line 422 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = block_join((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2651 "src/parser.c" /* yacc.c:1646 */ +#line 2664 "src/parser.c" /* yacc.c:1667 */ break; case 30: -#line 420 "src/parser.y" /* yacc.c:1646 */ +#line 426 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_both((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2659 "src/parser.c" /* yacc.c:1646 */ +#line 2672 "src/parser.c" /* yacc.c:1667 */ break; case 31: -#line 424 "src/parser.y" /* yacc.c:1646 */ +#line 430 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '+'); } -#line 2667 "src/parser.c" /* yacc.c:1646 */ +#line 2680 "src/parser.c" /* yacc.c:1667 */ break; case 32: -#line 428 "src/parser.y" /* yacc.c:1646 */ +#line 434 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '+'); } -#line 2675 "src/parser.c" /* yacc.c:1646 */ +#line 2688 "src/parser.c" /* yacc.c:1667 */ break; case 33: -#line 432 "src/parser.y" /* yacc.c:1646 */ +#line 438 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[0].blk), gen_call("_negate", gen_noop())); } -#line 2683 "src/parser.c" /* yacc.c:1646 */ +#line 2696 "src/parser.c" /* yacc.c:1667 */ break; case 34: -#line 436 "src/parser.y" /* yacc.c:1646 */ +#line 442 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '-'); } -#line 2691 "src/parser.c" /* yacc.c:1646 */ +#line 2704 "src/parser.c" /* yacc.c:1667 */ break; case 35: -#line 440 "src/parser.y" /* yacc.c:1646 */ +#line 446 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '-'); } -#line 2699 "src/parser.c" /* yacc.c:1646 */ +#line 2712 "src/parser.c" /* yacc.c:1667 */ break; case 36: -#line 444 "src/parser.y" /* yacc.c:1646 */ +#line 450 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '*'); } -#line 2707 "src/parser.c" /* yacc.c:1646 */ +#line 2720 "src/parser.c" /* yacc.c:1667 */ break; case 37: -#line 448 "src/parser.y" /* yacc.c:1646 */ +#line 454 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '*'); } -#line 2715 "src/parser.c" /* yacc.c:1646 */ +#line 2728 "src/parser.c" /* yacc.c:1667 */ break; case 38: -#line 452 "src/parser.y" /* yacc.c:1646 */ +#line 458 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '/'); if (block_is_const_inf((yyval.blk))) FAIL((yyloc), "Division by zero?"); } -#line 2725 "src/parser.c" /* yacc.c:1646 */ +#line 2738 "src/parser.c" /* yacc.c:1667 */ break; case 39: -#line 458 "src/parser.y" /* yacc.c:1646 */ +#line 464 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '%'); if (block_is_const_inf((yyval.blk))) FAIL((yyloc), "Remainder by zero?"); } -#line 2735 "src/parser.c" /* yacc.c:1646 */ +#line 2748 "src/parser.c" /* yacc.c:1667 */ break; case 40: -#line 464 "src/parser.y" /* yacc.c:1646 */ +#line 470 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '/'); } -#line 2743 "src/parser.c" /* yacc.c:1646 */ +#line 2756 "src/parser.c" /* yacc.c:1667 */ break; case 41: -#line 468 "src/parser.y" /* yacc.c:1646 */ +#line 474 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '%'); } -#line 2751 "src/parser.c" /* yacc.c:1646 */ +#line 2764 "src/parser.c" /* yacc.c:1667 */ break; case 42: -#line 472 "src/parser.y" /* yacc.c:1646 */ +#line 478 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), EQ); } -#line 2759 "src/parser.c" /* yacc.c:1646 */ +#line 2772 "src/parser.c" /* yacc.c:1667 */ break; case 43: -#line 476 "src/parser.y" /* yacc.c:1646 */ +#line 482 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), NEQ); } -#line 2767 "src/parser.c" /* yacc.c:1646 */ +#line 2780 "src/parser.c" /* yacc.c:1667 */ break; case 44: -#line 480 "src/parser.y" /* yacc.c:1646 */ +#line 486 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '<'); } -#line 2775 "src/parser.c" /* yacc.c:1646 */ +#line 2788 "src/parser.c" /* yacc.c:1667 */ break; case 45: -#line 484 "src/parser.y" /* yacc.c:1646 */ +#line 490 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '>'); } -#line 2783 "src/parser.c" /* yacc.c:1646 */ +#line 2796 "src/parser.c" /* yacc.c:1667 */ break; case 46: -#line 488 "src/parser.y" /* yacc.c:1646 */ +#line 494 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), LESSEQ); } -#line 2791 "src/parser.c" /* yacc.c:1646 */ +#line 2804 "src/parser.c" /* yacc.c:1667 */ break; case 47: -#line 492 "src/parser.y" /* yacc.c:1646 */ +#line 498 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), GREATEREQ); } -#line 2799 "src/parser.c" /* yacc.c:1646 */ +#line 2812 "src/parser.c" /* yacc.c:1667 */ break; case 48: -#line 496 "src/parser.y" /* yacc.c:1646 */ +#line 502 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 2807 "src/parser.c" /* yacc.c:1646 */ +#line 2820 "src/parser.c" /* yacc.c:1667 */ break; case 49: -#line 501 "src/parser.y" /* yacc.c:1646 */ +#line 507 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[-1].blk); } -#line 2815 "src/parser.c" /* yacc.c:1646 */ +#line 2828 "src/parser.c" /* yacc.c:1667 */ break; case 50: -#line 504 "src/parser.y" /* yacc.c:1646 */ +#line 510 "src/parser.y" /* yacc.c:1667 */ { if (!block_is_const((yyvsp[-1].blk))) { FAIL((yyloc), "Module metadata must be constant"); @@ -2831,11 +2844,11 @@ YYLTYPE yylloc = yyloc_default; (yyval.blk) = gen_import_meta((yyvsp[-2].blk), (yyvsp[-1].blk)); } } -#line 2835 "src/parser.c" /* yacc.c:1646 */ +#line 2848 "src/parser.c" /* yacc.c:1667 */ break; case 51: -#line 521 "src/parser.y" /* yacc.c:1646 */ +#line 527 "src/parser.y" /* yacc.c:1667 */ { jv v = block_const((yyvsp[-3].blk)); // XXX Make gen_import take only blocks and the int is_data so we @@ -2845,11 +2858,11 @@ YYLTYPE yylloc = yyloc_default; jv_free((yyvsp[0].literal)); jv_free(v); } -#line 2849 "src/parser.c" /* yacc.c:1646 */ +#line 2862 "src/parser.c" /* yacc.c:1667 */ break; case 52: -#line 530 "src/parser.y" /* yacc.c:1646 */ +#line 536 "src/parser.y" /* yacc.c:1667 */ { jv v = block_const((yyvsp[-2].blk)); (yyval.blk) = gen_import(jv_string_value(v), jv_string_value((yyvsp[0].literal)), 0); @@ -2857,22 +2870,22 @@ YYLTYPE yylloc = yyloc_default; jv_free((yyvsp[0].literal)); jv_free(v); } -#line 2861 "src/parser.c" /* yacc.c:1646 */ +#line 2874 "src/parser.c" /* yacc.c:1667 */ break; case 53: -#line 537 "src/parser.y" /* yacc.c:1646 */ +#line 543 "src/parser.y" /* yacc.c:1667 */ { jv v = block_const((yyvsp[0].blk)); (yyval.blk) = gen_import(jv_string_value(v), NULL, 0); block_free((yyvsp[0].blk)); jv_free(v); } -#line 2872 "src/parser.c" /* yacc.c:1646 */ +#line 2885 "src/parser.c" /* yacc.c:1667 */ break; case 54: -#line 545 "src/parser.y" /* yacc.c:1646 */ +#line 551 "src/parser.y" /* yacc.c:1667 */ { if (!block_is_const((yyvsp[0].blk))) { FAIL((yyloc), "Import path must be constant"); @@ -2882,182 +2895,182 @@ YYLTYPE yylloc = yyloc_default; (yyval.blk) = (yyvsp[0].blk); } } -#line 2886 "src/parser.c" /* yacc.c:1646 */ +#line 2899 "src/parser.c" /* yacc.c:1667 */ break; case 55: -#line 556 "src/parser.y" /* yacc.c:1646 */ +#line 562 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_function(jv_string_value((yyvsp[-3].literal)), gen_noop(), (yyvsp[-1].blk)); jv_free((yyvsp[-3].literal)); } -#line 2895 "src/parser.c" /* yacc.c:1646 */ +#line 2908 "src/parser.c" /* yacc.c:1667 */ break; case 56: -#line 561 "src/parser.y" /* yacc.c:1646 */ +#line 567 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_function(jv_string_value((yyvsp[-6].literal)), (yyvsp[-4].blk), (yyvsp[-1].blk)); jv_free((yyvsp[-6].literal)); } -#line 2904 "src/parser.c" /* yacc.c:1646 */ +#line 2917 "src/parser.c" /* yacc.c:1667 */ break; case 57: -#line 567 "src/parser.y" /* yacc.c:1646 */ +#line 573 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 2912 "src/parser.c" /* yacc.c:1646 */ +#line 2925 "src/parser.c" /* yacc.c:1667 */ break; case 58: -#line 570 "src/parser.y" /* yacc.c:1646 */ +#line 576 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2920 "src/parser.c" /* yacc.c:1646 */ +#line 2933 "src/parser.c" /* yacc.c:1667 */ break; case 59: -#line 575 "src/parser.y" /* yacc.c:1646 */ +#line 581 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_param_regular(jv_string_value((yyvsp[0].literal))); jv_free((yyvsp[0].literal)); } -#line 2929 "src/parser.c" /* yacc.c:1646 */ +#line 2942 "src/parser.c" /* yacc.c:1667 */ break; case 60: -#line 579 "src/parser.y" /* yacc.c:1646 */ +#line 585 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_param_regular(jv_string_value((yyvsp[0].literal))); jv_free((yyvsp[0].literal)); } -#line 2938 "src/parser.c" /* yacc.c:1646 */ +#line 2951 "src/parser.c" /* yacc.c:1667 */ break; case 61: -#line 583 "src/parser.y" /* yacc.c:1646 */ +#line 589 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_param(jv_string_value((yyvsp[0].literal))); jv_free((yyvsp[0].literal)); } -#line 2947 "src/parser.c" /* yacc.c:1646 */ +#line 2960 "src/parser.c" /* yacc.c:1667 */ break; case 62: -#line 590 "src/parser.y" /* yacc.c:1646 */ +#line 596 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("text"); } -#line 2953 "src/parser.c" /* yacc.c:1646 */ +#line 2966 "src/parser.c" /* yacc.c:1667 */ break; case 63: -#line 590 "src/parser.y" /* yacc.c:1646 */ +#line 596 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[-1].blk); jv_free((yyvsp[-2].literal)); } -#line 2962 "src/parser.c" /* yacc.c:1646 */ +#line 2975 "src/parser.c" /* yacc.c:1667 */ break; case 64: -#line 594 "src/parser.y" /* yacc.c:1646 */ +#line 600 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = (yyvsp[-1].literal); } -#line 2968 "src/parser.c" /* yacc.c:1646 */ +#line 2981 "src/parser.c" /* yacc.c:1667 */ break; case 65: -#line 594 "src/parser.y" /* yacc.c:1646 */ +#line 600 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[-1].blk); jv_free((yyvsp[-2].literal)); } -#line 2977 "src/parser.c" /* yacc.c:1646 */ +#line 2990 "src/parser.c" /* yacc.c:1667 */ break; case 66: -#line 601 "src/parser.y" /* yacc.c:1646 */ +#line 607 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_const(jv_string("")); } -#line 2985 "src/parser.c" /* yacc.c:1646 */ +#line 2998 "src/parser.c" /* yacc.c:1667 */ break; case 67: -#line 604 "src/parser.y" /* yacc.c:1646 */ +#line 610 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-1].blk), gen_const((yyvsp[0].literal)), '+'); } -#line 2993 "src/parser.c" /* yacc.c:1646 */ +#line 3006 "src/parser.c" /* yacc.c:1667 */ break; case 68: -#line 607 "src/parser.y" /* yacc.c:1646 */ +#line 613 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-3].blk), gen_format((yyvsp[-1].blk), jv_copy((yyvsp[-4].literal))), '+'); } -#line 3001 "src/parser.c" /* yacc.c:1646 */ +#line 3014 "src/parser.c" /* yacc.c:1667 */ break; case 69: -#line 613 "src/parser.y" /* yacc.c:1646 */ +#line 619 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_cond((yyvsp[-3].blk), (yyvsp[-1].blk), (yyvsp[0].blk)); } -#line 3009 "src/parser.c" /* yacc.c:1646 */ +#line 3022 "src/parser.c" /* yacc.c:1667 */ break; case 70: -#line 616 "src/parser.y" /* yacc.c:1646 */ +#line 622 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[-1].blk); } -#line 3017 "src/parser.c" /* yacc.c:1646 */ +#line 3030 "src/parser.c" /* yacc.c:1667 */ break; case 71: -#line 621 "src/parser.y" /* yacc.c:1646 */ +#line 627 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = block_join((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3025 "src/parser.c" /* yacc.c:1646 */ +#line 3038 "src/parser.c" /* yacc.c:1667 */ break; case 72: -#line 624 "src/parser.y" /* yacc.c:1646 */ +#line 630 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[0].blk), gen_call("_negate", gen_noop())); } -#line 3033 "src/parser.c" /* yacc.c:1646 */ +#line 3046 "src/parser.c" /* yacc.c:1667 */ break; case 73: -#line 627 "src/parser.y" /* yacc.c:1646 */ +#line 633 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 3041 "src/parser.c" /* yacc.c:1646 */ +#line 3054 "src/parser.c" /* yacc.c:1667 */ break; case 74: -#line 633 "src/parser.y" /* yacc.c:1646 */ +#line 639 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_noop(); } -#line 3049 "src/parser.c" /* yacc.c:1646 */ +#line 3062 "src/parser.c" /* yacc.c:1667 */ break; case 75: -#line 636 "src/parser.y" /* yacc.c:1646 */ +#line 642 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_call("recurse", gen_noop()); } -#line 3057 "src/parser.c" /* yacc.c:1646 */ +#line 3070 "src/parser.c" /* yacc.c:1667 */ break; case 76: -#line 639 "src/parser.y" /* yacc.c:1646 */ +#line 645 "src/parser.y" /* yacc.c:1667 */ { jv v = jv_string_fmt("*label-%s", jv_string_value((yyvsp[0].literal))); // impossible symbol (yyval.blk) = gen_location((yyloc), locations, @@ -3066,247 +3079,247 @@ YYLTYPE yylloc = yyloc_default; jv_free(v); jv_free((yyvsp[0].literal)); } -#line 3070 "src/parser.c" /* yacc.c:1646 */ +#line 3083 "src/parser.c" /* yacc.c:1667 */ break; case 77: -#line 647 "src/parser.y" /* yacc.c:1646 */ +#line 653 "src/parser.y" /* yacc.c:1667 */ { FAIL((yyloc), "break requires a label to break to"); (yyval.blk) = gen_noop(); } -#line 3079 "src/parser.c" /* yacc.c:1646 */ +#line 3092 "src/parser.c" /* yacc.c:1667 */ break; case 78: -#line 651 "src/parser.y" /* yacc.c:1646 */ +#line 657 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index_opt((yyvsp[-2].blk), gen_const((yyvsp[-1].literal))); } -#line 3087 "src/parser.c" /* yacc.c:1646 */ +#line 3100 "src/parser.c" /* yacc.c:1667 */ break; case 79: -#line 654 "src/parser.y" /* yacc.c:1646 */ +#line 660 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index_opt(gen_noop(), gen_const((yyvsp[-1].literal))); } -#line 3095 "src/parser.c" /* yacc.c:1646 */ +#line 3108 "src/parser.c" /* yacc.c:1667 */ break; case 80: -#line 657 "src/parser.y" /* yacc.c:1646 */ +#line 663 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index_opt((yyvsp[-3].blk), (yyvsp[-1].blk)); } -#line 3103 "src/parser.c" /* yacc.c:1646 */ +#line 3116 "src/parser.c" /* yacc.c:1667 */ break; case 81: -#line 660 "src/parser.y" /* yacc.c:1646 */ +#line 666 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index_opt(gen_noop(), (yyvsp[-1].blk)); } -#line 3111 "src/parser.c" /* yacc.c:1646 */ +#line 3124 "src/parser.c" /* yacc.c:1667 */ break; case 82: -#line 663 "src/parser.y" /* yacc.c:1646 */ +#line 669 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index((yyvsp[-1].blk), gen_const((yyvsp[0].literal))); } -#line 3119 "src/parser.c" /* yacc.c:1646 */ +#line 3132 "src/parser.c" /* yacc.c:1667 */ break; case 83: -#line 666 "src/parser.y" /* yacc.c:1646 */ +#line 672 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index(gen_noop(), gen_const((yyvsp[0].literal))); } -#line 3127 "src/parser.c" /* yacc.c:1646 */ +#line 3140 "src/parser.c" /* yacc.c:1667 */ break; case 84: -#line 669 "src/parser.y" /* yacc.c:1646 */ +#line 675 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3135 "src/parser.c" /* yacc.c:1646 */ +#line 3148 "src/parser.c" /* yacc.c:1667 */ break; case 85: -#line 672 "src/parser.y" /* yacc.c:1646 */ +#line 678 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index(gen_noop(), (yyvsp[0].blk)); } -#line 3143 "src/parser.c" /* yacc.c:1646 */ +#line 3156 "src/parser.c" /* yacc.c:1667 */ break; case 86: -#line 675 "src/parser.y" /* yacc.c:1646 */ +#line 681 "src/parser.y" /* yacc.c:1667 */ { FAIL((yyloc), "try .[\"field\"] instead of .field for unusually named fields"); (yyval.blk) = gen_noop(); } -#line 3152 "src/parser.c" /* yacc.c:1646 */ +#line 3165 "src/parser.c" /* yacc.c:1667 */ break; case 87: -#line 679 "src/parser.y" /* yacc.c:1646 */ +#line 685 "src/parser.y" /* yacc.c:1667 */ { jv_free((yyvsp[-1].literal)); FAIL((yyloc), "try .[\"field\"] instead of .field for unusually named fields"); (yyval.blk) = gen_noop(); } -#line 3162 "src/parser.c" /* yacc.c:1646 */ +#line 3175 "src/parser.c" /* yacc.c:1667 */ break; case 88: -#line 685 "src/parser.y" /* yacc.c:1646 */ +#line 691 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index_opt((yyvsp[-4].blk), (yyvsp[-2].blk)); } -#line 3170 "src/parser.c" /* yacc.c:1646 */ +#line 3183 "src/parser.c" /* yacc.c:1667 */ break; case 89: -#line 688 "src/parser.y" /* yacc.c:1646 */ +#line 694 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index((yyvsp[-3].blk), (yyvsp[-1].blk)); } -#line 3178 "src/parser.c" /* yacc.c:1646 */ +#line 3191 "src/parser.c" /* yacc.c:1667 */ break; case 90: -#line 691 "src/parser.y" /* yacc.c:1646 */ +#line 697 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index_opt((yyvsp[-5].blk), (yyvsp[-2].blk)); } -#line 3186 "src/parser.c" /* yacc.c:1646 */ +#line 3199 "src/parser.c" /* yacc.c:1667 */ break; case 91: -#line 694 "src/parser.y" /* yacc.c:1646 */ +#line 700 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index((yyvsp[-4].blk), (yyvsp[-1].blk)); } -#line 3194 "src/parser.c" /* yacc.c:1646 */ +#line 3207 "src/parser.c" /* yacc.c:1667 */ break; case 92: -#line 697 "src/parser.y" /* yacc.c:1646 */ +#line 703 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = block_join((yyvsp[-3].blk), gen_op_simple(EACH_OPT)); } -#line 3202 "src/parser.c" /* yacc.c:1646 */ +#line 3215 "src/parser.c" /* yacc.c:1667 */ break; case 93: -#line 700 "src/parser.y" /* yacc.c:1646 */ +#line 706 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = block_join((yyvsp[-2].blk), gen_op_simple(EACH)); } -#line 3210 "src/parser.c" /* yacc.c:1646 */ +#line 3223 "src/parser.c" /* yacc.c:1667 */ break; case 94: -#line 703 "src/parser.y" /* yacc.c:1646 */ +#line 709 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_slice_index((yyvsp[-6].blk), (yyvsp[-4].blk), (yyvsp[-2].blk), INDEX_OPT); } -#line 3218 "src/parser.c" /* yacc.c:1646 */ +#line 3231 "src/parser.c" /* yacc.c:1667 */ break; case 95: -#line 706 "src/parser.y" /* yacc.c:1646 */ +#line 712 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_slice_index((yyvsp[-5].blk), (yyvsp[-3].blk), gen_const(jv_null()), INDEX_OPT); } -#line 3226 "src/parser.c" /* yacc.c:1646 */ +#line 3239 "src/parser.c" /* yacc.c:1667 */ break; case 96: -#line 709 "src/parser.y" /* yacc.c:1646 */ +#line 715 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_slice_index((yyvsp[-5].blk), gen_const(jv_null()), (yyvsp[-2].blk), INDEX_OPT); } -#line 3234 "src/parser.c" /* yacc.c:1646 */ +#line 3247 "src/parser.c" /* yacc.c:1667 */ break; case 97: -#line 712 "src/parser.y" /* yacc.c:1646 */ +#line 718 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_slice_index((yyvsp[-5].blk), (yyvsp[-3].blk), (yyvsp[-1].blk), INDEX); } -#line 3242 "src/parser.c" /* yacc.c:1646 */ +#line 3255 "src/parser.c" /* yacc.c:1667 */ break; case 98: -#line 715 "src/parser.y" /* yacc.c:1646 */ +#line 721 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_slice_index((yyvsp[-4].blk), (yyvsp[-2].blk), gen_const(jv_null()), INDEX); } -#line 3250 "src/parser.c" /* yacc.c:1646 */ +#line 3263 "src/parser.c" /* yacc.c:1667 */ break; case 99: -#line 718 "src/parser.y" /* yacc.c:1646 */ +#line 724 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_slice_index((yyvsp[-4].blk), gen_const(jv_null()), (yyvsp[-1].blk), INDEX); } -#line 3258 "src/parser.c" /* yacc.c:1646 */ +#line 3271 "src/parser.c" /* yacc.c:1667 */ break; case 100: -#line 721 "src/parser.y" /* yacc.c:1646 */ +#line 727 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_const((yyvsp[0].literal)); } -#line 3266 "src/parser.c" /* yacc.c:1646 */ +#line 3279 "src/parser.c" /* yacc.c:1667 */ break; case 101: -#line 724 "src/parser.y" /* yacc.c:1646 */ +#line 730 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 3274 "src/parser.c" /* yacc.c:1646 */ +#line 3287 "src/parser.c" /* yacc.c:1667 */ break; case 102: -#line 727 "src/parser.y" /* yacc.c:1646 */ +#line 733 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_format(gen_noop(), (yyvsp[0].literal)); } -#line 3282 "src/parser.c" /* yacc.c:1646 */ +#line 3295 "src/parser.c" /* yacc.c:1667 */ break; case 103: -#line 730 "src/parser.y" /* yacc.c:1646 */ +#line 736 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[-1].blk); } -#line 3290 "src/parser.c" /* yacc.c:1646 */ +#line 3303 "src/parser.c" /* yacc.c:1667 */ break; case 104: -#line 733 "src/parser.y" /* yacc.c:1646 */ +#line 739 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_collect((yyvsp[-1].blk)); } -#line 3298 "src/parser.c" /* yacc.c:1646 */ +#line 3311 "src/parser.c" /* yacc.c:1667 */ break; case 105: -#line 736 "src/parser.y" /* yacc.c:1646 */ +#line 742 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_const(jv_array()); } -#line 3306 "src/parser.c" /* yacc.c:1646 */ +#line 3319 "src/parser.c" /* yacc.c:1667 */ break; case 106: -#line 739 "src/parser.y" /* yacc.c:1646 */ +#line 745 "src/parser.y" /* yacc.c:1667 */ { block o = gen_const_object((yyvsp[-1].blk)); if (o.first != NULL) @@ -3314,20 +3327,20 @@ YYLTYPE yylloc = yyloc_default; else (yyval.blk) = BLOCK(gen_subexp(gen_const(jv_object())), (yyvsp[-1].blk), gen_op_simple(POP)); } -#line 3318 "src/parser.c" /* yacc.c:1646 */ +#line 3331 "src/parser.c" /* yacc.c:1667 */ break; case 107: -#line 746 "src/parser.y" /* yacc.c:1646 */ +#line 752 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_location((yyloc), locations, gen_op_unbound(LOADV, jv_string_value((yyvsp[0].literal)))); jv_free((yyvsp[0].literal)); } -#line 3327 "src/parser.c" /* yacc.c:1646 */ +#line 3340 "src/parser.c" /* yacc.c:1667 */ break; case 108: -#line 750 "src/parser.y" /* yacc.c:1646 */ +#line 756 "src/parser.y" /* yacc.c:1667 */ { if (strcmp(jv_string_value((yyvsp[0].literal)), "__loc__") == 0) { (yyval.blk) = gen_const(JV_OBJECT(jv_string("file"), jv_copy(locations->fname), @@ -3337,11 +3350,11 @@ YYLTYPE yylloc = yyloc_default; } jv_free((yyvsp[0].literal)); } -#line 3341 "src/parser.c" /* yacc.c:1646 */ +#line 3354 "src/parser.c" /* yacc.c:1667 */ break; case 109: -#line 759 "src/parser.y" /* yacc.c:1646 */ +#line 765 "src/parser.y" /* yacc.c:1667 */ { const char *s = jv_string_value((yyvsp[0].literal)); if (strcmp(s, "false") == 0) @@ -3354,198 +3367,198 @@ YYLTYPE yylloc = yyloc_default; (yyval.blk) = gen_location((yyloc), locations, gen_call(s, gen_noop())); jv_free((yyvsp[0].literal)); } -#line 3358 "src/parser.c" /* yacc.c:1646 */ +#line 3371 "src/parser.c" /* yacc.c:1667 */ break; case 110: -#line 771 "src/parser.y" /* yacc.c:1646 */ +#line 777 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_call(jv_string_value((yyvsp[-3].literal)), (yyvsp[-1].blk)); (yyval.blk) = gen_location((yylsp[-3]), locations, (yyval.blk)); jv_free((yyvsp[-3].literal)); } -#line 3368 "src/parser.c" /* yacc.c:1646 */ +#line 3381 "src/parser.c" /* yacc.c:1667 */ break; case 111: -#line 776 "src/parser.y" /* yacc.c:1646 */ +#line 782 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_noop(); } -#line 3374 "src/parser.c" /* yacc.c:1646 */ +#line 3387 "src/parser.c" /* yacc.c:1667 */ break; case 112: -#line 777 "src/parser.y" /* yacc.c:1646 */ +#line 783 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_noop(); } -#line 3380 "src/parser.c" /* yacc.c:1646 */ +#line 3393 "src/parser.c" /* yacc.c:1667 */ break; case 113: -#line 778 "src/parser.y" /* yacc.c:1646 */ +#line 784 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[-3].blk); } -#line 3386 "src/parser.c" /* yacc.c:1646 */ +#line 3399 "src/parser.c" /* yacc.c:1667 */ break; case 114: -#line 779 "src/parser.y" /* yacc.c:1646 */ +#line 785 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_noop(); } -#line 3392 "src/parser.c" /* yacc.c:1646 */ +#line 3405 "src/parser.c" /* yacc.c:1667 */ break; case 115: -#line 782 "src/parser.y" /* yacc.c:1646 */ +#line 788 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 3400 "src/parser.c" /* yacc.c:1646 */ +#line 3413 "src/parser.c" /* yacc.c:1667 */ break; case 116: -#line 785 "src/parser.y" /* yacc.c:1646 */ +#line 791 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3408 "src/parser.c" /* yacc.c:1646 */ +#line 3421 "src/parser.c" /* yacc.c:1667 */ break; case 117: -#line 790 "src/parser.y" /* yacc.c:1646 */ +#line 796 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_lambda((yyvsp[0].blk)); } -#line 3416 "src/parser.c" /* yacc.c:1646 */ +#line 3429 "src/parser.c" /* yacc.c:1667 */ break; case 118: -#line 795 "src/parser.y" /* yacc.c:1646 */ +#line 801 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-2].blk), gen_destructure_alt((yyvsp[0].blk))); } -#line 3424 "src/parser.c" /* yacc.c:1646 */ +#line 3437 "src/parser.c" /* yacc.c:1667 */ break; case 119: -#line 798 "src/parser.y" /* yacc.c:1646 */ +#line 804 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_destructure_alt((yyvsp[0].blk)); } -#line 3432 "src/parser.c" /* yacc.c:1646 */ +#line 3445 "src/parser.c" /* yacc.c:1667 */ break; case 120: -#line 803 "src/parser.y" /* yacc.c:1646 */ +#line 809 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3440 "src/parser.c" /* yacc.c:1646 */ +#line 3453 "src/parser.c" /* yacc.c:1667 */ break; case 121: -#line 806 "src/parser.y" /* yacc.c:1646 */ +#line 812 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 3448 "src/parser.c" /* yacc.c:1646 */ +#line 3461 "src/parser.c" /* yacc.c:1667 */ break; case 122: -#line 811 "src/parser.y" /* yacc.c:1646 */ +#line 817 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_op_unbound(STOREV, jv_string_value((yyvsp[0].literal))); jv_free((yyvsp[0].literal)); } -#line 3457 "src/parser.c" /* yacc.c:1646 */ +#line 3470 "src/parser.c" /* yacc.c:1667 */ break; case 123: -#line 815 "src/parser.y" /* yacc.c:1646 */ +#line 821 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-1].blk), gen_op_simple(POP)); } -#line 3465 "src/parser.c" /* yacc.c:1646 */ +#line 3478 "src/parser.c" /* yacc.c:1667 */ break; case 124: -#line 818 "src/parser.y" /* yacc.c:1646 */ +#line 824 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-1].blk), gen_op_simple(POP)); } -#line 3473 "src/parser.c" /* yacc.c:1646 */ +#line 3486 "src/parser.c" /* yacc.c:1667 */ break; case 125: -#line 823 "src/parser.y" /* yacc.c:1646 */ +#line 829 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_array_matcher(gen_noop(), (yyvsp[0].blk)); } -#line 3481 "src/parser.c" /* yacc.c:1646 */ +#line 3494 "src/parser.c" /* yacc.c:1667 */ break; case 126: -#line 826 "src/parser.y" /* yacc.c:1646 */ +#line 832 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_array_matcher((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3489 "src/parser.c" /* yacc.c:1646 */ +#line 3502 "src/parser.c" /* yacc.c:1667 */ break; case 127: -#line 831 "src/parser.y" /* yacc.c:1646 */ +#line 837 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 3497 "src/parser.c" /* yacc.c:1646 */ +#line 3510 "src/parser.c" /* yacc.c:1667 */ break; case 128: -#line 834 "src/parser.y" /* yacc.c:1646 */ +#line 840 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3505 "src/parser.c" /* yacc.c:1646 */ +#line 3518 "src/parser.c" /* yacc.c:1667 */ break; case 129: -#line 839 "src/parser.y" /* yacc.c:1646 */ +#line 845 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_object_matcher(gen_const((yyvsp[0].literal)), gen_op_unbound(STOREV, jv_string_value((yyvsp[0].literal)))); } -#line 3513 "src/parser.c" /* yacc.c:1646 */ +#line 3526 "src/parser.c" /* yacc.c:1667 */ break; case 130: -#line 842 "src/parser.y" /* yacc.c:1646 */ +#line 848 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_object_matcher(gen_const((yyvsp[-2].literal)), BLOCK(gen_op_simple(DUP), gen_op_unbound(STOREV, jv_string_value((yyvsp[-2].literal))), (yyvsp[0].blk))); } -#line 3521 "src/parser.c" /* yacc.c:1646 */ +#line 3534 "src/parser.c" /* yacc.c:1667 */ break; case 131: -#line 845 "src/parser.y" /* yacc.c:1646 */ +#line 851 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_object_matcher(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk)); } -#line 3529 "src/parser.c" /* yacc.c:1646 */ +#line 3542 "src/parser.c" /* yacc.c:1667 */ break; case 132: -#line 848 "src/parser.y" /* yacc.c:1646 */ +#line 854 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_object_matcher(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk)); } -#line 3537 "src/parser.c" /* yacc.c:1646 */ +#line 3550 "src/parser.c" /* yacc.c:1667 */ break; case 133: -#line 851 "src/parser.y" /* yacc.c:1646 */ +#line 857 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_object_matcher((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3545 "src/parser.c" /* yacc.c:1646 */ +#line 3558 "src/parser.c" /* yacc.c:1667 */ break; case 134: -#line 854 "src/parser.y" /* yacc.c:1646 */ +#line 860 "src/parser.y" /* yacc.c:1667 */ { jv msg = check_object_key((yyvsp[-3].blk)); if (jv_is_valid(msg)) { @@ -3554,276 +3567,276 @@ YYLTYPE yylloc = yyloc_default; jv_free(msg); (yyval.blk) = gen_object_matcher((yyvsp[-3].blk), (yyvsp[0].blk)); } -#line 3558 "src/parser.c" /* yacc.c:1646 */ +#line 3571 "src/parser.c" /* yacc.c:1667 */ break; case 135: -#line 862 "src/parser.y" /* yacc.c:1646 */ +#line 868 "src/parser.y" /* yacc.c:1667 */ { FAIL((yyloc), "May need parentheses around object key expression"); (yyval.blk) = (yyvsp[0].blk); } -#line 3567 "src/parser.c" /* yacc.c:1646 */ +#line 3580 "src/parser.c" /* yacc.c:1667 */ break; case 136: -#line 868 "src/parser.y" /* yacc.c:1646 */ +#line 874 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("as"); } -#line 3575 "src/parser.c" /* yacc.c:1646 */ +#line 3588 "src/parser.c" /* yacc.c:1667 */ break; case 137: -#line 871 "src/parser.y" /* yacc.c:1646 */ +#line 877 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("def"); } -#line 3583 "src/parser.c" /* yacc.c:1646 */ +#line 3596 "src/parser.c" /* yacc.c:1667 */ break; case 138: -#line 874 "src/parser.y" /* yacc.c:1646 */ +#line 880 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("module"); } -#line 3591 "src/parser.c" /* yacc.c:1646 */ +#line 3604 "src/parser.c" /* yacc.c:1667 */ break; case 139: -#line 877 "src/parser.y" /* yacc.c:1646 */ +#line 883 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("import"); } -#line 3599 "src/parser.c" /* yacc.c:1646 */ +#line 3612 "src/parser.c" /* yacc.c:1667 */ break; case 140: -#line 880 "src/parser.y" /* yacc.c:1646 */ +#line 886 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("include"); } -#line 3607 "src/parser.c" /* yacc.c:1646 */ +#line 3620 "src/parser.c" /* yacc.c:1667 */ break; case 141: -#line 883 "src/parser.y" /* yacc.c:1646 */ +#line 889 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("if"); } -#line 3615 "src/parser.c" /* yacc.c:1646 */ +#line 3628 "src/parser.c" /* yacc.c:1667 */ break; case 142: -#line 886 "src/parser.y" /* yacc.c:1646 */ +#line 892 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("then"); } -#line 3623 "src/parser.c" /* yacc.c:1646 */ +#line 3636 "src/parser.c" /* yacc.c:1667 */ break; case 143: -#line 889 "src/parser.y" /* yacc.c:1646 */ +#line 895 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("else"); } -#line 3631 "src/parser.c" /* yacc.c:1646 */ +#line 3644 "src/parser.c" /* yacc.c:1667 */ break; case 144: -#line 892 "src/parser.y" /* yacc.c:1646 */ +#line 898 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("elif"); } -#line 3639 "src/parser.c" /* yacc.c:1646 */ +#line 3652 "src/parser.c" /* yacc.c:1667 */ break; case 145: -#line 895 "src/parser.y" /* yacc.c:1646 */ +#line 901 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("reduce"); } -#line 3647 "src/parser.c" /* yacc.c:1646 */ +#line 3660 "src/parser.c" /* yacc.c:1667 */ break; case 146: -#line 898 "src/parser.y" /* yacc.c:1646 */ +#line 904 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("foreach"); } -#line 3655 "src/parser.c" /* yacc.c:1646 */ +#line 3668 "src/parser.c" /* yacc.c:1667 */ break; case 147: -#line 901 "src/parser.y" /* yacc.c:1646 */ +#line 907 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("end"); } -#line 3663 "src/parser.c" /* yacc.c:1646 */ +#line 3676 "src/parser.c" /* yacc.c:1667 */ break; case 148: -#line 904 "src/parser.y" /* yacc.c:1646 */ +#line 910 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("and"); } -#line 3671 "src/parser.c" /* yacc.c:1646 */ +#line 3684 "src/parser.c" /* yacc.c:1667 */ break; case 149: -#line 907 "src/parser.y" /* yacc.c:1646 */ +#line 913 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("or"); } -#line 3679 "src/parser.c" /* yacc.c:1646 */ +#line 3692 "src/parser.c" /* yacc.c:1667 */ break; case 150: -#line 910 "src/parser.y" /* yacc.c:1646 */ +#line 916 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("try"); } -#line 3687 "src/parser.c" /* yacc.c:1646 */ +#line 3700 "src/parser.c" /* yacc.c:1667 */ break; case 151: -#line 913 "src/parser.y" /* yacc.c:1646 */ +#line 919 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("catch"); } -#line 3695 "src/parser.c" /* yacc.c:1646 */ +#line 3708 "src/parser.c" /* yacc.c:1667 */ break; case 152: -#line 916 "src/parser.y" /* yacc.c:1646 */ +#line 922 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("label"); } -#line 3703 "src/parser.c" /* yacc.c:1646 */ +#line 3716 "src/parser.c" /* yacc.c:1667 */ break; case 153: -#line 919 "src/parser.y" /* yacc.c:1646 */ +#line 925 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("break"); } -#line 3711 "src/parser.c" /* yacc.c:1646 */ +#line 3724 "src/parser.c" /* yacc.c:1667 */ break; case 154: -#line 922 "src/parser.y" /* yacc.c:1646 */ +#line 928 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("__loc__"); } -#line 3719 "src/parser.c" /* yacc.c:1646 */ +#line 3732 "src/parser.c" /* yacc.c:1667 */ break; case 155: -#line 927 "src/parser.y" /* yacc.c:1646 */ +#line 933 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk)=gen_noop(); } -#line 3727 "src/parser.c" /* yacc.c:1646 */ +#line 3740 "src/parser.c" /* yacc.c:1667 */ break; case 156: -#line 930 "src/parser.y" /* yacc.c:1646 */ +#line 936 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 3733 "src/parser.c" /* yacc.c:1646 */ +#line 3746 "src/parser.c" /* yacc.c:1667 */ break; case 157: -#line 931 "src/parser.y" /* yacc.c:1646 */ +#line 937 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk)=block_join((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3739 "src/parser.c" /* yacc.c:1646 */ +#line 3752 "src/parser.c" /* yacc.c:1667 */ break; case 158: -#line 932 "src/parser.y" /* yacc.c:1646 */ +#line 938 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 3745 "src/parser.c" /* yacc.c:1646 */ +#line 3758 "src/parser.c" /* yacc.c:1667 */ break; case 159: -#line 935 "src/parser.y" /* yacc.c:1646 */ +#line 941 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk)); } -#line 3753 "src/parser.c" /* yacc.c:1646 */ +#line 3766 "src/parser.c" /* yacc.c:1667 */ break; case 160: -#line 938 "src/parser.y" /* yacc.c:1646 */ +#line 944 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk)); } -#line 3761 "src/parser.c" /* yacc.c:1646 */ +#line 3774 "src/parser.c" /* yacc.c:1667 */ break; case 161: -#line 941 "src/parser.y" /* yacc.c:1646 */ +#line 947 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3769 "src/parser.c" /* yacc.c:1646 */ +#line 3782 "src/parser.c" /* yacc.c:1667 */ break; case 162: -#line 944 "src/parser.y" /* yacc.c:1646 */ +#line 950 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair((yyvsp[0].blk), BLOCK(gen_op_simple(POP), gen_op_simple(DUP2), gen_op_simple(DUP2), gen_op_simple(INDEX))); } -#line 3778 "src/parser.c" /* yacc.c:1646 */ +#line 3791 "src/parser.c" /* yacc.c:1667 */ break; case 163: -#line 948 "src/parser.y" /* yacc.c:1646 */ +#line 954 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair(gen_location((yyloc), locations, gen_op_unbound(LOADV, jv_string_value((yyvsp[-2].literal)))), (yyvsp[0].blk)); } -#line 3787 "src/parser.c" /* yacc.c:1646 */ +#line 3800 "src/parser.c" /* yacc.c:1667 */ break; case 164: -#line 952 "src/parser.y" /* yacc.c:1646 */ +#line 958 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair(gen_const((yyvsp[0].literal)), gen_location((yyloc), locations, gen_op_unbound(LOADV, jv_string_value((yyvsp[0].literal))))); } -#line 3796 "src/parser.c" /* yacc.c:1646 */ +#line 3809 "src/parser.c" /* yacc.c:1667 */ break; case 165: -#line 956 "src/parser.y" /* yacc.c:1646 */ +#line 962 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair(gen_const((yyvsp[0].literal)), gen_location((yyloc), locations, gen_op_unbound(LOADV, jv_string_value((yyvsp[0].literal))))); } -#line 3805 "src/parser.c" /* yacc.c:1646 */ +#line 3818 "src/parser.c" /* yacc.c:1667 */ break; case 166: -#line 960 "src/parser.y" /* yacc.c:1646 */ +#line 966 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair(gen_const(jv_copy((yyvsp[0].literal))), gen_index(gen_noop(), gen_const((yyvsp[0].literal)))); } -#line 3814 "src/parser.c" /* yacc.c:1646 */ +#line 3827 "src/parser.c" /* yacc.c:1667 */ break; case 167: -#line 964 "src/parser.y" /* yacc.c:1646 */ +#line 970 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair(gen_const(jv_copy((yyvsp[0].literal))), gen_index(gen_noop(), gen_const((yyvsp[0].literal)))); } -#line 3823 "src/parser.c" /* yacc.c:1646 */ +#line 3836 "src/parser.c" /* yacc.c:1667 */ break; case 168: -#line 968 "src/parser.y" /* yacc.c:1646 */ +#line 974 "src/parser.y" /* yacc.c:1667 */ { jv msg = check_object_key((yyvsp[-3].blk)); if (jv_is_valid(msg)) { @@ -3832,20 +3845,20 @@ YYLTYPE yylloc = yyloc_default; jv_free(msg); (yyval.blk) = gen_dictpair((yyvsp[-3].blk), (yyvsp[0].blk)); } -#line 3836 "src/parser.c" /* yacc.c:1646 */ +#line 3849 "src/parser.c" /* yacc.c:1667 */ break; case 169: -#line 976 "src/parser.y" /* yacc.c:1646 */ +#line 982 "src/parser.y" /* yacc.c:1667 */ { FAIL((yyloc), "May need parentheses around object key expression"); (yyval.blk) = (yyvsp[0].blk); } -#line 3845 "src/parser.c" /* yacc.c:1646 */ +#line 3858 "src/parser.c" /* yacc.c:1667 */ break; -#line 3849 "src/parser.c" /* yacc.c:1646 */ +#line 3862 "src/parser.c" /* yacc.c:1667 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -3871,14 +3884,13 @@ YYLTYPE yylloc = yyloc_default; /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } goto yynewstate; @@ -3961,14 +3973,11 @@ YYLTYPE yylloc = yyloc_default; | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - yyerror_range[1] = yylsp[1-yylen]; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ YYPOPSTACK (yylen); @@ -4034,6 +4043,7 @@ YYLTYPE yylloc = yyloc_default; yyresult = 0; goto yyreturn; + /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ @@ -4041,6 +4051,7 @@ YYLTYPE yylloc = yyloc_default; yyresult = 1; goto yyreturn; + #if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | @@ -4051,6 +4062,10 @@ YYLTYPE yylloc = yyloc_default; /* Fall through. */ #endif + +/*-----------------------------------------------------. +| yyreturn -- parsing is finished, return the result. | +`-----------------------------------------------------*/ yyreturn: if (yychar != YYEMPTY) { @@ -4080,7 +4095,7 @@ YYLTYPE yylloc = yyloc_default; #endif return yyresult; } -#line 980 "src/parser.y" /* yacc.c:1906 */ +#line 986 "src/parser.y" /* yacc.c:1918 */ int jq_parse(struct locfile* locations, block* answer) { diff --git a/src/parser.h b/src/parser.h index b15c53aad4..4d14e954f9 100644 --- a/src/parser.h +++ b/src/parser.h @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.3.2. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,6 +31,9 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + #ifndef YY_YY_SRC_PARSER_H_INCLUDED # define YY_YY_SRC_PARSER_H_INCLUDED /* Debug traces. */ @@ -40,7 +44,7 @@ extern int yydebug; #endif /* "%code requires" blocks. */ -#line 11 "src/parser.y" /* yacc.c:1909 */ +#line 11 "src/parser.y" /* yacc.c:1927 */ #include "locfile.h" struct lexer_param; @@ -57,7 +61,7 @@ struct lexer_param; } \ } while (0) -#line 61 "src/parser.h" /* yacc.c:1909 */ +#line 65 "src/parser.h" /* yacc.c:1927 */ /* Token type. */ #ifndef YYTOKENTYPE @@ -163,12 +167,12 @@ struct lexer_param; union YYSTYPE { -#line 31 "src/parser.y" /* yacc.c:1909 */ +#line 31 "src/parser.y" /* yacc.c:1927 */ jv literal; block blk; -#line 172 "src/parser.h" /* yacc.c:1909 */ +#line 176 "src/parser.h" /* yacc.c:1927 */ }; typedef union YYSTYPE YYSTYPE; diff --git a/src/parser.y b/src/parser.y index 6758102561..e223adab53 100644 --- a/src/parser.y +++ b/src/parser.y @@ -172,7 +172,7 @@ static jv check_object_key(block k) { char errbuf[15]; return jv_string_fmt("Cannot use %s (%s) as object key", jv_kind_name(block_const_kind(k)), - jv_dump_string_trunc(jv_copy(block_const(k)), errbuf, sizeof(errbuf))); + jv_dump_string_trunc(block_const(k), errbuf, sizeof(errbuf))); } return jv_invalid(); } @@ -216,19 +216,25 @@ static block constant_fold(block a, block b, int op) { jv res = jv_invalid(); if (block_const_kind(a) == JV_KIND_NUMBER) { - double na = jv_number_value(block_const(a)); - double nb = jv_number_value(block_const(b)); + jv jv_a = block_const(a); + jv jv_b = block_const(b); + + double na = jv_number_value(jv_a); + double nb = jv_number_value(jv_b); + + int cmp = jv_cmp(jv_a, jv_b); + switch (op) { case '+': res = jv_number(na + nb); break; case '-': res = jv_number(na - nb); break; case '*': res = jv_number(na * nb); break; case '/': res = jv_number(na / nb); break; - case EQ: res = (na == nb ? jv_true() : jv_false()); break; - case NEQ: res = (na != nb ? jv_true() : jv_false()); break; - case '<': res = (na < nb ? jv_true() : jv_false()); break; - case '>': res = (na > nb ? jv_true() : jv_false()); break; - case LESSEQ: res = (na <= nb ? jv_true() : jv_false()); break; - case GREATEREQ: res = (na >= nb ? jv_true() : jv_false()); break; + case EQ: res = (cmp == 0 ? jv_true() : jv_false()); break; + case NEQ: res = (cmp != 0 ? jv_true() : jv_false()); break; + case '<': res = (cmp < 0 ? jv_true() : jv_false()); break; + case '>': res = (cmp > 0 ? jv_true() : jv_false()); break; + case LESSEQ: res = (cmp <= 0 ? jv_true() : jv_false()); break; + case GREATEREQ: res = (cmp >= 0 ? jv_true() : jv_false()); break; default: break; } } else if (op == '+' && block_const_kind(a) == JV_KIND_STRING) { diff --git a/tests/jq.test b/tests/jq.test index a6a8d2194b..adc5788962 100644 --- a/tests/jq.test +++ b/tests/jq.test @@ -1673,3 +1673,42 @@ false #null +# +# Tests to cover the new toliteral number functionality +# For an example see #1652 and other linked issues +# + +# We are backward and sanity compatible + +map(. == 1) +[1, 1.0, 1.000, 100e-2, 1e+0, 0.0001e4] +[true, true, true, true, true, true] + +# When no arithmetic is involved jq should preserve the literal value + +.[0] | tostring +[13911860366432393] +"13911860366432393" + +.x | tojson +{"x":13911860366432393} +"13911860366432393" + +13911860366432393 == 13911860366432392 +null +false + + +# Applying arithmetic to the value will truncate the result to double + +. - 10 +13911860366432393 +13911860366432382 + +.[0] - 10 +[13911860366432393] +13911860366432382 + +.x - 10 +{"x":13911860366432393} +13911860366432382 diff --git a/tests/local.supp b/tests/local.supp new file mode 100644 index 0000000000..8bb878b06c --- /dev/null +++ b/tests/local.supp @@ -0,0 +1,14 @@ +{ + macos valgrind 1 + Memcheck:Leak + match-leak-kinds: possible + fun:calloc + fun:map_images_nolock + ... + fun:_dyld_objc_notify_register + fun:_objc_init + fun:_os_object_init + fun:libdispatch_init + fun:libSystem_initializer + ... +} diff --git a/tests/setup b/tests/setup index 4a96574d4c..bb5f62be3e 100755 --- a/tests/setup +++ b/tests/setup @@ -14,7 +14,8 @@ JQ=$JQBASEDIR/jq if [ -z "${NO_VALGRIND-}" ] && which valgrind > /dev/null; then VALGRIND="valgrind --error-exitcode=1 --leak-check=full \ - --suppressions=$JQTESTDIR/onig.supp" + --suppressions=$JQTESTDIR/onig.supp \ + --suppressions=$JQTESTDIR/local.supp" VG_EXIT0=--error-exitcode=0 Q=-q else