intl/icu/source/i18n/decNumber.c

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /* ------------------------------------------------------------------ */
michael@0 2 /* Decimal Number arithmetic module */
michael@0 3 /* ------------------------------------------------------------------ */
michael@0 4 /* Copyright (c) IBM Corporation, 2000-2012. All rights reserved. */
michael@0 5 /* */
michael@0 6 /* This software is made available under the terms of the */
michael@0 7 /* ICU License -- ICU 1.8.1 and later. */
michael@0 8 /* */
michael@0 9 /* The description and User's Guide ("The decNumber C Library") for */
michael@0 10 /* this software is called decNumber.pdf. This document is */
michael@0 11 /* available, together with arithmetic and format specifications, */
michael@0 12 /* testcases, and Web links, on the General Decimal Arithmetic page. */
michael@0 13 /* */
michael@0 14 /* Please send comments, suggestions, and corrections to the author: */
michael@0 15 /* mfc@uk.ibm.com */
michael@0 16 /* Mike Cowlishaw, IBM Fellow */
michael@0 17 /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
michael@0 18 /* ------------------------------------------------------------------ */
michael@0 19
michael@0 20 /* Modified version, for use from within ICU.
michael@0 21 * Renamed public functions, to avoid an unwanted export of the
michael@0 22 * standard names from the ICU library.
michael@0 23 *
michael@0 24 * Use ICU's uprv_malloc() and uprv_free()
michael@0 25 *
michael@0 26 * Revert comment syntax to plain C
michael@0 27 *
michael@0 28 * Remove a few compiler warnings.
michael@0 29 */
michael@0 30
michael@0 31 /* This module comprises the routines for arbitrary-precision General */
michael@0 32 /* Decimal Arithmetic as defined in the specification which may be */
michael@0 33 /* found on the General Decimal Arithmetic pages. It implements both */
michael@0 34 /* the full ('extended') arithmetic and the simpler ('subset') */
michael@0 35 /* arithmetic. */
michael@0 36 /* */
michael@0 37 /* Usage notes: */
michael@0 38 /* */
michael@0 39 /* 1. This code is ANSI C89 except: */
michael@0 40 /* */
michael@0 41 /* a) C99 line comments (double forward slash) are used. (Most C */
michael@0 42 /* compilers accept these. If yours does not, a simple script */
michael@0 43 /* can be used to convert them to ANSI C comments.) */
michael@0 44 /* */
michael@0 45 /* b) Types from C99 stdint.h are used. If you do not have this */
michael@0 46 /* header file, see the User's Guide section of the decNumber */
michael@0 47 /* documentation; this lists the necessary definitions. */
michael@0 48 /* */
michael@0 49 /* c) If DECDPUN>4 or DECUSE64=1, the C99 64-bit int64_t and */
michael@0 50 /* uint64_t types may be used. To avoid these, set DECUSE64=0 */
michael@0 51 /* and DECDPUN<=4 (see documentation). */
michael@0 52 /* */
michael@0 53 /* The code also conforms to C99 restrictions; in particular, */
michael@0 54 /* strict aliasing rules are observed. */
michael@0 55 /* */
michael@0 56 /* 2. The decNumber format which this library uses is optimized for */
michael@0 57 /* efficient processing of relatively short numbers; in particular */
michael@0 58 /* it allows the use of fixed sized structures and minimizes copy */
michael@0 59 /* and move operations. It does, however, support arbitrary */
michael@0 60 /* precision (up to 999,999,999 digits) and arbitrary exponent */
michael@0 61 /* range (Emax in the range 0 through 999,999,999 and Emin in the */
michael@0 62 /* range -999,999,999 through 0). Mathematical functions (for */
michael@0 63 /* example decNumberExp) as identified below are restricted more */
michael@0 64 /* tightly: digits, emax, and -emin in the context must be <= */
michael@0 65 /* DEC_MAX_MATH (999999), and their operand(s) must be within */
michael@0 66 /* these bounds. */
michael@0 67 /* */
michael@0 68 /* 3. Logical functions are further restricted; their operands must */
michael@0 69 /* be finite, positive, have an exponent of zero, and all digits */
michael@0 70 /* must be either 0 or 1. The result will only contain digits */
michael@0 71 /* which are 0 or 1 (and will have exponent=0 and a sign of 0). */
michael@0 72 /* */
michael@0 73 /* 4. Operands to operator functions are never modified unless they */
michael@0 74 /* are also specified to be the result number (which is always */
michael@0 75 /* permitted). Other than that case, operands must not overlap. */
michael@0 76 /* */
michael@0 77 /* 5. Error handling: the type of the error is ORed into the status */
michael@0 78 /* flags in the current context (decContext structure). The */
michael@0 79 /* SIGFPE signal is then raised if the corresponding trap-enabler */
michael@0 80 /* flag in the decContext is set (is 1). */
michael@0 81 /* */
michael@0 82 /* It is the responsibility of the caller to clear the status */
michael@0 83 /* flags as required. */
michael@0 84 /* */
michael@0 85 /* The result of any routine which returns a number will always */
michael@0 86 /* be a valid number (which may be a special value, such as an */
michael@0 87 /* Infinity or NaN). */
michael@0 88 /* */
michael@0 89 /* 6. The decNumber format is not an exchangeable concrete */
michael@0 90 /* representation as it comprises fields which may be machine- */
michael@0 91 /* dependent (packed or unpacked, or special length, for example). */
michael@0 92 /* Canonical conversions to and from strings are provided; other */
michael@0 93 /* conversions are available in separate modules. */
michael@0 94 /* */
michael@0 95 /* 7. Normally, input operands are assumed to be valid. Set DECCHECK */
michael@0 96 /* to 1 for extended operand checking (including NULL operands). */
michael@0 97 /* Results are undefined if a badly-formed structure (or a NULL */
michael@0 98 /* pointer to a structure) is provided, though with DECCHECK */
michael@0 99 /* enabled the operator routines are protected against exceptions. */
michael@0 100 /* (Except if the result pointer is NULL, which is unrecoverable.) */
michael@0 101 /* */
michael@0 102 /* However, the routines will never cause exceptions if they are */
michael@0 103 /* given well-formed operands, even if the value of the operands */
michael@0 104 /* is inappropriate for the operation and DECCHECK is not set. */
michael@0 105 /* (Except for SIGFPE, as and where documented.) */
michael@0 106 /* */
michael@0 107 /* 8. Subset arithmetic is available only if DECSUBSET is set to 1. */
michael@0 108 /* ------------------------------------------------------------------ */
michael@0 109 /* Implementation notes for maintenance of this module: */
michael@0 110 /* */
michael@0 111 /* 1. Storage leak protection: Routines which use malloc are not */
michael@0 112 /* permitted to use return for fastpath or error exits (i.e., */
michael@0 113 /* they follow strict structured programming conventions). */
michael@0 114 /* Instead they have a do{}while(0); construct surrounding the */
michael@0 115 /* code which is protected -- break may be used to exit this. */
michael@0 116 /* Other routines can safely use the return statement inline. */
michael@0 117 /* */
michael@0 118 /* Storage leak accounting can be enabled using DECALLOC. */
michael@0 119 /* */
michael@0 120 /* 2. All loops use the for(;;) construct. Any do construct does */
michael@0 121 /* not loop; it is for allocation protection as just described. */
michael@0 122 /* */
michael@0 123 /* 3. Setting status in the context must always be the very last */
michael@0 124 /* action in a routine, as non-0 status may raise a trap and hence */
michael@0 125 /* the call to set status may not return (if the handler uses long */
michael@0 126 /* jump). Therefore all cleanup must be done first. In general, */
michael@0 127 /* to achieve this status is accumulated and is only applied just */
michael@0 128 /* before return by calling decContextSetStatus (via decStatus). */
michael@0 129 /* */
michael@0 130 /* Routines which allocate storage cannot, in general, use the */
michael@0 131 /* 'top level' routines which could cause a non-returning */
michael@0 132 /* transfer of control. The decXxxxOp routines are safe (do not */
michael@0 133 /* call decStatus even if traps are set in the context) and should */
michael@0 134 /* be used instead (they are also a little faster). */
michael@0 135 /* */
michael@0 136 /* 4. Exponent checking is minimized by allowing the exponent to */
michael@0 137 /* grow outside its limits during calculations, provided that */
michael@0 138 /* the decFinalize function is called later. Multiplication and */
michael@0 139 /* division, and intermediate calculations in exponentiation, */
michael@0 140 /* require more careful checks because of the risk of 31-bit */
michael@0 141 /* overflow (the most negative valid exponent is -1999999997, for */
michael@0 142 /* a 999999999-digit number with adjusted exponent of -999999999). */
michael@0 143 /* */
michael@0 144 /* 5. Rounding is deferred until finalization of results, with any */
michael@0 145 /* 'off to the right' data being represented as a single digit */
michael@0 146 /* residue (in the range -1 through 9). This avoids any double- */
michael@0 147 /* rounding when more than one shortening takes place (for */
michael@0 148 /* example, when a result is subnormal). */
michael@0 149 /* */
michael@0 150 /* 6. The digits count is allowed to rise to a multiple of DECDPUN */
michael@0 151 /* during many operations, so whole Units are handled and exact */
michael@0 152 /* accounting of digits is not needed. The correct digits value */
michael@0 153 /* is found by decGetDigits, which accounts for leading zeros. */
michael@0 154 /* This must be called before any rounding if the number of digits */
michael@0 155 /* is not known exactly. */
michael@0 156 /* */
michael@0 157 /* 7. The multiply-by-reciprocal 'trick' is used for partitioning */
michael@0 158 /* numbers up to four digits, using appropriate constants. This */
michael@0 159 /* is not useful for longer numbers because overflow of 32 bits */
michael@0 160 /* would lead to 4 multiplies, which is almost as expensive as */
michael@0 161 /* a divide (unless a floating-point or 64-bit multiply is */
michael@0 162 /* assumed to be available). */
michael@0 163 /* */
michael@0 164 /* 8. Unusual abbreviations that may be used in the commentary: */
michael@0 165 /* lhs -- left hand side (operand, of an operation) */
michael@0 166 /* lsd -- least significant digit (of coefficient) */
michael@0 167 /* lsu -- least significant Unit (of coefficient) */
michael@0 168 /* msd -- most significant digit (of coefficient) */
michael@0 169 /* msi -- most significant item (in an array) */
michael@0 170 /* msu -- most significant Unit (of coefficient) */
michael@0 171 /* rhs -- right hand side (operand, of an operation) */
michael@0 172 /* +ve -- positive */
michael@0 173 /* -ve -- negative */
michael@0 174 /* ** -- raise to the power */
michael@0 175 /* ------------------------------------------------------------------ */
michael@0 176
michael@0 177 #include <stdlib.h> /* for malloc, free, etc. */
michael@0 178 /* #include <stdio.h> */ /* for printf [if needed] */
michael@0 179 #include <string.h> /* for strcpy */
michael@0 180 #include <ctype.h> /* for lower */
michael@0 181 #include "cmemory.h" /* for uprv_malloc, etc., in ICU */
michael@0 182 #include "decNumber.h" /* base number library */
michael@0 183 #include "decNumberLocal.h" /* decNumber local types, etc. */
michael@0 184 #include "uassert.h"
michael@0 185
michael@0 186 /* Constants */
michael@0 187 /* Public lookup table used by the D2U macro */
michael@0 188 static const uByte d2utable[DECMAXD2U+1]=D2UTABLE;
michael@0 189
michael@0 190 #define DECVERB 1 /* set to 1 for verbose DECCHECK */
michael@0 191 #define powers DECPOWERS /* old internal name */
michael@0 192
michael@0 193 /* Local constants */
michael@0 194 #define DIVIDE 0x80 /* Divide operators */
michael@0 195 #define REMAINDER 0x40 /* .. */
michael@0 196 #define DIVIDEINT 0x20 /* .. */
michael@0 197 #define REMNEAR 0x10 /* .. */
michael@0 198 #define COMPARE 0x01 /* Compare operators */
michael@0 199 #define COMPMAX 0x02 /* .. */
michael@0 200 #define COMPMIN 0x03 /* .. */
michael@0 201 #define COMPTOTAL 0x04 /* .. */
michael@0 202 #define COMPNAN 0x05 /* .. [NaN processing] */
michael@0 203 #define COMPSIG 0x06 /* .. [signaling COMPARE] */
michael@0 204 #define COMPMAXMAG 0x07 /* .. */
michael@0 205 #define COMPMINMAG 0x08 /* .. */
michael@0 206
michael@0 207 #define DEC_sNaN 0x40000000 /* local status: sNaN signal */
michael@0 208 #define BADINT (Int)0x80000000 /* most-negative Int; error indicator */
michael@0 209 /* Next two indicate an integer >= 10**6, and its parity (bottom bit) */
michael@0 210 #define BIGEVEN (Int)0x80000002
michael@0 211 #define BIGODD (Int)0x80000003
michael@0 212
michael@0 213 static const Unit uarrone[1]={1}; /* Unit array of 1, used for incrementing */
michael@0 214
michael@0 215 /* ------------------------------------------------------------------ */
michael@0 216 /* round-for-reround digits */
michael@0 217 /* ------------------------------------------------------------------ */
michael@0 218 static const uByte DECSTICKYTAB[10]={1,1,2,3,4,6,6,7,8,9}; /* used if sticky */
michael@0 219
michael@0 220 /* ------------------------------------------------------------------ */
michael@0 221 /* Powers of ten (powers[n]==10**n, 0<=n<=9) */
michael@0 222 /* ------------------------------------------------------------------ */
michael@0 223 static const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000,
michael@0 224 10000000, 100000000, 1000000000};
michael@0 225
michael@0 226
michael@0 227 /* Granularity-dependent code */
michael@0 228 #if DECDPUN<=4
michael@0 229 #define eInt Int /* extended integer */
michael@0 230 #define ueInt uInt /* unsigned extended integer */
michael@0 231 /* Constant multipliers for divide-by-power-of five using reciprocal */
michael@0 232 /* multiply, after removing powers of 2 by shifting, and final shift */
michael@0 233 /* of 17 [we only need up to **4] */
michael@0 234 static const uInt multies[]={131073, 26215, 5243, 1049, 210};
michael@0 235 /* QUOT10 -- macro to return the quotient of unit u divided by 10**n */
michael@0 236 #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17)
michael@0 237 #else
michael@0 238 /* For DECDPUN>4 non-ANSI-89 64-bit types are needed. */
michael@0 239 #if !DECUSE64
michael@0 240 #error decNumber.c: DECUSE64 must be 1 when DECDPUN>4
michael@0 241 #endif
michael@0 242 #define eInt Long /* extended integer */
michael@0 243 #define ueInt uLong /* unsigned extended integer */
michael@0 244 #endif
michael@0 245
michael@0 246 /* Local routines */
michael@0 247 static decNumber * decAddOp(decNumber *, const decNumber *, const decNumber *,
michael@0 248 decContext *, uByte, uInt *);
michael@0 249 static Flag decBiStr(const char *, const char *, const char *);
michael@0 250 static uInt decCheckMath(const decNumber *, decContext *, uInt *);
michael@0 251 static void decApplyRound(decNumber *, decContext *, Int, uInt *);
michael@0 252 static Int decCompare(const decNumber *lhs, const decNumber *rhs, Flag);
michael@0 253 static decNumber * decCompareOp(decNumber *, const decNumber *,
michael@0 254 const decNumber *, decContext *,
michael@0 255 Flag, uInt *);
michael@0 256 static void decCopyFit(decNumber *, const decNumber *, decContext *,
michael@0 257 Int *, uInt *);
michael@0 258 static decNumber * decDecap(decNumber *, Int);
michael@0 259 static decNumber * decDivideOp(decNumber *, const decNumber *,
michael@0 260 const decNumber *, decContext *, Flag, uInt *);
michael@0 261 static decNumber * decExpOp(decNumber *, const decNumber *,
michael@0 262 decContext *, uInt *);
michael@0 263 static void decFinalize(decNumber *, decContext *, Int *, uInt *);
michael@0 264 static Int decGetDigits(Unit *, Int);
michael@0 265 static Int decGetInt(const decNumber *);
michael@0 266 static decNumber * decLnOp(decNumber *, const decNumber *,
michael@0 267 decContext *, uInt *);
michael@0 268 static decNumber * decMultiplyOp(decNumber *, const decNumber *,
michael@0 269 const decNumber *, decContext *,
michael@0 270 uInt *);
michael@0 271 static decNumber * decNaNs(decNumber *, const decNumber *,
michael@0 272 const decNumber *, decContext *, uInt *);
michael@0 273 static decNumber * decQuantizeOp(decNumber *, const decNumber *,
michael@0 274 const decNumber *, decContext *, Flag,
michael@0 275 uInt *);
michael@0 276 static void decReverse(Unit *, Unit *);
michael@0 277 static void decSetCoeff(decNumber *, decContext *, const Unit *,
michael@0 278 Int, Int *, uInt *);
michael@0 279 static void decSetMaxValue(decNumber *, decContext *);
michael@0 280 static void decSetOverflow(decNumber *, decContext *, uInt *);
michael@0 281 static void decSetSubnormal(decNumber *, decContext *, Int *, uInt *);
michael@0 282 static Int decShiftToLeast(Unit *, Int, Int);
michael@0 283 static Int decShiftToMost(Unit *, Int, Int);
michael@0 284 static void decStatus(decNumber *, uInt, decContext *);
michael@0 285 static void decToString(const decNumber *, char[], Flag);
michael@0 286 static decNumber * decTrim(decNumber *, decContext *, Flag, Flag, Int *);
michael@0 287 static Int decUnitAddSub(const Unit *, Int, const Unit *, Int, Int,
michael@0 288 Unit *, Int);
michael@0 289 static Int decUnitCompare(const Unit *, Int, const Unit *, Int, Int);
michael@0 290
michael@0 291 #if !DECSUBSET
michael@0 292 /* decFinish == decFinalize when no subset arithmetic needed */
michael@0 293 #define decFinish(a,b,c,d) decFinalize(a,b,c,d)
michael@0 294 #else
michael@0 295 static void decFinish(decNumber *, decContext *, Int *, uInt *);
michael@0 296 static decNumber * decRoundOperand(const decNumber *, decContext *, uInt *);
michael@0 297 #endif
michael@0 298
michael@0 299 /* Local macros */
michael@0 300 /* masked special-values bits */
michael@0 301 #define SPECIALARG (rhs->bits & DECSPECIAL)
michael@0 302 #define SPECIALARGS ((lhs->bits | rhs->bits) & DECSPECIAL)
michael@0 303
michael@0 304 /* For use in ICU */
michael@0 305 #define malloc(a) uprv_malloc(a)
michael@0 306 #define free(a) uprv_free(a)
michael@0 307
michael@0 308 /* Diagnostic macros, etc. */
michael@0 309 #if DECALLOC
michael@0 310 /* Handle malloc/free accounting. If enabled, our accountable routines */
michael@0 311 /* are used; otherwise the code just goes straight to the system malloc */
michael@0 312 /* and free routines. */
michael@0 313 #define malloc(a) decMalloc(a)
michael@0 314 #define free(a) decFree(a)
michael@0 315 #define DECFENCE 0x5a /* corruption detector */
michael@0 316 /* 'Our' malloc and free: */
michael@0 317 static void *decMalloc(size_t);
michael@0 318 static void decFree(void *);
michael@0 319 uInt decAllocBytes=0; /* count of bytes allocated */
michael@0 320 /* Note that DECALLOC code only checks for storage buffer overflow. */
michael@0 321 /* To check for memory leaks, the decAllocBytes variable must be */
michael@0 322 /* checked to be 0 at appropriate times (e.g., after the test */
michael@0 323 /* harness completes a set of tests). This checking may be unreliable */
michael@0 324 /* if the testing is done in a multi-thread environment. */
michael@0 325 #endif
michael@0 326
michael@0 327 #if DECCHECK
michael@0 328 /* Optional checking routines. Enabling these means that decNumber */
michael@0 329 /* and decContext operands to operator routines are checked for */
michael@0 330 /* correctness. This roughly doubles the execution time of the */
michael@0 331 /* fastest routines (and adds 600+ bytes), so should not normally be */
michael@0 332 /* used in 'production'. */
michael@0 333 /* decCheckInexact is used to check that inexact results have a full */
michael@0 334 /* complement of digits (where appropriate -- this is not the case */
michael@0 335 /* for Quantize, for example) */
michael@0 336 #define DECUNRESU ((decNumber *)(void *)0xffffffff)
michael@0 337 #define DECUNUSED ((const decNumber *)(void *)0xffffffff)
michael@0 338 #define DECUNCONT ((decContext *)(void *)(0xffffffff))
michael@0 339 static Flag decCheckOperands(decNumber *, const decNumber *,
michael@0 340 const decNumber *, decContext *);
michael@0 341 static Flag decCheckNumber(const decNumber *);
michael@0 342 static void decCheckInexact(const decNumber *, decContext *);
michael@0 343 #endif
michael@0 344
michael@0 345 #if DECTRACE || DECCHECK
michael@0 346 /* Optional trace/debugging routines (may or may not be used) */
michael@0 347 void decNumberShow(const decNumber *); /* displays the components of a number */
michael@0 348 static void decDumpAr(char, const Unit *, Int);
michael@0 349 #endif
michael@0 350
michael@0 351 /* ================================================================== */
michael@0 352 /* Conversions */
michael@0 353 /* ================================================================== */
michael@0 354
michael@0 355 /* ------------------------------------------------------------------ */
michael@0 356 /* from-int32 -- conversion from Int or uInt */
michael@0 357 /* */
michael@0 358 /* dn is the decNumber to receive the integer */
michael@0 359 /* in or uin is the integer to be converted */
michael@0 360 /* returns dn */
michael@0 361 /* */
michael@0 362 /* No error is possible. */
michael@0 363 /* ------------------------------------------------------------------ */
michael@0 364 U_CAPI decNumber * U_EXPORT2 uprv_decNumberFromInt32(decNumber *dn, Int in) {
michael@0 365 uInt unsig;
michael@0 366 if (in>=0) unsig=in;
michael@0 367 else { /* negative (possibly BADINT) */
michael@0 368 if (in==BADINT) unsig=(uInt)1073741824*2; /* special case */
michael@0 369 else unsig=-in; /* invert */
michael@0 370 }
michael@0 371 /* in is now positive */
michael@0 372 uprv_decNumberFromUInt32(dn, unsig);
michael@0 373 if (in<0) dn->bits=DECNEG; /* sign needed */
michael@0 374 return dn;
michael@0 375 } /* decNumberFromInt32 */
michael@0 376
michael@0 377 U_CAPI decNumber * U_EXPORT2 uprv_decNumberFromUInt32(decNumber *dn, uInt uin) {
michael@0 378 Unit *up; /* work pointer */
michael@0 379 uprv_decNumberZero(dn); /* clean */
michael@0 380 if (uin==0) return dn; /* [or decGetDigits bad call] */
michael@0 381 for (up=dn->lsu; uin>0; up++) {
michael@0 382 *up=(Unit)(uin%(DECDPUNMAX+1));
michael@0 383 uin=uin/(DECDPUNMAX+1);
michael@0 384 }
michael@0 385 dn->digits=decGetDigits(dn->lsu, up-dn->lsu);
michael@0 386 return dn;
michael@0 387 } /* decNumberFromUInt32 */
michael@0 388
michael@0 389 /* ------------------------------------------------------------------ */
michael@0 390 /* to-int32 -- conversion to Int or uInt */
michael@0 391 /* */
michael@0 392 /* dn is the decNumber to convert */
michael@0 393 /* set is the context for reporting errors */
michael@0 394 /* returns the converted decNumber, or 0 if Invalid is set */
michael@0 395 /* */
michael@0 396 /* Invalid is set if the decNumber does not have exponent==0 or if */
michael@0 397 /* it is a NaN, Infinite, or out-of-range. */
michael@0 398 /* ------------------------------------------------------------------ */
michael@0 399 U_CAPI Int U_EXPORT2 uprv_decNumberToInt32(const decNumber *dn, decContext *set) {
michael@0 400 #if DECCHECK
michael@0 401 if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
michael@0 402 #endif
michael@0 403
michael@0 404 /* special or too many digits, or bad exponent */
michael@0 405 if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0) ; /* bad */
michael@0 406 else { /* is a finite integer with 10 or fewer digits */
michael@0 407 Int d; /* work */
michael@0 408 const Unit *up; /* .. */
michael@0 409 uInt hi=0, lo; /* .. */
michael@0 410 up=dn->lsu; /* -> lsu */
michael@0 411 lo=*up; /* get 1 to 9 digits */
michael@0 412 #if DECDPUN>1 /* split to higher */
michael@0 413 hi=lo/10;
michael@0 414 lo=lo%10;
michael@0 415 #endif
michael@0 416 up++;
michael@0 417 /* collect remaining Units, if any, into hi */
michael@0 418 for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1];
michael@0 419 /* now low has the lsd, hi the remainder */
michael@0 420 if (hi>214748364 || (hi==214748364 && lo>7)) { /* out of range? */
michael@0 421 /* most-negative is a reprieve */
michael@0 422 if (dn->bits&DECNEG && hi==214748364 && lo==8) return 0x80000000;
michael@0 423 /* bad -- drop through */
michael@0 424 }
michael@0 425 else { /* in-range always */
michael@0 426 Int i=X10(hi)+lo;
michael@0 427 if (dn->bits&DECNEG) return -i;
michael@0 428 return i;
michael@0 429 }
michael@0 430 } /* integer */
michael@0 431 uprv_decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */
michael@0 432 return 0;
michael@0 433 } /* decNumberToInt32 */
michael@0 434
michael@0 435 U_CAPI uInt U_EXPORT2 uprv_decNumberToUInt32(const decNumber *dn, decContext *set) {
michael@0 436 #if DECCHECK
michael@0 437 if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
michael@0 438 #endif
michael@0 439 /* special or too many digits, or bad exponent, or negative (<0) */
michael@0 440 if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0
michael@0 441 || (dn->bits&DECNEG && !ISZERO(dn))); /* bad */
michael@0 442 else { /* is a finite integer with 10 or fewer digits */
michael@0 443 Int d; /* work */
michael@0 444 const Unit *up; /* .. */
michael@0 445 uInt hi=0, lo; /* .. */
michael@0 446 up=dn->lsu; /* -> lsu */
michael@0 447 lo=*up; /* get 1 to 9 digits */
michael@0 448 #if DECDPUN>1 /* split to higher */
michael@0 449 hi=lo/10;
michael@0 450 lo=lo%10;
michael@0 451 #endif
michael@0 452 up++;
michael@0 453 /* collect remaining Units, if any, into hi */
michael@0 454 for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1];
michael@0 455
michael@0 456 /* now low has the lsd, hi the remainder */
michael@0 457 if (hi>429496729 || (hi==429496729 && lo>5)) ; /* no reprieve possible */
michael@0 458 else return X10(hi)+lo;
michael@0 459 } /* integer */
michael@0 460 uprv_decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */
michael@0 461 return 0;
michael@0 462 } /* decNumberToUInt32 */
michael@0 463
michael@0 464 /* ------------------------------------------------------------------ */
michael@0 465 /* to-scientific-string -- conversion to numeric string */
michael@0 466 /* to-engineering-string -- conversion to numeric string */
michael@0 467 /* */
michael@0 468 /* decNumberToString(dn, string); */
michael@0 469 /* decNumberToEngString(dn, string); */
michael@0 470 /* */
michael@0 471 /* dn is the decNumber to convert */
michael@0 472 /* string is the string where the result will be laid out */
michael@0 473 /* */
michael@0 474 /* string must be at least dn->digits+14 characters long */
michael@0 475 /* */
michael@0 476 /* No error is possible, and no status can be set. */
michael@0 477 /* ------------------------------------------------------------------ */
michael@0 478 U_CAPI char * U_EXPORT2 uprv_decNumberToString(const decNumber *dn, char *string){
michael@0 479 decToString(dn, string, 0);
michael@0 480 return string;
michael@0 481 } /* DecNumberToString */
michael@0 482
michael@0 483 U_CAPI char * U_EXPORT2 uprv_decNumberToEngString(const decNumber *dn, char *string){
michael@0 484 decToString(dn, string, 1);
michael@0 485 return string;
michael@0 486 } /* DecNumberToEngString */
michael@0 487
michael@0 488 /* ------------------------------------------------------------------ */
michael@0 489 /* to-number -- conversion from numeric string */
michael@0 490 /* */
michael@0 491 /* decNumberFromString -- convert string to decNumber */
michael@0 492 /* dn -- the number structure to fill */
michael@0 493 /* chars[] -- the string to convert ('\0' terminated) */
michael@0 494 /* set -- the context used for processing any error, */
michael@0 495 /* determining the maximum precision available */
michael@0 496 /* (set.digits), determining the maximum and minimum */
michael@0 497 /* exponent (set.emax and set.emin), determining if */
michael@0 498 /* extended values are allowed, and checking the */
michael@0 499 /* rounding mode if overflow occurs or rounding is */
michael@0 500 /* needed. */
michael@0 501 /* */
michael@0 502 /* The length of the coefficient and the size of the exponent are */
michael@0 503 /* checked by this routine, so the correct error (Underflow or */
michael@0 504 /* Overflow) can be reported or rounding applied, as necessary. */
michael@0 505 /* */
michael@0 506 /* If bad syntax is detected, the result will be a quiet NaN. */
michael@0 507 /* ------------------------------------------------------------------ */
michael@0 508 U_CAPI decNumber * U_EXPORT2 uprv_decNumberFromString(decNumber *dn, const char chars[],
michael@0 509 decContext *set) {
michael@0 510 Int exponent=0; /* working exponent [assume 0] */
michael@0 511 uByte bits=0; /* working flags [assume +ve] */
michael@0 512 Unit *res; /* where result will be built */
michael@0 513 Unit resbuff[SD2U(DECBUFFER+9)];/* local buffer in case need temporary */
michael@0 514 /* [+9 allows for ln() constants] */
michael@0 515 Unit *allocres=NULL; /* -> allocated result, iff allocated */
michael@0 516 Int d=0; /* count of digits found in decimal part */
michael@0 517 const char *dotchar=NULL; /* where dot was found */
michael@0 518 const char *cfirst=chars; /* -> first character of decimal part */
michael@0 519 const char *last=NULL; /* -> last digit of decimal part */
michael@0 520 const char *c; /* work */
michael@0 521 Unit *up; /* .. */
michael@0 522 #if DECDPUN>1
michael@0 523 Int cut, out; /* .. */
michael@0 524 #endif
michael@0 525 Int residue; /* rounding residue */
michael@0 526 uInt status=0; /* error code */
michael@0 527
michael@0 528 #if DECCHECK
michael@0 529 if (decCheckOperands(DECUNRESU, DECUNUSED, DECUNUSED, set))
michael@0 530 return uprv_decNumberZero(dn);
michael@0 531 #endif
michael@0 532
michael@0 533 do { /* status & malloc protection */
michael@0 534 for (c=chars;; c++) { /* -> input character */
michael@0 535 if (*c>='0' && *c<='9') { /* test for Arabic digit */
michael@0 536 last=c;
michael@0 537 d++; /* count of real digits */
michael@0 538 continue; /* still in decimal part */
michael@0 539 }
michael@0 540 if (*c=='.' && dotchar==NULL) { /* first '.' */
michael@0 541 dotchar=c; /* record offset into decimal part */
michael@0 542 if (c==cfirst) cfirst++; /* first digit must follow */
michael@0 543 continue;}
michael@0 544 if (c==chars) { /* first in string... */
michael@0 545 if (*c=='-') { /* valid - sign */
michael@0 546 cfirst++;
michael@0 547 bits=DECNEG;
michael@0 548 continue;}
michael@0 549 if (*c=='+') { /* valid + sign */
michael@0 550 cfirst++;
michael@0 551 continue;}
michael@0 552 }
michael@0 553 /* *c is not a digit, or a valid +, -, or '.' */
michael@0 554 break;
michael@0 555 } /* c */
michael@0 556
michael@0 557 if (last==NULL) { /* no digits yet */
michael@0 558 status=DEC_Conversion_syntax;/* assume the worst */
michael@0 559 if (*c=='\0') break; /* and no more to come... */
michael@0 560 #if DECSUBSET
michael@0 561 /* if subset then infinities and NaNs are not allowed */
michael@0 562 if (!set->extended) break; /* hopeless */
michael@0 563 #endif
michael@0 564 /* Infinities and NaNs are possible, here */
michael@0 565 if (dotchar!=NULL) break; /* .. unless had a dot */
michael@0 566 uprv_decNumberZero(dn); /* be optimistic */
michael@0 567 if (decBiStr(c, "infinity", "INFINITY")
michael@0 568 || decBiStr(c, "inf", "INF")) {
michael@0 569 dn->bits=bits | DECINF;
michael@0 570 status=0; /* is OK */
michael@0 571 break; /* all done */
michael@0 572 }
michael@0 573 /* a NaN expected */
michael@0 574 /* 2003.09.10 NaNs are now permitted to have a sign */
michael@0 575 dn->bits=bits | DECNAN; /* assume simple NaN */
michael@0 576 if (*c=='s' || *c=='S') { /* looks like an sNaN */
michael@0 577 c++;
michael@0 578 dn->bits=bits | DECSNAN;
michael@0 579 }
michael@0 580 if (*c!='n' && *c!='N') break; /* check caseless "NaN" */
michael@0 581 c++;
michael@0 582 if (*c!='a' && *c!='A') break; /* .. */
michael@0 583 c++;
michael@0 584 if (*c!='n' && *c!='N') break; /* .. */
michael@0 585 c++;
michael@0 586 /* now either nothing, or nnnn payload, expected */
michael@0 587 /* -> start of integer and skip leading 0s [including plain 0] */
michael@0 588 for (cfirst=c; *cfirst=='0';) cfirst++;
michael@0 589 if (*cfirst=='\0') { /* "NaN" or "sNaN", maybe with all 0s */
michael@0 590 status=0; /* it's good */
michael@0 591 break; /* .. */
michael@0 592 }
michael@0 593 /* something other than 0s; setup last and d as usual [no dots] */
michael@0 594 for (c=cfirst;; c++, d++) {
michael@0 595 if (*c<'0' || *c>'9') break; /* test for Arabic digit */
michael@0 596 last=c;
michael@0 597 }
michael@0 598 if (*c!='\0') break; /* not all digits */
michael@0 599 if (d>set->digits-1) {
michael@0 600 /* [NB: payload in a decNumber can be full length unless */
michael@0 601 /* clamped, in which case can only be digits-1] */
michael@0 602 if (set->clamp) break;
michael@0 603 if (d>set->digits) break;
michael@0 604 } /* too many digits? */
michael@0 605 /* good; drop through to convert the integer to coefficient */
michael@0 606 status=0; /* syntax is OK */
michael@0 607 bits=dn->bits; /* for copy-back */
michael@0 608 } /* last==NULL */
michael@0 609
michael@0 610 else if (*c!='\0') { /* more to process... */
michael@0 611 /* had some digits; exponent is only valid sequence now */
michael@0 612 Flag nege; /* 1=negative exponent */
michael@0 613 const char *firstexp; /* -> first significant exponent digit */
michael@0 614 status=DEC_Conversion_syntax;/* assume the worst */
michael@0 615 if (*c!='e' && *c!='E') break;
michael@0 616 /* Found 'e' or 'E' -- now process explicit exponent */
michael@0 617 /* 1998.07.11: sign no longer required */
michael@0 618 nege=0;
michael@0 619 c++; /* to (possible) sign */
michael@0 620 if (*c=='-') {nege=1; c++;}
michael@0 621 else if (*c=='+') c++;
michael@0 622 if (*c=='\0') break;
michael@0 623
michael@0 624 for (; *c=='0' && *(c+1)!='\0';) c++; /* strip insignificant zeros */
michael@0 625 firstexp=c; /* save exponent digit place */
michael@0 626 for (; ;c++) {
michael@0 627 if (*c<'0' || *c>'9') break; /* not a digit */
michael@0 628 exponent=X10(exponent)+(Int)*c-(Int)'0';
michael@0 629 } /* c */
michael@0 630 /* if not now on a '\0', *c must not be a digit */
michael@0 631 if (*c!='\0') break;
michael@0 632
michael@0 633 /* (this next test must be after the syntax checks) */
michael@0 634 /* if it was too long the exponent may have wrapped, so check */
michael@0 635 /* carefully and set it to a certain overflow if wrap possible */
michael@0 636 if (c>=firstexp+9+1) {
michael@0 637 if (c>firstexp+9+1 || *firstexp>'1') exponent=DECNUMMAXE*2;
michael@0 638 /* [up to 1999999999 is OK, for example 1E-1000000998] */
michael@0 639 }
michael@0 640 if (nege) exponent=-exponent; /* was negative */
michael@0 641 status=0; /* is OK */
michael@0 642 } /* stuff after digits */
michael@0 643
michael@0 644 /* Here when whole string has been inspected; syntax is good */
michael@0 645 /* cfirst->first digit (never dot), last->last digit (ditto) */
michael@0 646
michael@0 647 /* strip leading zeros/dot [leave final 0 if all 0's] */
michael@0 648 if (*cfirst=='0') { /* [cfirst has stepped over .] */
michael@0 649 for (c=cfirst; c<last; c++, cfirst++) {
michael@0 650 if (*c=='.') continue; /* ignore dots */
michael@0 651 if (*c!='0') break; /* non-zero found */
michael@0 652 d--; /* 0 stripped */
michael@0 653 } /* c */
michael@0 654 #if DECSUBSET
michael@0 655 /* make a rapid exit for easy zeros if !extended */
michael@0 656 if (*cfirst=='0' && !set->extended) {
michael@0 657 uprv_decNumberZero(dn); /* clean result */
michael@0 658 break; /* [could be return] */
michael@0 659 }
michael@0 660 #endif
michael@0 661 } /* at least one leading 0 */
michael@0 662
michael@0 663 /* Handle decimal point... */
michael@0 664 if (dotchar!=NULL && dotchar<last) /* non-trailing '.' found? */
michael@0 665 exponent-=(last-dotchar); /* adjust exponent */
michael@0 666 /* [we can now ignore the .] */
michael@0 667
michael@0 668 /* OK, the digits string is good. Assemble in the decNumber, or in */
michael@0 669 /* a temporary units array if rounding is needed */
michael@0 670 if (d<=set->digits) res=dn->lsu; /* fits into supplied decNumber */
michael@0 671 else { /* rounding needed */
michael@0 672 Int needbytes=D2U(d)*sizeof(Unit);/* bytes needed */
michael@0 673 res=resbuff; /* assume use local buffer */
michael@0 674 if (needbytes>(Int)sizeof(resbuff)) { /* too big for local */
michael@0 675 allocres=(Unit *)malloc(needbytes);
michael@0 676 if (allocres==NULL) {status|=DEC_Insufficient_storage; break;}
michael@0 677 res=allocres;
michael@0 678 }
michael@0 679 }
michael@0 680 /* res now -> number lsu, buffer, or allocated storage for Unit array */
michael@0 681
michael@0 682 /* Place the coefficient into the selected Unit array */
michael@0 683 /* [this is often 70% of the cost of this function when DECDPUN>1] */
michael@0 684 #if DECDPUN>1
michael@0 685 out=0; /* accumulator */
michael@0 686 up=res+D2U(d)-1; /* -> msu */
michael@0 687 cut=d-(up-res)*DECDPUN; /* digits in top unit */
michael@0 688 for (c=cfirst;; c++) { /* along the digits */
michael@0 689 if (*c=='.') continue; /* ignore '.' [don't decrement cut] */
michael@0 690 out=X10(out)+(Int)*c-(Int)'0';
michael@0 691 if (c==last) break; /* done [never get to trailing '.'] */
michael@0 692 cut--;
michael@0 693 if (cut>0) continue; /* more for this unit */
michael@0 694 *up=(Unit)out; /* write unit */
michael@0 695 up--; /* prepare for unit below.. */
michael@0 696 cut=DECDPUN; /* .. */
michael@0 697 out=0; /* .. */
michael@0 698 } /* c */
michael@0 699 *up=(Unit)out; /* write lsu */
michael@0 700
michael@0 701 #else
michael@0 702 /* DECDPUN==1 */
michael@0 703 up=res; /* -> lsu */
michael@0 704 for (c=last; c>=cfirst; c--) { /* over each character, from least */
michael@0 705 if (*c=='.') continue; /* ignore . [don't step up] */
michael@0 706 *up=(Unit)((Int)*c-(Int)'0');
michael@0 707 up++;
michael@0 708 } /* c */
michael@0 709 #endif
michael@0 710
michael@0 711 dn->bits=bits;
michael@0 712 dn->exponent=exponent;
michael@0 713 dn->digits=d;
michael@0 714
michael@0 715 /* if not in number (too long) shorten into the number */
michael@0 716 if (d>set->digits) {
michael@0 717 residue=0;
michael@0 718 decSetCoeff(dn, set, res, d, &residue, &status);
michael@0 719 /* always check for overflow or subnormal and round as needed */
michael@0 720 decFinalize(dn, set, &residue, &status);
michael@0 721 }
michael@0 722 else { /* no rounding, but may still have overflow or subnormal */
michael@0 723 /* [these tests are just for performance; finalize repeats them] */
michael@0 724 if ((dn->exponent-1<set->emin-dn->digits)
michael@0 725 || (dn->exponent-1>set->emax-set->digits)) {
michael@0 726 residue=0;
michael@0 727 decFinalize(dn, set, &residue, &status);
michael@0 728 }
michael@0 729 }
michael@0 730 /* decNumberShow(dn); */
michael@0 731 } while(0); /* [for break] */
michael@0 732
michael@0 733 if (allocres!=NULL) free(allocres); /* drop any storage used */
michael@0 734 if (status!=0) decStatus(dn, status, set);
michael@0 735 return dn;
michael@0 736 } /* decNumberFromString */
michael@0 737
michael@0 738 /* ================================================================== */
michael@0 739 /* Operators */
michael@0 740 /* ================================================================== */
michael@0 741
michael@0 742 /* ------------------------------------------------------------------ */
michael@0 743 /* decNumberAbs -- absolute value operator */
michael@0 744 /* */
michael@0 745 /* This computes C = abs(A) */
michael@0 746 /* */
michael@0 747 /* res is C, the result. C may be A */
michael@0 748 /* rhs is A */
michael@0 749 /* set is the context */
michael@0 750 /* */
michael@0 751 /* See also decNumberCopyAbs for a quiet bitwise version of this. */
michael@0 752 /* C must have space for set->digits digits. */
michael@0 753 /* ------------------------------------------------------------------ */
michael@0 754 /* This has the same effect as decNumberPlus unless A is negative, */
michael@0 755 /* in which case it has the same effect as decNumberMinus. */
michael@0 756 /* ------------------------------------------------------------------ */
michael@0 757 U_CAPI decNumber * U_EXPORT2 uprv_decNumberAbs(decNumber *res, const decNumber *rhs,
michael@0 758 decContext *set) {
michael@0 759 decNumber dzero; /* for 0 */
michael@0 760 uInt status=0; /* accumulator */
michael@0 761
michael@0 762 #if DECCHECK
michael@0 763 if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
michael@0 764 #endif
michael@0 765
michael@0 766 uprv_decNumberZero(&dzero); /* set 0 */
michael@0 767 dzero.exponent=rhs->exponent; /* [no coefficient expansion] */
michael@0 768 decAddOp(res, &dzero, rhs, set, (uByte)(rhs->bits & DECNEG), &status);
michael@0 769 if (status!=0) decStatus(res, status, set);
michael@0 770 #if DECCHECK
michael@0 771 decCheckInexact(res, set);
michael@0 772 #endif
michael@0 773 return res;
michael@0 774 } /* decNumberAbs */
michael@0 775
michael@0 776 /* ------------------------------------------------------------------ */
michael@0 777 /* decNumberAdd -- add two Numbers */
michael@0 778 /* */
michael@0 779 /* This computes C = A + B */
michael@0 780 /* */
michael@0 781 /* res is C, the result. C may be A and/or B (e.g., X=X+X) */
michael@0 782 /* lhs is A */
michael@0 783 /* rhs is B */
michael@0 784 /* set is the context */
michael@0 785 /* */
michael@0 786 /* C must have space for set->digits digits. */
michael@0 787 /* ------------------------------------------------------------------ */
michael@0 788 /* This just calls the routine shared with Subtract */
michael@0 789 U_CAPI decNumber * U_EXPORT2 uprv_decNumberAdd(decNumber *res, const decNumber *lhs,
michael@0 790 const decNumber *rhs, decContext *set) {
michael@0 791 uInt status=0; /* accumulator */
michael@0 792 decAddOp(res, lhs, rhs, set, 0, &status);
michael@0 793 if (status!=0) decStatus(res, status, set);
michael@0 794 #if DECCHECK
michael@0 795 decCheckInexact(res, set);
michael@0 796 #endif
michael@0 797 return res;
michael@0 798 } /* decNumberAdd */
michael@0 799
michael@0 800 /* ------------------------------------------------------------------ */
michael@0 801 /* decNumberAnd -- AND two Numbers, digitwise */
michael@0 802 /* */
michael@0 803 /* This computes C = A & B */
michael@0 804 /* */
michael@0 805 /* res is C, the result. C may be A and/or B (e.g., X=X&X) */
michael@0 806 /* lhs is A */
michael@0 807 /* rhs is B */
michael@0 808 /* set is the context (used for result length and error report) */
michael@0 809 /* */
michael@0 810 /* C must have space for set->digits digits. */
michael@0 811 /* */
michael@0 812 /* Logical function restrictions apply (see above); a NaN is */
michael@0 813 /* returned with Invalid_operation if a restriction is violated. */
michael@0 814 /* ------------------------------------------------------------------ */
michael@0 815 U_CAPI decNumber * U_EXPORT2 uprv_decNumberAnd(decNumber *res, const decNumber *lhs,
michael@0 816 const decNumber *rhs, decContext *set) {
michael@0 817 const Unit *ua, *ub; /* -> operands */
michael@0 818 const Unit *msua, *msub; /* -> operand msus */
michael@0 819 Unit *uc, *msuc; /* -> result and its msu */
michael@0 820 Int msudigs; /* digits in res msu */
michael@0 821 #if DECCHECK
michael@0 822 if (decCheckOperands(res, lhs, rhs, set)) return res;
michael@0 823 #endif
michael@0 824
michael@0 825 if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
michael@0 826 || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
michael@0 827 decStatus(res, DEC_Invalid_operation, set);
michael@0 828 return res;
michael@0 829 }
michael@0 830
michael@0 831 /* operands are valid */
michael@0 832 ua=lhs->lsu; /* bottom-up */
michael@0 833 ub=rhs->lsu; /* .. */
michael@0 834 uc=res->lsu; /* .. */
michael@0 835 msua=ua+D2U(lhs->digits)-1; /* -> msu of lhs */
michael@0 836 msub=ub+D2U(rhs->digits)-1; /* -> msu of rhs */
michael@0 837 msuc=uc+D2U(set->digits)-1; /* -> msu of result */
michael@0 838 msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */
michael@0 839 for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */
michael@0 840 Unit a, b; /* extract units */
michael@0 841 if (ua>msua) a=0;
michael@0 842 else a=*ua;
michael@0 843 if (ub>msub) b=0;
michael@0 844 else b=*ub;
michael@0 845 *uc=0; /* can now write back */
michael@0 846 if (a|b) { /* maybe 1 bits to examine */
michael@0 847 Int i, j;
michael@0 848 *uc=0; /* can now write back */
michael@0 849 /* This loop could be unrolled and/or use BIN2BCD tables */
michael@0 850 for (i=0; i<DECDPUN; i++) {
michael@0 851 if (a&b&1) *uc=*uc+(Unit)powers[i]; /* effect AND */
michael@0 852 j=a%10;
michael@0 853 a=a/10;
michael@0 854 j|=b%10;
michael@0 855 b=b/10;
michael@0 856 if (j>1) {
michael@0 857 decStatus(res, DEC_Invalid_operation, set);
michael@0 858 return res;
michael@0 859 }
michael@0 860 if (uc==msuc && i==msudigs-1) break; /* just did final digit */
michael@0 861 } /* each digit */
michael@0 862 } /* both OK */
michael@0 863 } /* each unit */
michael@0 864 /* [here uc-1 is the msu of the result] */
michael@0 865 res->digits=decGetDigits(res->lsu, uc-res->lsu);
michael@0 866 res->exponent=0; /* integer */
michael@0 867 res->bits=0; /* sign=0 */
michael@0 868 return res; /* [no status to set] */
michael@0 869 } /* decNumberAnd */
michael@0 870
michael@0 871 /* ------------------------------------------------------------------ */
michael@0 872 /* decNumberCompare -- compare two Numbers */
michael@0 873 /* */
michael@0 874 /* This computes C = A ? B */
michael@0 875 /* */
michael@0 876 /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
michael@0 877 /* lhs is A */
michael@0 878 /* rhs is B */
michael@0 879 /* set is the context */
michael@0 880 /* */
michael@0 881 /* C must have space for one digit (or NaN). */
michael@0 882 /* ------------------------------------------------------------------ */
michael@0 883 U_CAPI decNumber * U_EXPORT2 uprv_decNumberCompare(decNumber *res, const decNumber *lhs,
michael@0 884 const decNumber *rhs, decContext *set) {
michael@0 885 uInt status=0; /* accumulator */
michael@0 886 decCompareOp(res, lhs, rhs, set, COMPARE, &status);
michael@0 887 if (status!=0) decStatus(res, status, set);
michael@0 888 return res;
michael@0 889 } /* decNumberCompare */
michael@0 890
michael@0 891 /* ------------------------------------------------------------------ */
michael@0 892 /* decNumberCompareSignal -- compare, signalling on all NaNs */
michael@0 893 /* */
michael@0 894 /* This computes C = A ? B */
michael@0 895 /* */
michael@0 896 /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
michael@0 897 /* lhs is A */
michael@0 898 /* rhs is B */
michael@0 899 /* set is the context */
michael@0 900 /* */
michael@0 901 /* C must have space for one digit (or NaN). */
michael@0 902 /* ------------------------------------------------------------------ */
michael@0 903 U_CAPI decNumber * U_EXPORT2 uprv_decNumberCompareSignal(decNumber *res, const decNumber *lhs,
michael@0 904 const decNumber *rhs, decContext *set) {
michael@0 905 uInt status=0; /* accumulator */
michael@0 906 decCompareOp(res, lhs, rhs, set, COMPSIG, &status);
michael@0 907 if (status!=0) decStatus(res, status, set);
michael@0 908 return res;
michael@0 909 } /* decNumberCompareSignal */
michael@0 910
michael@0 911 /* ------------------------------------------------------------------ */
michael@0 912 /* decNumberCompareTotal -- compare two Numbers, using total ordering */
michael@0 913 /* */
michael@0 914 /* This computes C = A ? B, under total ordering */
michael@0 915 /* */
michael@0 916 /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
michael@0 917 /* lhs is A */
michael@0 918 /* rhs is B */
michael@0 919 /* set is the context */
michael@0 920 /* */
michael@0 921 /* C must have space for one digit; the result will always be one of */
michael@0 922 /* -1, 0, or 1. */
michael@0 923 /* ------------------------------------------------------------------ */
michael@0 924 U_CAPI decNumber * U_EXPORT2 uprv_decNumberCompareTotal(decNumber *res, const decNumber *lhs,
michael@0 925 const decNumber *rhs, decContext *set) {
michael@0 926 uInt status=0; /* accumulator */
michael@0 927 decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status);
michael@0 928 if (status!=0) decStatus(res, status, set);
michael@0 929 return res;
michael@0 930 } /* decNumberCompareTotal */
michael@0 931
michael@0 932 /* ------------------------------------------------------------------ */
michael@0 933 /* decNumberCompareTotalMag -- compare, total ordering of magnitudes */
michael@0 934 /* */
michael@0 935 /* This computes C = |A| ? |B|, under total ordering */
michael@0 936 /* */
michael@0 937 /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
michael@0 938 /* lhs is A */
michael@0 939 /* rhs is B */
michael@0 940 /* set is the context */
michael@0 941 /* */
michael@0 942 /* C must have space for one digit; the result will always be one of */
michael@0 943 /* -1, 0, or 1. */
michael@0 944 /* ------------------------------------------------------------------ */
michael@0 945 U_CAPI decNumber * U_EXPORT2 uprv_decNumberCompareTotalMag(decNumber *res, const decNumber *lhs,
michael@0 946 const decNumber *rhs, decContext *set) {
michael@0 947 uInt status=0; /* accumulator */
michael@0 948 uInt needbytes; /* for space calculations */
michael@0 949 decNumber bufa[D2N(DECBUFFER+1)];/* +1 in case DECBUFFER=0 */
michael@0 950 decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */
michael@0 951 decNumber bufb[D2N(DECBUFFER+1)];
michael@0 952 decNumber *allocbufb=NULL; /* -> allocated bufb, iff allocated */
michael@0 953 decNumber *a, *b; /* temporary pointers */
michael@0 954
michael@0 955 #if DECCHECK
michael@0 956 if (decCheckOperands(res, lhs, rhs, set)) return res;
michael@0 957 #endif
michael@0 958
michael@0 959 do { /* protect allocated storage */
michael@0 960 /* if either is negative, take a copy and absolute */
michael@0 961 if (decNumberIsNegative(lhs)) { /* lhs<0 */
michael@0 962 a=bufa;
michael@0 963 needbytes=sizeof(decNumber)+(D2U(lhs->digits)-1)*sizeof(Unit);
michael@0 964 if (needbytes>sizeof(bufa)) { /* need malloc space */
michael@0 965 allocbufa=(decNumber *)malloc(needbytes);
michael@0 966 if (allocbufa==NULL) { /* hopeless -- abandon */
michael@0 967 status|=DEC_Insufficient_storage;
michael@0 968 break;}
michael@0 969 a=allocbufa; /* use the allocated space */
michael@0 970 }
michael@0 971 uprv_decNumberCopy(a, lhs); /* copy content */
michael@0 972 a->bits&=~DECNEG; /* .. and clear the sign */
michael@0 973 lhs=a; /* use copy from here on */
michael@0 974 }
michael@0 975 if (decNumberIsNegative(rhs)) { /* rhs<0 */
michael@0 976 b=bufb;
michael@0 977 needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
michael@0 978 if (needbytes>sizeof(bufb)) { /* need malloc space */
michael@0 979 allocbufb=(decNumber *)malloc(needbytes);
michael@0 980 if (allocbufb==NULL) { /* hopeless -- abandon */
michael@0 981 status|=DEC_Insufficient_storage;
michael@0 982 break;}
michael@0 983 b=allocbufb; /* use the allocated space */
michael@0 984 }
michael@0 985 uprv_decNumberCopy(b, rhs); /* copy content */
michael@0 986 b->bits&=~DECNEG; /* .. and clear the sign */
michael@0 987 rhs=b; /* use copy from here on */
michael@0 988 }
michael@0 989 decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status);
michael@0 990 } while(0); /* end protected */
michael@0 991
michael@0 992 if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
michael@0 993 if (allocbufb!=NULL) free(allocbufb); /* .. */
michael@0 994 if (status!=0) decStatus(res, status, set);
michael@0 995 return res;
michael@0 996 } /* decNumberCompareTotalMag */
michael@0 997
michael@0 998 /* ------------------------------------------------------------------ */
michael@0 999 /* decNumberDivide -- divide one number by another */
michael@0 1000 /* */
michael@0 1001 /* This computes C = A / B */
michael@0 1002 /* */
michael@0 1003 /* res is C, the result. C may be A and/or B (e.g., X=X/X) */
michael@0 1004 /* lhs is A */
michael@0 1005 /* rhs is B */
michael@0 1006 /* set is the context */
michael@0 1007 /* */
michael@0 1008 /* C must have space for set->digits digits. */
michael@0 1009 /* ------------------------------------------------------------------ */
michael@0 1010 U_CAPI decNumber * U_EXPORT2 uprv_decNumberDivide(decNumber *res, const decNumber *lhs,
michael@0 1011 const decNumber *rhs, decContext *set) {
michael@0 1012 uInt status=0; /* accumulator */
michael@0 1013 decDivideOp(res, lhs, rhs, set, DIVIDE, &status);
michael@0 1014 if (status!=0) decStatus(res, status, set);
michael@0 1015 #if DECCHECK
michael@0 1016 decCheckInexact(res, set);
michael@0 1017 #endif
michael@0 1018 return res;
michael@0 1019 } /* decNumberDivide */
michael@0 1020
michael@0 1021 /* ------------------------------------------------------------------ */
michael@0 1022 /* decNumberDivideInteger -- divide and return integer quotient */
michael@0 1023 /* */
michael@0 1024 /* This computes C = A # B, where # is the integer divide operator */
michael@0 1025 /* */
michael@0 1026 /* res is C, the result. C may be A and/or B (e.g., X=X#X) */
michael@0 1027 /* lhs is A */
michael@0 1028 /* rhs is B */
michael@0 1029 /* set is the context */
michael@0 1030 /* */
michael@0 1031 /* C must have space for set->digits digits. */
michael@0 1032 /* ------------------------------------------------------------------ */
michael@0 1033 U_CAPI decNumber * U_EXPORT2 uprv_decNumberDivideInteger(decNumber *res, const decNumber *lhs,
michael@0 1034 const decNumber *rhs, decContext *set) {
michael@0 1035 uInt status=0; /* accumulator */
michael@0 1036 decDivideOp(res, lhs, rhs, set, DIVIDEINT, &status);
michael@0 1037 if (status!=0) decStatus(res, status, set);
michael@0 1038 return res;
michael@0 1039 } /* decNumberDivideInteger */
michael@0 1040
michael@0 1041 /* ------------------------------------------------------------------ */
michael@0 1042 /* decNumberExp -- exponentiation */
michael@0 1043 /* */
michael@0 1044 /* This computes C = exp(A) */
michael@0 1045 /* */
michael@0 1046 /* res is C, the result. C may be A */
michael@0 1047 /* rhs is A */
michael@0 1048 /* set is the context; note that rounding mode has no effect */
michael@0 1049 /* */
michael@0 1050 /* C must have space for set->digits digits. */
michael@0 1051 /* */
michael@0 1052 /* Mathematical function restrictions apply (see above); a NaN is */
michael@0 1053 /* returned with Invalid_operation if a restriction is violated. */
michael@0 1054 /* */
michael@0 1055 /* Finite results will always be full precision and Inexact, except */
michael@0 1056 /* when A is a zero or -Infinity (giving 1 or 0 respectively). */
michael@0 1057 /* */
michael@0 1058 /* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */
michael@0 1059 /* almost always be correctly rounded, but may be up to 1 ulp in */
michael@0 1060 /* error in rare cases. */
michael@0 1061 /* ------------------------------------------------------------------ */
michael@0 1062 /* This is a wrapper for decExpOp which can handle the slightly wider */
michael@0 1063 /* (double) range needed by Ln (which has to be able to calculate */
michael@0 1064 /* exp(-a) where a can be the tiniest number (Ntiny). */
michael@0 1065 /* ------------------------------------------------------------------ */
michael@0 1066 U_CAPI decNumber * U_EXPORT2 uprv_decNumberExp(decNumber *res, const decNumber *rhs,
michael@0 1067 decContext *set) {
michael@0 1068 uInt status=0; /* accumulator */
michael@0 1069 #if DECSUBSET
michael@0 1070 decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */
michael@0 1071 #endif
michael@0 1072
michael@0 1073 #if DECCHECK
michael@0 1074 if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
michael@0 1075 #endif
michael@0 1076
michael@0 1077 /* Check restrictions; these restrictions ensure that if h=8 (see */
michael@0 1078 /* decExpOp) then the result will either overflow or underflow to 0. */
michael@0 1079 /* Other math functions restrict the input range, too, for inverses. */
michael@0 1080 /* If not violated then carry out the operation. */
michael@0 1081 if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */
michael@0 1082 #if DECSUBSET
michael@0 1083 if (!set->extended) {
michael@0 1084 /* reduce operand and set lostDigits status, as needed */
michael@0 1085 if (rhs->digits>set->digits) {
michael@0 1086 allocrhs=decRoundOperand(rhs, set, &status);
michael@0 1087 if (allocrhs==NULL) break;
michael@0 1088 rhs=allocrhs;
michael@0 1089 }
michael@0 1090 }
michael@0 1091 #endif
michael@0 1092 decExpOp(res, rhs, set, &status);
michael@0 1093 } while(0); /* end protected */
michael@0 1094
michael@0 1095 #if DECSUBSET
michael@0 1096 if (allocrhs !=NULL) free(allocrhs); /* drop any storage used */
michael@0 1097 #endif
michael@0 1098 /* apply significant status */
michael@0 1099 if (status!=0) decStatus(res, status, set);
michael@0 1100 #if DECCHECK
michael@0 1101 decCheckInexact(res, set);
michael@0 1102 #endif
michael@0 1103 return res;
michael@0 1104 } /* decNumberExp */
michael@0 1105
michael@0 1106 /* ------------------------------------------------------------------ */
michael@0 1107 /* decNumberFMA -- fused multiply add */
michael@0 1108 /* */
michael@0 1109 /* This computes D = (A * B) + C with only one rounding */
michael@0 1110 /* */
michael@0 1111 /* res is D, the result. D may be A or B or C (e.g., X=FMA(X,X,X)) */
michael@0 1112 /* lhs is A */
michael@0 1113 /* rhs is B */
michael@0 1114 /* fhs is C [far hand side] */
michael@0 1115 /* set is the context */
michael@0 1116 /* */
michael@0 1117 /* Mathematical function restrictions apply (see above); a NaN is */
michael@0 1118 /* returned with Invalid_operation if a restriction is violated. */
michael@0 1119 /* */
michael@0 1120 /* C must have space for set->digits digits. */
michael@0 1121 /* ------------------------------------------------------------------ */
michael@0 1122 U_CAPI decNumber * U_EXPORT2 uprv_decNumberFMA(decNumber *res, const decNumber *lhs,
michael@0 1123 const decNumber *rhs, const decNumber *fhs,
michael@0 1124 decContext *set) {
michael@0 1125 uInt status=0; /* accumulator */
michael@0 1126 decContext dcmul; /* context for the multiplication */
michael@0 1127 uInt needbytes; /* for space calculations */
michael@0 1128 decNumber bufa[D2N(DECBUFFER*2+1)];
michael@0 1129 decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */
michael@0 1130 decNumber *acc; /* accumulator pointer */
michael@0 1131 decNumber dzero; /* work */
michael@0 1132
michael@0 1133 #if DECCHECK
michael@0 1134 if (decCheckOperands(res, lhs, rhs, set)) return res;
michael@0 1135 if (decCheckOperands(res, fhs, DECUNUSED, set)) return res;
michael@0 1136 #endif
michael@0 1137
michael@0 1138 do { /* protect allocated storage */
michael@0 1139 #if DECSUBSET
michael@0 1140 if (!set->extended) { /* [undefined if subset] */
michael@0 1141 status|=DEC_Invalid_operation;
michael@0 1142 break;}
michael@0 1143 #endif
michael@0 1144 /* Check math restrictions [these ensure no overflow or underflow] */
michael@0 1145 if ((!decNumberIsSpecial(lhs) && decCheckMath(lhs, set, &status))
michael@0 1146 || (!decNumberIsSpecial(rhs) && decCheckMath(rhs, set, &status))
michael@0 1147 || (!decNumberIsSpecial(fhs) && decCheckMath(fhs, set, &status))) break;
michael@0 1148 /* set up context for multiply */
michael@0 1149 dcmul=*set;
michael@0 1150 dcmul.digits=lhs->digits+rhs->digits; /* just enough */
michael@0 1151 /* [The above may be an over-estimate for subset arithmetic, but that's OK] */
michael@0 1152 dcmul.emax=DEC_MAX_EMAX; /* effectively unbounded .. */
michael@0 1153 dcmul.emin=DEC_MIN_EMIN; /* [thanks to Math restrictions] */
michael@0 1154 /* set up decNumber space to receive the result of the multiply */
michael@0 1155 acc=bufa; /* may fit */
michael@0 1156 needbytes=sizeof(decNumber)+(D2U(dcmul.digits)-1)*sizeof(Unit);
michael@0 1157 if (needbytes>sizeof(bufa)) { /* need malloc space */
michael@0 1158 allocbufa=(decNumber *)malloc(needbytes);
michael@0 1159 if (allocbufa==NULL) { /* hopeless -- abandon */
michael@0 1160 status|=DEC_Insufficient_storage;
michael@0 1161 break;}
michael@0 1162 acc=allocbufa; /* use the allocated space */
michael@0 1163 }
michael@0 1164 /* multiply with extended range and necessary precision */
michael@0 1165 /*printf("emin=%ld\n", dcmul.emin); */
michael@0 1166 decMultiplyOp(acc, lhs, rhs, &dcmul, &status);
michael@0 1167 /* Only Invalid operation (from sNaN or Inf * 0) is possible in */
michael@0 1168 /* status; if either is seen than ignore fhs (in case it is */
michael@0 1169 /* another sNaN) and set acc to NaN unless we had an sNaN */
michael@0 1170 /* [decMultiplyOp leaves that to caller] */
michael@0 1171 /* Note sNaN has to go through addOp to shorten payload if */
michael@0 1172 /* necessary */
michael@0 1173 if ((status&DEC_Invalid_operation)!=0) {
michael@0 1174 if (!(status&DEC_sNaN)) { /* but be true invalid */
michael@0 1175 uprv_decNumberZero(res); /* acc not yet set */
michael@0 1176 res->bits=DECNAN;
michael@0 1177 break;
michael@0 1178 }
michael@0 1179 uprv_decNumberZero(&dzero); /* make 0 (any non-NaN would do) */
michael@0 1180 fhs=&dzero; /* use that */
michael@0 1181 }
michael@0 1182 #if DECCHECK
michael@0 1183 else { /* multiply was OK */
michael@0 1184 if (status!=0) printf("Status=%08lx after FMA multiply\n", (LI)status);
michael@0 1185 }
michael@0 1186 #endif
michael@0 1187 /* add the third operand and result -> res, and all is done */
michael@0 1188 decAddOp(res, acc, fhs, set, 0, &status);
michael@0 1189 } while(0); /* end protected */
michael@0 1190
michael@0 1191 if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
michael@0 1192 if (status!=0) decStatus(res, status, set);
michael@0 1193 #if DECCHECK
michael@0 1194 decCheckInexact(res, set);
michael@0 1195 #endif
michael@0 1196 return res;
michael@0 1197 } /* decNumberFMA */
michael@0 1198
michael@0 1199 /* ------------------------------------------------------------------ */
michael@0 1200 /* decNumberInvert -- invert a Number, digitwise */
michael@0 1201 /* */
michael@0 1202 /* This computes C = ~A */
michael@0 1203 /* */
michael@0 1204 /* res is C, the result. C may be A (e.g., X=~X) */
michael@0 1205 /* rhs is A */
michael@0 1206 /* set is the context (used for result length and error report) */
michael@0 1207 /* */
michael@0 1208 /* C must have space for set->digits digits. */
michael@0 1209 /* */
michael@0 1210 /* Logical function restrictions apply (see above); a NaN is */
michael@0 1211 /* returned with Invalid_operation if a restriction is violated. */
michael@0 1212 /* ------------------------------------------------------------------ */
michael@0 1213 U_CAPI decNumber * U_EXPORT2 uprv_decNumberInvert(decNumber *res, const decNumber *rhs,
michael@0 1214 decContext *set) {
michael@0 1215 const Unit *ua, *msua; /* -> operand and its msu */
michael@0 1216 Unit *uc, *msuc; /* -> result and its msu */
michael@0 1217 Int msudigs; /* digits in res msu */
michael@0 1218 #if DECCHECK
michael@0 1219 if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
michael@0 1220 #endif
michael@0 1221
michael@0 1222 if (rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
michael@0 1223 decStatus(res, DEC_Invalid_operation, set);
michael@0 1224 return res;
michael@0 1225 }
michael@0 1226 /* operand is valid */
michael@0 1227 ua=rhs->lsu; /* bottom-up */
michael@0 1228 uc=res->lsu; /* .. */
michael@0 1229 msua=ua+D2U(rhs->digits)-1; /* -> msu of rhs */
michael@0 1230 msuc=uc+D2U(set->digits)-1; /* -> msu of result */
michael@0 1231 msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */
michael@0 1232 for (; uc<=msuc; ua++, uc++) { /* Unit loop */
michael@0 1233 Unit a; /* extract unit */
michael@0 1234 Int i, j; /* work */
michael@0 1235 if (ua>msua) a=0;
michael@0 1236 else a=*ua;
michael@0 1237 *uc=0; /* can now write back */
michael@0 1238 /* always need to examine all bits in rhs */
michael@0 1239 /* This loop could be unrolled and/or use BIN2BCD tables */
michael@0 1240 for (i=0; i<DECDPUN; i++) {
michael@0 1241 if ((~a)&1) *uc=*uc+(Unit)powers[i]; /* effect INVERT */
michael@0 1242 j=a%10;
michael@0 1243 a=a/10;
michael@0 1244 if (j>1) {
michael@0 1245 decStatus(res, DEC_Invalid_operation, set);
michael@0 1246 return res;
michael@0 1247 }
michael@0 1248 if (uc==msuc && i==msudigs-1) break; /* just did final digit */
michael@0 1249 } /* each digit */
michael@0 1250 } /* each unit */
michael@0 1251 /* [here uc-1 is the msu of the result] */
michael@0 1252 res->digits=decGetDigits(res->lsu, uc-res->lsu);
michael@0 1253 res->exponent=0; /* integer */
michael@0 1254 res->bits=0; /* sign=0 */
michael@0 1255 return res; /* [no status to set] */
michael@0 1256 } /* decNumberInvert */
michael@0 1257
michael@0 1258 /* ------------------------------------------------------------------ */
michael@0 1259 /* decNumberLn -- natural logarithm */
michael@0 1260 /* */
michael@0 1261 /* This computes C = ln(A) */
michael@0 1262 /* */
michael@0 1263 /* res is C, the result. C may be A */
michael@0 1264 /* rhs is A */
michael@0 1265 /* set is the context; note that rounding mode has no effect */
michael@0 1266 /* */
michael@0 1267 /* C must have space for set->digits digits. */
michael@0 1268 /* */
michael@0 1269 /* Notable cases: */
michael@0 1270 /* A<0 -> Invalid */
michael@0 1271 /* A=0 -> -Infinity (Exact) */
michael@0 1272 /* A=+Infinity -> +Infinity (Exact) */
michael@0 1273 /* A=1 exactly -> 0 (Exact) */
michael@0 1274 /* */
michael@0 1275 /* Mathematical function restrictions apply (see above); a NaN is */
michael@0 1276 /* returned with Invalid_operation if a restriction is violated. */
michael@0 1277 /* */
michael@0 1278 /* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */
michael@0 1279 /* almost always be correctly rounded, but may be up to 1 ulp in */
michael@0 1280 /* error in rare cases. */
michael@0 1281 /* ------------------------------------------------------------------ */
michael@0 1282 /* This is a wrapper for decLnOp which can handle the slightly wider */
michael@0 1283 /* (+11) range needed by Ln, Log10, etc. (which may have to be able */
michael@0 1284 /* to calculate at p+e+2). */
michael@0 1285 /* ------------------------------------------------------------------ */
michael@0 1286 U_CAPI decNumber * U_EXPORT2 uprv_decNumberLn(decNumber *res, const decNumber *rhs,
michael@0 1287 decContext *set) {
michael@0 1288 uInt status=0; /* accumulator */
michael@0 1289 #if DECSUBSET
michael@0 1290 decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */
michael@0 1291 #endif
michael@0 1292
michael@0 1293 #if DECCHECK
michael@0 1294 if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
michael@0 1295 #endif
michael@0 1296
michael@0 1297 /* Check restrictions; this is a math function; if not violated */
michael@0 1298 /* then carry out the operation. */
michael@0 1299 if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */
michael@0 1300 #if DECSUBSET
michael@0 1301 if (!set->extended) {
michael@0 1302 /* reduce operand and set lostDigits status, as needed */
michael@0 1303 if (rhs->digits>set->digits) {
michael@0 1304 allocrhs=decRoundOperand(rhs, set, &status);
michael@0 1305 if (allocrhs==NULL) break;
michael@0 1306 rhs=allocrhs;
michael@0 1307 }
michael@0 1308 /* special check in subset for rhs=0 */
michael@0 1309 if (ISZERO(rhs)) { /* +/- zeros -> error */
michael@0 1310 status|=DEC_Invalid_operation;
michael@0 1311 break;}
michael@0 1312 } /* extended=0 */
michael@0 1313 #endif
michael@0 1314 decLnOp(res, rhs, set, &status);
michael@0 1315 } while(0); /* end protected */
michael@0 1316
michael@0 1317 #if DECSUBSET
michael@0 1318 if (allocrhs !=NULL) free(allocrhs); /* drop any storage used */
michael@0 1319 #endif
michael@0 1320 /* apply significant status */
michael@0 1321 if (status!=0) decStatus(res, status, set);
michael@0 1322 #if DECCHECK
michael@0 1323 decCheckInexact(res, set);
michael@0 1324 #endif
michael@0 1325 return res;
michael@0 1326 } /* decNumberLn */
michael@0 1327
michael@0 1328 /* ------------------------------------------------------------------ */
michael@0 1329 /* decNumberLogB - get adjusted exponent, by 754 rules */
michael@0 1330 /* */
michael@0 1331 /* This computes C = adjustedexponent(A) */
michael@0 1332 /* */
michael@0 1333 /* res is C, the result. C may be A */
michael@0 1334 /* rhs is A */
michael@0 1335 /* set is the context, used only for digits and status */
michael@0 1336 /* */
michael@0 1337 /* C must have space for 10 digits (A might have 10**9 digits and */
michael@0 1338 /* an exponent of +999999999, or one digit and an exponent of */
michael@0 1339 /* -1999999999). */
michael@0 1340 /* */
michael@0 1341 /* This returns the adjusted exponent of A after (in theory) padding */
michael@0 1342 /* with zeros on the right to set->digits digits while keeping the */
michael@0 1343 /* same value. The exponent is not limited by emin/emax. */
michael@0 1344 /* */
michael@0 1345 /* Notable cases: */
michael@0 1346 /* A<0 -> Use |A| */
michael@0 1347 /* A=0 -> -Infinity (Division by zero) */
michael@0 1348 /* A=Infinite -> +Infinity (Exact) */
michael@0 1349 /* A=1 exactly -> 0 (Exact) */
michael@0 1350 /* NaNs are propagated as usual */
michael@0 1351 /* ------------------------------------------------------------------ */
michael@0 1352 U_CAPI decNumber * U_EXPORT2 uprv_decNumberLogB(decNumber *res, const decNumber *rhs,
michael@0 1353 decContext *set) {
michael@0 1354 uInt status=0; /* accumulator */
michael@0 1355
michael@0 1356 #if DECCHECK
michael@0 1357 if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
michael@0 1358 #endif
michael@0 1359
michael@0 1360 /* NaNs as usual; Infinities return +Infinity; 0->oops */
michael@0 1361 if (decNumberIsNaN(rhs)) decNaNs(res, rhs, NULL, set, &status);
michael@0 1362 else if (decNumberIsInfinite(rhs)) uprv_decNumberCopyAbs(res, rhs);
michael@0 1363 else if (decNumberIsZero(rhs)) {
michael@0 1364 uprv_decNumberZero(res); /* prepare for Infinity */
michael@0 1365 res->bits=DECNEG|DECINF; /* -Infinity */
michael@0 1366 status|=DEC_Division_by_zero; /* as per 754 */
michael@0 1367 }
michael@0 1368 else { /* finite non-zero */
michael@0 1369 Int ae=rhs->exponent+rhs->digits-1; /* adjusted exponent */
michael@0 1370 uprv_decNumberFromInt32(res, ae); /* lay it out */
michael@0 1371 }
michael@0 1372
michael@0 1373 if (status!=0) decStatus(res, status, set);
michael@0 1374 return res;
michael@0 1375 } /* decNumberLogB */
michael@0 1376
michael@0 1377 /* ------------------------------------------------------------------ */
michael@0 1378 /* decNumberLog10 -- logarithm in base 10 */
michael@0 1379 /* */
michael@0 1380 /* This computes C = log10(A) */
michael@0 1381 /* */
michael@0 1382 /* res is C, the result. C may be A */
michael@0 1383 /* rhs is A */
michael@0 1384 /* set is the context; note that rounding mode has no effect */
michael@0 1385 /* */
michael@0 1386 /* C must have space for set->digits digits. */
michael@0 1387 /* */
michael@0 1388 /* Notable cases: */
michael@0 1389 /* A<0 -> Invalid */
michael@0 1390 /* A=0 -> -Infinity (Exact) */
michael@0 1391 /* A=+Infinity -> +Infinity (Exact) */
michael@0 1392 /* A=10**n (if n is an integer) -> n (Exact) */
michael@0 1393 /* */
michael@0 1394 /* Mathematical function restrictions apply (see above); a NaN is */
michael@0 1395 /* returned with Invalid_operation if a restriction is violated. */
michael@0 1396 /* */
michael@0 1397 /* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */
michael@0 1398 /* almost always be correctly rounded, but may be up to 1 ulp in */
michael@0 1399 /* error in rare cases. */
michael@0 1400 /* ------------------------------------------------------------------ */
michael@0 1401 /* This calculates ln(A)/ln(10) using appropriate precision. For */
michael@0 1402 /* ln(A) this is the max(p, rhs->digits + t) + 3, where p is the */
michael@0 1403 /* requested digits and t is the number of digits in the exponent */
michael@0 1404 /* (maximum 6). For ln(10) it is p + 3; this is often handled by the */
michael@0 1405 /* fastpath in decLnOp. The final division is done to the requested */
michael@0 1406 /* precision. */
michael@0 1407 /* ------------------------------------------------------------------ */
michael@0 1408 #if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406
michael@0 1409 #pragma GCC diagnostic push
michael@0 1410 #pragma GCC diagnostic ignored "-Warray-bounds"
michael@0 1411 #endif
michael@0 1412 U_CAPI decNumber * U_EXPORT2 uprv_decNumberLog10(decNumber *res, const decNumber *rhs,
michael@0 1413 decContext *set) {
michael@0 1414 uInt status=0, ignore=0; /* status accumulators */
michael@0 1415 uInt needbytes; /* for space calculations */
michael@0 1416 Int p; /* working precision */
michael@0 1417 Int t; /* digits in exponent of A */
michael@0 1418
michael@0 1419 /* buffers for a and b working decimals */
michael@0 1420 /* (adjustment calculator, same size) */
michael@0 1421 decNumber bufa[D2N(DECBUFFER+2)];
michael@0 1422 decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */
michael@0 1423 decNumber *a=bufa; /* temporary a */
michael@0 1424 decNumber bufb[D2N(DECBUFFER+2)];
michael@0 1425 decNumber *allocbufb=NULL; /* -> allocated bufb, iff allocated */
michael@0 1426 decNumber *b=bufb; /* temporary b */
michael@0 1427 decNumber bufw[D2N(10)]; /* working 2-10 digit number */
michael@0 1428 decNumber *w=bufw; /* .. */
michael@0 1429 #if DECSUBSET
michael@0 1430 decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */
michael@0 1431 #endif
michael@0 1432
michael@0 1433 decContext aset; /* working context */
michael@0 1434
michael@0 1435 #if DECCHECK
michael@0 1436 if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
michael@0 1437 #endif
michael@0 1438
michael@0 1439 /* Check restrictions; this is a math function; if not violated */
michael@0 1440 /* then carry out the operation. */
michael@0 1441 if (!decCheckMath(rhs, set, &status)) do { /* protect malloc */
michael@0 1442 #if DECSUBSET
michael@0 1443 if (!set->extended) {
michael@0 1444 /* reduce operand and set lostDigits status, as needed */
michael@0 1445 if (rhs->digits>set->digits) {
michael@0 1446 allocrhs=decRoundOperand(rhs, set, &status);
michael@0 1447 if (allocrhs==NULL) break;
michael@0 1448 rhs=allocrhs;
michael@0 1449 }
michael@0 1450 /* special check in subset for rhs=0 */
michael@0 1451 if (ISZERO(rhs)) { /* +/- zeros -> error */
michael@0 1452 status|=DEC_Invalid_operation;
michael@0 1453 break;}
michael@0 1454 } /* extended=0 */
michael@0 1455 #endif
michael@0 1456
michael@0 1457 uprv_decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */
michael@0 1458
michael@0 1459 /* handle exact powers of 10; only check if +ve finite */
michael@0 1460 if (!(rhs->bits&(DECNEG|DECSPECIAL)) && !ISZERO(rhs)) {
michael@0 1461 Int residue=0; /* (no residue) */
michael@0 1462 uInt copystat=0; /* clean status */
michael@0 1463
michael@0 1464 /* round to a single digit... */
michael@0 1465 aset.digits=1;
michael@0 1466 decCopyFit(w, rhs, &aset, &residue, &copystat); /* copy & shorten */
michael@0 1467 /* if exact and the digit is 1, rhs is a power of 10 */
michael@0 1468 if (!(copystat&DEC_Inexact) && w->lsu[0]==1) {
michael@0 1469 /* the exponent, conveniently, is the power of 10; making */
michael@0 1470 /* this the result needs a little care as it might not fit, */
michael@0 1471 /* so first convert it into the working number, and then move */
michael@0 1472 /* to res */
michael@0 1473 uprv_decNumberFromInt32(w, w->exponent);
michael@0 1474 residue=0;
michael@0 1475 decCopyFit(res, w, set, &residue, &status); /* copy & round */
michael@0 1476 decFinish(res, set, &residue, &status); /* cleanup/set flags */
michael@0 1477 break;
michael@0 1478 } /* not a power of 10 */
michael@0 1479 } /* not a candidate for exact */
michael@0 1480
michael@0 1481 /* simplify the information-content calculation to use 'total */
michael@0 1482 /* number of digits in a, including exponent' as compared to the */
michael@0 1483 /* requested digits, as increasing this will only rarely cost an */
michael@0 1484 /* iteration in ln(a) anyway */
michael@0 1485 t=6; /* it can never be >6 */
michael@0 1486
michael@0 1487 /* allocate space when needed... */
michael@0 1488 p=(rhs->digits+t>set->digits?rhs->digits+t:set->digits)+3;
michael@0 1489 needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit);
michael@0 1490 if (needbytes>sizeof(bufa)) { /* need malloc space */
michael@0 1491 allocbufa=(decNumber *)malloc(needbytes);
michael@0 1492 if (allocbufa==NULL) { /* hopeless -- abandon */
michael@0 1493 status|=DEC_Insufficient_storage;
michael@0 1494 break;}
michael@0 1495 a=allocbufa; /* use the allocated space */
michael@0 1496 }
michael@0 1497 aset.digits=p; /* as calculated */
michael@0 1498 aset.emax=DEC_MAX_MATH; /* usual bounds */
michael@0 1499 aset.emin=-DEC_MAX_MATH; /* .. */
michael@0 1500 aset.clamp=0; /* and no concrete format */
michael@0 1501 decLnOp(a, rhs, &aset, &status); /* a=ln(rhs) */
michael@0 1502
michael@0 1503 /* skip the division if the result so far is infinite, NaN, or */
michael@0 1504 /* zero, or there was an error; note NaN from sNaN needs copy */
michael@0 1505 if (status&DEC_NaNs && !(status&DEC_sNaN)) break;
michael@0 1506 if (a->bits&DECSPECIAL || ISZERO(a)) {
michael@0 1507 uprv_decNumberCopy(res, a); /* [will fit] */
michael@0 1508 break;}
michael@0 1509
michael@0 1510 /* for ln(10) an extra 3 digits of precision are needed */
michael@0 1511 p=set->digits+3;
michael@0 1512 needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit);
michael@0 1513 if (needbytes>sizeof(bufb)) { /* need malloc space */
michael@0 1514 allocbufb=(decNumber *)malloc(needbytes);
michael@0 1515 if (allocbufb==NULL) { /* hopeless -- abandon */
michael@0 1516 status|=DEC_Insufficient_storage;
michael@0 1517 break;}
michael@0 1518 b=allocbufb; /* use the allocated space */
michael@0 1519 }
michael@0 1520 uprv_decNumberZero(w); /* set up 10... */
michael@0 1521 #if DECDPUN==1
michael@0 1522 w->lsu[1]=1; w->lsu[0]=0; /* .. */
michael@0 1523 #else
michael@0 1524 w->lsu[0]=10; /* .. */
michael@0 1525 #endif
michael@0 1526 w->digits=2; /* .. */
michael@0 1527
michael@0 1528 aset.digits=p;
michael@0 1529 decLnOp(b, w, &aset, &ignore); /* b=ln(10) */
michael@0 1530
michael@0 1531 aset.digits=set->digits; /* for final divide */
michael@0 1532 decDivideOp(res, a, b, &aset, DIVIDE, &status); /* into result */
michael@0 1533 } while(0); /* [for break] */
michael@0 1534
michael@0 1535 if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
michael@0 1536 if (allocbufb!=NULL) free(allocbufb); /* .. */
michael@0 1537 #if DECSUBSET
michael@0 1538 if (allocrhs !=NULL) free(allocrhs); /* .. */
michael@0 1539 #endif
michael@0 1540 /* apply significant status */
michael@0 1541 if (status!=0) decStatus(res, status, set);
michael@0 1542 #if DECCHECK
michael@0 1543 decCheckInexact(res, set);
michael@0 1544 #endif
michael@0 1545 return res;
michael@0 1546 } /* decNumberLog10 */
michael@0 1547 #if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406
michael@0 1548 #pragma GCC diagnostic pop
michael@0 1549 #endif
michael@0 1550
michael@0 1551 /* ------------------------------------------------------------------ */
michael@0 1552 /* decNumberMax -- compare two Numbers and return the maximum */
michael@0 1553 /* */
michael@0 1554 /* This computes C = A ? B, returning the maximum by 754 rules */
michael@0 1555 /* */
michael@0 1556 /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
michael@0 1557 /* lhs is A */
michael@0 1558 /* rhs is B */
michael@0 1559 /* set is the context */
michael@0 1560 /* */
michael@0 1561 /* C must have space for set->digits digits. */
michael@0 1562 /* ------------------------------------------------------------------ */
michael@0 1563 U_CAPI decNumber * U_EXPORT2 uprv_decNumberMax(decNumber *res, const decNumber *lhs,
michael@0 1564 const decNumber *rhs, decContext *set) {
michael@0 1565 uInt status=0; /* accumulator */
michael@0 1566 decCompareOp(res, lhs, rhs, set, COMPMAX, &status);
michael@0 1567 if (status!=0) decStatus(res, status, set);
michael@0 1568 #if DECCHECK
michael@0 1569 decCheckInexact(res, set);
michael@0 1570 #endif
michael@0 1571 return res;
michael@0 1572 } /* decNumberMax */
michael@0 1573
michael@0 1574 /* ------------------------------------------------------------------ */
michael@0 1575 /* decNumberMaxMag -- compare and return the maximum by magnitude */
michael@0 1576 /* */
michael@0 1577 /* This computes C = A ? B, returning the maximum by 754 rules */
michael@0 1578 /* */
michael@0 1579 /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
michael@0 1580 /* lhs is A */
michael@0 1581 /* rhs is B */
michael@0 1582 /* set is the context */
michael@0 1583 /* */
michael@0 1584 /* C must have space for set->digits digits. */
michael@0 1585 /* ------------------------------------------------------------------ */
michael@0 1586 U_CAPI decNumber * U_EXPORT2 uprv_decNumberMaxMag(decNumber *res, const decNumber *lhs,
michael@0 1587 const decNumber *rhs, decContext *set) {
michael@0 1588 uInt status=0; /* accumulator */
michael@0 1589 decCompareOp(res, lhs, rhs, set, COMPMAXMAG, &status);
michael@0 1590 if (status!=0) decStatus(res, status, set);
michael@0 1591 #if DECCHECK
michael@0 1592 decCheckInexact(res, set);
michael@0 1593 #endif
michael@0 1594 return res;
michael@0 1595 } /* decNumberMaxMag */
michael@0 1596
michael@0 1597 /* ------------------------------------------------------------------ */
michael@0 1598 /* decNumberMin -- compare two Numbers and return the minimum */
michael@0 1599 /* */
michael@0 1600 /* This computes C = A ? B, returning the minimum by 754 rules */
michael@0 1601 /* */
michael@0 1602 /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
michael@0 1603 /* lhs is A */
michael@0 1604 /* rhs is B */
michael@0 1605 /* set is the context */
michael@0 1606 /* */
michael@0 1607 /* C must have space for set->digits digits. */
michael@0 1608 /* ------------------------------------------------------------------ */
michael@0 1609 U_CAPI decNumber * U_EXPORT2 uprv_decNumberMin(decNumber *res, const decNumber *lhs,
michael@0 1610 const decNumber *rhs, decContext *set) {
michael@0 1611 uInt status=0; /* accumulator */
michael@0 1612 decCompareOp(res, lhs, rhs, set, COMPMIN, &status);
michael@0 1613 if (status!=0) decStatus(res, status, set);
michael@0 1614 #if DECCHECK
michael@0 1615 decCheckInexact(res, set);
michael@0 1616 #endif
michael@0 1617 return res;
michael@0 1618 } /* decNumberMin */
michael@0 1619
michael@0 1620 /* ------------------------------------------------------------------ */
michael@0 1621 /* decNumberMinMag -- compare and return the minimum by magnitude */
michael@0 1622 /* */
michael@0 1623 /* This computes C = A ? B, returning the minimum by 754 rules */
michael@0 1624 /* */
michael@0 1625 /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
michael@0 1626 /* lhs is A */
michael@0 1627 /* rhs is B */
michael@0 1628 /* set is the context */
michael@0 1629 /* */
michael@0 1630 /* C must have space for set->digits digits. */
michael@0 1631 /* ------------------------------------------------------------------ */
michael@0 1632 U_CAPI decNumber * U_EXPORT2 uprv_decNumberMinMag(decNumber *res, const decNumber *lhs,
michael@0 1633 const decNumber *rhs, decContext *set) {
michael@0 1634 uInt status=0; /* accumulator */
michael@0 1635 decCompareOp(res, lhs, rhs, set, COMPMINMAG, &status);
michael@0 1636 if (status!=0) decStatus(res, status, set);
michael@0 1637 #if DECCHECK
michael@0 1638 decCheckInexact(res, set);
michael@0 1639 #endif
michael@0 1640 return res;
michael@0 1641 } /* decNumberMinMag */
michael@0 1642
michael@0 1643 /* ------------------------------------------------------------------ */
michael@0 1644 /* decNumberMinus -- prefix minus operator */
michael@0 1645 /* */
michael@0 1646 /* This computes C = 0 - A */
michael@0 1647 /* */
michael@0 1648 /* res is C, the result. C may be A */
michael@0 1649 /* rhs is A */
michael@0 1650 /* set is the context */
michael@0 1651 /* */
michael@0 1652 /* See also decNumberCopyNegate for a quiet bitwise version of this. */
michael@0 1653 /* C must have space for set->digits digits. */
michael@0 1654 /* ------------------------------------------------------------------ */
michael@0 1655 /* Simply use AddOp for the subtract, which will do the necessary. */
michael@0 1656 /* ------------------------------------------------------------------ */
michael@0 1657 U_CAPI decNumber * U_EXPORT2 uprv_decNumberMinus(decNumber *res, const decNumber *rhs,
michael@0 1658 decContext *set) {
michael@0 1659 decNumber dzero;
michael@0 1660 uInt status=0; /* accumulator */
michael@0 1661
michael@0 1662 #if DECCHECK
michael@0 1663 if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
michael@0 1664 #endif
michael@0 1665
michael@0 1666 uprv_decNumberZero(&dzero); /* make 0 */
michael@0 1667 dzero.exponent=rhs->exponent; /* [no coefficient expansion] */
michael@0 1668 decAddOp(res, &dzero, rhs, set, DECNEG, &status);
michael@0 1669 if (status!=0) decStatus(res, status, set);
michael@0 1670 #if DECCHECK
michael@0 1671 decCheckInexact(res, set);
michael@0 1672 #endif
michael@0 1673 return res;
michael@0 1674 } /* decNumberMinus */
michael@0 1675
michael@0 1676 /* ------------------------------------------------------------------ */
michael@0 1677 /* decNumberNextMinus -- next towards -Infinity */
michael@0 1678 /* */
michael@0 1679 /* This computes C = A - infinitesimal, rounded towards -Infinity */
michael@0 1680 /* */
michael@0 1681 /* res is C, the result. C may be A */
michael@0 1682 /* rhs is A */
michael@0 1683 /* set is the context */
michael@0 1684 /* */
michael@0 1685 /* This is a generalization of 754 NextDown. */
michael@0 1686 /* ------------------------------------------------------------------ */
michael@0 1687 U_CAPI decNumber * U_EXPORT2 uprv_decNumberNextMinus(decNumber *res, const decNumber *rhs,
michael@0 1688 decContext *set) {
michael@0 1689 decNumber dtiny; /* constant */
michael@0 1690 decContext workset=*set; /* work */
michael@0 1691 uInt status=0; /* accumulator */
michael@0 1692 #if DECCHECK
michael@0 1693 if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
michael@0 1694 #endif
michael@0 1695
michael@0 1696 /* +Infinity is the special case */
michael@0 1697 if ((rhs->bits&(DECINF|DECNEG))==DECINF) {
michael@0 1698 decSetMaxValue(res, set); /* is +ve */
michael@0 1699 /* there is no status to set */
michael@0 1700 return res;
michael@0 1701 }
michael@0 1702 uprv_decNumberZero(&dtiny); /* start with 0 */
michael@0 1703 dtiny.lsu[0]=1; /* make number that is .. */
michael@0 1704 dtiny.exponent=DEC_MIN_EMIN-1; /* .. smaller than tiniest */
michael@0 1705 workset.round=DEC_ROUND_FLOOR;
michael@0 1706 decAddOp(res, rhs, &dtiny, &workset, DECNEG, &status);
michael@0 1707 status&=DEC_Invalid_operation|DEC_sNaN; /* only sNaN Invalid please */
michael@0 1708 if (status!=0) decStatus(res, status, set);
michael@0 1709 return res;
michael@0 1710 } /* decNumberNextMinus */
michael@0 1711
michael@0 1712 /* ------------------------------------------------------------------ */
michael@0 1713 /* decNumberNextPlus -- next towards +Infinity */
michael@0 1714 /* */
michael@0 1715 /* This computes C = A + infinitesimal, rounded towards +Infinity */
michael@0 1716 /* */
michael@0 1717 /* res is C, the result. C may be A */
michael@0 1718 /* rhs is A */
michael@0 1719 /* set is the context */
michael@0 1720 /* */
michael@0 1721 /* This is a generalization of 754 NextUp. */
michael@0 1722 /* ------------------------------------------------------------------ */
michael@0 1723 U_CAPI decNumber * U_EXPORT2 uprv_decNumberNextPlus(decNumber *res, const decNumber *rhs,
michael@0 1724 decContext *set) {
michael@0 1725 decNumber dtiny; /* constant */
michael@0 1726 decContext workset=*set; /* work */
michael@0 1727 uInt status=0; /* accumulator */
michael@0 1728 #if DECCHECK
michael@0 1729 if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
michael@0 1730 #endif
michael@0 1731
michael@0 1732 /* -Infinity is the special case */
michael@0 1733 if ((rhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) {
michael@0 1734 decSetMaxValue(res, set);
michael@0 1735 res->bits=DECNEG; /* negative */
michael@0 1736 /* there is no status to set */
michael@0 1737 return res;
michael@0 1738 }
michael@0 1739 uprv_decNumberZero(&dtiny); /* start with 0 */
michael@0 1740 dtiny.lsu[0]=1; /* make number that is .. */
michael@0 1741 dtiny.exponent=DEC_MIN_EMIN-1; /* .. smaller than tiniest */
michael@0 1742 workset.round=DEC_ROUND_CEILING;
michael@0 1743 decAddOp(res, rhs, &dtiny, &workset, 0, &status);
michael@0 1744 status&=DEC_Invalid_operation|DEC_sNaN; /* only sNaN Invalid please */
michael@0 1745 if (status!=0) decStatus(res, status, set);
michael@0 1746 return res;
michael@0 1747 } /* decNumberNextPlus */
michael@0 1748
michael@0 1749 /* ------------------------------------------------------------------ */
michael@0 1750 /* decNumberNextToward -- next towards rhs */
michael@0 1751 /* */
michael@0 1752 /* This computes C = A +/- infinitesimal, rounded towards */
michael@0 1753 /* +/-Infinity in the direction of B, as per 754-1985 nextafter */
michael@0 1754 /* modified during revision but dropped from 754-2008. */
michael@0 1755 /* */
michael@0 1756 /* res is C, the result. C may be A or B. */
michael@0 1757 /* lhs is A */
michael@0 1758 /* rhs is B */
michael@0 1759 /* set is the context */
michael@0 1760 /* */
michael@0 1761 /* This is a generalization of 754-1985 NextAfter. */
michael@0 1762 /* ------------------------------------------------------------------ */
michael@0 1763 U_CAPI decNumber * U_EXPORT2 uprv_decNumberNextToward(decNumber *res, const decNumber *lhs,
michael@0 1764 const decNumber *rhs, decContext *set) {
michael@0 1765 decNumber dtiny; /* constant */
michael@0 1766 decContext workset=*set; /* work */
michael@0 1767 Int result; /* .. */
michael@0 1768 uInt status=0; /* accumulator */
michael@0 1769 #if DECCHECK
michael@0 1770 if (decCheckOperands(res, lhs, rhs, set)) return res;
michael@0 1771 #endif
michael@0 1772
michael@0 1773 if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) {
michael@0 1774 decNaNs(res, lhs, rhs, set, &status);
michael@0 1775 }
michael@0 1776 else { /* Is numeric, so no chance of sNaN Invalid, etc. */
michael@0 1777 result=decCompare(lhs, rhs, 0); /* sign matters */
michael@0 1778 if (result==BADINT) status|=DEC_Insufficient_storage; /* rare */
michael@0 1779 else { /* valid compare */
michael@0 1780 if (result==0) uprv_decNumberCopySign(res, lhs, rhs); /* easy */
michael@0 1781 else { /* differ: need NextPlus or NextMinus */
michael@0 1782 uByte sub; /* add or subtract */
michael@0 1783 if (result<0) { /* lhs<rhs, do nextplus */
michael@0 1784 /* -Infinity is the special case */
michael@0 1785 if ((lhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) {
michael@0 1786 decSetMaxValue(res, set);
michael@0 1787 res->bits=DECNEG; /* negative */
michael@0 1788 return res; /* there is no status to set */
michael@0 1789 }
michael@0 1790 workset.round=DEC_ROUND_CEILING;
michael@0 1791 sub=0; /* add, please */
michael@0 1792 } /* plus */
michael@0 1793 else { /* lhs>rhs, do nextminus */
michael@0 1794 /* +Infinity is the special case */
michael@0 1795 if ((lhs->bits&(DECINF|DECNEG))==DECINF) {
michael@0 1796 decSetMaxValue(res, set);
michael@0 1797 return res; /* there is no status to set */
michael@0 1798 }
michael@0 1799 workset.round=DEC_ROUND_FLOOR;
michael@0 1800 sub=DECNEG; /* subtract, please */
michael@0 1801 } /* minus */
michael@0 1802 uprv_decNumberZero(&dtiny); /* start with 0 */
michael@0 1803 dtiny.lsu[0]=1; /* make number that is .. */
michael@0 1804 dtiny.exponent=DEC_MIN_EMIN-1; /* .. smaller than tiniest */
michael@0 1805 decAddOp(res, lhs, &dtiny, &workset, sub, &status); /* + or - */
michael@0 1806 /* turn off exceptions if the result is a normal number */
michael@0 1807 /* (including Nmin), otherwise let all status through */
michael@0 1808 if (uprv_decNumberIsNormal(res, set)) status=0;
michael@0 1809 } /* unequal */
michael@0 1810 } /* compare OK */
michael@0 1811 } /* numeric */
michael@0 1812 if (status!=0) decStatus(res, status, set);
michael@0 1813 return res;
michael@0 1814 } /* decNumberNextToward */
michael@0 1815
michael@0 1816 /* ------------------------------------------------------------------ */
michael@0 1817 /* decNumberOr -- OR two Numbers, digitwise */
michael@0 1818 /* */
michael@0 1819 /* This computes C = A | B */
michael@0 1820 /* */
michael@0 1821 /* res is C, the result. C may be A and/or B (e.g., X=X|X) */
michael@0 1822 /* lhs is A */
michael@0 1823 /* rhs is B */
michael@0 1824 /* set is the context (used for result length and error report) */
michael@0 1825 /* */
michael@0 1826 /* C must have space for set->digits digits. */
michael@0 1827 /* */
michael@0 1828 /* Logical function restrictions apply (see above); a NaN is */
michael@0 1829 /* returned with Invalid_operation if a restriction is violated. */
michael@0 1830 /* ------------------------------------------------------------------ */
michael@0 1831 U_CAPI decNumber * U_EXPORT2 uprv_decNumberOr(decNumber *res, const decNumber *lhs,
michael@0 1832 const decNumber *rhs, decContext *set) {
michael@0 1833 const Unit *ua, *ub; /* -> operands */
michael@0 1834 const Unit *msua, *msub; /* -> operand msus */
michael@0 1835 Unit *uc, *msuc; /* -> result and its msu */
michael@0 1836 Int msudigs; /* digits in res msu */
michael@0 1837 #if DECCHECK
michael@0 1838 if (decCheckOperands(res, lhs, rhs, set)) return res;
michael@0 1839 #endif
michael@0 1840
michael@0 1841 if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
michael@0 1842 || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
michael@0 1843 decStatus(res, DEC_Invalid_operation, set);
michael@0 1844 return res;
michael@0 1845 }
michael@0 1846 /* operands are valid */
michael@0 1847 ua=lhs->lsu; /* bottom-up */
michael@0 1848 ub=rhs->lsu; /* .. */
michael@0 1849 uc=res->lsu; /* .. */
michael@0 1850 msua=ua+D2U(lhs->digits)-1; /* -> msu of lhs */
michael@0 1851 msub=ub+D2U(rhs->digits)-1; /* -> msu of rhs */
michael@0 1852 msuc=uc+D2U(set->digits)-1; /* -> msu of result */
michael@0 1853 msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */
michael@0 1854 for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */
michael@0 1855 Unit a, b; /* extract units */
michael@0 1856 if (ua>msua) a=0;
michael@0 1857 else a=*ua;
michael@0 1858 if (ub>msub) b=0;
michael@0 1859 else b=*ub;
michael@0 1860 *uc=0; /* can now write back */
michael@0 1861 if (a|b) { /* maybe 1 bits to examine */
michael@0 1862 Int i, j;
michael@0 1863 /* This loop could be unrolled and/or use BIN2BCD tables */
michael@0 1864 for (i=0; i<DECDPUN; i++) {
michael@0 1865 if ((a|b)&1) *uc=*uc+(Unit)powers[i]; /* effect OR */
michael@0 1866 j=a%10;
michael@0 1867 a=a/10;
michael@0 1868 j|=b%10;
michael@0 1869 b=b/10;
michael@0 1870 if (j>1) {
michael@0 1871 decStatus(res, DEC_Invalid_operation, set);
michael@0 1872 return res;
michael@0 1873 }
michael@0 1874 if (uc==msuc && i==msudigs-1) break; /* just did final digit */
michael@0 1875 } /* each digit */
michael@0 1876 } /* non-zero */
michael@0 1877 } /* each unit */
michael@0 1878 /* [here uc-1 is the msu of the result] */
michael@0 1879 res->digits=decGetDigits(res->lsu, uc-res->lsu);
michael@0 1880 res->exponent=0; /* integer */
michael@0 1881 res->bits=0; /* sign=0 */
michael@0 1882 return res; /* [no status to set] */
michael@0 1883 } /* decNumberOr */
michael@0 1884
michael@0 1885 /* ------------------------------------------------------------------ */
michael@0 1886 /* decNumberPlus -- prefix plus operator */
michael@0 1887 /* */
michael@0 1888 /* This computes C = 0 + A */
michael@0 1889 /* */
michael@0 1890 /* res is C, the result. C may be A */
michael@0 1891 /* rhs is A */
michael@0 1892 /* set is the context */
michael@0 1893 /* */
michael@0 1894 /* See also decNumberCopy for a quiet bitwise version of this. */
michael@0 1895 /* C must have space for set->digits digits. */
michael@0 1896 /* ------------------------------------------------------------------ */
michael@0 1897 /* This simply uses AddOp; Add will take fast path after preparing A. */
michael@0 1898 /* Performance is a concern here, as this routine is often used to */
michael@0 1899 /* check operands and apply rounding and overflow/underflow testing. */
michael@0 1900 /* ------------------------------------------------------------------ */
michael@0 1901 U_CAPI decNumber * U_EXPORT2 uprv_decNumberPlus(decNumber *res, const decNumber *rhs,
michael@0 1902 decContext *set) {
michael@0 1903 decNumber dzero;
michael@0 1904 uInt status=0; /* accumulator */
michael@0 1905 #if DECCHECK
michael@0 1906 if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
michael@0 1907 #endif
michael@0 1908
michael@0 1909 uprv_decNumberZero(&dzero); /* make 0 */
michael@0 1910 dzero.exponent=rhs->exponent; /* [no coefficient expansion] */
michael@0 1911 decAddOp(res, &dzero, rhs, set, 0, &status);
michael@0 1912 if (status!=0) decStatus(res, status, set);
michael@0 1913 #if DECCHECK
michael@0 1914 decCheckInexact(res, set);
michael@0 1915 #endif
michael@0 1916 return res;
michael@0 1917 } /* decNumberPlus */
michael@0 1918
michael@0 1919 /* ------------------------------------------------------------------ */
michael@0 1920 /* decNumberMultiply -- multiply two Numbers */
michael@0 1921 /* */
michael@0 1922 /* This computes C = A x B */
michael@0 1923 /* */
michael@0 1924 /* res is C, the result. C may be A and/or B (e.g., X=X+X) */
michael@0 1925 /* lhs is A */
michael@0 1926 /* rhs is B */
michael@0 1927 /* set is the context */
michael@0 1928 /* */
michael@0 1929 /* C must have space for set->digits digits. */
michael@0 1930 /* ------------------------------------------------------------------ */
michael@0 1931 U_CAPI decNumber * U_EXPORT2 uprv_decNumberMultiply(decNumber *res, const decNumber *lhs,
michael@0 1932 const decNumber *rhs, decContext *set) {
michael@0 1933 uInt status=0; /* accumulator */
michael@0 1934 decMultiplyOp(res, lhs, rhs, set, &status);
michael@0 1935 if (status!=0) decStatus(res, status, set);
michael@0 1936 #if DECCHECK
michael@0 1937 decCheckInexact(res, set);
michael@0 1938 #endif
michael@0 1939 return res;
michael@0 1940 } /* decNumberMultiply */
michael@0 1941
michael@0 1942 /* ------------------------------------------------------------------ */
michael@0 1943 /* decNumberPower -- raise a number to a power */
michael@0 1944 /* */
michael@0 1945 /* This computes C = A ** B */
michael@0 1946 /* */
michael@0 1947 /* res is C, the result. C may be A and/or B (e.g., X=X**X) */
michael@0 1948 /* lhs is A */
michael@0 1949 /* rhs is B */
michael@0 1950 /* set is the context */
michael@0 1951 /* */
michael@0 1952 /* C must have space for set->digits digits. */
michael@0 1953 /* */
michael@0 1954 /* Mathematical function restrictions apply (see above); a NaN is */
michael@0 1955 /* returned with Invalid_operation if a restriction is violated. */
michael@0 1956 /* */
michael@0 1957 /* However, if 1999999997<=B<=999999999 and B is an integer then the */
michael@0 1958 /* restrictions on A and the context are relaxed to the usual bounds, */
michael@0 1959 /* for compatibility with the earlier (integer power only) version */
michael@0 1960 /* of this function. */
michael@0 1961 /* */
michael@0 1962 /* When B is an integer, the result may be exact, even if rounded. */
michael@0 1963 /* */
michael@0 1964 /* The final result is rounded according to the context; it will */
michael@0 1965 /* almost always be correctly rounded, but may be up to 1 ulp in */
michael@0 1966 /* error in rare cases. */
michael@0 1967 /* ------------------------------------------------------------------ */
michael@0 1968 U_CAPI decNumber * U_EXPORT2 uprv_decNumberPower(decNumber *res, const decNumber *lhs,
michael@0 1969 const decNumber *rhs, decContext *set) {
michael@0 1970 #if DECSUBSET
michael@0 1971 decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */
michael@0 1972 decNumber *allocrhs=NULL; /* .., rhs */
michael@0 1973 #endif
michael@0 1974 decNumber *allocdac=NULL; /* -> allocated acc buffer, iff used */
michael@0 1975 decNumber *allocinv=NULL; /* -> allocated 1/x buffer, iff used */
michael@0 1976 Int reqdigits=set->digits; /* requested DIGITS */
michael@0 1977 Int n; /* rhs in binary */
michael@0 1978 Flag rhsint=0; /* 1 if rhs is an integer */
michael@0 1979 Flag useint=0; /* 1 if can use integer calculation */
michael@0 1980 Flag isoddint=0; /* 1 if rhs is an integer and odd */
michael@0 1981 Int i; /* work */
michael@0 1982 #if DECSUBSET
michael@0 1983 Int dropped; /* .. */
michael@0 1984 #endif
michael@0 1985 uInt needbytes; /* buffer size needed */
michael@0 1986 Flag seenbit; /* seen a bit while powering */
michael@0 1987 Int residue=0; /* rounding residue */
michael@0 1988 uInt status=0; /* accumulators */
michael@0 1989 uByte bits=0; /* result sign if errors */
michael@0 1990 decContext aset; /* working context */
michael@0 1991 decNumber dnOne; /* work value 1... */
michael@0 1992 /* local accumulator buffer [a decNumber, with digits+elength+1 digits] */
michael@0 1993 decNumber dacbuff[D2N(DECBUFFER+9)];
michael@0 1994 decNumber *dac=dacbuff; /* -> result accumulator */
michael@0 1995 /* same again for possible 1/lhs calculation */
michael@0 1996 decNumber invbuff[D2N(DECBUFFER+9)];
michael@0 1997
michael@0 1998 #if DECCHECK
michael@0 1999 if (decCheckOperands(res, lhs, rhs, set)) return res;
michael@0 2000 #endif
michael@0 2001
michael@0 2002 do { /* protect allocated storage */
michael@0 2003 #if DECSUBSET
michael@0 2004 if (!set->extended) { /* reduce operands and set status, as needed */
michael@0 2005 if (lhs->digits>reqdigits) {
michael@0 2006 alloclhs=decRoundOperand(lhs, set, &status);
michael@0 2007 if (alloclhs==NULL) break;
michael@0 2008 lhs=alloclhs;
michael@0 2009 }
michael@0 2010 if (rhs->digits>reqdigits) {
michael@0 2011 allocrhs=decRoundOperand(rhs, set, &status);
michael@0 2012 if (allocrhs==NULL) break;
michael@0 2013 rhs=allocrhs;
michael@0 2014 }
michael@0 2015 }
michael@0 2016 #endif
michael@0 2017 /* [following code does not require input rounding] */
michael@0 2018
michael@0 2019 /* handle NaNs and rhs Infinity (lhs infinity is harder) */
michael@0 2020 if (SPECIALARGS) {
michael@0 2021 if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { /* NaNs */
michael@0 2022 decNaNs(res, lhs, rhs, set, &status);
michael@0 2023 break;}
michael@0 2024 if (decNumberIsInfinite(rhs)) { /* rhs Infinity */
michael@0 2025 Flag rhsneg=rhs->bits&DECNEG; /* save rhs sign */
michael@0 2026 if (decNumberIsNegative(lhs) /* lhs<0 */
michael@0 2027 && !decNumberIsZero(lhs)) /* .. */
michael@0 2028 status|=DEC_Invalid_operation;
michael@0 2029 else { /* lhs >=0 */
michael@0 2030 uprv_decNumberZero(&dnOne); /* set up 1 */
michael@0 2031 dnOne.lsu[0]=1;
michael@0 2032 uprv_decNumberCompare(dac, lhs, &dnOne, set); /* lhs ? 1 */
michael@0 2033 uprv_decNumberZero(res); /* prepare for 0/1/Infinity */
michael@0 2034 if (decNumberIsNegative(dac)) { /* lhs<1 */
michael@0 2035 if (rhsneg) res->bits|=DECINF; /* +Infinity [else is +0] */
michael@0 2036 }
michael@0 2037 else if (dac->lsu[0]==0) { /* lhs=1 */
michael@0 2038 /* 1**Infinity is inexact, so return fully-padded 1.0000 */
michael@0 2039 Int shift=set->digits-1;
michael@0 2040 *res->lsu=1; /* was 0, make int 1 */
michael@0 2041 res->digits=decShiftToMost(res->lsu, 1, shift);
michael@0 2042 res->exponent=-shift; /* make 1.0000... */
michael@0 2043 status|=DEC_Inexact|DEC_Rounded; /* deemed inexact */
michael@0 2044 }
michael@0 2045 else { /* lhs>1 */
michael@0 2046 if (!rhsneg) res->bits|=DECINF; /* +Infinity [else is +0] */
michael@0 2047 }
michael@0 2048 } /* lhs>=0 */
michael@0 2049 break;}
michael@0 2050 /* [lhs infinity drops through] */
michael@0 2051 } /* specials */
michael@0 2052
michael@0 2053 /* Original rhs may be an integer that fits and is in range */
michael@0 2054 n=decGetInt(rhs);
michael@0 2055 if (n!=BADINT) { /* it is an integer */
michael@0 2056 rhsint=1; /* record the fact for 1**n */
michael@0 2057 isoddint=(Flag)n&1; /* [works even if big] */
michael@0 2058 if (n!=BIGEVEN && n!=BIGODD) /* can use integer path? */
michael@0 2059 useint=1; /* looks good */
michael@0 2060 }
michael@0 2061
michael@0 2062 if (decNumberIsNegative(lhs) /* -x .. */
michael@0 2063 && isoddint) bits=DECNEG; /* .. to an odd power */
michael@0 2064
michael@0 2065 /* handle LHS infinity */
michael@0 2066 if (decNumberIsInfinite(lhs)) { /* [NaNs already handled] */
michael@0 2067 uByte rbits=rhs->bits; /* save */
michael@0 2068 uprv_decNumberZero(res); /* prepare */
michael@0 2069 if (n==0) *res->lsu=1; /* [-]Inf**0 => 1 */
michael@0 2070 else {
michael@0 2071 /* -Inf**nonint -> error */
michael@0 2072 if (!rhsint && decNumberIsNegative(lhs)) {
michael@0 2073 status|=DEC_Invalid_operation; /* -Inf**nonint is error */
michael@0 2074 break;}
michael@0 2075 if (!(rbits & DECNEG)) bits|=DECINF; /* was not a **-n */
michael@0 2076 /* [otherwise will be 0 or -0] */
michael@0 2077 res->bits=bits;
michael@0 2078 }
michael@0 2079 break;}
michael@0 2080
michael@0 2081 /* similarly handle LHS zero */
michael@0 2082 if (decNumberIsZero(lhs)) {
michael@0 2083 if (n==0) { /* 0**0 => Error */
michael@0 2084 #if DECSUBSET
michael@0 2085 if (!set->extended) { /* [unless subset] */
michael@0 2086 uprv_decNumberZero(res);
michael@0 2087 *res->lsu=1; /* return 1 */
michael@0 2088 break;}
michael@0 2089 #endif
michael@0 2090 status|=DEC_Invalid_operation;
michael@0 2091 }
michael@0 2092 else { /* 0**x */
michael@0 2093 uByte rbits=rhs->bits; /* save */
michael@0 2094 if (rbits & DECNEG) { /* was a 0**(-n) */
michael@0 2095 #if DECSUBSET
michael@0 2096 if (!set->extended) { /* [bad if subset] */
michael@0 2097 status|=DEC_Invalid_operation;
michael@0 2098 break;}
michael@0 2099 #endif
michael@0 2100 bits|=DECINF;
michael@0 2101 }
michael@0 2102 uprv_decNumberZero(res); /* prepare */
michael@0 2103 /* [otherwise will be 0 or -0] */
michael@0 2104 res->bits=bits;
michael@0 2105 }
michael@0 2106 break;}
michael@0 2107
michael@0 2108 /* here both lhs and rhs are finite; rhs==0 is handled in the */
michael@0 2109 /* integer path. Next handle the non-integer cases */
michael@0 2110 if (!useint) { /* non-integral rhs */
michael@0 2111 /* any -ve lhs is bad, as is either operand or context out of */
michael@0 2112 /* bounds */
michael@0 2113 if (decNumberIsNegative(lhs)) {
michael@0 2114 status|=DEC_Invalid_operation;
michael@0 2115 break;}
michael@0 2116 if (decCheckMath(lhs, set, &status)
michael@0 2117 || decCheckMath(rhs, set, &status)) break; /* variable status */
michael@0 2118
michael@0 2119 uprv_decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */
michael@0 2120 aset.emax=DEC_MAX_MATH; /* usual bounds */
michael@0 2121 aset.emin=-DEC_MAX_MATH; /* .. */
michael@0 2122 aset.clamp=0; /* and no concrete format */
michael@0 2123
michael@0 2124 /* calculate the result using exp(ln(lhs)*rhs), which can */
michael@0 2125 /* all be done into the accumulator, dac. The precision needed */
michael@0 2126 /* is enough to contain the full information in the lhs (which */
michael@0 2127 /* is the total digits, including exponent), or the requested */
michael@0 2128 /* precision, if larger, + 4; 6 is used for the exponent */
michael@0 2129 /* maximum length, and this is also used when it is shorter */
michael@0 2130 /* than the requested digits as it greatly reduces the >0.5 ulp */
michael@0 2131 /* cases at little cost (because Ln doubles digits each */
michael@0 2132 /* iteration so a few extra digits rarely causes an extra */
michael@0 2133 /* iteration) */
michael@0 2134 aset.digits=MAXI(lhs->digits, set->digits)+6+4;
michael@0 2135 } /* non-integer rhs */
michael@0 2136
michael@0 2137 else { /* rhs is in-range integer */
michael@0 2138 if (n==0) { /* x**0 = 1 */
michael@0 2139 /* (0**0 was handled above) */
michael@0 2140 uprv_decNumberZero(res); /* result=1 */
michael@0 2141 *res->lsu=1; /* .. */
michael@0 2142 break;}
michael@0 2143 /* rhs is a non-zero integer */
michael@0 2144 if (n<0) n=-n; /* use abs(n) */
michael@0 2145
michael@0 2146 aset=*set; /* clone the context */
michael@0 2147 aset.round=DEC_ROUND_HALF_EVEN; /* internally use balanced */
michael@0 2148 /* calculate the working DIGITS */
michael@0 2149 aset.digits=reqdigits+(rhs->digits+rhs->exponent)+2;
michael@0 2150 #if DECSUBSET
michael@0 2151 if (!set->extended) aset.digits--; /* use classic precision */
michael@0 2152 #endif
michael@0 2153 /* it's an error if this is more than can be handled */
michael@0 2154 if (aset.digits>DECNUMMAXP) {status|=DEC_Invalid_operation; break;}
michael@0 2155 } /* integer path */
michael@0 2156
michael@0 2157 /* aset.digits is the count of digits for the accumulator needed */
michael@0 2158 /* if accumulator is too long for local storage, then allocate */
michael@0 2159 needbytes=sizeof(decNumber)+(D2U(aset.digits)-1)*sizeof(Unit);
michael@0 2160 /* [needbytes also used below if 1/lhs needed] */
michael@0 2161 if (needbytes>sizeof(dacbuff)) {
michael@0 2162 allocdac=(decNumber *)malloc(needbytes);
michael@0 2163 if (allocdac==NULL) { /* hopeless -- abandon */
michael@0 2164 status|=DEC_Insufficient_storage;
michael@0 2165 break;}
michael@0 2166 dac=allocdac; /* use the allocated space */
michael@0 2167 }
michael@0 2168 /* here, aset is set up and accumulator is ready for use */
michael@0 2169
michael@0 2170 if (!useint) { /* non-integral rhs */
michael@0 2171 /* x ** y; special-case x=1 here as it will otherwise always */
michael@0 2172 /* reduce to integer 1; decLnOp has a fastpath which detects */
michael@0 2173 /* the case of x=1 */
michael@0 2174 decLnOp(dac, lhs, &aset, &status); /* dac=ln(lhs) */
michael@0 2175 /* [no error possible, as lhs 0 already handled] */
michael@0 2176 if (ISZERO(dac)) { /* x==1, 1.0, etc. */
michael@0 2177 /* need to return fully-padded 1.0000 etc., but rhsint->1 */
michael@0 2178 *dac->lsu=1; /* was 0, make int 1 */
michael@0 2179 if (!rhsint) { /* add padding */
michael@0 2180 Int shift=set->digits-1;
michael@0 2181 dac->digits=decShiftToMost(dac->lsu, 1, shift);
michael@0 2182 dac->exponent=-shift; /* make 1.0000... */
michael@0 2183 status|=DEC_Inexact|DEC_Rounded; /* deemed inexact */
michael@0 2184 }
michael@0 2185 }
michael@0 2186 else {
michael@0 2187 decMultiplyOp(dac, dac, rhs, &aset, &status); /* dac=dac*rhs */
michael@0 2188 decExpOp(dac, dac, &aset, &status); /* dac=exp(dac) */
michael@0 2189 }
michael@0 2190 /* and drop through for final rounding */
michael@0 2191 } /* non-integer rhs */
michael@0 2192
michael@0 2193 else { /* carry on with integer */
michael@0 2194 uprv_decNumberZero(dac); /* acc=1 */
michael@0 2195 *dac->lsu=1; /* .. */
michael@0 2196
michael@0 2197 /* if a negative power the constant 1 is needed, and if not subset */
michael@0 2198 /* invert the lhs now rather than inverting the result later */
michael@0 2199 if (decNumberIsNegative(rhs)) { /* was a **-n [hence digits>0] */
michael@0 2200 decNumber *inv=invbuff; /* asssume use fixed buffer */
michael@0 2201 uprv_decNumberCopy(&dnOne, dac); /* dnOne=1; [needed now or later] */
michael@0 2202 #if DECSUBSET
michael@0 2203 if (set->extended) { /* need to calculate 1/lhs */
michael@0 2204 #endif
michael@0 2205 /* divide lhs into 1, putting result in dac [dac=1/dac] */
michael@0 2206 decDivideOp(dac, &dnOne, lhs, &aset, DIVIDE, &status);
michael@0 2207 /* now locate or allocate space for the inverted lhs */
michael@0 2208 if (needbytes>sizeof(invbuff)) {
michael@0 2209 allocinv=(decNumber *)malloc(needbytes);
michael@0 2210 if (allocinv==NULL) { /* hopeless -- abandon */
michael@0 2211 status|=DEC_Insufficient_storage;
michael@0 2212 break;}
michael@0 2213 inv=allocinv; /* use the allocated space */
michael@0 2214 }
michael@0 2215 /* [inv now points to big-enough buffer or allocated storage] */
michael@0 2216 uprv_decNumberCopy(inv, dac); /* copy the 1/lhs */
michael@0 2217 uprv_decNumberCopy(dac, &dnOne); /* restore acc=1 */
michael@0 2218 lhs=inv; /* .. and go forward with new lhs */
michael@0 2219 #if DECSUBSET
michael@0 2220 }
michael@0 2221 #endif
michael@0 2222 }
michael@0 2223
michael@0 2224 /* Raise-to-the-power loop... */
michael@0 2225 seenbit=0; /* set once a 1-bit is encountered */
michael@0 2226 for (i=1;;i++){ /* for each bit [top bit ignored] */
michael@0 2227 /* abandon if had overflow or terminal underflow */
michael@0 2228 if (status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */
michael@0 2229 if (status&DEC_Overflow || ISZERO(dac)) break;
michael@0 2230 }
michael@0 2231 /* [the following two lines revealed an optimizer bug in a C++ */
michael@0 2232 /* compiler, with symptom: 5**3 -> 25, when n=n+n was used] */
michael@0 2233 n=n<<1; /* move next bit to testable position */
michael@0 2234 if (n<0) { /* top bit is set */
michael@0 2235 seenbit=1; /* OK, significant bit seen */
michael@0 2236 decMultiplyOp(dac, dac, lhs, &aset, &status); /* dac=dac*x */
michael@0 2237 }
michael@0 2238 if (i==31) break; /* that was the last bit */
michael@0 2239 if (!seenbit) continue; /* no need to square 1 */
michael@0 2240 decMultiplyOp(dac, dac, dac, &aset, &status); /* dac=dac*dac [square] */
michael@0 2241 } /*i*/ /* 32 bits */
michael@0 2242
michael@0 2243 /* complete internal overflow or underflow processing */
michael@0 2244 if (status & (DEC_Overflow|DEC_Underflow)) {
michael@0 2245 #if DECSUBSET
michael@0 2246 /* If subset, and power was negative, reverse the kind of -erflow */
michael@0 2247 /* [1/x not yet done] */
michael@0 2248 if (!set->extended && decNumberIsNegative(rhs)) {
michael@0 2249 if (status & DEC_Overflow)
michael@0 2250 status^=DEC_Overflow | DEC_Underflow | DEC_Subnormal;
michael@0 2251 else { /* trickier -- Underflow may or may not be set */
michael@0 2252 status&=~(DEC_Underflow | DEC_Subnormal); /* [one or both] */
michael@0 2253 status|=DEC_Overflow;
michael@0 2254 }
michael@0 2255 }
michael@0 2256 #endif
michael@0 2257 dac->bits=(dac->bits & ~DECNEG) | bits; /* force correct sign */
michael@0 2258 /* round subnormals [to set.digits rather than aset.digits] */
michael@0 2259 /* or set overflow result similarly as required */
michael@0 2260 decFinalize(dac, set, &residue, &status);
michael@0 2261 uprv_decNumberCopy(res, dac); /* copy to result (is now OK length) */
michael@0 2262 break;
michael@0 2263 }
michael@0 2264
michael@0 2265 #if DECSUBSET
michael@0 2266 if (!set->extended && /* subset math */
michael@0 2267 decNumberIsNegative(rhs)) { /* was a **-n [hence digits>0] */
michael@0 2268 /* so divide result into 1 [dac=1/dac] */
michael@0 2269 decDivideOp(dac, &dnOne, dac, &aset, DIVIDE, &status);
michael@0 2270 }
michael@0 2271 #endif
michael@0 2272 } /* rhs integer path */
michael@0 2273
michael@0 2274 /* reduce result to the requested length and copy to result */
michael@0 2275 decCopyFit(res, dac, set, &residue, &status);
michael@0 2276 decFinish(res, set, &residue, &status); /* final cleanup */
michael@0 2277 #if DECSUBSET
michael@0 2278 if (!set->extended) decTrim(res, set, 0, 1, &dropped); /* trailing zeros */
michael@0 2279 #endif
michael@0 2280 } while(0); /* end protected */
michael@0 2281
michael@0 2282 if (allocdac!=NULL) free(allocdac); /* drop any storage used */
michael@0 2283 if (allocinv!=NULL) free(allocinv); /* .. */
michael@0 2284 #if DECSUBSET
michael@0 2285 if (alloclhs!=NULL) free(alloclhs); /* .. */
michael@0 2286 if (allocrhs!=NULL) free(allocrhs); /* .. */
michael@0 2287 #endif
michael@0 2288 if (status!=0) decStatus(res, status, set);
michael@0 2289 #if DECCHECK
michael@0 2290 decCheckInexact(res, set);
michael@0 2291 #endif
michael@0 2292 return res;
michael@0 2293 } /* decNumberPower */
michael@0 2294
michael@0 2295 /* ------------------------------------------------------------------ */
michael@0 2296 /* decNumberQuantize -- force exponent to requested value */
michael@0 2297 /* */
michael@0 2298 /* This computes C = op(A, B), where op adjusts the coefficient */
michael@0 2299 /* of C (by rounding or shifting) such that the exponent (-scale) */
michael@0 2300 /* of C has exponent of B. The numerical value of C will equal A, */
michael@0 2301 /* except for the effects of any rounding that occurred. */
michael@0 2302 /* */
michael@0 2303 /* res is C, the result. C may be A or B */
michael@0 2304 /* lhs is A, the number to adjust */
michael@0 2305 /* rhs is B, the number with exponent to match */
michael@0 2306 /* set is the context */
michael@0 2307 /* */
michael@0 2308 /* C must have space for set->digits digits. */
michael@0 2309 /* */
michael@0 2310 /* Unless there is an error or the result is infinite, the exponent */
michael@0 2311 /* after the operation is guaranteed to be equal to that of B. */
michael@0 2312 /* ------------------------------------------------------------------ */
michael@0 2313 U_CAPI decNumber * U_EXPORT2 uprv_decNumberQuantize(decNumber *res, const decNumber *lhs,
michael@0 2314 const decNumber *rhs, decContext *set) {
michael@0 2315 uInt status=0; /* accumulator */
michael@0 2316 decQuantizeOp(res, lhs, rhs, set, 1, &status);
michael@0 2317 if (status!=0) decStatus(res, status, set);
michael@0 2318 return res;
michael@0 2319 } /* decNumberQuantize */
michael@0 2320
michael@0 2321 /* ------------------------------------------------------------------ */
michael@0 2322 /* decNumberReduce -- remove trailing zeros */
michael@0 2323 /* */
michael@0 2324 /* This computes C = 0 + A, and normalizes the result */
michael@0 2325 /* */
michael@0 2326 /* res is C, the result. C may be A */
michael@0 2327 /* rhs is A */
michael@0 2328 /* set is the context */
michael@0 2329 /* */
michael@0 2330 /* C must have space for set->digits digits. */
michael@0 2331 /* ------------------------------------------------------------------ */
michael@0 2332 /* Previously known as Normalize */
michael@0 2333 U_CAPI decNumber * U_EXPORT2 uprv_decNumberNormalize(decNumber *res, const decNumber *rhs,
michael@0 2334 decContext *set) {
michael@0 2335 return uprv_decNumberReduce(res, rhs, set);
michael@0 2336 } /* decNumberNormalize */
michael@0 2337
michael@0 2338 U_CAPI decNumber * U_EXPORT2 uprv_decNumberReduce(decNumber *res, const decNumber *rhs,
michael@0 2339 decContext *set) {
michael@0 2340 #if DECSUBSET
michael@0 2341 decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */
michael@0 2342 #endif
michael@0 2343 uInt status=0; /* as usual */
michael@0 2344 Int residue=0; /* as usual */
michael@0 2345 Int dropped; /* work */
michael@0 2346
michael@0 2347 #if DECCHECK
michael@0 2348 if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
michael@0 2349 #endif
michael@0 2350
michael@0 2351 do { /* protect allocated storage */
michael@0 2352 #if DECSUBSET
michael@0 2353 if (!set->extended) {
michael@0 2354 /* reduce operand and set lostDigits status, as needed */
michael@0 2355 if (rhs->digits>set->digits) {
michael@0 2356 allocrhs=decRoundOperand(rhs, set, &status);
michael@0 2357 if (allocrhs==NULL) break;
michael@0 2358 rhs=allocrhs;
michael@0 2359 }
michael@0 2360 }
michael@0 2361 #endif
michael@0 2362 /* [following code does not require input rounding] */
michael@0 2363
michael@0 2364 /* Infinities copy through; NaNs need usual treatment */
michael@0 2365 if (decNumberIsNaN(rhs)) {
michael@0 2366 decNaNs(res, rhs, NULL, set, &status);
michael@0 2367 break;
michael@0 2368 }
michael@0 2369
michael@0 2370 /* reduce result to the requested length and copy to result */
michael@0 2371 decCopyFit(res, rhs, set, &residue, &status); /* copy & round */
michael@0 2372 decFinish(res, set, &residue, &status); /* cleanup/set flags */
michael@0 2373 decTrim(res, set, 1, 0, &dropped); /* normalize in place */
michael@0 2374 /* [may clamp] */
michael@0 2375 } while(0); /* end protected */
michael@0 2376
michael@0 2377 #if DECSUBSET
michael@0 2378 if (allocrhs !=NULL) free(allocrhs); /* .. */
michael@0 2379 #endif
michael@0 2380 if (status!=0) decStatus(res, status, set);/* then report status */
michael@0 2381 return res;
michael@0 2382 } /* decNumberReduce */
michael@0 2383
michael@0 2384 /* ------------------------------------------------------------------ */
michael@0 2385 /* decNumberRescale -- force exponent to requested value */
michael@0 2386 /* */
michael@0 2387 /* This computes C = op(A, B), where op adjusts the coefficient */
michael@0 2388 /* of C (by rounding or shifting) such that the exponent (-scale) */
michael@0 2389 /* of C has the value B. The numerical value of C will equal A, */
michael@0 2390 /* except for the effects of any rounding that occurred. */
michael@0 2391 /* */
michael@0 2392 /* res is C, the result. C may be A or B */
michael@0 2393 /* lhs is A, the number to adjust */
michael@0 2394 /* rhs is B, the requested exponent */
michael@0 2395 /* set is the context */
michael@0 2396 /* */
michael@0 2397 /* C must have space for set->digits digits. */
michael@0 2398 /* */
michael@0 2399 /* Unless there is an error or the result is infinite, the exponent */
michael@0 2400 /* after the operation is guaranteed to be equal to B. */
michael@0 2401 /* ------------------------------------------------------------------ */
michael@0 2402 U_CAPI decNumber * U_EXPORT2 uprv_decNumberRescale(decNumber *res, const decNumber *lhs,
michael@0 2403 const decNumber *rhs, decContext *set) {
michael@0 2404 uInt status=0; /* accumulator */
michael@0 2405 decQuantizeOp(res, lhs, rhs, set, 0, &status);
michael@0 2406 if (status!=0) decStatus(res, status, set);
michael@0 2407 return res;
michael@0 2408 } /* decNumberRescale */
michael@0 2409
michael@0 2410 /* ------------------------------------------------------------------ */
michael@0 2411 /* decNumberRemainder -- divide and return remainder */
michael@0 2412 /* */
michael@0 2413 /* This computes C = A % B */
michael@0 2414 /* */
michael@0 2415 /* res is C, the result. C may be A and/or B (e.g., X=X%X) */
michael@0 2416 /* lhs is A */
michael@0 2417 /* rhs is B */
michael@0 2418 /* set is the context */
michael@0 2419 /* */
michael@0 2420 /* C must have space for set->digits digits. */
michael@0 2421 /* ------------------------------------------------------------------ */
michael@0 2422 U_CAPI decNumber * U_EXPORT2 uprv_decNumberRemainder(decNumber *res, const decNumber *lhs,
michael@0 2423 const decNumber *rhs, decContext *set) {
michael@0 2424 uInt status=0; /* accumulator */
michael@0 2425 decDivideOp(res, lhs, rhs, set, REMAINDER, &status);
michael@0 2426 if (status!=0) decStatus(res, status, set);
michael@0 2427 #if DECCHECK
michael@0 2428 decCheckInexact(res, set);
michael@0 2429 #endif
michael@0 2430 return res;
michael@0 2431 } /* decNumberRemainder */
michael@0 2432
michael@0 2433 /* ------------------------------------------------------------------ */
michael@0 2434 /* decNumberRemainderNear -- divide and return remainder from nearest */
michael@0 2435 /* */
michael@0 2436 /* This computes C = A % B, where % is the IEEE remainder operator */
michael@0 2437 /* */
michael@0 2438 /* res is C, the result. C may be A and/or B (e.g., X=X%X) */
michael@0 2439 /* lhs is A */
michael@0 2440 /* rhs is B */
michael@0 2441 /* set is the context */
michael@0 2442 /* */
michael@0 2443 /* C must have space for set->digits digits. */
michael@0 2444 /* ------------------------------------------------------------------ */
michael@0 2445 U_CAPI decNumber * U_EXPORT2 uprv_decNumberRemainderNear(decNumber *res, const decNumber *lhs,
michael@0 2446 const decNumber *rhs, decContext *set) {
michael@0 2447 uInt status=0; /* accumulator */
michael@0 2448 decDivideOp(res, lhs, rhs, set, REMNEAR, &status);
michael@0 2449 if (status!=0) decStatus(res, status, set);
michael@0 2450 #if DECCHECK
michael@0 2451 decCheckInexact(res, set);
michael@0 2452 #endif
michael@0 2453 return res;
michael@0 2454 } /* decNumberRemainderNear */
michael@0 2455
michael@0 2456 /* ------------------------------------------------------------------ */
michael@0 2457 /* decNumberRotate -- rotate the coefficient of a Number left/right */
michael@0 2458 /* */
michael@0 2459 /* This computes C = A rot B (in base ten and rotating set->digits */
michael@0 2460 /* digits). */
michael@0 2461 /* */
michael@0 2462 /* res is C, the result. C may be A and/or B (e.g., X=XrotX) */
michael@0 2463 /* lhs is A */
michael@0 2464 /* rhs is B, the number of digits to rotate (-ve to right) */
michael@0 2465 /* set is the context */
michael@0 2466 /* */
michael@0 2467 /* The digits of the coefficient of A are rotated to the left (if B */
michael@0 2468 /* is positive) or to the right (if B is negative) without adjusting */
michael@0 2469 /* the exponent or the sign of A. If lhs->digits is less than */
michael@0 2470 /* set->digits the coefficient is padded with zeros on the left */
michael@0 2471 /* before the rotate. Any leading zeros in the result are removed */
michael@0 2472 /* as usual. */
michael@0 2473 /* */
michael@0 2474 /* B must be an integer (q=0) and in the range -set->digits through */
michael@0 2475 /* +set->digits. */
michael@0 2476 /* C must have space for set->digits digits. */
michael@0 2477 /* NaNs are propagated as usual. Infinities are unaffected (but */
michael@0 2478 /* B must be valid). No status is set unless B is invalid or an */
michael@0 2479 /* operand is an sNaN. */
michael@0 2480 /* ------------------------------------------------------------------ */
michael@0 2481 U_CAPI decNumber * U_EXPORT2 uprv_decNumberRotate(decNumber *res, const decNumber *lhs,
michael@0 2482 const decNumber *rhs, decContext *set) {
michael@0 2483 uInt status=0; /* accumulator */
michael@0 2484 Int rotate; /* rhs as an Int */
michael@0 2485
michael@0 2486 #if DECCHECK
michael@0 2487 if (decCheckOperands(res, lhs, rhs, set)) return res;
michael@0 2488 #endif
michael@0 2489
michael@0 2490 /* NaNs propagate as normal */
michael@0 2491 if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
michael@0 2492 decNaNs(res, lhs, rhs, set, &status);
michael@0 2493 /* rhs must be an integer */
michael@0 2494 else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
michael@0 2495 status=DEC_Invalid_operation;
michael@0 2496 else { /* both numeric, rhs is an integer */
michael@0 2497 rotate=decGetInt(rhs); /* [cannot fail] */
michael@0 2498 if (rotate==BADINT /* something bad .. */
michael@0 2499 || rotate==BIGODD || rotate==BIGEVEN /* .. very big .. */
michael@0 2500 || abs(rotate)>set->digits) /* .. or out of range */
michael@0 2501 status=DEC_Invalid_operation;
michael@0 2502 else { /* rhs is OK */
michael@0 2503 uprv_decNumberCopy(res, lhs);
michael@0 2504 /* convert -ve rotate to equivalent positive rotation */
michael@0 2505 if (rotate<0) rotate=set->digits+rotate;
michael@0 2506 if (rotate!=0 && rotate!=set->digits /* zero or full rotation */
michael@0 2507 && !decNumberIsInfinite(res)) { /* lhs was infinite */
michael@0 2508 /* left-rotate to do; 0 < rotate < set->digits */
michael@0 2509 uInt units, shift; /* work */
michael@0 2510 uInt msudigits; /* digits in result msu */
michael@0 2511 Unit *msu=res->lsu+D2U(res->digits)-1; /* current msu */
michael@0 2512 Unit *msumax=res->lsu+D2U(set->digits)-1; /* rotation msu */
michael@0 2513 for (msu++; msu<=msumax; msu++) *msu=0; /* ensure high units=0 */
michael@0 2514 res->digits=set->digits; /* now full-length */
michael@0 2515 msudigits=MSUDIGITS(res->digits); /* actual digits in msu */
michael@0 2516
michael@0 2517 /* rotation here is done in-place, in three steps */
michael@0 2518 /* 1. shift all to least up to one unit to unit-align final */
michael@0 2519 /* lsd [any digits shifted out are rotated to the left, */
michael@0 2520 /* abutted to the original msd (which may require split)] */
michael@0 2521 /* */
michael@0 2522 /* [if there are no whole units left to rotate, the */
michael@0 2523 /* rotation is now complete] */
michael@0 2524 /* */
michael@0 2525 /* 2. shift to least, from below the split point only, so that */
michael@0 2526 /* the final msd is in the right place in its Unit [any */
michael@0 2527 /* digits shifted out will fit exactly in the current msu, */
michael@0 2528 /* left aligned, no split required] */
michael@0 2529 /* */
michael@0 2530 /* 3. rotate all the units by reversing left part, right */
michael@0 2531 /* part, and then whole */
michael@0 2532 /* */
michael@0 2533 /* example: rotate right 8 digits (2 units + 2), DECDPUN=3. */
michael@0 2534 /* */
michael@0 2535 /* start: 00a bcd efg hij klm npq */
michael@0 2536 /* */
michael@0 2537 /* 1a 000 0ab cde fgh|ijk lmn [pq saved] */
michael@0 2538 /* 1b 00p qab cde fgh|ijk lmn */
michael@0 2539 /* */
michael@0 2540 /* 2a 00p qab cde fgh|00i jkl [mn saved] */
michael@0 2541 /* 2b mnp qab cde fgh|00i jkl */
michael@0 2542 /* */
michael@0 2543 /* 3a fgh cde qab mnp|00i jkl */
michael@0 2544 /* 3b fgh cde qab mnp|jkl 00i */
michael@0 2545 /* 3c 00i jkl mnp qab cde fgh */
michael@0 2546
michael@0 2547 /* Step 1: amount to shift is the partial right-rotate count */
michael@0 2548 rotate=set->digits-rotate; /* make it right-rotate */
michael@0 2549 units=rotate/DECDPUN; /* whole units to rotate */
michael@0 2550 shift=rotate%DECDPUN; /* left-over digits count */
michael@0 2551 if (shift>0) { /* not an exact number of units */
michael@0 2552 uInt save=res->lsu[0]%powers[shift]; /* save low digit(s) */
michael@0 2553 decShiftToLeast(res->lsu, D2U(res->digits), shift);
michael@0 2554 if (shift>msudigits) { /* msumax-1 needs >0 digits */
michael@0 2555 uInt rem=save%powers[shift-msudigits];/* split save */
michael@0 2556 *msumax=(Unit)(save/powers[shift-msudigits]); /* and insert */
michael@0 2557 *(msumax-1)=*(msumax-1)
michael@0 2558 +(Unit)(rem*powers[DECDPUN-(shift-msudigits)]); /* .. */
michael@0 2559 }
michael@0 2560 else { /* all fits in msumax */
michael@0 2561 *msumax=*msumax+(Unit)(save*powers[msudigits-shift]); /* [maybe *1] */
michael@0 2562 }
michael@0 2563 } /* digits shift needed */
michael@0 2564
michael@0 2565 /* If whole units to rotate... */
michael@0 2566 if (units>0) { /* some to do */
michael@0 2567 /* Step 2: the units to touch are the whole ones in rotate, */
michael@0 2568 /* if any, and the shift is DECDPUN-msudigits (which may be */
michael@0 2569 /* 0, again) */
michael@0 2570 shift=DECDPUN-msudigits;
michael@0 2571 if (shift>0) { /* not an exact number of units */
michael@0 2572 uInt save=res->lsu[0]%powers[shift]; /* save low digit(s) */
michael@0 2573 decShiftToLeast(res->lsu, units, shift);
michael@0 2574 *msumax=*msumax+(Unit)(save*powers[msudigits]);
michael@0 2575 } /* partial shift needed */
michael@0 2576
michael@0 2577 /* Step 3: rotate the units array using triple reverse */
michael@0 2578 /* (reversing is easy and fast) */
michael@0 2579 decReverse(res->lsu+units, msumax); /* left part */
michael@0 2580 decReverse(res->lsu, res->lsu+units-1); /* right part */
michael@0 2581 decReverse(res->lsu, msumax); /* whole */
michael@0 2582 } /* whole units to rotate */
michael@0 2583 /* the rotation may have left an undetermined number of zeros */
michael@0 2584 /* on the left, so true length needs to be calculated */
michael@0 2585 res->digits=decGetDigits(res->lsu, msumax-res->lsu+1);
michael@0 2586 } /* rotate needed */
michael@0 2587 } /* rhs OK */
michael@0 2588 } /* numerics */
michael@0 2589 if (status!=0) decStatus(res, status, set);
michael@0 2590 return res;
michael@0 2591 } /* decNumberRotate */
michael@0 2592
michael@0 2593 /* ------------------------------------------------------------------ */
michael@0 2594 /* decNumberSameQuantum -- test for equal exponents */
michael@0 2595 /* */
michael@0 2596 /* res is the result number, which will contain either 0 or 1 */
michael@0 2597 /* lhs is a number to test */
michael@0 2598 /* rhs is the second (usually a pattern) */
michael@0 2599 /* */
michael@0 2600 /* No errors are possible and no context is needed. */
michael@0 2601 /* ------------------------------------------------------------------ */
michael@0 2602 U_CAPI decNumber * U_EXPORT2 uprv_decNumberSameQuantum(decNumber *res, const decNumber *lhs,
michael@0 2603 const decNumber *rhs) {
michael@0 2604 Unit ret=0; /* return value */
michael@0 2605
michael@0 2606 #if DECCHECK
michael@0 2607 if (decCheckOperands(res, lhs, rhs, DECUNCONT)) return res;
michael@0 2608 #endif
michael@0 2609
michael@0 2610 if (SPECIALARGS) {
michael@0 2611 if (decNumberIsNaN(lhs) && decNumberIsNaN(rhs)) ret=1;
michael@0 2612 else if (decNumberIsInfinite(lhs) && decNumberIsInfinite(rhs)) ret=1;
michael@0 2613 /* [anything else with a special gives 0] */
michael@0 2614 }
michael@0 2615 else if (lhs->exponent==rhs->exponent) ret=1;
michael@0 2616
michael@0 2617 uprv_decNumberZero(res); /* OK to overwrite an operand now */
michael@0 2618 *res->lsu=ret;
michael@0 2619 return res;
michael@0 2620 } /* decNumberSameQuantum */
michael@0 2621
michael@0 2622 /* ------------------------------------------------------------------ */
michael@0 2623 /* decNumberScaleB -- multiply by a power of 10 */
michael@0 2624 /* */
michael@0 2625 /* This computes C = A x 10**B where B is an integer (q=0) with */
michael@0 2626 /* maximum magnitude 2*(emax+digits) */
michael@0 2627 /* */
michael@0 2628 /* res is C, the result. C may be A or B */
michael@0 2629 /* lhs is A, the number to adjust */
michael@0 2630 /* rhs is B, the requested power of ten to use */
michael@0 2631 /* set is the context */
michael@0 2632 /* */
michael@0 2633 /* C must have space for set->digits digits. */
michael@0 2634 /* */
michael@0 2635 /* The result may underflow or overflow. */
michael@0 2636 /* ------------------------------------------------------------------ */
michael@0 2637 U_CAPI decNumber * U_EXPORT2 uprv_decNumberScaleB(decNumber *res, const decNumber *lhs,
michael@0 2638 const decNumber *rhs, decContext *set) {
michael@0 2639 Int reqexp; /* requested exponent change [B] */
michael@0 2640 uInt status=0; /* accumulator */
michael@0 2641 Int residue; /* work */
michael@0 2642
michael@0 2643 #if DECCHECK
michael@0 2644 if (decCheckOperands(res, lhs, rhs, set)) return res;
michael@0 2645 #endif
michael@0 2646
michael@0 2647 /* Handle special values except lhs infinite */
michael@0 2648 if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
michael@0 2649 decNaNs(res, lhs, rhs, set, &status);
michael@0 2650 /* rhs must be an integer */
michael@0 2651 else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
michael@0 2652 status=DEC_Invalid_operation;
michael@0 2653 else {
michael@0 2654 /* lhs is a number; rhs is a finite with q==0 */
michael@0 2655 reqexp=decGetInt(rhs); /* [cannot fail] */
michael@0 2656 if (reqexp==BADINT /* something bad .. */
michael@0 2657 || reqexp==BIGODD || reqexp==BIGEVEN /* .. very big .. */
michael@0 2658 || abs(reqexp)>(2*(set->digits+set->emax))) /* .. or out of range */
michael@0 2659 status=DEC_Invalid_operation;
michael@0 2660 else { /* rhs is OK */
michael@0 2661 uprv_decNumberCopy(res, lhs); /* all done if infinite lhs */
michael@0 2662 if (!decNumberIsInfinite(res)) { /* prepare to scale */
michael@0 2663 res->exponent+=reqexp; /* adjust the exponent */
michael@0 2664 residue=0;
michael@0 2665 decFinalize(res, set, &residue, &status); /* .. and check */
michael@0 2666 } /* finite LHS */
michael@0 2667 } /* rhs OK */
michael@0 2668 } /* rhs finite */
michael@0 2669 if (status!=0) decStatus(res, status, set);
michael@0 2670 return res;
michael@0 2671 } /* decNumberScaleB */
michael@0 2672
michael@0 2673 /* ------------------------------------------------------------------ */
michael@0 2674 /* decNumberShift -- shift the coefficient of a Number left or right */
michael@0 2675 /* */
michael@0 2676 /* This computes C = A << B or C = A >> -B (in base ten). */
michael@0 2677 /* */
michael@0 2678 /* res is C, the result. C may be A and/or B (e.g., X=X<<X) */
michael@0 2679 /* lhs is A */
michael@0 2680 /* rhs is B, the number of digits to shift (-ve to right) */
michael@0 2681 /* set is the context */
michael@0 2682 /* */
michael@0 2683 /* The digits of the coefficient of A are shifted to the left (if B */
michael@0 2684 /* is positive) or to the right (if B is negative) without adjusting */
michael@0 2685 /* the exponent or the sign of A. */
michael@0 2686 /* */
michael@0 2687 /* B must be an integer (q=0) and in the range -set->digits through */
michael@0 2688 /* +set->digits. */
michael@0 2689 /* C must have space for set->digits digits. */
michael@0 2690 /* NaNs are propagated as usual. Infinities are unaffected (but */
michael@0 2691 /* B must be valid). No status is set unless B is invalid or an */
michael@0 2692 /* operand is an sNaN. */
michael@0 2693 /* ------------------------------------------------------------------ */
michael@0 2694 U_CAPI decNumber * U_EXPORT2 uprv_decNumberShift(decNumber *res, const decNumber *lhs,
michael@0 2695 const decNumber *rhs, decContext *set) {
michael@0 2696 uInt status=0; /* accumulator */
michael@0 2697 Int shift; /* rhs as an Int */
michael@0 2698
michael@0 2699 #if DECCHECK
michael@0 2700 if (decCheckOperands(res, lhs, rhs, set)) return res;
michael@0 2701 #endif
michael@0 2702
michael@0 2703 /* NaNs propagate as normal */
michael@0 2704 if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
michael@0 2705 decNaNs(res, lhs, rhs, set, &status);
michael@0 2706 /* rhs must be an integer */
michael@0 2707 else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
michael@0 2708 status=DEC_Invalid_operation;
michael@0 2709 else { /* both numeric, rhs is an integer */
michael@0 2710 shift=decGetInt(rhs); /* [cannot fail] */
michael@0 2711 if (shift==BADINT /* something bad .. */
michael@0 2712 || shift==BIGODD || shift==BIGEVEN /* .. very big .. */
michael@0 2713 || abs(shift)>set->digits) /* .. or out of range */
michael@0 2714 status=DEC_Invalid_operation;
michael@0 2715 else { /* rhs is OK */
michael@0 2716 uprv_decNumberCopy(res, lhs);
michael@0 2717 if (shift!=0 && !decNumberIsInfinite(res)) { /* something to do */
michael@0 2718 if (shift>0) { /* to left */
michael@0 2719 if (shift==set->digits) { /* removing all */
michael@0 2720 *res->lsu=0; /* so place 0 */
michael@0 2721 res->digits=1; /* .. */
michael@0 2722 }
michael@0 2723 else { /* */
michael@0 2724 /* first remove leading digits if necessary */
michael@0 2725 if (res->digits+shift>set->digits) {
michael@0 2726 decDecap(res, res->digits+shift-set->digits);
michael@0 2727 /* that updated res->digits; may have gone to 1 (for a */
michael@0 2728 /* single digit or for zero */
michael@0 2729 }
michael@0 2730 if (res->digits>1 || *res->lsu) /* if non-zero.. */
michael@0 2731 res->digits=decShiftToMost(res->lsu, res->digits, shift);
michael@0 2732 } /* partial left */
michael@0 2733 } /* left */
michael@0 2734 else { /* to right */
michael@0 2735 if (-shift>=res->digits) { /* discarding all */
michael@0 2736 *res->lsu=0; /* so place 0 */
michael@0 2737 res->digits=1; /* .. */
michael@0 2738 }
michael@0 2739 else {
michael@0 2740 decShiftToLeast(res->lsu, D2U(res->digits), -shift);
michael@0 2741 res->digits-=(-shift);
michael@0 2742 }
michael@0 2743 } /* to right */
michael@0 2744 } /* non-0 non-Inf shift */
michael@0 2745 } /* rhs OK */
michael@0 2746 } /* numerics */
michael@0 2747 if (status!=0) decStatus(res, status, set);
michael@0 2748 return res;
michael@0 2749 } /* decNumberShift */
michael@0 2750
michael@0 2751 /* ------------------------------------------------------------------ */
michael@0 2752 /* decNumberSquareRoot -- square root operator */
michael@0 2753 /* */
michael@0 2754 /* This computes C = squareroot(A) */
michael@0 2755 /* */
michael@0 2756 /* res is C, the result. C may be A */
michael@0 2757 /* rhs is A */
michael@0 2758 /* set is the context; note that rounding mode has no effect */
michael@0 2759 /* */
michael@0 2760 /* C must have space for set->digits digits. */
michael@0 2761 /* ------------------------------------------------------------------ */
michael@0 2762 /* This uses the following varying-precision algorithm in: */
michael@0 2763 /* */
michael@0 2764 /* Properly Rounded Variable Precision Square Root, T. E. Hull and */
michael@0 2765 /* A. Abrham, ACM Transactions on Mathematical Software, Vol 11 #3, */
michael@0 2766 /* pp229-237, ACM, September 1985. */
michael@0 2767 /* */
michael@0 2768 /* The square-root is calculated using Newton's method, after which */
michael@0 2769 /* a check is made to ensure the result is correctly rounded. */
michael@0 2770 /* */
michael@0 2771 /* % [Reformatted original Numerical Turing source code follows.] */
michael@0 2772 /* function sqrt(x : real) : real */
michael@0 2773 /* % sqrt(x) returns the properly rounded approximation to the square */
michael@0 2774 /* % root of x, in the precision of the calling environment, or it */
michael@0 2775 /* % fails if x < 0. */
michael@0 2776 /* % t e hull and a abrham, august, 1984 */
michael@0 2777 /* if x <= 0 then */
michael@0 2778 /* if x < 0 then */
michael@0 2779 /* assert false */
michael@0 2780 /* else */
michael@0 2781 /* result 0 */
michael@0 2782 /* end if */
michael@0 2783 /* end if */
michael@0 2784 /* var f := setexp(x, 0) % fraction part of x [0.1 <= x < 1] */
michael@0 2785 /* var e := getexp(x) % exponent part of x */
michael@0 2786 /* var approx : real */
michael@0 2787 /* if e mod 2 = 0 then */
michael@0 2788 /* approx := .259 + .819 * f % approx to root of f */
michael@0 2789 /* else */
michael@0 2790 /* f := f/l0 % adjustments */
michael@0 2791 /* e := e + 1 % for odd */
michael@0 2792 /* approx := .0819 + 2.59 * f % exponent */
michael@0 2793 /* end if */
michael@0 2794 /* */
michael@0 2795 /* var p:= 3 */
michael@0 2796 /* const maxp := currentprecision + 2 */
michael@0 2797 /* loop */
michael@0 2798 /* p := min(2*p - 2, maxp) % p = 4,6,10, . . . , maxp */
michael@0 2799 /* precision p */
michael@0 2800 /* approx := .5 * (approx + f/approx) */
michael@0 2801 /* exit when p = maxp */
michael@0 2802 /* end loop */
michael@0 2803 /* */
michael@0 2804 /* % approx is now within 1 ulp of the properly rounded square root */
michael@0 2805 /* % of f; to ensure proper rounding, compare squares of (approx - */
michael@0 2806 /* % l/2 ulp) and (approx + l/2 ulp) with f. */
michael@0 2807 /* p := currentprecision */
michael@0 2808 /* begin */
michael@0 2809 /* precision p + 2 */
michael@0 2810 /* const approxsubhalf := approx - setexp(.5, -p) */
michael@0 2811 /* if mulru(approxsubhalf, approxsubhalf) > f then */
michael@0 2812 /* approx := approx - setexp(.l, -p + 1) */
michael@0 2813 /* else */
michael@0 2814 /* const approxaddhalf := approx + setexp(.5, -p) */
michael@0 2815 /* if mulrd(approxaddhalf, approxaddhalf) < f then */
michael@0 2816 /* approx := approx + setexp(.l, -p + 1) */
michael@0 2817 /* end if */
michael@0 2818 /* end if */
michael@0 2819 /* end */
michael@0 2820 /* result setexp(approx, e div 2) % fix exponent */
michael@0 2821 /* end sqrt */
michael@0 2822 /* ------------------------------------------------------------------ */
michael@0 2823 #if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406
michael@0 2824 #pragma GCC diagnostic push
michael@0 2825 #pragma GCC diagnostic ignored "-Warray-bounds"
michael@0 2826 #endif
michael@0 2827 U_CAPI decNumber * U_EXPORT2 uprv_decNumberSquareRoot(decNumber *res, const decNumber *rhs,
michael@0 2828 decContext *set) {
michael@0 2829 decContext workset, approxset; /* work contexts */
michael@0 2830 decNumber dzero; /* used for constant zero */
michael@0 2831 Int maxp; /* largest working precision */
michael@0 2832 Int workp; /* working precision */
michael@0 2833 Int residue=0; /* rounding residue */
michael@0 2834 uInt status=0, ignore=0; /* status accumulators */
michael@0 2835 uInt rstatus; /* .. */
michael@0 2836 Int exp; /* working exponent */
michael@0 2837 Int ideal; /* ideal (preferred) exponent */
michael@0 2838 Int needbytes; /* work */
michael@0 2839 Int dropped; /* .. */
michael@0 2840
michael@0 2841 #if DECSUBSET
michael@0 2842 decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */
michael@0 2843 #endif
michael@0 2844 /* buffer for f [needs +1 in case DECBUFFER 0] */
michael@0 2845 decNumber buff[D2N(DECBUFFER+1)];
michael@0 2846 /* buffer for a [needs +2 to match likely maxp] */
michael@0 2847 decNumber bufa[D2N(DECBUFFER+2)];
michael@0 2848 /* buffer for temporary, b [must be same size as a] */
michael@0 2849 decNumber bufb[D2N(DECBUFFER+2)];
michael@0 2850 decNumber *allocbuff=NULL; /* -> allocated buff, iff allocated */
michael@0 2851 decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */
michael@0 2852 decNumber *allocbufb=NULL; /* -> allocated bufb, iff allocated */
michael@0 2853 decNumber *f=buff; /* reduced fraction */
michael@0 2854 decNumber *a=bufa; /* approximation to result */
michael@0 2855 decNumber *b=bufb; /* intermediate result */
michael@0 2856 /* buffer for temporary variable, up to 3 digits */
michael@0 2857 decNumber buft[D2N(3)];
michael@0 2858 decNumber *t=buft; /* up-to-3-digit constant or work */
michael@0 2859
michael@0 2860 #if DECCHECK
michael@0 2861 if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
michael@0 2862 #endif
michael@0 2863
michael@0 2864 do { /* protect allocated storage */
michael@0 2865 #if DECSUBSET
michael@0 2866 if (!set->extended) {
michael@0 2867 /* reduce operand and set lostDigits status, as needed */
michael@0 2868 if (rhs->digits>set->digits) {
michael@0 2869 allocrhs=decRoundOperand(rhs, set, &status);
michael@0 2870 if (allocrhs==NULL) break;
michael@0 2871 /* [Note: 'f' allocation below could reuse this buffer if */
michael@0 2872 /* used, but as this is rare they are kept separate for clarity.] */
michael@0 2873 rhs=allocrhs;
michael@0 2874 }
michael@0 2875 }
michael@0 2876 #endif
michael@0 2877 /* [following code does not require input rounding] */
michael@0 2878
michael@0 2879 /* handle infinities and NaNs */
michael@0 2880 if (SPECIALARG) {
michael@0 2881 if (decNumberIsInfinite(rhs)) { /* an infinity */
michael@0 2882 if (decNumberIsNegative(rhs)) status|=DEC_Invalid_operation;
michael@0 2883 else uprv_decNumberCopy(res, rhs); /* +Infinity */
michael@0 2884 }
michael@0 2885 else decNaNs(res, rhs, NULL, set, &status); /* a NaN */
michael@0 2886 break;
michael@0 2887 }
michael@0 2888
michael@0 2889 /* calculate the ideal (preferred) exponent [floor(exp/2)] */
michael@0 2890 /* [It would be nicer to write: ideal=rhs->exponent>>1, but this */
michael@0 2891 /* generates a compiler warning. Generated code is the same.] */
michael@0 2892 ideal=(rhs->exponent&~1)/2; /* target */
michael@0 2893
michael@0 2894 /* handle zeros */
michael@0 2895 if (ISZERO(rhs)) {
michael@0 2896 uprv_decNumberCopy(res, rhs); /* could be 0 or -0 */
michael@0 2897 res->exponent=ideal; /* use the ideal [safe] */
michael@0 2898 /* use decFinish to clamp any out-of-range exponent, etc. */
michael@0 2899 decFinish(res, set, &residue, &status);
michael@0 2900 break;
michael@0 2901 }
michael@0 2902
michael@0 2903 /* any other -x is an oops */
michael@0 2904 if (decNumberIsNegative(rhs)) {
michael@0 2905 status|=DEC_Invalid_operation;
michael@0 2906 break;
michael@0 2907 }
michael@0 2908
michael@0 2909 /* space is needed for three working variables */
michael@0 2910 /* f -- the same precision as the RHS, reduced to 0.01->0.99... */
michael@0 2911 /* a -- Hull's approximation -- precision, when assigned, is */
michael@0 2912 /* currentprecision+1 or the input argument precision, */
michael@0 2913 /* whichever is larger (+2 for use as temporary) */
michael@0 2914 /* b -- intermediate temporary result (same size as a) */
michael@0 2915 /* if any is too long for local storage, then allocate */
michael@0 2916 workp=MAXI(set->digits+1, rhs->digits); /* actual rounding precision */
michael@0 2917 workp=MAXI(workp, 7); /* at least 7 for low cases */
michael@0 2918 maxp=workp+2; /* largest working precision */
michael@0 2919
michael@0 2920 needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
michael@0 2921 if (needbytes>(Int)sizeof(buff)) {
michael@0 2922 allocbuff=(decNumber *)malloc(needbytes);
michael@0 2923 if (allocbuff==NULL) { /* hopeless -- abandon */
michael@0 2924 status|=DEC_Insufficient_storage;
michael@0 2925 break;}
michael@0 2926 f=allocbuff; /* use the allocated space */
michael@0 2927 }
michael@0 2928 /* a and b both need to be able to hold a maxp-length number */
michael@0 2929 needbytes=sizeof(decNumber)+(D2U(maxp)-1)*sizeof(Unit);
michael@0 2930 if (needbytes>(Int)sizeof(bufa)) { /* [same applies to b] */
michael@0 2931 allocbufa=(decNumber *)malloc(needbytes);
michael@0 2932 allocbufb=(decNumber *)malloc(needbytes);
michael@0 2933 if (allocbufa==NULL || allocbufb==NULL) { /* hopeless */
michael@0 2934 status|=DEC_Insufficient_storage;
michael@0 2935 break;}
michael@0 2936 a=allocbufa; /* use the allocated spaces */
michael@0 2937 b=allocbufb; /* .. */
michael@0 2938 }
michael@0 2939
michael@0 2940 /* copy rhs -> f, save exponent, and reduce so 0.1 <= f < 1 */
michael@0 2941 uprv_decNumberCopy(f, rhs);
michael@0 2942 exp=f->exponent+f->digits; /* adjusted to Hull rules */
michael@0 2943 f->exponent=-(f->digits); /* to range */
michael@0 2944
michael@0 2945 /* set up working context */
michael@0 2946 uprv_decContextDefault(&workset, DEC_INIT_DECIMAL64);
michael@0 2947 workset.emax=DEC_MAX_EMAX;
michael@0 2948 workset.emin=DEC_MIN_EMIN;
michael@0 2949
michael@0 2950 /* [Until further notice, no error is possible and status bits */
michael@0 2951 /* (Rounded, etc.) should be ignored, not accumulated.] */
michael@0 2952
michael@0 2953 /* Calculate initial approximation, and allow for odd exponent */
michael@0 2954 workset.digits=workp; /* p for initial calculation */
michael@0 2955 t->bits=0; t->digits=3;
michael@0 2956 a->bits=0; a->digits=3;
michael@0 2957 if ((exp & 1)==0) { /* even exponent */
michael@0 2958 /* Set t=0.259, a=0.819 */
michael@0 2959 t->exponent=-3;
michael@0 2960 a->exponent=-3;
michael@0 2961 #if DECDPUN>=3
michael@0 2962 t->lsu[0]=259;
michael@0 2963 a->lsu[0]=819;
michael@0 2964 #elif DECDPUN==2
michael@0 2965 t->lsu[0]=59; t->lsu[1]=2;
michael@0 2966 a->lsu[0]=19; a->lsu[1]=8;
michael@0 2967 #else
michael@0 2968 t->lsu[0]=9; t->lsu[1]=5; t->lsu[2]=2;
michael@0 2969 a->lsu[0]=9; a->lsu[1]=1; a->lsu[2]=8;
michael@0 2970 #endif
michael@0 2971 }
michael@0 2972 else { /* odd exponent */
michael@0 2973 /* Set t=0.0819, a=2.59 */
michael@0 2974 f->exponent--; /* f=f/10 */
michael@0 2975 exp++; /* e=e+1 */
michael@0 2976 t->exponent=-4;
michael@0 2977 a->exponent=-2;
michael@0 2978 #if DECDPUN>=3
michael@0 2979 t->lsu[0]=819;
michael@0 2980 a->lsu[0]=259;
michael@0 2981 #elif DECDPUN==2
michael@0 2982 t->lsu[0]=19; t->lsu[1]=8;
michael@0 2983 a->lsu[0]=59; a->lsu[1]=2;
michael@0 2984 #else
michael@0 2985 t->lsu[0]=9; t->lsu[1]=1; t->lsu[2]=8;
michael@0 2986 a->lsu[0]=9; a->lsu[1]=5; a->lsu[2]=2;
michael@0 2987 #endif
michael@0 2988 }
michael@0 2989
michael@0 2990 decMultiplyOp(a, a, f, &workset, &ignore); /* a=a*f */
michael@0 2991 decAddOp(a, a, t, &workset, 0, &ignore); /* ..+t */
michael@0 2992 /* [a is now the initial approximation for sqrt(f), calculated with */
michael@0 2993 /* currentprecision, which is also a's precision.] */
michael@0 2994
michael@0 2995 /* the main calculation loop */
michael@0 2996 uprv_decNumberZero(&dzero); /* make 0 */
michael@0 2997 uprv_decNumberZero(t); /* set t = 0.5 */
michael@0 2998 t->lsu[0]=5; /* .. */
michael@0 2999 t->exponent=-1; /* .. */
michael@0 3000 workset.digits=3; /* initial p */
michael@0 3001 for (; workset.digits<maxp;) {
michael@0 3002 /* set p to min(2*p - 2, maxp) [hence 3; or: 4, 6, 10, ... , maxp] */
michael@0 3003 workset.digits=MINI(workset.digits*2-2, maxp);
michael@0 3004 /* a = 0.5 * (a + f/a) */
michael@0 3005 /* [calculated at p then rounded to currentprecision] */
michael@0 3006 decDivideOp(b, f, a, &workset, DIVIDE, &ignore); /* b=f/a */
michael@0 3007 decAddOp(b, b, a, &workset, 0, &ignore); /* b=b+a */
michael@0 3008 decMultiplyOp(a, b, t, &workset, &ignore); /* a=b*0.5 */
michael@0 3009 } /* loop */
michael@0 3010
michael@0 3011 /* Here, 0.1 <= a < 1 [Hull], and a has maxp digits */
michael@0 3012 /* now reduce to length, etc.; this needs to be done with a */
michael@0 3013 /* having the correct exponent so as to handle subnormals */
michael@0 3014 /* correctly */
michael@0 3015 approxset=*set; /* get emin, emax, etc. */
michael@0 3016 approxset.round=DEC_ROUND_HALF_EVEN;
michael@0 3017 a->exponent+=exp/2; /* set correct exponent */
michael@0 3018 rstatus=0; /* clear status */
michael@0 3019 residue=0; /* .. and accumulator */
michael@0 3020 decCopyFit(a, a, &approxset, &residue, &rstatus); /* reduce (if needed) */
michael@0 3021 decFinish(a, &approxset, &residue, &rstatus); /* clean and finalize */
michael@0 3022
michael@0 3023 /* Overflow was possible if the input exponent was out-of-range, */
michael@0 3024 /* in which case quit */
michael@0 3025 if (rstatus&DEC_Overflow) {
michael@0 3026 status=rstatus; /* use the status as-is */
michael@0 3027 uprv_decNumberCopy(res, a); /* copy to result */
michael@0 3028 break;
michael@0 3029 }
michael@0 3030
michael@0 3031 /* Preserve status except Inexact/Rounded */
michael@0 3032 status|=(rstatus & ~(DEC_Rounded|DEC_Inexact));
michael@0 3033
michael@0 3034 /* Carry out the Hull correction */
michael@0 3035 a->exponent-=exp/2; /* back to 0.1->1 */
michael@0 3036
michael@0 3037 /* a is now at final precision and within 1 ulp of the properly */
michael@0 3038 /* rounded square root of f; to ensure proper rounding, compare */
michael@0 3039 /* squares of (a - l/2 ulp) and (a + l/2 ulp) with f. */
michael@0 3040 /* Here workset.digits=maxp and t=0.5, and a->digits determines */
michael@0 3041 /* the ulp */
michael@0 3042 workset.digits--; /* maxp-1 is OK now */
michael@0 3043 t->exponent=-a->digits-1; /* make 0.5 ulp */
michael@0 3044 decAddOp(b, a, t, &workset, DECNEG, &ignore); /* b = a - 0.5 ulp */
michael@0 3045 workset.round=DEC_ROUND_UP;
michael@0 3046 decMultiplyOp(b, b, b, &workset, &ignore); /* b = mulru(b, b) */
michael@0 3047 decCompareOp(b, f, b, &workset, COMPARE, &ignore); /* b ? f, reversed */
michael@0 3048 if (decNumberIsNegative(b)) { /* f < b [i.e., b > f] */
michael@0 3049 /* this is the more common adjustment, though both are rare */
michael@0 3050 t->exponent++; /* make 1.0 ulp */
michael@0 3051 t->lsu[0]=1; /* .. */
michael@0 3052 decAddOp(a, a, t, &workset, DECNEG, &ignore); /* a = a - 1 ulp */
michael@0 3053 /* assign to approx [round to length] */
michael@0 3054 approxset.emin-=exp/2; /* adjust to match a */
michael@0 3055 approxset.emax-=exp/2;
michael@0 3056 decAddOp(a, &dzero, a, &approxset, 0, &ignore);
michael@0 3057 }
michael@0 3058 else {
michael@0 3059 decAddOp(b, a, t, &workset, 0, &ignore); /* b = a + 0.5 ulp */
michael@0 3060 workset.round=DEC_ROUND_DOWN;
michael@0 3061 decMultiplyOp(b, b, b, &workset, &ignore); /* b = mulrd(b, b) */
michael@0 3062 decCompareOp(b, b, f, &workset, COMPARE, &ignore); /* b ? f */
michael@0 3063 if (decNumberIsNegative(b)) { /* b < f */
michael@0 3064 t->exponent++; /* make 1.0 ulp */
michael@0 3065 t->lsu[0]=1; /* .. */
michael@0 3066 decAddOp(a, a, t, &workset, 0, &ignore); /* a = a + 1 ulp */
michael@0 3067 /* assign to approx [round to length] */
michael@0 3068 approxset.emin-=exp/2; /* adjust to match a */
michael@0 3069 approxset.emax-=exp/2;
michael@0 3070 decAddOp(a, &dzero, a, &approxset, 0, &ignore);
michael@0 3071 }
michael@0 3072 }
michael@0 3073 /* [no errors are possible in the above, and rounding/inexact during */
michael@0 3074 /* estimation are irrelevant, so status was not accumulated] */
michael@0 3075
michael@0 3076 /* Here, 0.1 <= a < 1 (still), so adjust back */
michael@0 3077 a->exponent+=exp/2; /* set correct exponent */
michael@0 3078
michael@0 3079 /* count droppable zeros [after any subnormal rounding] by */
michael@0 3080 /* trimming a copy */
michael@0 3081 uprv_decNumberCopy(b, a);
michael@0 3082 decTrim(b, set, 1, 1, &dropped); /* [drops trailing zeros] */
michael@0 3083
michael@0 3084 /* Set Inexact and Rounded. The answer can only be exact if */
michael@0 3085 /* it is short enough so that squaring it could fit in workp */
michael@0 3086 /* digits, so this is the only (relatively rare) condition that */
michael@0 3087 /* a careful check is needed */
michael@0 3088 if (b->digits*2-1 > workp) { /* cannot fit */
michael@0 3089 status|=DEC_Inexact|DEC_Rounded;
michael@0 3090 }
michael@0 3091 else { /* could be exact/unrounded */
michael@0 3092 uInt mstatus=0; /* local status */
michael@0 3093 decMultiplyOp(b, b, b, &workset, &mstatus); /* try the multiply */
michael@0 3094 if (mstatus&DEC_Overflow) { /* result just won't fit */
michael@0 3095 status|=DEC_Inexact|DEC_Rounded;
michael@0 3096 }
michael@0 3097 else { /* plausible */
michael@0 3098 decCompareOp(t, b, rhs, &workset, COMPARE, &mstatus); /* b ? rhs */
michael@0 3099 if (!ISZERO(t)) status|=DEC_Inexact|DEC_Rounded; /* not equal */
michael@0 3100 else { /* is Exact */
michael@0 3101 /* here, dropped is the count of trailing zeros in 'a' */
michael@0 3102 /* use closest exponent to ideal... */
michael@0 3103 Int todrop=ideal-a->exponent; /* most that can be dropped */
michael@0 3104 if (todrop<0) status|=DEC_Rounded; /* ideally would add 0s */
michael@0 3105 else { /* unrounded */
michael@0 3106 /* there are some to drop, but emax may not allow all */
michael@0 3107 Int maxexp=set->emax-set->digits+1;
michael@0 3108 Int maxdrop=maxexp-a->exponent;
michael@0 3109 if (todrop>maxdrop && set->clamp) { /* apply clamping */
michael@0 3110 todrop=maxdrop;
michael@0 3111 status|=DEC_Clamped;
michael@0 3112 }
michael@0 3113 if (dropped<todrop) { /* clamp to those available */
michael@0 3114 todrop=dropped;
michael@0 3115 status|=DEC_Clamped;
michael@0 3116 }
michael@0 3117 if (todrop>0) { /* have some to drop */
michael@0 3118 decShiftToLeast(a->lsu, D2U(a->digits), todrop);
michael@0 3119 a->exponent+=todrop; /* maintain numerical value */
michael@0 3120 a->digits-=todrop; /* new length */
michael@0 3121 }
michael@0 3122 }
michael@0 3123 }
michael@0 3124 }
michael@0 3125 }
michael@0 3126
michael@0 3127 /* double-check Underflow, as perhaps the result could not have */
michael@0 3128 /* been subnormal (initial argument too big), or it is now Exact */
michael@0 3129 if (status&DEC_Underflow) {
michael@0 3130 Int ae=rhs->exponent+rhs->digits-1; /* adjusted exponent */
michael@0 3131 /* check if truly subnormal */
michael@0 3132 #if DECEXTFLAG /* DEC_Subnormal too */
michael@0 3133 if (ae>=set->emin*2) status&=~(DEC_Subnormal|DEC_Underflow);
michael@0 3134 #else
michael@0 3135 if (ae>=set->emin*2) status&=~DEC_Underflow;
michael@0 3136 #endif
michael@0 3137 /* check if truly inexact */
michael@0 3138 if (!(status&DEC_Inexact)) status&=~DEC_Underflow;
michael@0 3139 }
michael@0 3140
michael@0 3141 uprv_decNumberCopy(res, a); /* a is now the result */
michael@0 3142 } while(0); /* end protected */
michael@0 3143
michael@0 3144 if (allocbuff!=NULL) free(allocbuff); /* drop any storage used */
michael@0 3145 if (allocbufa!=NULL) free(allocbufa); /* .. */
michael@0 3146 if (allocbufb!=NULL) free(allocbufb); /* .. */
michael@0 3147 #if DECSUBSET
michael@0 3148 if (allocrhs !=NULL) free(allocrhs); /* .. */
michael@0 3149 #endif
michael@0 3150 if (status!=0) decStatus(res, status, set);/* then report status */
michael@0 3151 #if DECCHECK
michael@0 3152 decCheckInexact(res, set);
michael@0 3153 #endif
michael@0 3154 return res;
michael@0 3155 } /* decNumberSquareRoot */
michael@0 3156 #if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406
michael@0 3157 #pragma GCC diagnostic pop
michael@0 3158 #endif
michael@0 3159
michael@0 3160 /* ------------------------------------------------------------------ */
michael@0 3161 /* decNumberSubtract -- subtract two Numbers */
michael@0 3162 /* */
michael@0 3163 /* This computes C = A - B */
michael@0 3164 /* */
michael@0 3165 /* res is C, the result. C may be A and/or B (e.g., X=X-X) */
michael@0 3166 /* lhs is A */
michael@0 3167 /* rhs is B */
michael@0 3168 /* set is the context */
michael@0 3169 /* */
michael@0 3170 /* C must have space for set->digits digits. */
michael@0 3171 /* ------------------------------------------------------------------ */
michael@0 3172 U_CAPI decNumber * U_EXPORT2 uprv_decNumberSubtract(decNumber *res, const decNumber *lhs,
michael@0 3173 const decNumber *rhs, decContext *set) {
michael@0 3174 uInt status=0; /* accumulator */
michael@0 3175
michael@0 3176 decAddOp(res, lhs, rhs, set, DECNEG, &status);
michael@0 3177 if (status!=0) decStatus(res, status, set);
michael@0 3178 #if DECCHECK
michael@0 3179 decCheckInexact(res, set);
michael@0 3180 #endif
michael@0 3181 return res;
michael@0 3182 } /* decNumberSubtract */
michael@0 3183
michael@0 3184 /* ------------------------------------------------------------------ */
michael@0 3185 /* decNumberToIntegralExact -- round-to-integral-value with InExact */
michael@0 3186 /* decNumberToIntegralValue -- round-to-integral-value */
michael@0 3187 /* */
michael@0 3188 /* res is the result */
michael@0 3189 /* rhs is input number */
michael@0 3190 /* set is the context */
michael@0 3191 /* */
michael@0 3192 /* res must have space for any value of rhs. */
michael@0 3193 /* */
michael@0 3194 /* This implements the IEEE special operators and therefore treats */
michael@0 3195 /* special values as valid. For finite numbers it returns */
michael@0 3196 /* rescale(rhs, 0) if rhs->exponent is <0. */
michael@0 3197 /* Otherwise the result is rhs (so no error is possible, except for */
michael@0 3198 /* sNaN). */
michael@0 3199 /* */
michael@0 3200 /* The context is used for rounding mode and status after sNaN, but */
michael@0 3201 /* the digits setting is ignored. The Exact version will signal */
michael@0 3202 /* Inexact if the result differs numerically from rhs; the other */
michael@0 3203 /* never signals Inexact. */
michael@0 3204 /* ------------------------------------------------------------------ */
michael@0 3205 U_CAPI decNumber * U_EXPORT2 uprv_decNumberToIntegralExact(decNumber *res, const decNumber *rhs,
michael@0 3206 decContext *set) {
michael@0 3207 decNumber dn;
michael@0 3208 decContext workset; /* working context */
michael@0 3209 uInt status=0; /* accumulator */
michael@0 3210
michael@0 3211 #if DECCHECK
michael@0 3212 if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
michael@0 3213 #endif
michael@0 3214
michael@0 3215 /* handle infinities and NaNs */
michael@0 3216 if (SPECIALARG) {
michael@0 3217 if (decNumberIsInfinite(rhs)) uprv_decNumberCopy(res, rhs); /* an Infinity */
michael@0 3218 else decNaNs(res, rhs, NULL, set, &status); /* a NaN */
michael@0 3219 }
michael@0 3220 else { /* finite */
michael@0 3221 /* have a finite number; no error possible (res must be big enough) */
michael@0 3222 if (rhs->exponent>=0) return uprv_decNumberCopy(res, rhs);
michael@0 3223 /* that was easy, but if negative exponent there is work to do... */
michael@0 3224 workset=*set; /* clone rounding, etc. */
michael@0 3225 workset.digits=rhs->digits; /* no length rounding */
michael@0 3226 workset.traps=0; /* no traps */
michael@0 3227 uprv_decNumberZero(&dn); /* make a number with exponent 0 */
michael@0 3228 uprv_decNumberQuantize(res, rhs, &dn, &workset);
michael@0 3229 status|=workset.status;
michael@0 3230 }
michael@0 3231 if (status!=0) decStatus(res, status, set);
michael@0 3232 return res;
michael@0 3233 } /* decNumberToIntegralExact */
michael@0 3234
michael@0 3235 U_CAPI decNumber * U_EXPORT2 uprv_decNumberToIntegralValue(decNumber *res, const decNumber *rhs,
michael@0 3236 decContext *set) {
michael@0 3237 decContext workset=*set; /* working context */
michael@0 3238 workset.traps=0; /* no traps */
michael@0 3239 uprv_decNumberToIntegralExact(res, rhs, &workset);
michael@0 3240 /* this never affects set, except for sNaNs; NaN will have been set */
michael@0 3241 /* or propagated already, so no need to call decStatus */
michael@0 3242 set->status|=workset.status&DEC_Invalid_operation;
michael@0 3243 return res;
michael@0 3244 } /* decNumberToIntegralValue */
michael@0 3245
michael@0 3246 /* ------------------------------------------------------------------ */
michael@0 3247 /* decNumberXor -- XOR two Numbers, digitwise */
michael@0 3248 /* */
michael@0 3249 /* This computes C = A ^ B */
michael@0 3250 /* */
michael@0 3251 /* res is C, the result. C may be A and/or B (e.g., X=X^X) */
michael@0 3252 /* lhs is A */
michael@0 3253 /* rhs is B */
michael@0 3254 /* set is the context (used for result length and error report) */
michael@0 3255 /* */
michael@0 3256 /* C must have space for set->digits digits. */
michael@0 3257 /* */
michael@0 3258 /* Logical function restrictions apply (see above); a NaN is */
michael@0 3259 /* returned with Invalid_operation if a restriction is violated. */
michael@0 3260 /* ------------------------------------------------------------------ */
michael@0 3261 U_CAPI decNumber * U_EXPORT2 uprv_decNumberXor(decNumber *res, const decNumber *lhs,
michael@0 3262 const decNumber *rhs, decContext *set) {
michael@0 3263 const Unit *ua, *ub; /* -> operands */
michael@0 3264 const Unit *msua, *msub; /* -> operand msus */
michael@0 3265 Unit *uc, *msuc; /* -> result and its msu */
michael@0 3266 Int msudigs; /* digits in res msu */
michael@0 3267 #if DECCHECK
michael@0 3268 if (decCheckOperands(res, lhs, rhs, set)) return res;
michael@0 3269 #endif
michael@0 3270
michael@0 3271 if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
michael@0 3272 || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
michael@0 3273 decStatus(res, DEC_Invalid_operation, set);
michael@0 3274 return res;
michael@0 3275 }
michael@0 3276 /* operands are valid */
michael@0 3277 ua=lhs->lsu; /* bottom-up */
michael@0 3278 ub=rhs->lsu; /* .. */
michael@0 3279 uc=res->lsu; /* .. */
michael@0 3280 msua=ua+D2U(lhs->digits)-1; /* -> msu of lhs */
michael@0 3281 msub=ub+D2U(rhs->digits)-1; /* -> msu of rhs */
michael@0 3282 msuc=uc+D2U(set->digits)-1; /* -> msu of result */
michael@0 3283 msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */
michael@0 3284 for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */
michael@0 3285 Unit a, b; /* extract units */
michael@0 3286 if (ua>msua) a=0;
michael@0 3287 else a=*ua;
michael@0 3288 if (ub>msub) b=0;
michael@0 3289 else b=*ub;
michael@0 3290 *uc=0; /* can now write back */
michael@0 3291 if (a|b) { /* maybe 1 bits to examine */
michael@0 3292 Int i, j;
michael@0 3293 /* This loop could be unrolled and/or use BIN2BCD tables */
michael@0 3294 for (i=0; i<DECDPUN; i++) {
michael@0 3295 if ((a^b)&1) *uc=*uc+(Unit)powers[i]; /* effect XOR */
michael@0 3296 j=a%10;
michael@0 3297 a=a/10;
michael@0 3298 j|=b%10;
michael@0 3299 b=b/10;
michael@0 3300 if (j>1) {
michael@0 3301 decStatus(res, DEC_Invalid_operation, set);
michael@0 3302 return res;
michael@0 3303 }
michael@0 3304 if (uc==msuc && i==msudigs-1) break; /* just did final digit */
michael@0 3305 } /* each digit */
michael@0 3306 } /* non-zero */
michael@0 3307 } /* each unit */
michael@0 3308 /* [here uc-1 is the msu of the result] */
michael@0 3309 res->digits=decGetDigits(res->lsu, uc-res->lsu);
michael@0 3310 res->exponent=0; /* integer */
michael@0 3311 res->bits=0; /* sign=0 */
michael@0 3312 return res; /* [no status to set] */
michael@0 3313 } /* decNumberXor */
michael@0 3314
michael@0 3315
michael@0 3316 /* ================================================================== */
michael@0 3317 /* Utility routines */
michael@0 3318 /* ================================================================== */
michael@0 3319
michael@0 3320 /* ------------------------------------------------------------------ */
michael@0 3321 /* decNumberClass -- return the decClass of a decNumber */
michael@0 3322 /* dn -- the decNumber to test */
michael@0 3323 /* set -- the context to use for Emin */
michael@0 3324 /* returns the decClass enum */
michael@0 3325 /* ------------------------------------------------------------------ */
michael@0 3326 enum decClass uprv_decNumberClass(const decNumber *dn, decContext *set) {
michael@0 3327 if (decNumberIsSpecial(dn)) {
michael@0 3328 if (decNumberIsQNaN(dn)) return DEC_CLASS_QNAN;
michael@0 3329 if (decNumberIsSNaN(dn)) return DEC_CLASS_SNAN;
michael@0 3330 /* must be an infinity */
michael@0 3331 if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_INF;
michael@0 3332 return DEC_CLASS_POS_INF;
michael@0 3333 }
michael@0 3334 /* is finite */
michael@0 3335 if (uprv_decNumberIsNormal(dn, set)) { /* most common */
michael@0 3336 if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_NORMAL;
michael@0 3337 return DEC_CLASS_POS_NORMAL;
michael@0 3338 }
michael@0 3339 /* is subnormal or zero */
michael@0 3340 if (decNumberIsZero(dn)) { /* most common */
michael@0 3341 if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_ZERO;
michael@0 3342 return DEC_CLASS_POS_ZERO;
michael@0 3343 }
michael@0 3344 if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_SUBNORMAL;
michael@0 3345 return DEC_CLASS_POS_SUBNORMAL;
michael@0 3346 } /* decNumberClass */
michael@0 3347
michael@0 3348 /* ------------------------------------------------------------------ */
michael@0 3349 /* decNumberClassToString -- convert decClass to a string */
michael@0 3350 /* */
michael@0 3351 /* eclass is a valid decClass */
michael@0 3352 /* returns a constant string describing the class (max 13+1 chars) */
michael@0 3353 /* ------------------------------------------------------------------ */
michael@0 3354 const char *uprv_decNumberClassToString(enum decClass eclass) {
michael@0 3355 if (eclass==DEC_CLASS_POS_NORMAL) return DEC_ClassString_PN;
michael@0 3356 if (eclass==DEC_CLASS_NEG_NORMAL) return DEC_ClassString_NN;
michael@0 3357 if (eclass==DEC_CLASS_POS_ZERO) return DEC_ClassString_PZ;
michael@0 3358 if (eclass==DEC_CLASS_NEG_ZERO) return DEC_ClassString_NZ;
michael@0 3359 if (eclass==DEC_CLASS_POS_SUBNORMAL) return DEC_ClassString_PS;
michael@0 3360 if (eclass==DEC_CLASS_NEG_SUBNORMAL) return DEC_ClassString_NS;
michael@0 3361 if (eclass==DEC_CLASS_POS_INF) return DEC_ClassString_PI;
michael@0 3362 if (eclass==DEC_CLASS_NEG_INF) return DEC_ClassString_NI;
michael@0 3363 if (eclass==DEC_CLASS_QNAN) return DEC_ClassString_QN;
michael@0 3364 if (eclass==DEC_CLASS_SNAN) return DEC_ClassString_SN;
michael@0 3365 return DEC_ClassString_UN; /* Unknown */
michael@0 3366 } /* decNumberClassToString */
michael@0 3367
michael@0 3368 /* ------------------------------------------------------------------ */
michael@0 3369 /* decNumberCopy -- copy a number */
michael@0 3370 /* */
michael@0 3371 /* dest is the target decNumber */
michael@0 3372 /* src is the source decNumber */
michael@0 3373 /* returns dest */
michael@0 3374 /* */
michael@0 3375 /* (dest==src is allowed and is a no-op) */
michael@0 3376 /* All fields are updated as required. This is a utility operation, */
michael@0 3377 /* so special values are unchanged and no error is possible. */
michael@0 3378 /* ------------------------------------------------------------------ */
michael@0 3379 U_CAPI decNumber * U_EXPORT2 uprv_decNumberCopy(decNumber *dest, const decNumber *src) {
michael@0 3380
michael@0 3381 #if DECCHECK
michael@0 3382 if (src==NULL) return uprv_decNumberZero(dest);
michael@0 3383 #endif
michael@0 3384
michael@0 3385 if (dest==src) return dest; /* no copy required */
michael@0 3386
michael@0 3387 /* Use explicit assignments here as structure assignment could copy */
michael@0 3388 /* more than just the lsu (for small DECDPUN). This would not affect */
michael@0 3389 /* the value of the results, but could disturb test harness spill */
michael@0 3390 /* checking. */
michael@0 3391 dest->bits=src->bits;
michael@0 3392 dest->exponent=src->exponent;
michael@0 3393 dest->digits=src->digits;
michael@0 3394 dest->lsu[0]=src->lsu[0];
michael@0 3395 if (src->digits>DECDPUN) { /* more Units to come */
michael@0 3396 const Unit *smsup, *s; /* work */
michael@0 3397 Unit *d; /* .. */
michael@0 3398 /* memcpy for the remaining Units would be safe as they cannot */
michael@0 3399 /* overlap. However, this explicit loop is faster in short cases. */
michael@0 3400 d=dest->lsu+1; /* -> first destination */
michael@0 3401 smsup=src->lsu+D2U(src->digits); /* -> source msu+1 */
michael@0 3402 for (s=src->lsu+1; s<smsup; s++, d++) *d=*s;
michael@0 3403 }
michael@0 3404 return dest;
michael@0 3405 } /* decNumberCopy */
michael@0 3406
michael@0 3407 /* ------------------------------------------------------------------ */
michael@0 3408 /* decNumberCopyAbs -- quiet absolute value operator */
michael@0 3409 /* */
michael@0 3410 /* This sets C = abs(A) */
michael@0 3411 /* */
michael@0 3412 /* res is C, the result. C may be A */
michael@0 3413 /* rhs is A */
michael@0 3414 /* */
michael@0 3415 /* C must have space for set->digits digits. */
michael@0 3416 /* No exception or error can occur; this is a quiet bitwise operation.*/
michael@0 3417 /* See also decNumberAbs for a checking version of this. */
michael@0 3418 /* ------------------------------------------------------------------ */
michael@0 3419 U_CAPI decNumber * U_EXPORT2 uprv_decNumberCopyAbs(decNumber *res, const decNumber *rhs) {
michael@0 3420 #if DECCHECK
michael@0 3421 if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
michael@0 3422 #endif
michael@0 3423 uprv_decNumberCopy(res, rhs);
michael@0 3424 res->bits&=~DECNEG; /* turn off sign */
michael@0 3425 return res;
michael@0 3426 } /* decNumberCopyAbs */
michael@0 3427
michael@0 3428 /* ------------------------------------------------------------------ */
michael@0 3429 /* decNumberCopyNegate -- quiet negate value operator */
michael@0 3430 /* */
michael@0 3431 /* This sets C = negate(A) */
michael@0 3432 /* */
michael@0 3433 /* res is C, the result. C may be A */
michael@0 3434 /* rhs is A */
michael@0 3435 /* */
michael@0 3436 /* C must have space for set->digits digits. */
michael@0 3437 /* No exception or error can occur; this is a quiet bitwise operation.*/
michael@0 3438 /* See also decNumberMinus for a checking version of this. */
michael@0 3439 /* ------------------------------------------------------------------ */
michael@0 3440 U_CAPI decNumber * U_EXPORT2 uprv_decNumberCopyNegate(decNumber *res, const decNumber *rhs) {
michael@0 3441 #if DECCHECK
michael@0 3442 if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
michael@0 3443 #endif
michael@0 3444 uprv_decNumberCopy(res, rhs);
michael@0 3445 res->bits^=DECNEG; /* invert the sign */
michael@0 3446 return res;
michael@0 3447 } /* decNumberCopyNegate */
michael@0 3448
michael@0 3449 /* ------------------------------------------------------------------ */
michael@0 3450 /* decNumberCopySign -- quiet copy and set sign operator */
michael@0 3451 /* */
michael@0 3452 /* This sets C = A with the sign of B */
michael@0 3453 /* */
michael@0 3454 /* res is C, the result. C may be A */
michael@0 3455 /* lhs is A */
michael@0 3456 /* rhs is B */
michael@0 3457 /* */
michael@0 3458 /* C must have space for set->digits digits. */
michael@0 3459 /* No exception or error can occur; this is a quiet bitwise operation.*/
michael@0 3460 /* ------------------------------------------------------------------ */
michael@0 3461 U_CAPI decNumber * U_EXPORT2 uprv_decNumberCopySign(decNumber *res, const decNumber *lhs,
michael@0 3462 const decNumber *rhs) {
michael@0 3463 uByte sign; /* rhs sign */
michael@0 3464 #if DECCHECK
michael@0 3465 if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
michael@0 3466 #endif
michael@0 3467 sign=rhs->bits & DECNEG; /* save sign bit */
michael@0 3468 uprv_decNumberCopy(res, lhs);
michael@0 3469 res->bits&=~DECNEG; /* clear the sign */
michael@0 3470 res->bits|=sign; /* set from rhs */
michael@0 3471 return res;
michael@0 3472 } /* decNumberCopySign */
michael@0 3473
michael@0 3474 /* ------------------------------------------------------------------ */
michael@0 3475 /* decNumberGetBCD -- get the coefficient in BCD8 */
michael@0 3476 /* dn is the source decNumber */
michael@0 3477 /* bcd is the uInt array that will receive dn->digits BCD bytes, */
michael@0 3478 /* most-significant at offset 0 */
michael@0 3479 /* returns bcd */
michael@0 3480 /* */
michael@0 3481 /* bcd must have at least dn->digits bytes. No error is possible; if */
michael@0 3482 /* dn is a NaN or Infinite, digits must be 1 and the coefficient 0. */
michael@0 3483 /* ------------------------------------------------------------------ */
michael@0 3484 U_CAPI uByte * U_EXPORT2 uprv_decNumberGetBCD(const decNumber *dn, uByte *bcd) {
michael@0 3485 uByte *ub=bcd+dn->digits-1; /* -> lsd */
michael@0 3486 const Unit *up=dn->lsu; /* Unit pointer, -> lsu */
michael@0 3487
michael@0 3488 #if DECDPUN==1 /* trivial simple copy */
michael@0 3489 for (; ub>=bcd; ub--, up++) *ub=*up;
michael@0 3490 #else /* chopping needed */
michael@0 3491 uInt u=*up; /* work */
michael@0 3492 uInt cut=DECDPUN; /* downcounter through unit */
michael@0 3493 for (; ub>=bcd; ub--) {
michael@0 3494 *ub=(uByte)(u%10); /* [*6554 trick inhibits, here] */
michael@0 3495 u=u/10;
michael@0 3496 cut--;
michael@0 3497 if (cut>0) continue; /* more in this unit */
michael@0 3498 up++;
michael@0 3499 u=*up;
michael@0 3500 cut=DECDPUN;
michael@0 3501 }
michael@0 3502 #endif
michael@0 3503 return bcd;
michael@0 3504 } /* decNumberGetBCD */
michael@0 3505
michael@0 3506 /* ------------------------------------------------------------------ */
michael@0 3507 /* decNumberSetBCD -- set (replace) the coefficient from BCD8 */
michael@0 3508 /* dn is the target decNumber */
michael@0 3509 /* bcd is the uInt array that will source n BCD bytes, most- */
michael@0 3510 /* significant at offset 0 */
michael@0 3511 /* n is the number of digits in the source BCD array (bcd) */
michael@0 3512 /* returns dn */
michael@0 3513 /* */
michael@0 3514 /* dn must have space for at least n digits. No error is possible; */
michael@0 3515 /* if dn is a NaN, or Infinite, or is to become a zero, n must be 1 */
michael@0 3516 /* and bcd[0] zero. */
michael@0 3517 /* ------------------------------------------------------------------ */
michael@0 3518 U_CAPI decNumber * U_EXPORT2 uprv_decNumberSetBCD(decNumber *dn, const uByte *bcd, uInt n) {
michael@0 3519 Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [target pointer] */
michael@0 3520 const uByte *ub=bcd; /* -> source msd */
michael@0 3521
michael@0 3522 #if DECDPUN==1 /* trivial simple copy */
michael@0 3523 for (; ub<bcd+n; ub++, up--) *up=*ub;
michael@0 3524 #else /* some assembly needed */
michael@0 3525 /* calculate how many digits in msu, and hence first cut */
michael@0 3526 Int cut=MSUDIGITS(n); /* [faster than remainder] */
michael@0 3527 for (;up>=dn->lsu; up--) { /* each Unit from msu */
michael@0 3528 *up=0; /* will take <=DECDPUN digits */
michael@0 3529 for (; cut>0; ub++, cut--) *up=X10(*up)+*ub;
michael@0 3530 cut=DECDPUN; /* next Unit has all digits */
michael@0 3531 }
michael@0 3532 #endif
michael@0 3533 dn->digits=n; /* set digit count */
michael@0 3534 return dn;
michael@0 3535 } /* decNumberSetBCD */
michael@0 3536
michael@0 3537 /* ------------------------------------------------------------------ */
michael@0 3538 /* decNumberIsNormal -- test normality of a decNumber */
michael@0 3539 /* dn is the decNumber to test */
michael@0 3540 /* set is the context to use for Emin */
michael@0 3541 /* returns 1 if |dn| is finite and >=Nmin, 0 otherwise */
michael@0 3542 /* ------------------------------------------------------------------ */
michael@0 3543 Int uprv_decNumberIsNormal(const decNumber *dn, decContext *set) {
michael@0 3544 Int ae; /* adjusted exponent */
michael@0 3545 #if DECCHECK
michael@0 3546 if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
michael@0 3547 #endif
michael@0 3548
michael@0 3549 if (decNumberIsSpecial(dn)) return 0; /* not finite */
michael@0 3550 if (decNumberIsZero(dn)) return 0; /* not non-zero */
michael@0 3551
michael@0 3552 ae=dn->exponent+dn->digits-1; /* adjusted exponent */
michael@0 3553 if (ae<set->emin) return 0; /* is subnormal */
michael@0 3554 return 1;
michael@0 3555 } /* decNumberIsNormal */
michael@0 3556
michael@0 3557 /* ------------------------------------------------------------------ */
michael@0 3558 /* decNumberIsSubnormal -- test subnormality of a decNumber */
michael@0 3559 /* dn is the decNumber to test */
michael@0 3560 /* set is the context to use for Emin */
michael@0 3561 /* returns 1 if |dn| is finite, non-zero, and <Nmin, 0 otherwise */
michael@0 3562 /* ------------------------------------------------------------------ */
michael@0 3563 Int uprv_decNumberIsSubnormal(const decNumber *dn, decContext *set) {
michael@0 3564 Int ae; /* adjusted exponent */
michael@0 3565 #if DECCHECK
michael@0 3566 if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
michael@0 3567 #endif
michael@0 3568
michael@0 3569 if (decNumberIsSpecial(dn)) return 0; /* not finite */
michael@0 3570 if (decNumberIsZero(dn)) return 0; /* not non-zero */
michael@0 3571
michael@0 3572 ae=dn->exponent+dn->digits-1; /* adjusted exponent */
michael@0 3573 if (ae<set->emin) return 1; /* is subnormal */
michael@0 3574 return 0;
michael@0 3575 } /* decNumberIsSubnormal */
michael@0 3576
michael@0 3577 /* ------------------------------------------------------------------ */
michael@0 3578 /* decNumberTrim -- remove insignificant zeros */
michael@0 3579 /* */
michael@0 3580 /* dn is the number to trim */
michael@0 3581 /* returns dn */
michael@0 3582 /* */
michael@0 3583 /* All fields are updated as required. This is a utility operation, */
michael@0 3584 /* so special values are unchanged and no error is possible. The */
michael@0 3585 /* zeros are removed unconditionally. */
michael@0 3586 /* ------------------------------------------------------------------ */
michael@0 3587 U_CAPI decNumber * U_EXPORT2 uprv_decNumberTrim(decNumber *dn) {
michael@0 3588 Int dropped; /* work */
michael@0 3589 decContext set; /* .. */
michael@0 3590 #if DECCHECK
michael@0 3591 if (decCheckOperands(DECUNRESU, DECUNUSED, dn, DECUNCONT)) return dn;
michael@0 3592 #endif
michael@0 3593 uprv_decContextDefault(&set, DEC_INIT_BASE); /* clamp=0 */
michael@0 3594 return decTrim(dn, &set, 0, 1, &dropped);
michael@0 3595 } /* decNumberTrim */
michael@0 3596
michael@0 3597 /* ------------------------------------------------------------------ */
michael@0 3598 /* decNumberVersion -- return the name and version of this module */
michael@0 3599 /* */
michael@0 3600 /* No error is possible. */
michael@0 3601 /* ------------------------------------------------------------------ */
michael@0 3602 const char * uprv_decNumberVersion(void) {
michael@0 3603 return DECVERSION;
michael@0 3604 } /* decNumberVersion */
michael@0 3605
michael@0 3606 /* ------------------------------------------------------------------ */
michael@0 3607 /* decNumberZero -- set a number to 0 */
michael@0 3608 /* */
michael@0 3609 /* dn is the number to set, with space for one digit */
michael@0 3610 /* returns dn */
michael@0 3611 /* */
michael@0 3612 /* No error is possible. */
michael@0 3613 /* ------------------------------------------------------------------ */
michael@0 3614 /* Memset is not used as it is much slower in some environments. */
michael@0 3615 U_CAPI decNumber * U_EXPORT2 uprv_decNumberZero(decNumber *dn) {
michael@0 3616
michael@0 3617 #if DECCHECK
michael@0 3618 if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn;
michael@0 3619 #endif
michael@0 3620
michael@0 3621 dn->bits=0;
michael@0 3622 dn->exponent=0;
michael@0 3623 dn->digits=1;
michael@0 3624 dn->lsu[0]=0;
michael@0 3625 return dn;
michael@0 3626 } /* decNumberZero */
michael@0 3627
michael@0 3628 /* ================================================================== */
michael@0 3629 /* Local routines */
michael@0 3630 /* ================================================================== */
michael@0 3631
michael@0 3632 /* ------------------------------------------------------------------ */
michael@0 3633 /* decToString -- lay out a number into a string */
michael@0 3634 /* */
michael@0 3635 /* dn is the number to lay out */
michael@0 3636 /* string is where to lay out the number */
michael@0 3637 /* eng is 1 if Engineering, 0 if Scientific */
michael@0 3638 /* */
michael@0 3639 /* string must be at least dn->digits+14 characters long */
michael@0 3640 /* No error is possible. */
michael@0 3641 /* */
michael@0 3642 /* Note that this routine can generate a -0 or 0.000. These are */
michael@0 3643 /* never generated in subset to-number or arithmetic, but can occur */
michael@0 3644 /* in non-subset arithmetic (e.g., -1*0 or 1.234-1.234). */
michael@0 3645 /* ------------------------------------------------------------------ */
michael@0 3646 /* If DECCHECK is enabled the string "?" is returned if a number is */
michael@0 3647 /* invalid. */
michael@0 3648 static void decToString(const decNumber *dn, char *string, Flag eng) {
michael@0 3649 Int exp=dn->exponent; /* local copy */
michael@0 3650 Int e; /* E-part value */
michael@0 3651 Int pre; /* digits before the '.' */
michael@0 3652 Int cut; /* for counting digits in a Unit */
michael@0 3653 char *c=string; /* work [output pointer] */
michael@0 3654 const Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [input pointer] */
michael@0 3655 uInt u, pow; /* work */
michael@0 3656
michael@0 3657 #if DECCHECK
michael@0 3658 if (decCheckOperands(DECUNRESU, dn, DECUNUSED, DECUNCONT)) {
michael@0 3659 strcpy(string, "?");
michael@0 3660 return;}
michael@0 3661 #endif
michael@0 3662
michael@0 3663 if (decNumberIsNegative(dn)) { /* Negatives get a minus */
michael@0 3664 *c='-';
michael@0 3665 c++;
michael@0 3666 }
michael@0 3667 if (dn->bits&DECSPECIAL) { /* Is a special value */
michael@0 3668 if (decNumberIsInfinite(dn)) {
michael@0 3669 strcpy(c, "Inf");
michael@0 3670 strcpy(c+3, "inity");
michael@0 3671 return;}
michael@0 3672 /* a NaN */
michael@0 3673 if (dn->bits&DECSNAN) { /* signalling NaN */
michael@0 3674 *c='s';
michael@0 3675 c++;
michael@0 3676 }
michael@0 3677 strcpy(c, "NaN");
michael@0 3678 c+=3; /* step past */
michael@0 3679 /* if not a clean non-zero coefficient, that's all there is in a */
michael@0 3680 /* NaN string */
michael@0 3681 if (exp!=0 || (*dn->lsu==0 && dn->digits==1)) return;
michael@0 3682 /* [drop through to add integer] */
michael@0 3683 }
michael@0 3684
michael@0 3685 /* calculate how many digits in msu, and hence first cut */
michael@0 3686 cut=MSUDIGITS(dn->digits); /* [faster than remainder] */
michael@0 3687 cut--; /* power of ten for digit */
michael@0 3688
michael@0 3689 if (exp==0) { /* simple integer [common fastpath] */
michael@0 3690 for (;up>=dn->lsu; up--) { /* each Unit from msu */
michael@0 3691 u=*up; /* contains DECDPUN digits to lay out */
michael@0 3692 for (; cut>=0; c++, cut--) TODIGIT(u, cut, c, pow);
michael@0 3693 cut=DECDPUN-1; /* next Unit has all digits */
michael@0 3694 }
michael@0 3695 *c='\0'; /* terminate the string */
michael@0 3696 return;}
michael@0 3697
michael@0 3698 /* non-0 exponent -- assume plain form */
michael@0 3699 pre=dn->digits+exp; /* digits before '.' */
michael@0 3700 e=0; /* no E */
michael@0 3701 if ((exp>0) || (pre<-5)) { /* need exponential form */
michael@0 3702 e=exp+dn->digits-1; /* calculate E value */
michael@0 3703 pre=1; /* assume one digit before '.' */
michael@0 3704 if (eng && (e!=0)) { /* engineering: may need to adjust */
michael@0 3705 Int adj; /* adjustment */
michael@0 3706 /* The C remainder operator is undefined for negative numbers, so */
michael@0 3707 /* a positive remainder calculation must be used here */
michael@0 3708 if (e<0) {
michael@0 3709 adj=(-e)%3;
michael@0 3710 if (adj!=0) adj=3-adj;
michael@0 3711 }
michael@0 3712 else { /* e>0 */
michael@0 3713 adj=e%3;
michael@0 3714 }
michael@0 3715 e=e-adj;
michael@0 3716 /* if dealing with zero still produce an exponent which is a */
michael@0 3717 /* multiple of three, as expected, but there will only be the */
michael@0 3718 /* one zero before the E, still. Otherwise note the padding. */
michael@0 3719 if (!ISZERO(dn)) pre+=adj;
michael@0 3720 else { /* is zero */
michael@0 3721 if (adj!=0) { /* 0.00Esnn needed */
michael@0 3722 e=e+3;
michael@0 3723 pre=-(2-adj);
michael@0 3724 }
michael@0 3725 } /* zero */
michael@0 3726 } /* eng */
michael@0 3727 } /* need exponent */
michael@0 3728
michael@0 3729 /* lay out the digits of the coefficient, adding 0s and . as needed */
michael@0 3730 u=*up;
michael@0 3731 if (pre>0) { /* xxx.xxx or xx00 (engineering) form */
michael@0 3732 Int n=pre;
michael@0 3733 for (; pre>0; pre--, c++, cut--) {
michael@0 3734 if (cut<0) { /* need new Unit */
michael@0 3735 if (up==dn->lsu) break; /* out of input digits (pre>digits) */
michael@0 3736 up--;
michael@0 3737 cut=DECDPUN-1;
michael@0 3738 u=*up;
michael@0 3739 }
michael@0 3740 TODIGIT(u, cut, c, pow);
michael@0 3741 }
michael@0 3742 if (n<dn->digits) { /* more to come, after '.' */
michael@0 3743 *c='.'; c++;
michael@0 3744 for (;; c++, cut--) {
michael@0 3745 if (cut<0) { /* need new Unit */
michael@0 3746 if (up==dn->lsu) break; /* out of input digits */
michael@0 3747 up--;
michael@0 3748 cut=DECDPUN-1;
michael@0 3749 u=*up;
michael@0 3750 }
michael@0 3751 TODIGIT(u, cut, c, pow);
michael@0 3752 }
michael@0 3753 }
michael@0 3754 else for (; pre>0; pre--, c++) *c='0'; /* 0 padding (for engineering) needed */
michael@0 3755 }
michael@0 3756 else { /* 0.xxx or 0.000xxx form */
michael@0 3757 *c='0'; c++;
michael@0 3758 *c='.'; c++;
michael@0 3759 for (; pre<0; pre++, c++) *c='0'; /* add any 0's after '.' */
michael@0 3760 for (; ; c++, cut--) {
michael@0 3761 if (cut<0) { /* need new Unit */
michael@0 3762 if (up==dn->lsu) break; /* out of input digits */
michael@0 3763 up--;
michael@0 3764 cut=DECDPUN-1;
michael@0 3765 u=*up;
michael@0 3766 }
michael@0 3767 TODIGIT(u, cut, c, pow);
michael@0 3768 }
michael@0 3769 }
michael@0 3770
michael@0 3771 /* Finally add the E-part, if needed. It will never be 0, has a
michael@0 3772 base maximum and minimum of +999999999 through -999999999, but
michael@0 3773 could range down to -1999999998 for anormal numbers */
michael@0 3774 if (e!=0) {
michael@0 3775 Flag had=0; /* 1=had non-zero */
michael@0 3776 *c='E'; c++;
michael@0 3777 *c='+'; c++; /* assume positive */
michael@0 3778 u=e; /* .. */
michael@0 3779 if (e<0) {
michael@0 3780 *(c-1)='-'; /* oops, need - */
michael@0 3781 u=-e; /* uInt, please */
michael@0 3782 }
michael@0 3783 /* lay out the exponent [_itoa or equivalent is not ANSI C] */
michael@0 3784 for (cut=9; cut>=0; cut--) {
michael@0 3785 TODIGIT(u, cut, c, pow);
michael@0 3786 if (*c=='0' && !had) continue; /* skip leading zeros */
michael@0 3787 had=1; /* had non-0 */
michael@0 3788 c++; /* step for next */
michael@0 3789 } /* cut */
michael@0 3790 }
michael@0 3791 *c='\0'; /* terminate the string (all paths) */
michael@0 3792 return;
michael@0 3793 } /* decToString */
michael@0 3794
michael@0 3795 /* ------------------------------------------------------------------ */
michael@0 3796 /* decAddOp -- add/subtract operation */
michael@0 3797 /* */
michael@0 3798 /* This computes C = A + B */
michael@0 3799 /* */
michael@0 3800 /* res is C, the result. C may be A and/or B (e.g., X=X+X) */
michael@0 3801 /* lhs is A */
michael@0 3802 /* rhs is B */
michael@0 3803 /* set is the context */
michael@0 3804 /* negate is DECNEG if rhs should be negated, or 0 otherwise */
michael@0 3805 /* status accumulates status for the caller */
michael@0 3806 /* */
michael@0 3807 /* C must have space for set->digits digits. */
michael@0 3808 /* Inexact in status must be 0 for correct Exact zero sign in result */
michael@0 3809 /* ------------------------------------------------------------------ */
michael@0 3810 /* If possible, the coefficient is calculated directly into C. */
michael@0 3811 /* However, if: */
michael@0 3812 /* -- a digits+1 calculation is needed because the numbers are */
michael@0 3813 /* unaligned and span more than set->digits digits */
michael@0 3814 /* -- a carry to digits+1 digits looks possible */
michael@0 3815 /* -- C is the same as A or B, and the result would destructively */
michael@0 3816 /* overlap the A or B coefficient */
michael@0 3817 /* then the result must be calculated into a temporary buffer. In */
michael@0 3818 /* this case a local (stack) buffer is used if possible, and only if */
michael@0 3819 /* too long for that does malloc become the final resort. */
michael@0 3820 /* */
michael@0 3821 /* Misalignment is handled as follows: */
michael@0 3822 /* Apad: (AExp>BExp) Swap operands and proceed as for BExp>AExp. */
michael@0 3823 /* BPad: Apply the padding by a combination of shifting (whole */
michael@0 3824 /* units) and multiplication (part units). */
michael@0 3825 /* */
michael@0 3826 /* Addition, especially x=x+1, is speed-critical. */
michael@0 3827 /* The static buffer is larger than might be expected to allow for */
michael@0 3828 /* calls from higher-level funtions (notable exp). */
michael@0 3829 /* ------------------------------------------------------------------ */
michael@0 3830 static decNumber * decAddOp(decNumber *res, const decNumber *lhs,
michael@0 3831 const decNumber *rhs, decContext *set,
michael@0 3832 uByte negate, uInt *status) {
michael@0 3833 #if DECSUBSET
michael@0 3834 decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */
michael@0 3835 decNumber *allocrhs=NULL; /* .., rhs */
michael@0 3836 #endif
michael@0 3837 Int rhsshift; /* working shift (in Units) */
michael@0 3838 Int maxdigits; /* longest logical length */
michael@0 3839 Int mult; /* multiplier */
michael@0 3840 Int residue; /* rounding accumulator */
michael@0 3841 uByte bits; /* result bits */
michael@0 3842 Flag diffsign; /* non-0 if arguments have different sign */
michael@0 3843 Unit *acc; /* accumulator for result */
michael@0 3844 Unit accbuff[SD2U(DECBUFFER*2+20)]; /* local buffer [*2+20 reduces many */
michael@0 3845 /* allocations when called from */
michael@0 3846 /* other operations, notable exp] */
michael@0 3847 Unit *allocacc=NULL; /* -> allocated acc buffer, iff allocated */
michael@0 3848 Int reqdigits=set->digits; /* local copy; requested DIGITS */
michael@0 3849 Int padding; /* work */
michael@0 3850
michael@0 3851 #if DECCHECK
michael@0 3852 if (decCheckOperands(res, lhs, rhs, set)) return res;
michael@0 3853 #endif
michael@0 3854
michael@0 3855 do { /* protect allocated storage */
michael@0 3856 #if DECSUBSET
michael@0 3857 if (!set->extended) {
michael@0 3858 /* reduce operands and set lostDigits status, as needed */
michael@0 3859 if (lhs->digits>reqdigits) {
michael@0 3860 alloclhs=decRoundOperand(lhs, set, status);
michael@0 3861 if (alloclhs==NULL) break;
michael@0 3862 lhs=alloclhs;
michael@0 3863 }
michael@0 3864 if (rhs->digits>reqdigits) {
michael@0 3865 allocrhs=decRoundOperand(rhs, set, status);
michael@0 3866 if (allocrhs==NULL) break;
michael@0 3867 rhs=allocrhs;
michael@0 3868 }
michael@0 3869 }
michael@0 3870 #endif
michael@0 3871 /* [following code does not require input rounding] */
michael@0 3872
michael@0 3873 /* note whether signs differ [used all paths] */
michael@0 3874 diffsign=(Flag)((lhs->bits^rhs->bits^negate)&DECNEG);
michael@0 3875
michael@0 3876 /* handle infinities and NaNs */
michael@0 3877 if (SPECIALARGS) { /* a special bit set */
michael@0 3878 if (SPECIALARGS & (DECSNAN | DECNAN)) /* a NaN */
michael@0 3879 decNaNs(res, lhs, rhs, set, status);
michael@0 3880 else { /* one or two infinities */
michael@0 3881 if (decNumberIsInfinite(lhs)) { /* LHS is infinity */
michael@0 3882 /* two infinities with different signs is invalid */
michael@0 3883 if (decNumberIsInfinite(rhs) && diffsign) {
michael@0 3884 *status|=DEC_Invalid_operation;
michael@0 3885 break;
michael@0 3886 }
michael@0 3887 bits=lhs->bits & DECNEG; /* get sign from LHS */
michael@0 3888 }
michael@0 3889 else bits=(rhs->bits^negate) & DECNEG;/* RHS must be Infinity */
michael@0 3890 bits|=DECINF;
michael@0 3891 uprv_decNumberZero(res);
michael@0 3892 res->bits=bits; /* set +/- infinity */
michael@0 3893 } /* an infinity */
michael@0 3894 break;
michael@0 3895 }
michael@0 3896
michael@0 3897 /* Quick exit for add 0s; return the non-0, modified as need be */
michael@0 3898 if (ISZERO(lhs)) {
michael@0 3899 Int adjust; /* work */
michael@0 3900 Int lexp=lhs->exponent; /* save in case LHS==RES */
michael@0 3901 bits=lhs->bits; /* .. */
michael@0 3902 residue=0; /* clear accumulator */
michael@0 3903 decCopyFit(res, rhs, set, &residue, status); /* copy (as needed) */
michael@0 3904 res->bits^=negate; /* flip if rhs was negated */
michael@0 3905 #if DECSUBSET
michael@0 3906 if (set->extended) { /* exponents on zeros count */
michael@0 3907 #endif
michael@0 3908 /* exponent will be the lower of the two */
michael@0 3909 adjust=lexp-res->exponent; /* adjustment needed [if -ve] */
michael@0 3910 if (ISZERO(res)) { /* both 0: special IEEE 754 rules */
michael@0 3911 if (adjust<0) res->exponent=lexp; /* set exponent */
michael@0 3912 /* 0-0 gives +0 unless rounding to -infinity, and -0-0 gives -0 */
michael@0 3913 if (diffsign) {
michael@0 3914 if (set->round!=DEC_ROUND_FLOOR) res->bits=0;
michael@0 3915 else res->bits=DECNEG; /* preserve 0 sign */
michael@0 3916 }
michael@0 3917 }
michael@0 3918 else { /* non-0 res */
michael@0 3919 if (adjust<0) { /* 0-padding needed */
michael@0 3920 if ((res->digits-adjust)>set->digits) {
michael@0 3921 adjust=res->digits-set->digits; /* to fit exactly */
michael@0 3922 *status|=DEC_Rounded; /* [but exact] */
michael@0 3923 }
michael@0 3924 res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
michael@0 3925 res->exponent+=adjust; /* set the exponent. */
michael@0 3926 }
michael@0 3927 } /* non-0 res */
michael@0 3928 #if DECSUBSET
michael@0 3929 } /* extended */
michael@0 3930 #endif
michael@0 3931 decFinish(res, set, &residue, status); /* clean and finalize */
michael@0 3932 break;}
michael@0 3933
michael@0 3934 if (ISZERO(rhs)) { /* [lhs is non-zero] */
michael@0 3935 Int adjust; /* work */
michael@0 3936 Int rexp=rhs->exponent; /* save in case RHS==RES */
michael@0 3937 bits=rhs->bits; /* be clean */
michael@0 3938 residue=0; /* clear accumulator */
michael@0 3939 decCopyFit(res, lhs, set, &residue, status); /* copy (as needed) */
michael@0 3940 #if DECSUBSET
michael@0 3941 if (set->extended) { /* exponents on zeros count */
michael@0 3942 #endif
michael@0 3943 /* exponent will be the lower of the two */
michael@0 3944 /* [0-0 case handled above] */
michael@0 3945 adjust=rexp-res->exponent; /* adjustment needed [if -ve] */
michael@0 3946 if (adjust<0) { /* 0-padding needed */
michael@0 3947 if ((res->digits-adjust)>set->digits) {
michael@0 3948 adjust=res->digits-set->digits; /* to fit exactly */
michael@0 3949 *status|=DEC_Rounded; /* [but exact] */
michael@0 3950 }
michael@0 3951 res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
michael@0 3952 res->exponent+=adjust; /* set the exponent. */
michael@0 3953 }
michael@0 3954 #if DECSUBSET
michael@0 3955 } /* extended */
michael@0 3956 #endif
michael@0 3957 decFinish(res, set, &residue, status); /* clean and finalize */
michael@0 3958 break;}
michael@0 3959
michael@0 3960 /* [NB: both fastpath and mainpath code below assume these cases */
michael@0 3961 /* (notably 0-0) have already been handled] */
michael@0 3962
michael@0 3963 /* calculate the padding needed to align the operands */
michael@0 3964 padding=rhs->exponent-lhs->exponent;
michael@0 3965
michael@0 3966 /* Fastpath cases where the numbers are aligned and normal, the RHS */
michael@0 3967 /* is all in one unit, no operand rounding is needed, and no carry, */
michael@0 3968 /* lengthening, or borrow is needed */
michael@0 3969 if (padding==0
michael@0 3970 && rhs->digits<=DECDPUN
michael@0 3971 && rhs->exponent>=set->emin /* [some normals drop through] */
michael@0 3972 && rhs->exponent<=set->emax-set->digits+1 /* [could clamp] */
michael@0 3973 && rhs->digits<=reqdigits
michael@0 3974 && lhs->digits<=reqdigits) {
michael@0 3975 Int partial=*lhs->lsu;
michael@0 3976 if (!diffsign) { /* adding */
michael@0 3977 partial+=*rhs->lsu;
michael@0 3978 if ((partial<=DECDPUNMAX) /* result fits in unit */
michael@0 3979 && (lhs->digits>=DECDPUN || /* .. and no digits-count change */
michael@0 3980 partial<(Int)powers[lhs->digits])) { /* .. */
michael@0 3981 if (res!=lhs) uprv_decNumberCopy(res, lhs); /* not in place */
michael@0 3982 *res->lsu=(Unit)partial; /* [copy could have overwritten RHS] */
michael@0 3983 break;
michael@0 3984 }
michael@0 3985 /* else drop out for careful add */
michael@0 3986 }
michael@0 3987 else { /* signs differ */
michael@0 3988 partial-=*rhs->lsu;
michael@0 3989 if (partial>0) { /* no borrow needed, and non-0 result */
michael@0 3990 if (res!=lhs) uprv_decNumberCopy(res, lhs); /* not in place */
michael@0 3991 *res->lsu=(Unit)partial;
michael@0 3992 /* this could have reduced digits [but result>0] */
michael@0 3993 res->digits=decGetDigits(res->lsu, D2U(res->digits));
michael@0 3994 break;
michael@0 3995 }
michael@0 3996 /* else drop out for careful subtract */
michael@0 3997 }
michael@0 3998 }
michael@0 3999
michael@0 4000 /* Now align (pad) the lhs or rhs so they can be added or */
michael@0 4001 /* subtracted, as necessary. If one number is much larger than */
michael@0 4002 /* the other (that is, if in plain form there is a least one */
michael@0 4003 /* digit between the lowest digit of one and the highest of the */
michael@0 4004 /* other) padding with up to DIGITS-1 trailing zeros may be */
michael@0 4005 /* needed; then apply rounding (as exotic rounding modes may be */
michael@0 4006 /* affected by the residue). */
michael@0 4007 rhsshift=0; /* rhs shift to left (padding) in Units */
michael@0 4008 bits=lhs->bits; /* assume sign is that of LHS */
michael@0 4009 mult=1; /* likely multiplier */
michael@0 4010
michael@0 4011 /* [if padding==0 the operands are aligned; no padding is needed] */
michael@0 4012 if (padding!=0) {
michael@0 4013 /* some padding needed; always pad the RHS, as any required */
michael@0 4014 /* padding can then be effected by a simple combination of */
michael@0 4015 /* shifts and a multiply */
michael@0 4016 Flag swapped=0;
michael@0 4017 if (padding<0) { /* LHS needs the padding */
michael@0 4018 const decNumber *t;
michael@0 4019 padding=-padding; /* will be +ve */
michael@0 4020 bits=(uByte)(rhs->bits^negate); /* assumed sign is now that of RHS */
michael@0 4021 t=lhs; lhs=rhs; rhs=t;
michael@0 4022 swapped=1;
michael@0 4023 }
michael@0 4024
michael@0 4025 /* If, after pad, rhs would be longer than lhs by digits+1 or */
michael@0 4026 /* more then lhs cannot affect the answer, except as a residue, */
michael@0 4027 /* so only need to pad up to a length of DIGITS+1. */
michael@0 4028 if (rhs->digits+padding > lhs->digits+reqdigits+1) {
michael@0 4029 /* The RHS is sufficient */
michael@0 4030 /* for residue use the relative sign indication... */
michael@0 4031 Int shift=reqdigits-rhs->digits; /* left shift needed */
michael@0 4032 residue=1; /* residue for rounding */
michael@0 4033 if (diffsign) residue=-residue; /* signs differ */
michael@0 4034 /* copy, shortening if necessary */
michael@0 4035 decCopyFit(res, rhs, set, &residue, status);
michael@0 4036 /* if it was already shorter, then need to pad with zeros */
michael@0 4037 if (shift>0) {
michael@0 4038 res->digits=decShiftToMost(res->lsu, res->digits, shift);
michael@0 4039 res->exponent-=shift; /* adjust the exponent. */
michael@0 4040 }
michael@0 4041 /* flip the result sign if unswapped and rhs was negated */
michael@0 4042 if (!swapped) res->bits^=negate;
michael@0 4043 decFinish(res, set, &residue, status); /* done */
michael@0 4044 break;}
michael@0 4045
michael@0 4046 /* LHS digits may affect result */
michael@0 4047 rhsshift=D2U(padding+1)-1; /* this much by Unit shift .. */
michael@0 4048 mult=powers[padding-(rhsshift*DECDPUN)]; /* .. this by multiplication */
michael@0 4049 } /* padding needed */
michael@0 4050
michael@0 4051 if (diffsign) mult=-mult; /* signs differ */
michael@0 4052
michael@0 4053 /* determine the longer operand */
michael@0 4054 maxdigits=rhs->digits+padding; /* virtual length of RHS */
michael@0 4055 if (lhs->digits>maxdigits) maxdigits=lhs->digits;
michael@0 4056
michael@0 4057 /* Decide on the result buffer to use; if possible place directly */
michael@0 4058 /* into result. */
michael@0 4059 acc=res->lsu; /* assume add direct to result */
michael@0 4060 /* If destructive overlap, or the number is too long, or a carry or */
michael@0 4061 /* borrow to DIGITS+1 might be possible, a buffer must be used. */
michael@0 4062 /* [Might be worth more sophisticated tests when maxdigits==reqdigits] */
michael@0 4063 if ((maxdigits>=reqdigits) /* is, or could be, too large */
michael@0 4064 || (res==rhs && rhsshift>0)) { /* destructive overlap */
michael@0 4065 /* buffer needed, choose it; units for maxdigits digits will be */
michael@0 4066 /* needed, +1 Unit for carry or borrow */
michael@0 4067 Int need=D2U(maxdigits)+1;
michael@0 4068 acc=accbuff; /* assume use local buffer */
michael@0 4069 if (need*sizeof(Unit)>sizeof(accbuff)) {
michael@0 4070 /* printf("malloc add %ld %ld\n", need, sizeof(accbuff)); */
michael@0 4071 allocacc=(Unit *)malloc(need*sizeof(Unit));
michael@0 4072 if (allocacc==NULL) { /* hopeless -- abandon */
michael@0 4073 *status|=DEC_Insufficient_storage;
michael@0 4074 break;}
michael@0 4075 acc=allocacc;
michael@0 4076 }
michael@0 4077 }
michael@0 4078
michael@0 4079 res->bits=(uByte)(bits&DECNEG); /* it's now safe to overwrite.. */
michael@0 4080 res->exponent=lhs->exponent; /* .. operands (even if aliased) */
michael@0 4081
michael@0 4082 #if DECTRACE
michael@0 4083 decDumpAr('A', lhs->lsu, D2U(lhs->digits));
michael@0 4084 decDumpAr('B', rhs->lsu, D2U(rhs->digits));
michael@0 4085 printf(" :h: %ld %ld\n", rhsshift, mult);
michael@0 4086 #endif
michael@0 4087
michael@0 4088 /* add [A+B*m] or subtract [A+B*(-m)] */
michael@0 4089 U_ASSERT(rhs->digits > 0);
michael@0 4090 U_ASSERT(lhs->digits > 0);
michael@0 4091 res->digits=decUnitAddSub(lhs->lsu, D2U(lhs->digits),
michael@0 4092 rhs->lsu, D2U(rhs->digits),
michael@0 4093 rhsshift, acc, mult)
michael@0 4094 *DECDPUN; /* [units -> digits] */
michael@0 4095 if (res->digits<0) { /* borrowed... */
michael@0 4096 res->digits=-res->digits;
michael@0 4097 res->bits^=DECNEG; /* flip the sign */
michael@0 4098 }
michael@0 4099 #if DECTRACE
michael@0 4100 decDumpAr('+', acc, D2U(res->digits));
michael@0 4101 #endif
michael@0 4102
michael@0 4103 /* If a buffer was used the result must be copied back, possibly */
michael@0 4104 /* shortening. (If no buffer was used then the result must have */
michael@0 4105 /* fit, so can't need rounding and residue must be 0.) */
michael@0 4106 residue=0; /* clear accumulator */
michael@0 4107 if (acc!=res->lsu) {
michael@0 4108 #if DECSUBSET
michael@0 4109 if (set->extended) { /* round from first significant digit */
michael@0 4110 #endif
michael@0 4111 /* remove leading zeros that were added due to rounding up to */
michael@0 4112 /* integral Units -- before the test for rounding. */
michael@0 4113 if (res->digits>reqdigits)
michael@0 4114 res->digits=decGetDigits(acc, D2U(res->digits));
michael@0 4115 decSetCoeff(res, set, acc, res->digits, &residue, status);
michael@0 4116 #if DECSUBSET
michael@0 4117 }
michael@0 4118 else { /* subset arithmetic rounds from original significant digit */
michael@0 4119 /* May have an underestimate. This only occurs when both */
michael@0 4120 /* numbers fit in DECDPUN digits and are padding with a */
michael@0 4121 /* negative multiple (-10, -100...) and the top digit(s) become */
michael@0 4122 /* 0. (This only matters when using X3.274 rules where the */
michael@0 4123 /* leading zero could be included in the rounding.) */
michael@0 4124 if (res->digits<maxdigits) {
michael@0 4125 *(acc+D2U(res->digits))=0; /* ensure leading 0 is there */
michael@0 4126 res->digits=maxdigits;
michael@0 4127 }
michael@0 4128 else {
michael@0 4129 /* remove leading zeros that added due to rounding up to */
michael@0 4130 /* integral Units (but only those in excess of the original */
michael@0 4131 /* maxdigits length, unless extended) before test for rounding. */
michael@0 4132 if (res->digits>reqdigits) {
michael@0 4133 res->digits=decGetDigits(acc, D2U(res->digits));
michael@0 4134 if (res->digits<maxdigits) res->digits=maxdigits;
michael@0 4135 }
michael@0 4136 }
michael@0 4137 decSetCoeff(res, set, acc, res->digits, &residue, status);
michael@0 4138 /* Now apply rounding if needed before removing leading zeros. */
michael@0 4139 /* This is safe because subnormals are not a possibility */
michael@0 4140 if (residue!=0) {
michael@0 4141 decApplyRound(res, set, residue, status);
michael@0 4142 residue=0; /* did what needed to be done */
michael@0 4143 }
michael@0 4144 } /* subset */
michael@0 4145 #endif
michael@0 4146 } /* used buffer */
michael@0 4147
michael@0 4148 /* strip leading zeros [these were left on in case of subset subtract] */
michael@0 4149 res->digits=decGetDigits(res->lsu, D2U(res->digits));
michael@0 4150
michael@0 4151 /* apply checks and rounding */
michael@0 4152 decFinish(res, set, &residue, status);
michael@0 4153
michael@0 4154 /* "When the sum of two operands with opposite signs is exactly */
michael@0 4155 /* zero, the sign of that sum shall be '+' in all rounding modes */
michael@0 4156 /* except round toward -Infinity, in which mode that sign shall be */
michael@0 4157 /* '-'." [Subset zeros also never have '-', set by decFinish.] */
michael@0 4158 if (ISZERO(res) && diffsign
michael@0 4159 #if DECSUBSET
michael@0 4160 && set->extended
michael@0 4161 #endif
michael@0 4162 && (*status&DEC_Inexact)==0) {
michael@0 4163 if (set->round==DEC_ROUND_FLOOR) res->bits|=DECNEG; /* sign - */
michael@0 4164 else res->bits&=~DECNEG; /* sign + */
michael@0 4165 }
michael@0 4166 } while(0); /* end protected */
michael@0 4167
michael@0 4168 if (allocacc!=NULL) free(allocacc); /* drop any storage used */
michael@0 4169 #if DECSUBSET
michael@0 4170 if (allocrhs!=NULL) free(allocrhs); /* .. */
michael@0 4171 if (alloclhs!=NULL) free(alloclhs); /* .. */
michael@0 4172 #endif
michael@0 4173 return res;
michael@0 4174 } /* decAddOp */
michael@0 4175
michael@0 4176 /* ------------------------------------------------------------------ */
michael@0 4177 /* decDivideOp -- division operation */
michael@0 4178 /* */
michael@0 4179 /* This routine performs the calculations for all four division */
michael@0 4180 /* operators (divide, divideInteger, remainder, remainderNear). */
michael@0 4181 /* */
michael@0 4182 /* C=A op B */
michael@0 4183 /* */
michael@0 4184 /* res is C, the result. C may be A and/or B (e.g., X=X/X) */
michael@0 4185 /* lhs is A */
michael@0 4186 /* rhs is B */
michael@0 4187 /* set is the context */
michael@0 4188 /* op is DIVIDE, DIVIDEINT, REMAINDER, or REMNEAR respectively. */
michael@0 4189 /* status is the usual accumulator */
michael@0 4190 /* */
michael@0 4191 /* C must have space for set->digits digits. */
michael@0 4192 /* */
michael@0 4193 /* ------------------------------------------------------------------ */
michael@0 4194 /* The underlying algorithm of this routine is the same as in the */
michael@0 4195 /* 1981 S/370 implementation, that is, non-restoring long division */
michael@0 4196 /* with bi-unit (rather than bi-digit) estimation for each unit */
michael@0 4197 /* multiplier. In this pseudocode overview, complications for the */
michael@0 4198 /* Remainder operators and division residues for exact rounding are */
michael@0 4199 /* omitted for clarity. */
michael@0 4200 /* */
michael@0 4201 /* Prepare operands and handle special values */
michael@0 4202 /* Test for x/0 and then 0/x */
michael@0 4203 /* Exp =Exp1 - Exp2 */
michael@0 4204 /* Exp =Exp +len(var1) -len(var2) */
michael@0 4205 /* Sign=Sign1 * Sign2 */
michael@0 4206 /* Pad accumulator (Var1) to double-length with 0's (pad1) */
michael@0 4207 /* Pad Var2 to same length as Var1 */
michael@0 4208 /* msu2pair/plus=1st 2 or 1 units of var2, +1 to allow for round */
michael@0 4209 /* have=0 */
michael@0 4210 /* Do until (have=digits+1 OR residue=0) */
michael@0 4211 /* if exp<0 then if integer divide/residue then leave */
michael@0 4212 /* this_unit=0 */
michael@0 4213 /* Do forever */
michael@0 4214 /* compare numbers */
michael@0 4215 /* if <0 then leave inner_loop */
michael@0 4216 /* if =0 then (* quick exit without subtract *) do */
michael@0 4217 /* this_unit=this_unit+1; output this_unit */
michael@0 4218 /* leave outer_loop; end */
michael@0 4219 /* Compare lengths of numbers (mantissae): */
michael@0 4220 /* If same then tops2=msu2pair -- {units 1&2 of var2} */
michael@0 4221 /* else tops2=msu2plus -- {0, unit 1 of var2} */
michael@0 4222 /* tops1=first_unit_of_Var1*10**DECDPUN +second_unit_of_var1 */
michael@0 4223 /* mult=tops1/tops2 -- Good and safe guess at divisor */
michael@0 4224 /* if mult=0 then mult=1 */
michael@0 4225 /* this_unit=this_unit+mult */
michael@0 4226 /* subtract */
michael@0 4227 /* end inner_loop */
michael@0 4228 /* if have\=0 | this_unit\=0 then do */
michael@0 4229 /* output this_unit */
michael@0 4230 /* have=have+1; end */
michael@0 4231 /* var2=var2/10 */
michael@0 4232 /* exp=exp-1 */
michael@0 4233 /* end outer_loop */
michael@0 4234 /* exp=exp+1 -- set the proper exponent */
michael@0 4235 /* if have=0 then generate answer=0 */
michael@0 4236 /* Return (Result is defined by Var1) */
michael@0 4237 /* */
michael@0 4238 /* ------------------------------------------------------------------ */
michael@0 4239 /* Two working buffers are needed during the division; one (digits+ */
michael@0 4240 /* 1) to accumulate the result, and the other (up to 2*digits+1) for */
michael@0 4241 /* long subtractions. These are acc and var1 respectively. */
michael@0 4242 /* var1 is a copy of the lhs coefficient, var2 is the rhs coefficient.*/
michael@0 4243 /* The static buffers may be larger than might be expected to allow */
michael@0 4244 /* for calls from higher-level funtions (notable exp). */
michael@0 4245 /* ------------------------------------------------------------------ */
michael@0 4246 static decNumber * decDivideOp(decNumber *res,
michael@0 4247 const decNumber *lhs, const decNumber *rhs,
michael@0 4248 decContext *set, Flag op, uInt *status) {
michael@0 4249 #if DECSUBSET
michael@0 4250 decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */
michael@0 4251 decNumber *allocrhs=NULL; /* .., rhs */
michael@0 4252 #endif
michael@0 4253 Unit accbuff[SD2U(DECBUFFER+DECDPUN+10)]; /* local buffer */
michael@0 4254 Unit *acc=accbuff; /* -> accumulator array for result */
michael@0 4255 Unit *allocacc=NULL; /* -> allocated buffer, iff allocated */
michael@0 4256 Unit *accnext; /* -> where next digit will go */
michael@0 4257 Int acclength; /* length of acc needed [Units] */
michael@0 4258 Int accunits; /* count of units accumulated */
michael@0 4259 Int accdigits; /* count of digits accumulated */
michael@0 4260
michael@0 4261 Unit varbuff[SD2U(DECBUFFER*2+DECDPUN)]; /* buffer for var1 */
michael@0 4262 Unit *var1=varbuff; /* -> var1 array for long subtraction */
michael@0 4263 Unit *varalloc=NULL; /* -> allocated buffer, iff used */
michael@0 4264 Unit *msu1; /* -> msu of var1 */
michael@0 4265
michael@0 4266 const Unit *var2; /* -> var2 array */
michael@0 4267 const Unit *msu2; /* -> msu of var2 */
michael@0 4268 Int msu2plus; /* msu2 plus one [does not vary] */
michael@0 4269 eInt msu2pair; /* msu2 pair plus one [does not vary] */
michael@0 4270
michael@0 4271 Int var1units, var2units; /* actual lengths */
michael@0 4272 Int var2ulen; /* logical length (units) */
michael@0 4273 Int var1initpad=0; /* var1 initial padding (digits) */
michael@0 4274 Int maxdigits; /* longest LHS or required acc length */
michael@0 4275 Int mult; /* multiplier for subtraction */
michael@0 4276 Unit thisunit; /* current unit being accumulated */
michael@0 4277 Int residue; /* for rounding */
michael@0 4278 Int reqdigits=set->digits; /* requested DIGITS */
michael@0 4279 Int exponent; /* working exponent */
michael@0 4280 Int maxexponent=0; /* DIVIDE maximum exponent if unrounded */
michael@0 4281 uByte bits; /* working sign */
michael@0 4282 Unit *target; /* work */
michael@0 4283 const Unit *source; /* .. */
michael@0 4284 uInt const *pow; /* .. */
michael@0 4285 Int shift, cut; /* .. */
michael@0 4286 #if DECSUBSET
michael@0 4287 Int dropped; /* work */
michael@0 4288 #endif
michael@0 4289
michael@0 4290 #if DECCHECK
michael@0 4291 if (decCheckOperands(res, lhs, rhs, set)) return res;
michael@0 4292 #endif
michael@0 4293
michael@0 4294 do { /* protect allocated storage */
michael@0 4295 #if DECSUBSET
michael@0 4296 if (!set->extended) {
michael@0 4297 /* reduce operands and set lostDigits status, as needed */
michael@0 4298 if (lhs->digits>reqdigits) {
michael@0 4299 alloclhs=decRoundOperand(lhs, set, status);
michael@0 4300 if (alloclhs==NULL) break;
michael@0 4301 lhs=alloclhs;
michael@0 4302 }
michael@0 4303 if (rhs->digits>reqdigits) {
michael@0 4304 allocrhs=decRoundOperand(rhs, set, status);
michael@0 4305 if (allocrhs==NULL) break;
michael@0 4306 rhs=allocrhs;
michael@0 4307 }
michael@0 4308 }
michael@0 4309 #endif
michael@0 4310 /* [following code does not require input rounding] */
michael@0 4311
michael@0 4312 bits=(lhs->bits^rhs->bits)&DECNEG; /* assumed sign for divisions */
michael@0 4313
michael@0 4314 /* handle infinities and NaNs */
michael@0 4315 if (SPECIALARGS) { /* a special bit set */
michael@0 4316 if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */
michael@0 4317 decNaNs(res, lhs, rhs, set, status);
michael@0 4318 break;
michael@0 4319 }
michael@0 4320 /* one or two infinities */
michael@0 4321 if (decNumberIsInfinite(lhs)) { /* LHS (dividend) is infinite */
michael@0 4322 if (decNumberIsInfinite(rhs) || /* two infinities are invalid .. */
michael@0 4323 op & (REMAINDER | REMNEAR)) { /* as is remainder of infinity */
michael@0 4324 *status|=DEC_Invalid_operation;
michael@0 4325 break;
michael@0 4326 }
michael@0 4327 /* [Note that infinity/0 raises no exceptions] */
michael@0 4328 uprv_decNumberZero(res);
michael@0 4329 res->bits=bits|DECINF; /* set +/- infinity */
michael@0 4330 break;
michael@0 4331 }
michael@0 4332 else { /* RHS (divisor) is infinite */
michael@0 4333 residue=0;
michael@0 4334 if (op&(REMAINDER|REMNEAR)) {
michael@0 4335 /* result is [finished clone of] lhs */
michael@0 4336 decCopyFit(res, lhs, set, &residue, status);
michael@0 4337 }
michael@0 4338 else { /* a division */
michael@0 4339 uprv_decNumberZero(res);
michael@0 4340 res->bits=bits; /* set +/- zero */
michael@0 4341 /* for DIVIDEINT the exponent is always 0. For DIVIDE, result */
michael@0 4342 /* is a 0 with infinitely negative exponent, clamped to minimum */
michael@0 4343 if (op&DIVIDE) {
michael@0 4344 res->exponent=set->emin-set->digits+1;
michael@0 4345 *status|=DEC_Clamped;
michael@0 4346 }
michael@0 4347 }
michael@0 4348 decFinish(res, set, &residue, status);
michael@0 4349 break;
michael@0 4350 }
michael@0 4351 }
michael@0 4352
michael@0 4353 /* handle 0 rhs (x/0) */
michael@0 4354 if (ISZERO(rhs)) { /* x/0 is always exceptional */
michael@0 4355 if (ISZERO(lhs)) {
michael@0 4356 uprv_decNumberZero(res); /* [after lhs test] */
michael@0 4357 *status|=DEC_Division_undefined;/* 0/0 will become NaN */
michael@0 4358 }
michael@0 4359 else {
michael@0 4360 uprv_decNumberZero(res);
michael@0 4361 if (op&(REMAINDER|REMNEAR)) *status|=DEC_Invalid_operation;
michael@0 4362 else {
michael@0 4363 *status|=DEC_Division_by_zero; /* x/0 */
michael@0 4364 res->bits=bits|DECINF; /* .. is +/- Infinity */
michael@0 4365 }
michael@0 4366 }
michael@0 4367 break;}
michael@0 4368
michael@0 4369 /* handle 0 lhs (0/x) */
michael@0 4370 if (ISZERO(lhs)) { /* 0/x [x!=0] */
michael@0 4371 #if DECSUBSET
michael@0 4372 if (!set->extended) uprv_decNumberZero(res);
michael@0 4373 else {
michael@0 4374 #endif
michael@0 4375 if (op&DIVIDE) {
michael@0 4376 residue=0;
michael@0 4377 exponent=lhs->exponent-rhs->exponent; /* ideal exponent */
michael@0 4378 uprv_decNumberCopy(res, lhs); /* [zeros always fit] */
michael@0 4379 res->bits=bits; /* sign as computed */
michael@0 4380 res->exponent=exponent; /* exponent, too */
michael@0 4381 decFinalize(res, set, &residue, status); /* check exponent */
michael@0 4382 }
michael@0 4383 else if (op&DIVIDEINT) {
michael@0 4384 uprv_decNumberZero(res); /* integer 0 */
michael@0 4385 res->bits=bits; /* sign as computed */
michael@0 4386 }
michael@0 4387 else { /* a remainder */
michael@0 4388 exponent=rhs->exponent; /* [save in case overwrite] */
michael@0 4389 uprv_decNumberCopy(res, lhs); /* [zeros always fit] */
michael@0 4390 if (exponent<res->exponent) res->exponent=exponent; /* use lower */
michael@0 4391 }
michael@0 4392 #if DECSUBSET
michael@0 4393 }
michael@0 4394 #endif
michael@0 4395 break;}
michael@0 4396
michael@0 4397 /* Precalculate exponent. This starts off adjusted (and hence fits */
michael@0 4398 /* in 31 bits) and becomes the usual unadjusted exponent as the */
michael@0 4399 /* division proceeds. The order of evaluation is important, here, */
michael@0 4400 /* to avoid wrap. */
michael@0 4401 exponent=(lhs->exponent+lhs->digits)-(rhs->exponent+rhs->digits);
michael@0 4402
michael@0 4403 /* If the working exponent is -ve, then some quick exits are */
michael@0 4404 /* possible because the quotient is known to be <1 */
michael@0 4405 /* [for REMNEAR, it needs to be < -1, as -0.5 could need work] */
michael@0 4406 if (exponent<0 && !(op==DIVIDE)) {
michael@0 4407 if (op&DIVIDEINT) {
michael@0 4408 uprv_decNumberZero(res); /* integer part is 0 */
michael@0 4409 #if DECSUBSET
michael@0 4410 if (set->extended)
michael@0 4411 #endif
michael@0 4412 res->bits=bits; /* set +/- zero */
michael@0 4413 break;}
michael@0 4414 /* fastpath remainders so long as the lhs has the smaller */
michael@0 4415 /* (or equal) exponent */
michael@0 4416 if (lhs->exponent<=rhs->exponent) {
michael@0 4417 if (op&REMAINDER || exponent<-1) {
michael@0 4418 /* It is REMAINDER or safe REMNEAR; result is [finished */
michael@0 4419 /* clone of] lhs (r = x - 0*y) */
michael@0 4420 residue=0;
michael@0 4421 decCopyFit(res, lhs, set, &residue, status);
michael@0 4422 decFinish(res, set, &residue, status);
michael@0 4423 break;
michael@0 4424 }
michael@0 4425 /* [unsafe REMNEAR drops through] */
michael@0 4426 }
michael@0 4427 } /* fastpaths */
michael@0 4428
michael@0 4429 /* Long (slow) division is needed; roll up the sleeves... */
michael@0 4430
michael@0 4431 /* The accumulator will hold the quotient of the division. */
michael@0 4432 /* If it needs to be too long for stack storage, then allocate. */
michael@0 4433 acclength=D2U(reqdigits+DECDPUN); /* in Units */
michael@0 4434 if (acclength*sizeof(Unit)>sizeof(accbuff)) {
michael@0 4435 /* printf("malloc dvacc %ld units\n", acclength); */
michael@0 4436 allocacc=(Unit *)malloc(acclength*sizeof(Unit));
michael@0 4437 if (allocacc==NULL) { /* hopeless -- abandon */
michael@0 4438 *status|=DEC_Insufficient_storage;
michael@0 4439 break;}
michael@0 4440 acc=allocacc; /* use the allocated space */
michael@0 4441 }
michael@0 4442
michael@0 4443 /* var1 is the padded LHS ready for subtractions. */
michael@0 4444 /* If it needs to be too long for stack storage, then allocate. */
michael@0 4445 /* The maximum units needed for var1 (long subtraction) is: */
michael@0 4446 /* Enough for */
michael@0 4447 /* (rhs->digits+reqdigits-1) -- to allow full slide to right */
michael@0 4448 /* or (lhs->digits) -- to allow for long lhs */
michael@0 4449 /* whichever is larger */
michael@0 4450 /* +1 -- for rounding of slide to right */
michael@0 4451 /* +1 -- for leading 0s */
michael@0 4452 /* +1 -- for pre-adjust if a remainder or DIVIDEINT */
michael@0 4453 /* [Note: unused units do not participate in decUnitAddSub data] */
michael@0 4454 maxdigits=rhs->digits+reqdigits-1;
michael@0 4455 if (lhs->digits>maxdigits) maxdigits=lhs->digits;
michael@0 4456 var1units=D2U(maxdigits)+2;
michael@0 4457 /* allocate a guard unit above msu1 for REMAINDERNEAR */
michael@0 4458 if (!(op&DIVIDE)) var1units++;
michael@0 4459 if ((var1units+1)*sizeof(Unit)>sizeof(varbuff)) {
michael@0 4460 /* printf("malloc dvvar %ld units\n", var1units+1); */
michael@0 4461 varalloc=(Unit *)malloc((var1units+1)*sizeof(Unit));
michael@0 4462 if (varalloc==NULL) { /* hopeless -- abandon */
michael@0 4463 *status|=DEC_Insufficient_storage;
michael@0 4464 break;}
michael@0 4465 var1=varalloc; /* use the allocated space */
michael@0 4466 }
michael@0 4467
michael@0 4468 /* Extend the lhs and rhs to full long subtraction length. The lhs */
michael@0 4469 /* is truly extended into the var1 buffer, with 0 padding, so a */
michael@0 4470 /* subtract in place is always possible. The rhs (var2) has */
michael@0 4471 /* virtual padding (implemented by decUnitAddSub). */
michael@0 4472 /* One guard unit was allocated above msu1 for rem=rem+rem in */
michael@0 4473 /* REMAINDERNEAR. */
michael@0 4474 msu1=var1+var1units-1; /* msu of var1 */
michael@0 4475 source=lhs->lsu+D2U(lhs->digits)-1; /* msu of input array */
michael@0 4476 for (target=msu1; source>=lhs->lsu; source--, target--) *target=*source;
michael@0 4477 for (; target>=var1; target--) *target=0;
michael@0 4478
michael@0 4479 /* rhs (var2) is left-aligned with var1 at the start */
michael@0 4480 var2ulen=var1units; /* rhs logical length (units) */
michael@0 4481 var2units=D2U(rhs->digits); /* rhs actual length (units) */
michael@0 4482 var2=rhs->lsu; /* -> rhs array */
michael@0 4483 msu2=var2+var2units-1; /* -> msu of var2 [never changes] */
michael@0 4484 /* now set up the variables which will be used for estimating the */
michael@0 4485 /* multiplication factor. If these variables are not exact, add */
michael@0 4486 /* 1 to make sure that the multiplier is never overestimated. */
michael@0 4487 msu2plus=*msu2; /* it's value .. */
michael@0 4488 if (var2units>1) msu2plus++; /* .. +1 if any more */
michael@0 4489 msu2pair=(eInt)*msu2*(DECDPUNMAX+1);/* top two pair .. */
michael@0 4490 if (var2units>1) { /* .. [else treat 2nd as 0] */
michael@0 4491 msu2pair+=*(msu2-1); /* .. */
michael@0 4492 if (var2units>2) msu2pair++; /* .. +1 if any more */
michael@0 4493 }
michael@0 4494
michael@0 4495 /* The calculation is working in units, which may have leading zeros, */
michael@0 4496 /* but the exponent was calculated on the assumption that they are */
michael@0 4497 /* both left-aligned. Adjust the exponent to compensate: add the */
michael@0 4498 /* number of leading zeros in var1 msu and subtract those in var2 msu. */
michael@0 4499 /* [This is actually done by counting the digits and negating, as */
michael@0 4500 /* lead1=DECDPUN-digits1, and similarly for lead2.] */
michael@0 4501 for (pow=&powers[1]; *msu1>=*pow; pow++) exponent--;
michael@0 4502 for (pow=&powers[1]; *msu2>=*pow; pow++) exponent++;
michael@0 4503
michael@0 4504 /* Now, if doing an integer divide or remainder, ensure that */
michael@0 4505 /* the result will be Unit-aligned. To do this, shift the var1 */
michael@0 4506 /* accumulator towards least if need be. (It's much easier to */
michael@0 4507 /* do this now than to reassemble the residue afterwards, if */
michael@0 4508 /* doing a remainder.) Also ensure the exponent is not negative. */
michael@0 4509 if (!(op&DIVIDE)) {
michael@0 4510 Unit *u; /* work */
michael@0 4511 /* save the initial 'false' padding of var1, in digits */
michael@0 4512 var1initpad=(var1units-D2U(lhs->digits))*DECDPUN;
michael@0 4513 /* Determine the shift to do. */
michael@0 4514 if (exponent<0) cut=-exponent;
michael@0 4515 else cut=DECDPUN-exponent%DECDPUN;
michael@0 4516 decShiftToLeast(var1, var1units, cut);
michael@0 4517 exponent+=cut; /* maintain numerical value */
michael@0 4518 var1initpad-=cut; /* .. and reduce padding */
michael@0 4519 /* clean any most-significant units which were just emptied */
michael@0 4520 for (u=msu1; cut>=DECDPUN; cut-=DECDPUN, u--) *u=0;
michael@0 4521 } /* align */
michael@0 4522 else { /* is DIVIDE */
michael@0 4523 maxexponent=lhs->exponent-rhs->exponent; /* save */
michael@0 4524 /* optimization: if the first iteration will just produce 0, */
michael@0 4525 /* preadjust to skip it [valid for DIVIDE only] */
michael@0 4526 if (*msu1<*msu2) {
michael@0 4527 var2ulen--; /* shift down */
michael@0 4528 exponent-=DECDPUN; /* update the exponent */
michael@0 4529 }
michael@0 4530 }
michael@0 4531
michael@0 4532 /* ---- start the long-division loops ------------------------------ */
michael@0 4533 accunits=0; /* no units accumulated yet */
michael@0 4534 accdigits=0; /* .. or digits */
michael@0 4535 accnext=acc+acclength-1; /* -> msu of acc [NB: allows digits+1] */
michael@0 4536 for (;;) { /* outer forever loop */
michael@0 4537 thisunit=0; /* current unit assumed 0 */
michael@0 4538 /* find the next unit */
michael@0 4539 for (;;) { /* inner forever loop */
michael@0 4540 /* strip leading zero units [from either pre-adjust or from */
michael@0 4541 /* subtract last time around]. Leave at least one unit. */
michael@0 4542 for (; *msu1==0 && msu1>var1; msu1--) var1units--;
michael@0 4543
michael@0 4544 if (var1units<var2ulen) break; /* var1 too low for subtract */
michael@0 4545 if (var1units==var2ulen) { /* unit-by-unit compare needed */
michael@0 4546 /* compare the two numbers, from msu */
michael@0 4547 const Unit *pv1, *pv2;
michael@0 4548 Unit v2; /* units to compare */
michael@0 4549 pv2=msu2; /* -> msu */
michael@0 4550 for (pv1=msu1; ; pv1--, pv2--) {
michael@0 4551 /* v1=*pv1 -- always OK */
michael@0 4552 v2=0; /* assume in padding */
michael@0 4553 if (pv2>=var2) v2=*pv2; /* in range */
michael@0 4554 if (*pv1!=v2) break; /* no longer the same */
michael@0 4555 if (pv1==var1) break; /* done; leave pv1 as is */
michael@0 4556 }
michael@0 4557 /* here when all inspected or a difference seen */
michael@0 4558 if (*pv1<v2) break; /* var1 too low to subtract */
michael@0 4559 if (*pv1==v2) { /* var1 == var2 */
michael@0 4560 /* reach here if var1 and var2 are identical; subtraction */
michael@0 4561 /* would increase digit by one, and the residue will be 0 so */
michael@0 4562 /* the calculation is done; leave the loop with residue=0. */
michael@0 4563 thisunit++; /* as though subtracted */
michael@0 4564 *var1=0; /* set var1 to 0 */
michael@0 4565 var1units=1; /* .. */
michael@0 4566 break; /* from inner */
michael@0 4567 } /* var1 == var2 */
michael@0 4568 /* *pv1>v2. Prepare for real subtraction; the lengths are equal */
michael@0 4569 /* Estimate the multiplier (there's always a msu1-1)... */
michael@0 4570 /* Bring in two units of var2 to provide a good estimate. */
michael@0 4571 mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2pair);
michael@0 4572 } /* lengths the same */
michael@0 4573 else { /* var1units > var2ulen, so subtraction is safe */
michael@0 4574 /* The var2 msu is one unit towards the lsu of the var1 msu, */
michael@0 4575 /* so only one unit for var2 can be used. */
michael@0 4576 mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2plus);
michael@0 4577 }
michael@0 4578 if (mult==0) mult=1; /* must always be at least 1 */
michael@0 4579 /* subtraction needed; var1 is > var2 */
michael@0 4580 thisunit=(Unit)(thisunit+mult); /* accumulate */
michael@0 4581 /* subtract var1-var2, into var1; only the overlap needs */
michael@0 4582 /* processing, as this is an in-place calculation */
michael@0 4583 shift=var2ulen-var2units;
michael@0 4584 #if DECTRACE
michael@0 4585 decDumpAr('1', &var1[shift], var1units-shift);
michael@0 4586 decDumpAr('2', var2, var2units);
michael@0 4587 printf("m=%ld\n", -mult);
michael@0 4588 #endif
michael@0 4589 decUnitAddSub(&var1[shift], var1units-shift,
michael@0 4590 var2, var2units, 0,
michael@0 4591 &var1[shift], -mult);
michael@0 4592 #if DECTRACE
michael@0 4593 decDumpAr('#', &var1[shift], var1units-shift);
michael@0 4594 #endif
michael@0 4595 /* var1 now probably has leading zeros; these are removed at the */
michael@0 4596 /* top of the inner loop. */
michael@0 4597 } /* inner loop */
michael@0 4598
michael@0 4599 /* The next unit has been calculated in full; unless it's a */
michael@0 4600 /* leading zero, add to acc */
michael@0 4601 if (accunits!=0 || thisunit!=0) { /* is first or non-zero */
michael@0 4602 *accnext=thisunit; /* store in accumulator */
michael@0 4603 /* account exactly for the new digits */
michael@0 4604 if (accunits==0) {
michael@0 4605 accdigits++; /* at least one */
michael@0 4606 for (pow=&powers[1]; thisunit>=*pow; pow++) accdigits++;
michael@0 4607 }
michael@0 4608 else accdigits+=DECDPUN;
michael@0 4609 accunits++; /* update count */
michael@0 4610 accnext--; /* ready for next */
michael@0 4611 if (accdigits>reqdigits) break; /* have enough digits */
michael@0 4612 }
michael@0 4613
michael@0 4614 /* if the residue is zero, the operation is done (unless divide */
michael@0 4615 /* or divideInteger and still not enough digits yet) */
michael@0 4616 if (*var1==0 && var1units==1) { /* residue is 0 */
michael@0 4617 if (op&(REMAINDER|REMNEAR)) break;
michael@0 4618 if ((op&DIVIDE) && (exponent<=maxexponent)) break;
michael@0 4619 /* [drop through if divideInteger] */
michael@0 4620 }
michael@0 4621 /* also done enough if calculating remainder or integer */
michael@0 4622 /* divide and just did the last ('units') unit */
michael@0 4623 if (exponent==0 && !(op&DIVIDE)) break;
michael@0 4624
michael@0 4625 /* to get here, var1 is less than var2, so divide var2 by the per- */
michael@0 4626 /* Unit power of ten and go for the next digit */
michael@0 4627 var2ulen--; /* shift down */
michael@0 4628 exponent-=DECDPUN; /* update the exponent */
michael@0 4629 } /* outer loop */
michael@0 4630
michael@0 4631 /* ---- division is complete --------------------------------------- */
michael@0 4632 /* here: acc has at least reqdigits+1 of good results (or fewer */
michael@0 4633 /* if early stop), starting at accnext+1 (its lsu) */
michael@0 4634 /* var1 has any residue at the stopping point */
michael@0 4635 /* accunits is the number of digits collected in acc */
michael@0 4636 if (accunits==0) { /* acc is 0 */
michael@0 4637 accunits=1; /* show have a unit .. */
michael@0 4638 accdigits=1; /* .. */
michael@0 4639 *accnext=0; /* .. whose value is 0 */
michael@0 4640 }
michael@0 4641 else accnext++; /* back to last placed */
michael@0 4642 /* accnext now -> lowest unit of result */
michael@0 4643
michael@0 4644 residue=0; /* assume no residue */
michael@0 4645 if (op&DIVIDE) {
michael@0 4646 /* record the presence of any residue, for rounding */
michael@0 4647 if (*var1!=0 || var1units>1) residue=1;
michael@0 4648 else { /* no residue */
michael@0 4649 /* Had an exact division; clean up spurious trailing 0s. */
michael@0 4650 /* There will be at most DECDPUN-1, from the final multiply, */
michael@0 4651 /* and then only if the result is non-0 (and even) and the */
michael@0 4652 /* exponent is 'loose'. */
michael@0 4653 #if DECDPUN>1
michael@0 4654 Unit lsu=*accnext;
michael@0 4655 if (!(lsu&0x01) && (lsu!=0)) {
michael@0 4656 /* count the trailing zeros */
michael@0 4657 Int drop=0;
michael@0 4658 for (;; drop++) { /* [will terminate because lsu!=0] */
michael@0 4659 if (exponent>=maxexponent) break; /* don't chop real 0s */
michael@0 4660 #if DECDPUN<=4
michael@0 4661 if ((lsu-QUOT10(lsu, drop+1)
michael@0 4662 *powers[drop+1])!=0) break; /* found non-0 digit */
michael@0 4663 #else
michael@0 4664 if (lsu%powers[drop+1]!=0) break; /* found non-0 digit */
michael@0 4665 #endif
michael@0 4666 exponent++;
michael@0 4667 }
michael@0 4668 if (drop>0) {
michael@0 4669 accunits=decShiftToLeast(accnext, accunits, drop);
michael@0 4670 accdigits=decGetDigits(accnext, accunits);
michael@0 4671 accunits=D2U(accdigits);
michael@0 4672 /* [exponent was adjusted in the loop] */
michael@0 4673 }
michael@0 4674 } /* neither odd nor 0 */
michael@0 4675 #endif
michael@0 4676 } /* exact divide */
michael@0 4677 } /* divide */
michael@0 4678 else /* op!=DIVIDE */ {
michael@0 4679 /* check for coefficient overflow */
michael@0 4680 if (accdigits+exponent>reqdigits) {
michael@0 4681 *status|=DEC_Division_impossible;
michael@0 4682 break;
michael@0 4683 }
michael@0 4684 if (op & (REMAINDER|REMNEAR)) {
michael@0 4685 /* [Here, the exponent will be 0, because var1 was adjusted */
michael@0 4686 /* appropriately.] */
michael@0 4687 Int postshift; /* work */
michael@0 4688 Flag wasodd=0; /* integer was odd */
michael@0 4689 Unit *quotlsu; /* for save */
michael@0 4690 Int quotdigits; /* .. */
michael@0 4691
michael@0 4692 bits=lhs->bits; /* remainder sign is always as lhs */
michael@0 4693
michael@0 4694 /* Fastpath when residue is truly 0 is worthwhile [and */
michael@0 4695 /* simplifies the code below] */
michael@0 4696 if (*var1==0 && var1units==1) { /* residue is 0 */
michael@0 4697 Int exp=lhs->exponent; /* save min(exponents) */
michael@0 4698 if (rhs->exponent<exp) exp=rhs->exponent;
michael@0 4699 uprv_decNumberZero(res); /* 0 coefficient */
michael@0 4700 #if DECSUBSET
michael@0 4701 if (set->extended)
michael@0 4702 #endif
michael@0 4703 res->exponent=exp; /* .. with proper exponent */
michael@0 4704 res->bits=(uByte)(bits&DECNEG); /* [cleaned] */
michael@0 4705 decFinish(res, set, &residue, status); /* might clamp */
michael@0 4706 break;
michael@0 4707 }
michael@0 4708 /* note if the quotient was odd */
michael@0 4709 if (*accnext & 0x01) wasodd=1; /* acc is odd */
michael@0 4710 quotlsu=accnext; /* save in case need to reinspect */
michael@0 4711 quotdigits=accdigits; /* .. */
michael@0 4712
michael@0 4713 /* treat the residue, in var1, as the value to return, via acc */
michael@0 4714 /* calculate the unused zero digits. This is the smaller of: */
michael@0 4715 /* var1 initial padding (saved above) */
michael@0 4716 /* var2 residual padding, which happens to be given by: */
michael@0 4717 postshift=var1initpad+exponent-lhs->exponent+rhs->exponent;
michael@0 4718 /* [the 'exponent' term accounts for the shifts during divide] */
michael@0 4719 if (var1initpad<postshift) postshift=var1initpad;
michael@0 4720
michael@0 4721 /* shift var1 the requested amount, and adjust its digits */
michael@0 4722 var1units=decShiftToLeast(var1, var1units, postshift);
michael@0 4723 accnext=var1;
michael@0 4724 accdigits=decGetDigits(var1, var1units);
michael@0 4725 accunits=D2U(accdigits);
michael@0 4726
michael@0 4727 exponent=lhs->exponent; /* exponent is smaller of lhs & rhs */
michael@0 4728 if (rhs->exponent<exponent) exponent=rhs->exponent;
michael@0 4729
michael@0 4730 /* Now correct the result if doing remainderNear; if it */
michael@0 4731 /* (looking just at coefficients) is > rhs/2, or == rhs/2 and */
michael@0 4732 /* the integer was odd then the result should be rem-rhs. */
michael@0 4733 if (op&REMNEAR) {
michael@0 4734 Int compare, tarunits; /* work */
michael@0 4735 Unit *up; /* .. */
michael@0 4736 /* calculate remainder*2 into the var1 buffer (which has */
michael@0 4737 /* 'headroom' of an extra unit and hence enough space) */
michael@0 4738 /* [a dedicated 'double' loop would be faster, here] */
michael@0 4739 tarunits=decUnitAddSub(accnext, accunits, accnext, accunits,
michael@0 4740 0, accnext, 1);
michael@0 4741 /* decDumpAr('r', accnext, tarunits); */
michael@0 4742
michael@0 4743 /* Here, accnext (var1) holds tarunits Units with twice the */
michael@0 4744 /* remainder's coefficient, which must now be compared to the */
michael@0 4745 /* RHS. The remainder's exponent may be smaller than the RHS's. */
michael@0 4746 compare=decUnitCompare(accnext, tarunits, rhs->lsu, D2U(rhs->digits),
michael@0 4747 rhs->exponent-exponent);
michael@0 4748 if (compare==BADINT) { /* deep trouble */
michael@0 4749 *status|=DEC_Insufficient_storage;
michael@0 4750 break;}
michael@0 4751
michael@0 4752 /* now restore the remainder by dividing by two; the lsu */
michael@0 4753 /* is known to be even. */
michael@0 4754 for (up=accnext; up<accnext+tarunits; up++) {
michael@0 4755 Int half; /* half to add to lower unit */
michael@0 4756 half=*up & 0x01;
michael@0 4757 *up/=2; /* [shift] */
michael@0 4758 if (!half) continue;
michael@0 4759 *(up-1)+=(DECDPUNMAX+1)/2;
michael@0 4760 }
michael@0 4761 /* [accunits still describes the original remainder length] */
michael@0 4762
michael@0 4763 if (compare>0 || (compare==0 && wasodd)) { /* adjustment needed */
michael@0 4764 Int exp, expunits, exprem; /* work */
michael@0 4765 /* This is effectively causing round-up of the quotient, */
michael@0 4766 /* so if it was the rare case where it was full and all */
michael@0 4767 /* nines, it would overflow and hence division-impossible */
michael@0 4768 /* should be raised */
michael@0 4769 Flag allnines=0; /* 1 if quotient all nines */
michael@0 4770 if (quotdigits==reqdigits) { /* could be borderline */
michael@0 4771 for (up=quotlsu; ; up++) {
michael@0 4772 if (quotdigits>DECDPUN) {
michael@0 4773 if (*up!=DECDPUNMAX) break;/* non-nines */
michael@0 4774 }
michael@0 4775 else { /* this is the last Unit */
michael@0 4776 if (*up==powers[quotdigits]-1) allnines=1;
michael@0 4777 break;
michael@0 4778 }
michael@0 4779 quotdigits-=DECDPUN; /* checked those digits */
michael@0 4780 } /* up */
michael@0 4781 } /* borderline check */
michael@0 4782 if (allnines) {
michael@0 4783 *status|=DEC_Division_impossible;
michael@0 4784 break;}
michael@0 4785
michael@0 4786 /* rem-rhs is needed; the sign will invert. Again, var1 */
michael@0 4787 /* can safely be used for the working Units array. */
michael@0 4788 exp=rhs->exponent-exponent; /* RHS padding needed */
michael@0 4789 /* Calculate units and remainder from exponent. */
michael@0 4790 expunits=exp/DECDPUN;
michael@0 4791 exprem=exp%DECDPUN;
michael@0 4792 /* subtract [A+B*(-m)]; the result will always be negative */
michael@0 4793 accunits=-decUnitAddSub(accnext, accunits,
michael@0 4794 rhs->lsu, D2U(rhs->digits),
michael@0 4795 expunits, accnext, -(Int)powers[exprem]);
michael@0 4796 accdigits=decGetDigits(accnext, accunits); /* count digits exactly */
michael@0 4797 accunits=D2U(accdigits); /* and recalculate the units for copy */
michael@0 4798 /* [exponent is as for original remainder] */
michael@0 4799 bits^=DECNEG; /* flip the sign */
michael@0 4800 }
michael@0 4801 } /* REMNEAR */
michael@0 4802 } /* REMAINDER or REMNEAR */
michael@0 4803 } /* not DIVIDE */
michael@0 4804
michael@0 4805 /* Set exponent and bits */
michael@0 4806 res->exponent=exponent;
michael@0 4807 res->bits=(uByte)(bits&DECNEG); /* [cleaned] */
michael@0 4808
michael@0 4809 /* Now the coefficient. */
michael@0 4810 decSetCoeff(res, set, accnext, accdigits, &residue, status);
michael@0 4811
michael@0 4812 decFinish(res, set, &residue, status); /* final cleanup */
michael@0 4813
michael@0 4814 #if DECSUBSET
michael@0 4815 /* If a divide then strip trailing zeros if subset [after round] */
michael@0 4816 if (!set->extended && (op==DIVIDE)) decTrim(res, set, 0, 1, &dropped);
michael@0 4817 #endif
michael@0 4818 } while(0); /* end protected */
michael@0 4819
michael@0 4820 if (varalloc!=NULL) free(varalloc); /* drop any storage used */
michael@0 4821 if (allocacc!=NULL) free(allocacc); /* .. */
michael@0 4822 #if DECSUBSET
michael@0 4823 if (allocrhs!=NULL) free(allocrhs); /* .. */
michael@0 4824 if (alloclhs!=NULL) free(alloclhs); /* .. */
michael@0 4825 #endif
michael@0 4826 return res;
michael@0 4827 } /* decDivideOp */
michael@0 4828
michael@0 4829 /* ------------------------------------------------------------------ */
michael@0 4830 /* decMultiplyOp -- multiplication operation */
michael@0 4831 /* */
michael@0 4832 /* This routine performs the multiplication C=A x B. */
michael@0 4833 /* */
michael@0 4834 /* res is C, the result. C may be A and/or B (e.g., X=X*X) */
michael@0 4835 /* lhs is A */
michael@0 4836 /* rhs is B */
michael@0 4837 /* set is the context */
michael@0 4838 /* status is the usual accumulator */
michael@0 4839 /* */
michael@0 4840 /* C must have space for set->digits digits. */
michael@0 4841 /* */
michael@0 4842 /* ------------------------------------------------------------------ */
michael@0 4843 /* 'Classic' multiplication is used rather than Karatsuba, as the */
michael@0 4844 /* latter would give only a minor improvement for the short numbers */
michael@0 4845 /* expected to be handled most (and uses much more memory). */
michael@0 4846 /* */
michael@0 4847 /* There are two major paths here: the general-purpose ('old code') */
michael@0 4848 /* path which handles all DECDPUN values, and a fastpath version */
michael@0 4849 /* which is used if 64-bit ints are available, DECDPUN<=4, and more */
michael@0 4850 /* than two calls to decUnitAddSub would be made. */
michael@0 4851 /* */
michael@0 4852 /* The fastpath version lumps units together into 8-digit or 9-digit */
michael@0 4853 /* chunks, and also uses a lazy carry strategy to minimise expensive */
michael@0 4854 /* 64-bit divisions. The chunks are then broken apart again into */
michael@0 4855 /* units for continuing processing. Despite this overhead, the */
michael@0 4856 /* fastpath can speed up some 16-digit operations by 10x (and much */
michael@0 4857 /* more for higher-precision calculations). */
michael@0 4858 /* */
michael@0 4859 /* A buffer always has to be used for the accumulator; in the */
michael@0 4860 /* fastpath, buffers are also always needed for the chunked copies of */
michael@0 4861 /* of the operand coefficients. */
michael@0 4862 /* Static buffers are larger than needed just for multiply, to allow */
michael@0 4863 /* for calls from other operations (notably exp). */
michael@0 4864 /* ------------------------------------------------------------------ */
michael@0 4865 #define FASTMUL (DECUSE64 && DECDPUN<5)
michael@0 4866 static decNumber * decMultiplyOp(decNumber *res, const decNumber *lhs,
michael@0 4867 const decNumber *rhs, decContext *set,
michael@0 4868 uInt *status) {
michael@0 4869 Int accunits; /* Units of accumulator in use */
michael@0 4870 Int exponent; /* work */
michael@0 4871 Int residue=0; /* rounding residue */
michael@0 4872 uByte bits; /* result sign */
michael@0 4873 Unit *acc; /* -> accumulator Unit array */
michael@0 4874 Int needbytes; /* size calculator */
michael@0 4875 void *allocacc=NULL; /* -> allocated accumulator, iff allocated */
michael@0 4876 Unit accbuff[SD2U(DECBUFFER*4+1)]; /* buffer (+1 for DECBUFFER==0, */
michael@0 4877 /* *4 for calls from other operations) */
michael@0 4878 const Unit *mer, *mermsup; /* work */
michael@0 4879 Int madlength; /* Units in multiplicand */
michael@0 4880 Int shift; /* Units to shift multiplicand by */
michael@0 4881
michael@0 4882 #if FASTMUL
michael@0 4883 /* if DECDPUN is 1 or 3 work in base 10**9, otherwise */
michael@0 4884 /* (DECDPUN is 2 or 4) then work in base 10**8 */
michael@0 4885 #if DECDPUN & 1 /* odd */
michael@0 4886 #define FASTBASE 1000000000 /* base */
michael@0 4887 #define FASTDIGS 9 /* digits in base */
michael@0 4888 #define FASTLAZY 18 /* carry resolution point [1->18] */
michael@0 4889 #else
michael@0 4890 #define FASTBASE 100000000
michael@0 4891 #define FASTDIGS 8
michael@0 4892 #define FASTLAZY 1844 /* carry resolution point [1->1844] */
michael@0 4893 #endif
michael@0 4894 /* three buffers are used, two for chunked copies of the operands */
michael@0 4895 /* (base 10**8 or base 10**9) and one base 2**64 accumulator with */
michael@0 4896 /* lazy carry evaluation */
michael@0 4897 uInt zlhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */
michael@0 4898 uInt *zlhi=zlhibuff; /* -> lhs array */
michael@0 4899 uInt *alloclhi=NULL; /* -> allocated buffer, iff allocated */
michael@0 4900 uInt zrhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */
michael@0 4901 uInt *zrhi=zrhibuff; /* -> rhs array */
michael@0 4902 uInt *allocrhi=NULL; /* -> allocated buffer, iff allocated */
michael@0 4903 uLong zaccbuff[(DECBUFFER*2+1)/4+2]; /* buffer (+1 for DECBUFFER==0) */
michael@0 4904 /* [allocacc is shared for both paths, as only one will run] */
michael@0 4905 uLong *zacc=zaccbuff; /* -> accumulator array for exact result */
michael@0 4906 #if DECDPUN==1
michael@0 4907 Int zoff; /* accumulator offset */
michael@0 4908 #endif
michael@0 4909 uInt *lip, *rip; /* item pointers */
michael@0 4910 uInt *lmsi, *rmsi; /* most significant items */
michael@0 4911 Int ilhs, irhs, iacc; /* item counts in the arrays */
michael@0 4912 Int lazy; /* lazy carry counter */
michael@0 4913 uLong lcarry; /* uLong carry */
michael@0 4914 uInt carry; /* carry (NB not uLong) */
michael@0 4915 Int count; /* work */
michael@0 4916 const Unit *cup; /* .. */
michael@0 4917 Unit *up; /* .. */
michael@0 4918 uLong *lp; /* .. */
michael@0 4919 Int p; /* .. */
michael@0 4920 #endif
michael@0 4921
michael@0 4922 #if DECSUBSET
michael@0 4923 decNumber *alloclhs=NULL; /* -> allocated buffer, iff allocated */
michael@0 4924 decNumber *allocrhs=NULL; /* -> allocated buffer, iff allocated */
michael@0 4925 #endif
michael@0 4926
michael@0 4927 #if DECCHECK
michael@0 4928 if (decCheckOperands(res, lhs, rhs, set)) return res;
michael@0 4929 #endif
michael@0 4930
michael@0 4931 /* precalculate result sign */
michael@0 4932 bits=(uByte)((lhs->bits^rhs->bits)&DECNEG);
michael@0 4933
michael@0 4934 /* handle infinities and NaNs */
michael@0 4935 if (SPECIALARGS) { /* a special bit set */
michael@0 4936 if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */
michael@0 4937 decNaNs(res, lhs, rhs, set, status);
michael@0 4938 return res;}
michael@0 4939 /* one or two infinities; Infinity * 0 is invalid */
michael@0 4940 if (((lhs->bits & DECINF)==0 && ISZERO(lhs))
michael@0 4941 ||((rhs->bits & DECINF)==0 && ISZERO(rhs))) {
michael@0 4942 *status|=DEC_Invalid_operation;
michael@0 4943 return res;}
michael@0 4944 uprv_decNumberZero(res);
michael@0 4945 res->bits=bits|DECINF; /* infinity */
michael@0 4946 return res;}
michael@0 4947
michael@0 4948 /* For best speed, as in DMSRCN [the original Rexx numerics */
michael@0 4949 /* module], use the shorter number as the multiplier (rhs) and */
michael@0 4950 /* the longer as the multiplicand (lhs) to minimise the number of */
michael@0 4951 /* adds (partial products) */
michael@0 4952 if (lhs->digits<rhs->digits) { /* swap... */
michael@0 4953 const decNumber *hold=lhs;
michael@0 4954 lhs=rhs;
michael@0 4955 rhs=hold;
michael@0 4956 }
michael@0 4957
michael@0 4958 do { /* protect allocated storage */
michael@0 4959 #if DECSUBSET
michael@0 4960 if (!set->extended) {
michael@0 4961 /* reduce operands and set lostDigits status, as needed */
michael@0 4962 if (lhs->digits>set->digits) {
michael@0 4963 alloclhs=decRoundOperand(lhs, set, status);
michael@0 4964 if (alloclhs==NULL) break;
michael@0 4965 lhs=alloclhs;
michael@0 4966 }
michael@0 4967 if (rhs->digits>set->digits) {
michael@0 4968 allocrhs=decRoundOperand(rhs, set, status);
michael@0 4969 if (allocrhs==NULL) break;
michael@0 4970 rhs=allocrhs;
michael@0 4971 }
michael@0 4972 }
michael@0 4973 #endif
michael@0 4974 /* [following code does not require input rounding] */
michael@0 4975
michael@0 4976 #if FASTMUL /* fastpath can be used */
michael@0 4977 /* use the fast path if there are enough digits in the shorter */
michael@0 4978 /* operand to make the setup and takedown worthwhile */
michael@0 4979 #define NEEDTWO (DECDPUN*2) /* within two decUnitAddSub calls */
michael@0 4980 if (rhs->digits>NEEDTWO) { /* use fastpath... */
michael@0 4981 /* calculate the number of elements in each array */
michael@0 4982 ilhs=(lhs->digits+FASTDIGS-1)/FASTDIGS; /* [ceiling] */
michael@0 4983 irhs=(rhs->digits+FASTDIGS-1)/FASTDIGS; /* .. */
michael@0 4984 iacc=ilhs+irhs;
michael@0 4985
michael@0 4986 /* allocate buffers if required, as usual */
michael@0 4987 needbytes=ilhs*sizeof(uInt);
michael@0 4988 if (needbytes>(Int)sizeof(zlhibuff)) {
michael@0 4989 alloclhi=(uInt *)malloc(needbytes);
michael@0 4990 zlhi=alloclhi;}
michael@0 4991 needbytes=irhs*sizeof(uInt);
michael@0 4992 if (needbytes>(Int)sizeof(zrhibuff)) {
michael@0 4993 allocrhi=(uInt *)malloc(needbytes);
michael@0 4994 zrhi=allocrhi;}
michael@0 4995
michael@0 4996 /* Allocating the accumulator space needs a special case when */
michael@0 4997 /* DECDPUN=1 because when converting the accumulator to Units */
michael@0 4998 /* after the multiplication each 8-byte item becomes 9 1-byte */
michael@0 4999 /* units. Therefore iacc extra bytes are needed at the front */
michael@0 5000 /* (rounded up to a multiple of 8 bytes), and the uLong */
michael@0 5001 /* accumulator starts offset the appropriate number of units */
michael@0 5002 /* to the right to avoid overwrite during the unchunking. */
michael@0 5003
michael@0 5004 /* Make sure no signed int overflow below. This is always true */
michael@0 5005 /* if the given numbers have less digits than DEC_MAX_DIGITS. */
michael@0 5006 U_ASSERT(iacc <= INT32_MAX/sizeof(uLong));
michael@0 5007 needbytes=iacc*sizeof(uLong);
michael@0 5008 #if DECDPUN==1
michael@0 5009 zoff=(iacc+7)/8; /* items to offset by */
michael@0 5010 needbytes+=zoff*8;
michael@0 5011 #endif
michael@0 5012 if (needbytes>(Int)sizeof(zaccbuff)) {
michael@0 5013 allocacc=(uLong *)malloc(needbytes);
michael@0 5014 zacc=(uLong *)allocacc;}
michael@0 5015 if (zlhi==NULL||zrhi==NULL||zacc==NULL) {
michael@0 5016 *status|=DEC_Insufficient_storage;
michael@0 5017 break;}
michael@0 5018
michael@0 5019 acc=(Unit *)zacc; /* -> target Unit array */
michael@0 5020 #if DECDPUN==1
michael@0 5021 zacc+=zoff; /* start uLong accumulator to right */
michael@0 5022 #endif
michael@0 5023
michael@0 5024 /* assemble the chunked copies of the left and right sides */
michael@0 5025 for (count=lhs->digits, cup=lhs->lsu, lip=zlhi; count>0; lip++)
michael@0 5026 for (p=0, *lip=0; p<FASTDIGS && count>0;
michael@0 5027 p+=DECDPUN, cup++, count-=DECDPUN)
michael@0 5028 *lip+=*cup*powers[p];
michael@0 5029 lmsi=lip-1; /* save -> msi */
michael@0 5030 for (count=rhs->digits, cup=rhs->lsu, rip=zrhi; count>0; rip++)
michael@0 5031 for (p=0, *rip=0; p<FASTDIGS && count>0;
michael@0 5032 p+=DECDPUN, cup++, count-=DECDPUN)
michael@0 5033 *rip+=*cup*powers[p];
michael@0 5034 rmsi=rip-1; /* save -> msi */
michael@0 5035
michael@0 5036 /* zero the accumulator */
michael@0 5037 for (lp=zacc; lp<zacc+iacc; lp++) *lp=0;
michael@0 5038
michael@0 5039 /* Start the multiplication */
michael@0 5040 /* Resolving carries can dominate the cost of accumulating the */
michael@0 5041 /* partial products, so this is only done when necessary. */
michael@0 5042 /* Each uLong item in the accumulator can hold values up to */
michael@0 5043 /* 2**64-1, and each partial product can be as large as */
michael@0 5044 /* (10**FASTDIGS-1)**2. When FASTDIGS=9, this can be added to */
michael@0 5045 /* itself 18.4 times in a uLong without overflowing, so during */
michael@0 5046 /* the main calculation resolution is carried out every 18th */
michael@0 5047 /* add -- every 162 digits. Similarly, when FASTDIGS=8, the */
michael@0 5048 /* partial products can be added to themselves 1844.6 times in */
michael@0 5049 /* a uLong without overflowing, so intermediate carry */
michael@0 5050 /* resolution occurs only every 14752 digits. Hence for common */
michael@0 5051 /* short numbers usually only the one final carry resolution */
michael@0 5052 /* occurs. */
michael@0 5053 /* (The count is set via FASTLAZY to simplify experiments to */
michael@0 5054 /* measure the value of this approach: a 35% improvement on a */
michael@0 5055 /* [34x34] multiply.) */
michael@0 5056 lazy=FASTLAZY; /* carry delay count */
michael@0 5057 for (rip=zrhi; rip<=rmsi; rip++) { /* over each item in rhs */
michael@0 5058 lp=zacc+(rip-zrhi); /* where to add the lhs */
michael@0 5059 for (lip=zlhi; lip<=lmsi; lip++, lp++) { /* over each item in lhs */
michael@0 5060 *lp+=(uLong)(*lip)*(*rip); /* [this should in-line] */
michael@0 5061 } /* lip loop */
michael@0 5062 lazy--;
michael@0 5063 if (lazy>0 && rip!=rmsi) continue;
michael@0 5064 lazy=FASTLAZY; /* reset delay count */
michael@0 5065 /* spin up the accumulator resolving overflows */
michael@0 5066 for (lp=zacc; lp<zacc+iacc; lp++) {
michael@0 5067 if (*lp<FASTBASE) continue; /* it fits */
michael@0 5068 lcarry=*lp/FASTBASE; /* top part [slow divide] */
michael@0 5069 /* lcarry can exceed 2**32-1, so check again; this check */
michael@0 5070 /* and occasional extra divide (slow) is well worth it, as */
michael@0 5071 /* it allows FASTLAZY to be increased to 18 rather than 4 */
michael@0 5072 /* in the FASTDIGS=9 case */
michael@0 5073 if (lcarry<FASTBASE) carry=(uInt)lcarry; /* [usual] */
michael@0 5074 else { /* two-place carry [fairly rare] */
michael@0 5075 uInt carry2=(uInt)(lcarry/FASTBASE); /* top top part */
michael@0 5076 *(lp+2)+=carry2; /* add to item+2 */
michael@0 5077 *lp-=((uLong)FASTBASE*FASTBASE*carry2); /* [slow] */
michael@0 5078 carry=(uInt)(lcarry-((uLong)FASTBASE*carry2)); /* [inline] */
michael@0 5079 }
michael@0 5080 *(lp+1)+=carry; /* add to item above [inline] */
michael@0 5081 *lp-=((uLong)FASTBASE*carry); /* [inline] */
michael@0 5082 } /* carry resolution */
michael@0 5083 } /* rip loop */
michael@0 5084
michael@0 5085 /* The multiplication is complete; time to convert back into */
michael@0 5086 /* units. This can be done in-place in the accumulator and in */
michael@0 5087 /* 32-bit operations, because carries were resolved after the */
michael@0 5088 /* final add. This needs N-1 divides and multiplies for */
michael@0 5089 /* each item in the accumulator (which will become up to N */
michael@0 5090 /* units, where 2<=N<=9). */
michael@0 5091 for (lp=zacc, up=acc; lp<zacc+iacc; lp++) {
michael@0 5092 uInt item=(uInt)*lp; /* decapitate to uInt */
michael@0 5093 for (p=0; p<FASTDIGS-DECDPUN; p+=DECDPUN, up++) {
michael@0 5094 uInt part=item/(DECDPUNMAX+1);
michael@0 5095 *up=(Unit)(item-(part*(DECDPUNMAX+1)));
michael@0 5096 item=part;
michael@0 5097 } /* p */
michael@0 5098 *up=(Unit)item; up++; /* [final needs no division] */
michael@0 5099 } /* lp */
michael@0 5100 accunits=up-acc; /* count of units */
michael@0 5101 }
michael@0 5102 else { /* here to use units directly, without chunking ['old code'] */
michael@0 5103 #endif
michael@0 5104
michael@0 5105 /* if accumulator will be too long for local storage, then allocate */
michael@0 5106 acc=accbuff; /* -> assume buffer for accumulator */
michael@0 5107 needbytes=(D2U(lhs->digits)+D2U(rhs->digits))*sizeof(Unit);
michael@0 5108 if (needbytes>(Int)sizeof(accbuff)) {
michael@0 5109 allocacc=(Unit *)malloc(needbytes);
michael@0 5110 if (allocacc==NULL) {*status|=DEC_Insufficient_storage; break;}
michael@0 5111 acc=(Unit *)allocacc; /* use the allocated space */
michael@0 5112 }
michael@0 5113
michael@0 5114 /* Now the main long multiplication loop */
michael@0 5115 /* Unlike the equivalent in the IBM Java implementation, there */
michael@0 5116 /* is no advantage in calculating from msu to lsu. So, do it */
michael@0 5117 /* by the book, as it were. */
michael@0 5118 /* Each iteration calculates ACC=ACC+MULTAND*MULT */
michael@0 5119 accunits=1; /* accumulator starts at '0' */
michael@0 5120 *acc=0; /* .. (lsu=0) */
michael@0 5121 shift=0; /* no multiplicand shift at first */
michael@0 5122 madlength=D2U(lhs->digits); /* this won't change */
michael@0 5123 mermsup=rhs->lsu+D2U(rhs->digits); /* -> msu+1 of multiplier */
michael@0 5124
michael@0 5125 for (mer=rhs->lsu; mer<mermsup; mer++) {
michael@0 5126 /* Here, *mer is the next Unit in the multiplier to use */
michael@0 5127 /* If non-zero [optimization] add it... */
michael@0 5128 if (*mer!=0) accunits=decUnitAddSub(&acc[shift], accunits-shift,
michael@0 5129 lhs->lsu, madlength, 0,
michael@0 5130 &acc[shift], *mer)
michael@0 5131 + shift;
michael@0 5132 else { /* extend acc with a 0; it will be used shortly */
michael@0 5133 *(acc+accunits)=0; /* [this avoids length of <=0 later] */
michael@0 5134 accunits++;
michael@0 5135 }
michael@0 5136 /* multiply multiplicand by 10**DECDPUN for next Unit to left */
michael@0 5137 shift++; /* add this for 'logical length' */
michael@0 5138 } /* n */
michael@0 5139 #if FASTMUL
michael@0 5140 } /* unchunked units */
michael@0 5141 #endif
michael@0 5142 /* common end-path */
michael@0 5143 #if DECTRACE
michael@0 5144 decDumpAr('*', acc, accunits); /* Show exact result */
michael@0 5145 #endif
michael@0 5146
michael@0 5147 /* acc now contains the exact result of the multiplication, */
michael@0 5148 /* possibly with a leading zero unit; build the decNumber from */
michael@0 5149 /* it, noting if any residue */
michael@0 5150 res->bits=bits; /* set sign */
michael@0 5151 res->digits=decGetDigits(acc, accunits); /* count digits exactly */
michael@0 5152
michael@0 5153 /* There can be a 31-bit wrap in calculating the exponent. */
michael@0 5154 /* This can only happen if both input exponents are negative and */
michael@0 5155 /* both their magnitudes are large. If there was a wrap, set a */
michael@0 5156 /* safe very negative exponent, from which decFinalize() will */
michael@0 5157 /* raise a hard underflow shortly. */
michael@0 5158 exponent=lhs->exponent+rhs->exponent; /* calculate exponent */
michael@0 5159 if (lhs->exponent<0 && rhs->exponent<0 && exponent>0)
michael@0 5160 exponent=-2*DECNUMMAXE; /* force underflow */
michael@0 5161 res->exponent=exponent; /* OK to overwrite now */
michael@0 5162
michael@0 5163
michael@0 5164 /* Set the coefficient. If any rounding, residue records */
michael@0 5165 decSetCoeff(res, set, acc, res->digits, &residue, status);
michael@0 5166 decFinish(res, set, &residue, status); /* final cleanup */
michael@0 5167 } while(0); /* end protected */
michael@0 5168
michael@0 5169 if (allocacc!=NULL) free(allocacc); /* drop any storage used */
michael@0 5170 #if DECSUBSET
michael@0 5171 if (allocrhs!=NULL) free(allocrhs); /* .. */
michael@0 5172 if (alloclhs!=NULL) free(alloclhs); /* .. */
michael@0 5173 #endif
michael@0 5174 #if FASTMUL
michael@0 5175 if (allocrhi!=NULL) free(allocrhi); /* .. */
michael@0 5176 if (alloclhi!=NULL) free(alloclhi); /* .. */
michael@0 5177 #endif
michael@0 5178 return res;
michael@0 5179 } /* decMultiplyOp */
michael@0 5180
michael@0 5181 /* ------------------------------------------------------------------ */
michael@0 5182 /* decExpOp -- effect exponentiation */
michael@0 5183 /* */
michael@0 5184 /* This computes C = exp(A) */
michael@0 5185 /* */
michael@0 5186 /* res is C, the result. C may be A */
michael@0 5187 /* rhs is A */
michael@0 5188 /* set is the context; note that rounding mode has no effect */
michael@0 5189 /* */
michael@0 5190 /* C must have space for set->digits digits. status is updated but */
michael@0 5191 /* not set. */
michael@0 5192 /* */
michael@0 5193 /* Restrictions: */
michael@0 5194 /* */
michael@0 5195 /* digits, emax, and -emin in the context must be less than */
michael@0 5196 /* 2*DEC_MAX_MATH (1999998), and the rhs must be within these */
michael@0 5197 /* bounds or a zero. This is an internal routine, so these */
michael@0 5198 /* restrictions are contractual and not enforced. */
michael@0 5199 /* */
michael@0 5200 /* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */
michael@0 5201 /* almost always be correctly rounded, but may be up to 1 ulp in */
michael@0 5202 /* error in rare cases. */
michael@0 5203 /* */
michael@0 5204 /* Finite results will always be full precision and Inexact, except */
michael@0 5205 /* when A is a zero or -Infinity (giving 1 or 0 respectively). */
michael@0 5206 /* ------------------------------------------------------------------ */
michael@0 5207 /* This approach used here is similar to the algorithm described in */
michael@0 5208 /* */
michael@0 5209 /* Variable Precision Exponential Function, T. E. Hull and */
michael@0 5210 /* A. Abrham, ACM Transactions on Mathematical Software, Vol 12 #2, */
michael@0 5211 /* pp79-91, ACM, June 1986. */
michael@0 5212 /* */
michael@0 5213 /* with the main difference being that the iterations in the series */
michael@0 5214 /* evaluation are terminated dynamically (which does not require the */
michael@0 5215 /* extra variable-precision variables which are expensive in this */
michael@0 5216 /* context). */
michael@0 5217 /* */
michael@0 5218 /* The error analysis in Hull & Abrham's paper applies except for the */
michael@0 5219 /* round-off error accumulation during the series evaluation. This */
michael@0 5220 /* code does not precalculate the number of iterations and so cannot */
michael@0 5221 /* use Horner's scheme. Instead, the accumulation is done at double- */
michael@0 5222 /* precision, which ensures that the additions of the terms are exact */
michael@0 5223 /* and do not accumulate round-off (and any round-off errors in the */
michael@0 5224 /* terms themselves move 'to the right' faster than they can */
michael@0 5225 /* accumulate). This code also extends the calculation by allowing, */
michael@0 5226 /* in the spirit of other decNumber operators, the input to be more */
michael@0 5227 /* precise than the result (the precision used is based on the more */
michael@0 5228 /* precise of the input or requested result). */
michael@0 5229 /* */
michael@0 5230 /* Implementation notes: */
michael@0 5231 /* */
michael@0 5232 /* 1. This is separated out as decExpOp so it can be called from */
michael@0 5233 /* other Mathematical functions (notably Ln) with a wider range */
michael@0 5234 /* than normal. In particular, it can handle the slightly wider */
michael@0 5235 /* (double) range needed by Ln (which has to be able to calculate */
michael@0 5236 /* exp(-x) where x can be the tiniest number (Ntiny). */
michael@0 5237 /* */
michael@0 5238 /* 2. Normalizing x to be <=0.1 (instead of <=1) reduces loop */
michael@0 5239 /* iterations by appoximately a third with additional (although */
michael@0 5240 /* diminishing) returns as the range is reduced to even smaller */
michael@0 5241 /* fractions. However, h (the power of 10 used to correct the */
michael@0 5242 /* result at the end, see below) must be kept <=8 as otherwise */
michael@0 5243 /* the final result cannot be computed. Hence the leverage is a */
michael@0 5244 /* sliding value (8-h), where potentially the range is reduced */
michael@0 5245 /* more for smaller values. */
michael@0 5246 /* */
michael@0 5247 /* The leverage that can be applied in this way is severely */
michael@0 5248 /* limited by the cost of the raise-to-the power at the end, */
michael@0 5249 /* which dominates when the number of iterations is small (less */
michael@0 5250 /* than ten) or when rhs is short. As an example, the adjustment */
michael@0 5251 /* x**10,000,000 needs 31 multiplications, all but one full-width. */
michael@0 5252 /* */
michael@0 5253 /* 3. The restrictions (especially precision) could be raised with */
michael@0 5254 /* care, but the full decNumber range seems very hard within the */
michael@0 5255 /* 32-bit limits. */
michael@0 5256 /* */
michael@0 5257 /* 4. The working precisions for the static buffers are twice the */
michael@0 5258 /* obvious size to allow for calls from decNumberPower. */
michael@0 5259 /* ------------------------------------------------------------------ */
michael@0 5260 decNumber * decExpOp(decNumber *res, const decNumber *rhs,
michael@0 5261 decContext *set, uInt *status) {
michael@0 5262 uInt ignore=0; /* working status */
michael@0 5263 Int h; /* adjusted exponent for 0.xxxx */
michael@0 5264 Int p; /* working precision */
michael@0 5265 Int residue; /* rounding residue */
michael@0 5266 uInt needbytes; /* for space calculations */
michael@0 5267 const decNumber *x=rhs; /* (may point to safe copy later) */
michael@0 5268 decContext aset, tset, dset; /* working contexts */
michael@0 5269 Int comp; /* work */
michael@0 5270
michael@0 5271 /* the argument is often copied to normalize it, so (unusually) it */
michael@0 5272 /* is treated like other buffers, using DECBUFFER, +1 in case */
michael@0 5273 /* DECBUFFER is 0 */
michael@0 5274 decNumber bufr[D2N(DECBUFFER*2+1)];
michael@0 5275 decNumber *allocrhs=NULL; /* non-NULL if rhs buffer allocated */
michael@0 5276
michael@0 5277 /* the working precision will be no more than set->digits+8+1 */
michael@0 5278 /* so for on-stack buffers DECBUFFER+9 is used, +1 in case DECBUFFER */
michael@0 5279 /* is 0 (and twice that for the accumulator) */
michael@0 5280
michael@0 5281 /* buffer for t, term (working precision plus) */
michael@0 5282 decNumber buft[D2N(DECBUFFER*2+9+1)];
michael@0 5283 decNumber *allocbuft=NULL; /* -> allocated buft, iff allocated */
michael@0 5284 decNumber *t=buft; /* term */
michael@0 5285 /* buffer for a, accumulator (working precision * 2), at least 9 */
michael@0 5286 decNumber bufa[D2N(DECBUFFER*4+18+1)];
michael@0 5287 decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */
michael@0 5288 decNumber *a=bufa; /* accumulator */
michael@0 5289 /* decNumber for the divisor term; this needs at most 9 digits */
michael@0 5290 /* and so can be fixed size [16 so can use standard context] */
michael@0 5291 decNumber bufd[D2N(16)];
michael@0 5292 decNumber *d=bufd; /* divisor */
michael@0 5293 decNumber numone; /* constant 1 */
michael@0 5294
michael@0 5295 #if DECCHECK
michael@0 5296 Int iterations=0; /* for later sanity check */
michael@0 5297 if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
michael@0 5298 #endif
michael@0 5299
michael@0 5300 do { /* protect allocated storage */
michael@0 5301 if (SPECIALARG) { /* handle infinities and NaNs */
michael@0 5302 if (decNumberIsInfinite(rhs)) { /* an infinity */
michael@0 5303 if (decNumberIsNegative(rhs)) /* -Infinity -> +0 */
michael@0 5304 uprv_decNumberZero(res);
michael@0 5305 else uprv_decNumberCopy(res, rhs); /* +Infinity -> self */
michael@0 5306 }
michael@0 5307 else decNaNs(res, rhs, NULL, set, status); /* a NaN */
michael@0 5308 break;}
michael@0 5309
michael@0 5310 if (ISZERO(rhs)) { /* zeros -> exact 1 */
michael@0 5311 uprv_decNumberZero(res); /* make clean 1 */
michael@0 5312 *res->lsu=1; /* .. */
michael@0 5313 break;} /* [no status to set] */
michael@0 5314
michael@0 5315 /* e**x when 0 < x < 0.66 is < 1+3x/2, hence can fast-path */
michael@0 5316 /* positive and negative tiny cases which will result in inexact */
michael@0 5317 /* 1. This also allows the later add-accumulate to always be */
michael@0 5318 /* exact (because its length will never be more than twice the */
michael@0 5319 /* working precision). */
michael@0 5320 /* The comparator (tiny) needs just one digit, so use the */
michael@0 5321 /* decNumber d for it (reused as the divisor, etc., below); its */
michael@0 5322 /* exponent is such that if x is positive it will have */
michael@0 5323 /* set->digits-1 zeros between the decimal point and the digit, */
michael@0 5324 /* which is 4, and if x is negative one more zero there as the */
michael@0 5325 /* more precise result will be of the form 0.9999999 rather than */
michael@0 5326 /* 1.0000001. Hence, tiny will be 0.0000004 if digits=7 and x>0 */
michael@0 5327 /* or 0.00000004 if digits=7 and x<0. If RHS not larger than */
michael@0 5328 /* this then the result will be 1.000000 */
michael@0 5329 uprv_decNumberZero(d); /* clean */
michael@0 5330 *d->lsu=4; /* set 4 .. */
michael@0 5331 d->exponent=-set->digits; /* * 10**(-d) */
michael@0 5332 if (decNumberIsNegative(rhs)) d->exponent--; /* negative case */
michael@0 5333 comp=decCompare(d, rhs, 1); /* signless compare */
michael@0 5334 if (comp==BADINT) {
michael@0 5335 *status|=DEC_Insufficient_storage;
michael@0 5336 break;}
michael@0 5337 if (comp>=0) { /* rhs < d */
michael@0 5338 Int shift=set->digits-1;
michael@0 5339 uprv_decNumberZero(res); /* set 1 */
michael@0 5340 *res->lsu=1; /* .. */
michael@0 5341 res->digits=decShiftToMost(res->lsu, 1, shift);
michael@0 5342 res->exponent=-shift; /* make 1.0000... */
michael@0 5343 *status|=DEC_Inexact | DEC_Rounded; /* .. inexactly */
michael@0 5344 break;} /* tiny */
michael@0 5345
michael@0 5346 /* set up the context to be used for calculating a, as this is */
michael@0 5347 /* used on both paths below */
michael@0 5348 uprv_decContextDefault(&aset, DEC_INIT_DECIMAL64);
michael@0 5349 /* accumulator bounds are as requested (could underflow) */
michael@0 5350 aset.emax=set->emax; /* usual bounds */
michael@0 5351 aset.emin=set->emin; /* .. */
michael@0 5352 aset.clamp=0; /* and no concrete format */
michael@0 5353
michael@0 5354 /* calculate the adjusted (Hull & Abrham) exponent (where the */
michael@0 5355 /* decimal point is just to the left of the coefficient msd) */
michael@0 5356 h=rhs->exponent+rhs->digits;
michael@0 5357 /* if h>8 then 10**h cannot be calculated safely; however, when */
michael@0 5358 /* h=8 then exp(|rhs|) will be at least exp(1E+7) which is at */
michael@0 5359 /* least 6.59E+4342944, so (due to the restriction on Emax/Emin) */
michael@0 5360 /* overflow (or underflow to 0) is guaranteed -- so this case can */
michael@0 5361 /* be handled by simply forcing the appropriate excess */
michael@0 5362 if (h>8) { /* overflow/underflow */
michael@0 5363 /* set up here so Power call below will over or underflow to */
michael@0 5364 /* zero; set accumulator to either 2 or 0.02 */
michael@0 5365 /* [stack buffer for a is always big enough for this] */
michael@0 5366 uprv_decNumberZero(a);
michael@0 5367 *a->lsu=2; /* not 1 but < exp(1) */
michael@0 5368 if (decNumberIsNegative(rhs)) a->exponent=-2; /* make 0.02 */
michael@0 5369 h=8; /* clamp so 10**h computable */
michael@0 5370 p=9; /* set a working precision */
michael@0 5371 }
michael@0 5372 else { /* h<=8 */
michael@0 5373 Int maxlever=(rhs->digits>8?1:0);
michael@0 5374 /* [could/should increase this for precisions >40 or so, too] */
michael@0 5375
michael@0 5376 /* if h is 8, cannot normalize to a lower upper limit because */
michael@0 5377 /* the final result will not be computable (see notes above), */
michael@0 5378 /* but leverage can be applied whenever h is less than 8. */
michael@0 5379 /* Apply as much as possible, up to a MAXLEVER digits, which */
michael@0 5380 /* sets the tradeoff against the cost of the later a**(10**h). */
michael@0 5381 /* As h is increased, the working precision below also */
michael@0 5382 /* increases to compensate for the "constant digits at the */
michael@0 5383 /* front" effect. */
michael@0 5384 Int lever=MINI(8-h, maxlever); /* leverage attainable */
michael@0 5385 Int use=-rhs->digits-lever; /* exponent to use for RHS */
michael@0 5386 h+=lever; /* apply leverage selected */
michael@0 5387 if (h<0) { /* clamp */
michael@0 5388 use+=h; /* [may end up subnormal] */
michael@0 5389 h=0;
michael@0 5390 }
michael@0 5391 /* Take a copy of RHS if it needs normalization (true whenever x>=1) */
michael@0 5392 if (rhs->exponent!=use) {
michael@0 5393 decNumber *newrhs=bufr; /* assume will fit on stack */
michael@0 5394 needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
michael@0 5395 if (needbytes>sizeof(bufr)) { /* need malloc space */
michael@0 5396 allocrhs=(decNumber *)malloc(needbytes);
michael@0 5397 if (allocrhs==NULL) { /* hopeless -- abandon */
michael@0 5398 *status|=DEC_Insufficient_storage;
michael@0 5399 break;}
michael@0 5400 newrhs=allocrhs; /* use the allocated space */
michael@0 5401 }
michael@0 5402 uprv_decNumberCopy(newrhs, rhs); /* copy to safe space */
michael@0 5403 newrhs->exponent=use; /* normalize; now <1 */
michael@0 5404 x=newrhs; /* ready for use */
michael@0 5405 /* decNumberShow(x); */
michael@0 5406 }
michael@0 5407
michael@0 5408 /* Now use the usual power series to evaluate exp(x). The */
michael@0 5409 /* series starts as 1 + x + x^2/2 ... so prime ready for the */
michael@0 5410 /* third term by setting the term variable t=x, the accumulator */
michael@0 5411 /* a=1, and the divisor d=2. */
michael@0 5412
michael@0 5413 /* First determine the working precision. From Hull & Abrham */
michael@0 5414 /* this is set->digits+h+2. However, if x is 'over-precise' we */
michael@0 5415 /* need to allow for all its digits to potentially participate */
michael@0 5416 /* (consider an x where all the excess digits are 9s) so in */
michael@0 5417 /* this case use x->digits+h+2 */
michael@0 5418 p=MAXI(x->digits, set->digits)+h+2; /* [h<=8] */
michael@0 5419
michael@0 5420 /* a and t are variable precision, and depend on p, so space */
michael@0 5421 /* must be allocated for them if necessary */
michael@0 5422
michael@0 5423 /* the accumulator needs to be able to hold 2p digits so that */
michael@0 5424 /* the additions on the second and subsequent iterations are */
michael@0 5425 /* sufficiently exact. */
michael@0 5426 needbytes=sizeof(decNumber)+(D2U(p*2)-1)*sizeof(Unit);
michael@0 5427 if (needbytes>sizeof(bufa)) { /* need malloc space */
michael@0 5428 allocbufa=(decNumber *)malloc(needbytes);
michael@0 5429 if (allocbufa==NULL) { /* hopeless -- abandon */
michael@0 5430 *status|=DEC_Insufficient_storage;
michael@0 5431 break;}
michael@0 5432 a=allocbufa; /* use the allocated space */
michael@0 5433 }
michael@0 5434 /* the term needs to be able to hold p digits (which is */
michael@0 5435 /* guaranteed to be larger than x->digits, so the initial copy */
michael@0 5436 /* is safe); it may also be used for the raise-to-power */
michael@0 5437 /* calculation below, which needs an extra two digits */
michael@0 5438 needbytes=sizeof(decNumber)+(D2U(p+2)-1)*sizeof(Unit);
michael@0 5439 if (needbytes>sizeof(buft)) { /* need malloc space */
michael@0 5440 allocbuft=(decNumber *)malloc(needbytes);
michael@0 5441 if (allocbuft==NULL) { /* hopeless -- abandon */
michael@0 5442 *status|=DEC_Insufficient_storage;
michael@0 5443 break;}
michael@0 5444 t=allocbuft; /* use the allocated space */
michael@0 5445 }
michael@0 5446
michael@0 5447 uprv_decNumberCopy(t, x); /* term=x */
michael@0 5448 uprv_decNumberZero(a); *a->lsu=1; /* accumulator=1 */
michael@0 5449 uprv_decNumberZero(d); *d->lsu=2; /* divisor=2 */
michael@0 5450 uprv_decNumberZero(&numone); *numone.lsu=1; /* constant 1 for increment */
michael@0 5451
michael@0 5452 /* set up the contexts for calculating a, t, and d */
michael@0 5453 uprv_decContextDefault(&tset, DEC_INIT_DECIMAL64);
michael@0 5454 dset=tset;
michael@0 5455 /* accumulator bounds are set above, set precision now */
michael@0 5456 aset.digits=p*2; /* double */
michael@0 5457 /* term bounds avoid any underflow or overflow */
michael@0 5458 tset.digits=p;
michael@0 5459 tset.emin=DEC_MIN_EMIN; /* [emax is plenty] */
michael@0 5460 /* [dset.digits=16, etc., are sufficient] */
michael@0 5461
michael@0 5462 /* finally ready to roll */
michael@0 5463 for (;;) {
michael@0 5464 #if DECCHECK
michael@0 5465 iterations++;
michael@0 5466 #endif
michael@0 5467 /* only the status from the accumulation is interesting */
michael@0 5468 /* [but it should remain unchanged after first add] */
michael@0 5469 decAddOp(a, a, t, &aset, 0, status); /* a=a+t */
michael@0 5470 decMultiplyOp(t, t, x, &tset, &ignore); /* t=t*x */
michael@0 5471 decDivideOp(t, t, d, &tset, DIVIDE, &ignore); /* t=t/d */
michael@0 5472 /* the iteration ends when the term cannot affect the result, */
michael@0 5473 /* if rounded to p digits, which is when its value is smaller */
michael@0 5474 /* than the accumulator by p+1 digits. There must also be */
michael@0 5475 /* full precision in a. */
michael@0 5476 if (((a->digits+a->exponent)>=(t->digits+t->exponent+p+1))
michael@0 5477 && (a->digits>=p)) break;
michael@0 5478 decAddOp(d, d, &numone, &dset, 0, &ignore); /* d=d+1 */
michael@0 5479 } /* iterate */
michael@0 5480
michael@0 5481 #if DECCHECK
michael@0 5482 /* just a sanity check; comment out test to show always */
michael@0 5483 if (iterations>p+3)
michael@0 5484 printf("Exp iterations=%ld, status=%08lx, p=%ld, d=%ld\n",
michael@0 5485 (LI)iterations, (LI)*status, (LI)p, (LI)x->digits);
michael@0 5486 #endif
michael@0 5487 } /* h<=8 */
michael@0 5488
michael@0 5489 /* apply postconditioning: a=a**(10**h) -- this is calculated */
michael@0 5490 /* at a slightly higher precision than Hull & Abrham suggest */
michael@0 5491 if (h>0) {
michael@0 5492 Int seenbit=0; /* set once a 1-bit is seen */
michael@0 5493 Int i; /* counter */
michael@0 5494 Int n=powers[h]; /* always positive */
michael@0 5495 aset.digits=p+2; /* sufficient precision */
michael@0 5496 /* avoid the overhead and many extra digits of decNumberPower */
michael@0 5497 /* as all that is needed is the short 'multipliers' loop; here */
michael@0 5498 /* accumulate the answer into t */
michael@0 5499 uprv_decNumberZero(t); *t->lsu=1; /* acc=1 */
michael@0 5500 for (i=1;;i++){ /* for each bit [top bit ignored] */
michael@0 5501 /* abandon if have had overflow or terminal underflow */
michael@0 5502 if (*status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */
michael@0 5503 if (*status&DEC_Overflow || ISZERO(t)) break;}
michael@0 5504 n=n<<1; /* move next bit to testable position */
michael@0 5505 if (n<0) { /* top bit is set */
michael@0 5506 seenbit=1; /* OK, have a significant bit */
michael@0 5507 decMultiplyOp(t, t, a, &aset, status); /* acc=acc*x */
michael@0 5508 }
michael@0 5509 if (i==31) break; /* that was the last bit */
michael@0 5510 if (!seenbit) continue; /* no need to square 1 */
michael@0 5511 decMultiplyOp(t, t, t, &aset, status); /* acc=acc*acc [square] */
michael@0 5512 } /*i*/ /* 32 bits */
michael@0 5513 /* decNumberShow(t); */
michael@0 5514 a=t; /* and carry on using t instead of a */
michael@0 5515 }
michael@0 5516
michael@0 5517 /* Copy and round the result to res */
michael@0 5518 residue=1; /* indicate dirt to right .. */
michael@0 5519 if (ISZERO(a)) residue=0; /* .. unless underflowed to 0 */
michael@0 5520 aset.digits=set->digits; /* [use default rounding] */
michael@0 5521 decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */
michael@0 5522 decFinish(res, set, &residue, status); /* cleanup/set flags */
michael@0 5523 } while(0); /* end protected */
michael@0 5524
michael@0 5525 if (allocrhs !=NULL) free(allocrhs); /* drop any storage used */
michael@0 5526 if (allocbufa!=NULL) free(allocbufa); /* .. */
michael@0 5527 if (allocbuft!=NULL) free(allocbuft); /* .. */
michael@0 5528 /* [status is handled by caller] */
michael@0 5529 return res;
michael@0 5530 } /* decExpOp */
michael@0 5531
michael@0 5532 /* ------------------------------------------------------------------ */
michael@0 5533 /* Initial-estimate natural logarithm table */
michael@0 5534 /* */
michael@0 5535 /* LNnn -- 90-entry 16-bit table for values from .10 through .99. */
michael@0 5536 /* The result is a 4-digit encode of the coefficient (c=the */
michael@0 5537 /* top 14 bits encoding 0-9999) and a 2-digit encode of the */
michael@0 5538 /* exponent (e=the bottom 2 bits encoding 0-3) */
michael@0 5539 /* */
michael@0 5540 /* The resulting value is given by: */
michael@0 5541 /* */
michael@0 5542 /* v = -c * 10**(-e-3) */
michael@0 5543 /* */
michael@0 5544 /* where e and c are extracted from entry k = LNnn[x-10] */
michael@0 5545 /* where x is truncated (NB) into the range 10 through 99, */
michael@0 5546 /* and then c = k>>2 and e = k&3. */
michael@0 5547 /* ------------------------------------------------------------------ */
michael@0 5548 static const uShort LNnn[90]={9016, 8652, 8316, 8008, 7724, 7456, 7208,
michael@0 5549 6972, 6748, 6540, 6340, 6148, 5968, 5792, 5628, 5464, 5312,
michael@0 5550 5164, 5020, 4884, 4748, 4620, 4496, 4376, 4256, 4144, 4032,
michael@0 5551 39233, 38181, 37157, 36157, 35181, 34229, 33297, 32389, 31501, 30629,
michael@0 5552 29777, 28945, 28129, 27329, 26545, 25777, 25021, 24281, 23553, 22837,
michael@0 5553 22137, 21445, 20769, 20101, 19445, 18801, 18165, 17541, 16925, 16321,
michael@0 5554 15721, 15133, 14553, 13985, 13421, 12865, 12317, 11777, 11241, 10717,
michael@0 5555 10197, 9685, 9177, 8677, 8185, 7697, 7213, 6737, 6269, 5801,
michael@0 5556 5341, 4889, 4437, 39930, 35534, 31186, 26886, 22630, 18418, 14254,
michael@0 5557 10130, 6046, 20055};
michael@0 5558
michael@0 5559 /* ------------------------------------------------------------------ */
michael@0 5560 /* decLnOp -- effect natural logarithm */
michael@0 5561 /* */
michael@0 5562 /* This computes C = ln(A) */
michael@0 5563 /* */
michael@0 5564 /* res is C, the result. C may be A */
michael@0 5565 /* rhs is A */
michael@0 5566 /* set is the context; note that rounding mode has no effect */
michael@0 5567 /* */
michael@0 5568 /* C must have space for set->digits digits. */
michael@0 5569 /* */
michael@0 5570 /* Notable cases: */
michael@0 5571 /* A<0 -> Invalid */
michael@0 5572 /* A=0 -> -Infinity (Exact) */
michael@0 5573 /* A=+Infinity -> +Infinity (Exact) */
michael@0 5574 /* A=1 exactly -> 0 (Exact) */
michael@0 5575 /* */
michael@0 5576 /* Restrictions (as for Exp): */
michael@0 5577 /* */
michael@0 5578 /* digits, emax, and -emin in the context must be less than */
michael@0 5579 /* DEC_MAX_MATH+11 (1000010), and the rhs must be within these */
michael@0 5580 /* bounds or a zero. This is an internal routine, so these */
michael@0 5581 /* restrictions are contractual and not enforced. */
michael@0 5582 /* */
michael@0 5583 /* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */
michael@0 5584 /* almost always be correctly rounded, but may be up to 1 ulp in */
michael@0 5585 /* error in rare cases. */
michael@0 5586 /* ------------------------------------------------------------------ */
michael@0 5587 /* The result is calculated using Newton's method, with each */
michael@0 5588 /* iteration calculating a' = a + x * exp(-a) - 1. See, for example, */
michael@0 5589 /* Epperson 1989. */
michael@0 5590 /* */
michael@0 5591 /* The iteration ends when the adjustment x*exp(-a)-1 is tiny enough. */
michael@0 5592 /* This has to be calculated at the sum of the precision of x and the */
michael@0 5593 /* working precision. */
michael@0 5594 /* */
michael@0 5595 /* Implementation notes: */
michael@0 5596 /* */
michael@0 5597 /* 1. This is separated out as decLnOp so it can be called from */
michael@0 5598 /* other Mathematical functions (e.g., Log 10) with a wider range */
michael@0 5599 /* than normal. In particular, it can handle the slightly wider */
michael@0 5600 /* (+9+2) range needed by a power function. */
michael@0 5601 /* */
michael@0 5602 /* 2. The speed of this function is about 10x slower than exp, as */
michael@0 5603 /* it typically needs 4-6 iterations for short numbers, and the */
michael@0 5604 /* extra precision needed adds a squaring effect, twice. */
michael@0 5605 /* */
michael@0 5606 /* 3. Fastpaths are included for ln(10) and ln(2), up to length 40, */
michael@0 5607 /* as these are common requests. ln(10) is used by log10(x). */
michael@0 5608 /* */
michael@0 5609 /* 4. An iteration might be saved by widening the LNnn table, and */
michael@0 5610 /* would certainly save at least one if it were made ten times */
michael@0 5611 /* bigger, too (for truncated fractions 0.100 through 0.999). */
michael@0 5612 /* However, for most practical evaluations, at least four or five */
michael@0 5613 /* iterations will be neede -- so this would only speed up by */
michael@0 5614 /* 20-25% and that probably does not justify increasing the table */
michael@0 5615 /* size. */
michael@0 5616 /* */
michael@0 5617 /* 5. The static buffers are larger than might be expected to allow */
michael@0 5618 /* for calls from decNumberPower. */
michael@0 5619 /* ------------------------------------------------------------------ */
michael@0 5620 #if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406
michael@0 5621 #pragma GCC diagnostic push
michael@0 5622 #pragma GCC diagnostic ignored "-Warray-bounds"
michael@0 5623 #endif
michael@0 5624 decNumber * decLnOp(decNumber *res, const decNumber *rhs,
michael@0 5625 decContext *set, uInt *status) {
michael@0 5626 uInt ignore=0; /* working status accumulator */
michael@0 5627 uInt needbytes; /* for space calculations */
michael@0 5628 Int residue; /* rounding residue */
michael@0 5629 Int r; /* rhs=f*10**r [see below] */
michael@0 5630 Int p; /* working precision */
michael@0 5631 Int pp; /* precision for iteration */
michael@0 5632 Int t; /* work */
michael@0 5633
michael@0 5634 /* buffers for a (accumulator, typically precision+2) and b */
michael@0 5635 /* (adjustment calculator, same size) */
michael@0 5636 decNumber bufa[D2N(DECBUFFER+12)];
michael@0 5637 decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */
michael@0 5638 decNumber *a=bufa; /* accumulator/work */
michael@0 5639 decNumber bufb[D2N(DECBUFFER*2+2)];
michael@0 5640 decNumber *allocbufb=NULL; /* -> allocated bufa, iff allocated */
michael@0 5641 decNumber *b=bufb; /* adjustment/work */
michael@0 5642
michael@0 5643 decNumber numone; /* constant 1 */
michael@0 5644 decNumber cmp; /* work */
michael@0 5645 decContext aset, bset; /* working contexts */
michael@0 5646
michael@0 5647 #if DECCHECK
michael@0 5648 Int iterations=0; /* for later sanity check */
michael@0 5649 if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
michael@0 5650 #endif
michael@0 5651
michael@0 5652 do { /* protect allocated storage */
michael@0 5653 if (SPECIALARG) { /* handle infinities and NaNs */
michael@0 5654 if (decNumberIsInfinite(rhs)) { /* an infinity */
michael@0 5655 if (decNumberIsNegative(rhs)) /* -Infinity -> error */
michael@0 5656 *status|=DEC_Invalid_operation;
michael@0 5657 else uprv_decNumberCopy(res, rhs); /* +Infinity -> self */
michael@0 5658 }
michael@0 5659 else decNaNs(res, rhs, NULL, set, status); /* a NaN */
michael@0 5660 break;}
michael@0 5661
michael@0 5662 if (ISZERO(rhs)) { /* +/- zeros -> -Infinity */
michael@0 5663 uprv_decNumberZero(res); /* make clean */
michael@0 5664 res->bits=DECINF|DECNEG; /* set - infinity */
michael@0 5665 break;} /* [no status to set] */
michael@0 5666
michael@0 5667 /* Non-zero negatives are bad... */
michael@0 5668 if (decNumberIsNegative(rhs)) { /* -x -> error */
michael@0 5669 *status|=DEC_Invalid_operation;
michael@0 5670 break;}
michael@0 5671
michael@0 5672 /* Here, rhs is positive, finite, and in range */
michael@0 5673
michael@0 5674 /* lookaside fastpath code for ln(2) and ln(10) at common lengths */
michael@0 5675 if (rhs->exponent==0 && set->digits<=40) {
michael@0 5676 #if DECDPUN==1
michael@0 5677 if (rhs->lsu[0]==0 && rhs->lsu[1]==1 && rhs->digits==2) { /* ln(10) */
michael@0 5678 #else
michael@0 5679 if (rhs->lsu[0]==10 && rhs->digits==2) { /* ln(10) */
michael@0 5680 #endif
michael@0 5681 aset=*set; aset.round=DEC_ROUND_HALF_EVEN;
michael@0 5682 #define LN10 "2.302585092994045684017991454684364207601"
michael@0 5683 uprv_decNumberFromString(res, LN10, &aset);
michael@0 5684 *status|=(DEC_Inexact | DEC_Rounded); /* is inexact */
michael@0 5685 break;}
michael@0 5686 if (rhs->lsu[0]==2 && rhs->digits==1) { /* ln(2) */
michael@0 5687 aset=*set; aset.round=DEC_ROUND_HALF_EVEN;
michael@0 5688 #define LN2 "0.6931471805599453094172321214581765680755"
michael@0 5689 uprv_decNumberFromString(res, LN2, &aset);
michael@0 5690 *status|=(DEC_Inexact | DEC_Rounded);
michael@0 5691 break;}
michael@0 5692 } /* integer and short */
michael@0 5693
michael@0 5694 /* Determine the working precision. This is normally the */
michael@0 5695 /* requested precision + 2, with a minimum of 9. However, if */
michael@0 5696 /* the rhs is 'over-precise' then allow for all its digits to */
michael@0 5697 /* potentially participate (consider an rhs where all the excess */
michael@0 5698 /* digits are 9s) so in this case use rhs->digits+2. */
michael@0 5699 p=MAXI(rhs->digits, MAXI(set->digits, 7))+2;
michael@0 5700
michael@0 5701 /* Allocate space for the accumulator and the high-precision */
michael@0 5702 /* adjustment calculator, if necessary. The accumulator must */
michael@0 5703 /* be able to hold p digits, and the adjustment up to */
michael@0 5704 /* rhs->digits+p digits. They are also made big enough for 16 */
michael@0 5705 /* digits so that they can be used for calculating the initial */
michael@0 5706 /* estimate. */
michael@0 5707 needbytes=sizeof(decNumber)+(D2U(MAXI(p,16))-1)*sizeof(Unit);
michael@0 5708 if (needbytes>sizeof(bufa)) { /* need malloc space */
michael@0 5709 allocbufa=(decNumber *)malloc(needbytes);
michael@0 5710 if (allocbufa==NULL) { /* hopeless -- abandon */
michael@0 5711 *status|=DEC_Insufficient_storage;
michael@0 5712 break;}
michael@0 5713 a=allocbufa; /* use the allocated space */
michael@0 5714 }
michael@0 5715 pp=p+rhs->digits;
michael@0 5716 needbytes=sizeof(decNumber)+(D2U(MAXI(pp,16))-1)*sizeof(Unit);
michael@0 5717 if (needbytes>sizeof(bufb)) { /* need malloc space */
michael@0 5718 allocbufb=(decNumber *)malloc(needbytes);
michael@0 5719 if (allocbufb==NULL) { /* hopeless -- abandon */
michael@0 5720 *status|=DEC_Insufficient_storage;
michael@0 5721 break;}
michael@0 5722 b=allocbufb; /* use the allocated space */
michael@0 5723 }
michael@0 5724
michael@0 5725 /* Prepare an initial estimate in acc. Calculate this by */
michael@0 5726 /* considering the coefficient of x to be a normalized fraction, */
michael@0 5727 /* f, with the decimal point at far left and multiplied by */
michael@0 5728 /* 10**r. Then, rhs=f*10**r and 0.1<=f<1, and */
michael@0 5729 /* ln(x) = ln(f) + ln(10)*r */
michael@0 5730 /* Get the initial estimate for ln(f) from a small lookup */
michael@0 5731 /* table (see above) indexed by the first two digits of f, */
michael@0 5732 /* truncated. */
michael@0 5733
michael@0 5734 uprv_decContextDefault(&aset, DEC_INIT_DECIMAL64); /* 16-digit extended */
michael@0 5735 r=rhs->exponent+rhs->digits; /* 'normalised' exponent */
michael@0 5736 uprv_decNumberFromInt32(a, r); /* a=r */
michael@0 5737 uprv_decNumberFromInt32(b, 2302585); /* b=ln(10) (2.302585) */
michael@0 5738 b->exponent=-6; /* .. */
michael@0 5739 decMultiplyOp(a, a, b, &aset, &ignore); /* a=a*b */
michael@0 5740 /* now get top two digits of rhs into b by simple truncate and */
michael@0 5741 /* force to integer */
michael@0 5742 residue=0; /* (no residue) */
michael@0 5743 aset.digits=2; aset.round=DEC_ROUND_DOWN;
michael@0 5744 decCopyFit(b, rhs, &aset, &residue, &ignore); /* copy & shorten */
michael@0 5745 b->exponent=0; /* make integer */
michael@0 5746 t=decGetInt(b); /* [cannot fail] */
michael@0 5747 if (t<10) t=X10(t); /* adjust single-digit b */
michael@0 5748 t=LNnn[t-10]; /* look up ln(b) */
michael@0 5749 uprv_decNumberFromInt32(b, t>>2); /* b=ln(b) coefficient */
michael@0 5750 b->exponent=-(t&3)-3; /* set exponent */
michael@0 5751 b->bits=DECNEG; /* ln(0.10)->ln(0.99) always -ve */
michael@0 5752 aset.digits=16; aset.round=DEC_ROUND_HALF_EVEN; /* restore */
michael@0 5753 decAddOp(a, a, b, &aset, 0, &ignore); /* acc=a+b */
michael@0 5754 /* the initial estimate is now in a, with up to 4 digits correct. */
michael@0 5755 /* When rhs is at or near Nmax the estimate will be low, so we */
michael@0 5756 /* will approach it from below, avoiding overflow when calling exp. */
michael@0 5757
michael@0 5758 uprv_decNumberZero(&numone); *numone.lsu=1; /* constant 1 for adjustment */
michael@0 5759
michael@0 5760 /* accumulator bounds are as requested (could underflow, but */
michael@0 5761 /* cannot overflow) */
michael@0 5762 aset.emax=set->emax;
michael@0 5763 aset.emin=set->emin;
michael@0 5764 aset.clamp=0; /* no concrete format */
michael@0 5765 /* set up a context to be used for the multiply and subtract */
michael@0 5766 bset=aset;
michael@0 5767 bset.emax=DEC_MAX_MATH*2; /* use double bounds for the */
michael@0 5768 bset.emin=-DEC_MAX_MATH*2; /* adjustment calculation */
michael@0 5769 /* [see decExpOp call below] */
michael@0 5770 /* for each iteration double the number of digits to calculate, */
michael@0 5771 /* up to a maximum of p */
michael@0 5772 pp=9; /* initial precision */
michael@0 5773 /* [initially 9 as then the sequence starts 7+2, 16+2, and */
michael@0 5774 /* 34+2, which is ideal for standard-sized numbers] */
michael@0 5775 aset.digits=pp; /* working context */
michael@0 5776 bset.digits=pp+rhs->digits; /* wider context */
michael@0 5777 for (;;) { /* iterate */
michael@0 5778 #if DECCHECK
michael@0 5779 iterations++;
michael@0 5780 if (iterations>24) break; /* consider 9 * 2**24 */
michael@0 5781 #endif
michael@0 5782 /* calculate the adjustment (exp(-a)*x-1) into b. This is a */
michael@0 5783 /* catastrophic subtraction but it really is the difference */
michael@0 5784 /* from 1 that is of interest. */
michael@0 5785 /* Use the internal entry point to Exp as it allows the double */
michael@0 5786 /* range for calculating exp(-a) when a is the tiniest subnormal. */
michael@0 5787 a->bits^=DECNEG; /* make -a */
michael@0 5788 decExpOp(b, a, &bset, &ignore); /* b=exp(-a) */
michael@0 5789 a->bits^=DECNEG; /* restore sign of a */
michael@0 5790 /* now multiply by rhs and subtract 1, at the wider precision */
michael@0 5791 decMultiplyOp(b, b, rhs, &bset, &ignore); /* b=b*rhs */
michael@0 5792 decAddOp(b, b, &numone, &bset, DECNEG, &ignore); /* b=b-1 */
michael@0 5793
michael@0 5794 /* the iteration ends when the adjustment cannot affect the */
michael@0 5795 /* result by >=0.5 ulp (at the requested digits), which */
michael@0 5796 /* is when its value is smaller than the accumulator by */
michael@0 5797 /* set->digits+1 digits (or it is zero) -- this is a looser */
michael@0 5798 /* requirement than for Exp because all that happens to the */
michael@0 5799 /* accumulator after this is the final rounding (but note that */
michael@0 5800 /* there must also be full precision in a, or a=0). */
michael@0 5801
michael@0 5802 if (decNumberIsZero(b) ||
michael@0 5803 (a->digits+a->exponent)>=(b->digits+b->exponent+set->digits+1)) {
michael@0 5804 if (a->digits==p) break;
michael@0 5805 if (decNumberIsZero(a)) {
michael@0 5806 decCompareOp(&cmp, rhs, &numone, &aset, COMPARE, &ignore); /* rhs=1 ? */
michael@0 5807 if (cmp.lsu[0]==0) a->exponent=0; /* yes, exact 0 */
michael@0 5808 else *status|=(DEC_Inexact | DEC_Rounded); /* no, inexact */
michael@0 5809 break;
michael@0 5810 }
michael@0 5811 /* force padding if adjustment has gone to 0 before full length */
michael@0 5812 if (decNumberIsZero(b)) b->exponent=a->exponent-p;
michael@0 5813 }
michael@0 5814
michael@0 5815 /* not done yet ... */
michael@0 5816 decAddOp(a, a, b, &aset, 0, &ignore); /* a=a+b for next estimate */
michael@0 5817 if (pp==p) continue; /* precision is at maximum */
michael@0 5818 /* lengthen the next calculation */
michael@0 5819 pp=pp*2; /* double precision */
michael@0 5820 if (pp>p) pp=p; /* clamp to maximum */
michael@0 5821 aset.digits=pp; /* working context */
michael@0 5822 bset.digits=pp+rhs->digits; /* wider context */
michael@0 5823 } /* Newton's iteration */
michael@0 5824
michael@0 5825 #if DECCHECK
michael@0 5826 /* just a sanity check; remove the test to show always */
michael@0 5827 if (iterations>24)
michael@0 5828 printf("Ln iterations=%ld, status=%08lx, p=%ld, d=%ld\n",
michael@0 5829 (LI)iterations, (LI)*status, (LI)p, (LI)rhs->digits);
michael@0 5830 #endif
michael@0 5831
michael@0 5832 /* Copy and round the result to res */
michael@0 5833 residue=1; /* indicate dirt to right */
michael@0 5834 if (ISZERO(a)) residue=0; /* .. unless underflowed to 0 */
michael@0 5835 aset.digits=set->digits; /* [use default rounding] */
michael@0 5836 decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */
michael@0 5837 decFinish(res, set, &residue, status); /* cleanup/set flags */
michael@0 5838 } while(0); /* end protected */
michael@0 5839
michael@0 5840 if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
michael@0 5841 if (allocbufb!=NULL) free(allocbufb); /* .. */
michael@0 5842 /* [status is handled by caller] */
michael@0 5843 return res;
michael@0 5844 } /* decLnOp */
michael@0 5845 #if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406
michael@0 5846 #pragma GCC diagnostic pop
michael@0 5847 #endif
michael@0 5848
michael@0 5849 /* ------------------------------------------------------------------ */
michael@0 5850 /* decQuantizeOp -- force exponent to requested value */
michael@0 5851 /* */
michael@0 5852 /* This computes C = op(A, B), where op adjusts the coefficient */
michael@0 5853 /* of C (by rounding or shifting) such that the exponent (-scale) */
michael@0 5854 /* of C has the value B or matches the exponent of B. */
michael@0 5855 /* The numerical value of C will equal A, except for the effects of */
michael@0 5856 /* any rounding that occurred. */
michael@0 5857 /* */
michael@0 5858 /* res is C, the result. C may be A or B */
michael@0 5859 /* lhs is A, the number to adjust */
michael@0 5860 /* rhs is B, the requested exponent */
michael@0 5861 /* set is the context */
michael@0 5862 /* quant is 1 for quantize or 0 for rescale */
michael@0 5863 /* status is the status accumulator (this can be called without */
michael@0 5864 /* risk of control loss) */
michael@0 5865 /* */
michael@0 5866 /* C must have space for set->digits digits. */
michael@0 5867 /* */
michael@0 5868 /* Unless there is an error or the result is infinite, the exponent */
michael@0 5869 /* after the operation is guaranteed to be that requested. */
michael@0 5870 /* ------------------------------------------------------------------ */
michael@0 5871 static decNumber * decQuantizeOp(decNumber *res, const decNumber *lhs,
michael@0 5872 const decNumber *rhs, decContext *set,
michael@0 5873 Flag quant, uInt *status) {
michael@0 5874 #if DECSUBSET
michael@0 5875 decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */
michael@0 5876 decNumber *allocrhs=NULL; /* .., rhs */
michael@0 5877 #endif
michael@0 5878 const decNumber *inrhs=rhs; /* save original rhs */
michael@0 5879 Int reqdigits=set->digits; /* requested DIGITS */
michael@0 5880 Int reqexp; /* requested exponent [-scale] */
michael@0 5881 Int residue=0; /* rounding residue */
michael@0 5882 Int etiny=set->emin-(reqdigits-1);
michael@0 5883
michael@0 5884 #if DECCHECK
michael@0 5885 if (decCheckOperands(res, lhs, rhs, set)) return res;
michael@0 5886 #endif
michael@0 5887
michael@0 5888 do { /* protect allocated storage */
michael@0 5889 #if DECSUBSET
michael@0 5890 if (!set->extended) {
michael@0 5891 /* reduce operands and set lostDigits status, as needed */
michael@0 5892 if (lhs->digits>reqdigits) {
michael@0 5893 alloclhs=decRoundOperand(lhs, set, status);
michael@0 5894 if (alloclhs==NULL) break;
michael@0 5895 lhs=alloclhs;
michael@0 5896 }
michael@0 5897 if (rhs->digits>reqdigits) { /* [this only checks lostDigits] */
michael@0 5898 allocrhs=decRoundOperand(rhs, set, status);
michael@0 5899 if (allocrhs==NULL) break;
michael@0 5900 rhs=allocrhs;
michael@0 5901 }
michael@0 5902 }
michael@0 5903 #endif
michael@0 5904 /* [following code does not require input rounding] */
michael@0 5905
michael@0 5906 /* Handle special values */
michael@0 5907 if (SPECIALARGS) {
michael@0 5908 /* NaNs get usual processing */
michael@0 5909 if (SPECIALARGS & (DECSNAN | DECNAN))
michael@0 5910 decNaNs(res, lhs, rhs, set, status);
michael@0 5911 /* one infinity but not both is bad */
michael@0 5912 else if ((lhs->bits ^ rhs->bits) & DECINF)
michael@0 5913 *status|=DEC_Invalid_operation;
michael@0 5914 /* both infinity: return lhs */
michael@0 5915 else uprv_decNumberCopy(res, lhs); /* [nop if in place] */
michael@0 5916 break;
michael@0 5917 }
michael@0 5918
michael@0 5919 /* set requested exponent */
michael@0 5920 if (quant) reqexp=inrhs->exponent; /* quantize -- match exponents */
michael@0 5921 else { /* rescale -- use value of rhs */
michael@0 5922 /* Original rhs must be an integer that fits and is in range, */
michael@0 5923 /* which could be from -1999999997 to +999999999, thanks to */
michael@0 5924 /* subnormals */
michael@0 5925 reqexp=decGetInt(inrhs); /* [cannot fail] */
michael@0 5926 }
michael@0 5927
michael@0 5928 #if DECSUBSET
michael@0 5929 if (!set->extended) etiny=set->emin; /* no subnormals */
michael@0 5930 #endif
michael@0 5931
michael@0 5932 if (reqexp==BADINT /* bad (rescale only) or .. */
michael@0 5933 || reqexp==BIGODD || reqexp==BIGEVEN /* very big (ditto) or .. */
michael@0 5934 || (reqexp<etiny) /* < lowest */
michael@0 5935 || (reqexp>set->emax)) { /* > emax */
michael@0 5936 *status|=DEC_Invalid_operation;
michael@0 5937 break;}
michael@0 5938
michael@0 5939 /* the RHS has been processed, so it can be overwritten now if necessary */
michael@0 5940 if (ISZERO(lhs)) { /* zero coefficient unchanged */
michael@0 5941 uprv_decNumberCopy(res, lhs); /* [nop if in place] */
michael@0 5942 res->exponent=reqexp; /* .. just set exponent */
michael@0 5943 #if DECSUBSET
michael@0 5944 if (!set->extended) res->bits=0; /* subset specification; no -0 */
michael@0 5945 #endif
michael@0 5946 }
michael@0 5947 else { /* non-zero lhs */
michael@0 5948 Int adjust=reqexp-lhs->exponent; /* digit adjustment needed */
michael@0 5949 /* if adjusted coefficient will definitely not fit, give up now */
michael@0 5950 if ((lhs->digits-adjust)>reqdigits) {
michael@0 5951 *status|=DEC_Invalid_operation;
michael@0 5952 break;
michael@0 5953 }
michael@0 5954
michael@0 5955 if (adjust>0) { /* increasing exponent */
michael@0 5956 /* this will decrease the length of the coefficient by adjust */
michael@0 5957 /* digits, and must round as it does so */
michael@0 5958 decContext workset; /* work */
michael@0 5959 workset=*set; /* clone rounding, etc. */
michael@0 5960 workset.digits=lhs->digits-adjust; /* set requested length */
michael@0 5961 /* [note that the latter can be <1, here] */
michael@0 5962 decCopyFit(res, lhs, &workset, &residue, status); /* fit to result */
michael@0 5963 decApplyRound(res, &workset, residue, status); /* .. and round */
michael@0 5964 residue=0; /* [used] */
michael@0 5965 /* If just rounded a 999s case, exponent will be off by one; */
michael@0 5966 /* adjust back (after checking space), if so. */
michael@0 5967 if (res->exponent>reqexp) {
michael@0 5968 /* re-check needed, e.g., for quantize(0.9999, 0.001) under */
michael@0 5969 /* set->digits==3 */
michael@0 5970 if (res->digits==reqdigits) { /* cannot shift by 1 */
michael@0 5971 *status&=~(DEC_Inexact | DEC_Rounded); /* [clean these] */
michael@0 5972 *status|=DEC_Invalid_operation;
michael@0 5973 break;
michael@0 5974 }
michael@0 5975 res->digits=decShiftToMost(res->lsu, res->digits, 1); /* shift */
michael@0 5976 res->exponent--; /* (re)adjust the exponent. */
michael@0 5977 }
michael@0 5978 #if DECSUBSET
michael@0 5979 if (ISZERO(res) && !set->extended) res->bits=0; /* subset; no -0 */
michael@0 5980 #endif
michael@0 5981 } /* increase */
michael@0 5982 else /* adjust<=0 */ { /* decreasing or = exponent */
michael@0 5983 /* this will increase the length of the coefficient by -adjust */
michael@0 5984 /* digits, by adding zero or more trailing zeros; this is */
michael@0 5985 /* already checked for fit, above */
michael@0 5986 uprv_decNumberCopy(res, lhs); /* [it will fit] */
michael@0 5987 /* if padding needed (adjust<0), add it now... */
michael@0 5988 if (adjust<0) {
michael@0 5989 res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
michael@0 5990 res->exponent+=adjust; /* adjust the exponent */
michael@0 5991 }
michael@0 5992 } /* decrease */
michael@0 5993 } /* non-zero */
michael@0 5994
michael@0 5995 /* Check for overflow [do not use Finalize in this case, as an */
michael@0 5996 /* overflow here is a "don't fit" situation] */
michael@0 5997 if (res->exponent>set->emax-res->digits+1) { /* too big */
michael@0 5998 *status|=DEC_Invalid_operation;
michael@0 5999 break;
michael@0 6000 }
michael@0 6001 else {
michael@0 6002 decFinalize(res, set, &residue, status); /* set subnormal flags */
michael@0 6003 *status&=~DEC_Underflow; /* suppress Underflow [as per 754] */
michael@0 6004 }
michael@0 6005 } while(0); /* end protected */
michael@0 6006
michael@0 6007 #if DECSUBSET
michael@0 6008 if (allocrhs!=NULL) free(allocrhs); /* drop any storage used */
michael@0 6009 if (alloclhs!=NULL) free(alloclhs); /* .. */
michael@0 6010 #endif
michael@0 6011 return res;
michael@0 6012 } /* decQuantizeOp */
michael@0 6013
michael@0 6014 /* ------------------------------------------------------------------ */
michael@0 6015 /* decCompareOp -- compare, min, or max two Numbers */
michael@0 6016 /* */
michael@0 6017 /* This computes C = A ? B and carries out one of four operations: */
michael@0 6018 /* COMPARE -- returns the signum (as a number) giving the */
michael@0 6019 /* result of a comparison unless one or both */
michael@0 6020 /* operands is a NaN (in which case a NaN results) */
michael@0 6021 /* COMPSIG -- as COMPARE except that a quiet NaN raises */
michael@0 6022 /* Invalid operation. */
michael@0 6023 /* COMPMAX -- returns the larger of the operands, using the */
michael@0 6024 /* 754 maxnum operation */
michael@0 6025 /* COMPMAXMAG -- ditto, comparing absolute values */
michael@0 6026 /* COMPMIN -- the 754 minnum operation */
michael@0 6027 /* COMPMINMAG -- ditto, comparing absolute values */
michael@0 6028 /* COMTOTAL -- returns the signum (as a number) giving the */
michael@0 6029 /* result of a comparison using 754 total ordering */
michael@0 6030 /* */
michael@0 6031 /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
michael@0 6032 /* lhs is A */
michael@0 6033 /* rhs is B */
michael@0 6034 /* set is the context */
michael@0 6035 /* op is the operation flag */
michael@0 6036 /* status is the usual accumulator */
michael@0 6037 /* */
michael@0 6038 /* C must have space for one digit for COMPARE or set->digits for */
michael@0 6039 /* COMPMAX, COMPMIN, COMPMAXMAG, or COMPMINMAG. */
michael@0 6040 /* ------------------------------------------------------------------ */
michael@0 6041 /* The emphasis here is on speed for common cases, and avoiding */
michael@0 6042 /* coefficient comparison if possible. */
michael@0 6043 /* ------------------------------------------------------------------ */
michael@0 6044 static decNumber * decCompareOp(decNumber *res, const decNumber *lhs,
michael@0 6045 const decNumber *rhs, decContext *set,
michael@0 6046 Flag op, uInt *status) {
michael@0 6047 #if DECSUBSET
michael@0 6048 decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */
michael@0 6049 decNumber *allocrhs=NULL; /* .., rhs */
michael@0 6050 #endif
michael@0 6051 Int result=0; /* default result value */
michael@0 6052 uByte merged; /* work */
michael@0 6053
michael@0 6054 #if DECCHECK
michael@0 6055 if (decCheckOperands(res, lhs, rhs, set)) return res;
michael@0 6056 #endif
michael@0 6057
michael@0 6058 do { /* protect allocated storage */
michael@0 6059 #if DECSUBSET
michael@0 6060 if (!set->extended) {
michael@0 6061 /* reduce operands and set lostDigits status, as needed */
michael@0 6062 if (lhs->digits>set->digits) {
michael@0 6063 alloclhs=decRoundOperand(lhs, set, status);
michael@0 6064 if (alloclhs==NULL) {result=BADINT; break;}
michael@0 6065 lhs=alloclhs;
michael@0 6066 }
michael@0 6067 if (rhs->digits>set->digits) {
michael@0 6068 allocrhs=decRoundOperand(rhs, set, status);
michael@0 6069 if (allocrhs==NULL) {result=BADINT; break;}
michael@0 6070 rhs=allocrhs;
michael@0 6071 }
michael@0 6072 }
michael@0 6073 #endif
michael@0 6074 /* [following code does not require input rounding] */
michael@0 6075
michael@0 6076 /* If total ordering then handle differing signs 'up front' */
michael@0 6077 if (op==COMPTOTAL) { /* total ordering */
michael@0 6078 if (decNumberIsNegative(lhs) && !decNumberIsNegative(rhs)) {
michael@0 6079 result=-1;
michael@0 6080 break;
michael@0 6081 }
michael@0 6082 if (!decNumberIsNegative(lhs) && decNumberIsNegative(rhs)) {
michael@0 6083 result=+1;
michael@0 6084 break;
michael@0 6085 }
michael@0 6086 }
michael@0 6087
michael@0 6088 /* handle NaNs specially; let infinities drop through */
michael@0 6089 /* This assumes sNaN (even just one) leads to NaN. */
michael@0 6090 merged=(lhs->bits | rhs->bits) & (DECSNAN | DECNAN);
michael@0 6091 if (merged) { /* a NaN bit set */
michael@0 6092 if (op==COMPARE); /* result will be NaN */
michael@0 6093 else if (op==COMPSIG) /* treat qNaN as sNaN */
michael@0 6094 *status|=DEC_Invalid_operation | DEC_sNaN;
michael@0 6095 else if (op==COMPTOTAL) { /* total ordering, always finite */
michael@0 6096 /* signs are known to be the same; compute the ordering here */
michael@0 6097 /* as if the signs are both positive, then invert for negatives */
michael@0 6098 if (!decNumberIsNaN(lhs)) result=-1;
michael@0 6099 else if (!decNumberIsNaN(rhs)) result=+1;
michael@0 6100 /* here if both NaNs */
michael@0 6101 else if (decNumberIsSNaN(lhs) && decNumberIsQNaN(rhs)) result=-1;
michael@0 6102 else if (decNumberIsQNaN(lhs) && decNumberIsSNaN(rhs)) result=+1;
michael@0 6103 else { /* both NaN or both sNaN */
michael@0 6104 /* now it just depends on the payload */
michael@0 6105 result=decUnitCompare(lhs->lsu, D2U(lhs->digits),
michael@0 6106 rhs->lsu, D2U(rhs->digits), 0);
michael@0 6107 /* [Error not possible, as these are 'aligned'] */
michael@0 6108 } /* both same NaNs */
michael@0 6109 if (decNumberIsNegative(lhs)) result=-result;
michael@0 6110 break;
michael@0 6111 } /* total order */
michael@0 6112
michael@0 6113 else if (merged & DECSNAN); /* sNaN -> qNaN */
michael@0 6114 else { /* here if MIN or MAX and one or two quiet NaNs */
michael@0 6115 /* min or max -- 754 rules ignore single NaN */
michael@0 6116 if (!decNumberIsNaN(lhs) || !decNumberIsNaN(rhs)) {
michael@0 6117 /* just one NaN; force choice to be the non-NaN operand */
michael@0 6118 op=COMPMAX;
michael@0 6119 if (lhs->bits & DECNAN) result=-1; /* pick rhs */
michael@0 6120 else result=+1; /* pick lhs */
michael@0 6121 break;
michael@0 6122 }
michael@0 6123 } /* max or min */
michael@0 6124 op=COMPNAN; /* use special path */
michael@0 6125 decNaNs(res, lhs, rhs, set, status); /* propagate NaN */
michael@0 6126 break;
michael@0 6127 }
michael@0 6128 /* have numbers */
michael@0 6129 if (op==COMPMAXMAG || op==COMPMINMAG) result=decCompare(lhs, rhs, 1);
michael@0 6130 else result=decCompare(lhs, rhs, 0); /* sign matters */
michael@0 6131 } while(0); /* end protected */
michael@0 6132
michael@0 6133 if (result==BADINT) *status|=DEC_Insufficient_storage; /* rare */
michael@0 6134 else {
michael@0 6135 if (op==COMPARE || op==COMPSIG ||op==COMPTOTAL) { /* returning signum */
michael@0 6136 if (op==COMPTOTAL && result==0) {
michael@0 6137 /* operands are numerically equal or same NaN (and same sign, */
michael@0 6138 /* tested first); if identical, leave result 0 */
michael@0 6139 if (lhs->exponent!=rhs->exponent) {
michael@0 6140 if (lhs->exponent<rhs->exponent) result=-1;
michael@0 6141 else result=+1;
michael@0 6142 if (decNumberIsNegative(lhs)) result=-result;
michael@0 6143 } /* lexp!=rexp */
michael@0 6144 } /* total-order by exponent */
michael@0 6145 uprv_decNumberZero(res); /* [always a valid result] */
michael@0 6146 if (result!=0) { /* must be -1 or +1 */
michael@0 6147 *res->lsu=1;
michael@0 6148 if (result<0) res->bits=DECNEG;
michael@0 6149 }
michael@0 6150 }
michael@0 6151 else if (op==COMPNAN); /* special, drop through */
michael@0 6152 else { /* MAX or MIN, non-NaN result */
michael@0 6153 Int residue=0; /* rounding accumulator */
michael@0 6154 /* choose the operand for the result */
michael@0 6155 const decNumber *choice;
michael@0 6156 if (result==0) { /* operands are numerically equal */
michael@0 6157 /* choose according to sign then exponent (see 754) */
michael@0 6158 uByte slhs=(lhs->bits & DECNEG);
michael@0 6159 uByte srhs=(rhs->bits & DECNEG);
michael@0 6160 #if DECSUBSET
michael@0 6161 if (!set->extended) { /* subset: force left-hand */
michael@0 6162 op=COMPMAX;
michael@0 6163 result=+1;
michael@0 6164 }
michael@0 6165 else
michael@0 6166 #endif
michael@0 6167 if (slhs!=srhs) { /* signs differ */
michael@0 6168 if (slhs) result=-1; /* rhs is max */
michael@0 6169 else result=+1; /* lhs is max */
michael@0 6170 }
michael@0 6171 else if (slhs && srhs) { /* both negative */
michael@0 6172 if (lhs->exponent<rhs->exponent) result=+1;
michael@0 6173 else result=-1;
michael@0 6174 /* [if equal, use lhs, technically identical] */
michael@0 6175 }
michael@0 6176 else { /* both positive */
michael@0 6177 if (lhs->exponent>rhs->exponent) result=+1;
michael@0 6178 else result=-1;
michael@0 6179 /* [ditto] */
michael@0 6180 }
michael@0 6181 } /* numerically equal */
michael@0 6182 /* here result will be non-0; reverse if looking for MIN */
michael@0 6183 if (op==COMPMIN || op==COMPMINMAG) result=-result;
michael@0 6184 choice=(result>0 ? lhs : rhs); /* choose */
michael@0 6185 /* copy chosen to result, rounding if need be */
michael@0 6186 decCopyFit(res, choice, set, &residue, status);
michael@0 6187 decFinish(res, set, &residue, status);
michael@0 6188 }
michael@0 6189 }
michael@0 6190 #if DECSUBSET
michael@0 6191 if (allocrhs!=NULL) free(allocrhs); /* free any storage used */
michael@0 6192 if (alloclhs!=NULL) free(alloclhs); /* .. */
michael@0 6193 #endif
michael@0 6194 return res;
michael@0 6195 } /* decCompareOp */
michael@0 6196
michael@0 6197 /* ------------------------------------------------------------------ */
michael@0 6198 /* decCompare -- compare two decNumbers by numerical value */
michael@0 6199 /* */
michael@0 6200 /* This routine compares A ? B without altering them. */
michael@0 6201 /* */
michael@0 6202 /* Arg1 is A, a decNumber which is not a NaN */
michael@0 6203 /* Arg2 is B, a decNumber which is not a NaN */
michael@0 6204 /* Arg3 is 1 for a sign-independent compare, 0 otherwise */
michael@0 6205 /* */
michael@0 6206 /* returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure */
michael@0 6207 /* (the only possible failure is an allocation error) */
michael@0 6208 /* ------------------------------------------------------------------ */
michael@0 6209 static Int decCompare(const decNumber *lhs, const decNumber *rhs,
michael@0 6210 Flag abs_c) {
michael@0 6211 Int result; /* result value */
michael@0 6212 Int sigr; /* rhs signum */
michael@0 6213 Int compare; /* work */
michael@0 6214
michael@0 6215 result=1; /* assume signum(lhs) */
michael@0 6216 if (ISZERO(lhs)) result=0;
michael@0 6217 if (abs_c) {
michael@0 6218 if (ISZERO(rhs)) return result; /* LHS wins or both 0 */
michael@0 6219 /* RHS is non-zero */
michael@0 6220 if (result==0) return -1; /* LHS is 0; RHS wins */
michael@0 6221 /* [here, both non-zero, result=1] */
michael@0 6222 }
michael@0 6223 else { /* signs matter */
michael@0 6224 if (result && decNumberIsNegative(lhs)) result=-1;
michael@0 6225 sigr=1; /* compute signum(rhs) */
michael@0 6226 if (ISZERO(rhs)) sigr=0;
michael@0 6227 else if (decNumberIsNegative(rhs)) sigr=-1;
michael@0 6228 if (result > sigr) return +1; /* L > R, return 1 */
michael@0 6229 if (result < sigr) return -1; /* L < R, return -1 */
michael@0 6230 if (result==0) return 0; /* both 0 */
michael@0 6231 }
michael@0 6232
michael@0 6233 /* signums are the same; both are non-zero */
michael@0 6234 if ((lhs->bits | rhs->bits) & DECINF) { /* one or more infinities */
michael@0 6235 if (decNumberIsInfinite(rhs)) {
michael@0 6236 if (decNumberIsInfinite(lhs)) result=0;/* both infinite */
michael@0 6237 else result=-result; /* only rhs infinite */
michael@0 6238 }
michael@0 6239 return result;
michael@0 6240 }
michael@0 6241 /* must compare the coefficients, allowing for exponents */
michael@0 6242 if (lhs->exponent>rhs->exponent) { /* LHS exponent larger */
michael@0 6243 /* swap sides, and sign */
michael@0 6244 const decNumber *temp=lhs;
michael@0 6245 lhs=rhs;
michael@0 6246 rhs=temp;
michael@0 6247 result=-result;
michael@0 6248 }
michael@0 6249 compare=decUnitCompare(lhs->lsu, D2U(lhs->digits),
michael@0 6250 rhs->lsu, D2U(rhs->digits),
michael@0 6251 rhs->exponent-lhs->exponent);
michael@0 6252 if (compare!=BADINT) compare*=result; /* comparison succeeded */
michael@0 6253 return compare;
michael@0 6254 } /* decCompare */
michael@0 6255
michael@0 6256 /* ------------------------------------------------------------------ */
michael@0 6257 /* decUnitCompare -- compare two >=0 integers in Unit arrays */
michael@0 6258 /* */
michael@0 6259 /* This routine compares A ? B*10**E where A and B are unit arrays */
michael@0 6260 /* A is a plain integer */
michael@0 6261 /* B has an exponent of E (which must be non-negative) */
michael@0 6262 /* */
michael@0 6263 /* Arg1 is A first Unit (lsu) */
michael@0 6264 /* Arg2 is A length in Units */
michael@0 6265 /* Arg3 is B first Unit (lsu) */
michael@0 6266 /* Arg4 is B length in Units */
michael@0 6267 /* Arg5 is E (0 if the units are aligned) */
michael@0 6268 /* */
michael@0 6269 /* returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure */
michael@0 6270 /* (the only possible failure is an allocation error, which can */
michael@0 6271 /* only occur if E!=0) */
michael@0 6272 /* ------------------------------------------------------------------ */
michael@0 6273 static Int decUnitCompare(const Unit *a, Int alength,
michael@0 6274 const Unit *b, Int blength, Int exp) {
michael@0 6275 Unit *acc; /* accumulator for result */
michael@0 6276 Unit accbuff[SD2U(DECBUFFER*2+1)]; /* local buffer */
michael@0 6277 Unit *allocacc=NULL; /* -> allocated acc buffer, iff allocated */
michael@0 6278 Int accunits, need; /* units in use or needed for acc */
michael@0 6279 const Unit *l, *r, *u; /* work */
michael@0 6280 Int expunits, exprem, result; /* .. */
michael@0 6281
michael@0 6282 if (exp==0) { /* aligned; fastpath */
michael@0 6283 if (alength>blength) return 1;
michael@0 6284 if (alength<blength) return -1;
michael@0 6285 /* same number of units in both -- need unit-by-unit compare */
michael@0 6286 l=a+alength-1;
michael@0 6287 r=b+alength-1;
michael@0 6288 for (;l>=a; l--, r--) {
michael@0 6289 if (*l>*r) return 1;
michael@0 6290 if (*l<*r) return -1;
michael@0 6291 }
michael@0 6292 return 0; /* all units match */
michael@0 6293 } /* aligned */
michael@0 6294
michael@0 6295 /* Unaligned. If one is >1 unit longer than the other, padded */
michael@0 6296 /* approximately, then can return easily */
michael@0 6297 if (alength>blength+(Int)D2U(exp)) return 1;
michael@0 6298 if (alength+1<blength+(Int)D2U(exp)) return -1;
michael@0 6299
michael@0 6300 /* Need to do a real subtract. For this, a result buffer is needed */
michael@0 6301 /* even though only the sign is of interest. Its length needs */
michael@0 6302 /* to be the larger of alength and padded blength, +2 */
michael@0 6303 need=blength+D2U(exp); /* maximum real length of B */
michael@0 6304 if (need<alength) need=alength;
michael@0 6305 need+=2;
michael@0 6306 acc=accbuff; /* assume use local buffer */
michael@0 6307 if (need*sizeof(Unit)>sizeof(accbuff)) {
michael@0 6308 allocacc=(Unit *)malloc(need*sizeof(Unit));
michael@0 6309 if (allocacc==NULL) return BADINT; /* hopeless -- abandon */
michael@0 6310 acc=allocacc;
michael@0 6311 }
michael@0 6312 /* Calculate units and remainder from exponent. */
michael@0 6313 expunits=exp/DECDPUN;
michael@0 6314 exprem=exp%DECDPUN;
michael@0 6315 /* subtract [A+B*(-m)] */
michael@0 6316 accunits=decUnitAddSub(a, alength, b, blength, expunits, acc,
michael@0 6317 -(Int)powers[exprem]);
michael@0 6318 /* [UnitAddSub result may have leading zeros, even on zero] */
michael@0 6319 if (accunits<0) result=-1; /* negative result */
michael@0 6320 else { /* non-negative result */
michael@0 6321 /* check units of the result before freeing any storage */
michael@0 6322 for (u=acc; u<acc+accunits-1 && *u==0;) u++;
michael@0 6323 result=(*u==0 ? 0 : +1);
michael@0 6324 }
michael@0 6325 /* clean up and return the result */
michael@0 6326 if (allocacc!=NULL) free(allocacc); /* drop any storage used */
michael@0 6327 return result;
michael@0 6328 } /* decUnitCompare */
michael@0 6329
michael@0 6330 /* ------------------------------------------------------------------ */
michael@0 6331 /* decUnitAddSub -- add or subtract two >=0 integers in Unit arrays */
michael@0 6332 /* */
michael@0 6333 /* This routine performs the calculation: */
michael@0 6334 /* */
michael@0 6335 /* C=A+(B*M) */
michael@0 6336 /* */
michael@0 6337 /* Where M is in the range -DECDPUNMAX through +DECDPUNMAX. */
michael@0 6338 /* */
michael@0 6339 /* A may be shorter or longer than B. */
michael@0 6340 /* */
michael@0 6341 /* Leading zeros are not removed after a calculation. The result is */
michael@0 6342 /* either the same length as the longer of A and B (adding any */
michael@0 6343 /* shift), or one Unit longer than that (if a Unit carry occurred). */
michael@0 6344 /* */
michael@0 6345 /* A and B content are not altered unless C is also A or B. */
michael@0 6346 /* C may be the same array as A or B, but only if no zero padding is */
michael@0 6347 /* requested (that is, C may be B only if bshift==0). */
michael@0 6348 /* C is filled from the lsu; only those units necessary to complete */
michael@0 6349 /* the calculation are referenced. */
michael@0 6350 /* */
michael@0 6351 /* Arg1 is A first Unit (lsu) */
michael@0 6352 /* Arg2 is A length in Units */
michael@0 6353 /* Arg3 is B first Unit (lsu) */
michael@0 6354 /* Arg4 is B length in Units */
michael@0 6355 /* Arg5 is B shift in Units (>=0; pads with 0 units if positive) */
michael@0 6356 /* Arg6 is C first Unit (lsu) */
michael@0 6357 /* Arg7 is M, the multiplier */
michael@0 6358 /* */
michael@0 6359 /* returns the count of Units written to C, which will be non-zero */
michael@0 6360 /* and negated if the result is negative. That is, the sign of the */
michael@0 6361 /* returned Int is the sign of the result (positive for zero) and */
michael@0 6362 /* the absolute value of the Int is the count of Units. */
michael@0 6363 /* */
michael@0 6364 /* It is the caller's responsibility to make sure that C size is */
michael@0 6365 /* safe, allowing space if necessary for a one-Unit carry. */
michael@0 6366 /* */
michael@0 6367 /* This routine is severely performance-critical; *any* change here */
michael@0 6368 /* must be measured (timed) to assure no performance degradation. */
michael@0 6369 /* In particular, trickery here tends to be counter-productive, as */
michael@0 6370 /* increased complexity of code hurts register optimizations on */
michael@0 6371 /* register-poor architectures. Avoiding divisions is nearly */
michael@0 6372 /* always a Good Idea, however. */
michael@0 6373 /* */
michael@0 6374 /* Special thanks to Rick McGuire (IBM Cambridge, MA) and Dave Clark */
michael@0 6375 /* (IBM Warwick, UK) for some of the ideas used in this routine. */
michael@0 6376 /* ------------------------------------------------------------------ */
michael@0 6377 static Int decUnitAddSub(const Unit *a, Int alength,
michael@0 6378 const Unit *b, Int blength, Int bshift,
michael@0 6379 Unit *c, Int m) {
michael@0 6380 const Unit *alsu=a; /* A lsu [need to remember it] */
michael@0 6381 Unit *clsu=c; /* C ditto */
michael@0 6382 Unit *minC; /* low water mark for C */
michael@0 6383 Unit *maxC; /* high water mark for C */
michael@0 6384 eInt carry=0; /* carry integer (could be Long) */
michael@0 6385 Int add; /* work */
michael@0 6386 #if DECDPUN<=4 /* myriadal, millenary, etc. */
michael@0 6387 Int est; /* estimated quotient */
michael@0 6388 #endif
michael@0 6389
michael@0 6390 #if DECTRACE
michael@0 6391 if (alength<1 || blength<1)
michael@0 6392 printf("decUnitAddSub: alen blen m %ld %ld [%ld]\n", alength, blength, m);
michael@0 6393 #endif
michael@0 6394
michael@0 6395 maxC=c+alength; /* A is usually the longer */
michael@0 6396 minC=c+blength; /* .. and B the shorter */
michael@0 6397 if (bshift!=0) { /* B is shifted; low As copy across */
michael@0 6398 minC+=bshift;
michael@0 6399 /* if in place [common], skip copy unless there's a gap [rare] */
michael@0 6400 if (a==c && bshift<=alength) {
michael@0 6401 c+=bshift;
michael@0 6402 a+=bshift;
michael@0 6403 }
michael@0 6404 else for (; c<clsu+bshift; a++, c++) { /* copy needed */
michael@0 6405 if (a<alsu+alength) *c=*a;
michael@0 6406 else *c=0;
michael@0 6407 }
michael@0 6408 }
michael@0 6409 if (minC>maxC) { /* swap */
michael@0 6410 Unit *hold=minC;
michael@0 6411 minC=maxC;
michael@0 6412 maxC=hold;
michael@0 6413 }
michael@0 6414
michael@0 6415 /* For speed, do the addition as two loops; the first where both A */
michael@0 6416 /* and B contribute, and the second (if necessary) where only one or */
michael@0 6417 /* other of the numbers contribute. */
michael@0 6418 /* Carry handling is the same (i.e., duplicated) in each case. */
michael@0 6419 for (; c<minC; c++) {
michael@0 6420 carry+=*a;
michael@0 6421 a++;
michael@0 6422 carry+=((eInt)*b)*m; /* [special-casing m=1/-1 */
michael@0 6423 b++; /* here is not a win] */
michael@0 6424 /* here carry is new Unit of digits; it could be +ve or -ve */
michael@0 6425 if ((ueInt)carry<=DECDPUNMAX) { /* fastpath 0-DECDPUNMAX */
michael@0 6426 *c=(Unit)carry;
michael@0 6427 carry=0;
michael@0 6428 continue;
michael@0 6429 }
michael@0 6430 #if DECDPUN==4 /* use divide-by-multiply */
michael@0 6431 if (carry>=0) {
michael@0 6432 est=(((ueInt)carry>>11)*53687)>>18;
michael@0 6433 *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
michael@0 6434 carry=est; /* likely quotient [89%] */
michael@0 6435 if (*c<DECDPUNMAX+1) continue; /* estimate was correct */
michael@0 6436 carry++;
michael@0 6437 *c-=DECDPUNMAX+1;
michael@0 6438 continue;
michael@0 6439 }
michael@0 6440 /* negative case */
michael@0 6441 carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
michael@0 6442 est=(((ueInt)carry>>11)*53687)>>18;
michael@0 6443 *c=(Unit)(carry-est*(DECDPUNMAX+1));
michael@0 6444 carry=est-(DECDPUNMAX+1); /* correctly negative */
michael@0 6445 if (*c<DECDPUNMAX+1) continue; /* was OK */
michael@0 6446 carry++;
michael@0 6447 *c-=DECDPUNMAX+1;
michael@0 6448 #elif DECDPUN==3
michael@0 6449 if (carry>=0) {
michael@0 6450 est=(((ueInt)carry>>3)*16777)>>21;
michael@0 6451 *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
michael@0 6452 carry=est; /* likely quotient [99%] */
michael@0 6453 if (*c<DECDPUNMAX+1) continue; /* estimate was correct */
michael@0 6454 carry++;
michael@0 6455 *c-=DECDPUNMAX+1;
michael@0 6456 continue;
michael@0 6457 }
michael@0 6458 /* negative case */
michael@0 6459 carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
michael@0 6460 est=(((ueInt)carry>>3)*16777)>>21;
michael@0 6461 *c=(Unit)(carry-est*(DECDPUNMAX+1));
michael@0 6462 carry=est-(DECDPUNMAX+1); /* correctly negative */
michael@0 6463 if (*c<DECDPUNMAX+1) continue; /* was OK */
michael@0 6464 carry++;
michael@0 6465 *c-=DECDPUNMAX+1;
michael@0 6466 #elif DECDPUN<=2
michael@0 6467 /* Can use QUOT10 as carry <= 4 digits */
michael@0 6468 if (carry>=0) {
michael@0 6469 est=QUOT10(carry, DECDPUN);
michael@0 6470 *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
michael@0 6471 carry=est; /* quotient */
michael@0 6472 continue;
michael@0 6473 }
michael@0 6474 /* negative case */
michael@0 6475 carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
michael@0 6476 est=QUOT10(carry, DECDPUN);
michael@0 6477 *c=(Unit)(carry-est*(DECDPUNMAX+1));
michael@0 6478 carry=est-(DECDPUNMAX+1); /* correctly negative */
michael@0 6479 #else
michael@0 6480 /* remainder operator is undefined if negative, so must test */
michael@0 6481 if ((ueInt)carry<(DECDPUNMAX+1)*2) { /* fastpath carry +1 */
michael@0 6482 *c=(Unit)(carry-(DECDPUNMAX+1)); /* [helps additions] */
michael@0 6483 carry=1;
michael@0 6484 continue;
michael@0 6485 }
michael@0 6486 if (carry>=0) {
michael@0 6487 *c=(Unit)(carry%(DECDPUNMAX+1));
michael@0 6488 carry=carry/(DECDPUNMAX+1);
michael@0 6489 continue;
michael@0 6490 }
michael@0 6491 /* negative case */
michael@0 6492 carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
michael@0 6493 *c=(Unit)(carry%(DECDPUNMAX+1));
michael@0 6494 carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1);
michael@0 6495 #endif
michael@0 6496 } /* c */
michael@0 6497
michael@0 6498 /* now may have one or other to complete */
michael@0 6499 /* [pretest to avoid loop setup/shutdown] */
michael@0 6500 if (c<maxC) for (; c<maxC; c++) {
michael@0 6501 if (a<alsu+alength) { /* still in A */
michael@0 6502 carry+=*a;
michael@0 6503 a++;
michael@0 6504 }
michael@0 6505 else { /* inside B */
michael@0 6506 carry+=((eInt)*b)*m;
michael@0 6507 b++;
michael@0 6508 }
michael@0 6509 /* here carry is new Unit of digits; it could be +ve or -ve and */
michael@0 6510 /* magnitude up to DECDPUNMAX squared */
michael@0 6511 if ((ueInt)carry<=DECDPUNMAX) { /* fastpath 0-DECDPUNMAX */
michael@0 6512 *c=(Unit)carry;
michael@0 6513 carry=0;
michael@0 6514 continue;
michael@0 6515 }
michael@0 6516 /* result for this unit is negative or >DECDPUNMAX */
michael@0 6517 #if DECDPUN==4 /* use divide-by-multiply */
michael@0 6518 if (carry>=0) {
michael@0 6519 est=(((ueInt)carry>>11)*53687)>>18;
michael@0 6520 *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
michael@0 6521 carry=est; /* likely quotient [79.7%] */
michael@0 6522 if (*c<DECDPUNMAX+1) continue; /* estimate was correct */
michael@0 6523 carry++;
michael@0 6524 *c-=DECDPUNMAX+1;
michael@0 6525 continue;
michael@0 6526 }
michael@0 6527 /* negative case */
michael@0 6528 carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
michael@0 6529 est=(((ueInt)carry>>11)*53687)>>18;
michael@0 6530 *c=(Unit)(carry-est*(DECDPUNMAX+1));
michael@0 6531 carry=est-(DECDPUNMAX+1); /* correctly negative */
michael@0 6532 if (*c<DECDPUNMAX+1) continue; /* was OK */
michael@0 6533 carry++;
michael@0 6534 *c-=DECDPUNMAX+1;
michael@0 6535 #elif DECDPUN==3
michael@0 6536 if (carry>=0) {
michael@0 6537 est=(((ueInt)carry>>3)*16777)>>21;
michael@0 6538 *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
michael@0 6539 carry=est; /* likely quotient [99%] */
michael@0 6540 if (*c<DECDPUNMAX+1) continue; /* estimate was correct */
michael@0 6541 carry++;
michael@0 6542 *c-=DECDPUNMAX+1;
michael@0 6543 continue;
michael@0 6544 }
michael@0 6545 /* negative case */
michael@0 6546 carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
michael@0 6547 est=(((ueInt)carry>>3)*16777)>>21;
michael@0 6548 *c=(Unit)(carry-est*(DECDPUNMAX+1));
michael@0 6549 carry=est-(DECDPUNMAX+1); /* correctly negative */
michael@0 6550 if (*c<DECDPUNMAX+1) continue; /* was OK */
michael@0 6551 carry++;
michael@0 6552 *c-=DECDPUNMAX+1;
michael@0 6553 #elif DECDPUN<=2
michael@0 6554 if (carry>=0) {
michael@0 6555 est=QUOT10(carry, DECDPUN);
michael@0 6556 *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
michael@0 6557 carry=est; /* quotient */
michael@0 6558 continue;
michael@0 6559 }
michael@0 6560 /* negative case */
michael@0 6561 carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
michael@0 6562 est=QUOT10(carry, DECDPUN);
michael@0 6563 *c=(Unit)(carry-est*(DECDPUNMAX+1));
michael@0 6564 carry=est-(DECDPUNMAX+1); /* correctly negative */
michael@0 6565 #else
michael@0 6566 if ((ueInt)carry<(DECDPUNMAX+1)*2){ /* fastpath carry 1 */
michael@0 6567 *c=(Unit)(carry-(DECDPUNMAX+1));
michael@0 6568 carry=1;
michael@0 6569 continue;
michael@0 6570 }
michael@0 6571 /* remainder operator is undefined if negative, so must test */
michael@0 6572 if (carry>=0) {
michael@0 6573 *c=(Unit)(carry%(DECDPUNMAX+1));
michael@0 6574 carry=carry/(DECDPUNMAX+1);
michael@0 6575 continue;
michael@0 6576 }
michael@0 6577 /* negative case */
michael@0 6578 carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
michael@0 6579 *c=(Unit)(carry%(DECDPUNMAX+1));
michael@0 6580 carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1);
michael@0 6581 #endif
michael@0 6582 } /* c */
michael@0 6583
michael@0 6584 /* OK, all A and B processed; might still have carry or borrow */
michael@0 6585 /* return number of Units in the result, negated if a borrow */
michael@0 6586 if (carry==0) return c-clsu; /* no carry, so no more to do */
michael@0 6587 if (carry>0) { /* positive carry */
michael@0 6588 *c=(Unit)carry; /* place as new unit */
michael@0 6589 c++; /* .. */
michael@0 6590 return c-clsu;
michael@0 6591 }
michael@0 6592 /* -ve carry: it's a borrow; complement needed */
michael@0 6593 add=1; /* temporary carry... */
michael@0 6594 for (c=clsu; c<maxC; c++) {
michael@0 6595 add=DECDPUNMAX+add-*c;
michael@0 6596 if (add<=DECDPUNMAX) {
michael@0 6597 *c=(Unit)add;
michael@0 6598 add=0;
michael@0 6599 }
michael@0 6600 else {
michael@0 6601 *c=0;
michael@0 6602 add=1;
michael@0 6603 }
michael@0 6604 }
michael@0 6605 /* add an extra unit iff it would be non-zero */
michael@0 6606 #if DECTRACE
michael@0 6607 printf("UAS borrow: add %ld, carry %ld\n", add, carry);
michael@0 6608 #endif
michael@0 6609 if ((add-carry-1)!=0) {
michael@0 6610 *c=(Unit)(add-carry-1);
michael@0 6611 c++; /* interesting, include it */
michael@0 6612 }
michael@0 6613 return clsu-c; /* -ve result indicates borrowed */
michael@0 6614 } /* decUnitAddSub */
michael@0 6615
michael@0 6616 /* ------------------------------------------------------------------ */
michael@0 6617 /* decTrim -- trim trailing zeros or normalize */
michael@0 6618 /* */
michael@0 6619 /* dn is the number to trim or normalize */
michael@0 6620 /* set is the context to use to check for clamp */
michael@0 6621 /* all is 1 to remove all trailing zeros, 0 for just fraction ones */
michael@0 6622 /* noclamp is 1 to unconditional (unclamped) trim */
michael@0 6623 /* dropped returns the number of discarded trailing zeros */
michael@0 6624 /* returns dn */
michael@0 6625 /* */
michael@0 6626 /* If clamp is set in the context then the number of zeros trimmed */
michael@0 6627 /* may be limited if the exponent is high. */
michael@0 6628 /* All fields are updated as required. This is a utility operation, */
michael@0 6629 /* so special values are unchanged and no error is possible. */
michael@0 6630 /* ------------------------------------------------------------------ */
michael@0 6631 static decNumber * decTrim(decNumber *dn, decContext *set, Flag all,
michael@0 6632 Flag noclamp, Int *dropped) {
michael@0 6633 Int d, exp; /* work */
michael@0 6634 uInt cut; /* .. */
michael@0 6635 Unit *up; /* -> current Unit */
michael@0 6636
michael@0 6637 #if DECCHECK
michael@0 6638 if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn;
michael@0 6639 #endif
michael@0 6640
michael@0 6641 *dropped=0; /* assume no zeros dropped */
michael@0 6642 if ((dn->bits & DECSPECIAL) /* fast exit if special .. */
michael@0 6643 || (*dn->lsu & 0x01)) return dn; /* .. or odd */
michael@0 6644 if (ISZERO(dn)) { /* .. or 0 */
michael@0 6645 dn->exponent=0; /* (sign is preserved) */
michael@0 6646 return dn;
michael@0 6647 }
michael@0 6648
michael@0 6649 /* have a finite number which is even */
michael@0 6650 exp=dn->exponent;
michael@0 6651 cut=1; /* digit (1-DECDPUN) in Unit */
michael@0 6652 up=dn->lsu; /* -> current Unit */
michael@0 6653 for (d=0; d<dn->digits-1; d++) { /* [don't strip the final digit] */
michael@0 6654 /* slice by powers */
michael@0 6655 #if DECDPUN<=4
michael@0 6656 uInt quot=QUOT10(*up, cut);
michael@0 6657 if ((*up-quot*powers[cut])!=0) break; /* found non-0 digit */
michael@0 6658 #else
michael@0 6659 if (*up%powers[cut]!=0) break; /* found non-0 digit */
michael@0 6660 #endif
michael@0 6661 /* have a trailing 0 */
michael@0 6662 if (!all) { /* trimming */
michael@0 6663 /* [if exp>0 then all trailing 0s are significant for trim] */
michael@0 6664 if (exp<=0) { /* if digit might be significant */
michael@0 6665 if (exp==0) break; /* then quit */
michael@0 6666 exp++; /* next digit might be significant */
michael@0 6667 }
michael@0 6668 }
michael@0 6669 cut++; /* next power */
michael@0 6670 if (cut>DECDPUN) { /* need new Unit */
michael@0 6671 up++;
michael@0 6672 cut=1;
michael@0 6673 }
michael@0 6674 } /* d */
michael@0 6675 if (d==0) return dn; /* none to drop */
michael@0 6676
michael@0 6677 /* may need to limit drop if clamping */
michael@0 6678 if (set->clamp && !noclamp) {
michael@0 6679 Int maxd=set->emax-set->digits+1-dn->exponent;
michael@0 6680 if (maxd<=0) return dn; /* nothing possible */
michael@0 6681 if (d>maxd) d=maxd;
michael@0 6682 }
michael@0 6683
michael@0 6684 /* effect the drop */
michael@0 6685 decShiftToLeast(dn->lsu, D2U(dn->digits), d);
michael@0 6686 dn->exponent+=d; /* maintain numerical value */
michael@0 6687 dn->digits-=d; /* new length */
michael@0 6688 *dropped=d; /* report the count */
michael@0 6689 return dn;
michael@0 6690 } /* decTrim */
michael@0 6691
michael@0 6692 /* ------------------------------------------------------------------ */
michael@0 6693 /* decReverse -- reverse a Unit array in place */
michael@0 6694 /* */
michael@0 6695 /* ulo is the start of the array */
michael@0 6696 /* uhi is the end of the array (highest Unit to include) */
michael@0 6697 /* */
michael@0 6698 /* The units ulo through uhi are reversed in place (if the number */
michael@0 6699 /* of units is odd, the middle one is untouched). Note that the */
michael@0 6700 /* digit(s) in each unit are unaffected. */
michael@0 6701 /* ------------------------------------------------------------------ */
michael@0 6702 static void decReverse(Unit *ulo, Unit *uhi) {
michael@0 6703 Unit temp;
michael@0 6704 for (; ulo<uhi; ulo++, uhi--) {
michael@0 6705 temp=*ulo;
michael@0 6706 *ulo=*uhi;
michael@0 6707 *uhi=temp;
michael@0 6708 }
michael@0 6709 return;
michael@0 6710 } /* decReverse */
michael@0 6711
michael@0 6712 /* ------------------------------------------------------------------ */
michael@0 6713 /* decShiftToMost -- shift digits in array towards most significant */
michael@0 6714 /* */
michael@0 6715 /* uar is the array */
michael@0 6716 /* digits is the count of digits in use in the array */
michael@0 6717 /* shift is the number of zeros to pad with (least significant); */
michael@0 6718 /* it must be zero or positive */
michael@0 6719 /* */
michael@0 6720 /* returns the new length of the integer in the array, in digits */
michael@0 6721 /* */
michael@0 6722 /* No overflow is permitted (that is, the uar array must be known to */
michael@0 6723 /* be large enough to hold the result, after shifting). */
michael@0 6724 /* ------------------------------------------------------------------ */
michael@0 6725 static Int decShiftToMost(Unit *uar, Int digits, Int shift) {
michael@0 6726 Unit *target, *source, *first; /* work */
michael@0 6727 Int cut; /* odd 0's to add */
michael@0 6728 uInt next; /* work */
michael@0 6729
michael@0 6730 if (shift==0) return digits; /* [fastpath] nothing to do */
michael@0 6731 if ((digits+shift)<=DECDPUN) { /* [fastpath] single-unit case */
michael@0 6732 *uar=(Unit)(*uar*powers[shift]);
michael@0 6733 return digits+shift;
michael@0 6734 }
michael@0 6735
michael@0 6736 next=0; /* all paths */
michael@0 6737 source=uar+D2U(digits)-1; /* where msu comes from */
michael@0 6738 target=source+D2U(shift); /* where upper part of first cut goes */
michael@0 6739 cut=DECDPUN-MSUDIGITS(shift); /* where to slice */
michael@0 6740 if (cut==0) { /* unit-boundary case */
michael@0 6741 for (; source>=uar; source--, target--) *target=*source;
michael@0 6742 }
michael@0 6743 else {
michael@0 6744 first=uar+D2U(digits+shift)-1; /* where msu of source will end up */
michael@0 6745 for (; source>=uar; source--, target--) {
michael@0 6746 /* split the source Unit and accumulate remainder for next */
michael@0 6747 #if DECDPUN<=4
michael@0 6748 uInt quot=QUOT10(*source, cut);
michael@0 6749 uInt rem=*source-quot*powers[cut];
michael@0 6750 next+=quot;
michael@0 6751 #else
michael@0 6752 uInt rem=*source%powers[cut];
michael@0 6753 next+=*source/powers[cut];
michael@0 6754 #endif
michael@0 6755 if (target<=first) *target=(Unit)next; /* write to target iff valid */
michael@0 6756 next=rem*powers[DECDPUN-cut]; /* save remainder for next Unit */
michael@0 6757 }
michael@0 6758 } /* shift-move */
michael@0 6759
michael@0 6760 /* propagate any partial unit to one below and clear the rest */
michael@0 6761 for (; target>=uar; target--) {
michael@0 6762 *target=(Unit)next;
michael@0 6763 next=0;
michael@0 6764 }
michael@0 6765 return digits+shift;
michael@0 6766 } /* decShiftToMost */
michael@0 6767
michael@0 6768 /* ------------------------------------------------------------------ */
michael@0 6769 /* decShiftToLeast -- shift digits in array towards least significant */
michael@0 6770 /* */
michael@0 6771 /* uar is the array */
michael@0 6772 /* units is length of the array, in units */
michael@0 6773 /* shift is the number of digits to remove from the lsu end; it */
michael@0 6774 /* must be zero or positive and <= than units*DECDPUN. */
michael@0 6775 /* */
michael@0 6776 /* returns the new length of the integer in the array, in units */
michael@0 6777 /* */
michael@0 6778 /* Removed digits are discarded (lost). Units not required to hold */
michael@0 6779 /* the final result are unchanged. */
michael@0 6780 /* ------------------------------------------------------------------ */
michael@0 6781 static Int decShiftToLeast(Unit *uar, Int units, Int shift) {
michael@0 6782 Unit *target, *up; /* work */
michael@0 6783 Int cut, count; /* work */
michael@0 6784 Int quot, rem; /* for division */
michael@0 6785
michael@0 6786 if (shift==0) return units; /* [fastpath] nothing to do */
michael@0 6787 if (shift==units*DECDPUN) { /* [fastpath] little to do */
michael@0 6788 *uar=0; /* all digits cleared gives zero */
michael@0 6789 return 1; /* leaves just the one */
michael@0 6790 }
michael@0 6791
michael@0 6792 target=uar; /* both paths */
michael@0 6793 cut=MSUDIGITS(shift);
michael@0 6794 if (cut==DECDPUN) { /* unit-boundary case; easy */
michael@0 6795 up=uar+D2U(shift);
michael@0 6796 for (; up<uar+units; target++, up++) *target=*up;
michael@0 6797 return target-uar;
michael@0 6798 }
michael@0 6799
michael@0 6800 /* messier */
michael@0 6801 up=uar+D2U(shift-cut); /* source; correct to whole Units */
michael@0 6802 count=units*DECDPUN-shift; /* the maximum new length */
michael@0 6803 #if DECDPUN<=4
michael@0 6804 quot=QUOT10(*up, cut);
michael@0 6805 #else
michael@0 6806 quot=*up/powers[cut];
michael@0 6807 #endif
michael@0 6808 for (; ; target++) {
michael@0 6809 *target=(Unit)quot;
michael@0 6810 count-=(DECDPUN-cut);
michael@0 6811 if (count<=0) break;
michael@0 6812 up++;
michael@0 6813 quot=*up;
michael@0 6814 #if DECDPUN<=4
michael@0 6815 quot=QUOT10(quot, cut);
michael@0 6816 rem=*up-quot*powers[cut];
michael@0 6817 #else
michael@0 6818 rem=quot%powers[cut];
michael@0 6819 quot=quot/powers[cut];
michael@0 6820 #endif
michael@0 6821 *target=(Unit)(*target+rem*powers[DECDPUN-cut]);
michael@0 6822 count-=cut;
michael@0 6823 if (count<=0) break;
michael@0 6824 }
michael@0 6825 return target-uar+1;
michael@0 6826 } /* decShiftToLeast */
michael@0 6827
michael@0 6828 #if DECSUBSET
michael@0 6829 /* ------------------------------------------------------------------ */
michael@0 6830 /* decRoundOperand -- round an operand [used for subset only] */
michael@0 6831 /* */
michael@0 6832 /* dn is the number to round (dn->digits is > set->digits) */
michael@0 6833 /* set is the relevant context */
michael@0 6834 /* status is the status accumulator */
michael@0 6835 /* */
michael@0 6836 /* returns an allocated decNumber with the rounded result. */
michael@0 6837 /* */
michael@0 6838 /* lostDigits and other status may be set by this. */
michael@0 6839 /* */
michael@0 6840 /* Since the input is an operand, it must not be modified. */
michael@0 6841 /* Instead, return an allocated decNumber, rounded as required. */
michael@0 6842 /* It is the caller's responsibility to free the allocated storage. */
michael@0 6843 /* */
michael@0 6844 /* If no storage is available then the result cannot be used, so NULL */
michael@0 6845 /* is returned. */
michael@0 6846 /* ------------------------------------------------------------------ */
michael@0 6847 static decNumber *decRoundOperand(const decNumber *dn, decContext *set,
michael@0 6848 uInt *status) {
michael@0 6849 decNumber *res; /* result structure */
michael@0 6850 uInt newstatus=0; /* status from round */
michael@0 6851 Int residue=0; /* rounding accumulator */
michael@0 6852
michael@0 6853 /* Allocate storage for the returned decNumber, big enough for the */
michael@0 6854 /* length specified by the context */
michael@0 6855 res=(decNumber *)malloc(sizeof(decNumber)
michael@0 6856 +(D2U(set->digits)-1)*sizeof(Unit));
michael@0 6857 if (res==NULL) {
michael@0 6858 *status|=DEC_Insufficient_storage;
michael@0 6859 return NULL;
michael@0 6860 }
michael@0 6861 decCopyFit(res, dn, set, &residue, &newstatus);
michael@0 6862 decApplyRound(res, set, residue, &newstatus);
michael@0 6863
michael@0 6864 /* If that set Inexact then "lost digits" is raised... */
michael@0 6865 if (newstatus & DEC_Inexact) newstatus|=DEC_Lost_digits;
michael@0 6866 *status|=newstatus;
michael@0 6867 return res;
michael@0 6868 } /* decRoundOperand */
michael@0 6869 #endif
michael@0 6870
michael@0 6871 /* ------------------------------------------------------------------ */
michael@0 6872 /* decCopyFit -- copy a number, truncating the coefficient if needed */
michael@0 6873 /* */
michael@0 6874 /* dest is the target decNumber */
michael@0 6875 /* src is the source decNumber */
michael@0 6876 /* set is the context [used for length (digits) and rounding mode] */
michael@0 6877 /* residue is the residue accumulator */
michael@0 6878 /* status contains the current status to be updated */
michael@0 6879 /* */
michael@0 6880 /* (dest==src is allowed and will be a no-op if fits) */
michael@0 6881 /* All fields are updated as required. */
michael@0 6882 /* ------------------------------------------------------------------ */
michael@0 6883 static void decCopyFit(decNumber *dest, const decNumber *src,
michael@0 6884 decContext *set, Int *residue, uInt *status) {
michael@0 6885 dest->bits=src->bits;
michael@0 6886 dest->exponent=src->exponent;
michael@0 6887 decSetCoeff(dest, set, src->lsu, src->digits, residue, status);
michael@0 6888 } /* decCopyFit */
michael@0 6889
michael@0 6890 /* ------------------------------------------------------------------ */
michael@0 6891 /* decSetCoeff -- set the coefficient of a number */
michael@0 6892 /* */
michael@0 6893 /* dn is the number whose coefficient array is to be set. */
michael@0 6894 /* It must have space for set->digits digits */
michael@0 6895 /* set is the context [for size] */
michael@0 6896 /* lsu -> lsu of the source coefficient [may be dn->lsu] */
michael@0 6897 /* len is digits in the source coefficient [may be dn->digits] */
michael@0 6898 /* residue is the residue accumulator. This has values as in */
michael@0 6899 /* decApplyRound, and will be unchanged unless the */
michael@0 6900 /* target size is less than len. In this case, the */
michael@0 6901 /* coefficient is truncated and the residue is updated to */
michael@0 6902 /* reflect the previous residue and the dropped digits. */
michael@0 6903 /* status is the status accumulator, as usual */
michael@0 6904 /* */
michael@0 6905 /* The coefficient may already be in the number, or it can be an */
michael@0 6906 /* external intermediate array. If it is in the number, lsu must == */
michael@0 6907 /* dn->lsu and len must == dn->digits. */
michael@0 6908 /* */
michael@0 6909 /* Note that the coefficient length (len) may be < set->digits, and */
michael@0 6910 /* in this case this merely copies the coefficient (or is a no-op */
michael@0 6911 /* if dn->lsu==lsu). */
michael@0 6912 /* */
michael@0 6913 /* Note also that (only internally, from decQuantizeOp and */
michael@0 6914 /* decSetSubnormal) the value of set->digits may be less than one, */
michael@0 6915 /* indicating a round to left. This routine handles that case */
michael@0 6916 /* correctly; caller ensures space. */
michael@0 6917 /* */
michael@0 6918 /* dn->digits, dn->lsu (and as required), and dn->exponent are */
michael@0 6919 /* updated as necessary. dn->bits (sign) is unchanged. */
michael@0 6920 /* */
michael@0 6921 /* DEC_Rounded status is set if any digits are discarded. */
michael@0 6922 /* DEC_Inexact status is set if any non-zero digits are discarded, or */
michael@0 6923 /* incoming residue was non-0 (implies rounded) */
michael@0 6924 /* ------------------------------------------------------------------ */
michael@0 6925 /* mapping array: maps 0-9 to canonical residues, so that a residue */
michael@0 6926 /* can be adjusted in the range [-1, +1] and achieve correct rounding */
michael@0 6927 /* 0 1 2 3 4 5 6 7 8 9 */
michael@0 6928 static const uByte resmap[10]={0, 3, 3, 3, 3, 5, 7, 7, 7, 7};
michael@0 6929 static void decSetCoeff(decNumber *dn, decContext *set, const Unit *lsu,
michael@0 6930 Int len, Int *residue, uInt *status) {
michael@0 6931 Int discard; /* number of digits to discard */
michael@0 6932 uInt cut; /* cut point in Unit */
michael@0 6933 const Unit *up; /* work */
michael@0 6934 Unit *target; /* .. */
michael@0 6935 Int count; /* .. */
michael@0 6936 #if DECDPUN<=4
michael@0 6937 uInt temp; /* .. */
michael@0 6938 #endif
michael@0 6939
michael@0 6940 discard=len-set->digits; /* digits to discard */
michael@0 6941 if (discard<=0) { /* no digits are being discarded */
michael@0 6942 if (dn->lsu!=lsu) { /* copy needed */
michael@0 6943 /* copy the coefficient array to the result number; no shift needed */
michael@0 6944 count=len; /* avoids D2U */
michael@0 6945 up=lsu;
michael@0 6946 for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN)
michael@0 6947 *target=*up;
michael@0 6948 dn->digits=len; /* set the new length */
michael@0 6949 }
michael@0 6950 /* dn->exponent and residue are unchanged, record any inexactitude */
michael@0 6951 if (*residue!=0) *status|=(DEC_Inexact | DEC_Rounded);
michael@0 6952 return;
michael@0 6953 }
michael@0 6954
michael@0 6955 /* some digits must be discarded ... */
michael@0 6956 dn->exponent+=discard; /* maintain numerical value */
michael@0 6957 *status|=DEC_Rounded; /* accumulate Rounded status */
michael@0 6958 if (*residue>1) *residue=1; /* previous residue now to right, so reduce */
michael@0 6959
michael@0 6960 if (discard>len) { /* everything, +1, is being discarded */
michael@0 6961 /* guard digit is 0 */
michael@0 6962 /* residue is all the number [NB could be all 0s] */
michael@0 6963 if (*residue<=0) { /* not already positive */
michael@0 6964 count=len; /* avoids D2U */
michael@0 6965 for (up=lsu; count>0; up++, count-=DECDPUN) if (*up!=0) { /* found non-0 */
michael@0 6966 *residue=1;
michael@0 6967 break; /* no need to check any others */
michael@0 6968 }
michael@0 6969 }
michael@0 6970 if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */
michael@0 6971 *dn->lsu=0; /* coefficient will now be 0 */
michael@0 6972 dn->digits=1; /* .. */
michael@0 6973 return;
michael@0 6974 } /* total discard */
michael@0 6975
michael@0 6976 /* partial discard [most common case] */
michael@0 6977 /* here, at least the first (most significant) discarded digit exists */
michael@0 6978
michael@0 6979 /* spin up the number, noting residue during the spin, until get to */
michael@0 6980 /* the Unit with the first discarded digit. When reach it, extract */
michael@0 6981 /* it and remember its position */
michael@0 6982 count=0;
michael@0 6983 for (up=lsu;; up++) {
michael@0 6984 count+=DECDPUN;
michael@0 6985 if (count>=discard) break; /* full ones all checked */
michael@0 6986 if (*up!=0) *residue=1;
michael@0 6987 } /* up */
michael@0 6988
michael@0 6989 /* here up -> Unit with first discarded digit */
michael@0 6990 cut=discard-(count-DECDPUN)-1;
michael@0 6991 if (cut==DECDPUN-1) { /* unit-boundary case (fast) */
michael@0 6992 Unit half=(Unit)powers[DECDPUN]>>1;
michael@0 6993 /* set residue directly */
michael@0 6994 if (*up>=half) {
michael@0 6995 if (*up>half) *residue=7;
michael@0 6996 else *residue+=5; /* add sticky bit */
michael@0 6997 }
michael@0 6998 else { /* <half */
michael@0 6999 if (*up!=0) *residue=3; /* [else is 0, leave as sticky bit] */
michael@0 7000 }
michael@0 7001 if (set->digits<=0) { /* special for Quantize/Subnormal :-( */
michael@0 7002 *dn->lsu=0; /* .. result is 0 */
michael@0 7003 dn->digits=1; /* .. */
michael@0 7004 }
michael@0 7005 else { /* shift to least */
michael@0 7006 count=set->digits; /* now digits to end up with */
michael@0 7007 dn->digits=count; /* set the new length */
michael@0 7008 up++; /* move to next */
michael@0 7009 /* on unit boundary, so shift-down copy loop is simple */
michael@0 7010 for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN)
michael@0 7011 *target=*up;
michael@0 7012 }
michael@0 7013 } /* unit-boundary case */
michael@0 7014
michael@0 7015 else { /* discard digit is in low digit(s), and not top digit */
michael@0 7016 uInt discard1; /* first discarded digit */
michael@0 7017 uInt quot, rem; /* for divisions */
michael@0 7018 if (cut==0) quot=*up; /* is at bottom of unit */
michael@0 7019 else /* cut>0 */ { /* it's not at bottom of unit */
michael@0 7020 #if DECDPUN<=4
michael@0 7021 U_ASSERT(/* cut >= 0 &&*/ cut <= 4);
michael@0 7022 quot=QUOT10(*up, cut);
michael@0 7023 rem=*up-quot*powers[cut];
michael@0 7024 #else
michael@0 7025 rem=*up%powers[cut];
michael@0 7026 quot=*up/powers[cut];
michael@0 7027 #endif
michael@0 7028 if (rem!=0) *residue=1;
michael@0 7029 }
michael@0 7030 /* discard digit is now at bottom of quot */
michael@0 7031 #if DECDPUN<=4
michael@0 7032 temp=(quot*6554)>>16; /* fast /10 */
michael@0 7033 /* Vowels algorithm here not a win (9 instructions) */
michael@0 7034 discard1=quot-X10(temp);
michael@0 7035 quot=temp;
michael@0 7036 #else
michael@0 7037 discard1=quot%10;
michael@0 7038 quot=quot/10;
michael@0 7039 #endif
michael@0 7040 /* here, discard1 is the guard digit, and residue is everything */
michael@0 7041 /* else [use mapping array to accumulate residue safely] */
michael@0 7042 *residue+=resmap[discard1];
michael@0 7043 cut++; /* update cut */
michael@0 7044 /* here: up -> Unit of the array with bottom digit */
michael@0 7045 /* cut is the division point for each Unit */
michael@0 7046 /* quot holds the uncut high-order digits for the current unit */
michael@0 7047 if (set->digits<=0) { /* special for Quantize/Subnormal :-( */
michael@0 7048 *dn->lsu=0; /* .. result is 0 */
michael@0 7049 dn->digits=1; /* .. */
michael@0 7050 }
michael@0 7051 else { /* shift to least needed */
michael@0 7052 count=set->digits; /* now digits to end up with */
michael@0 7053 dn->digits=count; /* set the new length */
michael@0 7054 /* shift-copy the coefficient array to the result number */
michael@0 7055 for (target=dn->lsu; ; target++) {
michael@0 7056 *target=(Unit)quot;
michael@0 7057 count-=(DECDPUN-cut);
michael@0 7058 if (count<=0) break;
michael@0 7059 up++;
michael@0 7060 quot=*up;
michael@0 7061 #if DECDPUN<=4
michael@0 7062 quot=QUOT10(quot, cut);
michael@0 7063 rem=*up-quot*powers[cut];
michael@0 7064 #else
michael@0 7065 rem=quot%powers[cut];
michael@0 7066 quot=quot/powers[cut];
michael@0 7067 #endif
michael@0 7068 *target=(Unit)(*target+rem*powers[DECDPUN-cut]);
michael@0 7069 count-=cut;
michael@0 7070 if (count<=0) break;
michael@0 7071 } /* shift-copy loop */
michael@0 7072 } /* shift to least */
michael@0 7073 } /* not unit boundary */
michael@0 7074
michael@0 7075 if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */
michael@0 7076 return;
michael@0 7077 } /* decSetCoeff */
michael@0 7078
michael@0 7079 /* ------------------------------------------------------------------ */
michael@0 7080 /* decApplyRound -- apply pending rounding to a number */
michael@0 7081 /* */
michael@0 7082 /* dn is the number, with space for set->digits digits */
michael@0 7083 /* set is the context [for size and rounding mode] */
michael@0 7084 /* residue indicates pending rounding, being any accumulated */
michael@0 7085 /* guard and sticky information. It may be: */
michael@0 7086 /* 6-9: rounding digit is >5 */
michael@0 7087 /* 5: rounding digit is exactly half-way */
michael@0 7088 /* 1-4: rounding digit is <5 and >0 */
michael@0 7089 /* 0: the coefficient is exact */
michael@0 7090 /* -1: as 1, but the hidden digits are subtractive, that */
michael@0 7091 /* is, of the opposite sign to dn. In this case the */
michael@0 7092 /* coefficient must be non-0. This case occurs when */
michael@0 7093 /* subtracting a small number (which can be reduced to */
michael@0 7094 /* a sticky bit); see decAddOp. */
michael@0 7095 /* status is the status accumulator, as usual */
michael@0 7096 /* */
michael@0 7097 /* This routine applies rounding while keeping the length of the */
michael@0 7098 /* coefficient constant. The exponent and status are unchanged */
michael@0 7099 /* except if: */
michael@0 7100 /* */
michael@0 7101 /* -- the coefficient was increased and is all nines (in which */
michael@0 7102 /* case Overflow could occur, and is handled directly here so */
michael@0 7103 /* the caller does not need to re-test for overflow) */
michael@0 7104 /* */
michael@0 7105 /* -- the coefficient was decreased and becomes all nines (in which */
michael@0 7106 /* case Underflow could occur, and is also handled directly). */
michael@0 7107 /* */
michael@0 7108 /* All fields in dn are updated as required. */
michael@0 7109 /* */
michael@0 7110 /* ------------------------------------------------------------------ */
michael@0 7111 static void decApplyRound(decNumber *dn, decContext *set, Int residue,
michael@0 7112 uInt *status) {
michael@0 7113 Int bump; /* 1 if coefficient needs to be incremented */
michael@0 7114 /* -1 if coefficient needs to be decremented */
michael@0 7115
michael@0 7116 if (residue==0) return; /* nothing to apply */
michael@0 7117
michael@0 7118 bump=0; /* assume a smooth ride */
michael@0 7119
michael@0 7120 /* now decide whether, and how, to round, depending on mode */
michael@0 7121 switch (set->round) {
michael@0 7122 case DEC_ROUND_05UP: { /* round zero or five up (for reround) */
michael@0 7123 /* This is the same as DEC_ROUND_DOWN unless there is a */
michael@0 7124 /* positive residue and the lsd of dn is 0 or 5, in which case */
michael@0 7125 /* it is bumped; when residue is <0, the number is therefore */
michael@0 7126 /* bumped down unless the final digit was 1 or 6 (in which */
michael@0 7127 /* case it is bumped down and then up -- a no-op) */
michael@0 7128 Int lsd5=*dn->lsu%5; /* get lsd and quintate */
michael@0 7129 if (residue<0 && lsd5!=1) bump=-1;
michael@0 7130 else if (residue>0 && lsd5==0) bump=1;
michael@0 7131 /* [bump==1 could be applied directly; use common path for clarity] */
michael@0 7132 break;} /* r-05 */
michael@0 7133
michael@0 7134 case DEC_ROUND_DOWN: {
michael@0 7135 /* no change, except if negative residue */
michael@0 7136 if (residue<0) bump=-1;
michael@0 7137 break;} /* r-d */
michael@0 7138
michael@0 7139 case DEC_ROUND_HALF_DOWN: {
michael@0 7140 if (residue>5) bump=1;
michael@0 7141 break;} /* r-h-d */
michael@0 7142
michael@0 7143 case DEC_ROUND_HALF_EVEN: {
michael@0 7144 if (residue>5) bump=1; /* >0.5 goes up */
michael@0 7145 else if (residue==5) { /* exactly 0.5000... */
michael@0 7146 /* 0.5 goes up iff [new] lsd is odd */
michael@0 7147 if (*dn->lsu & 0x01) bump=1;
michael@0 7148 }
michael@0 7149 break;} /* r-h-e */
michael@0 7150
michael@0 7151 case DEC_ROUND_HALF_UP: {
michael@0 7152 if (residue>=5) bump=1;
michael@0 7153 break;} /* r-h-u */
michael@0 7154
michael@0 7155 case DEC_ROUND_UP: {
michael@0 7156 if (residue>0) bump=1;
michael@0 7157 break;} /* r-u */
michael@0 7158
michael@0 7159 case DEC_ROUND_CEILING: {
michael@0 7160 /* same as _UP for positive numbers, and as _DOWN for negatives */
michael@0 7161 /* [negative residue cannot occur on 0] */
michael@0 7162 if (decNumberIsNegative(dn)) {
michael@0 7163 if (residue<0) bump=-1;
michael@0 7164 }
michael@0 7165 else {
michael@0 7166 if (residue>0) bump=1;
michael@0 7167 }
michael@0 7168 break;} /* r-c */
michael@0 7169
michael@0 7170 case DEC_ROUND_FLOOR: {
michael@0 7171 /* same as _UP for negative numbers, and as _DOWN for positive */
michael@0 7172 /* [negative residue cannot occur on 0] */
michael@0 7173 if (!decNumberIsNegative(dn)) {
michael@0 7174 if (residue<0) bump=-1;
michael@0 7175 }
michael@0 7176 else {
michael@0 7177 if (residue>0) bump=1;
michael@0 7178 }
michael@0 7179 break;} /* r-f */
michael@0 7180
michael@0 7181 default: { /* e.g., DEC_ROUND_MAX */
michael@0 7182 *status|=DEC_Invalid_context;
michael@0 7183 #if DECTRACE || (DECCHECK && DECVERB)
michael@0 7184 printf("Unknown rounding mode: %d\n", set->round);
michael@0 7185 #endif
michael@0 7186 break;}
michael@0 7187 } /* switch */
michael@0 7188
michael@0 7189 /* now bump the number, up or down, if need be */
michael@0 7190 if (bump==0) return; /* no action required */
michael@0 7191
michael@0 7192 /* Simply use decUnitAddSub unless bumping up and the number is */
michael@0 7193 /* all nines. In this special case set to 100... explicitly */
michael@0 7194 /* and adjust the exponent by one (as otherwise could overflow */
michael@0 7195 /* the array) */
michael@0 7196 /* Similarly handle all-nines result if bumping down. */
michael@0 7197 if (bump>0) {
michael@0 7198 Unit *up; /* work */
michael@0 7199 uInt count=dn->digits; /* digits to be checked */
michael@0 7200 for (up=dn->lsu; ; up++) {
michael@0 7201 if (count<=DECDPUN) {
michael@0 7202 /* this is the last Unit (the msu) */
michael@0 7203 if (*up!=powers[count]-1) break; /* not still 9s */
michael@0 7204 /* here if it, too, is all nines */
michael@0 7205 *up=(Unit)powers[count-1]; /* here 999 -> 100 etc. */
michael@0 7206 for (up=up-1; up>=dn->lsu; up--) *up=0; /* others all to 0 */
michael@0 7207 dn->exponent++; /* and bump exponent */
michael@0 7208 /* [which, very rarely, could cause Overflow...] */
michael@0 7209 if ((dn->exponent+dn->digits)>set->emax+1) {
michael@0 7210 decSetOverflow(dn, set, status);
michael@0 7211 }
michael@0 7212 return; /* done */
michael@0 7213 }
michael@0 7214 /* a full unit to check, with more to come */
michael@0 7215 if (*up!=DECDPUNMAX) break; /* not still 9s */
michael@0 7216 count-=DECDPUN;
michael@0 7217 } /* up */
michael@0 7218 } /* bump>0 */
michael@0 7219 else { /* -1 */
michael@0 7220 /* here checking for a pre-bump of 1000... (leading 1, all */
michael@0 7221 /* other digits zero) */
michael@0 7222 Unit *up, *sup; /* work */
michael@0 7223 uInt count=dn->digits; /* digits to be checked */
michael@0 7224 for (up=dn->lsu; ; up++) {
michael@0 7225 if (count<=DECDPUN) {
michael@0 7226 /* this is the last Unit (the msu) */
michael@0 7227 if (*up!=powers[count-1]) break; /* not 100.. */
michael@0 7228 /* here if have the 1000... case */
michael@0 7229 sup=up; /* save msu pointer */
michael@0 7230 *up=(Unit)powers[count]-1; /* here 100 in msu -> 999 */
michael@0 7231 /* others all to all-nines, too */
michael@0 7232 for (up=up-1; up>=dn->lsu; up--) *up=(Unit)powers[DECDPUN]-1;
michael@0 7233 dn->exponent--; /* and bump exponent */
michael@0 7234
michael@0 7235 /* iff the number was at the subnormal boundary (exponent=etiny) */
michael@0 7236 /* then the exponent is now out of range, so it will in fact get */
michael@0 7237 /* clamped to etiny and the final 9 dropped. */
michael@0 7238 /* printf(">> emin=%d exp=%d sdig=%d\n", set->emin, */
michael@0 7239 /* dn->exponent, set->digits); */
michael@0 7240 if (dn->exponent+1==set->emin-set->digits+1) {
michael@0 7241 if (count==1 && dn->digits==1) *sup=0; /* here 9 -> 0[.9] */
michael@0 7242 else {
michael@0 7243 *sup=(Unit)powers[count-1]-1; /* here 999.. in msu -> 99.. */
michael@0 7244 dn->digits--;
michael@0 7245 }
michael@0 7246 dn->exponent++;
michael@0 7247 *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
michael@0 7248 }
michael@0 7249 return; /* done */
michael@0 7250 }
michael@0 7251
michael@0 7252 /* a full unit to check, with more to come */
michael@0 7253 if (*up!=0) break; /* not still 0s */
michael@0 7254 count-=DECDPUN;
michael@0 7255 } /* up */
michael@0 7256
michael@0 7257 } /* bump<0 */
michael@0 7258
michael@0 7259 /* Actual bump needed. Do it. */
michael@0 7260 decUnitAddSub(dn->lsu, D2U(dn->digits), uarrone, 1, 0, dn->lsu, bump);
michael@0 7261 } /* decApplyRound */
michael@0 7262
michael@0 7263 #if DECSUBSET
michael@0 7264 /* ------------------------------------------------------------------ */
michael@0 7265 /* decFinish -- finish processing a number */
michael@0 7266 /* */
michael@0 7267 /* dn is the number */
michael@0 7268 /* set is the context */
michael@0 7269 /* residue is the rounding accumulator (as in decApplyRound) */
michael@0 7270 /* status is the accumulator */
michael@0 7271 /* */
michael@0 7272 /* This finishes off the current number by: */
michael@0 7273 /* 1. If not extended: */
michael@0 7274 /* a. Converting a zero result to clean '0' */
michael@0 7275 /* b. Reducing positive exponents to 0, if would fit in digits */
michael@0 7276 /* 2. Checking for overflow and subnormals (always) */
michael@0 7277 /* Note this is just Finalize when no subset arithmetic. */
michael@0 7278 /* All fields are updated as required. */
michael@0 7279 /* ------------------------------------------------------------------ */
michael@0 7280 static void decFinish(decNumber *dn, decContext *set, Int *residue,
michael@0 7281 uInt *status) {
michael@0 7282 if (!set->extended) {
michael@0 7283 if ISZERO(dn) { /* value is zero */
michael@0 7284 dn->exponent=0; /* clean exponent .. */
michael@0 7285 dn->bits=0; /* .. and sign */
michael@0 7286 return; /* no error possible */
michael@0 7287 }
michael@0 7288 if (dn->exponent>=0) { /* non-negative exponent */
michael@0 7289 /* >0; reduce to integer if possible */
michael@0 7290 if (set->digits >= (dn->exponent+dn->digits)) {
michael@0 7291 dn->digits=decShiftToMost(dn->lsu, dn->digits, dn->exponent);
michael@0 7292 dn->exponent=0;
michael@0 7293 }
michael@0 7294 }
michael@0 7295 } /* !extended */
michael@0 7296
michael@0 7297 decFinalize(dn, set, residue, status);
michael@0 7298 } /* decFinish */
michael@0 7299 #endif
michael@0 7300
michael@0 7301 /* ------------------------------------------------------------------ */
michael@0 7302 /* decFinalize -- final check, clamp, and round of a number */
michael@0 7303 /* */
michael@0 7304 /* dn is the number */
michael@0 7305 /* set is the context */
michael@0 7306 /* residue is the rounding accumulator (as in decApplyRound) */
michael@0 7307 /* status is the status accumulator */
michael@0 7308 /* */
michael@0 7309 /* This finishes off the current number by checking for subnormal */
michael@0 7310 /* results, applying any pending rounding, checking for overflow, */
michael@0 7311 /* and applying any clamping. */
michael@0 7312 /* Underflow and overflow conditions are raised as appropriate. */
michael@0 7313 /* All fields are updated as required. */
michael@0 7314 /* ------------------------------------------------------------------ */
michael@0 7315 static void decFinalize(decNumber *dn, decContext *set, Int *residue,
michael@0 7316 uInt *status) {
michael@0 7317 Int shift; /* shift needed if clamping */
michael@0 7318 Int tinyexp=set->emin-dn->digits+1; /* precalculate subnormal boundary */
michael@0 7319
michael@0 7320 /* Must be careful, here, when checking the exponent as the */
michael@0 7321 /* adjusted exponent could overflow 31 bits [because it may already */
michael@0 7322 /* be up to twice the expected]. */
michael@0 7323
michael@0 7324 /* First test for subnormal. This must be done before any final */
michael@0 7325 /* round as the result could be rounded to Nmin or 0. */
michael@0 7326 if (dn->exponent<=tinyexp) { /* prefilter */
michael@0 7327 Int comp;
michael@0 7328 decNumber nmin;
michael@0 7329 /* A very nasty case here is dn == Nmin and residue<0 */
michael@0 7330 if (dn->exponent<tinyexp) {
michael@0 7331 /* Go handle subnormals; this will apply round if needed. */
michael@0 7332 decSetSubnormal(dn, set, residue, status);
michael@0 7333 return;
michael@0 7334 }
michael@0 7335 /* Equals case: only subnormal if dn=Nmin and negative residue */
michael@0 7336 uprv_decNumberZero(&nmin);
michael@0 7337 nmin.lsu[0]=1;
michael@0 7338 nmin.exponent=set->emin;
michael@0 7339 comp=decCompare(dn, &nmin, 1); /* (signless compare) */
michael@0 7340 if (comp==BADINT) { /* oops */
michael@0 7341 *status|=DEC_Insufficient_storage; /* abandon... */
michael@0 7342 return;
michael@0 7343 }
michael@0 7344 if (*residue<0 && comp==0) { /* neg residue and dn==Nmin */
michael@0 7345 decApplyRound(dn, set, *residue, status); /* might force down */
michael@0 7346 decSetSubnormal(dn, set, residue, status);
michael@0 7347 return;
michael@0 7348 }
michael@0 7349 }
michael@0 7350
michael@0 7351 /* now apply any pending round (this could raise overflow). */
michael@0 7352 if (*residue!=0) decApplyRound(dn, set, *residue, status);
michael@0 7353
michael@0 7354 /* Check for overflow [redundant in the 'rare' case] or clamp */
michael@0 7355 if (dn->exponent<=set->emax-set->digits+1) return; /* neither needed */
michael@0 7356
michael@0 7357
michael@0 7358 /* here when might have an overflow or clamp to do */
michael@0 7359 if (dn->exponent>set->emax-dn->digits+1) { /* too big */
michael@0 7360 decSetOverflow(dn, set, status);
michael@0 7361 return;
michael@0 7362 }
michael@0 7363 /* here when the result is normal but in clamp range */
michael@0 7364 if (!set->clamp) return;
michael@0 7365
michael@0 7366 /* here when need to apply the IEEE exponent clamp (fold-down) */
michael@0 7367 shift=dn->exponent-(set->emax-set->digits+1);
michael@0 7368
michael@0 7369 /* shift coefficient (if non-zero) */
michael@0 7370 if (!ISZERO(dn)) {
michael@0 7371 dn->digits=decShiftToMost(dn->lsu, dn->digits, shift);
michael@0 7372 }
michael@0 7373 dn->exponent-=shift; /* adjust the exponent to match */
michael@0 7374 *status|=DEC_Clamped; /* and record the dirty deed */
michael@0 7375 return;
michael@0 7376 } /* decFinalize */
michael@0 7377
michael@0 7378 /* ------------------------------------------------------------------ */
michael@0 7379 /* decSetOverflow -- set number to proper overflow value */
michael@0 7380 /* */
michael@0 7381 /* dn is the number (used for sign [only] and result) */
michael@0 7382 /* set is the context [used for the rounding mode, etc.] */
michael@0 7383 /* status contains the current status to be updated */
michael@0 7384 /* */
michael@0 7385 /* This sets the sign of a number and sets its value to either */
michael@0 7386 /* Infinity or the maximum finite value, depending on the sign of */
michael@0 7387 /* dn and the rounding mode, following IEEE 754 rules. */
michael@0 7388 /* ------------------------------------------------------------------ */
michael@0 7389 static void decSetOverflow(decNumber *dn, decContext *set, uInt *status) {
michael@0 7390 Flag needmax=0; /* result is maximum finite value */
michael@0 7391 uByte sign=dn->bits&DECNEG; /* clean and save sign bit */
michael@0 7392
michael@0 7393 if (ISZERO(dn)) { /* zero does not overflow magnitude */
michael@0 7394 Int emax=set->emax; /* limit value */
michael@0 7395 if (set->clamp) emax-=set->digits-1; /* lower if clamping */
michael@0 7396 if (dn->exponent>emax) { /* clamp required */
michael@0 7397 dn->exponent=emax;
michael@0 7398 *status|=DEC_Clamped;
michael@0 7399 }
michael@0 7400 return;
michael@0 7401 }
michael@0 7402
michael@0 7403 uprv_decNumberZero(dn);
michael@0 7404 switch (set->round) {
michael@0 7405 case DEC_ROUND_DOWN: {
michael@0 7406 needmax=1; /* never Infinity */
michael@0 7407 break;} /* r-d */
michael@0 7408 case DEC_ROUND_05UP: {
michael@0 7409 needmax=1; /* never Infinity */
michael@0 7410 break;} /* r-05 */
michael@0 7411 case DEC_ROUND_CEILING: {
michael@0 7412 if (sign) needmax=1; /* Infinity if non-negative */
michael@0 7413 break;} /* r-c */
michael@0 7414 case DEC_ROUND_FLOOR: {
michael@0 7415 if (!sign) needmax=1; /* Infinity if negative */
michael@0 7416 break;} /* r-f */
michael@0 7417 default: break; /* Infinity in all other cases */
michael@0 7418 }
michael@0 7419 if (needmax) {
michael@0 7420 decSetMaxValue(dn, set);
michael@0 7421 dn->bits=sign; /* set sign */
michael@0 7422 }
michael@0 7423 else dn->bits=sign|DECINF; /* Value is +/-Infinity */
michael@0 7424 *status|=DEC_Overflow | DEC_Inexact | DEC_Rounded;
michael@0 7425 } /* decSetOverflow */
michael@0 7426
michael@0 7427 /* ------------------------------------------------------------------ */
michael@0 7428 /* decSetMaxValue -- set number to +Nmax (maximum normal value) */
michael@0 7429 /* */
michael@0 7430 /* dn is the number to set */
michael@0 7431 /* set is the context [used for digits and emax] */
michael@0 7432 /* */
michael@0 7433 /* This sets the number to the maximum positive value. */
michael@0 7434 /* ------------------------------------------------------------------ */
michael@0 7435 static void decSetMaxValue(decNumber *dn, decContext *set) {
michael@0 7436 Unit *up; /* work */
michael@0 7437 Int count=set->digits; /* nines to add */
michael@0 7438 dn->digits=count;
michael@0 7439 /* fill in all nines to set maximum value */
michael@0 7440 for (up=dn->lsu; ; up++) {
michael@0 7441 if (count>DECDPUN) *up=DECDPUNMAX; /* unit full o'nines */
michael@0 7442 else { /* this is the msu */
michael@0 7443 *up=(Unit)(powers[count]-1);
michael@0 7444 break;
michael@0 7445 }
michael@0 7446 count-=DECDPUN; /* filled those digits */
michael@0 7447 } /* up */
michael@0 7448 dn->bits=0; /* + sign */
michael@0 7449 dn->exponent=set->emax-set->digits+1;
michael@0 7450 } /* decSetMaxValue */
michael@0 7451
michael@0 7452 /* ------------------------------------------------------------------ */
michael@0 7453 /* decSetSubnormal -- process value whose exponent is <Emin */
michael@0 7454 /* */
michael@0 7455 /* dn is the number (used as input as well as output; it may have */
michael@0 7456 /* an allowed subnormal value, which may need to be rounded) */
michael@0 7457 /* set is the context [used for the rounding mode] */
michael@0 7458 /* residue is any pending residue */
michael@0 7459 /* status contains the current status to be updated */
michael@0 7460 /* */
michael@0 7461 /* If subset mode, set result to zero and set Underflow flags. */
michael@0 7462 /* */
michael@0 7463 /* Value may be zero with a low exponent; this does not set Subnormal */
michael@0 7464 /* but the exponent will be clamped to Etiny. */
michael@0 7465 /* */
michael@0 7466 /* Otherwise ensure exponent is not out of range, and round as */
michael@0 7467 /* necessary. Underflow is set if the result is Inexact. */
michael@0 7468 /* ------------------------------------------------------------------ */
michael@0 7469 static void decSetSubnormal(decNumber *dn, decContext *set, Int *residue,
michael@0 7470 uInt *status) {
michael@0 7471 decContext workset; /* work */
michael@0 7472 Int etiny, adjust; /* .. */
michael@0 7473
michael@0 7474 #if DECSUBSET
michael@0 7475 /* simple set to zero and 'hard underflow' for subset */
michael@0 7476 if (!set->extended) {
michael@0 7477 uprv_decNumberZero(dn);
michael@0 7478 /* always full overflow */
michael@0 7479 *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
michael@0 7480 return;
michael@0 7481 }
michael@0 7482 #endif
michael@0 7483
michael@0 7484 /* Full arithmetic -- allow subnormals, rounded to minimum exponent */
michael@0 7485 /* (Etiny) if needed */
michael@0 7486 etiny=set->emin-(set->digits-1); /* smallest allowed exponent */
michael@0 7487
michael@0 7488 if ISZERO(dn) { /* value is zero */
michael@0 7489 /* residue can never be non-zero here */
michael@0 7490 #if DECCHECK
michael@0 7491 if (*residue!=0) {
michael@0 7492 printf("++ Subnormal 0 residue %ld\n", (LI)*residue);
michael@0 7493 *status|=DEC_Invalid_operation;
michael@0 7494 }
michael@0 7495 #endif
michael@0 7496 if (dn->exponent<etiny) { /* clamp required */
michael@0 7497 dn->exponent=etiny;
michael@0 7498 *status|=DEC_Clamped;
michael@0 7499 }
michael@0 7500 return;
michael@0 7501 }
michael@0 7502
michael@0 7503 *status|=DEC_Subnormal; /* have a non-zero subnormal */
michael@0 7504 adjust=etiny-dn->exponent; /* calculate digits to remove */
michael@0 7505 if (adjust<=0) { /* not out of range; unrounded */
michael@0 7506 /* residue can never be non-zero here, except in the Nmin-residue */
michael@0 7507 /* case (which is a subnormal result), so can take fast-path here */
michael@0 7508 /* it may already be inexact (from setting the coefficient) */
michael@0 7509 if (*status&DEC_Inexact) *status|=DEC_Underflow;
michael@0 7510 return;
michael@0 7511 }
michael@0 7512
michael@0 7513 /* adjust>0, so need to rescale the result so exponent becomes Etiny */
michael@0 7514 /* [this code is similar to that in rescale] */
michael@0 7515 workset=*set; /* clone rounding, etc. */
michael@0 7516 workset.digits=dn->digits-adjust; /* set requested length */
michael@0 7517 workset.emin-=adjust; /* and adjust emin to match */
michael@0 7518 /* [note that the latter can be <1, here, similar to Rescale case] */
michael@0 7519 decSetCoeff(dn, &workset, dn->lsu, dn->digits, residue, status);
michael@0 7520 decApplyRound(dn, &workset, *residue, status);
michael@0 7521
michael@0 7522 /* Use 754 default rule: Underflow is set iff Inexact */
michael@0 7523 /* [independent of whether trapped] */
michael@0 7524 if (*status&DEC_Inexact) *status|=DEC_Underflow;
michael@0 7525
michael@0 7526 /* if rounded up a 999s case, exponent will be off by one; adjust */
michael@0 7527 /* back if so [it will fit, because it was shortened earlier] */
michael@0 7528 if (dn->exponent>etiny) {
michael@0 7529 dn->digits=decShiftToMost(dn->lsu, dn->digits, 1);
michael@0 7530 dn->exponent--; /* (re)adjust the exponent. */
michael@0 7531 }
michael@0 7532
michael@0 7533 /* if rounded to zero, it is by definition clamped... */
michael@0 7534 if (ISZERO(dn)) *status|=DEC_Clamped;
michael@0 7535 } /* decSetSubnormal */
michael@0 7536
michael@0 7537 /* ------------------------------------------------------------------ */
michael@0 7538 /* decCheckMath - check entry conditions for a math function */
michael@0 7539 /* */
michael@0 7540 /* This checks the context and the operand */
michael@0 7541 /* */
michael@0 7542 /* rhs is the operand to check */
michael@0 7543 /* set is the context to check */
michael@0 7544 /* status is unchanged if both are good */
michael@0 7545 /* */
michael@0 7546 /* returns non-zero if status is changed, 0 otherwise */
michael@0 7547 /* */
michael@0 7548 /* Restrictions enforced: */
michael@0 7549 /* */
michael@0 7550 /* digits, emax, and -emin in the context must be less than */
michael@0 7551 /* DEC_MAX_MATH (999999), and A must be within these bounds if */
michael@0 7552 /* non-zero. Invalid_operation is set in the status if a */
michael@0 7553 /* restriction is violated. */
michael@0 7554 /* ------------------------------------------------------------------ */
michael@0 7555 static uInt decCheckMath(const decNumber *rhs, decContext *set,
michael@0 7556 uInt *status) {
michael@0 7557 uInt save=*status; /* record */
michael@0 7558 if (set->digits>DEC_MAX_MATH
michael@0 7559 || set->emax>DEC_MAX_MATH
michael@0 7560 || -set->emin>DEC_MAX_MATH) *status|=DEC_Invalid_context;
michael@0 7561 else if ((rhs->digits>DEC_MAX_MATH
michael@0 7562 || rhs->exponent+rhs->digits>DEC_MAX_MATH+1
michael@0 7563 || rhs->exponent+rhs->digits<2*(1-DEC_MAX_MATH))
michael@0 7564 && !ISZERO(rhs)) *status|=DEC_Invalid_operation;
michael@0 7565 return (*status!=save);
michael@0 7566 } /* decCheckMath */
michael@0 7567
michael@0 7568 /* ------------------------------------------------------------------ */
michael@0 7569 /* decGetInt -- get integer from a number */
michael@0 7570 /* */
michael@0 7571 /* dn is the number [which will not be altered] */
michael@0 7572 /* */
michael@0 7573 /* returns one of: */
michael@0 7574 /* BADINT if there is a non-zero fraction */
michael@0 7575 /* the converted integer */
michael@0 7576 /* BIGEVEN if the integer is even and magnitude > 2*10**9 */
michael@0 7577 /* BIGODD if the integer is odd and magnitude > 2*10**9 */
michael@0 7578 /* */
michael@0 7579 /* This checks and gets a whole number from the input decNumber. */
michael@0 7580 /* The sign can be determined from dn by the caller when BIGEVEN or */
michael@0 7581 /* BIGODD is returned. */
michael@0 7582 /* ------------------------------------------------------------------ */
michael@0 7583 static Int decGetInt(const decNumber *dn) {
michael@0 7584 Int theInt; /* result accumulator */
michael@0 7585 const Unit *up; /* work */
michael@0 7586 Int got; /* digits (real or not) processed */
michael@0 7587 Int ilength=dn->digits+dn->exponent; /* integral length */
michael@0 7588 Flag neg=decNumberIsNegative(dn); /* 1 if -ve */
michael@0 7589
michael@0 7590 /* The number must be an integer that fits in 10 digits */
michael@0 7591 /* Assert, here, that 10 is enough for any rescale Etiny */
michael@0 7592 #if DEC_MAX_EMAX > 999999999
michael@0 7593 #error GetInt may need updating [for Emax]
michael@0 7594 #endif
michael@0 7595 #if DEC_MIN_EMIN < -999999999
michael@0 7596 #error GetInt may need updating [for Emin]
michael@0 7597 #endif
michael@0 7598 if (ISZERO(dn)) return 0; /* zeros are OK, with any exponent */
michael@0 7599
michael@0 7600 up=dn->lsu; /* ready for lsu */
michael@0 7601 theInt=0; /* ready to accumulate */
michael@0 7602 if (dn->exponent>=0) { /* relatively easy */
michael@0 7603 /* no fractional part [usual]; allow for positive exponent */
michael@0 7604 got=dn->exponent;
michael@0 7605 }
michael@0 7606 else { /* -ve exponent; some fractional part to check and discard */
michael@0 7607 Int count=-dn->exponent; /* digits to discard */
michael@0 7608 /* spin up whole units until reach the Unit with the unit digit */
michael@0 7609 for (; count>=DECDPUN; up++) {
michael@0 7610 if (*up!=0) return BADINT; /* non-zero Unit to discard */
michael@0 7611 count-=DECDPUN;
michael@0 7612 }
michael@0 7613 if (count==0) got=0; /* [a multiple of DECDPUN] */
michael@0 7614 else { /* [not multiple of DECDPUN] */
michael@0 7615 Int rem; /* work */
michael@0 7616 /* slice off fraction digits and check for non-zero */
michael@0 7617 #if DECDPUN<=4
michael@0 7618 theInt=QUOT10(*up, count);
michael@0 7619 rem=*up-theInt*powers[count];
michael@0 7620 #else
michael@0 7621 rem=*up%powers[count]; /* slice off discards */
michael@0 7622 theInt=*up/powers[count];
michael@0 7623 #endif
michael@0 7624 if (rem!=0) return BADINT; /* non-zero fraction */
michael@0 7625 /* it looks good */
michael@0 7626 got=DECDPUN-count; /* number of digits so far */
michael@0 7627 up++; /* ready for next */
michael@0 7628 }
michael@0 7629 }
michael@0 7630 /* now it's known there's no fractional part */
michael@0 7631
michael@0 7632 /* tricky code now, to accumulate up to 9.3 digits */
michael@0 7633 if (got==0) {theInt=*up; got+=DECDPUN; up++;} /* ensure lsu is there */
michael@0 7634
michael@0 7635 if (ilength<11) {
michael@0 7636 Int save=theInt;
michael@0 7637 /* collect any remaining unit(s) */
michael@0 7638 for (; got<ilength; up++) {
michael@0 7639 theInt+=*up*powers[got];
michael@0 7640 got+=DECDPUN;
michael@0 7641 }
michael@0 7642 if (ilength==10) { /* need to check for wrap */
michael@0 7643 if (theInt/(Int)powers[got-DECDPUN]!=(Int)*(up-1)) ilength=11;
michael@0 7644 /* [that test also disallows the BADINT result case] */
michael@0 7645 else if (neg && theInt>1999999997) ilength=11;
michael@0 7646 else if (!neg && theInt>999999999) ilength=11;
michael@0 7647 if (ilength==11) theInt=save; /* restore correct low bit */
michael@0 7648 }
michael@0 7649 }
michael@0 7650
michael@0 7651 if (ilength>10) { /* too big */
michael@0 7652 if (theInt&1) return BIGODD; /* bottom bit 1 */
michael@0 7653 return BIGEVEN; /* bottom bit 0 */
michael@0 7654 }
michael@0 7655
michael@0 7656 if (neg) theInt=-theInt; /* apply sign */
michael@0 7657 return theInt;
michael@0 7658 } /* decGetInt */
michael@0 7659
michael@0 7660 /* ------------------------------------------------------------------ */
michael@0 7661 /* decDecap -- decapitate the coefficient of a number */
michael@0 7662 /* */
michael@0 7663 /* dn is the number to be decapitated */
michael@0 7664 /* drop is the number of digits to be removed from the left of dn; */
michael@0 7665 /* this must be <= dn->digits (if equal, the coefficient is */
michael@0 7666 /* set to 0) */
michael@0 7667 /* */
michael@0 7668 /* Returns dn; dn->digits will be <= the initial digits less drop */
michael@0 7669 /* (after removing drop digits there may be leading zero digits */
michael@0 7670 /* which will also be removed). Only dn->lsu and dn->digits change. */
michael@0 7671 /* ------------------------------------------------------------------ */
michael@0 7672 static decNumber *decDecap(decNumber *dn, Int drop) {
michael@0 7673 Unit *msu; /* -> target cut point */
michael@0 7674 Int cut; /* work */
michael@0 7675 if (drop>=dn->digits) { /* losing the whole thing */
michael@0 7676 #if DECCHECK
michael@0 7677 if (drop>dn->digits)
michael@0 7678 printf("decDecap called with drop>digits [%ld>%ld]\n",
michael@0 7679 (LI)drop, (LI)dn->digits);
michael@0 7680 #endif
michael@0 7681 dn->lsu[0]=0;
michael@0 7682 dn->digits=1;
michael@0 7683 return dn;
michael@0 7684 }
michael@0 7685 msu=dn->lsu+D2U(dn->digits-drop)-1; /* -> likely msu */
michael@0 7686 cut=MSUDIGITS(dn->digits-drop); /* digits to be in use in msu */
michael@0 7687 if (cut!=DECDPUN) *msu%=powers[cut]; /* clear left digits */
michael@0 7688 /* that may have left leading zero digits, so do a proper count... */
michael@0 7689 dn->digits=decGetDigits(dn->lsu, msu-dn->lsu+1);
michael@0 7690 return dn;
michael@0 7691 } /* decDecap */
michael@0 7692
michael@0 7693 /* ------------------------------------------------------------------ */
michael@0 7694 /* decBiStr -- compare string with pairwise options */
michael@0 7695 /* */
michael@0 7696 /* targ is the string to compare */
michael@0 7697 /* str1 is one of the strings to compare against (length may be 0) */
michael@0 7698 /* str2 is the other; it must be the same length as str1 */
michael@0 7699 /* */
michael@0 7700 /* returns 1 if strings compare equal, (that is, it is the same */
michael@0 7701 /* length as str1 and str2, and each character of targ is in either */
michael@0 7702 /* str1 or str2 in the corresponding position), or 0 otherwise */
michael@0 7703 /* */
michael@0 7704 /* This is used for generic caseless compare, including the awkward */
michael@0 7705 /* case of the Turkish dotted and dotless Is. Use as (for example): */
michael@0 7706 /* if (decBiStr(test, "mike", "MIKE")) ... */
michael@0 7707 /* ------------------------------------------------------------------ */
michael@0 7708 static Flag decBiStr(const char *targ, const char *str1, const char *str2) {
michael@0 7709 for (;;targ++, str1++, str2++) {
michael@0 7710 if (*targ!=*str1 && *targ!=*str2) return 0;
michael@0 7711 /* *targ has a match in one (or both, if terminator) */
michael@0 7712 if (*targ=='\0') break;
michael@0 7713 } /* forever */
michael@0 7714 return 1;
michael@0 7715 } /* decBiStr */
michael@0 7716
michael@0 7717 /* ------------------------------------------------------------------ */
michael@0 7718 /* decNaNs -- handle NaN operand or operands */
michael@0 7719 /* */
michael@0 7720 /* res is the result number */
michael@0 7721 /* lhs is the first operand */
michael@0 7722 /* rhs is the second operand, or NULL if none */
michael@0 7723 /* context is used to limit payload length */
michael@0 7724 /* status contains the current status */
michael@0 7725 /* returns res in case convenient */
michael@0 7726 /* */
michael@0 7727 /* Called when one or both operands is a NaN, and propagates the */
michael@0 7728 /* appropriate result to res. When an sNaN is found, it is changed */
michael@0 7729 /* to a qNaN and Invalid operation is set. */
michael@0 7730 /* ------------------------------------------------------------------ */
michael@0 7731 static decNumber * decNaNs(decNumber *res, const decNumber *lhs,
michael@0 7732 const decNumber *rhs, decContext *set,
michael@0 7733 uInt *status) {
michael@0 7734 /* This decision tree ends up with LHS being the source pointer, */
michael@0 7735 /* and status updated if need be */
michael@0 7736 if (lhs->bits & DECSNAN)
michael@0 7737 *status|=DEC_Invalid_operation | DEC_sNaN;
michael@0 7738 else if (rhs==NULL);
michael@0 7739 else if (rhs->bits & DECSNAN) {
michael@0 7740 lhs=rhs;
michael@0 7741 *status|=DEC_Invalid_operation | DEC_sNaN;
michael@0 7742 }
michael@0 7743 else if (lhs->bits & DECNAN);
michael@0 7744 else lhs=rhs;
michael@0 7745
michael@0 7746 /* propagate the payload */
michael@0 7747 if (lhs->digits<=set->digits) uprv_decNumberCopy(res, lhs); /* easy */
michael@0 7748 else { /* too long */
michael@0 7749 const Unit *ul;
michael@0 7750 Unit *ur, *uresp1;
michael@0 7751 /* copy safe number of units, then decapitate */
michael@0 7752 res->bits=lhs->bits; /* need sign etc. */
michael@0 7753 uresp1=res->lsu+D2U(set->digits);
michael@0 7754 for (ur=res->lsu, ul=lhs->lsu; ur<uresp1; ur++, ul++) *ur=*ul;
michael@0 7755 res->digits=D2U(set->digits)*DECDPUN;
michael@0 7756 /* maybe still too long */
michael@0 7757 if (res->digits>set->digits) decDecap(res, res->digits-set->digits);
michael@0 7758 }
michael@0 7759
michael@0 7760 res->bits&=~DECSNAN; /* convert any sNaN to NaN, while */
michael@0 7761 res->bits|=DECNAN; /* .. preserving sign */
michael@0 7762 res->exponent=0; /* clean exponent */
michael@0 7763 /* [coefficient was copied/decapitated] */
michael@0 7764 return res;
michael@0 7765 } /* decNaNs */
michael@0 7766
michael@0 7767 /* ------------------------------------------------------------------ */
michael@0 7768 /* decStatus -- apply non-zero status */
michael@0 7769 /* */
michael@0 7770 /* dn is the number to set if error */
michael@0 7771 /* status contains the current status (not yet in context) */
michael@0 7772 /* set is the context */
michael@0 7773 /* */
michael@0 7774 /* If the status is an error status, the number is set to a NaN, */
michael@0 7775 /* unless the error was an overflow, divide-by-zero, or underflow, */
michael@0 7776 /* in which case the number will have already been set. */
michael@0 7777 /* */
michael@0 7778 /* The context status is then updated with the new status. Note that */
michael@0 7779 /* this may raise a signal, so control may never return from this */
michael@0 7780 /* routine (hence resources must be recovered before it is called). */
michael@0 7781 /* ------------------------------------------------------------------ */
michael@0 7782 static void decStatus(decNumber *dn, uInt status, decContext *set) {
michael@0 7783 if (status & DEC_NaNs) { /* error status -> NaN */
michael@0 7784 /* if cause was an sNaN, clear and propagate [NaN is already set up] */
michael@0 7785 if (status & DEC_sNaN) status&=~DEC_sNaN;
michael@0 7786 else {
michael@0 7787 uprv_decNumberZero(dn); /* other error: clean throughout */
michael@0 7788 dn->bits=DECNAN; /* and make a quiet NaN */
michael@0 7789 }
michael@0 7790 }
michael@0 7791 uprv_decContextSetStatus(set, status); /* [may not return] */
michael@0 7792 return;
michael@0 7793 } /* decStatus */
michael@0 7794
michael@0 7795 /* ------------------------------------------------------------------ */
michael@0 7796 /* decGetDigits -- count digits in a Units array */
michael@0 7797 /* */
michael@0 7798 /* uar is the Unit array holding the number (this is often an */
michael@0 7799 /* accumulator of some sort) */
michael@0 7800 /* len is the length of the array in units [>=1] */
michael@0 7801 /* */
michael@0 7802 /* returns the number of (significant) digits in the array */
michael@0 7803 /* */
michael@0 7804 /* All leading zeros are excluded, except the last if the array has */
michael@0 7805 /* only zero Units. */
michael@0 7806 /* ------------------------------------------------------------------ */
michael@0 7807 /* This may be called twice during some operations. */
michael@0 7808 static Int decGetDigits(Unit *uar, Int len) {
michael@0 7809 Unit *up=uar+(len-1); /* -> msu */
michael@0 7810 Int digits=(len-1)*DECDPUN+1; /* possible digits excluding msu */
michael@0 7811 #if DECDPUN>4
michael@0 7812 uInt const *pow; /* work */
michael@0 7813 #endif
michael@0 7814 /* (at least 1 in final msu) */
michael@0 7815 #if DECCHECK
michael@0 7816 if (len<1) printf("decGetDigits called with len<1 [%ld]\n", (LI)len);
michael@0 7817 #endif
michael@0 7818
michael@0 7819 for (; up>=uar; up--) {
michael@0 7820 if (*up==0) { /* unit is all 0s */
michael@0 7821 if (digits==1) break; /* a zero has one digit */
michael@0 7822 digits-=DECDPUN; /* adjust for 0 unit */
michael@0 7823 continue;}
michael@0 7824 /* found the first (most significant) non-zero Unit */
michael@0 7825 #if DECDPUN>1 /* not done yet */
michael@0 7826 if (*up<10) break; /* is 1-9 */
michael@0 7827 digits++;
michael@0 7828 #if DECDPUN>2 /* not done yet */
michael@0 7829 if (*up<100) break; /* is 10-99 */
michael@0 7830 digits++;
michael@0 7831 #if DECDPUN>3 /* not done yet */
michael@0 7832 if (*up<1000) break; /* is 100-999 */
michael@0 7833 digits++;
michael@0 7834 #if DECDPUN>4 /* count the rest ... */
michael@0 7835 for (pow=&powers[4]; *up>=*pow; pow++) digits++;
michael@0 7836 #endif
michael@0 7837 #endif
michael@0 7838 #endif
michael@0 7839 #endif
michael@0 7840 break;
michael@0 7841 } /* up */
michael@0 7842 return digits;
michael@0 7843 } /* decGetDigits */
michael@0 7844
michael@0 7845 #if DECTRACE | DECCHECK
michael@0 7846 /* ------------------------------------------------------------------ */
michael@0 7847 /* decNumberShow -- display a number [debug aid] */
michael@0 7848 /* dn is the number to show */
michael@0 7849 /* */
michael@0 7850 /* Shows: sign, exponent, coefficient (msu first), digits */
michael@0 7851 /* or: sign, special-value */
michael@0 7852 /* ------------------------------------------------------------------ */
michael@0 7853 /* this is public so other modules can use it */
michael@0 7854 void uprv_decNumberShow(const decNumber *dn) {
michael@0 7855 const Unit *up; /* work */
michael@0 7856 uInt u, d; /* .. */
michael@0 7857 Int cut; /* .. */
michael@0 7858 char isign='+'; /* main sign */
michael@0 7859 if (dn==NULL) {
michael@0 7860 printf("NULL\n");
michael@0 7861 return;}
michael@0 7862 if (decNumberIsNegative(dn)) isign='-';
michael@0 7863 printf(" >> %c ", isign);
michael@0 7864 if (dn->bits&DECSPECIAL) { /* Is a special value */
michael@0 7865 if (decNumberIsInfinite(dn)) printf("Infinity");
michael@0 7866 else { /* a NaN */
michael@0 7867 if (dn->bits&DECSNAN) printf("sNaN"); /* signalling NaN */
michael@0 7868 else printf("NaN");
michael@0 7869 }
michael@0 7870 /* if coefficient and exponent are 0, no more to do */
michael@0 7871 if (dn->exponent==0 && dn->digits==1 && *dn->lsu==0) {
michael@0 7872 printf("\n");
michael@0 7873 return;}
michael@0 7874 /* drop through to report other information */
michael@0 7875 printf(" ");
michael@0 7876 }
michael@0 7877
michael@0 7878 /* now carefully display the coefficient */
michael@0 7879 up=dn->lsu+D2U(dn->digits)-1; /* msu */
michael@0 7880 printf("%ld", (LI)*up);
michael@0 7881 for (up=up-1; up>=dn->lsu; up--) {
michael@0 7882 u=*up;
michael@0 7883 printf(":");
michael@0 7884 for (cut=DECDPUN-1; cut>=0; cut--) {
michael@0 7885 d=u/powers[cut];
michael@0 7886 u-=d*powers[cut];
michael@0 7887 printf("%ld", (LI)d);
michael@0 7888 } /* cut */
michael@0 7889 } /* up */
michael@0 7890 if (dn->exponent!=0) {
michael@0 7891 char esign='+';
michael@0 7892 if (dn->exponent<0) esign='-';
michael@0 7893 printf(" E%c%ld", esign, (LI)abs(dn->exponent));
michael@0 7894 }
michael@0 7895 printf(" [%ld]\n", (LI)dn->digits);
michael@0 7896 } /* decNumberShow */
michael@0 7897 #endif
michael@0 7898
michael@0 7899 #if DECTRACE || DECCHECK
michael@0 7900 /* ------------------------------------------------------------------ */
michael@0 7901 /* decDumpAr -- display a unit array [debug/check aid] */
michael@0 7902 /* name is a single-character tag name */
michael@0 7903 /* ar is the array to display */
michael@0 7904 /* len is the length of the array in Units */
michael@0 7905 /* ------------------------------------------------------------------ */
michael@0 7906 static void decDumpAr(char name, const Unit *ar, Int len) {
michael@0 7907 Int i;
michael@0 7908 const char *spec;
michael@0 7909 #if DECDPUN==9
michael@0 7910 spec="%09d ";
michael@0 7911 #elif DECDPUN==8
michael@0 7912 spec="%08d ";
michael@0 7913 #elif DECDPUN==7
michael@0 7914 spec="%07d ";
michael@0 7915 #elif DECDPUN==6
michael@0 7916 spec="%06d ";
michael@0 7917 #elif DECDPUN==5
michael@0 7918 spec="%05d ";
michael@0 7919 #elif DECDPUN==4
michael@0 7920 spec="%04d ";
michael@0 7921 #elif DECDPUN==3
michael@0 7922 spec="%03d ";
michael@0 7923 #elif DECDPUN==2
michael@0 7924 spec="%02d ";
michael@0 7925 #else
michael@0 7926 spec="%d ";
michael@0 7927 #endif
michael@0 7928 printf(" :%c: ", name);
michael@0 7929 for (i=len-1; i>=0; i--) {
michael@0 7930 if (i==len-1) printf("%ld ", (LI)ar[i]);
michael@0 7931 else printf(spec, ar[i]);
michael@0 7932 }
michael@0 7933 printf("\n");
michael@0 7934 return;}
michael@0 7935 #endif
michael@0 7936
michael@0 7937 #if DECCHECK
michael@0 7938 /* ------------------------------------------------------------------ */
michael@0 7939 /* decCheckOperands -- check operand(s) to a routine */
michael@0 7940 /* res is the result structure (not checked; it will be set to */
michael@0 7941 /* quiet NaN if error found (and it is not NULL)) */
michael@0 7942 /* lhs is the first operand (may be DECUNRESU) */
michael@0 7943 /* rhs is the second (may be DECUNUSED) */
michael@0 7944 /* set is the context (may be DECUNCONT) */
michael@0 7945 /* returns 0 if both operands, and the context are clean, or 1 */
michael@0 7946 /* otherwise (in which case the context will show an error, */
michael@0 7947 /* unless NULL). Note that res is not cleaned; caller should */
michael@0 7948 /* handle this so res=NULL case is safe. */
michael@0 7949 /* The caller is expected to abandon immediately if 1 is returned. */
michael@0 7950 /* ------------------------------------------------------------------ */
michael@0 7951 static Flag decCheckOperands(decNumber *res, const decNumber *lhs,
michael@0 7952 const decNumber *rhs, decContext *set) {
michael@0 7953 Flag bad=0;
michael@0 7954 if (set==NULL) { /* oops; hopeless */
michael@0 7955 #if DECTRACE || DECVERB
michael@0 7956 printf("Reference to context is NULL.\n");
michael@0 7957 #endif
michael@0 7958 bad=1;
michael@0 7959 return 1;}
michael@0 7960 else if (set!=DECUNCONT
michael@0 7961 && (set->digits<1 || set->round>=DEC_ROUND_MAX)) {
michael@0 7962 bad=1;
michael@0 7963 #if DECTRACE || DECVERB
michael@0 7964 printf("Bad context [digits=%ld round=%ld].\n",
michael@0 7965 (LI)set->digits, (LI)set->round);
michael@0 7966 #endif
michael@0 7967 }
michael@0 7968 else {
michael@0 7969 if (res==NULL) {
michael@0 7970 bad=1;
michael@0 7971 #if DECTRACE
michael@0 7972 /* this one not DECVERB as standard tests include NULL */
michael@0 7973 printf("Reference to result is NULL.\n");
michael@0 7974 #endif
michael@0 7975 }
michael@0 7976 if (!bad && lhs!=DECUNUSED) bad=(decCheckNumber(lhs));
michael@0 7977 if (!bad && rhs!=DECUNUSED) bad=(decCheckNumber(rhs));
michael@0 7978 }
michael@0 7979 if (bad) {
michael@0 7980 if (set!=DECUNCONT) uprv_decContextSetStatus(set, DEC_Invalid_operation);
michael@0 7981 if (res!=DECUNRESU && res!=NULL) {
michael@0 7982 uprv_decNumberZero(res);
michael@0 7983 res->bits=DECNAN; /* qNaN */
michael@0 7984 }
michael@0 7985 }
michael@0 7986 return bad;
michael@0 7987 } /* decCheckOperands */
michael@0 7988
michael@0 7989 /* ------------------------------------------------------------------ */
michael@0 7990 /* decCheckNumber -- check a number */
michael@0 7991 /* dn is the number to check */
michael@0 7992 /* returns 0 if the number is clean, or 1 otherwise */
michael@0 7993 /* */
michael@0 7994 /* The number is considered valid if it could be a result from some */
michael@0 7995 /* operation in some valid context. */
michael@0 7996 /* ------------------------------------------------------------------ */
michael@0 7997 static Flag decCheckNumber(const decNumber *dn) {
michael@0 7998 const Unit *up; /* work */
michael@0 7999 uInt maxuint; /* .. */
michael@0 8000 Int ae, d, digits; /* .. */
michael@0 8001 Int emin, emax; /* .. */
michael@0 8002
michael@0 8003 if (dn==NULL) { /* hopeless */
michael@0 8004 #if DECTRACE
michael@0 8005 /* this one not DECVERB as standard tests include NULL */
michael@0 8006 printf("Reference to decNumber is NULL.\n");
michael@0 8007 #endif
michael@0 8008 return 1;}
michael@0 8009
michael@0 8010 /* check special values */
michael@0 8011 if (dn->bits & DECSPECIAL) {
michael@0 8012 if (dn->exponent!=0) {
michael@0 8013 #if DECTRACE || DECVERB
michael@0 8014 printf("Exponent %ld (not 0) for a special value [%02x].\n",
michael@0 8015 (LI)dn->exponent, dn->bits);
michael@0 8016 #endif
michael@0 8017 return 1;}
michael@0 8018
michael@0 8019 /* 2003.09.08: NaNs may now have coefficients, so next tests Inf only */
michael@0 8020 if (decNumberIsInfinite(dn)) {
michael@0 8021 if (dn->digits!=1) {
michael@0 8022 #if DECTRACE || DECVERB
michael@0 8023 printf("Digits %ld (not 1) for an infinity.\n", (LI)dn->digits);
michael@0 8024 #endif
michael@0 8025 return 1;}
michael@0 8026 if (*dn->lsu!=0) {
michael@0 8027 #if DECTRACE || DECVERB
michael@0 8028 printf("LSU %ld (not 0) for an infinity.\n", (LI)*dn->lsu);
michael@0 8029 #endif
michael@0 8030 decDumpAr('I', dn->lsu, D2U(dn->digits));
michael@0 8031 return 1;}
michael@0 8032 } /* Inf */
michael@0 8033 /* 2002.12.26: negative NaNs can now appear through proposed IEEE */
michael@0 8034 /* concrete formats (decimal64, etc.). */
michael@0 8035 return 0;
michael@0 8036 }
michael@0 8037
michael@0 8038 /* check the coefficient */
michael@0 8039 if (dn->digits<1 || dn->digits>DECNUMMAXP) {
michael@0 8040 #if DECTRACE || DECVERB
michael@0 8041 printf("Digits %ld in number.\n", (LI)dn->digits);
michael@0 8042 #endif
michael@0 8043 return 1;}
michael@0 8044
michael@0 8045 d=dn->digits;
michael@0 8046
michael@0 8047 for (up=dn->lsu; d>0; up++) {
michael@0 8048 if (d>DECDPUN) maxuint=DECDPUNMAX;
michael@0 8049 else { /* reached the msu */
michael@0 8050 maxuint=powers[d]-1;
michael@0 8051 if (dn->digits>1 && *up<powers[d-1]) {
michael@0 8052 #if DECTRACE || DECVERB
michael@0 8053 printf("Leading 0 in number.\n");
michael@0 8054 uprv_decNumberShow(dn);
michael@0 8055 #endif
michael@0 8056 return 1;}
michael@0 8057 }
michael@0 8058 if (*up>maxuint) {
michael@0 8059 #if DECTRACE || DECVERB
michael@0 8060 printf("Bad Unit [%08lx] in %ld-digit number at offset %ld [maxuint %ld].\n",
michael@0 8061 (LI)*up, (LI)dn->digits, (LI)(up-dn->lsu), (LI)maxuint);
michael@0 8062 #endif
michael@0 8063 return 1;}
michael@0 8064 d-=DECDPUN;
michael@0 8065 }
michael@0 8066
michael@0 8067 /* check the exponent. Note that input operands can have exponents */
michael@0 8068 /* which are out of the set->emin/set->emax and set->digits range */
michael@0 8069 /* (just as they can have more digits than set->digits). */
michael@0 8070 ae=dn->exponent+dn->digits-1; /* adjusted exponent */
michael@0 8071 emax=DECNUMMAXE;
michael@0 8072 emin=DECNUMMINE;
michael@0 8073 digits=DECNUMMAXP;
michael@0 8074 if (ae<emin-(digits-1)) {
michael@0 8075 #if DECTRACE || DECVERB
michael@0 8076 printf("Adjusted exponent underflow [%ld].\n", (LI)ae);
michael@0 8077 uprv_decNumberShow(dn);
michael@0 8078 #endif
michael@0 8079 return 1;}
michael@0 8080 if (ae>+emax) {
michael@0 8081 #if DECTRACE || DECVERB
michael@0 8082 printf("Adjusted exponent overflow [%ld].\n", (LI)ae);
michael@0 8083 uprv_decNumberShow(dn);
michael@0 8084 #endif
michael@0 8085 return 1;}
michael@0 8086
michael@0 8087 return 0; /* it's OK */
michael@0 8088 } /* decCheckNumber */
michael@0 8089
michael@0 8090 /* ------------------------------------------------------------------ */
michael@0 8091 /* decCheckInexact -- check a normal finite inexact result has digits */
michael@0 8092 /* dn is the number to check */
michael@0 8093 /* set is the context (for status and precision) */
michael@0 8094 /* sets Invalid operation, etc., if some digits are missing */
michael@0 8095 /* [this check is not made for DECSUBSET compilation or when */
michael@0 8096 /* subnormal is not set] */
michael@0 8097 /* ------------------------------------------------------------------ */
michael@0 8098 static void decCheckInexact(const decNumber *dn, decContext *set) {
michael@0 8099 #if !DECSUBSET && DECEXTFLAG
michael@0 8100 if ((set->status & (DEC_Inexact|DEC_Subnormal))==DEC_Inexact
michael@0 8101 && (set->digits!=dn->digits) && !(dn->bits & DECSPECIAL)) {
michael@0 8102 #if DECTRACE || DECVERB
michael@0 8103 printf("Insufficient digits [%ld] on normal Inexact result.\n",
michael@0 8104 (LI)dn->digits);
michael@0 8105 uprv_decNumberShow(dn);
michael@0 8106 #endif
michael@0 8107 uprv_decContextSetStatus(set, DEC_Invalid_operation);
michael@0 8108 }
michael@0 8109 #else
michael@0 8110 /* next is a noop for quiet compiler */
michael@0 8111 if (dn!=NULL && dn->digits==0) set->status|=DEC_Invalid_operation;
michael@0 8112 #endif
michael@0 8113 return;
michael@0 8114 } /* decCheckInexact */
michael@0 8115 #endif
michael@0 8116
michael@0 8117 #if DECALLOC
michael@0 8118 #undef malloc
michael@0 8119 #undef free
michael@0 8120 /* ------------------------------------------------------------------ */
michael@0 8121 /* decMalloc -- accountable allocation routine */
michael@0 8122 /* n is the number of bytes to allocate */
michael@0 8123 /* */
michael@0 8124 /* Semantics is the same as the stdlib malloc routine, but bytes */
michael@0 8125 /* allocated are accounted for globally, and corruption fences are */
michael@0 8126 /* added before and after the 'actual' storage. */
michael@0 8127 /* ------------------------------------------------------------------ */
michael@0 8128 /* This routine allocates storage with an extra twelve bytes; 8 are */
michael@0 8129 /* at the start and hold: */
michael@0 8130 /* 0-3 the original length requested */
michael@0 8131 /* 4-7 buffer corruption detection fence (DECFENCE, x4) */
michael@0 8132 /* The 4 bytes at the end also hold a corruption fence (DECFENCE, x4) */
michael@0 8133 /* ------------------------------------------------------------------ */
michael@0 8134 static void *decMalloc(size_t n) {
michael@0 8135 uInt size=n+12; /* true size */
michael@0 8136 void *alloc; /* -> allocated storage */
michael@0 8137 uByte *b, *b0; /* work */
michael@0 8138 uInt uiwork; /* for macros */
michael@0 8139
michael@0 8140 alloc=malloc(size); /* -> allocated storage */
michael@0 8141 if (alloc==NULL) return NULL; /* out of strorage */
michael@0 8142 b0=(uByte *)alloc; /* as bytes */
michael@0 8143 decAllocBytes+=n; /* account for storage */
michael@0 8144 UBFROMUI(alloc, n); /* save n */
michael@0 8145 /* printf(" alloc ++ dAB: %ld (%ld)\n", (LI)decAllocBytes, (LI)n); */
michael@0 8146 for (b=b0+4; b<b0+8; b++) *b=DECFENCE;
michael@0 8147 for (b=b0+n+8; b<b0+n+12; b++) *b=DECFENCE;
michael@0 8148 return b0+8; /* -> play area */
michael@0 8149 } /* decMalloc */
michael@0 8150
michael@0 8151 /* ------------------------------------------------------------------ */
michael@0 8152 /* decFree -- accountable free routine */
michael@0 8153 /* alloc is the storage to free */
michael@0 8154 /* */
michael@0 8155 /* Semantics is the same as the stdlib malloc routine, except that */
michael@0 8156 /* the global storage accounting is updated and the fences are */
michael@0 8157 /* checked to ensure that no routine has written 'out of bounds'. */
michael@0 8158 /* ------------------------------------------------------------------ */
michael@0 8159 /* This routine first checks that the fences have not been corrupted. */
michael@0 8160 /* It then frees the storage using the 'truw' storage address (that */
michael@0 8161 /* is, offset by 8). */
michael@0 8162 /* ------------------------------------------------------------------ */
michael@0 8163 static void decFree(void *alloc) {
michael@0 8164 uInt n; /* original length */
michael@0 8165 uByte *b, *b0; /* work */
michael@0 8166 uInt uiwork; /* for macros */
michael@0 8167
michael@0 8168 if (alloc==NULL) return; /* allowed; it's a nop */
michael@0 8169 b0=(uByte *)alloc; /* as bytes */
michael@0 8170 b0-=8; /* -> true start of storage */
michael@0 8171 n=UBTOUI(b0); /* lift length */
michael@0 8172 for (b=b0+4; b<b0+8; b++) if (*b!=DECFENCE)
michael@0 8173 printf("=== Corrupt byte [%02x] at offset %d from %ld ===\n", *b,
michael@0 8174 b-b0-8, (LI)b0);
michael@0 8175 for (b=b0+n+8; b<b0+n+12; b++) if (*b!=DECFENCE)
michael@0 8176 printf("=== Corrupt byte [%02x] at offset +%d from %ld, n=%ld ===\n", *b,
michael@0 8177 b-b0-8, (LI)b0, (LI)n);
michael@0 8178 free(b0); /* drop the storage */
michael@0 8179 decAllocBytes-=n; /* account for storage */
michael@0 8180 /* printf(" free -- dAB: %d (%d)\n", decAllocBytes, -n); */
michael@0 8181 } /* decFree */
michael@0 8182 #define malloc(a) decMalloc(a)
michael@0 8183 #define free(a) decFree(a)
michael@0 8184 #endif

mercurial