150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Decimal Number arithmetic module */ 350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 4fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius/* Copyright (c) IBM Corporation, 2000-2014. All rights reserved. */ 550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This software is made available under the terms of the */ 750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ICU License -- ICU 1.8.1 and later. */ 850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The description and User's Guide ("The decNumber C Library") for */ 1050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* this software is called decNumber.pdf. This document is */ 1150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* available, together with arithmetic and format specifications, */ 1250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* testcases, and Web links, on the General Decimal Arithmetic page. */ 1350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 1450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Please send comments, suggestions, and corrections to the author: */ 1550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* mfc@uk.ibm.com */ 1650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Mike Cowlishaw, IBM Fellow */ 1750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ 1850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 1950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 2050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Modified version, for use from within ICU. 2150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Renamed public functions, to avoid an unwanted export of the 2250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * standard names from the ICU library. 2350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * 2450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Use ICU's uprv_malloc() and uprv_free() 2550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * 2650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Revert comment syntax to plain C 2750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * 2850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Remove a few compiler warnings. 2950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 3050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 3150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This module comprises the routines for arbitrary-precision General */ 3250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Decimal Arithmetic as defined in the specification which may be */ 3350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* found on the General Decimal Arithmetic pages. It implements both */ 3450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the full ('extended') arithmetic and the simpler ('subset') */ 3550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* arithmetic. */ 3650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 3750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Usage notes: */ 3850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 3950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 1. This code is ANSI C89 except: */ 4050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 4150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* a) C99 line comments (double forward slash) are used. (Most C */ 4250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* compilers accept these. If yours does not, a simple script */ 4350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* can be used to convert them to ANSI C comments.) */ 4450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 4550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* b) Types from C99 stdint.h are used. If you do not have this */ 4650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* header file, see the User's Guide section of the decNumber */ 4750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* documentation; this lists the necessary definitions. */ 4850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 4950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* c) If DECDPUN>4 or DECUSE64=1, the C99 64-bit int64_t and */ 5050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* uint64_t types may be used. To avoid these, set DECUSE64=0 */ 5150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and DECDPUN<=4 (see documentation). */ 5250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 5350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The code also conforms to C99 restrictions; in particular, */ 5450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* strict aliasing rules are observed. */ 5550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 5650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 2. The decNumber format which this library uses is optimized for */ 5750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* efficient processing of relatively short numbers; in particular */ 5850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* it allows the use of fixed sized structures and minimizes copy */ 5950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and move operations. It does, however, support arbitrary */ 6050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* precision (up to 999,999,999 digits) and arbitrary exponent */ 6150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* range (Emax in the range 0 through 999,999,999 and Emin in the */ 6250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* range -999,999,999 through 0). Mathematical functions (for */ 6350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* example decNumberExp) as identified below are restricted more */ 6450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* tightly: digits, emax, and -emin in the context must be <= */ 6550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* DEC_MAX_MATH (999999), and their operand(s) must be within */ 6650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* these bounds. */ 6750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 6850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 3. Logical functions are further restricted; their operands must */ 6950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* be finite, positive, have an exponent of zero, and all digits */ 7050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* must be either 0 or 1. The result will only contain digits */ 7150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* which are 0 or 1 (and will have exponent=0 and a sign of 0). */ 7250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 7350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 4. Operands to operator functions are never modified unless they */ 7450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* are also specified to be the result number (which is always */ 7550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* permitted). Other than that case, operands must not overlap. */ 7650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 7750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 5. Error handling: the type of the error is ORed into the status */ 7850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* flags in the current context (decContext structure). The */ 7950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* SIGFPE signal is then raised if the corresponding trap-enabler */ 8050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* flag in the decContext is set (is 1). */ 8150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 8250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* It is the responsibility of the caller to clear the status */ 8350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* flags as required. */ 8450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 8550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The result of any routine which returns a number will always */ 8650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* be a valid number (which may be a special value, such as an */ 8750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Infinity or NaN). */ 8850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 8950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 6. The decNumber format is not an exchangeable concrete */ 9050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* representation as it comprises fields which may be machine- */ 9150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dependent (packed or unpacked, or special length, for example). */ 9250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Canonical conversions to and from strings are provided; other */ 9350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* conversions are available in separate modules. */ 9450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 9550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 7. Normally, input operands are assumed to be valid. Set DECCHECK */ 9650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* to 1 for extended operand checking (including NULL operands). */ 9750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Results are undefined if a badly-formed structure (or a NULL */ 9850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* pointer to a structure) is provided, though with DECCHECK */ 9950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* enabled the operator routines are protected against exceptions. */ 10050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (Except if the result pointer is NULL, which is unrecoverable.) */ 10150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 10250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* However, the routines will never cause exceptions if they are */ 10350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* given well-formed operands, even if the value of the operands */ 10450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* is inappropriate for the operation and DECCHECK is not set. */ 10550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (Except for SIGFPE, as and where documented.) */ 10650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 10750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 8. Subset arithmetic is available only if DECSUBSET is set to 1. */ 10850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 10950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Implementation notes for maintenance of this module: */ 11050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 11150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 1. Storage leak protection: Routines which use malloc are not */ 11250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* permitted to use return for fastpath or error exits (i.e., */ 11350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* they follow strict structured programming conventions). */ 11450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Instead they have a do{}while(0); construct surrounding the */ 11550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* code which is protected -- break may be used to exit this. */ 11650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Other routines can safely use the return statement inline. */ 11750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 11850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Storage leak accounting can be enabled using DECALLOC. */ 11950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 12050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 2. All loops use the for(;;) construct. Any do construct does */ 12150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* not loop; it is for allocation protection as just described. */ 12250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 12350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 3. Setting status in the context must always be the very last */ 12450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* action in a routine, as non-0 status may raise a trap and hence */ 12550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the call to set status may not return (if the handler uses long */ 12650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* jump). Therefore all cleanup must be done first. In general, */ 12750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* to achieve this status is accumulated and is only applied just */ 12850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* before return by calling decContextSetStatus (via decStatus). */ 12950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 13050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Routines which allocate storage cannot, in general, use the */ 13150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 'top level' routines which could cause a non-returning */ 13250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* transfer of control. The decXxxxOp routines are safe (do not */ 13350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* call decStatus even if traps are set in the context) and should */ 13450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* be used instead (they are also a little faster). */ 13550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 13650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 4. Exponent checking is minimized by allowing the exponent to */ 13750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* grow outside its limits during calculations, provided that */ 13850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the decFinalize function is called later. Multiplication and */ 13950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* division, and intermediate calculations in exponentiation, */ 14050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* require more careful checks because of the risk of 31-bit */ 14150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* overflow (the most negative valid exponent is -1999999997, for */ 14250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* a 999999999-digit number with adjusted exponent of -999999999). */ 14350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 14450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 5. Rounding is deferred until finalization of results, with any */ 14550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 'off to the right' data being represented as a single digit */ 14650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* residue (in the range -1 through 9). This avoids any double- */ 14750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rounding when more than one shortening takes place (for */ 14850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* example, when a result is subnormal). */ 14950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 15050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 6. The digits count is allowed to rise to a multiple of DECDPUN */ 15150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* during many operations, so whole Units are handled and exact */ 15250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* accounting of digits is not needed. The correct digits value */ 15350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* is found by decGetDigits, which accounts for leading zeros. */ 15450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This must be called before any rounding if the number of digits */ 15550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* is not known exactly. */ 15650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 15750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 7. The multiply-by-reciprocal 'trick' is used for partitioning */ 15850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* numbers up to four digits, using appropriate constants. This */ 15950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* is not useful for longer numbers because overflow of 32 bits */ 16050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* would lead to 4 multiplies, which is almost as expensive as */ 16150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* a divide (unless a floating-point or 64-bit multiply is */ 16250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* assumed to be available). */ 16350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 16450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 8. Unusual abbreviations that may be used in the commentary: */ 16550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs -- left hand side (operand, of an operation) */ 16650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lsd -- least significant digit (of coefficient) */ 16750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lsu -- least significant Unit (of coefficient) */ 16850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* msd -- most significant digit (of coefficient) */ 16950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* msi -- most significant item (in an array) */ 17050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* msu -- most significant Unit (of coefficient) */ 17150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs -- right hand side (operand, of an operation) */ 17250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* +ve -- positive */ 17350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -ve -- negative */ 17450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ** -- raise to the power */ 17550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 17650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 17750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include <stdlib.h> /* for malloc, free, etc. */ 17850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* #include <stdio.h> */ /* for printf [if needed] */ 17950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include <string.h> /* for strcpy */ 18050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include <ctype.h> /* for lower */ 18127f654740f2a26ad62a5c155af9199af9e69b889claireho#include "cmemory.h" /* for uprv_malloc, etc., in ICU */ 18250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "decNumber.h" /* base number library */ 18350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "decNumberLocal.h" /* decNumber local types, etc. */ 184103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "uassert.h" 18550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 18650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Constants */ 18750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Public lookup table used by the D2U macro */ 18854dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const uByte d2utable[DECMAXD2U+1]=D2UTABLE; 18950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 19050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DECVERB 1 /* set to 1 for verbose DECCHECK */ 19150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define powers DECPOWERS /* old internal name */ 19250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 19350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Local constants */ 19450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DIVIDE 0x80 /* Divide operators */ 19550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define REMAINDER 0x40 /* .. */ 19650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DIVIDEINT 0x20 /* .. */ 19750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define REMNEAR 0x10 /* .. */ 19850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPARE 0x01 /* Compare operators */ 19950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPMAX 0x02 /* .. */ 20050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPMIN 0x03 /* .. */ 20150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPTOTAL 0x04 /* .. */ 20250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPNAN 0x05 /* .. [NaN processing] */ 20350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPSIG 0x06 /* .. [signaling COMPARE] */ 20450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPMAXMAG 0x07 /* .. */ 20550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPMINMAG 0x08 /* .. */ 20650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 20750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DEC_sNaN 0x40000000 /* local status: sNaN signal */ 20850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define BADINT (Int)0x80000000 /* most-negative Int; error indicator */ 20950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Next two indicate an integer >= 10**6, and its parity (bottom bit) */ 21050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define BIGEVEN (Int)0x80000002 21150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define BIGODD (Int)0x80000003 21250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 21354dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const Unit uarrone[1]={1}; /* Unit array of 1, used for incrementing */ 21454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 21554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius/* ------------------------------------------------------------------ */ 21654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius/* round-for-reround digits */ 21754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius/* ------------------------------------------------------------------ */ 218fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if 0 21954dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const uByte DECSTICKYTAB[10]={1,1,2,3,4,6,6,7,8,9}; /* used if sticky */ 220fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif 22154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 22254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius/* ------------------------------------------------------------------ */ 22354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius/* Powers of ten (powers[n]==10**n, 0<=n<=9) */ 22454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius/* ------------------------------------------------------------------ */ 22554dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000, 22654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 10000000, 100000000, 1000000000}; 22754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 22850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 22950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Granularity-dependent code */ 23050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECDPUN<=4 23150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define eInt Int /* extended integer */ 23250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define ueInt uInt /* unsigned extended integer */ 23350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Constant multipliers for divide-by-power-of five using reciprocal */ 23450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* multiply, after removing powers of 2 by shifting, and final shift */ 23550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* of 17 [we only need up to **4] */ 23650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho static const uInt multies[]={131073, 26215, 5243, 1049, 210}; 23750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* QUOT10 -- macro to return the quotient of unit u divided by 10**n */ 23850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17) 23950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#else 24050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* For DECDPUN>4 non-ANSI-89 64-bit types are needed. */ 24150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if !DECUSE64 24250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #error decNumber.c: DECUSE64 must be 1 when DECDPUN>4 24350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 24450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define eInt Long /* extended integer */ 24550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define ueInt uLong /* unsigned extended integer */ 24650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 24750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 24850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Local routines */ 24950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decAddOp(decNumber *, const decNumber *, const decNumber *, 25050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *, uByte, uInt *); 25150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Flag decBiStr(const char *, const char *, const char *); 25250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic uInt decCheckMath(const decNumber *, decContext *, uInt *); 25350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decApplyRound(decNumber *, decContext *, Int, uInt *); 25450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decCompare(const decNumber *lhs, const decNumber *rhs, Flag); 25550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decCompareOp(decNumber *, const decNumber *, 25650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *, decContext *, 25750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag, uInt *); 25850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decCopyFit(decNumber *, const decNumber *, decContext *, 25950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int *, uInt *); 26050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decDecap(decNumber *, Int); 26150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decDivideOp(decNumber *, const decNumber *, 26250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *, decContext *, Flag, uInt *); 26350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decExpOp(decNumber *, const decNumber *, 26450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *, uInt *); 26550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decFinalize(decNumber *, decContext *, Int *, uInt *); 26650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decGetDigits(Unit *, Int); 26750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decGetInt(const decNumber *); 26850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decLnOp(decNumber *, const decNumber *, 26950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *, uInt *); 27050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decMultiplyOp(decNumber *, const decNumber *, 27150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *, decContext *, 27250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *); 27350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decNaNs(decNumber *, const decNumber *, 27450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *, decContext *, uInt *); 27550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decQuantizeOp(decNumber *, const decNumber *, 27650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *, decContext *, Flag, 27750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *); 27850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decReverse(Unit *, Unit *); 27950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetCoeff(decNumber *, decContext *, const Unit *, 28050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int, Int *, uInt *); 28150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetMaxValue(decNumber *, decContext *); 28250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetOverflow(decNumber *, decContext *, uInt *); 28350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetSubnormal(decNumber *, decContext *, Int *, uInt *); 28450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decShiftToLeast(Unit *, Int, Int); 28550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decShiftToMost(Unit *, Int, Int); 28650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decStatus(decNumber *, uInt, decContext *); 28750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decToString(const decNumber *, char[], Flag); 28850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decTrim(decNumber *, decContext *, Flag, Flag, Int *); 28950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decUnitAddSub(const Unit *, Int, const Unit *, Int, Int, 29050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *, Int); 29150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decUnitCompare(const Unit *, Int, const Unit *, Int, Int); 29250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 29350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if !DECSUBSET 29450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decFinish == decFinalize when no subset arithmetic needed */ 29550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define decFinish(a,b,c,d) decFinalize(a,b,c,d) 29650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#else 29750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decFinish(decNumber *, decContext *, Int *, uInt *); 29850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decRoundOperand(const decNumber *, decContext *, uInt *); 29950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 30050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 30150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Local macros */ 30250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* masked special-values bits */ 30350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define SPECIALARG (rhs->bits & DECSPECIAL) 30450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define SPECIALARGS ((lhs->bits | rhs->bits) & DECSPECIAL) 30550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 30650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* For use in ICU */ 30750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define malloc(a) uprv_malloc(a) 30850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define free(a) uprv_free(a) 30950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 31050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Diagnostic macros, etc. */ 31150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECALLOC 31250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Handle malloc/free accounting. If enabled, our accountable routines */ 31350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* are used; otherwise the code just goes straight to the system malloc */ 31450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and free routines. */ 31550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define malloc(a) decMalloc(a) 31650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define free(a) decFree(a) 31750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DECFENCE 0x5a /* corruption detector */ 31850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 'Our' malloc and free: */ 31950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void *decMalloc(size_t); 32050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decFree(void *); 32150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehouInt decAllocBytes=0; /* count of bytes allocated */ 32250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Note that DECALLOC code only checks for storage buffer overflow. */ 32350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* To check for memory leaks, the decAllocBytes variable must be */ 32450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* checked to be 0 at appropriate times (e.g., after the test */ 32550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* harness completes a set of tests). This checking may be unreliable */ 32650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if the testing is done in a multi-thread environment. */ 32750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 32850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 32950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECCHECK 33050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Optional checking routines. Enabling these means that decNumber */ 33150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and decContext operands to operator routines are checked for */ 33250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* correctness. This roughly doubles the execution time of the */ 33350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* fastest routines (and adds 600+ bytes), so should not normally be */ 33450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* used in 'production'. */ 33550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCheckInexact is used to check that inexact results have a full */ 33650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* complement of digits (where appropriate -- this is not the case */ 33750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* for Quantize, for example) */ 33850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DECUNRESU ((decNumber *)(void *)0xffffffff) 33950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DECUNUSED ((const decNumber *)(void *)0xffffffff) 34050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DECUNCONT ((decContext *)(void *)(0xffffffff)) 34150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Flag decCheckOperands(decNumber *, const decNumber *, 34250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *, decContext *); 34350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Flag decCheckNumber(const decNumber *); 34450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decCheckInexact(const decNumber *, decContext *); 34550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 34650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 34750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECTRACE || DECCHECK 34850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Optional trace/debugging routines (may or may not be used) */ 34950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid decNumberShow(const decNumber *); /* displays the components of a number */ 35050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decDumpAr(char, const Unit *, Int); 35150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 35250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 35350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 35450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Conversions */ 35550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 35650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 35750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 35850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* from-int32 -- conversion from Int or uInt */ 35950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 36050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the decNumber to receive the integer */ 36150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* in or uin is the integer to be converted */ 36250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns dn */ 36350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 36450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No error is possible. */ 36550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 36650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberFromInt32(decNumber *dn, Int in) { 36750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt unsig; 36850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (in>=0) unsig=in; 36950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* negative (possibly BADINT) */ 37050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (in==BADINT) unsig=(uInt)1073741824*2; /* special case */ 37150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else unsig=-in; /* invert */ 37250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 37350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* in is now positive */ 37450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromUInt32(dn, unsig); 37550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (in<0) dn->bits=DECNEG; /* sign needed */ 37650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 37750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberFromInt32 */ 37850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 37950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberFromUInt32(decNumber *dn, uInt uin) { 38050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up; /* work pointer */ 38150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(dn); /* clean */ 38250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uin==0) return dn; /* [or decGetDigits bad call] */ 38350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=dn->lsu; uin>0; up++) { 38450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)(uin%(DECDPUNMAX+1)); 38550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uin=uin/(DECDPUNMAX+1); 38650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 38750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=decGetDigits(dn->lsu, up-dn->lsu); 38850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 38950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberFromUInt32 */ 39050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 39150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 39250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* to-int32 -- conversion to Int or uInt */ 39350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 39450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the decNumber to convert */ 39550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context for reporting errors */ 39650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns the converted decNumber, or 0 if Invalid is set */ 39750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 39850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Invalid is set if the decNumber does not have exponent==0 or if */ 39950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* it is a NaN, Infinite, or out-of-range. */ 40050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 40150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI Int U_EXPORT2 uprv_decNumberToInt32(const decNumber *dn, decContext *set) { 40250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 40350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0; 40450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 40550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 40650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* special or too many digits, or bad exponent */ 40750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0) ; /* bad */ 40850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* is a finite integer with 10 or fewer digits */ 40950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int d; /* work */ 41050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up; /* .. */ 41150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt hi=0, lo; /* .. */ 41250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=dn->lsu; /* -> lsu */ 41350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lo=*up; /* get 1 to 9 digits */ 41450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>1 /* split to higher */ 41550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho hi=lo/10; 41650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lo=lo%10; 41750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 41850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; 41950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* collect remaining Units, if any, into hi */ 42050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1]; 42150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now low has the lsd, hi the remainder */ 42250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (hi>214748364 || (hi==214748364 && lo>7)) { /* out of range? */ 42350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* most-negative is a reprieve */ 42450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECNEG && hi==214748364 && lo==8) return 0x80000000; 42550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* bad -- drop through */ 42650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 42750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* in-range always */ 42850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i=X10(hi)+lo; 42950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECNEG) return -i; 43050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return i; 43150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 43250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* integer */ 43350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */ 43450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; 43550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberToInt32 */ 43650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 43750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI uInt U_EXPORT2 uprv_decNumberToUInt32(const decNumber *dn, decContext *set) { 43850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 43950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0; 44050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 44150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* special or too many digits, or bad exponent, or negative (<0) */ 44250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0 44350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (dn->bits&DECNEG && !ISZERO(dn))); /* bad */ 44450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* is a finite integer with 10 or fewer digits */ 44550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int d; /* work */ 44650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up; /* .. */ 44750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt hi=0, lo; /* .. */ 44850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=dn->lsu; /* -> lsu */ 44950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lo=*up; /* get 1 to 9 digits */ 45050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>1 /* split to higher */ 45150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho hi=lo/10; 45250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lo=lo%10; 45350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 45450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; 45550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* collect remaining Units, if any, into hi */ 45650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1]; 45750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 45850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now low has the lsd, hi the remainder */ 45950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (hi>429496729 || (hi==429496729 && lo>5)) ; /* no reprieve possible */ 46050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else return X10(hi)+lo; 46150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* integer */ 46250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */ 46350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; 46450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberToUInt32 */ 46550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 46650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 46750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* to-scientific-string -- conversion to numeric string */ 46850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* to-engineering-string -- conversion to numeric string */ 46950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 47050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberToString(dn, string); */ 47150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberToEngString(dn, string); */ 47250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 47350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the decNumber to convert */ 47450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* string is the string where the result will be laid out */ 47550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 47650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* string must be at least dn->digits+14 characters long */ 47750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 47850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No error is possible, and no status can be set. */ 47950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 48050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI char * U_EXPORT2 uprv_decNumberToString(const decNumber *dn, char *string){ 48150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decToString(dn, string, 0); 48250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return string; 48350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* DecNumberToString */ 48450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 48550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI char * U_EXPORT2 uprv_decNumberToEngString(const decNumber *dn, char *string){ 48650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decToString(dn, string, 1); 48750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return string; 48850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* DecNumberToEngString */ 48950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 49050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 49150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* to-number -- conversion from numeric string */ 49250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 49350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberFromString -- convert string to decNumber */ 49450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn -- the number structure to fill */ 49550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* chars[] -- the string to convert ('\0' terminated) */ 49650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set -- the context used for processing any error, */ 49750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* determining the maximum precision available */ 49850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (set.digits), determining the maximum and minimum */ 49950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* exponent (set.emax and set.emin), determining if */ 50050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* extended values are allowed, and checking the */ 50150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rounding mode if overflow occurs or rounding is */ 50250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* needed. */ 50350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 50450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The length of the coefficient and the size of the exponent are */ 50550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* checked by this routine, so the correct error (Underflow or */ 50650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Overflow) can be reported or rounding applied, as necessary. */ 50750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 50850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If bad syntax is detected, the result will be a quiet NaN. */ 50950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 51050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberFromString(decNumber *dn, const char chars[], 51150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 51250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int exponent=0; /* working exponent [assume 0] */ 51350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte bits=0; /* working flags [assume +ve] */ 51450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *res; /* where result will be built */ 51550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit resbuff[SD2U(DECBUFFER+9)];/* local buffer in case need temporary */ 51650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [+9 allows for ln() constants] */ 51750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *allocres=NULL; /* -> allocated result, iff allocated */ 51850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int d=0; /* count of digits found in decimal part */ 51950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *dotchar=NULL; /* where dot was found */ 52050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *cfirst=chars; /* -> first character of decimal part */ 52150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *last=NULL; /* -> last digit of decimal part */ 52250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *c; /* work */ 52350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up; /* .. */ 52450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>1 52550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int cut, out; /* .. */ 52650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 52750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue; /* rounding residue */ 52850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* error code */ 52950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 53050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 53150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(DECUNRESU, DECUNUSED, DECUNUSED, set)) 53250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return uprv_decNumberZero(dn); 53350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 53450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 53550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* status & malloc protection */ 53650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (c=chars;; c++) { /* -> input character */ 53750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c>='0' && *c<='9') { /* test for Arabic digit */ 53850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho last=c; 53950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho d++; /* count of real digits */ 54050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; /* still in decimal part */ 54150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 54250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='.' && dotchar==NULL) { /* first '.' */ 54350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dotchar=c; /* record offset into decimal part */ 54450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (c==cfirst) cfirst++; /* first digit must follow */ 54550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue;} 54650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (c==chars) { /* first in string... */ 54750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='-') { /* valid - sign */ 54850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cfirst++; 54950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=DECNEG; 55050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue;} 55150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='+') { /* valid + sign */ 55250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cfirst++; 55350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue;} 55450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 55550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* *c is not a digit, or a valid +, -, or '.' */ 55650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 55750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* c */ 55850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 55950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (last==NULL) { /* no digits yet */ 56050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Conversion_syntax;/* assume the worst */ 56150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='\0') break; /* and no more to come... */ 56250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 56350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if subset then infinities and NaNs are not allowed */ 56450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) break; /* hopeless */ 56550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 56650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Infinities and NaNs are possible, here */ 56750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dotchar!=NULL) break; /* .. unless had a dot */ 56850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(dn); /* be optimistic */ 56950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decBiStr(c, "infinity", "INFINITY") 57050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || decBiStr(c, "inf", "INF")) { 57150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=bits | DECINF; 57250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=0; /* is OK */ 57350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* all done */ 57450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 57550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a NaN expected */ 57650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 2003.09.10 NaNs are now permitted to have a sign */ 57750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=bits | DECNAN; /* assume simple NaN */ 57850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='s' || *c=='S') { /* looks like an sNaN */ 57950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; 58050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=bits | DECSNAN; 58150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 58250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c!='n' && *c!='N') break; /* check caseless "NaN" */ 58350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; 58450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c!='a' && *c!='A') break; /* .. */ 58550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; 58650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c!='n' && *c!='N') break; /* .. */ 58750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; 58850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now either nothing, or nnnn payload, expected */ 58950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* -> start of integer and skip leading 0s [including plain 0] */ 59050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (cfirst=c; *cfirst=='0';) cfirst++; 59150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*cfirst=='\0') { /* "NaN" or "sNaN", maybe with all 0s */ 59250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=0; /* it's good */ 59350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* .. */ 59450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 59550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* something other than 0s; setup last and d as usual [no dots] */ 59650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (c=cfirst;; c++, d++) { 59750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<'0' || *c>'9') break; /* test for Arabic digit */ 59850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho last=c; 59950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 60050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c!='\0') break; /* not all digits */ 60150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (d>set->digits-1) { 60250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [NB: payload in a decNumber can be full length unless */ 60350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* clamped, in which case can only be digits-1] */ 60450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->clamp) break; 60550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (d>set->digits) break; 60650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* too many digits? */ 60750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* good; drop through to convert the integer to coefficient */ 60850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=0; /* syntax is OK */ 60950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=dn->bits; /* for copy-back */ 61050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* last==NULL */ 61150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 61250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (*c!='\0') { /* more to process... */ 61350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* had some digits; exponent is only valid sequence now */ 61450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag nege; /* 1=negative exponent */ 61550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *firstexp; /* -> first significant exponent digit */ 61650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Conversion_syntax;/* assume the worst */ 61750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c!='e' && *c!='E') break; 61850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Found 'e' or 'E' -- now process explicit exponent */ 61950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1998.07.11: sign no longer required */ 62050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho nege=0; 62150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; /* to (possible) sign */ 62250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='-') {nege=1; c++;} 62350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (*c=='+') c++; 62450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='\0') break; 62550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 62650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; *c=='0' && *(c+1)!='\0';) c++; /* strip insignificant zeros */ 62750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho firstexp=c; /* save exponent digit place */ 62850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; ;c++) { 62950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<'0' || *c>'9') break; /* not a digit */ 63050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent=X10(exponent)+(Int)*c-(Int)'0'; 63150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* c */ 63250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if not now on a '\0', *c must not be a digit */ 63350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c!='\0') break; 63450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 63550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (this next test must be after the syntax checks) */ 63650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if it was too long the exponent may have wrapped, so check */ 63750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* carefully and set it to a certain overflow if wrap possible */ 63850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (c>=firstexp+9+1) { 63950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (c>firstexp+9+1 || *firstexp>'1') exponent=DECNUMMAXE*2; 64050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [up to 1999999999 is OK, for example 1E-1000000998] */ 64150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 64250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (nege) exponent=-exponent; /* was negative */ 64350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=0; /* is OK */ 64450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* stuff after digits */ 64550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 64650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Here when whole string has been inspected; syntax is good */ 64750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* cfirst->first digit (never dot), last->last digit (ditto) */ 64850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 64950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* strip leading zeros/dot [leave final 0 if all 0's] */ 65050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*cfirst=='0') { /* [cfirst has stepped over .] */ 65150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (c=cfirst; c<last; c++, cfirst++) { 65250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='.') continue; /* ignore dots */ 65350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c!='0') break; /* non-zero found */ 65450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho d--; /* 0 stripped */ 65550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* c */ 65650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 65750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* make a rapid exit for easy zeros if !extended */ 65850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*cfirst=='0' && !set->extended) { 65950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(dn); /* clean result */ 66050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* [could be return] */ 66150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 66250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 66350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* at least one leading 0 */ 66450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 66550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Handle decimal point... */ 66650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dotchar!=NULL && dotchar<last) /* non-trailing '.' found? */ 66750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent-=(last-dotchar); /* adjust exponent */ 66850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [we can now ignore the .] */ 66950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 67050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* OK, the digits string is good. Assemble in the decNumber, or in */ 67150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a temporary units array if rounding is needed */ 67250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (d<=set->digits) res=dn->lsu; /* fits into supplied decNumber */ 67350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* rounding needed */ 67450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int needbytes=D2U(d)*sizeof(Unit);/* bytes needed */ 67550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res=resbuff; /* assume use local buffer */ 67650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>(Int)sizeof(resbuff)) { /* too big for local */ 67750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocres=(Unit *)malloc(needbytes); 67850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocres==NULL) {status|=DEC_Insufficient_storage; break;} 67950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res=allocres; 68050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 68150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 68250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* res now -> number lsu, buffer, or allocated storage for Unit array */ 68350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 68450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Place the coefficient into the selected Unit array */ 68550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [this is often 70% of the cost of this function when DECDPUN>1] */ 68650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>1 68750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho out=0; /* accumulator */ 68850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=res+D2U(d)-1; /* -> msu */ 68950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=d-(up-res)*DECDPUN; /* digits in top unit */ 69050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (c=cfirst;; c++) { /* along the digits */ 69150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='.') continue; /* ignore '.' [don't decrement cut] */ 69250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho out=X10(out)+(Int)*c-(Int)'0'; 69350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (c==last) break; /* done [never get to trailing '.'] */ 69450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut--; 69550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut>0) continue; /* more for this unit */ 69650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)out; /* write unit */ 69750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up--; /* prepare for unit below.. */ 69850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN; /* .. */ 69950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho out=0; /* .. */ 70050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* c */ 70150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)out; /* write lsu */ 70250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 70350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 70450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* DECDPUN==1 */ 70550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=res; /* -> lsu */ 70650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (c=last; c>=cfirst; c--) { /* over each character, from least */ 70750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='.') continue; /* ignore . [don't step up] */ 70850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)((Int)*c-(Int)'0'); 70950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; 71050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* c */ 71150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 71250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 71350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=bits; 71450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=exponent; 71550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=d; 71650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 71750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if not in number (too long) shorten into the number */ 71850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (d>set->digits) { 71950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; 72050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetCoeff(dn, set, res, d, &residue, &status); 72150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* always check for overflow or subnormal and round as needed */ 72250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinalize(dn, set, &residue, &status); 72350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 72450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* no rounding, but may still have overflow or subnormal */ 72550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [these tests are just for performance; finalize repeats them] */ 72650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((dn->exponent-1<set->emin-dn->digits) 72750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (dn->exponent-1>set->emax-set->digits)) { 72850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; 72950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinalize(dn, set, &residue, &status); 73050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 73150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 73250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decNumberShow(dn); */ 73350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* [for break] */ 73450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 73550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocres!=NULL) free(allocres); /* drop any storage used */ 73650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(dn, status, set); 73750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 73850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberFromString */ 73950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 74050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 74150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Operators */ 74250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 74350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 74450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 74550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberAbs -- absolute value operator */ 74650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 74750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = abs(A) */ 74850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 74950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 75050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 75150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 75250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 75350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* See also decNumberCopyAbs for a quiet bitwise version of this. */ 75450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 75550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 75650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This has the same effect as decNumberPlus unless A is negative, */ 75750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* in which case it has the same effect as decNumberMinus. */ 75850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 75950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberAbs(decNumber *res, const decNumber *rhs, 76050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 76150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dzero; /* for 0 */ 76250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 76350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 76450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 76550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 76650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 76750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 76850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dzero); /* set 0 */ 76950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dzero.exponent=rhs->exponent; /* [no coefficient expansion] */ 77050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, &dzero, rhs, set, (uByte)(rhs->bits & DECNEG), &status); 77150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 77250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 77350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 77450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 77550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 77650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberAbs */ 77750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 77850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 77950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberAdd -- add two Numbers */ 78050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 78150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A + B */ 78250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 78350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X+X) */ 78450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 78550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 78650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 78750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 78850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 78950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 79050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This just calls the routine shared with Subtract */ 79150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberAdd(decNumber *res, const decNumber *lhs, 79250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 79350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 79450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, lhs, rhs, set, 0, &status); 79550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 79650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 79750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 79850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 79950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 80050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberAdd */ 80150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 80250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 80350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberAnd -- AND two Numbers, digitwise */ 80450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 80550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A & B */ 80650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 80750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X&X) */ 80850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 80950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 81050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context (used for result length and error report) */ 81150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 81250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 81350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 81450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Logical function restrictions apply (see above); a NaN is */ 81550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 81650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 81750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberAnd(decNumber *res, const decNumber *lhs, 81850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 81950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *ua, *ub; /* -> operands */ 82050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *msua, *msub; /* -> operand msus */ 82150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *uc, *msuc; /* -> result and its msu */ 82250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int msudigs; /* digits in res msu */ 82350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 82450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 82550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 82650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 82750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs) 82850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { 82950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 83050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 83150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 83250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 83350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* operands are valid */ 83450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ua=lhs->lsu; /* bottom-up */ 83550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ub=rhs->lsu; /* .. */ 83650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uc=res->lsu; /* .. */ 83750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msua=ua+D2U(lhs->digits)-1; /* -> msu of lhs */ 83850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msub=ub+D2U(rhs->digits)-1; /* -> msu of rhs */ 83950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msuc=uc+D2U(set->digits)-1; /* -> msu of result */ 84050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */ 84150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */ 84250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit a, b; /* extract units */ 84350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ua>msua) a=0; 84450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else a=*ua; 84550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ub>msub) b=0; 84650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else b=*ub; 84750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uc=0; /* can now write back */ 84850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a|b) { /* maybe 1 bits to examine */ 84950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i, j; 85050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uc=0; /* can now write back */ 85150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This loop could be unrolled and/or use BIN2BCD tables */ 85250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i=0; i<DECDPUN; i++) { 85350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a&b&1) *uc=*uc+(Unit)powers[i]; /* effect AND */ 85450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho j=a%10; 85550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=a/10; 85650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho j|=b%10; 85750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=b/10; 85850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (j>1) { 85950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 86050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 86150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 86250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uc==msuc && i==msudigs-1) break; /* just did final digit */ 86350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each digit */ 86450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* both OK */ 86550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each unit */ 86650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [here uc-1 is the msu of the result] */ 86750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(res->lsu, uc-res->lsu); 86850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=0; /* integer */ 86950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=0; /* sign=0 */ 87050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; /* [no status to set] */ 87150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberAnd */ 87250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 87350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 87450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCompare -- compare two Numbers */ 87550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 87650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B */ 87750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 87850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 87950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 88050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 88150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 88250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 88350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for one digit (or NaN). */ 88450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 88550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCompare(decNumber *res, const decNumber *lhs, 88650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 88750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 88850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPARE, &status); 88950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 89050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 89150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCompare */ 89250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 89350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 89450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCompareSignal -- compare, signalling on all NaNs */ 89550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 89650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B */ 89750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 89850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 89950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 90050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 90150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 90250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 90350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for one digit (or NaN). */ 90450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 90550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCompareSignal(decNumber *res, const decNumber *lhs, 90650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 90750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 90850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPSIG, &status); 90950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 91050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 91150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCompareSignal */ 91250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 91350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 91450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCompareTotal -- compare two Numbers, using total ordering */ 91550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 91650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B, under total ordering */ 91750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 91850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 91950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 92050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 92150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 92250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 92350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for one digit; the result will always be one of */ 92450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -1, 0, or 1. */ 92550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 92650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCompareTotal(decNumber *res, const decNumber *lhs, 92750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 92850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 92950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status); 93050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 93150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 93250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCompareTotal */ 93350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 93450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 93550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCompareTotalMag -- compare, total ordering of magnitudes */ 93650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 93750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = |A| ? |B|, under total ordering */ 93850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 93950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 94050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 94150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 94250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 94350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 94450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for one digit; the result will always be one of */ 94550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -1, 0, or 1. */ 94650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 94750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCompareTotalMag(decNumber *res, const decNumber *lhs, 94850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 94950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 95050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt needbytes; /* for space calculations */ 95150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufa[D2N(DECBUFFER+1)];/* +1 in case DECBUFFER=0 */ 95250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ 95350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufb[D2N(DECBUFFER+1)]; 95450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufb=NULL; /* -> allocated bufb, iff allocated */ 95550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *a, *b; /* temporary pointers */ 95650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 95750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 95850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 95950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 96050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 96150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 96250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if either is negative, take a copy and absolute */ 96350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(lhs)) { /* lhs<0 */ 96450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=bufa; 96550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(lhs->digits)-1)*sizeof(Unit); 96650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufa)) { /* need malloc space */ 96750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufa=(decNumber *)malloc(needbytes); 96850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa==NULL) { /* hopeless -- abandon */ 96950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 97050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 97150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=allocbufa; /* use the allocated space */ 97250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 97350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(a, lhs); /* copy content */ 97450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->bits&=~DECNEG; /* .. and clear the sign */ 97550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=a; /* use copy from here on */ 97650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 97750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) { /* rhs<0 */ 97850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=bufb; 97950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit); 98050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufb)) { /* need malloc space */ 98150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufb=(decNumber *)malloc(needbytes); 98250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufb==NULL) { /* hopeless -- abandon */ 98350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 98450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 98550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=allocbufb; /* use the allocated space */ 98650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 98750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(b, rhs); /* copy content */ 98850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b->bits&=~DECNEG; /* .. and clear the sign */ 98950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=b; /* use copy from here on */ 99050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 99150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status); 99250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 99350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 99450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */ 99550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufb!=NULL) free(allocbufb); /* .. */ 99650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 99750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 99850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCompareTotalMag */ 99950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 100050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 100150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberDivide -- divide one number by another */ 100250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 100350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A / B */ 100450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 100550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X/X) */ 100650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 100750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 100850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 100950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 101050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 101150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 101250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberDivide(decNumber *res, const decNumber *lhs, 101350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 101450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 101550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(res, lhs, rhs, set, DIVIDE, &status); 101650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 101750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 101850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 101950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 102050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 102150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberDivide */ 102250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 102350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 102450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberDivideInteger -- divide and return integer quotient */ 102550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 102650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A # B, where # is the integer divide operator */ 102750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 102850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X#X) */ 102950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 103050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 103150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 103250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 103350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 103450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 103550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberDivideInteger(decNumber *res, const decNumber *lhs, 103650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 103750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 103850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(res, lhs, rhs, set, DIVIDEINT, &status); 103950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 104050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 104150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberDivideInteger */ 104250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 104350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 104450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberExp -- exponentiation */ 104550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 104650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = exp(A) */ 104750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 104850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 104950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 105050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context; note that rounding mode has no effect */ 105150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 105250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 105350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 105450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Mathematical function restrictions apply (see above); a NaN is */ 105550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 105650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 105750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Finite results will always be full precision and Inexact, except */ 105850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* when A is a zero or -Infinity (giving 1 or 0 respectively). */ 105950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 106050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */ 106150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* almost always be correctly rounded, but may be up to 1 ulp in */ 106250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* error in rare cases. */ 106350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 106450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This is a wrapper for decExpOp which can handle the slightly wider */ 106550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (double) range needed by Ln (which has to be able to calculate */ 106650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* exp(-a) where a can be the tiniest number (Ntiny). */ 106750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 106850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberExp(decNumber *res, const decNumber *rhs, 106950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 107050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 107150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 107250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */ 107350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 107450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 107550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 107650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 107750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 107850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 107950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Check restrictions; these restrictions ensure that if h=8 (see */ 108050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decExpOp) then the result will either overflow or underflow to 0. */ 108150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Other math functions restrict the input range, too, for inverses. */ 108250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If not violated then carry out the operation. */ 108350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */ 108450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 108550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 108650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operand and set lostDigits status, as needed */ 108750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>set->digits) { 108850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, &status); 108950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 109050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 109150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 109250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 109350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 109450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decExpOp(res, rhs, set, &status); 109550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 109650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 109750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 109850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs !=NULL) free(allocrhs); /* drop any storage used */ 109950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 110050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* apply significant status */ 110150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 110250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 110350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 110450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 110550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 110650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberExp */ 110750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 110850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 110950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberFMA -- fused multiply add */ 111050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 111150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes D = (A * B) + C with only one rounding */ 111250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 111350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is D, the result. D may be A or B or C (e.g., X=FMA(X,X,X)) */ 111450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 111550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 111650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* fhs is C [far hand side] */ 111750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 111850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 111950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Mathematical function restrictions apply (see above); a NaN is */ 112050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 112150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 112250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 112350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 112450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberFMA(decNumber *res, const decNumber *lhs, 112550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, const decNumber *fhs, 112650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 112750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 112850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext dcmul; /* context for the multiplication */ 112950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt needbytes; /* for space calculations */ 113050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufa[D2N(DECBUFFER*2+1)]; 113150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ 113250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *acc; /* accumulator pointer */ 113350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dzero; /* work */ 113450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 113550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 113650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 113750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, fhs, DECUNUSED, set)) return res; 113850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 113950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 114050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 114150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 114250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { /* [undefined if subset] */ 114350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 114450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 114550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 114650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Check math restrictions [these ensure no overflow or underflow] */ 114750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((!decNumberIsSpecial(lhs) && decCheckMath(lhs, set, &status)) 114850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (!decNumberIsSpecial(rhs) && decCheckMath(rhs, set, &status)) 114950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (!decNumberIsSpecial(fhs) && decCheckMath(fhs, set, &status))) break; 115050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set up context for multiply */ 115150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dcmul=*set; 115250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dcmul.digits=lhs->digits+rhs->digits; /* just enough */ 115350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [The above may be an over-estimate for subset arithmetic, but that's OK] */ 115450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dcmul.emax=DEC_MAX_EMAX; /* effectively unbounded .. */ 115550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dcmul.emin=DEC_MIN_EMIN; /* [thanks to Math restrictions] */ 115650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set up decNumber space to receive the result of the multiply */ 115750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=bufa; /* may fit */ 115850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(dcmul.digits)-1)*sizeof(Unit); 115950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufa)) { /* need malloc space */ 116050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufa=(decNumber *)malloc(needbytes); 116150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa==NULL) { /* hopeless -- abandon */ 116250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 116350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 116450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=allocbufa; /* use the allocated space */ 116550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 116650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* multiply with extended range and necessary precision */ 116750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /*printf("emin=%ld\n", dcmul.emin); */ 116850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(acc, lhs, rhs, &dcmul, &status); 116950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Only Invalid operation (from sNaN or Inf * 0) is possible in */ 117050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* status; if either is seen than ignore fhs (in case it is */ 117150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* another sNaN) and set acc to NaN unless we had an sNaN */ 117250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [decMultiplyOp leaves that to caller] */ 117350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Note sNaN has to go through addOp to shorten payload if */ 117450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* necessary */ 117550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((status&DEC_Invalid_operation)!=0) { 117650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(status&DEC_sNaN)) { /* but be true invalid */ 117750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* acc not yet set */ 117850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=DECNAN; 117950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 118050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 118150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dzero); /* make 0 (any non-NaN would do) */ 118250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fhs=&dzero; /* use that */ 118350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 118450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 118550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* multiply was OK */ 118650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) printf("Status=%08lx after FMA multiply\n", (LI)status); 118750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 118850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 118950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* add the third operand and result -> res, and all is done */ 119050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, acc, fhs, set, 0, &status); 119150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 119250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 119350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */ 119450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 119550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 119650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 119750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 119850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 119950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberFMA */ 120050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 120150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 120250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberInvert -- invert a Number, digitwise */ 120350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 120450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = ~A */ 120550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 120650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A (e.g., X=~X) */ 120750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 120850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context (used for result length and error report) */ 120950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 121050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 121150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 121250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Logical function restrictions apply (see above); a NaN is */ 121350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 121450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 121550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberInvert(decNumber *res, const decNumber *rhs, 121650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 121750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *ua, *msua; /* -> operand and its msu */ 121850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *uc, *msuc; /* -> result and its msu */ 121950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int msudigs; /* digits in res msu */ 122050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 122150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 122250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 122350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 122450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { 122550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 122650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 122750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 122850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* operand is valid */ 122950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ua=rhs->lsu; /* bottom-up */ 123050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uc=res->lsu; /* .. */ 123150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msua=ua+D2U(rhs->digits)-1; /* -> msu of rhs */ 123250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msuc=uc+D2U(set->digits)-1; /* -> msu of result */ 123350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */ 123450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; uc<=msuc; ua++, uc++) { /* Unit loop */ 123550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit a; /* extract unit */ 123650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i, j; /* work */ 123750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ua>msua) a=0; 123850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else a=*ua; 123950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uc=0; /* can now write back */ 124050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* always need to examine all bits in rhs */ 124150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This loop could be unrolled and/or use BIN2BCD tables */ 124250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i=0; i<DECDPUN; i++) { 124350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((~a)&1) *uc=*uc+(Unit)powers[i]; /* effect INVERT */ 124450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho j=a%10; 124550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=a/10; 124650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (j>1) { 124750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 124850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 124950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 125050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uc==msuc && i==msudigs-1) break; /* just did final digit */ 125150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each digit */ 125250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each unit */ 125350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [here uc-1 is the msu of the result] */ 125450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(res->lsu, uc-res->lsu); 125550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=0; /* integer */ 125650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=0; /* sign=0 */ 125750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; /* [no status to set] */ 125850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberInvert */ 125950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 126050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 126150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberLn -- natural logarithm */ 126250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 126350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = ln(A) */ 126450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 126550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 126650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 126750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context; note that rounding mode has no effect */ 126850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 126950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 127050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 127150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Notable cases: */ 127250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A<0 -> Invalid */ 127350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=0 -> -Infinity (Exact) */ 127450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=+Infinity -> +Infinity (Exact) */ 127550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=1 exactly -> 0 (Exact) */ 127650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 127750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Mathematical function restrictions apply (see above); a NaN is */ 127850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 127950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 128050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */ 128150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* almost always be correctly rounded, but may be up to 1 ulp in */ 128250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* error in rare cases. */ 128350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 128450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This is a wrapper for decLnOp which can handle the slightly wider */ 128550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (+11) range needed by Ln, Log10, etc. (which may have to be able */ 128650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* to calculate at p+e+2). */ 128750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 128850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberLn(decNumber *res, const decNumber *rhs, 128950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 129050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 129150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 129250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */ 129350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 129450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 129550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 129650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 129750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 129850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 129950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Check restrictions; this is a math function; if not violated */ 130050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* then carry out the operation. */ 130150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */ 130250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 130350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 130450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operand and set lostDigits status, as needed */ 130550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>set->digits) { 130650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, &status); 130750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 130850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 130950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 131050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* special check in subset for rhs=0 */ 131150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) { /* +/- zeros -> error */ 131250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 131350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 131450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* extended=0 */ 131550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 131650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decLnOp(res, rhs, set, &status); 131750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 131850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 131950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 132050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs !=NULL) free(allocrhs); /* drop any storage used */ 132150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 132250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* apply significant status */ 132350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 132450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 132550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 132650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 132750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 132850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberLn */ 132950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 133050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 133150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberLogB - get adjusted exponent, by 754 rules */ 133250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 133350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = adjustedexponent(A) */ 133450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 133550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 133650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 133750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context, used only for digits and status */ 133850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 133950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for 10 digits (A might have 10**9 digits and */ 134050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* an exponent of +999999999, or one digit and an exponent of */ 134150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -1999999999). */ 134250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 134350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This returns the adjusted exponent of A after (in theory) padding */ 134450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* with zeros on the right to set->digits digits while keeping the */ 134550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* same value. The exponent is not limited by emin/emax. */ 134650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 134750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Notable cases: */ 134850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A<0 -> Use |A| */ 134950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=0 -> -Infinity (Division by zero) */ 135050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=Infinite -> +Infinity (Exact) */ 135150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=1 exactly -> 0 (Exact) */ 135250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* NaNs are propagated as usual */ 135350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 135450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberLogB(decNumber *res, const decNumber *rhs, 135550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 135650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 135750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 135850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 135950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 136050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 136150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 136250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* NaNs as usual; Infinities return +Infinity; 0->oops */ 136350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(rhs)) decNaNs(res, rhs, NULL, set, &status); 136450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsInfinite(rhs)) uprv_decNumberCopyAbs(res, rhs); 136550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsZero(rhs)) { 136650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* prepare for Infinity */ 136750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=DECNEG|DECINF; /* -Infinity */ 136850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Division_by_zero; /* as per 754 */ 136950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 137050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* finite non-zero */ 137150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ae=rhs->exponent+rhs->digits-1; /* adjusted exponent */ 137250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromInt32(res, ae); /* lay it out */ 137350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 137450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 137550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 137650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 137750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberLogB */ 137850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 137950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 138050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberLog10 -- logarithm in base 10 */ 138150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 138250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = log10(A) */ 138350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 138450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 138550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 138650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context; note that rounding mode has no effect */ 138750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 138850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 138950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 139050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Notable cases: */ 139150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A<0 -> Invalid */ 139250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=0 -> -Infinity (Exact) */ 139350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=+Infinity -> +Infinity (Exact) */ 139450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=10**n (if n is an integer) -> n (Exact) */ 139550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 139650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Mathematical function restrictions apply (see above); a NaN is */ 139750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 139850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 139950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */ 140050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* almost always be correctly rounded, but may be up to 1 ulp in */ 140150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* error in rare cases. */ 140250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 140350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This calculates ln(A)/ln(10) using appropriate precision. For */ 140450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ln(A) this is the max(p, rhs->digits + t) + 3, where p is the */ 140550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* requested digits and t is the number of digits in the exponent */ 140650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (maximum 6). For ln(10) it is p + 3; this is often handled by the */ 140750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* fastpath in decLnOp. The final division is done to the requested */ 140850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* precision. */ 140950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 141054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406 141102c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic push 141202c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic ignored "-Warray-bounds" 141302c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#endif 141450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberLog10(decNumber *res, const decNumber *rhs, 141550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 141650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0, ignore=0; /* status accumulators */ 141750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt needbytes; /* for space calculations */ 141850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int p; /* working precision */ 141950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int t; /* digits in exponent of A */ 142050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 142150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffers for a and b working decimals */ 142250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (adjustment calculator, same size) */ 142350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufa[D2N(DECBUFFER+2)]; 142450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ 142550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *a=bufa; /* temporary a */ 142650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufb[D2N(DECBUFFER+2)]; 142750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufb=NULL; /* -> allocated bufb, iff allocated */ 142850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *b=bufb; /* temporary b */ 142950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufw[D2N(10)]; /* working 2-10 digit number */ 143050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *w=bufw; /* .. */ 143150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 143250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */ 143350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 143450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 143550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext aset; /* working context */ 143650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 143750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 143850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 143950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 144050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 144150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Check restrictions; this is a math function; if not violated */ 144250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* then carry out the operation. */ 144350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!decCheckMath(rhs, set, &status)) do { /* protect malloc */ 144450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 144550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 144650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operand and set lostDigits status, as needed */ 144750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>set->digits) { 144850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, &status); 144950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 145050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 145150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 145250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* special check in subset for rhs=0 */ 145350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) { /* +/- zeros -> error */ 145450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 145550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 145650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* extended=0 */ 145750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 145850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 145950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */ 146050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 146150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle exact powers of 10; only check if +ve finite */ 146250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(rhs->bits&(DECNEG|DECSPECIAL)) && !ISZERO(rhs)) { 146350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* (no residue) */ 146450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt copystat=0; /* clean status */ 146550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 146650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* round to a single digit... */ 146750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=1; 146850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(w, rhs, &aset, &residue, ©stat); /* copy & shorten */ 146950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if exact and the digit is 1, rhs is a power of 10 */ 147050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(copystat&DEC_Inexact) && w->lsu[0]==1) { 147150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the exponent, conveniently, is the power of 10; making */ 147250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this the result needs a little care as it might not fit, */ 147350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* so first convert it into the working number, and then move */ 147450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* to res */ 147550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromInt32(w, w->exponent); 147650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; 147750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, w, set, &residue, &status); /* copy & round */ 147850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, &status); /* cleanup/set flags */ 147950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 148050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* not a power of 10 */ 148150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* not a candidate for exact */ 148250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 148350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* simplify the information-content calculation to use 'total */ 148450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* number of digits in a, including exponent' as compared to the */ 148550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* requested digits, as increasing this will only rarely cost an */ 148650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* iteration in ln(a) anyway */ 148750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t=6; /* it can never be >6 */ 148850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 148950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* allocate space when needed... */ 149050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p=(rhs->digits+t>set->digits?rhs->digits+t:set->digits)+3; 149150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit); 149250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufa)) { /* need malloc space */ 149350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufa=(decNumber *)malloc(needbytes); 149450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa==NULL) { /* hopeless -- abandon */ 149550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 149650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 149750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=allocbufa; /* use the allocated space */ 149850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 149950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=p; /* as calculated */ 150050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emax=DEC_MAX_MATH; /* usual bounds */ 150150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emin=-DEC_MAX_MATH; /* .. */ 150250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.clamp=0; /* and no concrete format */ 150350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decLnOp(a, rhs, &aset, &status); /* a=ln(rhs) */ 150450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 150550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* skip the division if the result so far is infinite, NaN, or */ 150650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* zero, or there was an error; note NaN from sNaN needs copy */ 150750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status&DEC_NaNs && !(status&DEC_sNaN)) break; 150850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a->bits&DECSPECIAL || ISZERO(a)) { 150950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, a); /* [will fit] */ 151050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 151150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 151250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* for ln(10) an extra 3 digits of precision are needed */ 151350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p=set->digits+3; 151450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit); 151550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufb)) { /* need malloc space */ 151650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufb=(decNumber *)malloc(needbytes); 151750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufb==NULL) { /* hopeless -- abandon */ 151850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 151950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 152050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=allocbufb; /* use the allocated space */ 152150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 152250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(w); /* set up 10... */ 152350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==1 152450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho w->lsu[1]=1; w->lsu[0]=0; /* .. */ 152550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 152650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho w->lsu[0]=10; /* .. */ 152750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 152850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho w->digits=2; /* .. */ 152950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 153050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=p; 153150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decLnOp(b, w, &aset, &ignore); /* b=ln(10) */ 153250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 153350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=set->digits; /* for final divide */ 153450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(res, a, b, &aset, DIVIDE, &status); /* into result */ 153550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* [for break] */ 153650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 153750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */ 153850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufb!=NULL) free(allocbufb); /* .. */ 153950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 154050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs !=NULL) free(allocrhs); /* .. */ 154150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 154250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* apply significant status */ 154350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 154450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 154550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 154650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 154750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 154850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberLog10 */ 154954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406 155002c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic pop 155102c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#endif 155250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 155350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 155450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberMax -- compare two Numbers and return the maximum */ 155550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 155650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B, returning the maximum by 754 rules */ 155750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 155850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 155950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 156050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 156150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 156250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 156350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 156450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 156550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberMax(decNumber *res, const decNumber *lhs, 156650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 156750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 156850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPMAX, &status); 156950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 157050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 157150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 157250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 157350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 157450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberMax */ 157550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 157650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 157750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberMaxMag -- compare and return the maximum by magnitude */ 157850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 157950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B, returning the maximum by 754 rules */ 158050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 158150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 158250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 158350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 158450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 158550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 158650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 158750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 158850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberMaxMag(decNumber *res, const decNumber *lhs, 158950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 159050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 159150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPMAXMAG, &status); 159250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 159350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 159450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 159550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 159650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 159750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberMaxMag */ 159850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 159950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 160050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberMin -- compare two Numbers and return the minimum */ 160150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 160250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B, returning the minimum by 754 rules */ 160350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 160450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 160550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 160650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 160750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 160850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 160950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 161050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 161150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberMin(decNumber *res, const decNumber *lhs, 161250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 161350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 161450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPMIN, &status); 161550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 161650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 161750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 161850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 161950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 162050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberMin */ 162150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 162250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 162350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberMinMag -- compare and return the minimum by magnitude */ 162450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 162550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B, returning the minimum by 754 rules */ 162650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 162750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 162850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 162950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 163050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 163150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 163250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 163350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 163450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberMinMag(decNumber *res, const decNumber *lhs, 163550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 163650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 163750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPMINMAG, &status); 163850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 163950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 164050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 164150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 164250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 164350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberMinMag */ 164450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 164550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 164650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberMinus -- prefix minus operator */ 164750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 164850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = 0 - A */ 164950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 165050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 165150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 165250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 165350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 165450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* See also decNumberCopyNegate for a quiet bitwise version of this. */ 165550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 165650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 165750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Simply use AddOp for the subtract, which will do the necessary. */ 165850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 165950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberMinus(decNumber *res, const decNumber *rhs, 166050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 166150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dzero; 166250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 166350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 166450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 166550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 166650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 166750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 166850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dzero); /* make 0 */ 166950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dzero.exponent=rhs->exponent; /* [no coefficient expansion] */ 167050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, &dzero, rhs, set, DECNEG, &status); 167150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 167250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 167350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 167450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 167550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 167650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberMinus */ 167750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 167850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 167950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberNextMinus -- next towards -Infinity */ 168050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 168150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A - infinitesimal, rounded towards -Infinity */ 168250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 168350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 168450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 168550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 168650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 168750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This is a generalization of 754 NextDown. */ 168850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 168950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberNextMinus(decNumber *res, const decNumber *rhs, 169050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 169150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dtiny; /* constant */ 169250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset=*set; /* work */ 169350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 169450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 169550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 169650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 169750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 169850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* +Infinity is the special case */ 169950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((rhs->bits&(DECINF|DECNEG))==DECINF) { 170050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetMaxValue(res, set); /* is +ve */ 170150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* there is no status to set */ 170250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 170350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 170450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dtiny); /* start with 0 */ 170550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dtiny.lsu[0]=1; /* make number that is .. */ 170650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dtiny.exponent=DEC_MIN_EMIN-1; /* .. smaller than tiniest */ 170750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.round=DEC_ROUND_FLOOR; 170850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, rhs, &dtiny, &workset, DECNEG, &status); 170950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status&=DEC_Invalid_operation|DEC_sNaN; /* only sNaN Invalid please */ 171050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 171150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 171250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberNextMinus */ 171350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 171450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 171550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberNextPlus -- next towards +Infinity */ 171650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 171750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A + infinitesimal, rounded towards +Infinity */ 171850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 171950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 172050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 172150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 172250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 172350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This is a generalization of 754 NextUp. */ 172450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 172550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberNextPlus(decNumber *res, const decNumber *rhs, 172650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 172750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dtiny; /* constant */ 172850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset=*set; /* work */ 172950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 173050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 173150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 173250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 173350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 173450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* -Infinity is the special case */ 173550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((rhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) { 173650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetMaxValue(res, set); 173750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=DECNEG; /* negative */ 173850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* there is no status to set */ 173950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 174050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 174150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dtiny); /* start with 0 */ 174250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dtiny.lsu[0]=1; /* make number that is .. */ 174350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dtiny.exponent=DEC_MIN_EMIN-1; /* .. smaller than tiniest */ 174450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.round=DEC_ROUND_CEILING; 174550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, rhs, &dtiny, &workset, 0, &status); 174650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status&=DEC_Invalid_operation|DEC_sNaN; /* only sNaN Invalid please */ 174750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 174850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 174950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberNextPlus */ 175050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 175150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 175250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberNextToward -- next towards rhs */ 175350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 175450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A +/- infinitesimal, rounded towards */ 175550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* +/-Infinity in the direction of B, as per 754-1985 nextafter */ 175650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* modified during revision but dropped from 754-2008. */ 175750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 175850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A or B. */ 175950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 176050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 176150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 176250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 176350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This is a generalization of 754-1985 NextAfter. */ 176450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 176550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberNextToward(decNumber *res, const decNumber *lhs, 176650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 176750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dtiny; /* constant */ 176850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset=*set; /* work */ 176950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int result; /* .. */ 177050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 177150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 177250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 177350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 177450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 177550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { 177650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, &status); 177750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 177850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* Is numeric, so no chance of sNaN Invalid, etc. */ 177950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=decCompare(lhs, rhs, 0); /* sign matters */ 178050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result==BADINT) status|=DEC_Insufficient_storage; /* rare */ 178150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* valid compare */ 178250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result==0) uprv_decNumberCopySign(res, lhs, rhs); /* easy */ 178350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* differ: need NextPlus or NextMinus */ 178450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte sub; /* add or subtract */ 178550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result<0) { /* lhs<rhs, do nextplus */ 178650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* -Infinity is the special case */ 178750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((lhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) { 178850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetMaxValue(res, set); 178950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=DECNEG; /* negative */ 179050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; /* there is no status to set */ 179150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 179250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.round=DEC_ROUND_CEILING; 179350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho sub=0; /* add, please */ 179450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* plus */ 179550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* lhs>rhs, do nextminus */ 179650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* +Infinity is the special case */ 179750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((lhs->bits&(DECINF|DECNEG))==DECINF) { 179850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetMaxValue(res, set); 179950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; /* there is no status to set */ 180050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 180150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.round=DEC_ROUND_FLOOR; 180250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho sub=DECNEG; /* subtract, please */ 180350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* minus */ 180450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dtiny); /* start with 0 */ 180550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dtiny.lsu[0]=1; /* make number that is .. */ 180650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dtiny.exponent=DEC_MIN_EMIN-1; /* .. smaller than tiniest */ 180750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, lhs, &dtiny, &workset, sub, &status); /* + or - */ 180850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* turn off exceptions if the result is a normal number */ 180950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (including Nmin), otherwise let all status through */ 181050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_decNumberIsNormal(res, set)) status=0; 181150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* unequal */ 181250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* compare OK */ 181350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* numeric */ 181450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 181550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 181650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberNextToward */ 181750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 181850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 181950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberOr -- OR two Numbers, digitwise */ 182050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 182150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A | B */ 182250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 182350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X|X) */ 182450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 182550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 182650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context (used for result length and error report) */ 182750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 182850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 182950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 183050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Logical function restrictions apply (see above); a NaN is */ 183150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 183250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 183350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberOr(decNumber *res, const decNumber *lhs, 183450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 183550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *ua, *ub; /* -> operands */ 183650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *msua, *msub; /* -> operand msus */ 183750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *uc, *msuc; /* -> result and its msu */ 183850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int msudigs; /* digits in res msu */ 183950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 184050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 184150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 184250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 184350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs) 184450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { 184550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 184650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 184750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 184850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* operands are valid */ 184950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ua=lhs->lsu; /* bottom-up */ 185050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ub=rhs->lsu; /* .. */ 185150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uc=res->lsu; /* .. */ 185250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msua=ua+D2U(lhs->digits)-1; /* -> msu of lhs */ 185350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msub=ub+D2U(rhs->digits)-1; /* -> msu of rhs */ 185450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msuc=uc+D2U(set->digits)-1; /* -> msu of result */ 185550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */ 185650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */ 185750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit a, b; /* extract units */ 185850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ua>msua) a=0; 185950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else a=*ua; 186050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ub>msub) b=0; 186150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else b=*ub; 186250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uc=0; /* can now write back */ 186350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a|b) { /* maybe 1 bits to examine */ 186450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i, j; 186550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This loop could be unrolled and/or use BIN2BCD tables */ 186650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i=0; i<DECDPUN; i++) { 186750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((a|b)&1) *uc=*uc+(Unit)powers[i]; /* effect OR */ 186850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho j=a%10; 186950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=a/10; 187050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho j|=b%10; 187150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=b/10; 187250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (j>1) { 187350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 187450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 187550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 187650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uc==msuc && i==msudigs-1) break; /* just did final digit */ 187750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each digit */ 187850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* non-zero */ 187950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each unit */ 188050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [here uc-1 is the msu of the result] */ 188150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(res->lsu, uc-res->lsu); 188250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=0; /* integer */ 188350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=0; /* sign=0 */ 188450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; /* [no status to set] */ 188550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberOr */ 188650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 188750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 188850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberPlus -- prefix plus operator */ 188950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 189050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = 0 + A */ 189150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 189250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 189350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 189450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 189550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 189650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* See also decNumberCopy for a quiet bitwise version of this. */ 189750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 189850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 189950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This simply uses AddOp; Add will take fast path after preparing A. */ 190050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Performance is a concern here, as this routine is often used to */ 190150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* check operands and apply rounding and overflow/underflow testing. */ 190250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 190350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberPlus(decNumber *res, const decNumber *rhs, 190450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 190550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dzero; 190650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 190750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 190850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 190950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 191050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 191150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dzero); /* make 0 */ 191250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dzero.exponent=rhs->exponent; /* [no coefficient expansion] */ 191350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, &dzero, rhs, set, 0, &status); 191450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 191550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 191650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 191750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 191850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 191950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberPlus */ 192050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 192150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 192250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberMultiply -- multiply two Numbers */ 192350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 192450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A x B */ 192550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 192650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X+X) */ 192750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 192850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 192950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 193050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 193150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 193250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 193350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberMultiply(decNumber *res, const decNumber *lhs, 193450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 193550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 193650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(res, lhs, rhs, set, &status); 193750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 193850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 193950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 194050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 194150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 194250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberMultiply */ 194350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 194450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 194550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberPower -- raise a number to a power */ 194650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 194750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ** B */ 194850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 194950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X**X) */ 195050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 195150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 195250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 195350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 195450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 195550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 195650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Mathematical function restrictions apply (see above); a NaN is */ 195750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 195850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 195950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* However, if 1999999997<=B<=999999999 and B is an integer then the */ 196050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* restrictions on A and the context are relaxed to the usual bounds, */ 196150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* for compatibility with the earlier (integer power only) version */ 196250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of this function. */ 196350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 196450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* When B is an integer, the result may be exact, even if rounded. */ 196550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 196650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The final result is rounded according to the context; it will */ 196750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* almost always be correctly rounded, but may be up to 1 ulp in */ 196850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* error in rare cases. */ 196950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 197050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberPower(decNumber *res, const decNumber *lhs, 197150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 197250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 197350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */ 197450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* .., rhs */ 197550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 197650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocdac=NULL; /* -> allocated acc buffer, iff used */ 197750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocinv=NULL; /* -> allocated 1/x buffer, iff used */ 197850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int reqdigits=set->digits; /* requested DIGITS */ 197950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int n; /* rhs in binary */ 198050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag rhsint=0; /* 1 if rhs is an integer */ 198150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag useint=0; /* 1 if can use integer calculation */ 198250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag isoddint=0; /* 1 if rhs is an integer and odd */ 198350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i; /* work */ 198450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 198550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int dropped; /* .. */ 198650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 198750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt needbytes; /* buffer size needed */ 198850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag seenbit; /* seen a bit while powering */ 198950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* rounding residue */ 199050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulators */ 199150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte bits=0; /* result sign if errors */ 199250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext aset; /* working context */ 199350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dnOne; /* work value 1... */ 199450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* local accumulator buffer [a decNumber, with digits+elength+1 digits] */ 199550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dacbuff[D2N(DECBUFFER+9)]; 199650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *dac=dacbuff; /* -> result accumulator */ 199750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* same again for possible 1/lhs calculation */ 199850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber invbuff[D2N(DECBUFFER+9)]; 199950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 200050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 200150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 200250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 200350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 200450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 200550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 200650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { /* reduce operands and set status, as needed */ 200750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>reqdigits) { 200850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloclhs=decRoundOperand(lhs, set, &status); 200950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs==NULL) break; 201050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=alloclhs; 201150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 201250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>reqdigits) { 201350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, &status); 201450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 201550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 201650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 201750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 201850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 201950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 202050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 202150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle NaNs and rhs Infinity (lhs infinity is harder) */ 202250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS) { 202350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { /* NaNs */ 202450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, &status); 202550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 202650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs)) { /* rhs Infinity */ 202750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag rhsneg=rhs->bits&DECNEG; /* save rhs sign */ 202850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(lhs) /* lhs<0 */ 202950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && !decNumberIsZero(lhs)) /* .. */ 203050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 203150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* lhs >=0 */ 203250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dnOne); /* set up 1 */ 203350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dnOne.lsu[0]=1; 203450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCompare(dac, lhs, &dnOne, set); /* lhs ? 1 */ 203550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* prepare for 0/1/Infinity */ 203650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dac)) { /* lhs<1 */ 203750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhsneg) res->bits|=DECINF; /* +Infinity [else is +0] */ 203850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 203950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (dac->lsu[0]==0) { /* lhs=1 */ 204050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1**Infinity is inexact, so return fully-padded 1.0000 */ 204150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift=set->digits-1; 204250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=1; /* was 0, make int 1 */ 204350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, 1, shift); 204450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=-shift; /* make 1.0000... */ 204550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Inexact|DEC_Rounded; /* deemed inexact */ 204650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 204750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* lhs>1 */ 204850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!rhsneg) res->bits|=DECINF; /* +Infinity [else is +0] */ 204950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 205050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* lhs>=0 */ 205150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 205250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [lhs infinity drops through] */ 205350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* specials */ 205450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 205550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Original rhs may be an integer that fits and is in range */ 205650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho n=decGetInt(rhs); 205750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n!=BADINT) { /* it is an integer */ 205850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhsint=1; /* record the fact for 1**n */ 205950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho isoddint=(Flag)n&1; /* [works even if big] */ 206050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n!=BIGEVEN && n!=BIGODD) /* can use integer path? */ 206150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho useint=1; /* looks good */ 206250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 206350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 206450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(lhs) /* -x .. */ 206550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && isoddint) bits=DECNEG; /* .. to an odd power */ 206650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 206750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle LHS infinity */ 206850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(lhs)) { /* [NaNs already handled] */ 206950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte rbits=rhs->bits; /* save */ 207050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* prepare */ 207150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n==0) *res->lsu=1; /* [-]Inf**0 => 1 */ 207250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 207350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* -Inf**nonint -> error */ 207450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!rhsint && decNumberIsNegative(lhs)) { 207550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; /* -Inf**nonint is error */ 207650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 207750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(rbits & DECNEG)) bits|=DECINF; /* was not a **-n */ 207850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [otherwise will be 0 or -0] */ 207950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; 208050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 208150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 208250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 208350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* similarly handle LHS zero */ 208450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(lhs)) { 208550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n==0) { /* 0**0 => Error */ 208650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 208750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { /* [unless subset] */ 208850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 208950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=1; /* return 1 */ 209050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 209150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 209250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 209350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 209450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* 0**x */ 209550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte rbits=rhs->bits; /* save */ 209650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rbits & DECNEG) { /* was a 0**(-n) */ 209750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 209850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { /* [bad if subset] */ 209950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 210050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 210150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 210250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits|=DECINF; 210350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 210450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* prepare */ 210550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [otherwise will be 0 or -0] */ 210650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; 210750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 210850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 210950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 211050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here both lhs and rhs are finite; rhs==0 is handled in the */ 211150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* integer path. Next handle the non-integer cases */ 211250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!useint) { /* non-integral rhs */ 211350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* any -ve lhs is bad, as is either operand or context out of */ 211450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* bounds */ 211550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(lhs)) { 211650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 211750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 211850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckMath(lhs, set, &status) 211950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || decCheckMath(rhs, set, &status)) break; /* variable status */ 212050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 212150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */ 212250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emax=DEC_MAX_MATH; /* usual bounds */ 212350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emin=-DEC_MAX_MATH; /* .. */ 212450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.clamp=0; /* and no concrete format */ 212550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 212650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the result using exp(ln(lhs)*rhs), which can */ 212750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* all be done into the accumulator, dac. The precision needed */ 212850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is enough to contain the full information in the lhs (which */ 212950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is the total digits, including exponent), or the requested */ 213050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* precision, if larger, + 4; 6 is used for the exponent */ 213150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* maximum length, and this is also used when it is shorter */ 213250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* than the requested digits as it greatly reduces the >0.5 ulp */ 213350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* cases at little cost (because Ln doubles digits each */ 213450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* iteration so a few extra digits rarely causes an extra */ 213550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* iteration) */ 213650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=MAXI(lhs->digits, set->digits)+6+4; 213750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* non-integer rhs */ 213850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 213950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* rhs is in-range integer */ 214050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n==0) { /* x**0 = 1 */ 214150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (0**0 was handled above) */ 214250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* result=1 */ 214350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=1; /* .. */ 214450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 214550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rhs is a non-zero integer */ 214650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n<0) n=-n; /* use abs(n) */ 214750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 214850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset=*set; /* clone the context */ 214950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.round=DEC_ROUND_HALF_EVEN; /* internally use balanced */ 215050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the working DIGITS */ 215150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=reqdigits+(rhs->digits+rhs->exponent)+2; 215250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 215350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) aset.digits--; /* use classic precision */ 215450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 215550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it's an error if this is more than can be handled */ 215650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (aset.digits>DECNUMMAXP) {status|=DEC_Invalid_operation; break;} 215750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* integer path */ 215850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 215950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* aset.digits is the count of digits for the accumulator needed */ 216050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if accumulator is too long for local storage, then allocate */ 216150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(aset.digits)-1)*sizeof(Unit); 216250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [needbytes also used below if 1/lhs needed] */ 216350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(dacbuff)) { 216450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocdac=(decNumber *)malloc(needbytes); 216550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocdac==NULL) { /* hopeless -- abandon */ 216650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 216750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 216850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dac=allocdac; /* use the allocated space */ 216950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 217050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here, aset is set up and accumulator is ready for use */ 217150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 217250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!useint) { /* non-integral rhs */ 217350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* x ** y; special-case x=1 here as it will otherwise always */ 217450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce to integer 1; decLnOp has a fastpath which detects */ 217550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the case of x=1 */ 217650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decLnOp(dac, lhs, &aset, &status); /* dac=ln(lhs) */ 217750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [no error possible, as lhs 0 already handled] */ 217850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(dac)) { /* x==1, 1.0, etc. */ 217950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* need to return fully-padded 1.0000 etc., but rhsint->1 */ 218050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *dac->lsu=1; /* was 0, make int 1 */ 218150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!rhsint) { /* add padding */ 218250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift=set->digits-1; 218350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dac->digits=decShiftToMost(dac->lsu, 1, shift); 218450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dac->exponent=-shift; /* make 1.0000... */ 218550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Inexact|DEC_Rounded; /* deemed inexact */ 218650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 218750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 218850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 218950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(dac, dac, rhs, &aset, &status); /* dac=dac*rhs */ 219050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decExpOp(dac, dac, &aset, &status); /* dac=exp(dac) */ 219150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 219250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* and drop through for final rounding */ 219350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* non-integer rhs */ 219450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 219550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* carry on with integer */ 219650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(dac); /* acc=1 */ 219750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *dac->lsu=1; /* .. */ 219850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 219950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if a negative power the constant 1 is needed, and if not subset */ 220050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* invert the lhs now rather than inverting the result later */ 220150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) { /* was a **-n [hence digits>0] */ 220250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *inv=invbuff; /* asssume use fixed buffer */ 220350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(&dnOne, dac); /* dnOne=1; [needed now or later] */ 220450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 220550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->extended) { /* need to calculate 1/lhs */ 220650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 220750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* divide lhs into 1, putting result in dac [dac=1/dac] */ 220850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(dac, &dnOne, lhs, &aset, DIVIDE, &status); 220950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now locate or allocate space for the inverted lhs */ 221050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(invbuff)) { 221150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocinv=(decNumber *)malloc(needbytes); 221250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocinv==NULL) { /* hopeless -- abandon */ 221350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 221450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 221550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho inv=allocinv; /* use the allocated space */ 221650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 221750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [inv now points to big-enough buffer or allocated storage] */ 221850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(inv, dac); /* copy the 1/lhs */ 221950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(dac, &dnOne); /* restore acc=1 */ 222050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=inv; /* .. and go forward with new lhs */ 222150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 222250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 222350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 222450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 222550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 222650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Raise-to-the-power loop... */ 222750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho seenbit=0; /* set once a 1-bit is encountered */ 222850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i=1;;i++){ /* for each bit [top bit ignored] */ 222950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* abandon if had overflow or terminal underflow */ 223050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */ 223150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status&DEC_Overflow || ISZERO(dac)) break; 223250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 223350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [the following two lines revealed an optimizer bug in a C++ */ 223450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* compiler, with symptom: 5**3 -> 25, when n=n+n was used] */ 223550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho n=n<<1; /* move next bit to testable position */ 223650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n<0) { /* top bit is set */ 223750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho seenbit=1; /* OK, significant bit seen */ 223850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(dac, dac, lhs, &aset, &status); /* dac=dac*x */ 223950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 224050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (i==31) break; /* that was the last bit */ 224150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!seenbit) continue; /* no need to square 1 */ 224250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(dac, dac, dac, &aset, &status); /* dac=dac*dac [square] */ 224350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /*i*/ /* 32 bits */ 224450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 224550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* complete internal overflow or underflow processing */ 224650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status & (DEC_Overflow|DEC_Underflow)) { 224750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 224850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If subset, and power was negative, reverse the kind of -erflow */ 224950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [1/x not yet done] */ 225050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended && decNumberIsNegative(rhs)) { 225150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status & DEC_Overflow) 225250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status^=DEC_Overflow | DEC_Underflow | DEC_Subnormal; 225350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* trickier -- Underflow may or may not be set */ 225450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status&=~(DEC_Underflow | DEC_Subnormal); /* [one or both] */ 225550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Overflow; 225650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 225750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 225850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 225950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dac->bits=(dac->bits & ~DECNEG) | bits; /* force correct sign */ 226050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* round subnormals [to set.digits rather than aset.digits] */ 226150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* or set overflow result similarly as required */ 226250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinalize(dac, set, &residue, &status); 226350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, dac); /* copy to result (is now OK length) */ 226450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 226550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 226650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 226750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 226850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended && /* subset math */ 226950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumberIsNegative(rhs)) { /* was a **-n [hence digits>0] */ 227050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* so divide result into 1 [dac=1/dac] */ 227150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(dac, &dnOne, dac, &aset, DIVIDE, &status); 227250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 227350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 227450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* rhs integer path */ 227550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 227650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce result to the requested length and copy to result */ 227750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, dac, set, &residue, &status); 227850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, &status); /* final cleanup */ 227950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 228050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) decTrim(res, set, 0, 1, &dropped); /* trailing zeros */ 228150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 228250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 228350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 228450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocdac!=NULL) free(allocdac); /* drop any storage used */ 228550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocinv!=NULL) free(allocinv); /* .. */ 228650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 228750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs!=NULL) free(alloclhs); /* .. */ 228850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs!=NULL) free(allocrhs); /* .. */ 228950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 229050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 229150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 229250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 229350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 229450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 229550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberPower */ 229650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 229750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 229850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberQuantize -- force exponent to requested value */ 229950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 230050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = op(A, B), where op adjusts the coefficient */ 230150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of C (by rounding or shifting) such that the exponent (-scale) */ 230250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of C has exponent of B. The numerical value of C will equal A, */ 230350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* except for the effects of any rounding that occurred. */ 230450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 230550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A or B */ 230650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A, the number to adjust */ 230750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B, the number with exponent to match */ 230850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 230950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 231050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 231150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 231250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Unless there is an error or the result is infinite, the exponent */ 231350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* after the operation is guaranteed to be equal to that of B. */ 231450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 231550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberQuantize(decNumber *res, const decNumber *lhs, 231650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 231750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 231850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decQuantizeOp(res, lhs, rhs, set, 1, &status); 231950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 232050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 232150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberQuantize */ 232250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 232350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 232450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberReduce -- remove trailing zeros */ 232550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 232650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = 0 + A, and normalizes the result */ 232750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 232850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 232950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 233050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 233150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 233250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 233350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 233450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Previously known as Normalize */ 233550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberNormalize(decNumber *res, const decNumber *rhs, 233650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 233750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return uprv_decNumberReduce(res, rhs, set); 233850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberNormalize */ 233950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 234050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberReduce(decNumber *res, const decNumber *rhs, 234150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 234250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 234350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */ 234450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 234550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* as usual */ 234650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* as usual */ 234750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int dropped; /* work */ 234850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 234950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 235050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 235150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 235250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 235350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 235450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 235550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 235650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operand and set lostDigits status, as needed */ 235750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>set->digits) { 235850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, &status); 235950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 236050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 236150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 236250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 236350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 236450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 236550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 236650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Infinities copy through; NaNs need usual treatment */ 236750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(rhs)) { 236850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, rhs, NULL, set, &status); 236950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 237050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 237150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 237250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce result to the requested length and copy to result */ 237350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, rhs, set, &residue, &status); /* copy & round */ 237450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, &status); /* cleanup/set flags */ 237550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decTrim(res, set, 1, 0, &dropped); /* normalize in place */ 237650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [may clamp] */ 237750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 237850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 237950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 238050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs !=NULL) free(allocrhs); /* .. */ 238150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 238250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set);/* then report status */ 238350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 238450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberReduce */ 238550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 238650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 238750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberRescale -- force exponent to requested value */ 238850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 238950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = op(A, B), where op adjusts the coefficient */ 239050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of C (by rounding or shifting) such that the exponent (-scale) */ 239150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of C has the value B. The numerical value of C will equal A, */ 239250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* except for the effects of any rounding that occurred. */ 239350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 239450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A or B */ 239550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A, the number to adjust */ 239650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B, the requested exponent */ 239750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 239850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 239950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 240050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 240150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Unless there is an error or the result is infinite, the exponent */ 240250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* after the operation is guaranteed to be equal to B. */ 240350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 240450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberRescale(decNumber *res, const decNumber *lhs, 240550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 240650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 240750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decQuantizeOp(res, lhs, rhs, set, 0, &status); 240850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 240950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 241050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberRescale */ 241150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 241250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 241350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberRemainder -- divide and return remainder */ 241450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 241550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A % B */ 241650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 241750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X%X) */ 241850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 241950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 242050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 242150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 242250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 242350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 242450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberRemainder(decNumber *res, const decNumber *lhs, 242550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 242650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 242750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(res, lhs, rhs, set, REMAINDER, &status); 242850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 242950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 243050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 243150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 243250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 243350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberRemainder */ 243450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 243550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 243650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberRemainderNear -- divide and return remainder from nearest */ 243750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 243850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A % B, where % is the IEEE remainder operator */ 243950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 244050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X%X) */ 244150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 244250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 244350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 244450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 244550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 244650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 244750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberRemainderNear(decNumber *res, const decNumber *lhs, 244850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 244950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 245050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(res, lhs, rhs, set, REMNEAR, &status); 245150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 245250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 245350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 245450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 245550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 245650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberRemainderNear */ 245750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 245850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 245950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberRotate -- rotate the coefficient of a Number left/right */ 246050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 246150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A rot B (in base ten and rotating set->digits */ 246250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* digits). */ 246350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 246450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=XrotX) */ 246550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 246650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B, the number of digits to rotate (-ve to right) */ 246750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 246850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 246950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The digits of the coefficient of A are rotated to the left (if B */ 247050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* is positive) or to the right (if B is negative) without adjusting */ 247150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the exponent or the sign of A. If lhs->digits is less than */ 247250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set->digits the coefficient is padded with zeros on the left */ 247350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* before the rotate. Any leading zeros in the result are removed */ 247450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* as usual. */ 247550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 247650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* B must be an integer (q=0) and in the range -set->digits through */ 247750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* +set->digits. */ 247850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 247950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* NaNs are propagated as usual. Infinities are unaffected (but */ 248050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* B must be valid). No status is set unless B is invalid or an */ 248150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* operand is an sNaN. */ 248250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 248350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberRotate(decNumber *res, const decNumber *lhs, 248450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 248550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 248650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int rotate; /* rhs as an Int */ 248750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 248850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 248950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 249050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 249150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 249250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* NaNs propagate as normal */ 249350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) 249450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, &status); 249550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rhs must be an integer */ 249650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsInfinite(rhs) || rhs->exponent!=0) 249750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Invalid_operation; 249850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* both numeric, rhs is an integer */ 249950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rotate=decGetInt(rhs); /* [cannot fail] */ 250050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rotate==BADINT /* something bad .. */ 250150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || rotate==BIGODD || rotate==BIGEVEN /* .. very big .. */ 250250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || abs(rotate)>set->digits) /* .. or out of range */ 250350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Invalid_operation; 250450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* rhs is OK */ 250550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); 250650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* convert -ve rotate to equivalent positive rotation */ 250750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rotate<0) rotate=set->digits+rotate; 250850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rotate!=0 && rotate!=set->digits /* zero or full rotation */ 250950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && !decNumberIsInfinite(res)) { /* lhs was infinite */ 251050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* left-rotate to do; 0 < rotate < set->digits */ 251150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt units, shift; /* work */ 251250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt msudigits; /* digits in result msu */ 251350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *msu=res->lsu+D2U(res->digits)-1; /* current msu */ 251450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *msumax=res->lsu+D2U(set->digits)-1; /* rotation msu */ 251550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (msu++; msu<=msumax; msu++) *msu=0; /* ensure high units=0 */ 251650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=set->digits; /* now full-length */ 251750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msudigits=MSUDIGITS(res->digits); /* actual digits in msu */ 251850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 251950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rotation here is done in-place, in three steps */ 252050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1. shift all to least up to one unit to unit-align final */ 252150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lsd [any digits shifted out are rotated to the left, */ 252250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* abutted to the original msd (which may require split)] */ 252350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 252450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [if there are no whole units left to rotate, the */ 252550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rotation is now complete] */ 252650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 252750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 2. shift to least, from below the split point only, so that */ 252850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the final msd is in the right place in its Unit [any */ 252950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* digits shifted out will fit exactly in the current msu, */ 253050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* left aligned, no split required] */ 253150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 253250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 3. rotate all the units by reversing left part, right */ 253350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* part, and then whole */ 253450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 253550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* example: rotate right 8 digits (2 units + 2), DECDPUN=3. */ 253650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 253750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* start: 00a bcd efg hij klm npq */ 253850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 253950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1a 000 0ab cde fgh|ijk lmn [pq saved] */ 254050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1b 00p qab cde fgh|ijk lmn */ 254150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 254250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 2a 00p qab cde fgh|00i jkl [mn saved] */ 254350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 2b mnp qab cde fgh|00i jkl */ 254450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 254550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 3a fgh cde qab mnp|00i jkl */ 254650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 3b fgh cde qab mnp|jkl 00i */ 254750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 3c 00i jkl mnp qab cde fgh */ 254850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 254950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Step 1: amount to shift is the partial right-rotate count */ 255050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rotate=set->digits-rotate; /* make it right-rotate */ 255150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho units=rotate/DECDPUN; /* whole units to rotate */ 255250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho shift=rotate%DECDPUN; /* left-over digits count */ 255350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift>0) { /* not an exact number of units */ 255450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt save=res->lsu[0]%powers[shift]; /* save low digit(s) */ 255550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decShiftToLeast(res->lsu, D2U(res->digits), shift); 255650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift>msudigits) { /* msumax-1 needs >0 digits */ 255750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt rem=save%powers[shift-msudigits];/* split save */ 255850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *msumax=(Unit)(save/powers[shift-msudigits]); /* and insert */ 255950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *(msumax-1)=*(msumax-1) 256050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho +(Unit)(rem*powers[DECDPUN-(shift-msudigits)]); /* .. */ 256150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 256250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* all fits in msumax */ 256350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *msumax=*msumax+(Unit)(save*powers[msudigits-shift]); /* [maybe *1] */ 256450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 256550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* digits shift needed */ 256650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 256750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If whole units to rotate... */ 256850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (units>0) { /* some to do */ 256950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Step 2: the units to touch are the whole ones in rotate, */ 257050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if any, and the shift is DECDPUN-msudigits (which may be */ 257150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 0, again) */ 257250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho shift=DECDPUN-msudigits; 257350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift>0) { /* not an exact number of units */ 257450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt save=res->lsu[0]%powers[shift]; /* save low digit(s) */ 257550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decShiftToLeast(res->lsu, units, shift); 257650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *msumax=*msumax+(Unit)(save*powers[msudigits]); 257750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* partial shift needed */ 257850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 257950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Step 3: rotate the units array using triple reverse */ 258050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (reversing is easy and fast) */ 258150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decReverse(res->lsu+units, msumax); /* left part */ 258250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decReverse(res->lsu, res->lsu+units-1); /* right part */ 258350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decReverse(res->lsu, msumax); /* whole */ 258450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* whole units to rotate */ 258550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the rotation may have left an undetermined number of zeros */ 258650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* on the left, so true length needs to be calculated */ 258750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(res->lsu, msumax-res->lsu+1); 258850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* rotate needed */ 258950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* rhs OK */ 259050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* numerics */ 259150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 259250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 259350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberRotate */ 259450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 259550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 259650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberSameQuantum -- test for equal exponents */ 259750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 259850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is the result number, which will contain either 0 or 1 */ 259950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is a number to test */ 260050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is the second (usually a pattern) */ 260150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 260250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No errors are possible and no context is needed. */ 260350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 260450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberSameQuantum(decNumber *res, const decNumber *lhs, 260550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs) { 260650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit ret=0; /* return value */ 260750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 260850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 260950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, DECUNCONT)) return res; 261050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 261150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 261250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS) { 261350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(lhs) && decNumberIsNaN(rhs)) ret=1; 261450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsInfinite(lhs) && decNumberIsInfinite(rhs)) ret=1; 261550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [anything else with a special gives 0] */ 261650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 261750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (lhs->exponent==rhs->exponent) ret=1; 261850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 261950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* OK to overwrite an operand now */ 262050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=ret; 262150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 262250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberSameQuantum */ 262350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 262450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 262550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberScaleB -- multiply by a power of 10 */ 262650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 262750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A x 10**B where B is an integer (q=0) with */ 262850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* maximum magnitude 2*(emax+digits) */ 262950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 263050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A or B */ 263150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A, the number to adjust */ 263250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B, the requested power of ten to use */ 263350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 263450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 263550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 263650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 263750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The result may underflow or overflow. */ 263850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 263950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberScaleB(decNumber *res, const decNumber *lhs, 264050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 264150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int reqexp; /* requested exponent change [B] */ 264250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 264350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue; /* work */ 264450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 264550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 264650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 264750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 264850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 264950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Handle special values except lhs infinite */ 265050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) 265150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, &status); 265250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rhs must be an integer */ 265350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsInfinite(rhs) || rhs->exponent!=0) 265450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Invalid_operation; 265550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 265650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lhs is a number; rhs is a finite with q==0 */ 265750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho reqexp=decGetInt(rhs); /* [cannot fail] */ 265850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (reqexp==BADINT /* something bad .. */ 265950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || reqexp==BIGODD || reqexp==BIGEVEN /* .. very big .. */ 266050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || abs(reqexp)>(2*(set->digits+set->emax))) /* .. or out of range */ 266150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Invalid_operation; 266250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* rhs is OK */ 266350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); /* all done if infinite lhs */ 266450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!decNumberIsInfinite(res)) { /* prepare to scale */ 266550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent+=reqexp; /* adjust the exponent */ 266650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; 266750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinalize(res, set, &residue, &status); /* .. and check */ 266850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* finite LHS */ 266950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* rhs OK */ 267050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* rhs finite */ 267150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 267250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 267350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberScaleB */ 267450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 267550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 267650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberShift -- shift the coefficient of a Number left or right */ 267750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 267850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A << B or C = A >> -B (in base ten). */ 267950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 268050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X<<X) */ 268150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 268250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B, the number of digits to shift (-ve to right) */ 268350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 268450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 268550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The digits of the coefficient of A are shifted to the left (if B */ 268650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* is positive) or to the right (if B is negative) without adjusting */ 268750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the exponent or the sign of A. */ 268850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 268950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* B must be an integer (q=0) and in the range -set->digits through */ 269050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* +set->digits. */ 269150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 269250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* NaNs are propagated as usual. Infinities are unaffected (but */ 269350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* B must be valid). No status is set unless B is invalid or an */ 269450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* operand is an sNaN. */ 269550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 269650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberShift(decNumber *res, const decNumber *lhs, 269750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 269850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 269950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift; /* rhs as an Int */ 270050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 270150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 270250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 270350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 270450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 270550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* NaNs propagate as normal */ 270650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) 270750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, &status); 270850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rhs must be an integer */ 270950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsInfinite(rhs) || rhs->exponent!=0) 271050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Invalid_operation; 271150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* both numeric, rhs is an integer */ 271250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho shift=decGetInt(rhs); /* [cannot fail] */ 271350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift==BADINT /* something bad .. */ 271450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || shift==BIGODD || shift==BIGEVEN /* .. very big .. */ 271550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || abs(shift)>set->digits) /* .. or out of range */ 271650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Invalid_operation; 271750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* rhs is OK */ 271850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); 271950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift!=0 && !decNumberIsInfinite(res)) { /* something to do */ 272050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift>0) { /* to left */ 272150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift==set->digits) { /* removing all */ 272250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=0; /* so place 0 */ 272350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=1; /* .. */ 272450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 272550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* */ 272650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* first remove leading digits if necessary */ 272750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits+shift>set->digits) { 272850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDecap(res, res->digits+shift-set->digits); 272950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* that updated res->digits; may have gone to 1 (for a */ 273050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* single digit or for zero */ 273150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 273250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits>1 || *res->lsu) /* if non-zero.. */ 273350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, res->digits, shift); 273450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* partial left */ 273550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* left */ 273650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* to right */ 273750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (-shift>=res->digits) { /* discarding all */ 273850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=0; /* so place 0 */ 273950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=1; /* .. */ 274050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 274150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 274250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decShiftToLeast(res->lsu, D2U(res->digits), -shift); 274350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits-=(-shift); 274450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 274550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* to right */ 274650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* non-0 non-Inf shift */ 274750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* rhs OK */ 274850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* numerics */ 274950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 275050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 275150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberShift */ 275250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 275350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 275450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberSquareRoot -- square root operator */ 275550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 275650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = squareroot(A) */ 275750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 275850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 275950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 276050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context; note that rounding mode has no effect */ 276150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 276250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 276350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 276450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This uses the following varying-precision algorithm in: */ 276550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 276650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Properly Rounded Variable Precision Square Root, T. E. Hull and */ 276750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A. Abrham, ACM Transactions on Mathematical Software, Vol 11 #3, */ 276850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* pp229-237, ACM, September 1985. */ 276950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 277050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The square-root is calculated using Newton's method, after which */ 277150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* a check is made to ensure the result is correctly rounded. */ 277250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 277350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % [Reformatted original Numerical Turing source code follows.] */ 277450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* function sqrt(x : real) : real */ 277550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % sqrt(x) returns the properly rounded approximation to the square */ 277650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % root of x, in the precision of the calling environment, or it */ 277750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % fails if x < 0. */ 277850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % t e hull and a abrham, august, 1984 */ 277950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if x <= 0 then */ 278050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if x < 0 then */ 278150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* assert false */ 278250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* else */ 278350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* result 0 */ 278450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end if */ 278550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end if */ 278650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* var f := setexp(x, 0) % fraction part of x [0.1 <= x < 1] */ 278750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* var e := getexp(x) % exponent part of x */ 278850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* var approx : real */ 278950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if e mod 2 = 0 then */ 279050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* approx := .259 + .819 * f % approx to root of f */ 279150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* else */ 279250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* f := f/l0 % adjustments */ 279350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* e := e + 1 % for odd */ 279450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* approx := .0819 + 2.59 * f % exponent */ 279550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end if */ 279650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 279750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* var p:= 3 */ 279850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* const maxp := currentprecision + 2 */ 279950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* loop */ 280050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* p := min(2*p - 2, maxp) % p = 4,6,10, . . . , maxp */ 280150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* precision p */ 280250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* approx := .5 * (approx + f/approx) */ 280350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* exit when p = maxp */ 280450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end loop */ 280550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 280650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % approx is now within 1 ulp of the properly rounded square root */ 280750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % of f; to ensure proper rounding, compare squares of (approx - */ 280850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % l/2 ulp) and (approx + l/2 ulp) with f. */ 280950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* p := currentprecision */ 281050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* begin */ 281150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* precision p + 2 */ 281250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* const approxsubhalf := approx - setexp(.5, -p) */ 281350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if mulru(approxsubhalf, approxsubhalf) > f then */ 281450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* approx := approx - setexp(.l, -p + 1) */ 281550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* else */ 281650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* const approxaddhalf := approx + setexp(.5, -p) */ 281750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if mulrd(approxaddhalf, approxaddhalf) < f then */ 281850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* approx := approx + setexp(.l, -p + 1) */ 281950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end if */ 282050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end if */ 282150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end */ 282250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* result setexp(approx, e div 2) % fix exponent */ 282350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end sqrt */ 282450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 282554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406 282602c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic push 282702c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic ignored "-Warray-bounds" 282802c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#endif 282950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberSquareRoot(decNumber *res, const decNumber *rhs, 283050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 283150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset, approxset; /* work contexts */ 283250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dzero; /* used for constant zero */ 283350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxp; /* largest working precision */ 283450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int workp; /* working precision */ 283550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* rounding residue */ 283650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0, ignore=0; /* status accumulators */ 283750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt rstatus; /* .. */ 283850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int exp; /* working exponent */ 283950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ideal; /* ideal (preferred) exponent */ 284050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int needbytes; /* work */ 284150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int dropped; /* .. */ 284250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 284350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 284450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */ 284550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 284650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffer for f [needs +1 in case DECBUFFER 0] */ 284750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber buff[D2N(DECBUFFER+1)]; 284850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffer for a [needs +2 to match likely maxp] */ 284950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufa[D2N(DECBUFFER+2)]; 285050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffer for temporary, b [must be same size as a] */ 285150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufb[D2N(DECBUFFER+2)]; 285250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbuff=NULL; /* -> allocated buff, iff allocated */ 285350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ 285450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufb=NULL; /* -> allocated bufb, iff allocated */ 285550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *f=buff; /* reduced fraction */ 285650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *a=bufa; /* approximation to result */ 285750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *b=bufb; /* intermediate result */ 285850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffer for temporary variable, up to 3 digits */ 285950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber buft[D2N(3)]; 286050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *t=buft; /* up-to-3-digit constant or work */ 286150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 286250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 286350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 286450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 286550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 286650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 286750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 286850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 286950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operand and set lostDigits status, as needed */ 287050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>set->digits) { 287150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, &status); 287250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 287350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [Note: 'f' allocation below could reuse this buffer if */ 287450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* used, but as this is rare they are kept separate for clarity.] */ 287550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 287650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 287750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 287850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 287950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 288050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 288150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle infinities and NaNs */ 288250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARG) { 288350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs)) { /* an infinity */ 288450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) status|=DEC_Invalid_operation; 288550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else uprv_decNumberCopy(res, rhs); /* +Infinity */ 288650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 288750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else decNaNs(res, rhs, NULL, set, &status); /* a NaN */ 288850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 288950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 289050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 289150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the ideal (preferred) exponent [floor(exp/2)] */ 289250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [It would be nicer to write: ideal=rhs->exponent>>1, but this */ 289350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* generates a compiler warning. Generated code is the same.] */ 289450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ideal=(rhs->exponent&~1)/2; /* target */ 289550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 289650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle zeros */ 289750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) { 289850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, rhs); /* could be 0 or -0 */ 289950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=ideal; /* use the ideal [safe] */ 290050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* use decFinish to clamp any out-of-range exponent, etc. */ 290150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, &status); 290250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 290350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 290450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 290550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* any other -x is an oops */ 290650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) { 290750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 290850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 290950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 291050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 291150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* space is needed for three working variables */ 291250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* f -- the same precision as the RHS, reduced to 0.01->0.99... */ 291350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a -- Hull's approximation -- precision, when assigned, is */ 291450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* currentprecision+1 or the input argument precision, */ 291550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* whichever is larger (+2 for use as temporary) */ 291650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* b -- intermediate temporary result (same size as a) */ 291750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if any is too long for local storage, then allocate */ 291850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workp=MAXI(set->digits+1, rhs->digits); /* actual rounding precision */ 291950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workp=MAXI(workp, 7); /* at least 7 for low cases */ 292050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxp=workp+2; /* largest working precision */ 292150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 292250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit); 292350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>(Int)sizeof(buff)) { 292450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbuff=(decNumber *)malloc(needbytes); 292550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbuff==NULL) { /* hopeless -- abandon */ 292650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 292750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 292850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho f=allocbuff; /* use the allocated space */ 292950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 293050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a and b both need to be able to hold a maxp-length number */ 293150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(maxp)-1)*sizeof(Unit); 293250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>(Int)sizeof(bufa)) { /* [same applies to b] */ 293350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufa=(decNumber *)malloc(needbytes); 293450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufb=(decNumber *)malloc(needbytes); 293550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa==NULL || allocbufb==NULL) { /* hopeless */ 293650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 293750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 293850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=allocbufa; /* use the allocated spaces */ 293950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=allocbufb; /* .. */ 294050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 294150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 294250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* copy rhs -> f, save exponent, and reduce so 0.1 <= f < 1 */ 294350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(f, rhs); 294450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exp=f->exponent+f->digits; /* adjusted to Hull rules */ 294550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho f->exponent=-(f->digits); /* to range */ 294650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 294750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set up working context */ 294850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&workset, DEC_INIT_DECIMAL64); 294950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.emax=DEC_MAX_EMAX; 295050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.emin=DEC_MIN_EMIN; 295150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 295250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [Until further notice, no error is possible and status bits */ 295350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (Rounded, etc.) should be ignored, not accumulated.] */ 295450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 295550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Calculate initial approximation, and allow for odd exponent */ 295650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.digits=workp; /* p for initial calculation */ 295750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->bits=0; t->digits=3; 295850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->bits=0; a->digits=3; 295950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((exp & 1)==0) { /* even exponent */ 296050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Set t=0.259, a=0.819 */ 296150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->exponent=-3; 296250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->exponent=-3; 296350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>=3 296450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=259; 296550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->lsu[0]=819; 296650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==2 296750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=59; t->lsu[1]=2; 296850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->lsu[0]=19; a->lsu[1]=8; 296950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 297050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=9; t->lsu[1]=5; t->lsu[2]=2; 297150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->lsu[0]=9; a->lsu[1]=1; a->lsu[2]=8; 297250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 297350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 297450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* odd exponent */ 297550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Set t=0.0819, a=2.59 */ 297650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho f->exponent--; /* f=f/10 */ 297750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exp++; /* e=e+1 */ 297850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->exponent=-4; 297950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->exponent=-2; 298050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>=3 298150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=819; 298250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->lsu[0]=259; 298350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==2 298450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=19; t->lsu[1]=8; 298550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->lsu[0]=59; a->lsu[1]=2; 298650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 298750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=9; t->lsu[1]=1; t->lsu[2]=8; 298850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->lsu[0]=9; a->lsu[1]=5; a->lsu[2]=2; 298950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 299050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 299150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 299250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(a, a, f, &workset, &ignore); /* a=a*f */ 299350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, a, t, &workset, 0, &ignore); /* ..+t */ 299450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [a is now the initial approximation for sqrt(f), calculated with */ 299550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* currentprecision, which is also a's precision.] */ 299650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 299750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the main calculation loop */ 299850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dzero); /* make 0 */ 299950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(t); /* set t = 0.5 */ 300050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=5; /* .. */ 300150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->exponent=-1; /* .. */ 300250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.digits=3; /* initial p */ 300350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; workset.digits<maxp;) { 300450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set p to min(2*p - 2, maxp) [hence 3; or: 4, 6, 10, ... , maxp] */ 300550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.digits=MINI(workset.digits*2-2, maxp); 300650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a = 0.5 * (a + f/a) */ 300750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [calculated at p then rounded to currentprecision] */ 300850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(b, f, a, &workset, DIVIDE, &ignore); /* b=f/a */ 300950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(b, b, a, &workset, 0, &ignore); /* b=b+a */ 301050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(a, b, t, &workset, &ignore); /* a=b*0.5 */ 301150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* loop */ 301250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 301350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Here, 0.1 <= a < 1 [Hull], and a has maxp digits */ 301450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now reduce to length, etc.; this needs to be done with a */ 301550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* having the correct exponent so as to handle subnormals */ 301650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* correctly */ 301750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho approxset=*set; /* get emin, emax, etc. */ 301850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho approxset.round=DEC_ROUND_HALF_EVEN; 301950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->exponent+=exp/2; /* set correct exponent */ 302050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rstatus=0; /* clear status */ 302150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* .. and accumulator */ 302250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(a, a, &approxset, &residue, &rstatus); /* reduce (if needed) */ 302350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(a, &approxset, &residue, &rstatus); /* clean and finalize */ 302450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 302550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Overflow was possible if the input exponent was out-of-range, */ 302650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* in which case quit */ 302750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rstatus&DEC_Overflow) { 302850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=rstatus; /* use the status as-is */ 302950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, a); /* copy to result */ 303050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 303150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 303250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 303350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Preserve status except Inexact/Rounded */ 303450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=(rstatus & ~(DEC_Rounded|DEC_Inexact)); 303550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 303650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Carry out the Hull correction */ 303750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->exponent-=exp/2; /* back to 0.1->1 */ 303850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 303950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a is now at final precision and within 1 ulp of the properly */ 304050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rounded square root of f; to ensure proper rounding, compare */ 304150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* squares of (a - l/2 ulp) and (a + l/2 ulp) with f. */ 304250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Here workset.digits=maxp and t=0.5, and a->digits determines */ 304350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the ulp */ 304450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.digits--; /* maxp-1 is OK now */ 304550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->exponent=-a->digits-1; /* make 0.5 ulp */ 304650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(b, a, t, &workset, DECNEG, &ignore); /* b = a - 0.5 ulp */ 304750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.round=DEC_ROUND_UP; 304850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(b, b, b, &workset, &ignore); /* b = mulru(b, b) */ 304950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(b, f, b, &workset, COMPARE, &ignore); /* b ? f, reversed */ 305050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(b)) { /* f < b [i.e., b > f] */ 305150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this is the more common adjustment, though both are rare */ 305250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->exponent++; /* make 1.0 ulp */ 305350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=1; /* .. */ 305450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, a, t, &workset, DECNEG, &ignore); /* a = a - 1 ulp */ 305550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* assign to approx [round to length] */ 305650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho approxset.emin-=exp/2; /* adjust to match a */ 305750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho approxset.emax-=exp/2; 305850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, &dzero, a, &approxset, 0, &ignore); 305950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 306050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 306150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(b, a, t, &workset, 0, &ignore); /* b = a + 0.5 ulp */ 306250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.round=DEC_ROUND_DOWN; 306350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(b, b, b, &workset, &ignore); /* b = mulrd(b, b) */ 306450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(b, b, f, &workset, COMPARE, &ignore); /* b ? f */ 306550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(b)) { /* b < f */ 306650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->exponent++; /* make 1.0 ulp */ 306750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=1; /* .. */ 306850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, a, t, &workset, 0, &ignore); /* a = a + 1 ulp */ 306950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* assign to approx [round to length] */ 307050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho approxset.emin-=exp/2; /* adjust to match a */ 307150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho approxset.emax-=exp/2; 307250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, &dzero, a, &approxset, 0, &ignore); 307350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 307450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 307550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [no errors are possible in the above, and rounding/inexact during */ 307650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* estimation are irrelevant, so status was not accumulated] */ 307750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 307850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Here, 0.1 <= a < 1 (still), so adjust back */ 307950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->exponent+=exp/2; /* set correct exponent */ 308050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 308150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* count droppable zeros [after any subnormal rounding] by */ 308250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* trimming a copy */ 308350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(b, a); 308450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decTrim(b, set, 1, 1, &dropped); /* [drops trailing zeros] */ 308550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 308650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Set Inexact and Rounded. The answer can only be exact if */ 308750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it is short enough so that squaring it could fit in workp */ 308850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* digits, so this is the only (relatively rare) condition that */ 308950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a careful check is needed */ 309050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (b->digits*2-1 > workp) { /* cannot fit */ 309150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Inexact|DEC_Rounded; 309250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 309350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* could be exact/unrounded */ 309450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt mstatus=0; /* local status */ 309550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(b, b, b, &workset, &mstatus); /* try the multiply */ 309650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mstatus&DEC_Overflow) { /* result just won't fit */ 309750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Inexact|DEC_Rounded; 309850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 309950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* plausible */ 310050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(t, b, rhs, &workset, COMPARE, &mstatus); /* b ? rhs */ 310150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!ISZERO(t)) status|=DEC_Inexact|DEC_Rounded; /* not equal */ 310250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* is Exact */ 310350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here, dropped is the count of trailing zeros in 'a' */ 310450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* use closest exponent to ideal... */ 310550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int todrop=ideal-a->exponent; /* most that can be dropped */ 310650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (todrop<0) status|=DEC_Rounded; /* ideally would add 0s */ 310750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* unrounded */ 310850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* there are some to drop, but emax may not allow all */ 310950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxexp=set->emax-set->digits+1; 311050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxdrop=maxexp-a->exponent; 311150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (todrop>maxdrop && set->clamp) { /* apply clamping */ 311250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho todrop=maxdrop; 311350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Clamped; 311450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 311550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dropped<todrop) { /* clamp to those available */ 311650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho todrop=dropped; 311750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Clamped; 311850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 311950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (todrop>0) { /* have some to drop */ 312050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decShiftToLeast(a->lsu, D2U(a->digits), todrop); 312150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->exponent+=todrop; /* maintain numerical value */ 312250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->digits-=todrop; /* new length */ 312350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 312450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 312550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 312650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 312750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 312850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 312950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* double-check Underflow, as perhaps the result could not have */ 313050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* been subnormal (initial argument too big), or it is now Exact */ 313150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status&DEC_Underflow) { 313250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ae=rhs->exponent+rhs->digits-1; /* adjusted exponent */ 313350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* check if truly subnormal */ 313450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECEXTFLAG /* DEC_Subnormal too */ 313550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ae>=set->emin*2) status&=~(DEC_Subnormal|DEC_Underflow); 313650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 313750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ae>=set->emin*2) status&=~DEC_Underflow; 313850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 313950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* check if truly inexact */ 314050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(status&DEC_Inexact)) status&=~DEC_Underflow; 314150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 314250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 314350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, a); /* a is now the result */ 314450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 314550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 314650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbuff!=NULL) free(allocbuff); /* drop any storage used */ 314750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa!=NULL) free(allocbufa); /* .. */ 314850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufb!=NULL) free(allocbufb); /* .. */ 314950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 315050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs !=NULL) free(allocrhs); /* .. */ 315150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 315250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set);/* then report status */ 315350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 315450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 315550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 315650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 315750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberSquareRoot */ 315854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406 315902c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic pop 316002c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#endif 316150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 316250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 316350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberSubtract -- subtract two Numbers */ 316450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 316550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A - B */ 316650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 316750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X-X) */ 316850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 316950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 317050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 317150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 317250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 317350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 317450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberSubtract(decNumber *res, const decNumber *lhs, 317550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 317650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 317750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 317850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, lhs, rhs, set, DECNEG, &status); 317950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 318050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 318150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 318250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 318350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 318450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberSubtract */ 318550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 318650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 318750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberToIntegralExact -- round-to-integral-value with InExact */ 318850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberToIntegralValue -- round-to-integral-value */ 318950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 319050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is the result */ 319150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is input number */ 319250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 319350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 319450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res must have space for any value of rhs. */ 319550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 319650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This implements the IEEE special operators and therefore treats */ 319750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* special values as valid. For finite numbers it returns */ 319850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rescale(rhs, 0) if rhs->exponent is <0. */ 319950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Otherwise the result is rhs (so no error is possible, except for */ 320050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* sNaN). */ 320150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 320250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The context is used for rounding mode and status after sNaN, but */ 320350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the digits setting is ignored. The Exact version will signal */ 320450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Inexact if the result differs numerically from rhs; the other */ 320550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* never signals Inexact. */ 320650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 320750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberToIntegralExact(decNumber *res, const decNumber *rhs, 320850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 320950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dn; 321050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset; /* working context */ 321150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 321250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 321350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 321450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 321550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 321650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 321750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle infinities and NaNs */ 321850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARG) { 321950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs)) uprv_decNumberCopy(res, rhs); /* an Infinity */ 322050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else decNaNs(res, rhs, NULL, set, &status); /* a NaN */ 322150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 322250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* finite */ 322350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* have a finite number; no error possible (res must be big enough) */ 322450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->exponent>=0) return uprv_decNumberCopy(res, rhs); 322550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* that was easy, but if negative exponent there is work to do... */ 322650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset=*set; /* clone rounding, etc. */ 322750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.digits=rhs->digits; /* no length rounding */ 322850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.traps=0; /* no traps */ 322950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dn); /* make a number with exponent 0 */ 323050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberQuantize(res, rhs, &dn, &workset); 323150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=workset.status; 323250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 323350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 323450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 323550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberToIntegralExact */ 323650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 323750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberToIntegralValue(decNumber *res, const decNumber *rhs, 323850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 323950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset=*set; /* working context */ 324050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.traps=0; /* no traps */ 324150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberToIntegralExact(res, rhs, &workset); 324250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this never affects set, except for sNaNs; NaN will have been set */ 324350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* or propagated already, so no need to call decStatus */ 324450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho set->status|=workset.status&DEC_Invalid_operation; 324550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 324650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberToIntegralValue */ 324750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 324850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 324950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberXor -- XOR two Numbers, digitwise */ 325050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 325150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ^ B */ 325250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 325350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X^X) */ 325450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 325550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 325650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context (used for result length and error report) */ 325750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 325850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 325950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 326050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Logical function restrictions apply (see above); a NaN is */ 326150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 326250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 326350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberXor(decNumber *res, const decNumber *lhs, 326450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 326550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *ua, *ub; /* -> operands */ 326650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *msua, *msub; /* -> operand msus */ 326750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *uc, *msuc; /* -> result and its msu */ 326850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int msudigs; /* digits in res msu */ 326950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 327050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 327150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 327250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 327350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs) 327450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { 327550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 327650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 327750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 327850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* operands are valid */ 327950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ua=lhs->lsu; /* bottom-up */ 328050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ub=rhs->lsu; /* .. */ 328150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uc=res->lsu; /* .. */ 328250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msua=ua+D2U(lhs->digits)-1; /* -> msu of lhs */ 328350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msub=ub+D2U(rhs->digits)-1; /* -> msu of rhs */ 328450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msuc=uc+D2U(set->digits)-1; /* -> msu of result */ 328550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */ 328650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */ 328750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit a, b; /* extract units */ 328850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ua>msua) a=0; 328950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else a=*ua; 329050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ub>msub) b=0; 329150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else b=*ub; 329250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uc=0; /* can now write back */ 329350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a|b) { /* maybe 1 bits to examine */ 329450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i, j; 329550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This loop could be unrolled and/or use BIN2BCD tables */ 329650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i=0; i<DECDPUN; i++) { 329750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((a^b)&1) *uc=*uc+(Unit)powers[i]; /* effect XOR */ 329850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho j=a%10; 329950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=a/10; 330050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho j|=b%10; 330150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=b/10; 330250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (j>1) { 330350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 330450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 330550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 330650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uc==msuc && i==msudigs-1) break; /* just did final digit */ 330750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each digit */ 330850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* non-zero */ 330950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each unit */ 331050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [here uc-1 is the msu of the result] */ 331150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(res->lsu, uc-res->lsu); 331250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=0; /* integer */ 331350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=0; /* sign=0 */ 331450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; /* [no status to set] */ 331550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberXor */ 331650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 331750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 331850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 331950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Utility routines */ 332050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 332150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 332250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 332350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberClass -- return the decClass of a decNumber */ 332450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn -- the decNumber to test */ 332550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set -- the context to use for Emin */ 332650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns the decClass enum */ 332750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 332850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoenum decClass uprv_decNumberClass(const decNumber *dn, decContext *set) { 332950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsSpecial(dn)) { 333050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsQNaN(dn)) return DEC_CLASS_QNAN; 333150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsSNaN(dn)) return DEC_CLASS_SNAN; 333250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* must be an infinity */ 333350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_INF; 333450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return DEC_CLASS_POS_INF; 333550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 333650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is finite */ 333750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_decNumberIsNormal(dn, set)) { /* most common */ 333850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_NORMAL; 333950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return DEC_CLASS_POS_NORMAL; 334050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 334150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is subnormal or zero */ 334250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(dn)) { /* most common */ 334350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_ZERO; 334450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return DEC_CLASS_POS_ZERO; 334550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 334650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_SUBNORMAL; 334750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return DEC_CLASS_POS_SUBNORMAL; 334850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberClass */ 334950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 335050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 335150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberClassToString -- convert decClass to a string */ 335250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 335350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* eclass is a valid decClass */ 335450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns a constant string describing the class (max 13+1 chars) */ 335550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 335650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst char *uprv_decNumberClassToString(enum decClass eclass) { 335750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_POS_NORMAL) return DEC_ClassString_PN; 335850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_NEG_NORMAL) return DEC_ClassString_NN; 335950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_POS_ZERO) return DEC_ClassString_PZ; 336050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_NEG_ZERO) return DEC_ClassString_NZ; 336150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_POS_SUBNORMAL) return DEC_ClassString_PS; 336250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_NEG_SUBNORMAL) return DEC_ClassString_NS; 336350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_POS_INF) return DEC_ClassString_PI; 336450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_NEG_INF) return DEC_ClassString_NI; 336550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_QNAN) return DEC_ClassString_QN; 336650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_SNAN) return DEC_ClassString_SN; 336750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return DEC_ClassString_UN; /* Unknown */ 336850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberClassToString */ 336950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 337050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 337150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCopy -- copy a number */ 337250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 337350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dest is the target decNumber */ 337450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* src is the source decNumber */ 337550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns dest */ 337650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 337750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (dest==src is allowed and is a no-op) */ 337850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All fields are updated as required. This is a utility operation, */ 337950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* so special values are unchanged and no error is possible. */ 338050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 338150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCopy(decNumber *dest, const decNumber *src) { 338250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 338350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 338450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (src==NULL) return uprv_decNumberZero(dest); 338550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 338650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 338750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dest==src) return dest; /* no copy required */ 338850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 338950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Use explicit assignments here as structure assignment could copy */ 339050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* more than just the lsu (for small DECDPUN). This would not affect */ 339150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the value of the results, but could disturb test harness spill */ 339250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* checking. */ 339350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dest->bits=src->bits; 339450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dest->exponent=src->exponent; 339550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dest->digits=src->digits; 339650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dest->lsu[0]=src->lsu[0]; 339750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (src->digits>DECDPUN) { /* more Units to come */ 339850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *smsup, *s; /* work */ 339950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *d; /* .. */ 340050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* memcpy for the remaining Units would be safe as they cannot */ 340150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* overlap. However, this explicit loop is faster in short cases. */ 340250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho d=dest->lsu+1; /* -> first destination */ 340350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho smsup=src->lsu+D2U(src->digits); /* -> source msu+1 */ 340450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (s=src->lsu+1; s<smsup; s++, d++) *d=*s; 340550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 340650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dest; 340750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCopy */ 340850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 340950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 341050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCopyAbs -- quiet absolute value operator */ 341150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 341250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This sets C = abs(A) */ 341350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 341450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 341550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 341650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 341750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 341850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No exception or error can occur; this is a quiet bitwise operation.*/ 341950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* See also decNumberAbs for a checking version of this. */ 342050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 342150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCopyAbs(decNumber *res, const decNumber *rhs) { 342250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 342350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res; 342450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 342550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, rhs); 342650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits&=~DECNEG; /* turn off sign */ 342750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 342850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCopyAbs */ 342950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 343050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 343150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCopyNegate -- quiet negate value operator */ 343250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 343350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This sets C = negate(A) */ 343450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 343550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 343650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 343750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 343850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 343950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No exception or error can occur; this is a quiet bitwise operation.*/ 344050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* See also decNumberMinus for a checking version of this. */ 344150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 344250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCopyNegate(decNumber *res, const decNumber *rhs) { 344350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 344450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res; 344550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 344650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, rhs); 344750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits^=DECNEG; /* invert the sign */ 344850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 344950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCopyNegate */ 345050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 345150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 345250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCopySign -- quiet copy and set sign operator */ 345350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 345450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This sets C = A with the sign of B */ 345550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 345650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 345750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 345850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 345950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 346050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 346150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No exception or error can occur; this is a quiet bitwise operation.*/ 346250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 346350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCopySign(decNumber *res, const decNumber *lhs, 346450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs) { 346550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte sign; /* rhs sign */ 346650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 346750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res; 346850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 346950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho sign=rhs->bits & DECNEG; /* save sign bit */ 347050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); 347150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits&=~DECNEG; /* clear the sign */ 347250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits|=sign; /* set from rhs */ 347350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 347450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCopySign */ 347550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 347650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 347750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberGetBCD -- get the coefficient in BCD8 */ 347850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the source decNumber */ 347950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* bcd is the uInt array that will receive dn->digits BCD bytes, */ 348050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* most-significant at offset 0 */ 348150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns bcd */ 348250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 348350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* bcd must have at least dn->digits bytes. No error is possible; if */ 348450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is a NaN or Infinite, digits must be 1 and the coefficient 0. */ 348550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 348650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI uByte * U_EXPORT2 uprv_decNumberGetBCD(const decNumber *dn, uByte *bcd) { 348750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte *ub=bcd+dn->digits-1; /* -> lsd */ 348850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up=dn->lsu; /* Unit pointer, -> lsu */ 348950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 349050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==1 /* trivial simple copy */ 349150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; ub>=bcd; ub--, up++) *ub=*up; 349250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else /* chopping needed */ 349350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt u=*up; /* work */ 349450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt cut=DECDPUN; /* downcounter through unit */ 349550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; ub>=bcd; ub--) { 349650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *ub=(uByte)(u%10); /* [*6554 trick inhibits, here] */ 349750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=u/10; 349850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut--; 349950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut>0) continue; /* more in this unit */ 350050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; 350150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=*up; 350250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN; 350350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 350450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 350550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return bcd; 350650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberGetBCD */ 350750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 350850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 350950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberSetBCD -- set (replace) the coefficient from BCD8 */ 351050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the target decNumber */ 351150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* bcd is the uInt array that will source n BCD bytes, most- */ 351250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* significant at offset 0 */ 351350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* n is the number of digits in the source BCD array (bcd) */ 351450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns dn */ 351550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 351650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn must have space for at least n digits. No error is possible; */ 351750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if dn is a NaN, or Infinite, or is to become a zero, n must be 1 */ 351850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and bcd[0] zero. */ 351950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 352050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberSetBCD(decNumber *dn, const uByte *bcd, uInt n) { 352150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [target pointer] */ 352250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const uByte *ub=bcd; /* -> source msd */ 352350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 352450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==1 /* trivial simple copy */ 352550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; ub<bcd+n; ub++, up--) *up=*ub; 352650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else /* some assembly needed */ 352750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate how many digits in msu, and hence first cut */ 352850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int cut=MSUDIGITS(n); /* [faster than remainder] */ 352950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;up>=dn->lsu; up--) { /* each Unit from msu */ 353050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=0; /* will take <=DECDPUN digits */ 353150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; cut>0; ub++, cut--) *up=X10(*up)+*ub; 353250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN; /* next Unit has all digits */ 353350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 353450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 353550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=n; /* set digit count */ 353650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 353750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberSetBCD */ 353850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 353950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 354050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberIsNormal -- test normality of a decNumber */ 354150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the decNumber to test */ 354250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context to use for Emin */ 354350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns 1 if |dn| is finite and >=Nmin, 0 otherwise */ 354450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 354550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoInt uprv_decNumberIsNormal(const decNumber *dn, decContext *set) { 354650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ae; /* adjusted exponent */ 354750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 354850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0; 354950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 355050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 355150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsSpecial(dn)) return 0; /* not finite */ 355250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(dn)) return 0; /* not non-zero */ 355350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 355450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ae=dn->exponent+dn->digits-1; /* adjusted exponent */ 355550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ae<set->emin) return 0; /* is subnormal */ 355650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1; 355750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberIsNormal */ 355850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 355950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 356050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberIsSubnormal -- test subnormality of a decNumber */ 356150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the decNumber to test */ 356250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context to use for Emin */ 356350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns 1 if |dn| is finite, non-zero, and <Nmin, 0 otherwise */ 356450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 356550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoInt uprv_decNumberIsSubnormal(const decNumber *dn, decContext *set) { 356650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ae; /* adjusted exponent */ 356750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 356850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0; 356950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 357050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 357150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsSpecial(dn)) return 0; /* not finite */ 357250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(dn)) return 0; /* not non-zero */ 357350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 357450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ae=dn->exponent+dn->digits-1; /* adjusted exponent */ 357550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ae<set->emin) return 1; /* is subnormal */ 357650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; 357750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberIsSubnormal */ 357850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 357950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 358050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberTrim -- remove insignificant zeros */ 358150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 358250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to trim */ 358350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns dn */ 358450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 358550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All fields are updated as required. This is a utility operation, */ 358650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* so special values are unchanged and no error is possible. The */ 358750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* zeros are removed unconditionally. */ 358850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 358950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberTrim(decNumber *dn) { 359050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int dropped; /* work */ 359150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext set; /* .. */ 359250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 359350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(DECUNRESU, DECUNUSED, dn, DECUNCONT)) return dn; 359450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 359550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&set, DEC_INIT_BASE); /* clamp=0 */ 359650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return decTrim(dn, &set, 0, 1, &dropped); 359750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberTrim */ 359850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 359950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 360050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberVersion -- return the name and version of this module */ 360150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 360250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No error is possible. */ 360350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 360450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst char * uprv_decNumberVersion(void) { 360550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return DECVERSION; 360650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberVersion */ 360750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 360850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 360950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberZero -- set a number to 0 */ 361050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 361150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to set, with space for one digit */ 361250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns dn */ 361350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 361450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No error is possible. */ 361550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 361650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Memset is not used as it is much slower in some environments. */ 361750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberZero(decNumber *dn) { 361850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 361950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 362050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn; 362150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 362250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 362350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=0; 362450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=0; 362550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=1; 362650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->lsu[0]=0; 362750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 362850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberZero */ 362950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 363050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 363150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Local routines */ 363250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 363350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 363450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 363550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decToString -- lay out a number into a string */ 363650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 363750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to lay out */ 363850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* string is where to lay out the number */ 363950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* eng is 1 if Engineering, 0 if Scientific */ 364050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 364150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* string must be at least dn->digits+14 characters long */ 364250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No error is possible. */ 364350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 364450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Note that this routine can generate a -0 or 0.000. These are */ 364550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* never generated in subset to-number or arithmetic, but can occur */ 364650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* in non-subset arithmetic (e.g., -1*0 or 1.234-1.234). */ 364750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 364850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If DECCHECK is enabled the string "?" is returned if a number is */ 364950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* invalid. */ 365050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decToString(const decNumber *dn, char *string, Flag eng) { 365150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int exp=dn->exponent; /* local copy */ 365250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int e; /* E-part value */ 365350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int pre; /* digits before the '.' */ 365450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int cut; /* for counting digits in a Unit */ 365550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *c=string; /* work [output pointer] */ 365650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [input pointer] */ 365750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt u, pow; /* work */ 365850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 365950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 366050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(DECUNRESU, dn, DECUNUSED, DECUNCONT)) { 366150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho strcpy(string, "?"); 366250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return;} 366350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 366450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 366550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dn)) { /* Negatives get a minus */ 366650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='-'; 366750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; 366850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 366950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECSPECIAL) { /* Is a special value */ 367050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(dn)) { 367150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho strcpy(c, "Inf"); 367250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho strcpy(c+3, "inity"); 367350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return;} 367450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a NaN */ 367550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECSNAN) { /* signalling NaN */ 367650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='s'; 367750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; 367850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 367950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho strcpy(c, "NaN"); 368050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c+=3; /* step past */ 368150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if not a clean non-zero coefficient, that's all there is in a */ 368250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* NaN string */ 368350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exp!=0 || (*dn->lsu==0 && dn->digits==1)) return; 368450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [drop through to add integer] */ 368550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 368650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 368750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate how many digits in msu, and hence first cut */ 368850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=MSUDIGITS(dn->digits); /* [faster than remainder] */ 368950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut--; /* power of ten for digit */ 369050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 369150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exp==0) { /* simple integer [common fastpath] */ 369250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;up>=dn->lsu; up--) { /* each Unit from msu */ 369350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=*up; /* contains DECDPUN digits to lay out */ 369450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; cut>=0; c++, cut--) TODIGIT(u, cut, c, pow); 369550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN-1; /* next Unit has all digits */ 369650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 369750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='\0'; /* terminate the string */ 369850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return;} 369950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 370050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* non-0 exponent -- assume plain form */ 370150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pre=dn->digits+exp; /* digits before '.' */ 370250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho e=0; /* no E */ 370350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((exp>0) || (pre<-5)) { /* need exponential form */ 370450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho e=exp+dn->digits-1; /* calculate E value */ 370550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pre=1; /* assume one digit before '.' */ 370650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eng && (e!=0)) { /* engineering: may need to adjust */ 370750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int adj; /* adjustment */ 370850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The C remainder operator is undefined for negative numbers, so */ 370950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a positive remainder calculation must be used here */ 371050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (e<0) { 371150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adj=(-e)%3; 371250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adj!=0) adj=3-adj; 371350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 371450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* e>0 */ 371550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adj=e%3; 371650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 371750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho e=e-adj; 371850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if dealing with zero still produce an exponent which is a */ 371950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* multiple of three, as expected, but there will only be the */ 372050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* one zero before the E, still. Otherwise note the padding. */ 372150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!ISZERO(dn)) pre+=adj; 372250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* is zero */ 372350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adj!=0) { /* 0.00Esnn needed */ 372450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho e=e+3; 372550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pre=-(2-adj); 372650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 372750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* zero */ 372850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* eng */ 372950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* need exponent */ 373050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 373150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lay out the digits of the coefficient, adding 0s and . as needed */ 373250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=*up; 373350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pre>0) { /* xxx.xxx or xx00 (engineering) form */ 373450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int n=pre; 373550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; pre>0; pre--, c++, cut--) { 373650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut<0) { /* need new Unit */ 373750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (up==dn->lsu) break; /* out of input digits (pre>digits) */ 373850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up--; 373950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN-1; 374050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=*up; 374150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 374250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho TODIGIT(u, cut, c, pow); 374350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 374450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n<dn->digits) { /* more to come, after '.' */ 374550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='.'; c++; 374650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;; c++, cut--) { 374750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut<0) { /* need new Unit */ 374850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (up==dn->lsu) break; /* out of input digits */ 374950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up--; 375050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN-1; 375150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=*up; 375250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 375350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho TODIGIT(u, cut, c, pow); 375450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 375550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 375650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else for (; pre>0; pre--, c++) *c='0'; /* 0 padding (for engineering) needed */ 375750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 375850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* 0.xxx or 0.000xxx form */ 375950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='0'; c++; 376050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='.'; c++; 376150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; pre<0; pre++, c++) *c='0'; /* add any 0's after '.' */ 376250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; ; c++, cut--) { 376350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut<0) { /* need new Unit */ 376450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (up==dn->lsu) break; /* out of input digits */ 376550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up--; 376650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN-1; 376750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=*up; 376850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 376950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho TODIGIT(u, cut, c, pow); 377050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 377150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 377250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 377350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Finally add the E-part, if needed. It will never be 0, has a 377450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho base maximum and minimum of +999999999 through -999999999, but 377550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho could range down to -1999999998 for anormal numbers */ 377650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (e!=0) { 377750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag had=0; /* 1=had non-zero */ 377850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='E'; c++; 377950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='+'; c++; /* assume positive */ 378050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=e; /* .. */ 378150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (e<0) { 378250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *(c-1)='-'; /* oops, need - */ 378350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=-e; /* uInt, please */ 378450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 378550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lay out the exponent [_itoa or equivalent is not ANSI C] */ 378650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (cut=9; cut>=0; cut--) { 378750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho TODIGIT(u, cut, c, pow); 378850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='0' && !had) continue; /* skip leading zeros */ 378950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho had=1; /* had non-0 */ 379050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; /* step for next */ 379150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* cut */ 379250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 379350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='\0'; /* terminate the string (all paths) */ 379450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 379550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decToString */ 379650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 379750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 379850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decAddOp -- add/subtract operation */ 379950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 380050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A + B */ 380150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 380250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X+X) */ 380350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 380450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 380550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 380650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* negate is DECNEG if rhs should be negated, or 0 otherwise */ 380750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status accumulates status for the caller */ 380850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 380950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 381050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Inexact in status must be 0 for correct Exact zero sign in result */ 381150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 381250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If possible, the coefficient is calculated directly into C. */ 381350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* However, if: */ 381450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -- a digits+1 calculation is needed because the numbers are */ 381550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* unaligned and span more than set->digits digits */ 381650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -- a carry to digits+1 digits looks possible */ 381750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -- C is the same as A or B, and the result would destructively */ 381850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* overlap the A or B coefficient */ 381950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* then the result must be calculated into a temporary buffer. In */ 382050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* this case a local (stack) buffer is used if possible, and only if */ 382150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* too long for that does malloc become the final resort. */ 382250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 382350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Misalignment is handled as follows: */ 382450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Apad: (AExp>BExp) Swap operands and proceed as for BExp>AExp. */ 382550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* BPad: Apply the padding by a combination of shifting (whole */ 382650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* units) and multiplication (part units). */ 382750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 382850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Addition, especially x=x+1, is speed-critical. */ 382950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The static buffer is larger than might be expected to allow for */ 383050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* calls from higher-level funtions (notable exp). */ 383150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 383250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decAddOp(decNumber *res, const decNumber *lhs, 383350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set, 383450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte negate, uInt *status) { 383550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 383650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */ 383750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* .., rhs */ 383850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 383950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int rhsshift; /* working shift (in Units) */ 384050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxdigits; /* longest logical length */ 384150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int mult; /* multiplier */ 384250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue; /* rounding accumulator */ 384350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte bits; /* result bits */ 384450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag diffsign; /* non-0 if arguments have different sign */ 384550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *acc; /* accumulator for result */ 384650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit accbuff[SD2U(DECBUFFER*2+20)]; /* local buffer [*2+20 reduces many */ 384750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* allocations when called from */ 384850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* other operations, notable exp] */ 384950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *allocacc=NULL; /* -> allocated acc buffer, iff allocated */ 385050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int reqdigits=set->digits; /* local copy; requested DIGITS */ 385150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int padding; /* work */ 385250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 385350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 385450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 385550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 385650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 385750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 385850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 385950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 386050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operands and set lostDigits status, as needed */ 386150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>reqdigits) { 386250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloclhs=decRoundOperand(lhs, set, status); 386350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs==NULL) break; 386450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=alloclhs; 386550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 386650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>reqdigits) { 386750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, status); 386850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 386950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 387050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 387150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 387250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 387350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 387450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 387550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* note whether signs differ [used all paths] */ 387650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho diffsign=(Flag)((lhs->bits^rhs->bits^negate)&DECNEG); 387750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 387850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle infinities and NaNs */ 387950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS) { /* a special bit set */ 388050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS & (DECSNAN | DECNAN)) /* a NaN */ 388150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, status); 388250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* one or two infinities */ 388350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(lhs)) { /* LHS is infinity */ 388450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* two infinities with different signs is invalid */ 388550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs) && diffsign) { 388650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 388750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 388850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 388950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=lhs->bits & DECNEG; /* get sign from LHS */ 389050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 389150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else bits=(rhs->bits^negate) & DECNEG;/* RHS must be Infinity */ 389250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits|=DECINF; 389350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 389450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; /* set +/- infinity */ 389550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* an infinity */ 389650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 389750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 389850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 389950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Quick exit for add 0s; return the non-0, modified as need be */ 390050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(lhs)) { 390150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int adjust; /* work */ 390250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int lexp=lhs->exponent; /* save in case LHS==RES */ 390350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=lhs->bits; /* .. */ 390450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* clear accumulator */ 390550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, rhs, set, &residue, status); /* copy (as needed) */ 390650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits^=negate; /* flip if rhs was negated */ 390750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 390850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->extended) { /* exponents on zeros count */ 390950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 391050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* exponent will be the lower of the two */ 391150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adjust=lexp-res->exponent; /* adjustment needed [if -ve] */ 391250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(res)) { /* both 0: special IEEE 754 rules */ 391350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adjust<0) res->exponent=lexp; /* set exponent */ 391450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 0-0 gives +0 unless rounding to -infinity, and -0-0 gives -0 */ 391550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (diffsign) { 391650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->round!=DEC_ROUND_FLOOR) res->bits=0; 391750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else res->bits=DECNEG; /* preserve 0 sign */ 391850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 391950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 392050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* non-0 res */ 392150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adjust<0) { /* 0-padding needed */ 392250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((res->digits-adjust)>set->digits) { 392350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adjust=res->digits-set->digits; /* to fit exactly */ 392450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Rounded; /* [but exact] */ 392550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 392650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, res->digits, -adjust); 392750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent+=adjust; /* set the exponent. */ 392850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 392950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* non-0 res */ 393050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 393150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* extended */ 393250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 393350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* clean and finalize */ 393450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 393550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 393650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) { /* [lhs is non-zero] */ 393750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int adjust; /* work */ 393850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int rexp=rhs->exponent; /* save in case RHS==RES */ 393950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=rhs->bits; /* be clean */ 394050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* clear accumulator */ 394150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, lhs, set, &residue, status); /* copy (as needed) */ 394250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 394350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->extended) { /* exponents on zeros count */ 394450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 394550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* exponent will be the lower of the two */ 394650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [0-0 case handled above] */ 394750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adjust=rexp-res->exponent; /* adjustment needed [if -ve] */ 394850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adjust<0) { /* 0-padding needed */ 394950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((res->digits-adjust)>set->digits) { 395050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adjust=res->digits-set->digits; /* to fit exactly */ 395150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Rounded; /* [but exact] */ 395250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 395350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, res->digits, -adjust); 395450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent+=adjust; /* set the exponent. */ 395550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 395650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 395750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* extended */ 395850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 395950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* clean and finalize */ 396050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 396150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 396250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [NB: both fastpath and mainpath code below assume these cases */ 396350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (notably 0-0) have already been handled] */ 396450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 396550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the padding needed to align the operands */ 396650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho padding=rhs->exponent-lhs->exponent; 396750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 396850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Fastpath cases where the numbers are aligned and normal, the RHS */ 396950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is all in one unit, no operand rounding is needed, and no carry, */ 397050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lengthening, or borrow is needed */ 397150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (padding==0 397250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && rhs->digits<=DECDPUN 397350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && rhs->exponent>=set->emin /* [some normals drop through] */ 397450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && rhs->exponent<=set->emax-set->digits+1 /* [could clamp] */ 397550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && rhs->digits<=reqdigits 397650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && lhs->digits<=reqdigits) { 397750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int partial=*lhs->lsu; 397850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!diffsign) { /* adding */ 397950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho partial+=*rhs->lsu; 398050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((partial<=DECDPUNMAX) /* result fits in unit */ 398150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && (lhs->digits>=DECDPUN || /* .. and no digits-count change */ 398250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho partial<(Int)powers[lhs->digits])) { /* .. */ 398350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res!=lhs) uprv_decNumberCopy(res, lhs); /* not in place */ 398450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=(Unit)partial; /* [copy could have overwritten RHS] */ 398550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 398650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 398750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* else drop out for careful add */ 398850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 398950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* signs differ */ 399050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho partial-=*rhs->lsu; 399150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (partial>0) { /* no borrow needed, and non-0 result */ 399250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res!=lhs) uprv_decNumberCopy(res, lhs); /* not in place */ 399350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=(Unit)partial; 399450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this could have reduced digits [but result>0] */ 399550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(res->lsu, D2U(res->digits)); 399650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 399750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 399850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* else drop out for careful subtract */ 399950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 400050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 400150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 400250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Now align (pad) the lhs or rhs so they can be added or */ 400350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subtracted, as necessary. If one number is much larger than */ 400450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the other (that is, if in plain form there is a least one */ 400550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* digit between the lowest digit of one and the highest of the */ 400650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* other) padding with up to DIGITS-1 trailing zeros may be */ 400750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* needed; then apply rounding (as exotic rounding modes may be */ 400850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* affected by the residue). */ 400950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhsshift=0; /* rhs shift to left (padding) in Units */ 401050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=lhs->bits; /* assume sign is that of LHS */ 401150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mult=1; /* likely multiplier */ 401250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 401350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [if padding==0 the operands are aligned; no padding is needed] */ 401450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (padding!=0) { 401550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* some padding needed; always pad the RHS, as any required */ 401650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* padding can then be effected by a simple combination of */ 401750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* shifts and a multiply */ 401850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag swapped=0; 401950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (padding<0) { /* LHS needs the padding */ 402050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *t; 402150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho padding=-padding; /* will be +ve */ 402250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=(uByte)(rhs->bits^negate); /* assumed sign is now that of RHS */ 402350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t=lhs; lhs=rhs; rhs=t; 402450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho swapped=1; 402550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 402650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 402750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If, after pad, rhs would be longer than lhs by digits+1 or */ 402850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* more then lhs cannot affect the answer, except as a residue, */ 402950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* so only need to pad up to a length of DIGITS+1. */ 403050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits+padding > lhs->digits+reqdigits+1) { 403150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The RHS is sufficient */ 403250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* for residue use the relative sign indication... */ 403350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift=reqdigits-rhs->digits; /* left shift needed */ 403450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=1; /* residue for rounding */ 403550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (diffsign) residue=-residue; /* signs differ */ 403650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* copy, shortening if necessary */ 403750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, rhs, set, &residue, status); 403850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if it was already shorter, then need to pad with zeros */ 403950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift>0) { 404050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, res->digits, shift); 404150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent-=shift; /* adjust the exponent. */ 404250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 404350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* flip the result sign if unswapped and rhs was negated */ 404450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!swapped) res->bits^=negate; 404550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* done */ 404650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 404750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 404850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* LHS digits may affect result */ 404950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhsshift=D2U(padding+1)-1; /* this much by Unit shift .. */ 405050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mult=powers[padding-(rhsshift*DECDPUN)]; /* .. this by multiplication */ 405150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* padding needed */ 405250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 405350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (diffsign) mult=-mult; /* signs differ */ 405450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 405550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* determine the longer operand */ 405650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxdigits=rhs->digits+padding; /* virtual length of RHS */ 405750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>maxdigits) maxdigits=lhs->digits; 405850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 405950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Decide on the result buffer to use; if possible place directly */ 406050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* into result. */ 406150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=res->lsu; /* assume add direct to result */ 406250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If destructive overlap, or the number is too long, or a carry or */ 406350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* borrow to DIGITS+1 might be possible, a buffer must be used. */ 406450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [Might be worth more sophisticated tests when maxdigits==reqdigits] */ 406550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((maxdigits>=reqdigits) /* is, or could be, too large */ 406650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (res==rhs && rhsshift>0)) { /* destructive overlap */ 406750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffer needed, choose it; units for maxdigits digits will be */ 406850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* needed, +1 Unit for carry or borrow */ 406950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int need=D2U(maxdigits)+1; 407050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=accbuff; /* assume use local buffer */ 407150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (need*sizeof(Unit)>sizeof(accbuff)) { 407250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* printf("malloc add %ld %ld\n", need, sizeof(accbuff)); */ 407350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocacc=(Unit *)malloc(need*sizeof(Unit)); 407450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc==NULL) { /* hopeless -- abandon */ 407550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 407650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 407750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=allocacc; 407850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 407950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 408050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 408150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=(uByte)(bits&DECNEG); /* it's now safe to overwrite.. */ 408250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=lhs->exponent; /* .. operands (even if aliased) */ 408350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 408450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 408550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('A', lhs->lsu, D2U(lhs->digits)); 408650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('B', rhs->lsu, D2U(rhs->digits)); 408750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf(" :h: %ld %ld\n", rhsshift, mult); 408850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 408950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 409050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* add [A+B*m] or subtract [A+B*(-m)] */ 4091103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius U_ASSERT(rhs->digits > 0); 4092103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius U_ASSERT(lhs->digits > 0); 409350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decUnitAddSub(lhs->lsu, D2U(lhs->digits), 409450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs->lsu, D2U(rhs->digits), 409550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhsshift, acc, mult) 409650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *DECDPUN; /* [units -> digits] */ 409750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits<0) { /* borrowed... */ 409850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=-res->digits; 409950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits^=DECNEG; /* flip the sign */ 410050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 410150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 410250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('+', acc, D2U(res->digits)); 410350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 410450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 410550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If a buffer was used the result must be copied back, possibly */ 410650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* shortening. (If no buffer was used then the result must have */ 410750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* fit, so can't need rounding and residue must be 0.) */ 410850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* clear accumulator */ 410950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (acc!=res->lsu) { 411050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 411150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->extended) { /* round from first significant digit */ 411250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 411350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* remove leading zeros that were added due to rounding up to */ 411450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* integral Units -- before the test for rounding. */ 411550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits>reqdigits) 411650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(acc, D2U(res->digits)); 411750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetCoeff(res, set, acc, res->digits, &residue, status); 411850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 411950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 412050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* subset arithmetic rounds from original significant digit */ 412150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* May have an underestimate. This only occurs when both */ 412250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* numbers fit in DECDPUN digits and are padding with a */ 412350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative multiple (-10, -100...) and the top digit(s) become */ 412450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 0. (This only matters when using X3.274 rules where the */ 412550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* leading zero could be included in the rounding.) */ 412650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits<maxdigits) { 412750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *(acc+D2U(res->digits))=0; /* ensure leading 0 is there */ 412850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=maxdigits; 412950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 413050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 413150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* remove leading zeros that added due to rounding up to */ 413250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* integral Units (but only those in excess of the original */ 413350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* maxdigits length, unless extended) before test for rounding. */ 413450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits>reqdigits) { 413550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(acc, D2U(res->digits)); 413650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits<maxdigits) res->digits=maxdigits; 413750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 413850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 413950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetCoeff(res, set, acc, res->digits, &residue, status); 414050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Now apply rounding if needed before removing leading zeros. */ 414150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This is safe because subnormals are not a possibility */ 414250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue!=0) { 414350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decApplyRound(res, set, residue, status); 414450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* did what needed to be done */ 414550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 414650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* subset */ 414750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 414850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* used buffer */ 414950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 415050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* strip leading zeros [these were left on in case of subset subtract] */ 415150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(res->lsu, D2U(res->digits)); 415250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 415350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* apply checks and rounding */ 415450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); 415550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 415650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* "When the sum of two operands with opposite signs is exactly */ 415750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* zero, the sign of that sum shall be '+' in all rounding modes */ 415850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* except round toward -Infinity, in which mode that sign shall be */ 415950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* '-'." [Subset zeros also never have '-', set by decFinish.] */ 416050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(res) && diffsign 416150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 416250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && set->extended 416350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 416450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && (*status&DEC_Inexact)==0) { 416550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->round==DEC_ROUND_FLOOR) res->bits|=DECNEG; /* sign - */ 416650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else res->bits&=~DECNEG; /* sign + */ 416750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 416850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 416950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 417050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc!=NULL) free(allocacc); /* drop any storage used */ 417150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 417250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs!=NULL) free(allocrhs); /* .. */ 417350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs!=NULL) free(alloclhs); /* .. */ 417450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 417550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 417650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decAddOp */ 417750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 417850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 417950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decDivideOp -- division operation */ 418050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 418150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine performs the calculations for all four division */ 418250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* operators (divide, divideInteger, remainder, remainderNear). */ 418350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 418450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C=A op B */ 418550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 418650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X/X) */ 418750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 418850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 418950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 419050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* op is DIVIDE, DIVIDEINT, REMAINDER, or REMNEAR respectively. */ 419150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the usual accumulator */ 419250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 419350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 419450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 419550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 419650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The underlying algorithm of this routine is the same as in the */ 419750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 1981 S/370 implementation, that is, non-restoring long division */ 419850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* with bi-unit (rather than bi-digit) estimation for each unit */ 419950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* multiplier. In this pseudocode overview, complications for the */ 420050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Remainder operators and division residues for exact rounding are */ 420150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* omitted for clarity. */ 420250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 420350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Prepare operands and handle special values */ 420450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Test for x/0 and then 0/x */ 420550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Exp =Exp1 - Exp2 */ 420650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Exp =Exp +len(var1) -len(var2) */ 420750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Sign=Sign1 * Sign2 */ 420850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Pad accumulator (Var1) to double-length with 0's (pad1) */ 420950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Pad Var2 to same length as Var1 */ 421050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* msu2pair/plus=1st 2 or 1 units of var2, +1 to allow for round */ 421150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* have=0 */ 421250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Do until (have=digits+1 OR residue=0) */ 421350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if exp<0 then if integer divide/residue then leave */ 421450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* this_unit=0 */ 421550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Do forever */ 421650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* compare numbers */ 421750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if <0 then leave inner_loop */ 421850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if =0 then (* quick exit without subtract *) do */ 421950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* this_unit=this_unit+1; output this_unit */ 422050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* leave outer_loop; end */ 422150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Compare lengths of numbers (mantissae): */ 422250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If same then tops2=msu2pair -- {units 1&2 of var2} */ 422350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* else tops2=msu2plus -- {0, unit 1 of var2} */ 422450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* tops1=first_unit_of_Var1*10**DECDPUN +second_unit_of_var1 */ 422550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* mult=tops1/tops2 -- Good and safe guess at divisor */ 422650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if mult=0 then mult=1 */ 422750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* this_unit=this_unit+mult */ 422850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* subtract */ 422950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end inner_loop */ 423050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if have\=0 | this_unit\=0 then do */ 423150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* output this_unit */ 423250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* have=have+1; end */ 423350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* var2=var2/10 */ 423450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* exp=exp-1 */ 423550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end outer_loop */ 423650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* exp=exp+1 -- set the proper exponent */ 423750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if have=0 then generate answer=0 */ 423850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Return (Result is defined by Var1) */ 423950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 424050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 424150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Two working buffers are needed during the division; one (digits+ */ 424250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 1) to accumulate the result, and the other (up to 2*digits+1) for */ 424350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* long subtractions. These are acc and var1 respectively. */ 424450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* var1 is a copy of the lhs coefficient, var2 is the rhs coefficient.*/ 424550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The static buffers may be larger than might be expected to allow */ 424650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* for calls from higher-level funtions (notable exp). */ 424750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 424850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decDivideOp(decNumber *res, 424950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *lhs, const decNumber *rhs, 425050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set, Flag op, uInt *status) { 425150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 425250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */ 425350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* .., rhs */ 425450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 425550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit accbuff[SD2U(DECBUFFER+DECDPUN+10)]; /* local buffer */ 425650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *acc=accbuff; /* -> accumulator array for result */ 425750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *allocacc=NULL; /* -> allocated buffer, iff allocated */ 425850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *accnext; /* -> where next digit will go */ 425950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int acclength; /* length of acc needed [Units] */ 426050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int accunits; /* count of units accumulated */ 426150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int accdigits; /* count of digits accumulated */ 426250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 426350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit varbuff[SD2U(DECBUFFER*2+DECDPUN)]; /* buffer for var1 */ 426450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *var1=varbuff; /* -> var1 array for long subtraction */ 426550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *varalloc=NULL; /* -> allocated buffer, iff used */ 426650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *msu1; /* -> msu of var1 */ 426750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 426850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *var2; /* -> var2 array */ 426950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *msu2; /* -> msu of var2 */ 427050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int msu2plus; /* msu2 plus one [does not vary] */ 427150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho eInt msu2pair; /* msu2 pair plus one [does not vary] */ 427250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 427350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int var1units, var2units; /* actual lengths */ 427450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int var2ulen; /* logical length (units) */ 427550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int var1initpad=0; /* var1 initial padding (digits) */ 427650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxdigits; /* longest LHS or required acc length */ 427750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int mult; /* multiplier for subtraction */ 427850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit thisunit; /* current unit being accumulated */ 427950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue; /* for rounding */ 428050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int reqdigits=set->digits; /* requested DIGITS */ 428150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int exponent; /* working exponent */ 428250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxexponent=0; /* DIVIDE maximum exponent if unrounded */ 428350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte bits; /* working sign */ 428450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *target; /* work */ 428550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *source; /* .. */ 428650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt const *pow; /* .. */ 428750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift, cut; /* .. */ 428850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 428950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int dropped; /* work */ 429050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 429150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 429250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 429350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 429450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 429550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 429650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 429750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 429850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 429950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operands and set lostDigits status, as needed */ 430050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>reqdigits) { 430150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloclhs=decRoundOperand(lhs, set, status); 430250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs==NULL) break; 430350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=alloclhs; 430450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 430550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>reqdigits) { 430650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, status); 430750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 430850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 430950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 431050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 431150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 431250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 431350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 431450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=(lhs->bits^rhs->bits)&DECNEG; /* assumed sign for divisions */ 431550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 431650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle infinities and NaNs */ 431750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS) { /* a special bit set */ 431850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */ 431950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, status); 432050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 432150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 432250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* one or two infinities */ 432350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(lhs)) { /* LHS (dividend) is infinite */ 432450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs) || /* two infinities are invalid .. */ 432550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho op & (REMAINDER | REMNEAR)) { /* as is remainder of infinity */ 432650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 432750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 432850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 432950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [Note that infinity/0 raises no exceptions] */ 433050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 433150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits|DECINF; /* set +/- infinity */ 433250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 433350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 433450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* RHS (divisor) is infinite */ 433550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; 433650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&(REMAINDER|REMNEAR)) { 433750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* result is [finished clone of] lhs */ 433850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, lhs, set, &residue, status); 433950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 434050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* a division */ 434150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 434250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; /* set +/- zero */ 434350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* for DIVIDEINT the exponent is always 0. For DIVIDE, result */ 434450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is a 0 with infinitely negative exponent, clamped to minimum */ 434550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&DIVIDE) { 434650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=set->emin-set->digits+1; 434750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Clamped; 434850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 434950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 435050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); 435150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 435250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 435350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 435450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 435550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle 0 rhs (x/0) */ 435650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) { /* x/0 is always exceptional */ 435750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(lhs)) { 435850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* [after lhs test] */ 435950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Division_undefined;/* 0/0 will become NaN */ 436050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 436150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 436250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 436350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&(REMAINDER|REMNEAR)) *status|=DEC_Invalid_operation; 436450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 436550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Division_by_zero; /* x/0 */ 436650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits|DECINF; /* .. is +/- Infinity */ 436750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 436850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 436950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 437050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 437150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle 0 lhs (0/x) */ 437250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(lhs)) { /* 0/x [x!=0] */ 437350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 437450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) uprv_decNumberZero(res); 437550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 437650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 437750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&DIVIDE) { 437850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; 437950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent=lhs->exponent-rhs->exponent; /* ideal exponent */ 438050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); /* [zeros always fit] */ 438150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; /* sign as computed */ 438250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=exponent; /* exponent, too */ 438350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinalize(res, set, &residue, status); /* check exponent */ 438450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 438550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (op&DIVIDEINT) { 438650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* integer 0 */ 438750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; /* sign as computed */ 438850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 438950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* a remainder */ 439050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent=rhs->exponent; /* [save in case overwrite] */ 439150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); /* [zeros always fit] */ 439250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exponent<res->exponent) res->exponent=exponent; /* use lower */ 439350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 439450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 439550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 439650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 439750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 439850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 439950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Precalculate exponent. This starts off adjusted (and hence fits */ 440050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* in 31 bits) and becomes the usual unadjusted exponent as the */ 440150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* division proceeds. The order of evaluation is important, here, */ 440250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* to avoid wrap. */ 440350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent=(lhs->exponent+lhs->digits)-(rhs->exponent+rhs->digits); 440450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 440550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If the working exponent is -ve, then some quick exits are */ 440650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* possible because the quotient is known to be <1 */ 440750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [for REMNEAR, it needs to be < -1, as -0.5 could need work] */ 440850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exponent<0 && !(op==DIVIDE)) { 440950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&DIVIDEINT) { 441050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* integer part is 0 */ 441150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 441250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->extended) 441350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 441450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; /* set +/- zero */ 441550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 441650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* fastpath remainders so long as the lhs has the smaller */ 441750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (or equal) exponent */ 441850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent<=rhs->exponent) { 441950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&REMAINDER || exponent<-1) { 442050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* It is REMAINDER or safe REMNEAR; result is [finished */ 442150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* clone of] lhs (r = x - 0*y) */ 442250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; 442350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, lhs, set, &residue, status); 442450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); 442550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 442650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 442750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [unsafe REMNEAR drops through] */ 442850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 442950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* fastpaths */ 443050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 443150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Long (slow) division is needed; roll up the sleeves... */ 443250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 443350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The accumulator will hold the quotient of the division. */ 443450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If it needs to be too long for stack storage, then allocate. */ 443550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acclength=D2U(reqdigits+DECDPUN); /* in Units */ 443650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (acclength*sizeof(Unit)>sizeof(accbuff)) { 443750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* printf("malloc dvacc %ld units\n", acclength); */ 443850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocacc=(Unit *)malloc(acclength*sizeof(Unit)); 443950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc==NULL) { /* hopeless -- abandon */ 444050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 444150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 444250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=allocacc; /* use the allocated space */ 444350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 444450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 444550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* var1 is the padded LHS ready for subtractions. */ 444650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If it needs to be too long for stack storage, then allocate. */ 444750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The maximum units needed for var1 (long subtraction) is: */ 444850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Enough for */ 444950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (rhs->digits+reqdigits-1) -- to allow full slide to right */ 445050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* or (lhs->digits) -- to allow for long lhs */ 445150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* whichever is larger */ 445250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* +1 -- for rounding of slide to right */ 445350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* +1 -- for leading 0s */ 445450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* +1 -- for pre-adjust if a remainder or DIVIDEINT */ 445550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [Note: unused units do not participate in decUnitAddSub data] */ 445650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxdigits=rhs->digits+reqdigits-1; 445750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>maxdigits) maxdigits=lhs->digits; 445850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var1units=D2U(maxdigits)+2; 445950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* allocate a guard unit above msu1 for REMAINDERNEAR */ 446050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(op&DIVIDE)) var1units++; 446150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((var1units+1)*sizeof(Unit)>sizeof(varbuff)) { 446250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* printf("malloc dvvar %ld units\n", var1units+1); */ 446350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho varalloc=(Unit *)malloc((var1units+1)*sizeof(Unit)); 446450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (varalloc==NULL) { /* hopeless -- abandon */ 446550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 446650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 446750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var1=varalloc; /* use the allocated space */ 446850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 446950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 447050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Extend the lhs and rhs to full long subtraction length. The lhs */ 447150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is truly extended into the var1 buffer, with 0 padding, so a */ 447250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subtract in place is always possible. The rhs (var2) has */ 447350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* virtual padding (implemented by decUnitAddSub). */ 447450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* One guard unit was allocated above msu1 for rem=rem+rem in */ 447550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* REMAINDERNEAR. */ 447650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msu1=var1+var1units-1; /* msu of var1 */ 447750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho source=lhs->lsu+D2U(lhs->digits)-1; /* msu of input array */ 447850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (target=msu1; source>=lhs->lsu; source--, target--) *target=*source; 447950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; target>=var1; target--) *target=0; 448050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 448150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rhs (var2) is left-aligned with var1 at the start */ 448250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var2ulen=var1units; /* rhs logical length (units) */ 448350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var2units=D2U(rhs->digits); /* rhs actual length (units) */ 448450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var2=rhs->lsu; /* -> rhs array */ 448550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msu2=var2+var2units-1; /* -> msu of var2 [never changes] */ 448650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now set up the variables which will be used for estimating the */ 448750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* multiplication factor. If these variables are not exact, add */ 448850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1 to make sure that the multiplier is never overestimated. */ 448950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msu2plus=*msu2; /* it's value .. */ 449050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (var2units>1) msu2plus++; /* .. +1 if any more */ 449150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msu2pair=(eInt)*msu2*(DECDPUNMAX+1);/* top two pair .. */ 449250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (var2units>1) { /* .. [else treat 2nd as 0] */ 449350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msu2pair+=*(msu2-1); /* .. */ 449450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (var2units>2) msu2pair++; /* .. +1 if any more */ 449550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 449650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 449750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The calculation is working in units, which may have leading zeros, */ 449850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* but the exponent was calculated on the assumption that they are */ 449950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* both left-aligned. Adjust the exponent to compensate: add the */ 450050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* number of leading zeros in var1 msu and subtract those in var2 msu. */ 450150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [This is actually done by counting the digits and negating, as */ 450250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lead1=DECDPUN-digits1, and similarly for lead2.] */ 450350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (pow=&powers[1]; *msu1>=*pow; pow++) exponent--; 450450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (pow=&powers[1]; *msu2>=*pow; pow++) exponent++; 450550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 450650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Now, if doing an integer divide or remainder, ensure that */ 450750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the result will be Unit-aligned. To do this, shift the var1 */ 450850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accumulator towards least if need be. (It's much easier to */ 450950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* do this now than to reassemble the residue afterwards, if */ 451050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* doing a remainder.) Also ensure the exponent is not negative. */ 451150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(op&DIVIDE)) { 451250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *u; /* work */ 451350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* save the initial 'false' padding of var1, in digits */ 451450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var1initpad=(var1units-D2U(lhs->digits))*DECDPUN; 451550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Determine the shift to do. */ 451650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exponent<0) cut=-exponent; 451750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else cut=DECDPUN-exponent%DECDPUN; 451850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decShiftToLeast(var1, var1units, cut); 451950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent+=cut; /* maintain numerical value */ 452050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var1initpad-=cut; /* .. and reduce padding */ 452150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* clean any most-significant units which were just emptied */ 452250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (u=msu1; cut>=DECDPUN; cut-=DECDPUN, u--) *u=0; 452350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* align */ 452450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* is DIVIDE */ 452550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxexponent=lhs->exponent-rhs->exponent; /* save */ 452650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* optimization: if the first iteration will just produce 0, */ 452750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* preadjust to skip it [valid for DIVIDE only] */ 452850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*msu1<*msu2) { 452950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var2ulen--; /* shift down */ 453050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent-=DECDPUN; /* update the exponent */ 453150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 453250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 453350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 453450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* ---- start the long-division loops ------------------------------ */ 453550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=0; /* no units accumulated yet */ 453650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accdigits=0; /* .. or digits */ 453750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accnext=acc+acclength-1; /* -> msu of acc [NB: allows digits+1] */ 453850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;;) { /* outer forever loop */ 453950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho thisunit=0; /* current unit assumed 0 */ 454050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* find the next unit */ 454150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;;) { /* inner forever loop */ 454250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* strip leading zero units [from either pre-adjust or from */ 454350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subtract last time around]. Leave at least one unit. */ 454450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; *msu1==0 && msu1>var1; msu1--) var1units--; 454550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 454650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (var1units<var2ulen) break; /* var1 too low for subtract */ 454750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (var1units==var2ulen) { /* unit-by-unit compare needed */ 454850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* compare the two numbers, from msu */ 454950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *pv1, *pv2; 455050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit v2; /* units to compare */ 455150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pv2=msu2; /* -> msu */ 455250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (pv1=msu1; ; pv1--, pv2--) { 455350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* v1=*pv1 -- always OK */ 455450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho v2=0; /* assume in padding */ 455550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pv2>=var2) v2=*pv2; /* in range */ 455650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*pv1!=v2) break; /* no longer the same */ 455750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pv1==var1) break; /* done; leave pv1 as is */ 455850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 455950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here when all inspected or a difference seen */ 456050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*pv1<v2) break; /* var1 too low to subtract */ 456150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*pv1==v2) { /* var1 == var2 */ 456250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reach here if var1 and var2 are identical; subtraction */ 456350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* would increase digit by one, and the residue will be 0 so */ 456450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the calculation is done; leave the loop with residue=0. */ 456550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho thisunit++; /* as though subtracted */ 456650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *var1=0; /* set var1 to 0 */ 456750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var1units=1; /* .. */ 456850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* from inner */ 456950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* var1 == var2 */ 457050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* *pv1>v2. Prepare for real subtraction; the lengths are equal */ 457150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Estimate the multiplier (there's always a msu1-1)... */ 457250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Bring in two units of var2 to provide a good estimate. */ 457350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2pair); 457450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* lengths the same */ 457550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* var1units > var2ulen, so subtraction is safe */ 457650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The var2 msu is one unit towards the lsu of the var1 msu, */ 457750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* so only one unit for var2 can be used. */ 457850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2plus); 457950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 458050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mult==0) mult=1; /* must always be at least 1 */ 458150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subtraction needed; var1 is > var2 */ 458250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho thisunit=(Unit)(thisunit+mult); /* accumulate */ 458350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subtract var1-var2, into var1; only the overlap needs */ 458450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* processing, as this is an in-place calculation */ 458550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho shift=var2ulen-var2units; 458650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 458750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('1', &var1[shift], var1units-shift); 458850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('2', var2, var2units); 458950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("m=%ld\n", -mult); 459050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 459150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decUnitAddSub(&var1[shift], var1units-shift, 459250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var2, var2units, 0, 459350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho &var1[shift], -mult); 459450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 459550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('#', &var1[shift], var1units-shift); 459650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 459750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* var1 now probably has leading zeros; these are removed at the */ 459850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* top of the inner loop. */ 459950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* inner loop */ 460050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 460150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The next unit has been calculated in full; unless it's a */ 460250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* leading zero, add to acc */ 460350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (accunits!=0 || thisunit!=0) { /* is first or non-zero */ 460450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *accnext=thisunit; /* store in accumulator */ 460550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* account exactly for the new digits */ 460650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (accunits==0) { 460750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accdigits++; /* at least one */ 460850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (pow=&powers[1]; thisunit>=*pow; pow++) accdigits++; 460950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 461050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else accdigits+=DECDPUN; 461150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits++; /* update count */ 461250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accnext--; /* ready for next */ 461350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (accdigits>reqdigits) break; /* have enough digits */ 461450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 461550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 461650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if the residue is zero, the operation is done (unless divide */ 461750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* or divideInteger and still not enough digits yet) */ 461850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*var1==0 && var1units==1) { /* residue is 0 */ 461950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&(REMAINDER|REMNEAR)) break; 462050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((op&DIVIDE) && (exponent<=maxexponent)) break; 462150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [drop through if divideInteger] */ 462250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 462350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* also done enough if calculating remainder or integer */ 462450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* divide and just did the last ('units') unit */ 462550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exponent==0 && !(op&DIVIDE)) break; 462650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 462750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* to get here, var1 is less than var2, so divide var2 by the per- */ 462850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Unit power of ten and go for the next digit */ 462950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var2ulen--; /* shift down */ 463050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent-=DECDPUN; /* update the exponent */ 463150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* outer loop */ 463250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 463350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* ---- division is complete --------------------------------------- */ 463450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here: acc has at least reqdigits+1 of good results (or fewer */ 463550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if early stop), starting at accnext+1 (its lsu) */ 463650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* var1 has any residue at the stopping point */ 463750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accunits is the number of digits collected in acc */ 463850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (accunits==0) { /* acc is 0 */ 463950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=1; /* show have a unit .. */ 464050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accdigits=1; /* .. */ 464150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *accnext=0; /* .. whose value is 0 */ 464250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 464350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else accnext++; /* back to last placed */ 464450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accnext now -> lowest unit of result */ 464550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 464650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* assume no residue */ 464750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&DIVIDE) { 464850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* record the presence of any residue, for rounding */ 464950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*var1!=0 || var1units>1) residue=1; 465050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* no residue */ 465150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Had an exact division; clean up spurious trailing 0s. */ 465250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* There will be at most DECDPUN-1, from the final multiply, */ 465350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* and then only if the result is non-0 (and even) and the */ 465450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* exponent is 'loose'. */ 465550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>1 465650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit lsu=*accnext; 465750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(lsu&0x01) && (lsu!=0)) { 465850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* count the trailing zeros */ 465950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int drop=0; 466050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;; drop++) { /* [will terminate because lsu!=0] */ 466150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exponent>=maxexponent) break; /* don't chop real 0s */ 466250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 466350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((lsu-QUOT10(lsu, drop+1) 466450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *powers[drop+1])!=0) break; /* found non-0 digit */ 466550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 466650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lsu%powers[drop+1]!=0) break; /* found non-0 digit */ 466750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 466850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent++; 466950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 467050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (drop>0) { 467150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=decShiftToLeast(accnext, accunits, drop); 467250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accdigits=decGetDigits(accnext, accunits); 467350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=D2U(accdigits); 467450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [exponent was adjusted in the loop] */ 467550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 467650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* neither odd nor 0 */ 467750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 467850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* exact divide */ 467950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* divide */ 468050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else /* op!=DIVIDE */ { 468150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* check for coefficient overflow */ 468250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (accdigits+exponent>reqdigits) { 468350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Division_impossible; 468450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 468550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 468650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op & (REMAINDER|REMNEAR)) { 468750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [Here, the exponent will be 0, because var1 was adjusted */ 468850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* appropriately.] */ 468950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int postshift; /* work */ 469050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag wasodd=0; /* integer was odd */ 469150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *quotlsu; /* for save */ 469250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int quotdigits; /* .. */ 469350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 469450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=lhs->bits; /* remainder sign is always as lhs */ 469550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 469650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Fastpath when residue is truly 0 is worthwhile [and */ 469750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* simplifies the code below] */ 469850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*var1==0 && var1units==1) { /* residue is 0 */ 469950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int exp=lhs->exponent; /* save min(exponents) */ 470050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->exponent<exp) exp=rhs->exponent; 470150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* 0 coefficient */ 470250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 470350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->extended) 470450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 470550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=exp; /* .. with proper exponent */ 470650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=(uByte)(bits&DECNEG); /* [cleaned] */ 470750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* might clamp */ 470850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 470950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 471050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* note if the quotient was odd */ 471150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*accnext & 0x01) wasodd=1; /* acc is odd */ 471250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quotlsu=accnext; /* save in case need to reinspect */ 471350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quotdigits=accdigits; /* .. */ 471450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 471550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* treat the residue, in var1, as the value to return, via acc */ 471650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the unused zero digits. This is the smaller of: */ 471750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* var1 initial padding (saved above) */ 471850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* var2 residual padding, which happens to be given by: */ 471950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho postshift=var1initpad+exponent-lhs->exponent+rhs->exponent; 472050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [the 'exponent' term accounts for the shifts during divide] */ 472150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (var1initpad<postshift) postshift=var1initpad; 472250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 472350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* shift var1 the requested amount, and adjust its digits */ 472450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var1units=decShiftToLeast(var1, var1units, postshift); 472550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accnext=var1; 472650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accdigits=decGetDigits(var1, var1units); 472750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=D2U(accdigits); 472850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 472950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent=lhs->exponent; /* exponent is smaller of lhs & rhs */ 473050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->exponent<exponent) exponent=rhs->exponent; 473150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 473250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Now correct the result if doing remainderNear; if it */ 473350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (looking just at coefficients) is > rhs/2, or == rhs/2 and */ 473450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the integer was odd then the result should be rem-rhs. */ 473550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&REMNEAR) { 473650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int compare, tarunits; /* work */ 473750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up; /* .. */ 473850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate remainder*2 into the var1 buffer (which has */ 473950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 'headroom' of an extra unit and hence enough space) */ 474050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [a dedicated 'double' loop would be faster, here] */ 474150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tarunits=decUnitAddSub(accnext, accunits, accnext, accunits, 474250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0, accnext, 1); 474350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decDumpAr('r', accnext, tarunits); */ 474450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 474550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Here, accnext (var1) holds tarunits Units with twice the */ 474650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* remainder's coefficient, which must now be compared to the */ 474750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* RHS. The remainder's exponent may be smaller than the RHS's. */ 474850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho compare=decUnitCompare(accnext, tarunits, rhs->lsu, D2U(rhs->digits), 474950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs->exponent-exponent); 475050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (compare==BADINT) { /* deep trouble */ 475150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 475250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 475350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 475450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now restore the remainder by dividing by two; the lsu */ 475550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is known to be even. */ 475650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=accnext; up<accnext+tarunits; up++) { 475750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int half; /* half to add to lower unit */ 475850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho half=*up & 0x01; 475950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up/=2; /* [shift] */ 476050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!half) continue; 476150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *(up-1)+=(DECDPUNMAX+1)/2; 476250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 476350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [accunits still describes the original remainder length] */ 476450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 476550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (compare>0 || (compare==0 && wasodd)) { /* adjustment needed */ 476650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int exp, expunits, exprem; /* work */ 476750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This is effectively causing round-up of the quotient, */ 476850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* so if it was the rare case where it was full and all */ 476950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* nines, it would overflow and hence division-impossible */ 477050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* should be raised */ 477150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag allnines=0; /* 1 if quotient all nines */ 477250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (quotdigits==reqdigits) { /* could be borderline */ 477350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=quotlsu; ; up++) { 477450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (quotdigits>DECDPUN) { 477550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=DECDPUNMAX) break;/* non-nines */ 477650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 477750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* this is the last Unit */ 477850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up==powers[quotdigits]-1) allnines=1; 477950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 478050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 478150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quotdigits-=DECDPUN; /* checked those digits */ 478250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* up */ 478350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* borderline check */ 478450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allnines) { 478550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Division_impossible; 478650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 478750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 478850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rem-rhs is needed; the sign will invert. Again, var1 */ 478950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* can safely be used for the working Units array. */ 479050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exp=rhs->exponent-exponent; /* RHS padding needed */ 479150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Calculate units and remainder from exponent. */ 479250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho expunits=exp/DECDPUN; 479350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exprem=exp%DECDPUN; 479450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subtract [A+B*(-m)]; the result will always be negative */ 479550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=-decUnitAddSub(accnext, accunits, 479650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs->lsu, D2U(rhs->digits), 479750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho expunits, accnext, -(Int)powers[exprem]); 479850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accdigits=decGetDigits(accnext, accunits); /* count digits exactly */ 479950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=D2U(accdigits); /* and recalculate the units for copy */ 480050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [exponent is as for original remainder] */ 480150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits^=DECNEG; /* flip the sign */ 480250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 480350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* REMNEAR */ 480450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* REMAINDER or REMNEAR */ 480550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* not DIVIDE */ 480650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 480750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Set exponent and bits */ 480850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=exponent; 480950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=(uByte)(bits&DECNEG); /* [cleaned] */ 481050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 481150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Now the coefficient. */ 481250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetCoeff(res, set, accnext, accdigits, &residue, status); 481350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 481450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* final cleanup */ 481550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 481650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 481750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If a divide then strip trailing zeros if subset [after round] */ 481850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended && (op==DIVIDE)) decTrim(res, set, 0, 1, &dropped); 481950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 482050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 482150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 482250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (varalloc!=NULL) free(varalloc); /* drop any storage used */ 482350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc!=NULL) free(allocacc); /* .. */ 482450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 482550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs!=NULL) free(allocrhs); /* .. */ 482650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs!=NULL) free(alloclhs); /* .. */ 482750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 482850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 482950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decDivideOp */ 483050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 483150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 483250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decMultiplyOp -- multiplication operation */ 483350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 483450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine performs the multiplication C=A x B. */ 483550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 483650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X*X) */ 483750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 483850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 483950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 484050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the usual accumulator */ 484150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 484250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 484350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 484450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 484550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 'Classic' multiplication is used rather than Karatsuba, as the */ 484650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* latter would give only a minor improvement for the short numbers */ 484750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* expected to be handled most (and uses much more memory). */ 484850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 484950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* There are two major paths here: the general-purpose ('old code') */ 485050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* path which handles all DECDPUN values, and a fastpath version */ 485150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* which is used if 64-bit ints are available, DECDPUN<=4, and more */ 485250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* than two calls to decUnitAddSub would be made. */ 485350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 485450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The fastpath version lumps units together into 8-digit or 9-digit */ 485550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* chunks, and also uses a lazy carry strategy to minimise expensive */ 485650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 64-bit divisions. The chunks are then broken apart again into */ 485750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* units for continuing processing. Despite this overhead, the */ 485850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* fastpath can speed up some 16-digit operations by 10x (and much */ 485950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* more for higher-precision calculations). */ 486050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 486150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A buffer always has to be used for the accumulator; in the */ 486250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* fastpath, buffers are also always needed for the chunked copies of */ 486350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of the operand coefficients. */ 486450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Static buffers are larger than needed just for multiply, to allow */ 486550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* for calls from other operations (notably exp). */ 486650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 486750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define FASTMUL (DECUSE64 && DECDPUN<5) 486850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decMultiplyOp(decNumber *res, const decNumber *lhs, 486950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set, 487050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 487150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int accunits; /* Units of accumulator in use */ 487250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int exponent; /* work */ 487350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* rounding residue */ 487450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte bits; /* result sign */ 487550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *acc; /* -> accumulator Unit array */ 487650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int needbytes; /* size calculator */ 487750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho void *allocacc=NULL; /* -> allocated accumulator, iff allocated */ 487850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit accbuff[SD2U(DECBUFFER*4+1)]; /* buffer (+1 for DECBUFFER==0, */ 487950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* *4 for calls from other operations) */ 488050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *mer, *mermsup; /* work */ 488150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int madlength; /* Units in multiplicand */ 488250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift; /* Units to shift multiplicand by */ 488350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 488450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if FASTMUL 488550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if DECDPUN is 1 or 3 work in base 10**9, otherwise */ 488650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (DECDPUN is 2 or 4) then work in base 10**8 */ 488750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN & 1 /* odd */ 488850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define FASTBASE 1000000000 /* base */ 488950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define FASTDIGS 9 /* digits in base */ 489050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define FASTLAZY 18 /* carry resolution point [1->18] */ 489150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 489250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define FASTBASE 100000000 489350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define FASTDIGS 8 489450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define FASTLAZY 1844 /* carry resolution point [1->1844] */ 489550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 489650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* three buffers are used, two for chunked copies of the operands */ 489750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (base 10**8 or base 10**9) and one base 2**64 accumulator with */ 489850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lazy carry evaluation */ 489950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt zlhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */ 490050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *zlhi=zlhibuff; /* -> lhs array */ 490150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *alloclhi=NULL; /* -> allocated buffer, iff allocated */ 490250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt zrhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */ 490350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *zrhi=zrhibuff; /* -> rhs array */ 490450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *allocrhi=NULL; /* -> allocated buffer, iff allocated */ 490550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uLong zaccbuff[(DECBUFFER*2+1)/4+2]; /* buffer (+1 for DECBUFFER==0) */ 490650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [allocacc is shared for both paths, as only one will run] */ 490750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uLong *zacc=zaccbuff; /* -> accumulator array for exact result */ 490850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==1 490950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int zoff; /* accumulator offset */ 491050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 491150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *lip, *rip; /* item pointers */ 491250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *lmsi, *rmsi; /* most significant items */ 491350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ilhs, irhs, iacc; /* item counts in the arrays */ 491450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int lazy; /* lazy carry counter */ 491550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uLong lcarry; /* uLong carry */ 491650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt carry; /* carry (NB not uLong) */ 491750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int count; /* work */ 491850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *cup; /* .. */ 491950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up; /* .. */ 492050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uLong *lp; /* .. */ 492150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int p; /* .. */ 492250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 492350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 492450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 492550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *alloclhs=NULL; /* -> allocated buffer, iff allocated */ 492650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* -> allocated buffer, iff allocated */ 492750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 492850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 492950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 493050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 493150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 493250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 493350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* precalculate result sign */ 493450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=(uByte)((lhs->bits^rhs->bits)&DECNEG); 493550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 493650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle infinities and NaNs */ 493750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS) { /* a special bit set */ 493850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */ 493950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, status); 494050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res;} 494150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* one or two infinities; Infinity * 0 is invalid */ 494250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (((lhs->bits & DECINF)==0 && ISZERO(lhs)) 494350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ||((rhs->bits & DECINF)==0 && ISZERO(rhs))) { 494450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 494550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res;} 494650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 494750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits|DECINF; /* infinity */ 494850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res;} 494950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 495050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* For best speed, as in DMSRCN [the original Rexx numerics */ 495150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* module], use the shorter number as the multiplier (rhs) and */ 495250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the longer as the multiplicand (lhs) to minimise the number of */ 495350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* adds (partial products) */ 495450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits<rhs->digits) { /* swap... */ 495550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *hold=lhs; 495650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=rhs; 495750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=hold; 495850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 495950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 496050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 496150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 496250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 496350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operands and set lostDigits status, as needed */ 496450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>set->digits) { 496550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloclhs=decRoundOperand(lhs, set, status); 496650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs==NULL) break; 496750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=alloclhs; 496850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 496950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>set->digits) { 497050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, status); 497150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 497250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 497350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 497450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 497550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 497650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 497750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 497850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if FASTMUL /* fastpath can be used */ 497950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* use the fast path if there are enough digits in the shorter */ 498050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* operand to make the setup and takedown worthwhile */ 498150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define NEEDTWO (DECDPUN*2) /* within two decUnitAddSub calls */ 498250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>NEEDTWO) { /* use fastpath... */ 498350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the number of elements in each array */ 498450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ilhs=(lhs->digits+FASTDIGS-1)/FASTDIGS; /* [ceiling] */ 498550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho irhs=(rhs->digits+FASTDIGS-1)/FASTDIGS; /* .. */ 498650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho iacc=ilhs+irhs; 498750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 498850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* allocate buffers if required, as usual */ 498950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=ilhs*sizeof(uInt); 499050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>(Int)sizeof(zlhibuff)) { 499150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloclhi=(uInt *)malloc(needbytes); 499250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho zlhi=alloclhi;} 499350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=irhs*sizeof(uInt); 499450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>(Int)sizeof(zrhibuff)) { 499550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhi=(uInt *)malloc(needbytes); 499650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho zrhi=allocrhi;} 499750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 499850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Allocating the accumulator space needs a special case when */ 499950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* DECDPUN=1 because when converting the accumulator to Units */ 500050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* after the multiplication each 8-byte item becomes 9 1-byte */ 500150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* units. Therefore iacc extra bytes are needed at the front */ 500250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (rounded up to a multiple of 8 bytes), and the uLong */ 500350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accumulator starts offset the appropriate number of units */ 500450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* to the right to avoid overwrite during the unchunking. */ 5005103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 5006103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius /* Make sure no signed int overflow below. This is always true */ 5007103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius /* if the given numbers have less digits than DEC_MAX_DIGITS. */ 5008103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius U_ASSERT(iacc <= INT32_MAX/sizeof(uLong)); 500950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=iacc*sizeof(uLong); 501050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==1 501150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho zoff=(iacc+7)/8; /* items to offset by */ 501250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes+=zoff*8; 501350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 501450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>(Int)sizeof(zaccbuff)) { 501550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocacc=(uLong *)malloc(needbytes); 501650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho zacc=(uLong *)allocacc;} 501750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (zlhi==NULL||zrhi==NULL||zacc==NULL) { 501850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 501950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 502050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 502150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=(Unit *)zacc; /* -> target Unit array */ 502250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==1 502350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho zacc+=zoff; /* start uLong accumulator to right */ 502450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 502550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 502650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* assemble the chunked copies of the left and right sides */ 502750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (count=lhs->digits, cup=lhs->lsu, lip=zlhi; count>0; lip++) 502850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (p=0, *lip=0; p<FASTDIGS && count>0; 502950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p+=DECDPUN, cup++, count-=DECDPUN) 503050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *lip+=*cup*powers[p]; 503150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lmsi=lip-1; /* save -> msi */ 503250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (count=rhs->digits, cup=rhs->lsu, rip=zrhi; count>0; rip++) 503350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (p=0, *rip=0; p<FASTDIGS && count>0; 503450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p+=DECDPUN, cup++, count-=DECDPUN) 503550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *rip+=*cup*powers[p]; 503650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rmsi=rip-1; /* save -> msi */ 503750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 503850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* zero the accumulator */ 503950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (lp=zacc; lp<zacc+iacc; lp++) *lp=0; 504050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 504150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Start the multiplication */ 504250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Resolving carries can dominate the cost of accumulating the */ 504350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* partial products, so this is only done when necessary. */ 504450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Each uLong item in the accumulator can hold values up to */ 504550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 2**64-1, and each partial product can be as large as */ 504650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (10**FASTDIGS-1)**2. When FASTDIGS=9, this can be added to */ 504750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* itself 18.4 times in a uLong without overflowing, so during */ 504850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the main calculation resolution is carried out every 18th */ 504950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* add -- every 162 digits. Similarly, when FASTDIGS=8, the */ 505050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* partial products can be added to themselves 1844.6 times in */ 505150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a uLong without overflowing, so intermediate carry */ 505250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* resolution occurs only every 14752 digits. Hence for common */ 505350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* short numbers usually only the one final carry resolution */ 505450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* occurs. */ 505550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (The count is set via FASTLAZY to simplify experiments to */ 505650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* measure the value of this approach: a 35% improvement on a */ 505750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [34x34] multiply.) */ 505850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lazy=FASTLAZY; /* carry delay count */ 505950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (rip=zrhi; rip<=rmsi; rip++) { /* over each item in rhs */ 506050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lp=zacc+(rip-zrhi); /* where to add the lhs */ 506150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (lip=zlhi; lip<=lmsi; lip++, lp++) { /* over each item in lhs */ 506250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *lp+=(uLong)(*lip)*(*rip); /* [this should in-line] */ 506350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* lip loop */ 506450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lazy--; 506550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lazy>0 && rip!=rmsi) continue; 506650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lazy=FASTLAZY; /* reset delay count */ 506750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* spin up the accumulator resolving overflows */ 506850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (lp=zacc; lp<zacc+iacc; lp++) { 506950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*lp<FASTBASE) continue; /* it fits */ 507050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lcarry=*lp/FASTBASE; /* top part [slow divide] */ 507150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lcarry can exceed 2**32-1, so check again; this check */ 507250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* and occasional extra divide (slow) is well worth it, as */ 507350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it allows FASTLAZY to be increased to 18 rather than 4 */ 507450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* in the FASTDIGS=9 case */ 507550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lcarry<FASTBASE) carry=(uInt)lcarry; /* [usual] */ 507650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* two-place carry [fairly rare] */ 507750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt carry2=(uInt)(lcarry/FASTBASE); /* top top part */ 507850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *(lp+2)+=carry2; /* add to item+2 */ 507950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *lp-=((uLong)FASTBASE*FASTBASE*carry2); /* [slow] */ 508050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=(uInt)(lcarry-((uLong)FASTBASE*carry2)); /* [inline] */ 508150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 508250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *(lp+1)+=carry; /* add to item above [inline] */ 508350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *lp-=((uLong)FASTBASE*carry); /* [inline] */ 508450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* carry resolution */ 508550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* rip loop */ 508650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 508750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The multiplication is complete; time to convert back into */ 508850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* units. This can be done in-place in the accumulator and in */ 508950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 32-bit operations, because carries were resolved after the */ 509050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* final add. This needs N-1 divides and multiplies for */ 509150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* each item in the accumulator (which will become up to N */ 509250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* units, where 2<=N<=9). */ 509350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (lp=zacc, up=acc; lp<zacc+iacc; lp++) { 509450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt item=(uInt)*lp; /* decapitate to uInt */ 509550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (p=0; p<FASTDIGS-DECDPUN; p+=DECDPUN, up++) { 509650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt part=item/(DECDPUNMAX+1); 509750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)(item-(part*(DECDPUNMAX+1))); 509850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho item=part; 509950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* p */ 510050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)item; up++; /* [final needs no division] */ 510150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* lp */ 510250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=up-acc; /* count of units */ 510350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 510450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* here to use units directly, without chunking ['old code'] */ 510550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 510650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 510750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if accumulator will be too long for local storage, then allocate */ 510850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=accbuff; /* -> assume buffer for accumulator */ 510950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=(D2U(lhs->digits)+D2U(rhs->digits))*sizeof(Unit); 511050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>(Int)sizeof(accbuff)) { 511150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocacc=(Unit *)malloc(needbytes); 511250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc==NULL) {*status|=DEC_Insufficient_storage; break;} 511350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=(Unit *)allocacc; /* use the allocated space */ 511450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 511550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 511650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Now the main long multiplication loop */ 511750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Unlike the equivalent in the IBM Java implementation, there */ 511850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is no advantage in calculating from msu to lsu. So, do it */ 511950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* by the book, as it were. */ 512050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Each iteration calculates ACC=ACC+MULTAND*MULT */ 512150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=1; /* accumulator starts at '0' */ 512250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *acc=0; /* .. (lsu=0) */ 512350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho shift=0; /* no multiplicand shift at first */ 512450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho madlength=D2U(lhs->digits); /* this won't change */ 512550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mermsup=rhs->lsu+D2U(rhs->digits); /* -> msu+1 of multiplier */ 512650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 512750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (mer=rhs->lsu; mer<mermsup; mer++) { 512850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Here, *mer is the next Unit in the multiplier to use */ 512950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If non-zero [optimization] add it... */ 513050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*mer!=0) accunits=decUnitAddSub(&acc[shift], accunits-shift, 513150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs->lsu, madlength, 0, 513250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho &acc[shift], *mer) 513350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho + shift; 513450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* extend acc with a 0; it will be used shortly */ 513550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *(acc+accunits)=0; /* [this avoids length of <=0 later] */ 513650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits++; 513750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 513850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* multiply multiplicand by 10**DECDPUN for next Unit to left */ 513950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho shift++; /* add this for 'logical length' */ 514050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* n */ 514150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if FASTMUL 514250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* unchunked units */ 514350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 514450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* common end-path */ 514550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 514650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('*', acc, accunits); /* Show exact result */ 514750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 514850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 514950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* acc now contains the exact result of the multiplication, */ 515050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* possibly with a leading zero unit; build the decNumber from */ 515150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it, noting if any residue */ 515250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; /* set sign */ 515350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(acc, accunits); /* count digits exactly */ 515450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 515550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* There can be a 31-bit wrap in calculating the exponent. */ 515650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This can only happen if both input exponents are negative and */ 515750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* both their magnitudes are large. If there was a wrap, set a */ 515850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* safe very negative exponent, from which decFinalize() will */ 515950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* raise a hard underflow shortly. */ 516050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent=lhs->exponent+rhs->exponent; /* calculate exponent */ 516150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent<0 && rhs->exponent<0 && exponent>0) 516250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent=-2*DECNUMMAXE; /* force underflow */ 516350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=exponent; /* OK to overwrite now */ 516450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 516550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 516650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Set the coefficient. If any rounding, residue records */ 516750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetCoeff(res, set, acc, res->digits, &residue, status); 516850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* final cleanup */ 516950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 517050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 517150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc!=NULL) free(allocacc); /* drop any storage used */ 517250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 517350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs!=NULL) free(allocrhs); /* .. */ 517450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs!=NULL) free(alloclhs); /* .. */ 517550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 517650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if FASTMUL 517750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhi!=NULL) free(allocrhi); /* .. */ 517850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhi!=NULL) free(alloclhi); /* .. */ 517950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 518050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 518150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decMultiplyOp */ 518250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 518350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 518450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decExpOp -- effect exponentiation */ 518550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 518650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = exp(A) */ 518750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 518850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 518950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 519050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context; note that rounding mode has no effect */ 519150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 519250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. status is updated but */ 519350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* not set. */ 519450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 519550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Restrictions: */ 519650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 519750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* digits, emax, and -emin in the context must be less than */ 519850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 2*DEC_MAX_MATH (1999998), and the rhs must be within these */ 519950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* bounds or a zero. This is an internal routine, so these */ 520050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* restrictions are contractual and not enforced. */ 520150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 520250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */ 520350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* almost always be correctly rounded, but may be up to 1 ulp in */ 520450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* error in rare cases. */ 520550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 520650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Finite results will always be full precision and Inexact, except */ 520750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* when A is a zero or -Infinity (giving 1 or 0 respectively). */ 520850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 520950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This approach used here is similar to the algorithm described in */ 521050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 521150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Variable Precision Exponential Function, T. E. Hull and */ 521250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A. Abrham, ACM Transactions on Mathematical Software, Vol 12 #2, */ 521350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* pp79-91, ACM, June 1986. */ 521450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 521550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* with the main difference being that the iterations in the series */ 521650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* evaluation are terminated dynamically (which does not require the */ 521750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* extra variable-precision variables which are expensive in this */ 521850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* context). */ 521950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 522050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The error analysis in Hull & Abrham's paper applies except for the */ 522150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* round-off error accumulation during the series evaluation. This */ 522250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* code does not precalculate the number of iterations and so cannot */ 522350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* use Horner's scheme. Instead, the accumulation is done at double- */ 522450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* precision, which ensures that the additions of the terms are exact */ 522550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and do not accumulate round-off (and any round-off errors in the */ 522650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* terms themselves move 'to the right' faster than they can */ 522750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* accumulate). This code also extends the calculation by allowing, */ 522850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* in the spirit of other decNumber operators, the input to be more */ 522950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* precise than the result (the precision used is based on the more */ 523050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* precise of the input or requested result). */ 523150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 523250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Implementation notes: */ 523350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 523450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 1. This is separated out as decExpOp so it can be called from */ 523550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* other Mathematical functions (notably Ln) with a wider range */ 523650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* than normal. In particular, it can handle the slightly wider */ 523750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (double) range needed by Ln (which has to be able to calculate */ 523850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* exp(-x) where x can be the tiniest number (Ntiny). */ 523950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 524050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 2. Normalizing x to be <=0.1 (instead of <=1) reduces loop */ 524150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* iterations by appoximately a third with additional (although */ 524250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* diminishing) returns as the range is reduced to even smaller */ 524350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* fractions. However, h (the power of 10 used to correct the */ 524450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* result at the end, see below) must be kept <=8 as otherwise */ 524550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the final result cannot be computed. Hence the leverage is a */ 524650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* sliding value (8-h), where potentially the range is reduced */ 524750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* more for smaller values. */ 524850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 524950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The leverage that can be applied in this way is severely */ 525050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* limited by the cost of the raise-to-the power at the end, */ 525150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* which dominates when the number of iterations is small (less */ 525250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* than ten) or when rhs is short. As an example, the adjustment */ 525350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* x**10,000,000 needs 31 multiplications, all but one full-width. */ 525450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 525550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 3. The restrictions (especially precision) could be raised with */ 525650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* care, but the full decNumber range seems very hard within the */ 525750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 32-bit limits. */ 525850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 525950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 4. The working precisions for the static buffers are twice the */ 526050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* obvious size to allow for calls from decNumberPower. */ 526150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 526250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehodecNumber * decExpOp(decNumber *res, const decNumber *rhs, 526350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set, uInt *status) { 526450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt ignore=0; /* working status */ 526550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int h; /* adjusted exponent for 0.xxxx */ 526650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int p; /* working precision */ 526750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue; /* rounding residue */ 526850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt needbytes; /* for space calculations */ 526950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *x=rhs; /* (may point to safe copy later) */ 527050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext aset, tset, dset; /* working contexts */ 527150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int comp; /* work */ 527250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 527350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the argument is often copied to normalize it, so (unusually) it */ 527450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is treated like other buffers, using DECBUFFER, +1 in case */ 527550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* DECBUFFER is 0 */ 527650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufr[D2N(DECBUFFER*2+1)]; 527750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* non-NULL if rhs buffer allocated */ 527850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 527950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the working precision will be no more than set->digits+8+1 */ 528050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* so for on-stack buffers DECBUFFER+9 is used, +1 in case DECBUFFER */ 528150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is 0 (and twice that for the accumulator) */ 528250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 528350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffer for t, term (working precision plus) */ 528450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber buft[D2N(DECBUFFER*2+9+1)]; 528550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbuft=NULL; /* -> allocated buft, iff allocated */ 528650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *t=buft; /* term */ 528750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffer for a, accumulator (working precision * 2), at least 9 */ 528850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufa[D2N(DECBUFFER*4+18+1)]; 528950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ 529050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *a=bufa; /* accumulator */ 529150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decNumber for the divisor term; this needs at most 9 digits */ 529250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* and so can be fixed size [16 so can use standard context] */ 529350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufd[D2N(16)]; 529450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *d=bufd; /* divisor */ 529550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber numone; /* constant 1 */ 529650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 529750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 529850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int iterations=0; /* for later sanity check */ 529950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 530050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 530150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 530250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 530350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARG) { /* handle infinities and NaNs */ 530450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs)) { /* an infinity */ 530550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) /* -Infinity -> +0 */ 530650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 530750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else uprv_decNumberCopy(res, rhs); /* +Infinity -> self */ 530850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 530950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else decNaNs(res, rhs, NULL, set, status); /* a NaN */ 531050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 531150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 531250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) { /* zeros -> exact 1 */ 531350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* make clean 1 */ 531450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=1; /* .. */ 531550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* [no status to set] */ 531650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 531750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* e**x when 0 < x < 0.66 is < 1+3x/2, hence can fast-path */ 531850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* positive and negative tiny cases which will result in inexact */ 531950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1. This also allows the later add-accumulate to always be */ 532050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* exact (because its length will never be more than twice the */ 532150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* working precision). */ 532250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The comparator (tiny) needs just one digit, so use the */ 532350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decNumber d for it (reused as the divisor, etc., below); its */ 532450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* exponent is such that if x is positive it will have */ 532550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set->digits-1 zeros between the decimal point and the digit, */ 532650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* which is 4, and if x is negative one more zero there as the */ 532750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* more precise result will be of the form 0.9999999 rather than */ 532850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1.0000001. Hence, tiny will be 0.0000004 if digits=7 and x>0 */ 532950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* or 0.00000004 if digits=7 and x<0. If RHS not larger than */ 533050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this then the result will be 1.000000 */ 533150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(d); /* clean */ 533250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *d->lsu=4; /* set 4 .. */ 533350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho d->exponent=-set->digits; /* * 10**(-d) */ 533450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) d->exponent--; /* negative case */ 533550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho comp=decCompare(d, rhs, 1); /* signless compare */ 533650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (comp==BADINT) { 533750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 533850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 533950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (comp>=0) { /* rhs < d */ 534050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift=set->digits-1; 534150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* set 1 */ 534250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=1; /* .. */ 534350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, 1, shift); 534450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=-shift; /* make 1.0000... */ 534550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Inexact | DEC_Rounded; /* .. inexactly */ 534650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* tiny */ 534750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 534850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set up the context to be used for calculating a, as this is */ 534950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* used on both paths below */ 535050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&aset, DEC_INIT_DECIMAL64); 535150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accumulator bounds are as requested (could underflow) */ 535250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emax=set->emax; /* usual bounds */ 535350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emin=set->emin; /* .. */ 535450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.clamp=0; /* and no concrete format */ 535550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 535650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the adjusted (Hull & Abrham) exponent (where the */ 535750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decimal point is just to the left of the coefficient msd) */ 535850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho h=rhs->exponent+rhs->digits; 535950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if h>8 then 10**h cannot be calculated safely; however, when */ 536050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* h=8 then exp(|rhs|) will be at least exp(1E+7) which is at */ 536150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* least 6.59E+4342944, so (due to the restriction on Emax/Emin) */ 536250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* overflow (or underflow to 0) is guaranteed -- so this case can */ 536350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* be handled by simply forcing the appropriate excess */ 536450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (h>8) { /* overflow/underflow */ 536550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set up here so Power call below will over or underflow to */ 536650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* zero; set accumulator to either 2 or 0.02 */ 536750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [stack buffer for a is always big enough for this] */ 536850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(a); 536950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *a->lsu=2; /* not 1 but < exp(1) */ 537050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) a->exponent=-2; /* make 0.02 */ 537150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho h=8; /* clamp so 10**h computable */ 537250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p=9; /* set a working precision */ 537350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 537450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* h<=8 */ 537550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxlever=(rhs->digits>8?1:0); 537650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [could/should increase this for precisions >40 or so, too] */ 537750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 537850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if h is 8, cannot normalize to a lower upper limit because */ 537950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the final result will not be computable (see notes above), */ 538050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* but leverage can be applied whenever h is less than 8. */ 538150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Apply as much as possible, up to a MAXLEVER digits, which */ 538250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* sets the tradeoff against the cost of the later a**(10**h). */ 538350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* As h is increased, the working precision below also */ 538450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* increases to compensate for the "constant digits at the */ 538550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* front" effect. */ 538650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int lever=MINI(8-h, maxlever); /* leverage attainable */ 538750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int use=-rhs->digits-lever; /* exponent to use for RHS */ 538850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho h+=lever; /* apply leverage selected */ 538950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (h<0) { /* clamp */ 539050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho use+=h; /* [may end up subnormal] */ 539150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho h=0; 539250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 539350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Take a copy of RHS if it needs normalization (true whenever x>=1) */ 539450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->exponent!=use) { 539550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *newrhs=bufr; /* assume will fit on stack */ 539650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit); 539750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufr)) { /* need malloc space */ 539850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=(decNumber *)malloc(needbytes); 539950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) { /* hopeless -- abandon */ 540050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 540150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 540250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho newrhs=allocrhs; /* use the allocated space */ 540350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 540450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(newrhs, rhs); /* copy to safe space */ 540550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho newrhs->exponent=use; /* normalize; now <1 */ 540650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho x=newrhs; /* ready for use */ 540750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decNumberShow(x); */ 540850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 540950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 541050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Now use the usual power series to evaluate exp(x). The */ 541150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* series starts as 1 + x + x^2/2 ... so prime ready for the */ 541250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* third term by setting the term variable t=x, the accumulator */ 541350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a=1, and the divisor d=2. */ 541450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 541550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* First determine the working precision. From Hull & Abrham */ 541650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this is set->digits+h+2. However, if x is 'over-precise' we */ 541750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* need to allow for all its digits to potentially participate */ 541850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (consider an x where all the excess digits are 9s) so in */ 541950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this case use x->digits+h+2 */ 542050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p=MAXI(x->digits, set->digits)+h+2; /* [h<=8] */ 542150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 542250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a and t are variable precision, and depend on p, so space */ 542350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* must be allocated for them if necessary */ 542450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 542550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the accumulator needs to be able to hold 2p digits so that */ 542650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the additions on the second and subsequent iterations are */ 542750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* sufficiently exact. */ 542850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(p*2)-1)*sizeof(Unit); 542950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufa)) { /* need malloc space */ 543050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufa=(decNumber *)malloc(needbytes); 543150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa==NULL) { /* hopeless -- abandon */ 543250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 543350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 543450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=allocbufa; /* use the allocated space */ 543550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 543650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the term needs to be able to hold p digits (which is */ 543750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* guaranteed to be larger than x->digits, so the initial copy */ 543850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is safe); it may also be used for the raise-to-power */ 543950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculation below, which needs an extra two digits */ 544050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(p+2)-1)*sizeof(Unit); 544150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(buft)) { /* need malloc space */ 544250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbuft=(decNumber *)malloc(needbytes); 544350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbuft==NULL) { /* hopeless -- abandon */ 544450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 544550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 544650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t=allocbuft; /* use the allocated space */ 544750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 544850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 544950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(t, x); /* term=x */ 545050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(a); *a->lsu=1; /* accumulator=1 */ 545150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(d); *d->lsu=2; /* divisor=2 */ 545250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&numone); *numone.lsu=1; /* constant 1 for increment */ 545350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 545450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set up the contexts for calculating a, t, and d */ 545550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&tset, DEC_INIT_DECIMAL64); 545650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dset=tset; 545750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accumulator bounds are set above, set precision now */ 545850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=p*2; /* double */ 545950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* term bounds avoid any underflow or overflow */ 546050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tset.digits=p; 546150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tset.emin=DEC_MIN_EMIN; /* [emax is plenty] */ 546250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [dset.digits=16, etc., are sufficient] */ 546350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 546450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* finally ready to roll */ 546550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;;) { 546650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 546750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho iterations++; 546850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 546950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* only the status from the accumulation is interesting */ 547050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [but it should remain unchanged after first add] */ 547150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, a, t, &aset, 0, status); /* a=a+t */ 547250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(t, t, x, &tset, &ignore); /* t=t*x */ 547350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(t, t, d, &tset, DIVIDE, &ignore); /* t=t/d */ 547450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the iteration ends when the term cannot affect the result, */ 547550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if rounded to p digits, which is when its value is smaller */ 547650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* than the accumulator by p+1 digits. There must also be */ 547750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* full precision in a. */ 547850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (((a->digits+a->exponent)>=(t->digits+t->exponent+p+1)) 547950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && (a->digits>=p)) break; 548050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(d, d, &numone, &dset, 0, &ignore); /* d=d+1 */ 548150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* iterate */ 548250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 548350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 548450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* just a sanity check; comment out test to show always */ 548550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (iterations>p+3) 548650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Exp iterations=%ld, status=%08lx, p=%ld, d=%ld\n", 548750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (LI)iterations, (LI)*status, (LI)p, (LI)x->digits); 548850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 548950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* h<=8 */ 549050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 549150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* apply postconditioning: a=a**(10**h) -- this is calculated */ 549250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* at a slightly higher precision than Hull & Abrham suggest */ 549350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (h>0) { 549450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int seenbit=0; /* set once a 1-bit is seen */ 549550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i; /* counter */ 549650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int n=powers[h]; /* always positive */ 549750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=p+2; /* sufficient precision */ 549850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* avoid the overhead and many extra digits of decNumberPower */ 549950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* as all that is needed is the short 'multipliers' loop; here */ 550050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accumulate the answer into t */ 550150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(t); *t->lsu=1; /* acc=1 */ 550250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i=1;;i++){ /* for each bit [top bit ignored] */ 550350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* abandon if have had overflow or terminal underflow */ 550450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */ 550550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*status&DEC_Overflow || ISZERO(t)) break;} 550650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho n=n<<1; /* move next bit to testable position */ 550750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n<0) { /* top bit is set */ 550850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho seenbit=1; /* OK, have a significant bit */ 550950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(t, t, a, &aset, status); /* acc=acc*x */ 551050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 551150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (i==31) break; /* that was the last bit */ 551250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!seenbit) continue; /* no need to square 1 */ 551350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(t, t, t, &aset, status); /* acc=acc*acc [square] */ 551450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /*i*/ /* 32 bits */ 551550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decNumberShow(t); */ 551650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=t; /* and carry on using t instead of a */ 551750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 551850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 551950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Copy and round the result to res */ 552050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=1; /* indicate dirt to right .. */ 552150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(a)) residue=0; /* .. unless underflowed to 0 */ 552250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=set->digits; /* [use default rounding] */ 552350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */ 552450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* cleanup/set flags */ 552550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 552650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 552750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs !=NULL) free(allocrhs); /* drop any storage used */ 552850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa!=NULL) free(allocbufa); /* .. */ 552950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbuft!=NULL) free(allocbuft); /* .. */ 553050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [status is handled by caller] */ 553150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 553250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decExpOp */ 553350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 553450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 553550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Initial-estimate natural logarithm table */ 553650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 553750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* LNnn -- 90-entry 16-bit table for values from .10 through .99. */ 553850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The result is a 4-digit encode of the coefficient (c=the */ 553950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* top 14 bits encoding 0-9999) and a 2-digit encode of the */ 554050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* exponent (e=the bottom 2 bits encoding 0-3) */ 554150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 554250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The resulting value is given by: */ 554350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 554450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* v = -c * 10**(-e-3) */ 554550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 554650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* where e and c are extracted from entry k = LNnn[x-10] */ 554750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* where x is truncated (NB) into the range 10 through 99, */ 554850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and then c = k>>2 and e = k&3. */ 554950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 5550103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic const uShort LNnn[90]={9016, 8652, 8316, 8008, 7724, 7456, 7208, 555150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 6972, 6748, 6540, 6340, 6148, 5968, 5792, 5628, 5464, 5312, 555250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 5164, 5020, 4884, 4748, 4620, 4496, 4376, 4256, 4144, 4032, 555350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 39233, 38181, 37157, 36157, 35181, 34229, 33297, 32389, 31501, 30629, 555450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 29777, 28945, 28129, 27329, 26545, 25777, 25021, 24281, 23553, 22837, 555550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 22137, 21445, 20769, 20101, 19445, 18801, 18165, 17541, 16925, 16321, 555650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 15721, 15133, 14553, 13985, 13421, 12865, 12317, 11777, 11241, 10717, 555750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 10197, 9685, 9177, 8677, 8185, 7697, 7213, 6737, 6269, 5801, 555850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 5341, 4889, 4437, 39930, 35534, 31186, 26886, 22630, 18418, 14254, 555950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 10130, 6046, 20055}; 556050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 556150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 556250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decLnOp -- effect natural logarithm */ 556350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 556450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = ln(A) */ 556550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 556650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 556750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 556850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context; note that rounding mode has no effect */ 556950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 557050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 557150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 557250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Notable cases: */ 557350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A<0 -> Invalid */ 557450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=0 -> -Infinity (Exact) */ 557550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=+Infinity -> +Infinity (Exact) */ 557650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=1 exactly -> 0 (Exact) */ 557750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 557850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Restrictions (as for Exp): */ 557950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 558050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* digits, emax, and -emin in the context must be less than */ 558150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* DEC_MAX_MATH+11 (1000010), and the rhs must be within these */ 558250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* bounds or a zero. This is an internal routine, so these */ 558350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* restrictions are contractual and not enforced. */ 558450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 558550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */ 558650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* almost always be correctly rounded, but may be up to 1 ulp in */ 558750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* error in rare cases. */ 558850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 558950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The result is calculated using Newton's method, with each */ 559050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* iteration calculating a' = a + x * exp(-a) - 1. See, for example, */ 559150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Epperson 1989. */ 559250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 559350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The iteration ends when the adjustment x*exp(-a)-1 is tiny enough. */ 559450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This has to be calculated at the sum of the precision of x and the */ 559550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* working precision. */ 559650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 559750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Implementation notes: */ 559850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 559950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 1. This is separated out as decLnOp so it can be called from */ 560050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* other Mathematical functions (e.g., Log 10) with a wider range */ 560150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* than normal. In particular, it can handle the slightly wider */ 560250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (+9+2) range needed by a power function. */ 560350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 560450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 2. The speed of this function is about 10x slower than exp, as */ 560550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* it typically needs 4-6 iterations for short numbers, and the */ 560650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* extra precision needed adds a squaring effect, twice. */ 560750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 560850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 3. Fastpaths are included for ln(10) and ln(2), up to length 40, */ 560950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* as these are common requests. ln(10) is used by log10(x). */ 561050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 561150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 4. An iteration might be saved by widening the LNnn table, and */ 561250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* would certainly save at least one if it were made ten times */ 561350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* bigger, too (for truncated fractions 0.100 through 0.999). */ 561450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* However, for most practical evaluations, at least four or five */ 561550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* iterations will be neede -- so this would only speed up by */ 561650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 20-25% and that probably does not justify increasing the table */ 561750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* size. */ 561850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 561950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 5. The static buffers are larger than might be expected to allow */ 562050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* for calls from decNumberPower. */ 562150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 562254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406 562302c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic push 562402c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic ignored "-Warray-bounds" 562502c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#endif 562650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehodecNumber * decLnOp(decNumber *res, const decNumber *rhs, 562750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set, uInt *status) { 562850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt ignore=0; /* working status accumulator */ 562950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt needbytes; /* for space calculations */ 563050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue; /* rounding residue */ 563150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int r; /* rhs=f*10**r [see below] */ 563250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int p; /* working precision */ 563350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int pp; /* precision for iteration */ 563450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int t; /* work */ 563550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 563650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffers for a (accumulator, typically precision+2) and b */ 563750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (adjustment calculator, same size) */ 563850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufa[D2N(DECBUFFER+12)]; 563950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ 564050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *a=bufa; /* accumulator/work */ 564150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufb[D2N(DECBUFFER*2+2)]; 564250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufb=NULL; /* -> allocated bufa, iff allocated */ 564350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *b=bufb; /* adjustment/work */ 564450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 564550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber numone; /* constant 1 */ 564650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber cmp; /* work */ 564750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext aset, bset; /* working contexts */ 564850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 564950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 565050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int iterations=0; /* for later sanity check */ 565150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 565250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 565350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 565450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 565550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARG) { /* handle infinities and NaNs */ 565650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs)) { /* an infinity */ 565750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) /* -Infinity -> error */ 565850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 565950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else uprv_decNumberCopy(res, rhs); /* +Infinity -> self */ 566050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 566150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else decNaNs(res, rhs, NULL, set, status); /* a NaN */ 566250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 566350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 566450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) { /* +/- zeros -> -Infinity */ 566550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* make clean */ 566650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=DECINF|DECNEG; /* set - infinity */ 566750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* [no status to set] */ 566850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 566950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Non-zero negatives are bad... */ 567050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) { /* -x -> error */ 567150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 567250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 567350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 567450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Here, rhs is positive, finite, and in range */ 567550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 567650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lookaside fastpath code for ln(2) and ln(10) at common lengths */ 567750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->exponent==0 && set->digits<=40) { 567850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==1 567950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->lsu[0]==0 && rhs->lsu[1]==1 && rhs->digits==2) { /* ln(10) */ 568050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 568150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->lsu[0]==10 && rhs->digits==2) { /* ln(10) */ 568250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 568350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset=*set; aset.round=DEC_ROUND_HALF_EVEN; 568450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define LN10 "2.302585092994045684017991454684364207601" 568550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromString(res, LN10, &aset); 568650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=(DEC_Inexact | DEC_Rounded); /* is inexact */ 568750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 568850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->lsu[0]==2 && rhs->digits==1) { /* ln(2) */ 568950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset=*set; aset.round=DEC_ROUND_HALF_EVEN; 569050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define LN2 "0.6931471805599453094172321214581765680755" 569150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromString(res, LN2, &aset); 569250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=(DEC_Inexact | DEC_Rounded); 569350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 569450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* integer and short */ 569550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 569650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Determine the working precision. This is normally the */ 569750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* requested precision + 2, with a minimum of 9. However, if */ 569850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the rhs is 'over-precise' then allow for all its digits to */ 569950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* potentially participate (consider an rhs where all the excess */ 570050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* digits are 9s) so in this case use rhs->digits+2. */ 570150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p=MAXI(rhs->digits, MAXI(set->digits, 7))+2; 570250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 570350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Allocate space for the accumulator and the high-precision */ 570450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* adjustment calculator, if necessary. The accumulator must */ 570550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* be able to hold p digits, and the adjustment up to */ 570650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rhs->digits+p digits. They are also made big enough for 16 */ 570750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* digits so that they can be used for calculating the initial */ 570850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* estimate. */ 570950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(MAXI(p,16))-1)*sizeof(Unit); 571050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufa)) { /* need malloc space */ 571150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufa=(decNumber *)malloc(needbytes); 571250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa==NULL) { /* hopeless -- abandon */ 571350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 571450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 571550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=allocbufa; /* use the allocated space */ 571650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 571750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pp=p+rhs->digits; 571850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(MAXI(pp,16))-1)*sizeof(Unit); 571950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufb)) { /* need malloc space */ 572050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufb=(decNumber *)malloc(needbytes); 572150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufb==NULL) { /* hopeless -- abandon */ 572250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 572350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 572450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=allocbufb; /* use the allocated space */ 572550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 572650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 572750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Prepare an initial estimate in acc. Calculate this by */ 572850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* considering the coefficient of x to be a normalized fraction, */ 572950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* f, with the decimal point at far left and multiplied by */ 573050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 10**r. Then, rhs=f*10**r and 0.1<=f<1, and */ 573150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* ln(x) = ln(f) + ln(10)*r */ 573250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Get the initial estimate for ln(f) from a small lookup */ 573350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* table (see above) indexed by the first two digits of f, */ 573450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* truncated. */ 573550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 573650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&aset, DEC_INIT_DECIMAL64); /* 16-digit extended */ 573750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho r=rhs->exponent+rhs->digits; /* 'normalised' exponent */ 573850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromInt32(a, r); /* a=r */ 573950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromInt32(b, 2302585); /* b=ln(10) (2.302585) */ 574050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b->exponent=-6; /* .. */ 574150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(a, a, b, &aset, &ignore); /* a=a*b */ 574250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now get top two digits of rhs into b by simple truncate and */ 574350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* force to integer */ 574450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* (no residue) */ 574550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=2; aset.round=DEC_ROUND_DOWN; 574650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(b, rhs, &aset, &residue, &ignore); /* copy & shorten */ 574750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b->exponent=0; /* make integer */ 574850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t=decGetInt(b); /* [cannot fail] */ 574950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (t<10) t=X10(t); /* adjust single-digit b */ 575050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t=LNnn[t-10]; /* look up ln(b) */ 575150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromInt32(b, t>>2); /* b=ln(b) coefficient */ 575250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b->exponent=-(t&3)-3; /* set exponent */ 575350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b->bits=DECNEG; /* ln(0.10)->ln(0.99) always -ve */ 575450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=16; aset.round=DEC_ROUND_HALF_EVEN; /* restore */ 575550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, a, b, &aset, 0, &ignore); /* acc=a+b */ 575650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the initial estimate is now in a, with up to 4 digits correct. */ 575750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* When rhs is at or near Nmax the estimate will be low, so we */ 575850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* will approach it from below, avoiding overflow when calling exp. */ 575950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 576050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&numone); *numone.lsu=1; /* constant 1 for adjustment */ 576150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 576250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accumulator bounds are as requested (could underflow, but */ 576350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* cannot overflow) */ 576450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emax=set->emax; 576550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emin=set->emin; 576650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.clamp=0; /* no concrete format */ 576750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set up a context to be used for the multiply and subtract */ 576850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bset=aset; 576950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bset.emax=DEC_MAX_MATH*2; /* use double bounds for the */ 577050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bset.emin=-DEC_MAX_MATH*2; /* adjustment calculation */ 577150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [see decExpOp call below] */ 577250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* for each iteration double the number of digits to calculate, */ 577350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* up to a maximum of p */ 577450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pp=9; /* initial precision */ 577550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [initially 9 as then the sequence starts 7+2, 16+2, and */ 577650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 34+2, which is ideal for standard-sized numbers] */ 577750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=pp; /* working context */ 577850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bset.digits=pp+rhs->digits; /* wider context */ 577950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;;) { /* iterate */ 578050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 578150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho iterations++; 578250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (iterations>24) break; /* consider 9 * 2**24 */ 578350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 578450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the adjustment (exp(-a)*x-1) into b. This is a */ 578550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* catastrophic subtraction but it really is the difference */ 578650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* from 1 that is of interest. */ 578750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Use the internal entry point to Exp as it allows the double */ 578850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* range for calculating exp(-a) when a is the tiniest subnormal. */ 578950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->bits^=DECNEG; /* make -a */ 579050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decExpOp(b, a, &bset, &ignore); /* b=exp(-a) */ 579150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->bits^=DECNEG; /* restore sign of a */ 579250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now multiply by rhs and subtract 1, at the wider precision */ 579350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(b, b, rhs, &bset, &ignore); /* b=b*rhs */ 579450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(b, b, &numone, &bset, DECNEG, &ignore); /* b=b-1 */ 579550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 579650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the iteration ends when the adjustment cannot affect the */ 579750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* result by >=0.5 ulp (at the requested digits), which */ 579850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is when its value is smaller than the accumulator by */ 579950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set->digits+1 digits (or it is zero) -- this is a looser */ 580050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* requirement than for Exp because all that happens to the */ 580150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accumulator after this is the final rounding (but note that */ 580250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* there must also be full precision in a, or a=0). */ 580350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 580450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(b) || 580550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (a->digits+a->exponent)>=(b->digits+b->exponent+set->digits+1)) { 580650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a->digits==p) break; 580750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(a)) { 580850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(&cmp, rhs, &numone, &aset, COMPARE, &ignore); /* rhs=1 ? */ 580950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cmp.lsu[0]==0) a->exponent=0; /* yes, exact 0 */ 581050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else *status|=(DEC_Inexact | DEC_Rounded); /* no, inexact */ 581150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 581250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 581350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* force padding if adjustment has gone to 0 before full length */ 581450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(b)) b->exponent=a->exponent-p; 581550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 581650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 581750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* not done yet ... */ 581850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, a, b, &aset, 0, &ignore); /* a=a+b for next estimate */ 581950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pp==p) continue; /* precision is at maximum */ 582050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lengthen the next calculation */ 582150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pp=pp*2; /* double precision */ 582250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pp>p) pp=p; /* clamp to maximum */ 582350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=pp; /* working context */ 582450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bset.digits=pp+rhs->digits; /* wider context */ 582550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* Newton's iteration */ 582650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 582750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 582850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* just a sanity check; remove the test to show always */ 582950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (iterations>24) 583050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Ln iterations=%ld, status=%08lx, p=%ld, d=%ld\n", 583150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (LI)iterations, (LI)*status, (LI)p, (LI)rhs->digits); 583250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 583350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 583450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Copy and round the result to res */ 583550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=1; /* indicate dirt to right */ 583650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(a)) residue=0; /* .. unless underflowed to 0 */ 583750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=set->digits; /* [use default rounding] */ 583850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */ 583950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* cleanup/set flags */ 584050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 584150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 584250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */ 584350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufb!=NULL) free(allocbufb); /* .. */ 584450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [status is handled by caller] */ 584550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 584650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decLnOp */ 584754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406 584802c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic pop 584902c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#endif 585050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 585150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 585250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decQuantizeOp -- force exponent to requested value */ 585350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 585450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = op(A, B), where op adjusts the coefficient */ 585550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of C (by rounding or shifting) such that the exponent (-scale) */ 585650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of C has the value B or matches the exponent of B. */ 585750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The numerical value of C will equal A, except for the effects of */ 585850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* any rounding that occurred. */ 585950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 586050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A or B */ 586150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A, the number to adjust */ 586250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B, the requested exponent */ 586350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 586450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* quant is 1 for quantize or 0 for rescale */ 586550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the status accumulator (this can be called without */ 586650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* risk of control loss) */ 586750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 586850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 586950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 587050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Unless there is an error or the result is infinite, the exponent */ 587150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* after the operation is guaranteed to be that requested. */ 587250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 587350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decQuantizeOp(decNumber *res, const decNumber *lhs, 587450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set, 587550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag quant, uInt *status) { 587650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 587750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */ 587850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* .., rhs */ 587950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 588050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *inrhs=rhs; /* save original rhs */ 588150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int reqdigits=set->digits; /* requested DIGITS */ 588250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int reqexp; /* requested exponent [-scale] */ 588350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* rounding residue */ 588450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int etiny=set->emin-(reqdigits-1); 588550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 588650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 588750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 588850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 588950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 589050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 589150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 589250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 589350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operands and set lostDigits status, as needed */ 589450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>reqdigits) { 589550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloclhs=decRoundOperand(lhs, set, status); 589650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs==NULL) break; 589750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=alloclhs; 589850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 589950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>reqdigits) { /* [this only checks lostDigits] */ 590050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, status); 590150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 590250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 590350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 590450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 590550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 590650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 590750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 590850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Handle special values */ 590950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS) { 591050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* NaNs get usual processing */ 591150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS & (DECSNAN | DECNAN)) 591250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, status); 591350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* one infinity but not both is bad */ 591450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if ((lhs->bits ^ rhs->bits) & DECINF) 591550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 591650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* both infinity: return lhs */ 591750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else uprv_decNumberCopy(res, lhs); /* [nop if in place] */ 591850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 591950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 592050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 592150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set requested exponent */ 592250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (quant) reqexp=inrhs->exponent; /* quantize -- match exponents */ 592350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* rescale -- use value of rhs */ 592450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Original rhs must be an integer that fits and is in range, */ 592550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* which could be from -1999999997 to +999999999, thanks to */ 592650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subnormals */ 592750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho reqexp=decGetInt(inrhs); /* [cannot fail] */ 592850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 592950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 593050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 593150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) etiny=set->emin; /* no subnormals */ 593250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 593350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 593450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (reqexp==BADINT /* bad (rescale only) or .. */ 593550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || reqexp==BIGODD || reqexp==BIGEVEN /* very big (ditto) or .. */ 593650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (reqexp<etiny) /* < lowest */ 593750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (reqexp>set->emax)) { /* > emax */ 593850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 593950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 594050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 594150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the RHS has been processed, so it can be overwritten now if necessary */ 594250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(lhs)) { /* zero coefficient unchanged */ 594350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); /* [nop if in place] */ 594450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=reqexp; /* .. just set exponent */ 594550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 594650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) res->bits=0; /* subset specification; no -0 */ 594750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 594850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 594950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* non-zero lhs */ 595050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int adjust=reqexp-lhs->exponent; /* digit adjustment needed */ 595150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if adjusted coefficient will definitely not fit, give up now */ 595250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((lhs->digits-adjust)>reqdigits) { 595350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 595450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 595550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 595650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 595750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adjust>0) { /* increasing exponent */ 595850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this will decrease the length of the coefficient by adjust */ 595950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* digits, and must round as it does so */ 596050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset; /* work */ 596150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset=*set; /* clone rounding, etc. */ 596250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.digits=lhs->digits-adjust; /* set requested length */ 596350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [note that the latter can be <1, here] */ 596450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, lhs, &workset, &residue, status); /* fit to result */ 596550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decApplyRound(res, &workset, residue, status); /* .. and round */ 596650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* [used] */ 596750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If just rounded a 999s case, exponent will be off by one; */ 596850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* adjust back (after checking space), if so. */ 596950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->exponent>reqexp) { 597050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* re-check needed, e.g., for quantize(0.9999, 0.001) under */ 597150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set->digits==3 */ 597250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits==reqdigits) { /* cannot shift by 1 */ 597350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status&=~(DEC_Inexact | DEC_Rounded); /* [clean these] */ 597450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 597550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 597650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 597750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, res->digits, 1); /* shift */ 597850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent--; /* (re)adjust the exponent. */ 597950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 598050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 598150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(res) && !set->extended) res->bits=0; /* subset; no -0 */ 598250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 598350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* increase */ 598450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else /* adjust<=0 */ { /* decreasing or = exponent */ 598550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this will increase the length of the coefficient by -adjust */ 598650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* digits, by adding zero or more trailing zeros; this is */ 598750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* already checked for fit, above */ 598850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); /* [it will fit] */ 598950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if padding needed (adjust<0), add it now... */ 599050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adjust<0) { 599150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, res->digits, -adjust); 599250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent+=adjust; /* adjust the exponent */ 599350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 599450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decrease */ 599550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* non-zero */ 599650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 599750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Check for overflow [do not use Finalize in this case, as an */ 599850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* overflow here is a "don't fit" situation] */ 599950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->exponent>set->emax-res->digits+1) { /* too big */ 600050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 600150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 600250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 600350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 600450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinalize(res, set, &residue, status); /* set subnormal flags */ 600550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status&=~DEC_Underflow; /* suppress Underflow [as per 754] */ 600650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 600750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 600850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 600950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 601050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs!=NULL) free(allocrhs); /* drop any storage used */ 601150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs!=NULL) free(alloclhs); /* .. */ 601250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 601350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 601450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decQuantizeOp */ 601550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 601650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 601750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCompareOp -- compare, min, or max two Numbers */ 601850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 601950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B and carries out one of four operations: */ 602050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMPARE -- returns the signum (as a number) giving the */ 602150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* result of a comparison unless one or both */ 602250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* operands is a NaN (in which case a NaN results) */ 602350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMPSIG -- as COMPARE except that a quiet NaN raises */ 602450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Invalid operation. */ 602550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMPMAX -- returns the larger of the operands, using the */ 602650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 754 maxnum operation */ 602750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMPMAXMAG -- ditto, comparing absolute values */ 602850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMPMIN -- the 754 minnum operation */ 602950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMPMINMAG -- ditto, comparing absolute values */ 603050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMTOTAL -- returns the signum (as a number) giving the */ 603150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* result of a comparison using 754 total ordering */ 603250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 603350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 603450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 603550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 603650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 603750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* op is the operation flag */ 603850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the usual accumulator */ 603950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 604050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for one digit for COMPARE or set->digits for */ 604150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMPMAX, COMPMIN, COMPMAXMAG, or COMPMINMAG. */ 604250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 604350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The emphasis here is on speed for common cases, and avoiding */ 604450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* coefficient comparison if possible. */ 604550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 604650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decCompareOp(decNumber *res, const decNumber *lhs, 604750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set, 604850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag op, uInt *status) { 604950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 605050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */ 605150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* .., rhs */ 605250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 605350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int result=0; /* default result value */ 605450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte merged; /* work */ 605550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 605650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 605750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 605850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 605950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 606050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 606150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 606250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 606350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operands and set lostDigits status, as needed */ 606450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>set->digits) { 606550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloclhs=decRoundOperand(lhs, set, status); 606650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs==NULL) {result=BADINT; break;} 606750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=alloclhs; 606850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 606950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>set->digits) { 607050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, status); 607150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) {result=BADINT; break;} 607250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 607350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 607450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 607550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 607650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 607750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 607850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If total ordering then handle differing signs 'up front' */ 607950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op==COMPTOTAL) { /* total ordering */ 608054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (decNumberIsNegative(lhs) && !decNumberIsNegative(rhs)) { 608150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=-1; 608250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 608350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 608454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (!decNumberIsNegative(lhs) && decNumberIsNegative(rhs)) { 608550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=+1; 608650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 608750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 608850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 608950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 609050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle NaNs specially; let infinities drop through */ 609150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This assumes sNaN (even just one) leads to NaN. */ 609250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho merged=(lhs->bits | rhs->bits) & (DECSNAN | DECNAN); 609350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (merged) { /* a NaN bit set */ 609450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op==COMPARE); /* result will be NaN */ 609550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (op==COMPSIG) /* treat qNaN as sNaN */ 609650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation | DEC_sNaN; 609750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (op==COMPTOTAL) { /* total ordering, always finite */ 609850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* signs are known to be the same; compute the ordering here */ 609950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* as if the signs are both positive, then invert for negatives */ 610050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!decNumberIsNaN(lhs)) result=-1; 610150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (!decNumberIsNaN(rhs)) result=+1; 610250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here if both NaNs */ 610350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsSNaN(lhs) && decNumberIsQNaN(rhs)) result=-1; 610450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsQNaN(lhs) && decNumberIsSNaN(rhs)) result=+1; 610550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* both NaN or both sNaN */ 610650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now it just depends on the payload */ 610750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=decUnitCompare(lhs->lsu, D2U(lhs->digits), 610850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs->lsu, D2U(rhs->digits), 0); 610950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [Error not possible, as these are 'aligned'] */ 611050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* both same NaNs */ 611150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(lhs)) result=-result; 611250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 611350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* total order */ 611450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 611550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (merged & DECSNAN); /* sNaN -> qNaN */ 611650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* here if MIN or MAX and one or two quiet NaNs */ 611750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* min or max -- 754 rules ignore single NaN */ 611850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!decNumberIsNaN(lhs) || !decNumberIsNaN(rhs)) { 611950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* just one NaN; force choice to be the non-NaN operand */ 612050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho op=COMPMAX; 612150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->bits & DECNAN) result=-1; /* pick rhs */ 612250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else result=+1; /* pick lhs */ 612350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 612450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 612550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* max or min */ 612650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho op=COMPNAN; /* use special path */ 612750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, status); /* propagate NaN */ 612850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 612950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 613050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* have numbers */ 613150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op==COMPMAXMAG || op==COMPMINMAG) result=decCompare(lhs, rhs, 1); 613250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else result=decCompare(lhs, rhs, 0); /* sign matters */ 613350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 613450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 613550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result==BADINT) *status|=DEC_Insufficient_storage; /* rare */ 613650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 613750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op==COMPARE || op==COMPSIG ||op==COMPTOTAL) { /* returning signum */ 613850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op==COMPTOTAL && result==0) { 613950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* operands are numerically equal or same NaN (and same sign, */ 614050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* tested first); if identical, leave result 0 */ 614150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent!=rhs->exponent) { 614250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent<rhs->exponent) result=-1; 614350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else result=+1; 614450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(lhs)) result=-result; 614550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* lexp!=rexp */ 614650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* total-order by exponent */ 614750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* [always a valid result] */ 614850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result!=0) { /* must be -1 or +1 */ 614950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=1; 615050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result<0) res->bits=DECNEG; 615150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 615250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 615350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (op==COMPNAN); /* special, drop through */ 615450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* MAX or MIN, non-NaN result */ 615550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* rounding accumulator */ 615650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* choose the operand for the result */ 615750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *choice; 615850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result==0) { /* operands are numerically equal */ 615950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* choose according to sign then exponent (see 754) */ 616050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte slhs=(lhs->bits & DECNEG); 616150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte srhs=(rhs->bits & DECNEG); 616250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 616350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { /* subset: force left-hand */ 616450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho op=COMPMAX; 616550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=+1; 616650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 616750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else 616850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 616950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (slhs!=srhs) { /* signs differ */ 617050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (slhs) result=-1; /* rhs is max */ 617150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else result=+1; /* lhs is max */ 617250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 617350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (slhs && srhs) { /* both negative */ 617450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent<rhs->exponent) result=+1; 617550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else result=-1; 617650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [if equal, use lhs, technically identical] */ 617750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 617850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* both positive */ 617950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent>rhs->exponent) result=+1; 618050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else result=-1; 618150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [ditto] */ 618250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 618350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* numerically equal */ 618450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here result will be non-0; reverse if looking for MIN */ 618550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op==COMPMIN || op==COMPMINMAG) result=-result; 618650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho choice=(result>0 ? lhs : rhs); /* choose */ 618750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* copy chosen to result, rounding if need be */ 618850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, choice, set, &residue, status); 618950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); 619050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 619150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 619250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 619350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs!=NULL) free(allocrhs); /* free any storage used */ 619450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs!=NULL) free(alloclhs); /* .. */ 619550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 619650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 619750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decCompareOp */ 619850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 619950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 620050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCompare -- compare two decNumbers by numerical value */ 620150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 620250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine compares A ? B without altering them. */ 620350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 620450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg1 is A, a decNumber which is not a NaN */ 620550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg2 is B, a decNumber which is not a NaN */ 620650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg3 is 1 for a sign-independent compare, 0 otherwise */ 620750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 620850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure */ 620950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (the only possible failure is an allocation error) */ 621050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 621150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decCompare(const decNumber *lhs, const decNumber *rhs, 621250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag abs_c) { 621350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int result; /* result value */ 621450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int sigr; /* rhs signum */ 621550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int compare; /* work */ 621650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 621750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=1; /* assume signum(lhs) */ 621850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(lhs)) result=0; 621950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (abs_c) { 622050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) return result; /* LHS wins or both 0 */ 622150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* RHS is non-zero */ 622250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result==0) return -1; /* LHS is 0; RHS wins */ 622350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [here, both non-zero, result=1] */ 622450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 622550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* signs matter */ 622650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result && decNumberIsNegative(lhs)) result=-1; 622750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho sigr=1; /* compute signum(rhs) */ 622850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) sigr=0; 622950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsNegative(rhs)) sigr=-1; 623050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result > sigr) return +1; /* L > R, return 1 */ 623150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result < sigr) return -1; /* L < R, return -1 */ 623250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result==0) return 0; /* both 0 */ 623350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 623450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 623550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* signums are the same; both are non-zero */ 623650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((lhs->bits | rhs->bits) & DECINF) { /* one or more infinities */ 623750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs)) { 623850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(lhs)) result=0;/* both infinite */ 623950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else result=-result; /* only rhs infinite */ 624050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 624150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 624250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 624350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* must compare the coefficients, allowing for exponents */ 624450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent>rhs->exponent) { /* LHS exponent larger */ 624550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* swap sides, and sign */ 624650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *temp=lhs; 624750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=rhs; 624850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=temp; 624950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=-result; 625050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 625150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho compare=decUnitCompare(lhs->lsu, D2U(lhs->digits), 625250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs->lsu, D2U(rhs->digits), 625350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs->exponent-lhs->exponent); 625450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (compare!=BADINT) compare*=result; /* comparison succeeded */ 625550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return compare; 625650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decCompare */ 625750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 625850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 625950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decUnitCompare -- compare two >=0 integers in Unit arrays */ 626050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 626150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine compares A ? B*10**E where A and B are unit arrays */ 626250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A is a plain integer */ 626350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* B has an exponent of E (which must be non-negative) */ 626450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 626550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg1 is A first Unit (lsu) */ 626650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg2 is A length in Units */ 626750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg3 is B first Unit (lsu) */ 626850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg4 is B length in Units */ 626950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg5 is E (0 if the units are aligned) */ 627050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 627150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure */ 627250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (the only possible failure is an allocation error, which can */ 627350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* only occur if E!=0) */ 627450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 627550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decUnitCompare(const Unit *a, Int alength, 627650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *b, Int blength, Int exp) { 627750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *acc; /* accumulator for result */ 627850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit accbuff[SD2U(DECBUFFER*2+1)]; /* local buffer */ 627950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *allocacc=NULL; /* -> allocated acc buffer, iff allocated */ 628050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int accunits, need; /* units in use or needed for acc */ 628150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *l, *r, *u; /* work */ 628250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int expunits, exprem, result; /* .. */ 628350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 628450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exp==0) { /* aligned; fastpath */ 628550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alength>blength) return 1; 628650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alength<blength) return -1; 628750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* same number of units in both -- need unit-by-unit compare */ 628850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho l=a+alength-1; 628950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho r=b+alength-1; 629050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;l>=a; l--, r--) { 629150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*l>*r) return 1; 629250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*l<*r) return -1; 629350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 629450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; /* all units match */ 629550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* aligned */ 629650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 629750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Unaligned. If one is >1 unit longer than the other, padded */ 629850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* approximately, then can return easily */ 629950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alength>blength+(Int)D2U(exp)) return 1; 630050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alength+1<blength+(Int)D2U(exp)) return -1; 630150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 630250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Need to do a real subtract. For this, a result buffer is needed */ 630350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* even though only the sign is of interest. Its length needs */ 630450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* to be the larger of alength and padded blength, +2 */ 630550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho need=blength+D2U(exp); /* maximum real length of B */ 630650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (need<alength) need=alength; 630750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho need+=2; 630850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=accbuff; /* assume use local buffer */ 630950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (need*sizeof(Unit)>sizeof(accbuff)) { 631050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocacc=(Unit *)malloc(need*sizeof(Unit)); 631150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc==NULL) return BADINT; /* hopeless -- abandon */ 631250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=allocacc; 631350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 631450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Calculate units and remainder from exponent. */ 631550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho expunits=exp/DECDPUN; 631650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exprem=exp%DECDPUN; 631750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subtract [A+B*(-m)] */ 631850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=decUnitAddSub(a, alength, b, blength, expunits, acc, 631950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho -(Int)powers[exprem]); 632050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [UnitAddSub result may have leading zeros, even on zero] */ 632150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (accunits<0) result=-1; /* negative result */ 632250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* non-negative result */ 632350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* check units of the result before freeing any storage */ 632450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (u=acc; u<acc+accunits-1 && *u==0;) u++; 632550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=(*u==0 ? 0 : +1); 632650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 632750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* clean up and return the result */ 632850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc!=NULL) free(allocacc); /* drop any storage used */ 632950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 633050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decUnitCompare */ 633150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 633250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 633350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decUnitAddSub -- add or subtract two >=0 integers in Unit arrays */ 633450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 633550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine performs the calculation: */ 633650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 633750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C=A+(B*M) */ 633850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 633950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Where M is in the range -DECDPUNMAX through +DECDPUNMAX. */ 634050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 634150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A may be shorter or longer than B. */ 634250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 634350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Leading zeros are not removed after a calculation. The result is */ 634450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* either the same length as the longer of A and B (adding any */ 634550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* shift), or one Unit longer than that (if a Unit carry occurred). */ 634650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 634750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A and B content are not altered unless C is also A or B. */ 634850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C may be the same array as A or B, but only if no zero padding is */ 634950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* requested (that is, C may be B only if bshift==0). */ 635050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C is filled from the lsu; only those units necessary to complete */ 635150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the calculation are referenced. */ 635250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 635350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg1 is A first Unit (lsu) */ 635450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg2 is A length in Units */ 635550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg3 is B first Unit (lsu) */ 635650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg4 is B length in Units */ 635750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg5 is B shift in Units (>=0; pads with 0 units if positive) */ 635850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg6 is C first Unit (lsu) */ 635950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg7 is M, the multiplier */ 636050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 636150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns the count of Units written to C, which will be non-zero */ 636250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and negated if the result is negative. That is, the sign of the */ 636350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned Int is the sign of the result (positive for zero) and */ 636450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the absolute value of the Int is the count of Units. */ 636550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 636650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* It is the caller's responsibility to make sure that C size is */ 636750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* safe, allowing space if necessary for a one-Unit carry. */ 636850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 636950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine is severely performance-critical; *any* change here */ 637050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* must be measured (timed) to assure no performance degradation. */ 637150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* In particular, trickery here tends to be counter-productive, as */ 637250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* increased complexity of code hurts register optimizations on */ 637350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* register-poor architectures. Avoiding divisions is nearly */ 637450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* always a Good Idea, however. */ 637550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 637650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Special thanks to Rick McGuire (IBM Cambridge, MA) and Dave Clark */ 637750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (IBM Warwick, UK) for some of the ideas used in this routine. */ 637850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 637950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decUnitAddSub(const Unit *a, Int alength, 638050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *b, Int blength, Int bshift, 638150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *c, Int m) { 638250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *alsu=a; /* A lsu [need to remember it] */ 638350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *clsu=c; /* C ditto */ 638450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *minC; /* low water mark for C */ 638550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *maxC; /* high water mark for C */ 638650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho eInt carry=0; /* carry integer (could be Long) */ 638750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int add; /* work */ 638850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 /* myriadal, millenary, etc. */ 638950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int est; /* estimated quotient */ 639050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 639150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 639250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 639350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alength<1 || blength<1) 639450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("decUnitAddSub: alen blen m %ld %ld [%ld]\n", alength, blength, m); 639550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 639650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 639750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxC=c+alength; /* A is usually the longer */ 639850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho minC=c+blength; /* .. and B the shorter */ 639950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bshift!=0) { /* B is shifted; low As copy across */ 640050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho minC+=bshift; 640150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if in place [common], skip copy unless there's a gap [rare] */ 640250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a==c && bshift<=alength) { 640350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c+=bshift; 640450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a+=bshift; 640550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 640650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else for (; c<clsu+bshift; a++, c++) { /* copy needed */ 640750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a<alsu+alength) *c=*a; 640850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else *c=0; 640950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 641050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 641150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (minC>maxC) { /* swap */ 641250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *hold=minC; 641350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho minC=maxC; 641450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxC=hold; 641550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 641650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 641750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* For speed, do the addition as two loops; the first where both A */ 641850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* and B contribute, and the second (if necessary) where only one or */ 641950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* other of the numbers contribute. */ 642050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Carry handling is the same (i.e., duplicated) in each case. */ 642150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; c<minC; c++) { 642250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry+=*a; 642350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a++; 642450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry+=((eInt)*b)*m; /* [special-casing m=1/-1 */ 642550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b++; /* here is not a win] */ 642650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here carry is new Unit of digits; it could be +ve or -ve */ 642750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((ueInt)carry<=DECDPUNMAX) { /* fastpath 0-DECDPUNMAX */ 642850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)carry; 642950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=0; 643050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 643150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 643250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==4 /* use divide-by-multiply */ 643350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 643450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>11)*53687)>>18; 643550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ 643650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est; /* likely quotient [89%] */ 643750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* estimate was correct */ 643850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 643950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 644050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 644150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 644250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 644350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 644450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>11)*53687)>>18; 644550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); 644650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est-(DECDPUNMAX+1); /* correctly negative */ 644750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* was OK */ 644850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 644950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 645050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==3 645150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 645250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>3)*16777)>>21; 645350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ 645450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est; /* likely quotient [99%] */ 645550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* estimate was correct */ 645650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 645750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 645850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 645950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 646050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 646150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 646250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>3)*16777)>>21; 646350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); 646450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est-(DECDPUNMAX+1); /* correctly negative */ 646550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* was OK */ 646650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 646750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 646850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN<=2 646950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Can use QUOT10 as carry <= 4 digits */ 647050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 647150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=QUOT10(carry, DECDPUN); 647250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ 647350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est; /* quotient */ 647450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 647550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 647650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 647750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 647850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=QUOT10(carry, DECDPUN); 647950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); 648050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est-(DECDPUNMAX+1); /* correctly negative */ 648150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 648250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* remainder operator is undefined if negative, so must test */ 648350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((ueInt)carry<(DECDPUNMAX+1)*2) { /* fastpath carry +1 */ 648450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-(DECDPUNMAX+1)); /* [helps additions] */ 648550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=1; 648650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 648750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 648850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 648950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry%(DECDPUNMAX+1)); 649050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry/(DECDPUNMAX+1); 649150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 649250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 649350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 649450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 649550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry%(DECDPUNMAX+1)); 649650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1); 649750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 649850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* c */ 649950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 650050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now may have one or other to complete */ 650150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [pretest to avoid loop setup/shutdown] */ 650250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (c<maxC) for (; c<maxC; c++) { 650350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a<alsu+alength) { /* still in A */ 650450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry+=*a; 650550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a++; 650650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 650750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* inside B */ 650850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry+=((eInt)*b)*m; 650950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b++; 651050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 651150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here carry is new Unit of digits; it could be +ve or -ve and */ 651250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* magnitude up to DECDPUNMAX squared */ 651350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((ueInt)carry<=DECDPUNMAX) { /* fastpath 0-DECDPUNMAX */ 651450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)carry; 651550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=0; 651650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 651750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 651850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* result for this unit is negative or >DECDPUNMAX */ 651950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==4 /* use divide-by-multiply */ 652050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 652150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>11)*53687)>>18; 652250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ 652350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est; /* likely quotient [79.7%] */ 652450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* estimate was correct */ 652550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 652650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 652750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 652850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 652950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 653050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 653150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>11)*53687)>>18; 653250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); 653350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est-(DECDPUNMAX+1); /* correctly negative */ 653450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* was OK */ 653550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 653650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 653750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==3 653850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 653950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>3)*16777)>>21; 654050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ 654150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est; /* likely quotient [99%] */ 654250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* estimate was correct */ 654350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 654450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 654550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 654650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 654750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 654850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 654950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>3)*16777)>>21; 655050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); 655150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est-(DECDPUNMAX+1); /* correctly negative */ 655250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* was OK */ 655350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 655450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 655550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN<=2 655650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 655750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=QUOT10(carry, DECDPUN); 655850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ 655950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est; /* quotient */ 656050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 656150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 656250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 656350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 656450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=QUOT10(carry, DECDPUN); 656550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); 656650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est-(DECDPUNMAX+1); /* correctly negative */ 656750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 656850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((ueInt)carry<(DECDPUNMAX+1)*2){ /* fastpath carry 1 */ 656950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-(DECDPUNMAX+1)); 657050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=1; 657150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 657250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 657350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* remainder operator is undefined if negative, so must test */ 657450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 657550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry%(DECDPUNMAX+1)); 657650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry/(DECDPUNMAX+1); 657750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 657850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 657950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 658050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 658150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry%(DECDPUNMAX+1)); 658250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1); 658350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 658450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* c */ 658550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 658650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* OK, all A and B processed; might still have carry or borrow */ 658750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* return number of Units in the result, negated if a borrow */ 658850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry==0) return c-clsu; /* no carry, so no more to do */ 658950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>0) { /* positive carry */ 659050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)carry; /* place as new unit */ 659150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; /* .. */ 659250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return c-clsu; 659350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 659450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* -ve carry: it's a borrow; complement needed */ 659550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho add=1; /* temporary carry... */ 659650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (c=clsu; c<maxC; c++) { 659750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho add=DECDPUNMAX+add-*c; 659850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (add<=DECDPUNMAX) { 659950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)add; 660050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho add=0; 660150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 660250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 660350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=0; 660450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho add=1; 660550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 660650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 660750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* add an extra unit iff it would be non-zero */ 660850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 660950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("UAS borrow: add %ld, carry %ld\n", add, carry); 661050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 661150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((add-carry-1)!=0) { 661250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(add-carry-1); 661350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; /* interesting, include it */ 661450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 661550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return clsu-c; /* -ve result indicates borrowed */ 661650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decUnitAddSub */ 661750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 661850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 661950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decTrim -- trim trailing zeros or normalize */ 662050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 662150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to trim or normalize */ 662250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context to use to check for clamp */ 662350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* all is 1 to remove all trailing zeros, 0 for just fraction ones */ 662450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* noclamp is 1 to unconditional (unclamped) trim */ 662550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dropped returns the number of discarded trailing zeros */ 662650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns dn */ 662750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 662850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If clamp is set in the context then the number of zeros trimmed */ 662950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* may be limited if the exponent is high. */ 663050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All fields are updated as required. This is a utility operation, */ 663150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* so special values are unchanged and no error is possible. */ 663250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 663350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decTrim(decNumber *dn, decContext *set, Flag all, 663450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag noclamp, Int *dropped) { 663550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int d, exp; /* work */ 663650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt cut; /* .. */ 663750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up; /* -> current Unit */ 663850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 663950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 664050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn; 664150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 664250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 664350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *dropped=0; /* assume no zeros dropped */ 664450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((dn->bits & DECSPECIAL) /* fast exit if special .. */ 664550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (*dn->lsu & 0x01)) return dn; /* .. or odd */ 664650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(dn)) { /* .. or 0 */ 664750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=0; /* (sign is preserved) */ 664850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 664950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 665050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 665150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* have a finite number which is even */ 665250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exp=dn->exponent; 665350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=1; /* digit (1-DECDPUN) in Unit */ 665450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=dn->lsu; /* -> current Unit */ 665550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (d=0; d<dn->digits-1; d++) { /* [don't strip the final digit] */ 665650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* slice by powers */ 665750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 665850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt quot=QUOT10(*up, cut); 665950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((*up-quot*powers[cut])!=0) break; /* found non-0 digit */ 666050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 666150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up%powers[cut]!=0) break; /* found non-0 digit */ 666250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 666350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* have a trailing 0 */ 666450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!all) { /* trimming */ 666550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [if exp>0 then all trailing 0s are significant for trim] */ 666650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exp<=0) { /* if digit might be significant */ 666750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exp==0) break; /* then quit */ 666850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exp++; /* next digit might be significant */ 666950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 667050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 667150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut++; /* next power */ 667250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut>DECDPUN) { /* need new Unit */ 667350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; 667450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=1; 667550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 667650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* d */ 667750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (d==0) return dn; /* none to drop */ 667850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 667950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* may need to limit drop if clamping */ 668050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->clamp && !noclamp) { 668150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxd=set->emax-set->digits+1-dn->exponent; 668250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (maxd<=0) return dn; /* nothing possible */ 668350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (d>maxd) d=maxd; 668450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 668550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 668650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* effect the drop */ 668750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decShiftToLeast(dn->lsu, D2U(dn->digits), d); 668850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent+=d; /* maintain numerical value */ 668950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits-=d; /* new length */ 669050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *dropped=d; /* report the count */ 669150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 669250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decTrim */ 669350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 669450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 669550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decReverse -- reverse a Unit array in place */ 669650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 669750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ulo is the start of the array */ 669850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* uhi is the end of the array (highest Unit to include) */ 669950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 670050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The units ulo through uhi are reversed in place (if the number */ 670150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of units is odd, the middle one is untouched). Note that the */ 670250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* digit(s) in each unit are unaffected. */ 670350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 670450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decReverse(Unit *ulo, Unit *uhi) { 670550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit temp; 670650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; ulo<uhi; ulo++, uhi--) { 670750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho temp=*ulo; 670850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *ulo=*uhi; 670950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uhi=temp; 671050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 671150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 671250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decReverse */ 671350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 671450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 671550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decShiftToMost -- shift digits in array towards most significant */ 671650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 671750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* uar is the array */ 671850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* digits is the count of digits in use in the array */ 671950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* shift is the number of zeros to pad with (least significant); */ 672050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* it must be zero or positive */ 672150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 672250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns the new length of the integer in the array, in digits */ 672350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 672450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No overflow is permitted (that is, the uar array must be known to */ 672550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* be large enough to hold the result, after shifting). */ 672650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 672750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decShiftToMost(Unit *uar, Int digits, Int shift) { 672850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *target, *source, *first; /* work */ 672950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int cut; /* odd 0's to add */ 673050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt next; /* work */ 673150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 673250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift==0) return digits; /* [fastpath] nothing to do */ 673350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((digits+shift)<=DECDPUN) { /* [fastpath] single-unit case */ 673450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uar=(Unit)(*uar*powers[shift]); 673550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return digits+shift; 673650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 673750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 673850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho next=0; /* all paths */ 673950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho source=uar+D2U(digits)-1; /* where msu comes from */ 674050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho target=source+D2U(shift); /* where upper part of first cut goes */ 674150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN-MSUDIGITS(shift); /* where to slice */ 674250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut==0) { /* unit-boundary case */ 674350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; source>=uar; source--, target--) *target=*source; 674450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 674550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 674650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho first=uar+D2U(digits+shift)-1; /* where msu of source will end up */ 674750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; source>=uar; source--, target--) { 674850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* split the source Unit and accumulate remainder for next */ 674950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 675050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt quot=QUOT10(*source, cut); 675150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt rem=*source-quot*powers[cut]; 675250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho next+=quot; 675350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 675450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt rem=*source%powers[cut]; 675550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho next+=*source/powers[cut]; 675650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 675750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (target<=first) *target=(Unit)next; /* write to target iff valid */ 675850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho next=rem*powers[DECDPUN-cut]; /* save remainder for next Unit */ 675950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 676050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* shift-move */ 676150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 676250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* propagate any partial unit to one below and clear the rest */ 676350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; target>=uar; target--) { 676450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *target=(Unit)next; 676550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho next=0; 676650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 676750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return digits+shift; 676850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decShiftToMost */ 676950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 677050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 677150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decShiftToLeast -- shift digits in array towards least significant */ 677250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 677350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* uar is the array */ 677450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* units is length of the array, in units */ 677550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* shift is the number of digits to remove from the lsu end; it */ 677650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* must be zero or positive and <= than units*DECDPUN. */ 677750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 677850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns the new length of the integer in the array, in units */ 677950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 678050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Removed digits are discarded (lost). Units not required to hold */ 678150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the final result are unchanged. */ 678250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 678350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decShiftToLeast(Unit *uar, Int units, Int shift) { 678450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *target, *up; /* work */ 678550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int cut, count; /* work */ 678650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int quot, rem; /* for division */ 678750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 678850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift==0) return units; /* [fastpath] nothing to do */ 678950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift==units*DECDPUN) { /* [fastpath] little to do */ 679050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uar=0; /* all digits cleared gives zero */ 679150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1; /* leaves just the one */ 679250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 679350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 679450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho target=uar; /* both paths */ 679550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=MSUDIGITS(shift); 679650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut==DECDPUN) { /* unit-boundary case; easy */ 679750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=uar+D2U(shift); 679850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; up<uar+units; target++, up++) *target=*up; 679950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return target-uar; 680050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 680150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 680250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* messier */ 680350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=uar+D2U(shift-cut); /* source; correct to whole Units */ 680450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count=units*DECDPUN-shift; /* the maximum new length */ 680550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 680650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=QUOT10(*up, cut); 680750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 680850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=*up/powers[cut]; 680950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 681050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; ; target++) { 681150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *target=(Unit)quot; 681250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=(DECDPUN-cut); 681350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count<=0) break; 681450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; 681550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=*up; 681650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 681750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=QUOT10(quot, cut); 681850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=*up-quot*powers[cut]; 681950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 682050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=quot%powers[cut]; 682150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=quot/powers[cut]; 682250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 682350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *target=(Unit)(*target+rem*powers[DECDPUN-cut]); 682450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=cut; 682550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count<=0) break; 682650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 682750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return target-uar+1; 682850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decShiftToLeast */ 682950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 683050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECSUBSET 683150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 683250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decRoundOperand -- round an operand [used for subset only] */ 683350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 683450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to round (dn->digits is > set->digits) */ 683550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the relevant context */ 683650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the status accumulator */ 683750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 683850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns an allocated decNumber with the rounded result. */ 683950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 684050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lostDigits and other status may be set by this. */ 684150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 684250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Since the input is an operand, it must not be modified. */ 684350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Instead, return an allocated decNumber, rounded as required. */ 684450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* It is the caller's responsibility to free the allocated storage. */ 684550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 684650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If no storage is available then the result cannot be used, so NULL */ 684750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* is returned. */ 684850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 684950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber *decRoundOperand(const decNumber *dn, decContext *set, 685050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 685150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *res; /* result structure */ 685250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt newstatus=0; /* status from round */ 685350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* rounding accumulator */ 685450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 685550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Allocate storage for the returned decNumber, big enough for the */ 685650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* length specified by the context */ 685750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res=(decNumber *)malloc(sizeof(decNumber) 685850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho +(D2U(set->digits)-1)*sizeof(Unit)); 685950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res==NULL) { 686050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 686150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return NULL; 686250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 686350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, dn, set, &residue, &newstatus); 686450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decApplyRound(res, set, residue, &newstatus); 686550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 686650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If that set Inexact then "lost digits" is raised... */ 686750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (newstatus & DEC_Inexact) newstatus|=DEC_Lost_digits; 686850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=newstatus; 686950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 687050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decRoundOperand */ 687150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 687250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 687350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 687450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCopyFit -- copy a number, truncating the coefficient if needed */ 687550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 687650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dest is the target decNumber */ 687750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* src is the source decNumber */ 687850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context [used for length (digits) and rounding mode] */ 687950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* residue is the residue accumulator */ 688050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status contains the current status to be updated */ 688150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 688250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (dest==src is allowed and will be a no-op if fits) */ 688350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All fields are updated as required. */ 688450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 688550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decCopyFit(decNumber *dest, const decNumber *src, 688650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set, Int *residue, uInt *status) { 688750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dest->bits=src->bits; 688850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dest->exponent=src->exponent; 688950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetCoeff(dest, set, src->lsu, src->digits, residue, status); 689050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decCopyFit */ 689150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 689250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 689350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decSetCoeff -- set the coefficient of a number */ 689450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 689550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number whose coefficient array is to be set. */ 689650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* It must have space for set->digits digits */ 689750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context [for size] */ 689850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lsu -> lsu of the source coefficient [may be dn->lsu] */ 689950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* len is digits in the source coefficient [may be dn->digits] */ 690050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* residue is the residue accumulator. This has values as in */ 690150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decApplyRound, and will be unchanged unless the */ 690250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* target size is less than len. In this case, the */ 690350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* coefficient is truncated and the residue is updated to */ 690450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* reflect the previous residue and the dropped digits. */ 690550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the status accumulator, as usual */ 690650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 690750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The coefficient may already be in the number, or it can be an */ 690850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* external intermediate array. If it is in the number, lsu must == */ 690950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn->lsu and len must == dn->digits. */ 691050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 691150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Note that the coefficient length (len) may be < set->digits, and */ 691250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* in this case this merely copies the coefficient (or is a no-op */ 691350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if dn->lsu==lsu). */ 691450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 691550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Note also that (only internally, from decQuantizeOp and */ 691650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decSetSubnormal) the value of set->digits may be less than one, */ 691750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* indicating a round to left. This routine handles that case */ 691850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* correctly; caller ensures space. */ 691950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 692050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn->digits, dn->lsu (and as required), and dn->exponent are */ 692150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* updated as necessary. dn->bits (sign) is unchanged. */ 692250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 692350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* DEC_Rounded status is set if any digits are discarded. */ 692450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* DEC_Inexact status is set if any non-zero digits are discarded, or */ 692550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* incoming residue was non-0 (implies rounded) */ 692650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 692750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* mapping array: maps 0-9 to canonical residues, so that a residue */ 692850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* can be adjusted in the range [-1, +1] and achieve correct rounding */ 692950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 0 1 2 3 4 5 6 7 8 9 */ 693050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const uByte resmap[10]={0, 3, 3, 3, 3, 5, 7, 7, 7, 7}; 693150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetCoeff(decNumber *dn, decContext *set, const Unit *lsu, 693250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int len, Int *residue, uInt *status) { 693350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int discard; /* number of digits to discard */ 693450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt cut; /* cut point in Unit */ 693550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up; /* work */ 693650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *target; /* .. */ 693750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int count; /* .. */ 693850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 693950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt temp; /* .. */ 694050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 694150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 694250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho discard=len-set->digits; /* digits to discard */ 694350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (discard<=0) { /* no digits are being discarded */ 694450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->lsu!=lsu) { /* copy needed */ 694550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* copy the coefficient array to the result number; no shift needed */ 694650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count=len; /* avoids D2U */ 694750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=lsu; 694850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN) 694950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *target=*up; 695050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=len; /* set the new length */ 695150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 695250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* dn->exponent and residue are unchanged, record any inexactitude */ 695350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue!=0) *status|=(DEC_Inexact | DEC_Rounded); 695450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 695550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 695650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 695750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* some digits must be discarded ... */ 695850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent+=discard; /* maintain numerical value */ 695950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Rounded; /* accumulate Rounded status */ 696050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue>1) *residue=1; /* previous residue now to right, so reduce */ 696150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 696250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (discard>len) { /* everything, +1, is being discarded */ 696350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* guard digit is 0 */ 696450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* residue is all the number [NB could be all 0s] */ 696550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue<=0) { /* not already positive */ 696650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count=len; /* avoids D2U */ 696750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=lsu; count>0; up++, count-=DECDPUN) if (*up!=0) { /* found non-0 */ 696850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *residue=1; 696950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* no need to check any others */ 697050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 697150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 697250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */ 697350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *dn->lsu=0; /* coefficient will now be 0 */ 697450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=1; /* .. */ 697550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 697650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* total discard */ 697750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 697850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* partial discard [most common case] */ 697950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here, at least the first (most significant) discarded digit exists */ 698050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 698150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* spin up the number, noting residue during the spin, until get to */ 698250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the Unit with the first discarded digit. When reach it, extract */ 698350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it and remember its position */ 698450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count=0; 698550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=lsu;; up++) { 698650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count+=DECDPUN; 698750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count>=discard) break; /* full ones all checked */ 698850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=0) *residue=1; 698950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* up */ 699050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 699150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here up -> Unit with first discarded digit */ 699250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=discard-(count-DECDPUN)-1; 699350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut==DECDPUN-1) { /* unit-boundary case (fast) */ 699450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit half=(Unit)powers[DECDPUN]>>1; 699550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set residue directly */ 699650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up>=half) { 699750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up>half) *residue=7; 699850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else *residue+=5; /* add sticky bit */ 699950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 700050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* <half */ 700150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=0) *residue=3; /* [else is 0, leave as sticky bit] */ 700250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 700350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->digits<=0) { /* special for Quantize/Subnormal :-( */ 700450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *dn->lsu=0; /* .. result is 0 */ 700550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=1; /* .. */ 700650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 700750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* shift to least */ 700850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count=set->digits; /* now digits to end up with */ 700950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=count; /* set the new length */ 701050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; /* move to next */ 701150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* on unit boundary, so shift-down copy loop is simple */ 701250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN) 701350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *target=*up; 701450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 701550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* unit-boundary case */ 701650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 701750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* discard digit is in low digit(s), and not top digit */ 701850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt discard1; /* first discarded digit */ 701950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt quot, rem; /* for divisions */ 702050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut==0) quot=*up; /* is at bottom of unit */ 702150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else /* cut>0 */ { /* it's not at bottom of unit */ 702250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 70238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius U_ASSERT(/* cut >= 0 &&*/ cut <= 4); 702450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=QUOT10(*up, cut); 702550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=*up-quot*powers[cut]; 702650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 702750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=*up%powers[cut]; 702850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=*up/powers[cut]; 702950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 703050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rem!=0) *residue=1; 703150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 703250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* discard digit is now at bottom of quot */ 703350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 703450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho temp=(quot*6554)>>16; /* fast /10 */ 703550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Vowels algorithm here not a win (9 instructions) */ 703650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho discard1=quot-X10(temp); 703750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=temp; 703850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 703950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho discard1=quot%10; 704050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=quot/10; 704150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 704250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here, discard1 is the guard digit, and residue is everything */ 704350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* else [use mapping array to accumulate residue safely] */ 704450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *residue+=resmap[discard1]; 704550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut++; /* update cut */ 704650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here: up -> Unit of the array with bottom digit */ 704750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* cut is the division point for each Unit */ 704850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* quot holds the uncut high-order digits for the current unit */ 704950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->digits<=0) { /* special for Quantize/Subnormal :-( */ 705050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *dn->lsu=0; /* .. result is 0 */ 705150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=1; /* .. */ 705250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 705350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* shift to least needed */ 705450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count=set->digits; /* now digits to end up with */ 705550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=count; /* set the new length */ 705650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* shift-copy the coefficient array to the result number */ 705750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (target=dn->lsu; ; target++) { 705850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *target=(Unit)quot; 705950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=(DECDPUN-cut); 706050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count<=0) break; 706150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; 706250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=*up; 706350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 706450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=QUOT10(quot, cut); 706550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=*up-quot*powers[cut]; 706650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 706750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=quot%powers[cut]; 706850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=quot/powers[cut]; 706950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 707050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *target=(Unit)(*target+rem*powers[DECDPUN-cut]); 707150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=cut; 707250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count<=0) break; 707350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* shift-copy loop */ 707450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* shift to least */ 707550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* not unit boundary */ 707650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 707750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */ 707850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 707950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decSetCoeff */ 708050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 708150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 708250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decApplyRound -- apply pending rounding to a number */ 708350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 708450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number, with space for set->digits digits */ 708550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context [for size and rounding mode] */ 708650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* residue indicates pending rounding, being any accumulated */ 708750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* guard and sticky information. It may be: */ 708850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 6-9: rounding digit is >5 */ 708950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 5: rounding digit is exactly half-way */ 709050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 1-4: rounding digit is <5 and >0 */ 709150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 0: the coefficient is exact */ 709250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -1: as 1, but the hidden digits are subtractive, that */ 709350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* is, of the opposite sign to dn. In this case the */ 709450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* coefficient must be non-0. This case occurs when */ 709550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* subtracting a small number (which can be reduced to */ 709650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* a sticky bit); see decAddOp. */ 709750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the status accumulator, as usual */ 709850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 709950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine applies rounding while keeping the length of the */ 710050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* coefficient constant. The exponent and status are unchanged */ 710150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* except if: */ 710250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 710350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -- the coefficient was increased and is all nines (in which */ 710450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* case Overflow could occur, and is handled directly here so */ 710550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the caller does not need to re-test for overflow) */ 710650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 710750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -- the coefficient was decreased and becomes all nines (in which */ 710850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* case Underflow could occur, and is also handled directly). */ 710950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 711050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All fields in dn are updated as required. */ 711150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 711250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 711350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decApplyRound(decNumber *dn, decContext *set, Int residue, 711450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 711550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int bump; /* 1 if coefficient needs to be incremented */ 711650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* -1 if coefficient needs to be decremented */ 711750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 711850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue==0) return; /* nothing to apply */ 711950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 712050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bump=0; /* assume a smooth ride */ 712150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 712250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now decide whether, and how, to round, depending on mode */ 712350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho switch (set->round) { 712450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_05UP: { /* round zero or five up (for reround) */ 712550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This is the same as DEC_ROUND_DOWN unless there is a */ 712650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* positive residue and the lsd of dn is 0 or 5, in which case */ 712750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it is bumped; when residue is <0, the number is therefore */ 712850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* bumped down unless the final digit was 1 or 6 (in which */ 712950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* case it is bumped down and then up -- a no-op) */ 713050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int lsd5=*dn->lsu%5; /* get lsd and quintate */ 713150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue<0 && lsd5!=1) bump=-1; 713250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (residue>0 && lsd5==0) bump=1; 713350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [bump==1 could be applied directly; use common path for clarity] */ 713450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-05 */ 713550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 713650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_DOWN: { 713750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* no change, except if negative residue */ 713850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue<0) bump=-1; 713950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-d */ 714050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 714150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_HALF_DOWN: { 714250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue>5) bump=1; 714350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-h-d */ 714450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 714550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_HALF_EVEN: { 714650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue>5) bump=1; /* >0.5 goes up */ 714750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (residue==5) { /* exactly 0.5000... */ 714850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 0.5 goes up iff [new] lsd is odd */ 714950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*dn->lsu & 0x01) bump=1; 715050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 715150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-h-e */ 715250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 715350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_HALF_UP: { 715450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue>=5) bump=1; 715550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-h-u */ 715650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 715750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_UP: { 715850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue>0) bump=1; 715950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-u */ 716050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 716150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_CEILING: { 716250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* same as _UP for positive numbers, and as _DOWN for negatives */ 716350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [negative residue cannot occur on 0] */ 716450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dn)) { 716550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue<0) bump=-1; 716650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 716750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 716850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue>0) bump=1; 716950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 717050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-c */ 717150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 717250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_FLOOR: { 717350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* same as _UP for negative numbers, and as _DOWN for positive */ 717450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [negative residue cannot occur on 0] */ 717550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!decNumberIsNegative(dn)) { 717650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue<0) bump=-1; 717750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 717850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 717950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue>0) bump=1; 718050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 718150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-f */ 718250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 718350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho default: { /* e.g., DEC_ROUND_MAX */ 718450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_context; 718550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || (DECCHECK && DECVERB) 718650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Unknown rounding mode: %d\n", set->round); 718750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 718850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 718950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* switch */ 719050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 719150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now bump the number, up or down, if need be */ 719250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bump==0) return; /* no action required */ 719350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 719450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Simply use decUnitAddSub unless bumping up and the number is */ 719550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* all nines. In this special case set to 100... explicitly */ 719650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* and adjust the exponent by one (as otherwise could overflow */ 719750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the array) */ 719850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Similarly handle all-nines result if bumping down. */ 719950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bump>0) { 720050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up; /* work */ 720150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt count=dn->digits; /* digits to be checked */ 720250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=dn->lsu; ; up++) { 720350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count<=DECDPUN) { 720450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this is the last Unit (the msu) */ 720550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=powers[count]-1) break; /* not still 9s */ 720650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here if it, too, is all nines */ 720750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)powers[count-1]; /* here 999 -> 100 etc. */ 720850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=up-1; up>=dn->lsu; up--) *up=0; /* others all to 0 */ 720950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent++; /* and bump exponent */ 721050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [which, very rarely, could cause Overflow...] */ 721150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((dn->exponent+dn->digits)>set->emax+1) { 721250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetOverflow(dn, set, status); 721350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 721450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; /* done */ 721550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 721650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a full unit to check, with more to come */ 721750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=DECDPUNMAX) break; /* not still 9s */ 721850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=DECDPUN; 721950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* up */ 722050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* bump>0 */ 722150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* -1 */ 722250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here checking for a pre-bump of 1000... (leading 1, all */ 722350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* other digits zero) */ 722450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up, *sup; /* work */ 722550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt count=dn->digits; /* digits to be checked */ 722650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=dn->lsu; ; up++) { 722750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count<=DECDPUN) { 722850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this is the last Unit (the msu) */ 722950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=powers[count-1]) break; /* not 100.. */ 723050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here if have the 1000... case */ 723150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho sup=up; /* save msu pointer */ 723250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)powers[count]-1; /* here 100 in msu -> 999 */ 723350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* others all to all-nines, too */ 723450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=up-1; up>=dn->lsu; up--) *up=(Unit)powers[DECDPUN]-1; 723550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent--; /* and bump exponent */ 723650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 723750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* iff the number was at the subnormal boundary (exponent=etiny) */ 723850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* then the exponent is now out of range, so it will in fact get */ 723950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* clamped to etiny and the final 9 dropped. */ 724050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* printf(">> emin=%d exp=%d sdig=%d\n", set->emin, */ 724150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* dn->exponent, set->digits); */ 724250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent+1==set->emin-set->digits+1) { 724350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count==1 && dn->digits==1) *sup=0; /* here 9 -> 0[.9] */ 724450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 724550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *sup=(Unit)powers[count-1]-1; /* here 999.. in msu -> 99.. */ 724650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits--; 724750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 724850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent++; 724950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded; 725050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 725150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; /* done */ 725250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 725350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 725450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a full unit to check, with more to come */ 725550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=0) break; /* not still 0s */ 725650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=DECDPUN; 725750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* up */ 725850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 725950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* bump<0 */ 726050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 726150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Actual bump needed. Do it. */ 726250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decUnitAddSub(dn->lsu, D2U(dn->digits), uarrone, 1, 0, dn->lsu, bump); 726350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decApplyRound */ 726450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 726550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECSUBSET 726650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 726750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decFinish -- finish processing a number */ 726850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 726950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number */ 727050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 727150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* residue is the rounding accumulator (as in decApplyRound) */ 727250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the accumulator */ 727350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 727450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This finishes off the current number by: */ 727550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 1. If not extended: */ 727650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* a. Converting a zero result to clean '0' */ 727750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* b. Reducing positive exponents to 0, if would fit in digits */ 727850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 2. Checking for overflow and subnormals (always) */ 727950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Note this is just Finalize when no subset arithmetic. */ 728050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All fields are updated as required. */ 728150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 728250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decFinish(decNumber *dn, decContext *set, Int *residue, 728350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 728450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 728550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ISZERO(dn) { /* value is zero */ 728650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=0; /* clean exponent .. */ 728750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=0; /* .. and sign */ 728850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; /* no error possible */ 728950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 729050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent>=0) { /* non-negative exponent */ 729150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* >0; reduce to integer if possible */ 729250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->digits >= (dn->exponent+dn->digits)) { 729350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=decShiftToMost(dn->lsu, dn->digits, dn->exponent); 729450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=0; 729550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 729650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 729750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* !extended */ 729850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 729950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinalize(dn, set, residue, status); 730050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decFinish */ 730150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 730250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 730350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 730450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decFinalize -- final check, clamp, and round of a number */ 730550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 730650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number */ 730750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 730850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* residue is the rounding accumulator (as in decApplyRound) */ 730950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the status accumulator */ 731050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 731150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This finishes off the current number by checking for subnormal */ 731250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* results, applying any pending rounding, checking for overflow, */ 731350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and applying any clamping. */ 731450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Underflow and overflow conditions are raised as appropriate. */ 731550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All fields are updated as required. */ 731650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 731750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decFinalize(decNumber *dn, decContext *set, Int *residue, 731850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 731950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift; /* shift needed if clamping */ 732050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int tinyexp=set->emin-dn->digits+1; /* precalculate subnormal boundary */ 732150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 732250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Must be careful, here, when checking the exponent as the */ 732350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* adjusted exponent could overflow 31 bits [because it may already */ 732450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* be up to twice the expected]. */ 732550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 732650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* First test for subnormal. This must be done before any final */ 732750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* round as the result could be rounded to Nmin or 0. */ 732850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent<=tinyexp) { /* prefilter */ 732950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int comp; 733050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber nmin; 733150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* A very nasty case here is dn == Nmin and residue<0 */ 733250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent<tinyexp) { 733350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Go handle subnormals; this will apply round if needed. */ 733450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetSubnormal(dn, set, residue, status); 733550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 733650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 733750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Equals case: only subnormal if dn=Nmin and negative residue */ 733850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&nmin); 733950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho nmin.lsu[0]=1; 734050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho nmin.exponent=set->emin; 734150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho comp=decCompare(dn, &nmin, 1); /* (signless compare) */ 734250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (comp==BADINT) { /* oops */ 734350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; /* abandon... */ 734450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 734550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 734650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue<0 && comp==0) { /* neg residue and dn==Nmin */ 734750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decApplyRound(dn, set, *residue, status); /* might force down */ 734850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetSubnormal(dn, set, residue, status); 734950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 735050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 735150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 735250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 735350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now apply any pending round (this could raise overflow). */ 735450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue!=0) decApplyRound(dn, set, *residue, status); 735550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 735650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Check for overflow [redundant in the 'rare' case] or clamp */ 735750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent<=set->emax-set->digits+1) return; /* neither needed */ 735850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 735950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 736050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here when might have an overflow or clamp to do */ 736150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent>set->emax-dn->digits+1) { /* too big */ 736250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetOverflow(dn, set, status); 736350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 736450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 736550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here when the result is normal but in clamp range */ 736650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->clamp) return; 736750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 736850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here when need to apply the IEEE exponent clamp (fold-down) */ 736950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho shift=dn->exponent-(set->emax-set->digits+1); 737050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 737150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* shift coefficient (if non-zero) */ 737250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!ISZERO(dn)) { 737350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=decShiftToMost(dn->lsu, dn->digits, shift); 737450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 737550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent-=shift; /* adjust the exponent to match */ 737650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Clamped; /* and record the dirty deed */ 737750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 737850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decFinalize */ 737950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 738050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 738150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decSetOverflow -- set number to proper overflow value */ 738250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 738350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number (used for sign [only] and result) */ 738450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context [used for the rounding mode, etc.] */ 738550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status contains the current status to be updated */ 738650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 738750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This sets the sign of a number and sets its value to either */ 738850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Infinity or the maximum finite value, depending on the sign of */ 738950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn and the rounding mode, following IEEE 754 rules. */ 739050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 739150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetOverflow(decNumber *dn, decContext *set, uInt *status) { 739250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag needmax=0; /* result is maximum finite value */ 739350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte sign=dn->bits&DECNEG; /* clean and save sign bit */ 739450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 739550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(dn)) { /* zero does not overflow magnitude */ 739650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int emax=set->emax; /* limit value */ 739750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->clamp) emax-=set->digits-1; /* lower if clamping */ 739850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent>emax) { /* clamp required */ 739950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=emax; 740050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Clamped; 740150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 740250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 740350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 740450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 740550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(dn); 740650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho switch (set->round) { 740750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_DOWN: { 740850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needmax=1; /* never Infinity */ 740950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-d */ 741050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_05UP: { 741150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needmax=1; /* never Infinity */ 741250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-05 */ 741350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_CEILING: { 741450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (sign) needmax=1; /* Infinity if non-negative */ 741550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-c */ 741650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_FLOOR: { 741750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!sign) needmax=1; /* Infinity if negative */ 741850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-f */ 741950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho default: break; /* Infinity in all other cases */ 742050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 742150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needmax) { 742250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetMaxValue(dn, set); 742350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=sign; /* set sign */ 742450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 742550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else dn->bits=sign|DECINF; /* Value is +/-Infinity */ 742650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Overflow | DEC_Inexact | DEC_Rounded; 742750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decSetOverflow */ 742850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 742950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 743050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decSetMaxValue -- set number to +Nmax (maximum normal value) */ 743150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 743250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to set */ 743350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context [used for digits and emax] */ 743450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 743550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This sets the number to the maximum positive value. */ 743650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 743750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetMaxValue(decNumber *dn, decContext *set) { 743850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up; /* work */ 743950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int count=set->digits; /* nines to add */ 744050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=count; 744150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* fill in all nines to set maximum value */ 744250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=dn->lsu; ; up++) { 744350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count>DECDPUN) *up=DECDPUNMAX; /* unit full o'nines */ 744450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* this is the msu */ 744550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)(powers[count]-1); 744650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 744750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 744850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=DECDPUN; /* filled those digits */ 744950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* up */ 745050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=0; /* + sign */ 745150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=set->emax-set->digits+1; 745250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decSetMaxValue */ 745350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 745450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 745550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decSetSubnormal -- process value whose exponent is <Emin */ 745650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 745750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number (used as input as well as output; it may have */ 745850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* an allowed subnormal value, which may need to be rounded) */ 745950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context [used for the rounding mode] */ 746050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* residue is any pending residue */ 746150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status contains the current status to be updated */ 746250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 746350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If subset mode, set result to zero and set Underflow flags. */ 746450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 746550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Value may be zero with a low exponent; this does not set Subnormal */ 746650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* but the exponent will be clamped to Etiny. */ 746750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 746850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Otherwise ensure exponent is not out of range, and round as */ 746950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* necessary. Underflow is set if the result is Inexact. */ 747050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 747150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetSubnormal(decNumber *dn, decContext *set, Int *residue, 747250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 747350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset; /* work */ 747450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int etiny, adjust; /* .. */ 747550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 747650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 747750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* simple set to zero and 'hard underflow' for subset */ 747850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 747950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(dn); 748050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* always full overflow */ 748150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded; 748250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 748350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 748450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 748550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 748650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Full arithmetic -- allow subnormals, rounded to minimum exponent */ 748750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (Etiny) if needed */ 748850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho etiny=set->emin-(set->digits-1); /* smallest allowed exponent */ 748950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 749050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ISZERO(dn) { /* value is zero */ 749150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* residue can never be non-zero here */ 749250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 749350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue!=0) { 749450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("++ Subnormal 0 residue %ld\n", (LI)*residue); 749550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 749650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 749750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 749850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent<etiny) { /* clamp required */ 749950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=etiny; 750050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Clamped; 750150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 750250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 750350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 750450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 750550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Subnormal; /* have a non-zero subnormal */ 750650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adjust=etiny-dn->exponent; /* calculate digits to remove */ 750750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adjust<=0) { /* not out of range; unrounded */ 750850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* residue can never be non-zero here, except in the Nmin-residue */ 750950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* case (which is a subnormal result), so can take fast-path here */ 751050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it may already be inexact (from setting the coefficient) */ 751150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*status&DEC_Inexact) *status|=DEC_Underflow; 751250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 751350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 751450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 751550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* adjust>0, so need to rescale the result so exponent becomes Etiny */ 751650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [this code is similar to that in rescale] */ 751750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset=*set; /* clone rounding, etc. */ 751850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.digits=dn->digits-adjust; /* set requested length */ 751950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.emin-=adjust; /* and adjust emin to match */ 752050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [note that the latter can be <1, here, similar to Rescale case] */ 752150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetCoeff(dn, &workset, dn->lsu, dn->digits, residue, status); 752250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decApplyRound(dn, &workset, *residue, status); 752350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 752450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Use 754 default rule: Underflow is set iff Inexact */ 752550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [independent of whether trapped] */ 752650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*status&DEC_Inexact) *status|=DEC_Underflow; 752750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 752850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if rounded up a 999s case, exponent will be off by one; adjust */ 752950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* back if so [it will fit, because it was shortened earlier] */ 753050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent>etiny) { 753150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=decShiftToMost(dn->lsu, dn->digits, 1); 753250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent--; /* (re)adjust the exponent. */ 753350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 753450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 753550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if rounded to zero, it is by definition clamped... */ 753650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(dn)) *status|=DEC_Clamped; 753750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decSetSubnormal */ 753850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 753950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 754050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCheckMath - check entry conditions for a math function */ 754150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 754250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This checks the context and the operand */ 754350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 754450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is the operand to check */ 754550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context to check */ 754650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is unchanged if both are good */ 754750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 754850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns non-zero if status is changed, 0 otherwise */ 754950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 755050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Restrictions enforced: */ 755150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 755250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* digits, emax, and -emin in the context must be less than */ 755350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* DEC_MAX_MATH (999999), and A must be within these bounds if */ 755450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* non-zero. Invalid_operation is set in the status if a */ 755550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* restriction is violated. */ 755650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 755750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic uInt decCheckMath(const decNumber *rhs, decContext *set, 755850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 755950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt save=*status; /* record */ 756050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->digits>DEC_MAX_MATH 756150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || set->emax>DEC_MAX_MATH 756250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || -set->emin>DEC_MAX_MATH) *status|=DEC_Invalid_context; 756350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if ((rhs->digits>DEC_MAX_MATH 756450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || rhs->exponent+rhs->digits>DEC_MAX_MATH+1 756550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || rhs->exponent+rhs->digits<2*(1-DEC_MAX_MATH)) 756650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && !ISZERO(rhs)) *status|=DEC_Invalid_operation; 756750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return (*status!=save); 756850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decCheckMath */ 756950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 757050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 757150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decGetInt -- get integer from a number */ 757250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 757350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number [which will not be altered] */ 757450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 757550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns one of: */ 757650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* BADINT if there is a non-zero fraction */ 757750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the converted integer */ 757850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* BIGEVEN if the integer is even and magnitude > 2*10**9 */ 757950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* BIGODD if the integer is odd and magnitude > 2*10**9 */ 758050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 758150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This checks and gets a whole number from the input decNumber. */ 758250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The sign can be determined from dn by the caller when BIGEVEN or */ 758350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* BIGODD is returned. */ 758450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 758550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decGetInt(const decNumber *dn) { 758650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int theInt; /* result accumulator */ 758750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up; /* work */ 758850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int got; /* digits (real or not) processed */ 758950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ilength=dn->digits+dn->exponent; /* integral length */ 759050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag neg=decNumberIsNegative(dn); /* 1 if -ve */ 759150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 759250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The number must be an integer that fits in 10 digits */ 759350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Assert, here, that 10 is enough for any rescale Etiny */ 759450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DEC_MAX_EMAX > 999999999 759550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #error GetInt may need updating [for Emax] 759650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 759750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DEC_MIN_EMIN < -999999999 759850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #error GetInt may need updating [for Emin] 759950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 760050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(dn)) return 0; /* zeros are OK, with any exponent */ 760150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 760250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=dn->lsu; /* ready for lsu */ 760350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho theInt=0; /* ready to accumulate */ 760450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent>=0) { /* relatively easy */ 760550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* no fractional part [usual]; allow for positive exponent */ 760650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho got=dn->exponent; 760750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 760850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* -ve exponent; some fractional part to check and discard */ 760950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int count=-dn->exponent; /* digits to discard */ 761050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* spin up whole units until reach the Unit with the unit digit */ 761150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; count>=DECDPUN; up++) { 761250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=0) return BADINT; /* non-zero Unit to discard */ 761350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=DECDPUN; 761450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 761550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count==0) got=0; /* [a multiple of DECDPUN] */ 761650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* [not multiple of DECDPUN] */ 761750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int rem; /* work */ 761850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* slice off fraction digits and check for non-zero */ 761950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 762050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho theInt=QUOT10(*up, count); 762150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=*up-theInt*powers[count]; 762250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 762350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=*up%powers[count]; /* slice off discards */ 762450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho theInt=*up/powers[count]; 762550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 762650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rem!=0) return BADINT; /* non-zero fraction */ 762750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it looks good */ 762850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho got=DECDPUN-count; /* number of digits so far */ 762950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; /* ready for next */ 763050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 763150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 763250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now it's known there's no fractional part */ 763350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 763450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* tricky code now, to accumulate up to 9.3 digits */ 763550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (got==0) {theInt=*up; got+=DECDPUN; up++;} /* ensure lsu is there */ 763650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 763750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ilength<11) { 763850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int save=theInt; 763950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* collect any remaining unit(s) */ 764050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; got<ilength; up++) { 764150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho theInt+=*up*powers[got]; 764250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho got+=DECDPUN; 764350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 764450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ilength==10) { /* need to check for wrap */ 764550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (theInt/(Int)powers[got-DECDPUN]!=(Int)*(up-1)) ilength=11; 764650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [that test also disallows the BADINT result case] */ 764750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (neg && theInt>1999999997) ilength=11; 764850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (!neg && theInt>999999999) ilength=11; 764950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ilength==11) theInt=save; /* restore correct low bit */ 765050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 765150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 765250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 765350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ilength>10) { /* too big */ 765450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (theInt&1) return BIGODD; /* bottom bit 1 */ 765550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return BIGEVEN; /* bottom bit 0 */ 765650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 765750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 765850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (neg) theInt=-theInt; /* apply sign */ 765950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return theInt; 766050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decGetInt */ 766150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 766250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 766350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decDecap -- decapitate the coefficient of a number */ 766450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 766550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to be decapitated */ 766650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* drop is the number of digits to be removed from the left of dn; */ 766750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* this must be <= dn->digits (if equal, the coefficient is */ 766850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set to 0) */ 766950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 767050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Returns dn; dn->digits will be <= the initial digits less drop */ 767150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (after removing drop digits there may be leading zero digits */ 767250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* which will also be removed). Only dn->lsu and dn->digits change. */ 767350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 767450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber *decDecap(decNumber *dn, Int drop) { 767550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *msu; /* -> target cut point */ 767650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int cut; /* work */ 767750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (drop>=dn->digits) { /* losing the whole thing */ 767850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 767950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (drop>dn->digits) 768050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("decDecap called with drop>digits [%ld>%ld]\n", 768150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (LI)drop, (LI)dn->digits); 768250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 768350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->lsu[0]=0; 768450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=1; 768550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 768650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 768750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msu=dn->lsu+D2U(dn->digits-drop)-1; /* -> likely msu */ 768850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=MSUDIGITS(dn->digits-drop); /* digits to be in use in msu */ 768950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut!=DECDPUN) *msu%=powers[cut]; /* clear left digits */ 769050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* that may have left leading zero digits, so do a proper count... */ 769150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=decGetDigits(dn->lsu, msu-dn->lsu+1); 769250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 769350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decDecap */ 769450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 769550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 769650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decBiStr -- compare string with pairwise options */ 769750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 769850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* targ is the string to compare */ 769950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* str1 is one of the strings to compare against (length may be 0) */ 770050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* str2 is the other; it must be the same length as str1 */ 770150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 770250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns 1 if strings compare equal, (that is, it is the same */ 770350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* length as str1 and str2, and each character of targ is in either */ 770450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* str1 or str2 in the corresponding position), or 0 otherwise */ 770550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 770650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This is used for generic caseless compare, including the awkward */ 770750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* case of the Turkish dotted and dotless Is. Use as (for example): */ 770850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if (decBiStr(test, "mike", "MIKE")) ... */ 770950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 771050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Flag decBiStr(const char *targ, const char *str1, const char *str2) { 771150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;;targ++, str1++, str2++) { 771250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*targ!=*str1 && *targ!=*str2) return 0; 771350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* *targ has a match in one (or both, if terminator) */ 771450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*targ=='\0') break; 771550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* forever */ 771650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1; 771750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decBiStr */ 771850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 771950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 772050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNaNs -- handle NaN operand or operands */ 772150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 772250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is the result number */ 772350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is the first operand */ 772450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is the second operand, or NULL if none */ 772550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* context is used to limit payload length */ 772650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status contains the current status */ 772750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns res in case convenient */ 772850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 772950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Called when one or both operands is a NaN, and propagates the */ 773050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* appropriate result to res. When an sNaN is found, it is changed */ 773150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* to a qNaN and Invalid operation is set. */ 773250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 773350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decNaNs(decNumber *res, const decNumber *lhs, 773450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set, 773550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 773650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This decision tree ends up with LHS being the source pointer, */ 773750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* and status updated if need be */ 773850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->bits & DECSNAN) 773950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation | DEC_sNaN; 774050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (rhs==NULL); 774150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (rhs->bits & DECSNAN) { 774250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=rhs; 774350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation | DEC_sNaN; 774450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 774550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (lhs->bits & DECNAN); 774650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else lhs=rhs; 774750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 774850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* propagate the payload */ 774950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits<=set->digits) uprv_decNumberCopy(res, lhs); /* easy */ 775050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* too long */ 775150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *ul; 775250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *ur, *uresp1; 775350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* copy safe number of units, then decapitate */ 775450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=lhs->bits; /* need sign etc. */ 775550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uresp1=res->lsu+D2U(set->digits); 775650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (ur=res->lsu, ul=lhs->lsu; ur<uresp1; ur++, ul++) *ur=*ul; 775750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=D2U(set->digits)*DECDPUN; 775850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* maybe still too long */ 775950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits>set->digits) decDecap(res, res->digits-set->digits); 776050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 776150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 776250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits&=~DECSNAN; /* convert any sNaN to NaN, while */ 776350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits|=DECNAN; /* .. preserving sign */ 776450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=0; /* clean exponent */ 776550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [coefficient was copied/decapitated] */ 776650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 776750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNaNs */ 776850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 776950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 777050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decStatus -- apply non-zero status */ 777150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 777250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to set if error */ 777350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status contains the current status (not yet in context) */ 777450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 777550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 777650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If the status is an error status, the number is set to a NaN, */ 777750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* unless the error was an overflow, divide-by-zero, or underflow, */ 777850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* in which case the number will have already been set. */ 777950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 778050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The context status is then updated with the new status. Note that */ 778150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* this may raise a signal, so control may never return from this */ 778250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* routine (hence resources must be recovered before it is called). */ 778350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 778450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decStatus(decNumber *dn, uInt status, decContext *set) { 778550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status & DEC_NaNs) { /* error status -> NaN */ 778650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if cause was an sNaN, clear and propagate [NaN is already set up] */ 778750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status & DEC_sNaN) status&=~DEC_sNaN; 778850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 778950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(dn); /* other error: clean throughout */ 779050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=DECNAN; /* and make a quiet NaN */ 779150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 779250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 779350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextSetStatus(set, status); /* [may not return] */ 779450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 779550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decStatus */ 779650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 779750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 779850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decGetDigits -- count digits in a Units array */ 779950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 780050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* uar is the Unit array holding the number (this is often an */ 780150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* accumulator of some sort) */ 780250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* len is the length of the array in units [>=1] */ 780350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 780450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns the number of (significant) digits in the array */ 780550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 780650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All leading zeros are excluded, except the last if the array has */ 780750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* only zero Units. */ 780850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 780950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This may be called twice during some operations. */ 781050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decGetDigits(Unit *uar, Int len) { 781150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up=uar+(len-1); /* -> msu */ 781250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int digits=(len-1)*DECDPUN+1; /* possible digits excluding msu */ 781350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>4 781450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt const *pow; /* work */ 781550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 781650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (at least 1 in final msu) */ 781750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 781850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (len<1) printf("decGetDigits called with len<1 [%ld]\n", (LI)len); 781950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 782050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 782150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; up>=uar; up--) { 782250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up==0) { /* unit is all 0s */ 782350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (digits==1) break; /* a zero has one digit */ 782450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho digits-=DECDPUN; /* adjust for 0 unit */ 782550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue;} 782650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* found the first (most significant) non-zero Unit */ 782750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>1 /* not done yet */ 782850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up<10) break; /* is 1-9 */ 782950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho digits++; 783050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>2 /* not done yet */ 783150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up<100) break; /* is 10-99 */ 783250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho digits++; 783350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>3 /* not done yet */ 783450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up<1000) break; /* is 100-999 */ 783550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho digits++; 783650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>4 /* count the rest ... */ 783750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (pow=&powers[4]; *up>=*pow; pow++) digits++; 783850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 783950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 784050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 784150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 784250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 784350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* up */ 784450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return digits; 784550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decGetDigits */ 784650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 784750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECTRACE | DECCHECK 784850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 784950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberShow -- display a number [debug aid] */ 785050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to show */ 785150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 785250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Shows: sign, exponent, coefficient (msu first), digits */ 785350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* or: sign, special-value */ 785450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 785550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* this is public so other modules can use it */ 785650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid uprv_decNumberShow(const decNumber *dn) { 785750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up; /* work */ 785850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt u, d; /* .. */ 785950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int cut; /* .. */ 786050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char isign='+'; /* main sign */ 786150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn==NULL) { 786250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("NULL\n"); 786350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return;} 786450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dn)) isign='-'; 786550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf(" >> %c ", isign); 786650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECSPECIAL) { /* Is a special value */ 786750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(dn)) printf("Infinity"); 786850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* a NaN */ 786950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECSNAN) printf("sNaN"); /* signalling NaN */ 787050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else printf("NaN"); 787150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 787250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if coefficient and exponent are 0, no more to do */ 787350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent==0 && dn->digits==1 && *dn->lsu==0) { 787450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("\n"); 787550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return;} 787650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* drop through to report other information */ 787750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf(" "); 787850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 787950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 788050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now carefully display the coefficient */ 788150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=dn->lsu+D2U(dn->digits)-1; /* msu */ 788250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("%ld", (LI)*up); 788350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=up-1; up>=dn->lsu; up--) { 788450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=*up; 788550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf(":"); 788650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (cut=DECDPUN-1; cut>=0; cut--) { 788750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho d=u/powers[cut]; 788850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u-=d*powers[cut]; 788950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("%ld", (LI)d); 789050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* cut */ 789150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* up */ 789250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent!=0) { 789350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char esign='+'; 789450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent<0) esign='-'; 789550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf(" E%c%ld", esign, (LI)abs(dn->exponent)); 789650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 789750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf(" [%ld]\n", (LI)dn->digits); 789850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberShow */ 789950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 790050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 790150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECTRACE || DECCHECK 790250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 790350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decDumpAr -- display a unit array [debug/check aid] */ 790450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* name is a single-character tag name */ 790550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ar is the array to display */ 790650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* len is the length of the array in Units */ 790750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 790850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decDumpAr(char name, const Unit *ar, Int len) { 790950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i; 791050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *spec; 791150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==9 791250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%09d "; 791350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==8 791450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%08d "; 791550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==7 791650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%07d "; 791750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==6 791850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%06d "; 791950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==5 792050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%05d "; 792150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==4 792250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%04d "; 792350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==3 792450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%03d "; 792550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==2 792650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%02d "; 792750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 792850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%d "; 792950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 793050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf(" :%c: ", name); 793150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i=len-1; i>=0; i--) { 793250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (i==len-1) printf("%ld ", (LI)ar[i]); 793350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else printf(spec, ar[i]); 793450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 793550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("\n"); 793650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return;} 793750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 793850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 793950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECCHECK 794050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 794150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCheckOperands -- check operand(s) to a routine */ 794250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is the result structure (not checked; it will be set to */ 794350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* quiet NaN if error found (and it is not NULL)) */ 794450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is the first operand (may be DECUNRESU) */ 794550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is the second (may be DECUNUSED) */ 794650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context (may be DECUNCONT) */ 794750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns 0 if both operands, and the context are clean, or 1 */ 794850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* otherwise (in which case the context will show an error, */ 794950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* unless NULL). Note that res is not cleaned; caller should */ 795050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* handle this so res=NULL case is safe. */ 795150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The caller is expected to abandon immediately if 1 is returned. */ 795250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 795350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Flag decCheckOperands(decNumber *res, const decNumber *lhs, 795450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 795550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag bad=0; 795650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set==NULL) { /* oops; hopeless */ 795750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 795850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Reference to context is NULL.\n"); 795950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 796050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bad=1; 796150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 796250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (set!=DECUNCONT 796350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && (set->digits<1 || set->round>=DEC_ROUND_MAX)) { 796450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bad=1; 796550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 796650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Bad context [digits=%ld round=%ld].\n", 796750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (LI)set->digits, (LI)set->round); 796850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 796950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 797050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 797150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res==NULL) { 797250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bad=1; 797350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 797450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this one not DECVERB as standard tests include NULL */ 797550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Reference to result is NULL.\n"); 797650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 797750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 797850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!bad && lhs!=DECUNUSED) bad=(decCheckNumber(lhs)); 797950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!bad && rhs!=DECUNUSED) bad=(decCheckNumber(rhs)); 798050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 798150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bad) { 798250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set!=DECUNCONT) uprv_decContextSetStatus(set, DEC_Invalid_operation); 798350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res!=DECUNRESU && res!=NULL) { 798450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 798550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=DECNAN; /* qNaN */ 798650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 798750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 798850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return bad; 798950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decCheckOperands */ 799050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 799150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 799250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCheckNumber -- check a number */ 799350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to check */ 799450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns 0 if the number is clean, or 1 otherwise */ 799550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 799650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The number is considered valid if it could be a result from some */ 799750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* operation in some valid context. */ 799850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 799950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Flag decCheckNumber(const decNumber *dn) { 800050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up; /* work */ 800150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt maxuint; /* .. */ 800250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ae, d, digits; /* .. */ 800350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int emin, emax; /* .. */ 800450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 800550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn==NULL) { /* hopeless */ 800650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 800750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this one not DECVERB as standard tests include NULL */ 800850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Reference to decNumber is NULL.\n"); 800950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 801050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 801150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 801250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* check special values */ 801350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits & DECSPECIAL) { 801450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent!=0) { 801550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 801650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Exponent %ld (not 0) for a special value [%02x].\n", 801750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (LI)dn->exponent, dn->bits); 801850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 801950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 802050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 802150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 2003.09.08: NaNs may now have coefficients, so next tests Inf only */ 802250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(dn)) { 802350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->digits!=1) { 802450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 802550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Digits %ld (not 1) for an infinity.\n", (LI)dn->digits); 802650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 802750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 802850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*dn->lsu!=0) { 802950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 803050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("LSU %ld (not 0) for an infinity.\n", (LI)*dn->lsu); 803150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 803250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('I', dn->lsu, D2U(dn->digits)); 803350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 803450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* Inf */ 803550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 2002.12.26: negative NaNs can now appear through proposed IEEE */ 803650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* concrete formats (decimal64, etc.). */ 803750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; 803850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 803950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 804050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* check the coefficient */ 804150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->digits<1 || dn->digits>DECNUMMAXP) { 804250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 804350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Digits %ld in number.\n", (LI)dn->digits); 804450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 804550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 804650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 804750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho d=dn->digits; 804850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 804950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=dn->lsu; d>0; up++) { 805050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (d>DECDPUN) maxuint=DECDPUNMAX; 805150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* reached the msu */ 805250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxuint=powers[d]-1; 805350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->digits>1 && *up<powers[d-1]) { 805450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 805550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Leading 0 in number.\n"); 805650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberShow(dn); 805750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 805850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 805950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 806050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up>maxuint) { 806150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 806250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Bad Unit [%08lx] in %ld-digit number at offset %ld [maxuint %ld].\n", 806350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (LI)*up, (LI)dn->digits, (LI)(up-dn->lsu), (LI)maxuint); 806450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 806550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 806650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho d-=DECDPUN; 806750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 806850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 806950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* check the exponent. Note that input operands can have exponents */ 807050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* which are out of the set->emin/set->emax and set->digits range */ 807150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (just as they can have more digits than set->digits). */ 807250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ae=dn->exponent+dn->digits-1; /* adjusted exponent */ 807350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho emax=DECNUMMAXE; 807450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho emin=DECNUMMINE; 807550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho digits=DECNUMMAXP; 807650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ae<emin-(digits-1)) { 807750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 807850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Adjusted exponent underflow [%ld].\n", (LI)ae); 807950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberShow(dn); 808050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 808150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 808250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ae>+emax) { 808350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 808450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Adjusted exponent overflow [%ld].\n", (LI)ae); 808550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberShow(dn); 808650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 808750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 808850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 808950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; /* it's OK */ 809050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decCheckNumber */ 809150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 809250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 809350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCheckInexact -- check a normal finite inexact result has digits */ 809450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to check */ 809550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context (for status and precision) */ 809650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* sets Invalid operation, etc., if some digits are missing */ 809750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* [this check is not made for DECSUBSET compilation or when */ 809850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* subnormal is not set] */ 809950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 810050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decCheckInexact(const decNumber *dn, decContext *set) { 810150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if !DECSUBSET && DECEXTFLAG 810250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((set->status & (DEC_Inexact|DEC_Subnormal))==DEC_Inexact 810350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && (set->digits!=dn->digits) && !(dn->bits & DECSPECIAL)) { 810450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 810550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Insufficient digits [%ld] on normal Inexact result.\n", 810650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (LI)dn->digits); 810750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberShow(dn); 810850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 810950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextSetStatus(set, DEC_Invalid_operation); 811050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 811150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 811250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* next is a noop for quiet compiler */ 811350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn!=NULL && dn->digits==0) set->status|=DEC_Invalid_operation; 811450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 811550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 811650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decCheckInexact */ 811750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 811850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 811950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECALLOC 812050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#undef malloc 812150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#undef free 812250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 812350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decMalloc -- accountable allocation routine */ 812450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* n is the number of bytes to allocate */ 812550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 812650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Semantics is the same as the stdlib malloc routine, but bytes */ 812750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* allocated are accounted for globally, and corruption fences are */ 812850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* added before and after the 'actual' storage. */ 812950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 813050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine allocates storage with an extra twelve bytes; 8 are */ 813150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* at the start and hold: */ 813250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 0-3 the original length requested */ 813350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 4-7 buffer corruption detection fence (DECFENCE, x4) */ 813450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The 4 bytes at the end also hold a corruption fence (DECFENCE, x4) */ 813550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 813650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void *decMalloc(size_t n) { 813750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt size=n+12; /* true size */ 813850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho void *alloc; /* -> allocated storage */ 813950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte *b, *b0; /* work */ 814050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt uiwork; /* for macros */ 814150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 814250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloc=malloc(size); /* -> allocated storage */ 814350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloc==NULL) return NULL; /* out of strorage */ 814450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b0=(uByte *)alloc; /* as bytes */ 814550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAllocBytes+=n; /* account for storage */ 814650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBFROMUI(alloc, n); /* save n */ 814750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* printf(" alloc ++ dAB: %ld (%ld)\n", (LI)decAllocBytes, (LI)n); */ 814850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (b=b0+4; b<b0+8; b++) *b=DECFENCE; 814950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (b=b0+n+8; b<b0+n+12; b++) *b=DECFENCE; 815050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return b0+8; /* -> play area */ 815150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decMalloc */ 815250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 815350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 815450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decFree -- accountable free routine */ 815550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* alloc is the storage to free */ 815650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 815750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Semantics is the same as the stdlib malloc routine, except that */ 815850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the global storage accounting is updated and the fences are */ 815950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* checked to ensure that no routine has written 'out of bounds'. */ 816050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 816150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine first checks that the fences have not been corrupted. */ 816250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* It then frees the storage using the 'truw' storage address (that */ 816350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* is, offset by 8). */ 816450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 816550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decFree(void *alloc) { 816650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt n; /* original length */ 816750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte *b, *b0; /* work */ 816850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt uiwork; /* for macros */ 816950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 817050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloc==NULL) return; /* allowed; it's a nop */ 817150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b0=(uByte *)alloc; /* as bytes */ 817250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b0-=8; /* -> true start of storage */ 817350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho n=UBTOUI(b0); /* lift length */ 817450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (b=b0+4; b<b0+8; b++) if (*b!=DECFENCE) 817550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("=== Corrupt byte [%02x] at offset %d from %ld ===\n", *b, 817650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b-b0-8, (LI)b0); 817750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (b=b0+n+8; b<b0+n+12; b++) if (*b!=DECFENCE) 817850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("=== Corrupt byte [%02x] at offset +%d from %ld, n=%ld ===\n", *b, 817950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b-b0-8, (LI)b0, (LI)n); 818050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho free(b0); /* drop the storage */ 818150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAllocBytes-=n; /* account for storage */ 818250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* printf(" free -- dAB: %d (%d)\n", decAllocBytes, -n); */ 818350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decFree */ 818450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define malloc(a) decMalloc(a) 818550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define free(a) decFree(a) 818650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 8187