Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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, ©stat); /* 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 |