150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Decimal Number arithmetic module */ 350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 402c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho/* Copyright (c) IBM Corporation, 2000-2012. 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. */ 18450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 18550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Constants */ 18650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Public lookup table used by the D2U macro */ 18750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst uByte d2utable[DECMAXD2U+1]=D2UTABLE; 18850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 18950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DECVERB 1 /* set to 1 for verbose DECCHECK */ 19050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define powers DECPOWERS /* old internal name */ 19150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 19250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Local constants */ 19350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DIVIDE 0x80 /* Divide operators */ 19450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define REMAINDER 0x40 /* .. */ 19550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DIVIDEINT 0x20 /* .. */ 19650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define REMNEAR 0x10 /* .. */ 19750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPARE 0x01 /* Compare operators */ 19850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPMAX 0x02 /* .. */ 19950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPMIN 0x03 /* .. */ 20050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPTOTAL 0x04 /* .. */ 20150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPNAN 0x05 /* .. [NaN processing] */ 20250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPSIG 0x06 /* .. [signaling COMPARE] */ 20350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPMAXMAG 0x07 /* .. */ 20450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define COMPMINMAG 0x08 /* .. */ 20550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 20650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DEC_sNaN 0x40000000 /* local status: sNaN signal */ 20750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define BADINT (Int)0x80000000 /* most-negative Int; error indicator */ 20850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Next two indicate an integer >= 10**6, and its parity (bottom bit) */ 20950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define BIGEVEN (Int)0x80000002 21050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define BIGODD (Int)0x80000003 21150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 21250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Unit uarrone[1]={1}; /* Unit array of 1, used for incrementing */ 21350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 21450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Granularity-dependent code */ 21550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECDPUN<=4 21650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define eInt Int /* extended integer */ 21750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define ueInt uInt /* unsigned extended integer */ 21850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Constant multipliers for divide-by-power-of five using reciprocal */ 21950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* multiply, after removing powers of 2 by shifting, and final shift */ 22050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* of 17 [we only need up to **4] */ 22150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho static const uInt multies[]={131073, 26215, 5243, 1049, 210}; 22250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* QUOT10 -- macro to return the quotient of unit u divided by 10**n */ 22350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17) 22450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#else 22550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* For DECDPUN>4 non-ANSI-89 64-bit types are needed. */ 22650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if !DECUSE64 22750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #error decNumber.c: DECUSE64 must be 1 when DECDPUN>4 22850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 22950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define eInt Long /* extended integer */ 23050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define ueInt uLong /* unsigned extended integer */ 23150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 23250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 23350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Local routines */ 23450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decAddOp(decNumber *, const decNumber *, const decNumber *, 23550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *, uByte, uInt *); 23650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Flag decBiStr(const char *, const char *, const char *); 23750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic uInt decCheckMath(const decNumber *, decContext *, uInt *); 23850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decApplyRound(decNumber *, decContext *, Int, uInt *); 23950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decCompare(const decNumber *lhs, const decNumber *rhs, Flag); 24050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decCompareOp(decNumber *, const decNumber *, 24150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *, decContext *, 24250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag, uInt *); 24350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decCopyFit(decNumber *, const decNumber *, decContext *, 24450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int *, uInt *); 24550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decDecap(decNumber *, Int); 24650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decDivideOp(decNumber *, const decNumber *, 24750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *, decContext *, Flag, uInt *); 24850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decExpOp(decNumber *, const decNumber *, 24950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *, uInt *); 25050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decFinalize(decNumber *, decContext *, Int *, uInt *); 25150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decGetDigits(Unit *, Int); 25250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decGetInt(const decNumber *); 25350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decLnOp(decNumber *, const decNumber *, 25450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *, uInt *); 25550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decMultiplyOp(decNumber *, const decNumber *, 25650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *, decContext *, 25750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *); 25850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decNaNs(decNumber *, const decNumber *, 25950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *, decContext *, uInt *); 26050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decQuantizeOp(decNumber *, const decNumber *, 26150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *, decContext *, Flag, 26250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *); 26350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decReverse(Unit *, Unit *); 26450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetCoeff(decNumber *, decContext *, const Unit *, 26550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int, Int *, uInt *); 26650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetMaxValue(decNumber *, decContext *); 26750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetOverflow(decNumber *, decContext *, uInt *); 26850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetSubnormal(decNumber *, decContext *, Int *, uInt *); 26950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decShiftToLeast(Unit *, Int, Int); 27050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decShiftToMost(Unit *, Int, Int); 27150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decStatus(decNumber *, uInt, decContext *); 27250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decToString(const decNumber *, char[], Flag); 27350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decTrim(decNumber *, decContext *, Flag, Flag, Int *); 27450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decUnitAddSub(const Unit *, Int, const Unit *, Int, Int, 27550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *, Int); 27650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decUnitCompare(const Unit *, Int, const Unit *, Int, Int); 27750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 27850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if !DECSUBSET 27950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decFinish == decFinalize when no subset arithmetic needed */ 28050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define decFinish(a,b,c,d) decFinalize(a,b,c,d) 28150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#else 28250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decFinish(decNumber *, decContext *, Int *, uInt *); 28350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decRoundOperand(const decNumber *, decContext *, uInt *); 28450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 28550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 28650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Local macros */ 28750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* masked special-values bits */ 28850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define SPECIALARG (rhs->bits & DECSPECIAL) 28950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define SPECIALARGS ((lhs->bits | rhs->bits) & DECSPECIAL) 29050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 29150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* For use in ICU */ 29250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define malloc(a) uprv_malloc(a) 29350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define free(a) uprv_free(a) 29450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 29550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Diagnostic macros, etc. */ 29650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECALLOC 29750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Handle malloc/free accounting. If enabled, our accountable routines */ 29850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* are used; otherwise the code just goes straight to the system malloc */ 29950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and free routines. */ 30050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define malloc(a) decMalloc(a) 30150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define free(a) decFree(a) 30250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DECFENCE 0x5a /* corruption detector */ 30350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 'Our' malloc and free: */ 30450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void *decMalloc(size_t); 30550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decFree(void *); 30650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehouInt decAllocBytes=0; /* count of bytes allocated */ 30750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Note that DECALLOC code only checks for storage buffer overflow. */ 30850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* To check for memory leaks, the decAllocBytes variable must be */ 30950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* checked to be 0 at appropriate times (e.g., after the test */ 31050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* harness completes a set of tests). This checking may be unreliable */ 31150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if the testing is done in a multi-thread environment. */ 31250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 31350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 31450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECCHECK 31550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Optional checking routines. Enabling these means that decNumber */ 31650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and decContext operands to operator routines are checked for */ 31750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* correctness. This roughly doubles the execution time of the */ 31850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* fastest routines (and adds 600+ bytes), so should not normally be */ 31950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* used in 'production'. */ 32050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCheckInexact is used to check that inexact results have a full */ 32150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* complement of digits (where appropriate -- this is not the case */ 32250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* for Quantize, for example) */ 32350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DECUNRESU ((decNumber *)(void *)0xffffffff) 32450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DECUNUSED ((const decNumber *)(void *)0xffffffff) 32550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define DECUNCONT ((decContext *)(void *)(0xffffffff)) 32650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Flag decCheckOperands(decNumber *, const decNumber *, 32750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *, decContext *); 32850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Flag decCheckNumber(const decNumber *); 32950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decCheckInexact(const decNumber *, decContext *); 33050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 33150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 33250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECTRACE || DECCHECK 33350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Optional trace/debugging routines (may or may not be used) */ 33450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid decNumberShow(const decNumber *); /* displays the components of a number */ 33550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decDumpAr(char, const Unit *, Int); 33650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 33750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 33850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 33950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Conversions */ 34050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 34150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 34250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 34350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* from-int32 -- conversion from Int or uInt */ 34450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 34550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the decNumber to receive the integer */ 34650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* in or uin is the integer to be converted */ 34750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns dn */ 34850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 34950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No error is possible. */ 35050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 35150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberFromInt32(decNumber *dn, Int in) { 35250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt unsig; 35350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (in>=0) unsig=in; 35450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* negative (possibly BADINT) */ 35550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (in==BADINT) unsig=(uInt)1073741824*2; /* special case */ 35650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else unsig=-in; /* invert */ 35750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 35850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* in is now positive */ 35950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromUInt32(dn, unsig); 36050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (in<0) dn->bits=DECNEG; /* sign needed */ 36150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 36250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberFromInt32 */ 36350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 36450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberFromUInt32(decNumber *dn, uInt uin) { 36550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up; /* work pointer */ 36650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(dn); /* clean */ 36750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uin==0) return dn; /* [or decGetDigits bad call] */ 36850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=dn->lsu; uin>0; up++) { 36950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)(uin%(DECDPUNMAX+1)); 37050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uin=uin/(DECDPUNMAX+1); 37150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 37250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=decGetDigits(dn->lsu, up-dn->lsu); 37350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 37450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberFromUInt32 */ 37550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 37650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 37750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* to-int32 -- conversion to Int or uInt */ 37850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 37950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the decNumber to convert */ 38050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context for reporting errors */ 38150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns the converted decNumber, or 0 if Invalid is set */ 38250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 38350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Invalid is set if the decNumber does not have exponent==0 or if */ 38450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* it is a NaN, Infinite, or out-of-range. */ 38550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 38650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI Int U_EXPORT2 uprv_decNumberToInt32(const decNumber *dn, decContext *set) { 38750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 38850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0; 38950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 39050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 39150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* special or too many digits, or bad exponent */ 39250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0) ; /* bad */ 39350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* is a finite integer with 10 or fewer digits */ 39450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int d; /* work */ 39550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up; /* .. */ 39650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt hi=0, lo; /* .. */ 39750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=dn->lsu; /* -> lsu */ 39850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lo=*up; /* get 1 to 9 digits */ 39950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>1 /* split to higher */ 40050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho hi=lo/10; 40150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lo=lo%10; 40250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 40350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; 40450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* collect remaining Units, if any, into hi */ 40550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1]; 40650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now low has the lsd, hi the remainder */ 40750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (hi>214748364 || (hi==214748364 && lo>7)) { /* out of range? */ 40850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* most-negative is a reprieve */ 40950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECNEG && hi==214748364 && lo==8) return 0x80000000; 41050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* bad -- drop through */ 41150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 41250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* in-range always */ 41350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i=X10(hi)+lo; 41450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECNEG) return -i; 41550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return i; 41650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 41750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* integer */ 41850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */ 41950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; 42050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberToInt32 */ 42150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 42250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI uInt U_EXPORT2 uprv_decNumberToUInt32(const decNumber *dn, decContext *set) { 42350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 42450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0; 42550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 42650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* special or too many digits, or bad exponent, or negative (<0) */ 42750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0 42850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (dn->bits&DECNEG && !ISZERO(dn))); /* bad */ 42950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* is a finite integer with 10 or fewer digits */ 43050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int d; /* work */ 43150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up; /* .. */ 43250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt hi=0, lo; /* .. */ 43350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=dn->lsu; /* -> lsu */ 43450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lo=*up; /* get 1 to 9 digits */ 43550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>1 /* split to higher */ 43650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho hi=lo/10; 43750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lo=lo%10; 43850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 43950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; 44050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* collect remaining Units, if any, into hi */ 44150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1]; 44250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 44350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now low has the lsd, hi the remainder */ 44450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (hi>429496729 || (hi==429496729 && lo>5)) ; /* no reprieve possible */ 44550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else return X10(hi)+lo; 44650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* integer */ 44750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */ 44850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; 44950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberToUInt32 */ 45050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 45150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 45250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* to-scientific-string -- conversion to numeric string */ 45350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* to-engineering-string -- conversion to numeric string */ 45450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 45550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberToString(dn, string); */ 45650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberToEngString(dn, string); */ 45750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 45850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the decNumber to convert */ 45950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* string is the string where the result will be laid out */ 46050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 46150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* string must be at least dn->digits+14 characters long */ 46250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 46350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No error is possible, and no status can be set. */ 46450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 46550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI char * U_EXPORT2 uprv_decNumberToString(const decNumber *dn, char *string){ 46650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decToString(dn, string, 0); 46750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return string; 46850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* DecNumberToString */ 46950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 47050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI char * U_EXPORT2 uprv_decNumberToEngString(const decNumber *dn, char *string){ 47150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decToString(dn, string, 1); 47250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return string; 47350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* DecNumberToEngString */ 47450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 47550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 47650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* to-number -- conversion from numeric string */ 47750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 47850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberFromString -- convert string to decNumber */ 47950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn -- the number structure to fill */ 48050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* chars[] -- the string to convert ('\0' terminated) */ 48150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set -- the context used for processing any error, */ 48250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* determining the maximum precision available */ 48350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (set.digits), determining the maximum and minimum */ 48450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* exponent (set.emax and set.emin), determining if */ 48550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* extended values are allowed, and checking the */ 48650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rounding mode if overflow occurs or rounding is */ 48750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* needed. */ 48850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 48950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The length of the coefficient and the size of the exponent are */ 49050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* checked by this routine, so the correct error (Underflow or */ 49150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Overflow) can be reported or rounding applied, as necessary. */ 49250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 49350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If bad syntax is detected, the result will be a quiet NaN. */ 49450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 49550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberFromString(decNumber *dn, const char chars[], 49650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 49750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int exponent=0; /* working exponent [assume 0] */ 49850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte bits=0; /* working flags [assume +ve] */ 49950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *res; /* where result will be built */ 50050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit resbuff[SD2U(DECBUFFER+9)];/* local buffer in case need temporary */ 50150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [+9 allows for ln() constants] */ 50250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *allocres=NULL; /* -> allocated result, iff allocated */ 50350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int d=0; /* count of digits found in decimal part */ 50450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *dotchar=NULL; /* where dot was found */ 50550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *cfirst=chars; /* -> first character of decimal part */ 50650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *last=NULL; /* -> last digit of decimal part */ 50750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *c; /* work */ 50850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up; /* .. */ 50950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>1 51050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int cut, out; /* .. */ 51150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 51250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue; /* rounding residue */ 51350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* error code */ 51450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 51550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 51650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(DECUNRESU, DECUNUSED, DECUNUSED, set)) 51750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return uprv_decNumberZero(dn); 51850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 51950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 52050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* status & malloc protection */ 52150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (c=chars;; c++) { /* -> input character */ 52250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c>='0' && *c<='9') { /* test for Arabic digit */ 52350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho last=c; 52450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho d++; /* count of real digits */ 52550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; /* still in decimal part */ 52650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 52750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='.' && dotchar==NULL) { /* first '.' */ 52850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dotchar=c; /* record offset into decimal part */ 52950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (c==cfirst) cfirst++; /* first digit must follow */ 53050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue;} 53150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (c==chars) { /* first in string... */ 53250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='-') { /* valid - sign */ 53350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cfirst++; 53450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=DECNEG; 53550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue;} 53650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='+') { /* valid + sign */ 53750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cfirst++; 53850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue;} 53950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 54050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* *c is not a digit, or a valid +, -, or '.' */ 54150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 54250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* c */ 54350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 54450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (last==NULL) { /* no digits yet */ 54550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Conversion_syntax;/* assume the worst */ 54650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='\0') break; /* and no more to come... */ 54750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 54850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if subset then infinities and NaNs are not allowed */ 54950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) break; /* hopeless */ 55050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 55150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Infinities and NaNs are possible, here */ 55250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dotchar!=NULL) break; /* .. unless had a dot */ 55350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(dn); /* be optimistic */ 55450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decBiStr(c, "infinity", "INFINITY") 55550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || decBiStr(c, "inf", "INF")) { 55650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=bits | DECINF; 55750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=0; /* is OK */ 55850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* all done */ 55950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 56050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a NaN expected */ 56150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 2003.09.10 NaNs are now permitted to have a sign */ 56250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=bits | DECNAN; /* assume simple NaN */ 56350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='s' || *c=='S') { /* looks like an sNaN */ 56450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; 56550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=bits | DECSNAN; 56650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 56750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c!='n' && *c!='N') break; /* check caseless "NaN" */ 56850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; 56950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c!='a' && *c!='A') break; /* .. */ 57050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; 57150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c!='n' && *c!='N') break; /* .. */ 57250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; 57350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now either nothing, or nnnn payload, expected */ 57450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* -> start of integer and skip leading 0s [including plain 0] */ 57550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (cfirst=c; *cfirst=='0';) cfirst++; 57650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*cfirst=='\0') { /* "NaN" or "sNaN", maybe with all 0s */ 57750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=0; /* it's good */ 57850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* .. */ 57950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 58050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* something other than 0s; setup last and d as usual [no dots] */ 58150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (c=cfirst;; c++, d++) { 58250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<'0' || *c>'9') break; /* test for Arabic digit */ 58350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho last=c; 58450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 58550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c!='\0') break; /* not all digits */ 58650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (d>set->digits-1) { 58750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [NB: payload in a decNumber can be full length unless */ 58850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* clamped, in which case can only be digits-1] */ 58950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->clamp) break; 59050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (d>set->digits) break; 59150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* too many digits? */ 59250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* good; drop through to convert the integer to coefficient */ 59350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=0; /* syntax is OK */ 59450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=dn->bits; /* for copy-back */ 59550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* last==NULL */ 59650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 59750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (*c!='\0') { /* more to process... */ 59850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* had some digits; exponent is only valid sequence now */ 59950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag nege; /* 1=negative exponent */ 60050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *firstexp; /* -> first significant exponent digit */ 60150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Conversion_syntax;/* assume the worst */ 60250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c!='e' && *c!='E') break; 60350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Found 'e' or 'E' -- now process explicit exponent */ 60450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1998.07.11: sign no longer required */ 60550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho nege=0; 60650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; /* to (possible) sign */ 60750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='-') {nege=1; c++;} 60850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (*c=='+') c++; 60950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='\0') break; 61050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 61150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; *c=='0' && *(c+1)!='\0';) c++; /* strip insignificant zeros */ 61250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho firstexp=c; /* save exponent digit place */ 61350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; ;c++) { 61450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<'0' || *c>'9') break; /* not a digit */ 61550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent=X10(exponent)+(Int)*c-(Int)'0'; 61650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* c */ 61750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if not now on a '\0', *c must not be a digit */ 61850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c!='\0') break; 61950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 62050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (this next test must be after the syntax checks) */ 62150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if it was too long the exponent may have wrapped, so check */ 62250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* carefully and set it to a certain overflow if wrap possible */ 62350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (c>=firstexp+9+1) { 62450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (c>firstexp+9+1 || *firstexp>'1') exponent=DECNUMMAXE*2; 62550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [up to 1999999999 is OK, for example 1E-1000000998] */ 62650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 62750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (nege) exponent=-exponent; /* was negative */ 62850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=0; /* is OK */ 62950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* stuff after digits */ 63050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 63150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Here when whole string has been inspected; syntax is good */ 63250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* cfirst->first digit (never dot), last->last digit (ditto) */ 63350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 63450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* strip leading zeros/dot [leave final 0 if all 0's] */ 63550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*cfirst=='0') { /* [cfirst has stepped over .] */ 63650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (c=cfirst; c<last; c++, cfirst++) { 63750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='.') continue; /* ignore dots */ 63850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c!='0') break; /* non-zero found */ 63950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho d--; /* 0 stripped */ 64050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* c */ 64150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 64250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* make a rapid exit for easy zeros if !extended */ 64350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*cfirst=='0' && !set->extended) { 64450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(dn); /* clean result */ 64550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* [could be return] */ 64650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 64750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 64850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* at least one leading 0 */ 64950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 65050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Handle decimal point... */ 65150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dotchar!=NULL && dotchar<last) /* non-trailing '.' found? */ 65250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent-=(last-dotchar); /* adjust exponent */ 65350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [we can now ignore the .] */ 65450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 65550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* OK, the digits string is good. Assemble in the decNumber, or in */ 65650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a temporary units array if rounding is needed */ 65750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (d<=set->digits) res=dn->lsu; /* fits into supplied decNumber */ 65850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* rounding needed */ 65950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int needbytes=D2U(d)*sizeof(Unit);/* bytes needed */ 66050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res=resbuff; /* assume use local buffer */ 66150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>(Int)sizeof(resbuff)) { /* too big for local */ 66250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocres=(Unit *)malloc(needbytes); 66350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocres==NULL) {status|=DEC_Insufficient_storage; break;} 66450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res=allocres; 66550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 66650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 66750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* res now -> number lsu, buffer, or allocated storage for Unit array */ 66850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 66950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Place the coefficient into the selected Unit array */ 67050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [this is often 70% of the cost of this function when DECDPUN>1] */ 67150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>1 67250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho out=0; /* accumulator */ 67350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=res+D2U(d)-1; /* -> msu */ 67450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=d-(up-res)*DECDPUN; /* digits in top unit */ 67550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (c=cfirst;; c++) { /* along the digits */ 67650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='.') continue; /* ignore '.' [don't decrement cut] */ 67750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho out=X10(out)+(Int)*c-(Int)'0'; 67850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (c==last) break; /* done [never get to trailing '.'] */ 67950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut--; 68050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut>0) continue; /* more for this unit */ 68150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)out; /* write unit */ 68250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up--; /* prepare for unit below.. */ 68350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN; /* .. */ 68450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho out=0; /* .. */ 68550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* c */ 68650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)out; /* write lsu */ 68750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 68850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 68950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* DECDPUN==1 */ 69050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=res; /* -> lsu */ 69150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (c=last; c>=cfirst; c--) { /* over each character, from least */ 69250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='.') continue; /* ignore . [don't step up] */ 69350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)((Int)*c-(Int)'0'); 69450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; 69550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* c */ 69650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 69750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 69850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=bits; 69950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=exponent; 70050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=d; 70150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 70250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if not in number (too long) shorten into the number */ 70350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (d>set->digits) { 70450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; 70550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetCoeff(dn, set, res, d, &residue, &status); 70650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* always check for overflow or subnormal and round as needed */ 70750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinalize(dn, set, &residue, &status); 70850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 70950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* no rounding, but may still have overflow or subnormal */ 71050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [these tests are just for performance; finalize repeats them] */ 71150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((dn->exponent-1<set->emin-dn->digits) 71250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (dn->exponent-1>set->emax-set->digits)) { 71350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; 71450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinalize(dn, set, &residue, &status); 71550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 71650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 71750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decNumberShow(dn); */ 71850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* [for break] */ 71950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 72050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocres!=NULL) free(allocres); /* drop any storage used */ 72150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(dn, status, set); 72250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 72350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberFromString */ 72450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 72550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 72650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Operators */ 72750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 72850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 72950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 73050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberAbs -- absolute value operator */ 73150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 73250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = abs(A) */ 73350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 73450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 73550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 73650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 73750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 73850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* See also decNumberCopyAbs for a quiet bitwise version of this. */ 73950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 74050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 74150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This has the same effect as decNumberPlus unless A is negative, */ 74250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* in which case it has the same effect as decNumberMinus. */ 74350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 74450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberAbs(decNumber *res, const decNumber *rhs, 74550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 74650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dzero; /* for 0 */ 74750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 74850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 74950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 75050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 75150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 75250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 75350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dzero); /* set 0 */ 75450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dzero.exponent=rhs->exponent; /* [no coefficient expansion] */ 75550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, &dzero, rhs, set, (uByte)(rhs->bits & DECNEG), &status); 75650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 75750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 75850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 75950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 76050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 76150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberAbs */ 76250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 76350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 76450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberAdd -- add two Numbers */ 76550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 76650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A + B */ 76750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 76850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X+X) */ 76950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 77050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 77150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 77250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 77350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 77450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 77550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This just calls the routine shared with Subtract */ 77650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberAdd(decNumber *res, const decNumber *lhs, 77750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 77850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 77950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, lhs, rhs, set, 0, &status); 78050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 78150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 78250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 78350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 78450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 78550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberAdd */ 78650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 78750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 78850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberAnd -- AND two Numbers, digitwise */ 78950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 79050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A & B */ 79150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 79250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X&X) */ 79350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 79450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 79550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context (used for result length and error report) */ 79650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 79750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 79850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 79950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Logical function restrictions apply (see above); a NaN is */ 80050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 80150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 80250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberAnd(decNumber *res, const decNumber *lhs, 80350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 80450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *ua, *ub; /* -> operands */ 80550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *msua, *msub; /* -> operand msus */ 80650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *uc, *msuc; /* -> result and its msu */ 80750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int msudigs; /* digits in res msu */ 80850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 80950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 81050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 81150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 81250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs) 81350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { 81450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 81550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 81650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 81750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 81850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* operands are valid */ 81950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ua=lhs->lsu; /* bottom-up */ 82050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ub=rhs->lsu; /* .. */ 82150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uc=res->lsu; /* .. */ 82250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msua=ua+D2U(lhs->digits)-1; /* -> msu of lhs */ 82350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msub=ub+D2U(rhs->digits)-1; /* -> msu of rhs */ 82450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msuc=uc+D2U(set->digits)-1; /* -> msu of result */ 82550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */ 82650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */ 82750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit a, b; /* extract units */ 82850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ua>msua) a=0; 82950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else a=*ua; 83050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ub>msub) b=0; 83150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else b=*ub; 83250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uc=0; /* can now write back */ 83350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a|b) { /* maybe 1 bits to examine */ 83450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i, j; 83550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uc=0; /* can now write back */ 83650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This loop could be unrolled and/or use BIN2BCD tables */ 83750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i=0; i<DECDPUN; i++) { 83850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a&b&1) *uc=*uc+(Unit)powers[i]; /* effect AND */ 83950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho j=a%10; 84050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=a/10; 84150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho j|=b%10; 84250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=b/10; 84350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (j>1) { 84450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 84550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 84650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 84750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uc==msuc && i==msudigs-1) break; /* just did final digit */ 84850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each digit */ 84950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* both OK */ 85050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each unit */ 85150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [here uc-1 is the msu of the result] */ 85250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(res->lsu, uc-res->lsu); 85350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=0; /* integer */ 85450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=0; /* sign=0 */ 85550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; /* [no status to set] */ 85650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberAnd */ 85750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 85850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 85950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCompare -- compare two Numbers */ 86050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 86150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B */ 86250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 86350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 86450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 86550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 86650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 86750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 86850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for one digit (or NaN). */ 86950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 87050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCompare(decNumber *res, const decNumber *lhs, 87150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 87250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 87350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPARE, &status); 87450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 87550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 87650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCompare */ 87750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 87850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 87950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCompareSignal -- compare, signalling on all NaNs */ 88050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 88150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B */ 88250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 88350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 88450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 88550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 88650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 88750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 88850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for one digit (or NaN). */ 88950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 89050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCompareSignal(decNumber *res, const decNumber *lhs, 89150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 89250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 89350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPSIG, &status); 89450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 89550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 89650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCompareSignal */ 89750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 89850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 89950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCompareTotal -- compare two Numbers, using total ordering */ 90050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 90150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B, under total ordering */ 90250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 90350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 90450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 90550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 90650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 90750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 90850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for one digit; the result will always be one of */ 90950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -1, 0, or 1. */ 91050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 91150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCompareTotal(decNumber *res, const decNumber *lhs, 91250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 91350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 91450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status); 91550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 91650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 91750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCompareTotal */ 91850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 91950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 92050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCompareTotalMag -- compare, total ordering of magnitudes */ 92150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 92250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = |A| ? |B|, under total ordering */ 92350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 92450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 92550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 92650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 92750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 92850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 92950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for one digit; the result will always be one of */ 93050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -1, 0, or 1. */ 93150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 93250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCompareTotalMag(decNumber *res, const decNumber *lhs, 93350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 93450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 93550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt needbytes; /* for space calculations */ 93650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufa[D2N(DECBUFFER+1)];/* +1 in case DECBUFFER=0 */ 93750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ 93850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufb[D2N(DECBUFFER+1)]; 93950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufb=NULL; /* -> allocated bufb, iff allocated */ 94050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *a, *b; /* temporary pointers */ 94150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 94250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 94350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 94450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 94550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 94650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 94750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if either is negative, take a copy and absolute */ 94850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(lhs)) { /* lhs<0 */ 94950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=bufa; 95050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(lhs->digits)-1)*sizeof(Unit); 95150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufa)) { /* need malloc space */ 95250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufa=(decNumber *)malloc(needbytes); 95350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa==NULL) { /* hopeless -- abandon */ 95450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 95550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 95650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=allocbufa; /* use the allocated space */ 95750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 95850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(a, lhs); /* copy content */ 95950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->bits&=~DECNEG; /* .. and clear the sign */ 96050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=a; /* use copy from here on */ 96150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 96250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) { /* rhs<0 */ 96350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=bufb; 96450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit); 96550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufb)) { /* need malloc space */ 96650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufb=(decNumber *)malloc(needbytes); 96750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufb==NULL) { /* hopeless -- abandon */ 96850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 96950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 97050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=allocbufb; /* use the allocated space */ 97150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 97250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(b, rhs); /* copy content */ 97350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b->bits&=~DECNEG; /* .. and clear the sign */ 97450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=b; /* use copy from here on */ 97550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 97650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status); 97750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 97850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 97950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */ 98050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufb!=NULL) free(allocbufb); /* .. */ 98150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 98250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 98350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCompareTotalMag */ 98450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 98550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 98650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberDivide -- divide one number by another */ 98750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 98850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A / B */ 98950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 99050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X/X) */ 99150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 99250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 99350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 99450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 99550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 99650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 99750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberDivide(decNumber *res, const decNumber *lhs, 99850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 99950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 100050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(res, lhs, rhs, set, DIVIDE, &status); 100150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 100250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 100350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 100450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 100550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 100650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberDivide */ 100750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 100850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 100950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberDivideInteger -- divide and return integer quotient */ 101050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 101150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A # B, where # is the integer divide operator */ 101250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 101350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X#X) */ 101450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 101550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 101650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 101750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 101850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 101950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 102050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberDivideInteger(decNumber *res, const decNumber *lhs, 102150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 102250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 102350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(res, lhs, rhs, set, DIVIDEINT, &status); 102450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 102550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 102650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberDivideInteger */ 102750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 102850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 102950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberExp -- exponentiation */ 103050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 103150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = exp(A) */ 103250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 103350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 103450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 103550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context; note that rounding mode has no effect */ 103650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 103750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 103850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 103950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Mathematical function restrictions apply (see above); a NaN is */ 104050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 104150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 104250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Finite results will always be full precision and Inexact, except */ 104350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* when A is a zero or -Infinity (giving 1 or 0 respectively). */ 104450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 104550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */ 104650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* almost always be correctly rounded, but may be up to 1 ulp in */ 104750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* error in rare cases. */ 104850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 104950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This is a wrapper for decExpOp which can handle the slightly wider */ 105050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (double) range needed by Ln (which has to be able to calculate */ 105150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* exp(-a) where a can be the tiniest number (Ntiny). */ 105250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 105350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberExp(decNumber *res, const decNumber *rhs, 105450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 105550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 105650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 105750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */ 105850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 105950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 106050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 106150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 106250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 106350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 106450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Check restrictions; these restrictions ensure that if h=8 (see */ 106550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decExpOp) then the result will either overflow or underflow to 0. */ 106650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Other math functions restrict the input range, too, for inverses. */ 106750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If not violated then carry out the operation. */ 106850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */ 106950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 107050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 107150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operand and set lostDigits status, as needed */ 107250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>set->digits) { 107350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, &status); 107450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 107550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 107650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 107750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 107850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 107950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decExpOp(res, rhs, set, &status); 108050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 108150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 108250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 108350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs !=NULL) free(allocrhs); /* drop any storage used */ 108450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 108550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* apply significant status */ 108650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 108750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 108850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 108950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 109050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 109150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberExp */ 109250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 109350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 109450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberFMA -- fused multiply add */ 109550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 109650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes D = (A * B) + C with only one rounding */ 109750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 109850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is D, the result. D may be A or B or C (e.g., X=FMA(X,X,X)) */ 109950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 110050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 110150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* fhs is C [far hand side] */ 110250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 110350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 110450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Mathematical function restrictions apply (see above); a NaN is */ 110550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 110650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 110750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 110850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 110950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberFMA(decNumber *res, const decNumber *lhs, 111050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, const decNumber *fhs, 111150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 111250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 111350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext dcmul; /* context for the multiplication */ 111450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt needbytes; /* for space calculations */ 111550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufa[D2N(DECBUFFER*2+1)]; 111650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ 111750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *acc; /* accumulator pointer */ 111850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dzero; /* work */ 111950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 112050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 112150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 112250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, fhs, DECUNUSED, set)) return res; 112350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 112450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 112550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 112650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 112750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { /* [undefined if subset] */ 112850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 112950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 113050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 113150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Check math restrictions [these ensure no overflow or underflow] */ 113250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((!decNumberIsSpecial(lhs) && decCheckMath(lhs, set, &status)) 113350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (!decNumberIsSpecial(rhs) && decCheckMath(rhs, set, &status)) 113450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (!decNumberIsSpecial(fhs) && decCheckMath(fhs, set, &status))) break; 113550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set up context for multiply */ 113650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dcmul=*set; 113750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dcmul.digits=lhs->digits+rhs->digits; /* just enough */ 113850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [The above may be an over-estimate for subset arithmetic, but that's OK] */ 113950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dcmul.emax=DEC_MAX_EMAX; /* effectively unbounded .. */ 114050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dcmul.emin=DEC_MIN_EMIN; /* [thanks to Math restrictions] */ 114150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set up decNumber space to receive the result of the multiply */ 114250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=bufa; /* may fit */ 114350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(dcmul.digits)-1)*sizeof(Unit); 114450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufa)) { /* need malloc space */ 114550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufa=(decNumber *)malloc(needbytes); 114650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa==NULL) { /* hopeless -- abandon */ 114750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 114850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 114950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=allocbufa; /* use the allocated space */ 115050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 115150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* multiply with extended range and necessary precision */ 115250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /*printf("emin=%ld\n", dcmul.emin); */ 115350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(acc, lhs, rhs, &dcmul, &status); 115450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Only Invalid operation (from sNaN or Inf * 0) is possible in */ 115550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* status; if either is seen than ignore fhs (in case it is */ 115650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* another sNaN) and set acc to NaN unless we had an sNaN */ 115750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [decMultiplyOp leaves that to caller] */ 115850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Note sNaN has to go through addOp to shorten payload if */ 115950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* necessary */ 116050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((status&DEC_Invalid_operation)!=0) { 116150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(status&DEC_sNaN)) { /* but be true invalid */ 116250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* acc not yet set */ 116350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=DECNAN; 116450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 116550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 116650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dzero); /* make 0 (any non-NaN would do) */ 116750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fhs=&dzero; /* use that */ 116850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 116950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 117050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* multiply was OK */ 117150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) printf("Status=%08lx after FMA multiply\n", (LI)status); 117250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 117350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 117450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* add the third operand and result -> res, and all is done */ 117550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, acc, fhs, set, 0, &status); 117650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 117750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 117850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */ 117950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 118050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 118150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 118250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 118350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 118450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberFMA */ 118550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 118650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 118750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberInvert -- invert a Number, digitwise */ 118850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 118950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = ~A */ 119050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 119150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A (e.g., X=~X) */ 119250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 119350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context (used for result length and error report) */ 119450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 119550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 119650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 119750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Logical function restrictions apply (see above); a NaN is */ 119850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 119950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 120050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberInvert(decNumber *res, const decNumber *rhs, 120150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 120250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *ua, *msua; /* -> operand and its msu */ 120350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *uc, *msuc; /* -> result and its msu */ 120450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int msudigs; /* digits in res msu */ 120550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 120650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 120750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 120850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 120950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { 121050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 121150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 121250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 121350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* operand is valid */ 121450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ua=rhs->lsu; /* bottom-up */ 121550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uc=res->lsu; /* .. */ 121650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msua=ua+D2U(rhs->digits)-1; /* -> msu of rhs */ 121750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msuc=uc+D2U(set->digits)-1; /* -> msu of result */ 121850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */ 121950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; uc<=msuc; ua++, uc++) { /* Unit loop */ 122050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit a; /* extract unit */ 122150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i, j; /* work */ 122250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ua>msua) a=0; 122350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else a=*ua; 122450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uc=0; /* can now write back */ 122550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* always need to examine all bits in rhs */ 122650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This loop could be unrolled and/or use BIN2BCD tables */ 122750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i=0; i<DECDPUN; i++) { 122850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((~a)&1) *uc=*uc+(Unit)powers[i]; /* effect INVERT */ 122950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho j=a%10; 123050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=a/10; 123150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (j>1) { 123250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 123350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 123450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 123550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uc==msuc && i==msudigs-1) break; /* just did final digit */ 123650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each digit */ 123750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each unit */ 123850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [here uc-1 is the msu of the result] */ 123950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(res->lsu, uc-res->lsu); 124050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=0; /* integer */ 124150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=0; /* sign=0 */ 124250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; /* [no status to set] */ 124350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberInvert */ 124450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 124550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 124650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberLn -- natural logarithm */ 124750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 124850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = ln(A) */ 124950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 125050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 125150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 125250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context; note that rounding mode has no effect */ 125350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 125450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 125550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 125650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Notable cases: */ 125750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A<0 -> Invalid */ 125850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=0 -> -Infinity (Exact) */ 125950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=+Infinity -> +Infinity (Exact) */ 126050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=1 exactly -> 0 (Exact) */ 126150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 126250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Mathematical function restrictions apply (see above); a NaN is */ 126350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 126450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 126550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */ 126650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* almost always be correctly rounded, but may be up to 1 ulp in */ 126750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* error in rare cases. */ 126850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 126950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This is a wrapper for decLnOp which can handle the slightly wider */ 127050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (+11) range needed by Ln, Log10, etc. (which may have to be able */ 127150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* to calculate at p+e+2). */ 127250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 127350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberLn(decNumber *res, const decNumber *rhs, 127450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 127550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 127650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 127750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */ 127850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 127950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 128050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 128150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 128250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 128350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 128450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Check restrictions; this is a math function; if not violated */ 128550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* then carry out the operation. */ 128650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */ 128750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 128850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 128950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operand and set lostDigits status, as needed */ 129050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>set->digits) { 129150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, &status); 129250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 129350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 129450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 129550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* special check in subset for rhs=0 */ 129650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) { /* +/- zeros -> error */ 129750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 129850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 129950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* extended=0 */ 130050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 130150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decLnOp(res, rhs, set, &status); 130250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 130350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 130450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 130550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs !=NULL) free(allocrhs); /* drop any storage used */ 130650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 130750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* apply significant status */ 130850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 130950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 131050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 131150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 131250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 131350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberLn */ 131450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 131550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 131650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberLogB - get adjusted exponent, by 754 rules */ 131750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 131850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = adjustedexponent(A) */ 131950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 132050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 132150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 132250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context, used only for digits and status */ 132350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 132450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for 10 digits (A might have 10**9 digits and */ 132550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* an exponent of +999999999, or one digit and an exponent of */ 132650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -1999999999). */ 132750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 132850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This returns the adjusted exponent of A after (in theory) padding */ 132950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* with zeros on the right to set->digits digits while keeping the */ 133050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* same value. The exponent is not limited by emin/emax. */ 133150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 133250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Notable cases: */ 133350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A<0 -> Use |A| */ 133450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=0 -> -Infinity (Division by zero) */ 133550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=Infinite -> +Infinity (Exact) */ 133650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=1 exactly -> 0 (Exact) */ 133750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* NaNs are propagated as usual */ 133850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 133950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberLogB(decNumber *res, const decNumber *rhs, 134050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 134150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 134250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 134350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 134450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 134550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 134650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 134750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* NaNs as usual; Infinities return +Infinity; 0->oops */ 134850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(rhs)) decNaNs(res, rhs, NULL, set, &status); 134950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsInfinite(rhs)) uprv_decNumberCopyAbs(res, rhs); 135050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsZero(rhs)) { 135150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* prepare for Infinity */ 135250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=DECNEG|DECINF; /* -Infinity */ 135350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Division_by_zero; /* as per 754 */ 135450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 135550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* finite non-zero */ 135650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ae=rhs->exponent+rhs->digits-1; /* adjusted exponent */ 135750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromInt32(res, ae); /* lay it out */ 135850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 135950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 136050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 136150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 136250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberLogB */ 136350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 136450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 136550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberLog10 -- logarithm in base 10 */ 136650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 136750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = log10(A) */ 136850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 136950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 137050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 137150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context; note that rounding mode has no effect */ 137250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 137350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 137450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 137550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Notable cases: */ 137650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A<0 -> Invalid */ 137750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=0 -> -Infinity (Exact) */ 137850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=+Infinity -> +Infinity (Exact) */ 137950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=10**n (if n is an integer) -> n (Exact) */ 138050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 138150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Mathematical function restrictions apply (see above); a NaN is */ 138250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 138350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 138450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */ 138550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* almost always be correctly rounded, but may be up to 1 ulp in */ 138650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* error in rare cases. */ 138750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 138850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This calculates ln(A)/ln(10) using appropriate precision. For */ 138950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ln(A) this is the max(p, rhs->digits + t) + 3, where p is the */ 139050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* requested digits and t is the number of digits in the exponent */ 139150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (maximum 6). For ln(10) it is p + 3; this is often handled by the */ 139250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* fastpath in decLnOp. The final division is done to the requested */ 139350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* precision. */ 139450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 139502c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) 139602c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic push 139702c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic ignored "-Warray-bounds" 139802c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#endif 139950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberLog10(decNumber *res, const decNumber *rhs, 140050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 140150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0, ignore=0; /* status accumulators */ 140250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt needbytes; /* for space calculations */ 140350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int p; /* working precision */ 140450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int t; /* digits in exponent of A */ 140550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 140650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffers for a and b working decimals */ 140750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (adjustment calculator, same size) */ 140850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufa[D2N(DECBUFFER+2)]; 140950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ 141050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *a=bufa; /* temporary a */ 141150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufb[D2N(DECBUFFER+2)]; 141250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufb=NULL; /* -> allocated bufb, iff allocated */ 141350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *b=bufb; /* temporary b */ 141450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufw[D2N(10)]; /* working 2-10 digit number */ 141550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *w=bufw; /* .. */ 141650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 141750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */ 141850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 141950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 142050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext aset; /* working context */ 142150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 142250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 142350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 142450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 142550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 142650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Check restrictions; this is a math function; if not violated */ 142750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* then carry out the operation. */ 142850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!decCheckMath(rhs, set, &status)) do { /* protect malloc */ 142950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 143050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 143150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operand and set lostDigits status, as needed */ 143250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>set->digits) { 143350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, &status); 143450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 143550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 143650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 143750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* special check in subset for rhs=0 */ 143850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) { /* +/- zeros -> error */ 143950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 144050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 144150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* extended=0 */ 144250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 144350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 144450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */ 144550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 144650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle exact powers of 10; only check if +ve finite */ 144750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(rhs->bits&(DECNEG|DECSPECIAL)) && !ISZERO(rhs)) { 144850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* (no residue) */ 144950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt copystat=0; /* clean status */ 145050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 145150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* round to a single digit... */ 145250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=1; 145350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(w, rhs, &aset, &residue, ©stat); /* copy & shorten */ 145450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if exact and the digit is 1, rhs is a power of 10 */ 145550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(copystat&DEC_Inexact) && w->lsu[0]==1) { 145650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the exponent, conveniently, is the power of 10; making */ 145750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this the result needs a little care as it might not fit, */ 145850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* so first convert it into the working number, and then move */ 145950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* to res */ 146050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromInt32(w, w->exponent); 146150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; 146250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, w, set, &residue, &status); /* copy & round */ 146350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, &status); /* cleanup/set flags */ 146450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 146550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* not a power of 10 */ 146650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* not a candidate for exact */ 146750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 146850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* simplify the information-content calculation to use 'total */ 146950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* number of digits in a, including exponent' as compared to the */ 147050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* requested digits, as increasing this will only rarely cost an */ 147150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* iteration in ln(a) anyway */ 147250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t=6; /* it can never be >6 */ 147350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 147450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* allocate space when needed... */ 147550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p=(rhs->digits+t>set->digits?rhs->digits+t:set->digits)+3; 147650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit); 147750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufa)) { /* need malloc space */ 147850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufa=(decNumber *)malloc(needbytes); 147950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa==NULL) { /* hopeless -- abandon */ 148050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 148150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 148250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=allocbufa; /* use the allocated space */ 148350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 148450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=p; /* as calculated */ 148550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emax=DEC_MAX_MATH; /* usual bounds */ 148650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emin=-DEC_MAX_MATH; /* .. */ 148750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.clamp=0; /* and no concrete format */ 148850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decLnOp(a, rhs, &aset, &status); /* a=ln(rhs) */ 148950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 149050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* skip the division if the result so far is infinite, NaN, or */ 149150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* zero, or there was an error; note NaN from sNaN needs copy */ 149250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status&DEC_NaNs && !(status&DEC_sNaN)) break; 149350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a->bits&DECSPECIAL || ISZERO(a)) { 149450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, a); /* [will fit] */ 149550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 149650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 149750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* for ln(10) an extra 3 digits of precision are needed */ 149850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p=set->digits+3; 149950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit); 150050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufb)) { /* need malloc space */ 150150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufb=(decNumber *)malloc(needbytes); 150250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufb==NULL) { /* hopeless -- abandon */ 150350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 150450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 150550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=allocbufb; /* use the allocated space */ 150650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 150750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(w); /* set up 10... */ 150850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==1 150950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho w->lsu[1]=1; w->lsu[0]=0; /* .. */ 151050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 151150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho w->lsu[0]=10; /* .. */ 151250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 151350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho w->digits=2; /* .. */ 151450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 151550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=p; 151650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decLnOp(b, w, &aset, &ignore); /* b=ln(10) */ 151750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 151850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=set->digits; /* for final divide */ 151950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(res, a, b, &aset, DIVIDE, &status); /* into result */ 152050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* [for break] */ 152150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 152250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */ 152350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufb!=NULL) free(allocbufb); /* .. */ 152450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 152550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs !=NULL) free(allocrhs); /* .. */ 152650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 152750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* apply significant status */ 152850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 152950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 153050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 153150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 153250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 153350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberLog10 */ 153402c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) 153502c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic pop 153602c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#endif 153750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 153850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 153950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberMax -- compare two Numbers and return the maximum */ 154050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 154150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B, returning the maximum by 754 rules */ 154250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 154350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 154450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 154550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 154650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 154750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 154850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 154950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 155050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberMax(decNumber *res, const decNumber *lhs, 155150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 155250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 155350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPMAX, &status); 155450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 155550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 155650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 155750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 155850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 155950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberMax */ 156050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 156150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 156250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberMaxMag -- compare and return the maximum by magnitude */ 156350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 156450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B, returning the maximum by 754 rules */ 156550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 156650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 156750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 156850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 156950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 157050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 157150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 157250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 157350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberMaxMag(decNumber *res, const decNumber *lhs, 157450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 157550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 157650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPMAXMAG, &status); 157750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 157850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 157950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 158050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 158150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 158250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberMaxMag */ 158350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 158450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 158550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberMin -- compare two Numbers and return the minimum */ 158650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 158750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B, returning the minimum by 754 rules */ 158850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 158950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 159050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 159150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 159250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 159350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 159450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 159550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 159650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberMin(decNumber *res, const decNumber *lhs, 159750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 159850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 159950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPMIN, &status); 160050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 160150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 160250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 160350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 160450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 160550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberMin */ 160650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 160750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 160850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberMinMag -- compare and return the minimum by magnitude */ 160950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 161050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B, returning the minimum by 754 rules */ 161150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 161250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 161350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 161450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 161550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 161650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 161750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 161850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 161950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberMinMag(decNumber *res, const decNumber *lhs, 162050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 162150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 162250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(res, lhs, rhs, set, COMPMINMAG, &status); 162350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 162450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 162550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 162650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 162750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 162850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberMinMag */ 162950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 163050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 163150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberMinus -- prefix minus operator */ 163250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 163350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = 0 - A */ 163450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 163550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 163650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 163750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 163850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 163950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* See also decNumberCopyNegate for a quiet bitwise version of this. */ 164050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 164150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 164250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Simply use AddOp for the subtract, which will do the necessary. */ 164350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 164450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberMinus(decNumber *res, const decNumber *rhs, 164550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 164650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dzero; 164750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 164850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 164950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 165050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 165150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 165250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 165350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dzero); /* make 0 */ 165450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dzero.exponent=rhs->exponent; /* [no coefficient expansion] */ 165550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, &dzero, rhs, set, DECNEG, &status); 165650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 165750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 165850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 165950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 166050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 166150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberMinus */ 166250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 166350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 166450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberNextMinus -- next towards -Infinity */ 166550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 166650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A - infinitesimal, rounded towards -Infinity */ 166750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 166850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 166950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 167050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 167150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 167250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This is a generalization of 754 NextDown. */ 167350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 167450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberNextMinus(decNumber *res, const decNumber *rhs, 167550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 167650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dtiny; /* constant */ 167750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset=*set; /* work */ 167850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 167950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 168050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 168150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 168250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 168350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* +Infinity is the special case */ 168450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((rhs->bits&(DECINF|DECNEG))==DECINF) { 168550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetMaxValue(res, set); /* is +ve */ 168650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* there is no status to set */ 168750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 168850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 168950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dtiny); /* start with 0 */ 169050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dtiny.lsu[0]=1; /* make number that is .. */ 169150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dtiny.exponent=DEC_MIN_EMIN-1; /* .. smaller than tiniest */ 169250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.round=DEC_ROUND_FLOOR; 169350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, rhs, &dtiny, &workset, DECNEG, &status); 169450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status&=DEC_Invalid_operation|DEC_sNaN; /* only sNaN Invalid please */ 169550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 169650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 169750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberNextMinus */ 169850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 169950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 170050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberNextPlus -- next towards +Infinity */ 170150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 170250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A + infinitesimal, rounded towards +Infinity */ 170350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 170450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 170550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 170650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 170750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 170850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This is a generalization of 754 NextUp. */ 170950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 171050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberNextPlus(decNumber *res, const decNumber *rhs, 171150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 171250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dtiny; /* constant */ 171350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset=*set; /* work */ 171450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 171550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 171650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 171750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 171850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 171950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* -Infinity is the special case */ 172050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((rhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) { 172150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetMaxValue(res, set); 172250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=DECNEG; /* negative */ 172350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* there is no status to set */ 172450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 172550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 172650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dtiny); /* start with 0 */ 172750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dtiny.lsu[0]=1; /* make number that is .. */ 172850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dtiny.exponent=DEC_MIN_EMIN-1; /* .. smaller than tiniest */ 172950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.round=DEC_ROUND_CEILING; 173050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, rhs, &dtiny, &workset, 0, &status); 173150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status&=DEC_Invalid_operation|DEC_sNaN; /* only sNaN Invalid please */ 173250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 173350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 173450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberNextPlus */ 173550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 173650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 173750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberNextToward -- next towards rhs */ 173850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 173950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A +/- infinitesimal, rounded towards */ 174050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* +/-Infinity in the direction of B, as per 754-1985 nextafter */ 174150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* modified during revision but dropped from 754-2008. */ 174250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 174350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A or B. */ 174450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 174550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 174650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 174750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 174850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This is a generalization of 754-1985 NextAfter. */ 174950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 175050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberNextToward(decNumber *res, const decNumber *lhs, 175150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 175250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dtiny; /* constant */ 175350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset=*set; /* work */ 175450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int result; /* .. */ 175550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 175650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 175750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 175850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 175950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 176050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { 176150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, &status); 176250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 176350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* Is numeric, so no chance of sNaN Invalid, etc. */ 176450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=decCompare(lhs, rhs, 0); /* sign matters */ 176550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result==BADINT) status|=DEC_Insufficient_storage; /* rare */ 176650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* valid compare */ 176750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result==0) uprv_decNumberCopySign(res, lhs, rhs); /* easy */ 176850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* differ: need NextPlus or NextMinus */ 176950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte sub; /* add or subtract */ 177050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result<0) { /* lhs<rhs, do nextplus */ 177150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* -Infinity is the special case */ 177250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((lhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) { 177350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetMaxValue(res, set); 177450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=DECNEG; /* negative */ 177550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; /* there is no status to set */ 177650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 177750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.round=DEC_ROUND_CEILING; 177850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho sub=0; /* add, please */ 177950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* plus */ 178050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* lhs>rhs, do nextminus */ 178150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* +Infinity is the special case */ 178250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((lhs->bits&(DECINF|DECNEG))==DECINF) { 178350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetMaxValue(res, set); 178450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; /* there is no status to set */ 178550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 178650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.round=DEC_ROUND_FLOOR; 178750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho sub=DECNEG; /* subtract, please */ 178850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* minus */ 178950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dtiny); /* start with 0 */ 179050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dtiny.lsu[0]=1; /* make number that is .. */ 179150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dtiny.exponent=DEC_MIN_EMIN-1; /* .. smaller than tiniest */ 179250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, lhs, &dtiny, &workset, sub, &status); /* + or - */ 179350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* turn off exceptions if the result is a normal number */ 179450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (including Nmin), otherwise let all status through */ 179550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_decNumberIsNormal(res, set)) status=0; 179650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* unequal */ 179750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* compare OK */ 179850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* numeric */ 179950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 180050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 180150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberNextToward */ 180250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 180350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 180450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberOr -- OR two Numbers, digitwise */ 180550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 180650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A | B */ 180750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 180850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X|X) */ 180950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 181050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 181150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context (used for result length and error report) */ 181250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 181350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 181450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 181550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Logical function restrictions apply (see above); a NaN is */ 181650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 181750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 181850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberOr(decNumber *res, const decNumber *lhs, 181950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 182050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *ua, *ub; /* -> operands */ 182150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *msua, *msub; /* -> operand msus */ 182250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *uc, *msuc; /* -> result and its msu */ 182350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int msudigs; /* digits in res msu */ 182450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 182550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 182650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 182750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 182850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs) 182950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { 183050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 183150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 183250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 183350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* operands are valid */ 183450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ua=lhs->lsu; /* bottom-up */ 183550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ub=rhs->lsu; /* .. */ 183650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uc=res->lsu; /* .. */ 183750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msua=ua+D2U(lhs->digits)-1; /* -> msu of lhs */ 183850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msub=ub+D2U(rhs->digits)-1; /* -> msu of rhs */ 183950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msuc=uc+D2U(set->digits)-1; /* -> msu of result */ 184050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */ 184150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */ 184250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit a, b; /* extract units */ 184350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ua>msua) a=0; 184450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else a=*ua; 184550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ub>msub) b=0; 184650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else b=*ub; 184750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uc=0; /* can now write back */ 184850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a|b) { /* maybe 1 bits to examine */ 184950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i, j; 185050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This loop could be unrolled and/or use BIN2BCD tables */ 185150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i=0; i<DECDPUN; i++) { 185250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((a|b)&1) *uc=*uc+(Unit)powers[i]; /* effect OR */ 185350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho j=a%10; 185450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=a/10; 185550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho j|=b%10; 185650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=b/10; 185750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (j>1) { 185850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 185950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 186050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 186150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uc==msuc && i==msudigs-1) break; /* just did final digit */ 186250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each digit */ 186350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* non-zero */ 186450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each unit */ 186550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [here uc-1 is the msu of the result] */ 186650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(res->lsu, uc-res->lsu); 186750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=0; /* integer */ 186850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=0; /* sign=0 */ 186950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; /* [no status to set] */ 187050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberOr */ 187150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 187250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 187350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberPlus -- prefix plus operator */ 187450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 187550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = 0 + A */ 187650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 187750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 187850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 187950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 188050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 188150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* See also decNumberCopy for a quiet bitwise version of this. */ 188250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 188350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 188450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This simply uses AddOp; Add will take fast path after preparing A. */ 188550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Performance is a concern here, as this routine is often used to */ 188650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* check operands and apply rounding and overflow/underflow testing. */ 188750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 188850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberPlus(decNumber *res, const decNumber *rhs, 188950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 189050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dzero; 189150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 189250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 189350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 189450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 189550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 189650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dzero); /* make 0 */ 189750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dzero.exponent=rhs->exponent; /* [no coefficient expansion] */ 189850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, &dzero, rhs, set, 0, &status); 189950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 190050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 190150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 190250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 190350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 190450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberPlus */ 190550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 190650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 190750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberMultiply -- multiply two Numbers */ 190850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 190950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A x B */ 191050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 191150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X+X) */ 191250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 191350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 191450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 191550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 191650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 191750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 191850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberMultiply(decNumber *res, const decNumber *lhs, 191950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 192050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 192150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(res, lhs, rhs, set, &status); 192250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 192350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 192450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 192550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 192650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 192750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberMultiply */ 192850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 192950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 193050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberPower -- raise a number to a power */ 193150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 193250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ** B */ 193350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 193450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X**X) */ 193550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 193650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 193750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 193850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 193950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 194050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 194150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Mathematical function restrictions apply (see above); a NaN is */ 194250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 194350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 194450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* However, if 1999999997<=B<=999999999 and B is an integer then the */ 194550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* restrictions on A and the context are relaxed to the usual bounds, */ 194650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* for compatibility with the earlier (integer power only) version */ 194750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of this function. */ 194850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 194950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* When B is an integer, the result may be exact, even if rounded. */ 195050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 195150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The final result is rounded according to the context; it will */ 195250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* almost always be correctly rounded, but may be up to 1 ulp in */ 195350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* error in rare cases. */ 195450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 195550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberPower(decNumber *res, const decNumber *lhs, 195650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 195750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 195850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */ 195950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* .., rhs */ 196050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 196150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocdac=NULL; /* -> allocated acc buffer, iff used */ 196250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocinv=NULL; /* -> allocated 1/x buffer, iff used */ 196350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int reqdigits=set->digits; /* requested DIGITS */ 196450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int n; /* rhs in binary */ 196550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag rhsint=0; /* 1 if rhs is an integer */ 196650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag useint=0; /* 1 if can use integer calculation */ 196750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag isoddint=0; /* 1 if rhs is an integer and odd */ 196850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i; /* work */ 196950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 197050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int dropped; /* .. */ 197150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 197250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt needbytes; /* buffer size needed */ 197350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag seenbit; /* seen a bit while powering */ 197450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* rounding residue */ 197550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulators */ 197650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte bits=0; /* result sign if errors */ 197750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext aset; /* working context */ 197850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dnOne; /* work value 1... */ 197950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* local accumulator buffer [a decNumber, with digits+elength+1 digits] */ 198050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dacbuff[D2N(DECBUFFER+9)]; 198150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *dac=dacbuff; /* -> result accumulator */ 198250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* same again for possible 1/lhs calculation */ 198350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber invbuff[D2N(DECBUFFER+9)]; 198450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 198550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 198650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 198750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 198850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 198950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 199050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 199150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { /* reduce operands and set status, as needed */ 199250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>reqdigits) { 199350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloclhs=decRoundOperand(lhs, set, &status); 199450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs==NULL) break; 199550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=alloclhs; 199650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 199750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>reqdigits) { 199850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, &status); 199950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 200050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 200150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 200250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 200350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 200450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 200550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 200650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle NaNs and rhs Infinity (lhs infinity is harder) */ 200750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS) { 200850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { /* NaNs */ 200950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, &status); 201050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 201150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs)) { /* rhs Infinity */ 201250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag rhsneg=rhs->bits&DECNEG; /* save rhs sign */ 201350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(lhs) /* lhs<0 */ 201450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && !decNumberIsZero(lhs)) /* .. */ 201550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 201650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* lhs >=0 */ 201750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dnOne); /* set up 1 */ 201850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dnOne.lsu[0]=1; 201950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCompare(dac, lhs, &dnOne, set); /* lhs ? 1 */ 202050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* prepare for 0/1/Infinity */ 202150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dac)) { /* lhs<1 */ 202250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhsneg) res->bits|=DECINF; /* +Infinity [else is +0] */ 202350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 202450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (dac->lsu[0]==0) { /* lhs=1 */ 202550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1**Infinity is inexact, so return fully-padded 1.0000 */ 202650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift=set->digits-1; 202750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=1; /* was 0, make int 1 */ 202850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, 1, shift); 202950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=-shift; /* make 1.0000... */ 203050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Inexact|DEC_Rounded; /* deemed inexact */ 203150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 203250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* lhs>1 */ 203350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!rhsneg) res->bits|=DECINF; /* +Infinity [else is +0] */ 203450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 203550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* lhs>=0 */ 203650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 203750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [lhs infinity drops through] */ 203850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* specials */ 203950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 204050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Original rhs may be an integer that fits and is in range */ 204150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho n=decGetInt(rhs); 204250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n!=BADINT) { /* it is an integer */ 204350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhsint=1; /* record the fact for 1**n */ 204450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho isoddint=(Flag)n&1; /* [works even if big] */ 204550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n!=BIGEVEN && n!=BIGODD) /* can use integer path? */ 204650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho useint=1; /* looks good */ 204750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 204850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 204950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(lhs) /* -x .. */ 205050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && isoddint) bits=DECNEG; /* .. to an odd power */ 205150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 205250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle LHS infinity */ 205350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(lhs)) { /* [NaNs already handled] */ 205450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte rbits=rhs->bits; /* save */ 205550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* prepare */ 205650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n==0) *res->lsu=1; /* [-]Inf**0 => 1 */ 205750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 205850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* -Inf**nonint -> error */ 205950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!rhsint && decNumberIsNegative(lhs)) { 206050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; /* -Inf**nonint is error */ 206150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 206250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(rbits & DECNEG)) bits|=DECINF; /* was not a **-n */ 206350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [otherwise will be 0 or -0] */ 206450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; 206550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 206650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 206750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 206850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* similarly handle LHS zero */ 206950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(lhs)) { 207050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n==0) { /* 0**0 => Error */ 207150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 207250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { /* [unless subset] */ 207350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 207450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=1; /* return 1 */ 207550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 207650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 207750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 207850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 207950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* 0**x */ 208050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte rbits=rhs->bits; /* save */ 208150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rbits & DECNEG) { /* was a 0**(-n) */ 208250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 208350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { /* [bad if subset] */ 208450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 208550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 208650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 208750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits|=DECINF; 208850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 208950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* prepare */ 209050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [otherwise will be 0 or -0] */ 209150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; 209250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 209350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 209450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 209550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here both lhs and rhs are finite; rhs==0 is handled in the */ 209650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* integer path. Next handle the non-integer cases */ 209750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!useint) { /* non-integral rhs */ 209850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* any -ve lhs is bad, as is either operand or context out of */ 209950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* bounds */ 210050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(lhs)) { 210150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 210250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 210350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckMath(lhs, set, &status) 210450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || decCheckMath(rhs, set, &status)) break; /* variable status */ 210550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 210650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */ 210750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emax=DEC_MAX_MATH; /* usual bounds */ 210850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emin=-DEC_MAX_MATH; /* .. */ 210950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.clamp=0; /* and no concrete format */ 211050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 211150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the result using exp(ln(lhs)*rhs), which can */ 211250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* all be done into the accumulator, dac. The precision needed */ 211350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is enough to contain the full information in the lhs (which */ 211450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is the total digits, including exponent), or the requested */ 211550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* precision, if larger, + 4; 6 is used for the exponent */ 211650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* maximum length, and this is also used when it is shorter */ 211750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* than the requested digits as it greatly reduces the >0.5 ulp */ 211850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* cases at little cost (because Ln doubles digits each */ 211950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* iteration so a few extra digits rarely causes an extra */ 212050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* iteration) */ 212150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=MAXI(lhs->digits, set->digits)+6+4; 212250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* non-integer rhs */ 212350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 212450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* rhs is in-range integer */ 212550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n==0) { /* x**0 = 1 */ 212650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (0**0 was handled above) */ 212750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* result=1 */ 212850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=1; /* .. */ 212950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 213050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rhs is a non-zero integer */ 213150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n<0) n=-n; /* use abs(n) */ 213250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 213350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset=*set; /* clone the context */ 213450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.round=DEC_ROUND_HALF_EVEN; /* internally use balanced */ 213550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the working DIGITS */ 213650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=reqdigits+(rhs->digits+rhs->exponent)+2; 213750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 213850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) aset.digits--; /* use classic precision */ 213950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 214050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it's an error if this is more than can be handled */ 214150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (aset.digits>DECNUMMAXP) {status|=DEC_Invalid_operation; break;} 214250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* integer path */ 214350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 214450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* aset.digits is the count of digits for the accumulator needed */ 214550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if accumulator is too long for local storage, then allocate */ 214650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(aset.digits)-1)*sizeof(Unit); 214750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [needbytes also used below if 1/lhs needed] */ 214850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(dacbuff)) { 214950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocdac=(decNumber *)malloc(needbytes); 215050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocdac==NULL) { /* hopeless -- abandon */ 215150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 215250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 215350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dac=allocdac; /* use the allocated space */ 215450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 215550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here, aset is set up and accumulator is ready for use */ 215650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 215750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!useint) { /* non-integral rhs */ 215850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* x ** y; special-case x=1 here as it will otherwise always */ 215950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce to integer 1; decLnOp has a fastpath which detects */ 216050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the case of x=1 */ 216150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decLnOp(dac, lhs, &aset, &status); /* dac=ln(lhs) */ 216250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [no error possible, as lhs 0 already handled] */ 216350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(dac)) { /* x==1, 1.0, etc. */ 216450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* need to return fully-padded 1.0000 etc., but rhsint->1 */ 216550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *dac->lsu=1; /* was 0, make int 1 */ 216650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!rhsint) { /* add padding */ 216750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift=set->digits-1; 216850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dac->digits=decShiftToMost(dac->lsu, 1, shift); 216950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dac->exponent=-shift; /* make 1.0000... */ 217050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Inexact|DEC_Rounded; /* deemed inexact */ 217150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 217250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 217350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 217450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(dac, dac, rhs, &aset, &status); /* dac=dac*rhs */ 217550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decExpOp(dac, dac, &aset, &status); /* dac=exp(dac) */ 217650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 217750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* and drop through for final rounding */ 217850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* non-integer rhs */ 217950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 218050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* carry on with integer */ 218150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(dac); /* acc=1 */ 218250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *dac->lsu=1; /* .. */ 218350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 218450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if a negative power the constant 1 is needed, and if not subset */ 218550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* invert the lhs now rather than inverting the result later */ 218650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) { /* was a **-n [hence digits>0] */ 218750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *inv=invbuff; /* asssume use fixed buffer */ 218850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(&dnOne, dac); /* dnOne=1; [needed now or later] */ 218950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 219050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->extended) { /* need to calculate 1/lhs */ 219150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 219250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* divide lhs into 1, putting result in dac [dac=1/dac] */ 219350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(dac, &dnOne, lhs, &aset, DIVIDE, &status); 219450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now locate or allocate space for the inverted lhs */ 219550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(invbuff)) { 219650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocinv=(decNumber *)malloc(needbytes); 219750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocinv==NULL) { /* hopeless -- abandon */ 219850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 219950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 220050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho inv=allocinv; /* use the allocated space */ 220150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 220250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [inv now points to big-enough buffer or allocated storage] */ 220350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(inv, dac); /* copy the 1/lhs */ 220450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(dac, &dnOne); /* restore acc=1 */ 220550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=inv; /* .. and go forward with new lhs */ 220650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 220750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 220850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 220950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 221050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 221150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Raise-to-the-power loop... */ 221250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho seenbit=0; /* set once a 1-bit is encountered */ 221350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i=1;;i++){ /* for each bit [top bit ignored] */ 221450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* abandon if had overflow or terminal underflow */ 221550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */ 221650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status&DEC_Overflow || ISZERO(dac)) break; 221750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 221850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [the following two lines revealed an optimizer bug in a C++ */ 221950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* compiler, with symptom: 5**3 -> 25, when n=n+n was used] */ 222050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho n=n<<1; /* move next bit to testable position */ 222150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n<0) { /* top bit is set */ 222250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho seenbit=1; /* OK, significant bit seen */ 222350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(dac, dac, lhs, &aset, &status); /* dac=dac*x */ 222450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 222550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (i==31) break; /* that was the last bit */ 222650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!seenbit) continue; /* no need to square 1 */ 222750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(dac, dac, dac, &aset, &status); /* dac=dac*dac [square] */ 222850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /*i*/ /* 32 bits */ 222950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 223050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* complete internal overflow or underflow processing */ 223150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status & (DEC_Overflow|DEC_Underflow)) { 223250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 223350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If subset, and power was negative, reverse the kind of -erflow */ 223450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [1/x not yet done] */ 223550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended && decNumberIsNegative(rhs)) { 223650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status & DEC_Overflow) 223750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status^=DEC_Overflow | DEC_Underflow | DEC_Subnormal; 223850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* trickier -- Underflow may or may not be set */ 223950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status&=~(DEC_Underflow | DEC_Subnormal); /* [one or both] */ 224050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Overflow; 224150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 224250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 224350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 224450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dac->bits=(dac->bits & ~DECNEG) | bits; /* force correct sign */ 224550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* round subnormals [to set.digits rather than aset.digits] */ 224650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* or set overflow result similarly as required */ 224750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinalize(dac, set, &residue, &status); 224850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, dac); /* copy to result (is now OK length) */ 224950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 225050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 225150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 225250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 225350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended && /* subset math */ 225450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumberIsNegative(rhs)) { /* was a **-n [hence digits>0] */ 225550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* so divide result into 1 [dac=1/dac] */ 225650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(dac, &dnOne, dac, &aset, DIVIDE, &status); 225750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 225850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 225950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* rhs integer path */ 226050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 226150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce result to the requested length and copy to result */ 226250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, dac, set, &residue, &status); 226350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, &status); /* final cleanup */ 226450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 226550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) decTrim(res, set, 0, 1, &dropped); /* trailing zeros */ 226650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 226750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 226850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 226950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocdac!=NULL) free(allocdac); /* drop any storage used */ 227050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocinv!=NULL) free(allocinv); /* .. */ 227150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 227250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs!=NULL) free(alloclhs); /* .. */ 227350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs!=NULL) free(allocrhs); /* .. */ 227450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 227550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 227650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 227750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 227850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 227950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 228050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberPower */ 228150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 228250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 228350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberQuantize -- force exponent to requested value */ 228450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 228550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = op(A, B), where op adjusts the coefficient */ 228650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of C (by rounding or shifting) such that the exponent (-scale) */ 228750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of C has exponent of B. The numerical value of C will equal A, */ 228850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* except for the effects of any rounding that occurred. */ 228950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 229050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A or B */ 229150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A, the number to adjust */ 229250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B, the number with exponent to match */ 229350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 229450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 229550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 229650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 229750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Unless there is an error or the result is infinite, the exponent */ 229850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* after the operation is guaranteed to be equal to that of B. */ 229950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 230050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberQuantize(decNumber *res, const decNumber *lhs, 230150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 230250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 230350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decQuantizeOp(res, lhs, rhs, set, 1, &status); 230450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 230550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 230650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberQuantize */ 230750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 230850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 230950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberReduce -- remove trailing zeros */ 231050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 231150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = 0 + A, and normalizes the result */ 231250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 231350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 231450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 231550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 231650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 231750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 231850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 231950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Previously known as Normalize */ 232050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberNormalize(decNumber *res, const decNumber *rhs, 232150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 232250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return uprv_decNumberReduce(res, rhs, set); 232350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberNormalize */ 232450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 232550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberReduce(decNumber *res, const decNumber *rhs, 232650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 232750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 232850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */ 232950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 233050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* as usual */ 233150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* as usual */ 233250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int dropped; /* work */ 233350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 233450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 233550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 233650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 233750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 233850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 233950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 234050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 234150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operand and set lostDigits status, as needed */ 234250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>set->digits) { 234350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, &status); 234450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 234550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 234650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 234750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 234850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 234950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 235050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 235150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Infinities copy through; NaNs need usual treatment */ 235250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(rhs)) { 235350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, rhs, NULL, set, &status); 235450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 235550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 235650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 235750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce result to the requested length and copy to result */ 235850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, rhs, set, &residue, &status); /* copy & round */ 235950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, &status); /* cleanup/set flags */ 236050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decTrim(res, set, 1, 0, &dropped); /* normalize in place */ 236150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [may clamp] */ 236250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 236350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 236450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 236550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs !=NULL) free(allocrhs); /* .. */ 236650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 236750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set);/* then report status */ 236850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 236950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberReduce */ 237050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 237150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 237250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberRescale -- force exponent to requested value */ 237350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 237450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = op(A, B), where op adjusts the coefficient */ 237550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of C (by rounding or shifting) such that the exponent (-scale) */ 237650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of C has the value B. The numerical value of C will equal A, */ 237750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* except for the effects of any rounding that occurred. */ 237850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 237950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A or B */ 238050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A, the number to adjust */ 238150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B, the requested exponent */ 238250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 238350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 238450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 238550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 238650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Unless there is an error or the result is infinite, the exponent */ 238750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* after the operation is guaranteed to be equal to B. */ 238850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 238950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberRescale(decNumber *res, const decNumber *lhs, 239050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 239150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 239250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decQuantizeOp(res, lhs, rhs, set, 0, &status); 239350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 239450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 239550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberRescale */ 239650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 239750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 239850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberRemainder -- divide and return remainder */ 239950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 240050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A % B */ 240150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 240250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X%X) */ 240350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 240450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 240550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 240650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 240750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 240850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 240950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberRemainder(decNumber *res, const decNumber *lhs, 241050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 241150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 241250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(res, lhs, rhs, set, REMAINDER, &status); 241350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 241450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 241550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 241650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 241750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 241850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberRemainder */ 241950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 242050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 242150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberRemainderNear -- divide and return remainder from nearest */ 242250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 242350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A % B, where % is the IEEE remainder operator */ 242450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 242550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X%X) */ 242650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 242750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 242850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 242950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 243050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 243150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 243250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberRemainderNear(decNumber *res, const decNumber *lhs, 243350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 243450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 243550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(res, lhs, rhs, set, REMNEAR, &status); 243650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 243750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 243850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 243950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 244050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 244150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberRemainderNear */ 244250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 244350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 244450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberRotate -- rotate the coefficient of a Number left/right */ 244550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 244650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A rot B (in base ten and rotating set->digits */ 244750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* digits). */ 244850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 244950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=XrotX) */ 245050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 245150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B, the number of digits to rotate (-ve to right) */ 245250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 245350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 245450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The digits of the coefficient of A are rotated to the left (if B */ 245550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* is positive) or to the right (if B is negative) without adjusting */ 245650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the exponent or the sign of A. If lhs->digits is less than */ 245750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set->digits the coefficient is padded with zeros on the left */ 245850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* before the rotate. Any leading zeros in the result are removed */ 245950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* as usual. */ 246050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 246150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* B must be an integer (q=0) and in the range -set->digits through */ 246250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* +set->digits. */ 246350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 246450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* NaNs are propagated as usual. Infinities are unaffected (but */ 246550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* B must be valid). No status is set unless B is invalid or an */ 246650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* operand is an sNaN. */ 246750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 246850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberRotate(decNumber *res, const decNumber *lhs, 246950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 247050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 247150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int rotate; /* rhs as an Int */ 247250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 247350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 247450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 247550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 247650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 247750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* NaNs propagate as normal */ 247850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) 247950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, &status); 248050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rhs must be an integer */ 248150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsInfinite(rhs) || rhs->exponent!=0) 248250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Invalid_operation; 248350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* both numeric, rhs is an integer */ 248450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rotate=decGetInt(rhs); /* [cannot fail] */ 248550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rotate==BADINT /* something bad .. */ 248650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || rotate==BIGODD || rotate==BIGEVEN /* .. very big .. */ 248750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || abs(rotate)>set->digits) /* .. or out of range */ 248850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Invalid_operation; 248950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* rhs is OK */ 249050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); 249150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* convert -ve rotate to equivalent positive rotation */ 249250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rotate<0) rotate=set->digits+rotate; 249350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rotate!=0 && rotate!=set->digits /* zero or full rotation */ 249450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && !decNumberIsInfinite(res)) { /* lhs was infinite */ 249550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* left-rotate to do; 0 < rotate < set->digits */ 249650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt units, shift; /* work */ 249750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt msudigits; /* digits in result msu */ 249850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *msu=res->lsu+D2U(res->digits)-1; /* current msu */ 249950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *msumax=res->lsu+D2U(set->digits)-1; /* rotation msu */ 250050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (msu++; msu<=msumax; msu++) *msu=0; /* ensure high units=0 */ 250150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=set->digits; /* now full-length */ 250250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msudigits=MSUDIGITS(res->digits); /* actual digits in msu */ 250350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 250450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rotation here is done in-place, in three steps */ 250550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1. shift all to least up to one unit to unit-align final */ 250650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lsd [any digits shifted out are rotated to the left, */ 250750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* abutted to the original msd (which may require split)] */ 250850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 250950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [if there are no whole units left to rotate, the */ 251050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rotation is now complete] */ 251150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 251250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 2. shift to least, from below the split point only, so that */ 251350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the final msd is in the right place in its Unit [any */ 251450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* digits shifted out will fit exactly in the current msu, */ 251550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* left aligned, no split required] */ 251650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 251750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 3. rotate all the units by reversing left part, right */ 251850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* part, and then whole */ 251950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 252050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* example: rotate right 8 digits (2 units + 2), DECDPUN=3. */ 252150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 252250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* start: 00a bcd efg hij klm npq */ 252350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 252450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1a 000 0ab cde fgh|ijk lmn [pq saved] */ 252550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1b 00p qab cde fgh|ijk lmn */ 252650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 252750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 2a 00p qab cde fgh|00i jkl [mn saved] */ 252850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 2b mnp qab cde fgh|00i jkl */ 252950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* */ 253050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 3a fgh cde qab mnp|00i jkl */ 253150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 3b fgh cde qab mnp|jkl 00i */ 253250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 3c 00i jkl mnp qab cde fgh */ 253350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 253450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Step 1: amount to shift is the partial right-rotate count */ 253550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rotate=set->digits-rotate; /* make it right-rotate */ 253650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho units=rotate/DECDPUN; /* whole units to rotate */ 253750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho shift=rotate%DECDPUN; /* left-over digits count */ 253850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift>0) { /* not an exact number of units */ 253950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt save=res->lsu[0]%powers[shift]; /* save low digit(s) */ 254050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decShiftToLeast(res->lsu, D2U(res->digits), shift); 254150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift>msudigits) { /* msumax-1 needs >0 digits */ 254250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt rem=save%powers[shift-msudigits];/* split save */ 254350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *msumax=(Unit)(save/powers[shift-msudigits]); /* and insert */ 254450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *(msumax-1)=*(msumax-1) 254550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho +(Unit)(rem*powers[DECDPUN-(shift-msudigits)]); /* .. */ 254650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 254750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* all fits in msumax */ 254850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *msumax=*msumax+(Unit)(save*powers[msudigits-shift]); /* [maybe *1] */ 254950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 255050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* digits shift needed */ 255150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 255250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If whole units to rotate... */ 255350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (units>0) { /* some to do */ 255450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Step 2: the units to touch are the whole ones in rotate, */ 255550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if any, and the shift is DECDPUN-msudigits (which may be */ 255650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 0, again) */ 255750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho shift=DECDPUN-msudigits; 255850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift>0) { /* not an exact number of units */ 255950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt save=res->lsu[0]%powers[shift]; /* save low digit(s) */ 256050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decShiftToLeast(res->lsu, units, shift); 256150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *msumax=*msumax+(Unit)(save*powers[msudigits]); 256250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* partial shift needed */ 256350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 256450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Step 3: rotate the units array using triple reverse */ 256550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (reversing is easy and fast) */ 256650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decReverse(res->lsu+units, msumax); /* left part */ 256750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decReverse(res->lsu, res->lsu+units-1); /* right part */ 256850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decReverse(res->lsu, msumax); /* whole */ 256950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* whole units to rotate */ 257050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the rotation may have left an undetermined number of zeros */ 257150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* on the left, so true length needs to be calculated */ 257250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(res->lsu, msumax-res->lsu+1); 257350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* rotate needed */ 257450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* rhs OK */ 257550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* numerics */ 257650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 257750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 257850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberRotate */ 257950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 258050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 258150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberSameQuantum -- test for equal exponents */ 258250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 258350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is the result number, which will contain either 0 or 1 */ 258450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is a number to test */ 258550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is the second (usually a pattern) */ 258650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 258750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No errors are possible and no context is needed. */ 258850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 258950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberSameQuantum(decNumber *res, const decNumber *lhs, 259050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs) { 259150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit ret=0; /* return value */ 259250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 259350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 259450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, DECUNCONT)) return res; 259550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 259650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 259750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS) { 259850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(lhs) && decNumberIsNaN(rhs)) ret=1; 259950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsInfinite(lhs) && decNumberIsInfinite(rhs)) ret=1; 260050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [anything else with a special gives 0] */ 260150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 260250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (lhs->exponent==rhs->exponent) ret=1; 260350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 260450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* OK to overwrite an operand now */ 260550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=ret; 260650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 260750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberSameQuantum */ 260850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 260950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 261050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberScaleB -- multiply by a power of 10 */ 261150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 261250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A x 10**B where B is an integer (q=0) with */ 261350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* maximum magnitude 2*(emax+digits) */ 261450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 261550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A or B */ 261650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A, the number to adjust */ 261750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B, the requested power of ten to use */ 261850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 261950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 262050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 262150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 262250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The result may underflow or overflow. */ 262350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 262450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberScaleB(decNumber *res, const decNumber *lhs, 262550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 262650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int reqexp; /* requested exponent change [B] */ 262750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 262850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue; /* work */ 262950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 263050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 263150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 263250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 263350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 263450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Handle special values except lhs infinite */ 263550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) 263650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, &status); 263750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rhs must be an integer */ 263850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsInfinite(rhs) || rhs->exponent!=0) 263950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Invalid_operation; 264050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 264150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lhs is a number; rhs is a finite with q==0 */ 264250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho reqexp=decGetInt(rhs); /* [cannot fail] */ 264350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (reqexp==BADINT /* something bad .. */ 264450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || reqexp==BIGODD || reqexp==BIGEVEN /* .. very big .. */ 264550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || abs(reqexp)>(2*(set->digits+set->emax))) /* .. or out of range */ 264650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Invalid_operation; 264750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* rhs is OK */ 264850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); /* all done if infinite lhs */ 264950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!decNumberIsInfinite(res)) { /* prepare to scale */ 265050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent+=reqexp; /* adjust the exponent */ 265150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; 265250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinalize(res, set, &residue, &status); /* .. and check */ 265350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* finite LHS */ 265450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* rhs OK */ 265550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* rhs finite */ 265650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 265750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 265850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberScaleB */ 265950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 266050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 266150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberShift -- shift the coefficient of a Number left or right */ 266250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 266350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A << B or C = A >> -B (in base ten). */ 266450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 266550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X<<X) */ 266650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 266750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B, the number of digits to shift (-ve to right) */ 266850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 266950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 267050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The digits of the coefficient of A are shifted to the left (if B */ 267150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* is positive) or to the right (if B is negative) without adjusting */ 267250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the exponent or the sign of A. */ 267350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 267450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* B must be an integer (q=0) and in the range -set->digits through */ 267550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* +set->digits. */ 267650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 267750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* NaNs are propagated as usual. Infinities are unaffected (but */ 267850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* B must be valid). No status is set unless B is invalid or an */ 267950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* operand is an sNaN. */ 268050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 268150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberShift(decNumber *res, const decNumber *lhs, 268250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 268350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 268450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift; /* rhs as an Int */ 268550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 268650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 268750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 268850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 268950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 269050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* NaNs propagate as normal */ 269150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) 269250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, &status); 269350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rhs must be an integer */ 269450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsInfinite(rhs) || rhs->exponent!=0) 269550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Invalid_operation; 269650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* both numeric, rhs is an integer */ 269750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho shift=decGetInt(rhs); /* [cannot fail] */ 269850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift==BADINT /* something bad .. */ 269950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || shift==BIGODD || shift==BIGEVEN /* .. very big .. */ 270050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || abs(shift)>set->digits) /* .. or out of range */ 270150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=DEC_Invalid_operation; 270250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* rhs is OK */ 270350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); 270450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift!=0 && !decNumberIsInfinite(res)) { /* something to do */ 270550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift>0) { /* to left */ 270650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift==set->digits) { /* removing all */ 270750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=0; /* so place 0 */ 270850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=1; /* .. */ 270950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 271050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* */ 271150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* first remove leading digits if necessary */ 271250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits+shift>set->digits) { 271350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDecap(res, res->digits+shift-set->digits); 271450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* that updated res->digits; may have gone to 1 (for a */ 271550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* single digit or for zero */ 271650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 271750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits>1 || *res->lsu) /* if non-zero.. */ 271850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, res->digits, shift); 271950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* partial left */ 272050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* left */ 272150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* to right */ 272250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (-shift>=res->digits) { /* discarding all */ 272350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=0; /* so place 0 */ 272450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=1; /* .. */ 272550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 272650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 272750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decShiftToLeast(res->lsu, D2U(res->digits), -shift); 272850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits-=(-shift); 272950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 273050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* to right */ 273150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* non-0 non-Inf shift */ 273250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* rhs OK */ 273350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* numerics */ 273450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 273550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 273650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberShift */ 273750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 273850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 273950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberSquareRoot -- square root operator */ 274050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 274150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = squareroot(A) */ 274250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 274350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 274450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 274550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context; note that rounding mode has no effect */ 274650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 274750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 274850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 274950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This uses the following varying-precision algorithm in: */ 275050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 275150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Properly Rounded Variable Precision Square Root, T. E. Hull and */ 275250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A. Abrham, ACM Transactions on Mathematical Software, Vol 11 #3, */ 275350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* pp229-237, ACM, September 1985. */ 275450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 275550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The square-root is calculated using Newton's method, after which */ 275650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* a check is made to ensure the result is correctly rounded. */ 275750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 275850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % [Reformatted original Numerical Turing source code follows.] */ 275950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* function sqrt(x : real) : real */ 276050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % sqrt(x) returns the properly rounded approximation to the square */ 276150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % root of x, in the precision of the calling environment, or it */ 276250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % fails if x < 0. */ 276350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % t e hull and a abrham, august, 1984 */ 276450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if x <= 0 then */ 276550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if x < 0 then */ 276650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* assert false */ 276750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* else */ 276850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* result 0 */ 276950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end if */ 277050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end if */ 277150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* var f := setexp(x, 0) % fraction part of x [0.1 <= x < 1] */ 277250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* var e := getexp(x) % exponent part of x */ 277350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* var approx : real */ 277450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if e mod 2 = 0 then */ 277550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* approx := .259 + .819 * f % approx to root of f */ 277650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* else */ 277750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* f := f/l0 % adjustments */ 277850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* e := e + 1 % for odd */ 277950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* approx := .0819 + 2.59 * f % exponent */ 278050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end if */ 278150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 278250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* var p:= 3 */ 278350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* const maxp := currentprecision + 2 */ 278450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* loop */ 278550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* p := min(2*p - 2, maxp) % p = 4,6,10, . . . , maxp */ 278650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* precision p */ 278750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* approx := .5 * (approx + f/approx) */ 278850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* exit when p = maxp */ 278950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end loop */ 279050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 279150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % approx is now within 1 ulp of the properly rounded square root */ 279250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % of f; to ensure proper rounding, compare squares of (approx - */ 279350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* % l/2 ulp) and (approx + l/2 ulp) with f. */ 279450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* p := currentprecision */ 279550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* begin */ 279650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* precision p + 2 */ 279750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* const approxsubhalf := approx - setexp(.5, -p) */ 279850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if mulru(approxsubhalf, approxsubhalf) > f then */ 279950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* approx := approx - setexp(.l, -p + 1) */ 280050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* else */ 280150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* const approxaddhalf := approx + setexp(.5, -p) */ 280250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if mulrd(approxaddhalf, approxaddhalf) < f then */ 280350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* approx := approx + setexp(.l, -p + 1) */ 280450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end if */ 280550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end if */ 280650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end */ 280750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* result setexp(approx, e div 2) % fix exponent */ 280850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end sqrt */ 280950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 281002c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) 281102c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic push 281202c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic ignored "-Warray-bounds" 281302c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#endif 281450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberSquareRoot(decNumber *res, const decNumber *rhs, 281550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 281650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset, approxset; /* work contexts */ 281750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dzero; /* used for constant zero */ 281850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxp; /* largest working precision */ 281950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int workp; /* working precision */ 282050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* rounding residue */ 282150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0, ignore=0; /* status accumulators */ 282250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt rstatus; /* .. */ 282350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int exp; /* working exponent */ 282450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ideal; /* ideal (preferred) exponent */ 282550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int needbytes; /* work */ 282650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int dropped; /* .. */ 282750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 282850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 282950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */ 283050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 283150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffer for f [needs +1 in case DECBUFFER 0] */ 283250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber buff[D2N(DECBUFFER+1)]; 283350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffer for a [needs +2 to match likely maxp] */ 283450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufa[D2N(DECBUFFER+2)]; 283550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffer for temporary, b [must be same size as a] */ 283650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufb[D2N(DECBUFFER+2)]; 283750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbuff=NULL; /* -> allocated buff, iff allocated */ 283850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ 283950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufb=NULL; /* -> allocated bufb, iff allocated */ 284050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *f=buff; /* reduced fraction */ 284150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *a=bufa; /* approximation to result */ 284250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *b=bufb; /* intermediate result */ 284350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffer for temporary variable, up to 3 digits */ 284450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber buft[D2N(3)]; 284550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *t=buft; /* up-to-3-digit constant or work */ 284650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 284750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 284850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 284950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 285050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 285150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 285250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 285350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 285450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operand and set lostDigits status, as needed */ 285550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>set->digits) { 285650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, &status); 285750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 285850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [Note: 'f' allocation below could reuse this buffer if */ 285950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* used, but as this is rare they are kept separate for clarity.] */ 286050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 286150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 286250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 286350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 286450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 286550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 286650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle infinities and NaNs */ 286750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARG) { 286850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs)) { /* an infinity */ 286950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) status|=DEC_Invalid_operation; 287050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else uprv_decNumberCopy(res, rhs); /* +Infinity */ 287150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 287250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else decNaNs(res, rhs, NULL, set, &status); /* a NaN */ 287350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 287450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 287550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 287650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the ideal (preferred) exponent [floor(exp/2)] */ 287750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [It would be nicer to write: ideal=rhs->exponent>>1, but this */ 287850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* generates a compiler warning. Generated code is the same.] */ 287950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ideal=(rhs->exponent&~1)/2; /* target */ 288050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 288150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle zeros */ 288250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) { 288350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, rhs); /* could be 0 or -0 */ 288450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=ideal; /* use the ideal [safe] */ 288550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* use decFinish to clamp any out-of-range exponent, etc. */ 288650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, &status); 288750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 288850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 288950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 289050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* any other -x is an oops */ 289150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) { 289250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Invalid_operation; 289350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 289450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 289550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 289650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* space is needed for three working variables */ 289750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* f -- the same precision as the RHS, reduced to 0.01->0.99... */ 289850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a -- Hull's approximation -- precision, when assigned, is */ 289950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* currentprecision+1 or the input argument precision, */ 290050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* whichever is larger (+2 for use as temporary) */ 290150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* b -- intermediate temporary result (same size as a) */ 290250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if any is too long for local storage, then allocate */ 290350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workp=MAXI(set->digits+1, rhs->digits); /* actual rounding precision */ 290450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workp=MAXI(workp, 7); /* at least 7 for low cases */ 290550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxp=workp+2; /* largest working precision */ 290650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 290750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit); 290850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>(Int)sizeof(buff)) { 290950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbuff=(decNumber *)malloc(needbytes); 291050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbuff==NULL) { /* hopeless -- abandon */ 291150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 291250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 291350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho f=allocbuff; /* use the allocated space */ 291450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 291550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a and b both need to be able to hold a maxp-length number */ 291650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(maxp)-1)*sizeof(Unit); 291750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>(Int)sizeof(bufa)) { /* [same applies to b] */ 291850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufa=(decNumber *)malloc(needbytes); 291950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufb=(decNumber *)malloc(needbytes); 292050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa==NULL || allocbufb==NULL) { /* hopeless */ 292150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Insufficient_storage; 292250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 292350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=allocbufa; /* use the allocated spaces */ 292450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=allocbufb; /* .. */ 292550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 292650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 292750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* copy rhs -> f, save exponent, and reduce so 0.1 <= f < 1 */ 292850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(f, rhs); 292950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exp=f->exponent+f->digits; /* adjusted to Hull rules */ 293050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho f->exponent=-(f->digits); /* to range */ 293150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 293250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set up working context */ 293350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&workset, DEC_INIT_DECIMAL64); 293450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.emax=DEC_MAX_EMAX; 293550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.emin=DEC_MIN_EMIN; 293650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 293750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [Until further notice, no error is possible and status bits */ 293850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (Rounded, etc.) should be ignored, not accumulated.] */ 293950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 294050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Calculate initial approximation, and allow for odd exponent */ 294150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.digits=workp; /* p for initial calculation */ 294250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->bits=0; t->digits=3; 294350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->bits=0; a->digits=3; 294450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((exp & 1)==0) { /* even exponent */ 294550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Set t=0.259, a=0.819 */ 294650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->exponent=-3; 294750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->exponent=-3; 294850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>=3 294950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=259; 295050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->lsu[0]=819; 295150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==2 295250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=59; t->lsu[1]=2; 295350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->lsu[0]=19; a->lsu[1]=8; 295450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 295550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=9; t->lsu[1]=5; t->lsu[2]=2; 295650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->lsu[0]=9; a->lsu[1]=1; a->lsu[2]=8; 295750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 295850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 295950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* odd exponent */ 296050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Set t=0.0819, a=2.59 */ 296150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho f->exponent--; /* f=f/10 */ 296250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exp++; /* e=e+1 */ 296350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->exponent=-4; 296450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->exponent=-2; 296550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>=3 296650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=819; 296750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->lsu[0]=259; 296850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==2 296950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=19; t->lsu[1]=8; 297050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->lsu[0]=59; a->lsu[1]=2; 297150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 297250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=9; t->lsu[1]=1; t->lsu[2]=8; 297350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->lsu[0]=9; a->lsu[1]=5; a->lsu[2]=2; 297450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 297550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 297650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 297750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(a, a, f, &workset, &ignore); /* a=a*f */ 297850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, a, t, &workset, 0, &ignore); /* ..+t */ 297950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [a is now the initial approximation for sqrt(f), calculated with */ 298050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* currentprecision, which is also a's precision.] */ 298150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 298250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the main calculation loop */ 298350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dzero); /* make 0 */ 298450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(t); /* set t = 0.5 */ 298550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=5; /* .. */ 298650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->exponent=-1; /* .. */ 298750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.digits=3; /* initial p */ 298850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; workset.digits<maxp;) { 298950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set p to min(2*p - 2, maxp) [hence 3; or: 4, 6, 10, ... , maxp] */ 299050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.digits=MINI(workset.digits*2-2, maxp); 299150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a = 0.5 * (a + f/a) */ 299250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [calculated at p then rounded to currentprecision] */ 299350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(b, f, a, &workset, DIVIDE, &ignore); /* b=f/a */ 299450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(b, b, a, &workset, 0, &ignore); /* b=b+a */ 299550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(a, b, t, &workset, &ignore); /* a=b*0.5 */ 299650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* loop */ 299750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 299850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Here, 0.1 <= a < 1 [Hull], and a has maxp digits */ 299950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now reduce to length, etc.; this needs to be done with a */ 300050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* having the correct exponent so as to handle subnormals */ 300150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* correctly */ 300250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho approxset=*set; /* get emin, emax, etc. */ 300350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho approxset.round=DEC_ROUND_HALF_EVEN; 300450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->exponent+=exp/2; /* set correct exponent */ 300550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rstatus=0; /* clear status */ 300650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* .. and accumulator */ 300750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(a, a, &approxset, &residue, &rstatus); /* reduce (if needed) */ 300850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(a, &approxset, &residue, &rstatus); /* clean and finalize */ 300950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 301050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Overflow was possible if the input exponent was out-of-range, */ 301150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* in which case quit */ 301250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rstatus&DEC_Overflow) { 301350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status=rstatus; /* use the status as-is */ 301450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, a); /* copy to result */ 301550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 301650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 301750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 301850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Preserve status except Inexact/Rounded */ 301950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=(rstatus & ~(DEC_Rounded|DEC_Inexact)); 302050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 302150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Carry out the Hull correction */ 302250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->exponent-=exp/2; /* back to 0.1->1 */ 302350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 302450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a is now at final precision and within 1 ulp of the properly */ 302550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rounded square root of f; to ensure proper rounding, compare */ 302650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* squares of (a - l/2 ulp) and (a + l/2 ulp) with f. */ 302750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Here workset.digits=maxp and t=0.5, and a->digits determines */ 302850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the ulp */ 302950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.digits--; /* maxp-1 is OK now */ 303050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->exponent=-a->digits-1; /* make 0.5 ulp */ 303150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(b, a, t, &workset, DECNEG, &ignore); /* b = a - 0.5 ulp */ 303250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.round=DEC_ROUND_UP; 303350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(b, b, b, &workset, &ignore); /* b = mulru(b, b) */ 303450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(b, f, b, &workset, COMPARE, &ignore); /* b ? f, reversed */ 303550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(b)) { /* f < b [i.e., b > f] */ 303650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this is the more common adjustment, though both are rare */ 303750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->exponent++; /* make 1.0 ulp */ 303850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=1; /* .. */ 303950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, a, t, &workset, DECNEG, &ignore); /* a = a - 1 ulp */ 304050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* assign to approx [round to length] */ 304150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho approxset.emin-=exp/2; /* adjust to match a */ 304250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho approxset.emax-=exp/2; 304350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, &dzero, a, &approxset, 0, &ignore); 304450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 304550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 304650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(b, a, t, &workset, 0, &ignore); /* b = a + 0.5 ulp */ 304750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.round=DEC_ROUND_DOWN; 304850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(b, b, b, &workset, &ignore); /* b = mulrd(b, b) */ 304950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(b, b, f, &workset, COMPARE, &ignore); /* b ? f */ 305050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(b)) { /* b < f */ 305150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->exponent++; /* make 1.0 ulp */ 305250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->lsu[0]=1; /* .. */ 305350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, a, t, &workset, 0, &ignore); /* a = a + 1 ulp */ 305450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* assign to approx [round to length] */ 305550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho approxset.emin-=exp/2; /* adjust to match a */ 305650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho approxset.emax-=exp/2; 305750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, &dzero, a, &approxset, 0, &ignore); 305850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 305950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 306050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [no errors are possible in the above, and rounding/inexact during */ 306150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* estimation are irrelevant, so status was not accumulated] */ 306250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 306350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Here, 0.1 <= a < 1 (still), so adjust back */ 306450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->exponent+=exp/2; /* set correct exponent */ 306550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 306650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* count droppable zeros [after any subnormal rounding] by */ 306750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* trimming a copy */ 306850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(b, a); 306950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decTrim(b, set, 1, 1, &dropped); /* [drops trailing zeros] */ 307050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 307150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Set Inexact and Rounded. The answer can only be exact if */ 307250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it is short enough so that squaring it could fit in workp */ 307350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* digits, so this is the only (relatively rare) condition that */ 307450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a careful check is needed */ 307550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (b->digits*2-1 > workp) { /* cannot fit */ 307650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Inexact|DEC_Rounded; 307750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 307850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* could be exact/unrounded */ 307950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt mstatus=0; /* local status */ 308050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(b, b, b, &workset, &mstatus); /* try the multiply */ 308150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mstatus&DEC_Overflow) { /* result just won't fit */ 308250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Inexact|DEC_Rounded; 308350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 308450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* plausible */ 308550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(t, b, rhs, &workset, COMPARE, &mstatus); /* b ? rhs */ 308650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!ISZERO(t)) status|=DEC_Inexact|DEC_Rounded; /* not equal */ 308750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* is Exact */ 308850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here, dropped is the count of trailing zeros in 'a' */ 308950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* use closest exponent to ideal... */ 309050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int todrop=ideal-a->exponent; /* most that can be dropped */ 309150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (todrop<0) status|=DEC_Rounded; /* ideally would add 0s */ 309250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* unrounded */ 309350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* there are some to drop, but emax may not allow all */ 309450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxexp=set->emax-set->digits+1; 309550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxdrop=maxexp-a->exponent; 309650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (todrop>maxdrop && set->clamp) { /* apply clamping */ 309750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho todrop=maxdrop; 309850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Clamped; 309950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 310050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dropped<todrop) { /* clamp to those available */ 310150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho todrop=dropped; 310250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=DEC_Clamped; 310350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 310450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (todrop>0) { /* have some to drop */ 310550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decShiftToLeast(a->lsu, D2U(a->digits), todrop); 310650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->exponent+=todrop; /* maintain numerical value */ 310750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->digits-=todrop; /* new length */ 310850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 310950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 311050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 311150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 311250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 311350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 311450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* double-check Underflow, as perhaps the result could not have */ 311550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* been subnormal (initial argument too big), or it is now Exact */ 311650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status&DEC_Underflow) { 311750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ae=rhs->exponent+rhs->digits-1; /* adjusted exponent */ 311850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* check if truly subnormal */ 311950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECEXTFLAG /* DEC_Subnormal too */ 312050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ae>=set->emin*2) status&=~(DEC_Subnormal|DEC_Underflow); 312150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 312250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ae>=set->emin*2) status&=~DEC_Underflow; 312350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 312450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* check if truly inexact */ 312550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(status&DEC_Inexact)) status&=~DEC_Underflow; 312650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 312750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 312850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, a); /* a is now the result */ 312950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 313050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 313150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbuff!=NULL) free(allocbuff); /* drop any storage used */ 313250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa!=NULL) free(allocbufa); /* .. */ 313350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufb!=NULL) free(allocbufb); /* .. */ 313450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 313550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs !=NULL) free(allocrhs); /* .. */ 313650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 313750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set);/* then report status */ 313850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 313950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 314050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 314150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 314250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberSquareRoot */ 314302c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) 314402c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic pop 314502c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#endif 314650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 314750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 314850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberSubtract -- subtract two Numbers */ 314950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 315050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A - B */ 315150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 315250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X-X) */ 315350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 315450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 315550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 315650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 315750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 315850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 315950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberSubtract(decNumber *res, const decNumber *lhs, 316050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 316150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 316250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 316350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(res, lhs, rhs, set, DECNEG, &status); 316450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 316550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 316650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCheckInexact(res, set); 316750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 316850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 316950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberSubtract */ 317050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 317150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 317250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberToIntegralExact -- round-to-integral-value with InExact */ 317350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberToIntegralValue -- round-to-integral-value */ 317450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 317550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is the result */ 317650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is input number */ 317750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 317850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 317950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res must have space for any value of rhs. */ 318050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 318150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This implements the IEEE special operators and therefore treats */ 318250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* special values as valid. For finite numbers it returns */ 318350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rescale(rhs, 0) if rhs->exponent is <0. */ 318450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Otherwise the result is rhs (so no error is possible, except for */ 318550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* sNaN). */ 318650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 318750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The context is used for rounding mode and status after sNaN, but */ 318850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the digits setting is ignored. The Exact version will signal */ 318950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Inexact if the result differs numerically from rhs; the other */ 319050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* never signals Inexact. */ 319150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 319250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberToIntegralExact(decNumber *res, const decNumber *rhs, 319350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 319450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber dn; 319550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset; /* working context */ 319650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt status=0; /* accumulator */ 319750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 319850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 319950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 320050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 320150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 320250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle infinities and NaNs */ 320350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARG) { 320450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs)) uprv_decNumberCopy(res, rhs); /* an Infinity */ 320550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else decNaNs(res, rhs, NULL, set, &status); /* a NaN */ 320650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 320750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* finite */ 320850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* have a finite number; no error possible (res must be big enough) */ 320950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->exponent>=0) return uprv_decNumberCopy(res, rhs); 321050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* that was easy, but if negative exponent there is work to do... */ 321150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset=*set; /* clone rounding, etc. */ 321250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.digits=rhs->digits; /* no length rounding */ 321350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.traps=0; /* no traps */ 321450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&dn); /* make a number with exponent 0 */ 321550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberQuantize(res, rhs, &dn, &workset); 321650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status|=workset.status; 321750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 321850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status!=0) decStatus(res, status, set); 321950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 322050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberToIntegralExact */ 322150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 322250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberToIntegralValue(decNumber *res, const decNumber *rhs, 322350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set) { 322450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset=*set; /* working context */ 322550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.traps=0; /* no traps */ 322650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberToIntegralExact(res, rhs, &workset); 322750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this never affects set, except for sNaNs; NaN will have been set */ 322850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* or propagated already, so no need to call decStatus */ 322950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho set->status|=workset.status&DEC_Invalid_operation; 323050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 323150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberToIntegralValue */ 323250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 323350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 323450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberXor -- XOR two Numbers, digitwise */ 323550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 323650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ^ B */ 323750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 323850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X^X) */ 323950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 324050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 324150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context (used for result length and error report) */ 324250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 324350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 324450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 324550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Logical function restrictions apply (see above); a NaN is */ 324650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned with Invalid_operation if a restriction is violated. */ 324750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 324850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberXor(decNumber *res, const decNumber *lhs, 324950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 325050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *ua, *ub; /* -> operands */ 325150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *msua, *msub; /* -> operand msus */ 325250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *uc, *msuc; /* -> result and its msu */ 325350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int msudigs; /* digits in res msu */ 325450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 325550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 325650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 325750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 325850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs) 325950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { 326050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 326150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 326250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 326350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* operands are valid */ 326450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ua=lhs->lsu; /* bottom-up */ 326550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ub=rhs->lsu; /* .. */ 326650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uc=res->lsu; /* .. */ 326750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msua=ua+D2U(lhs->digits)-1; /* -> msu of lhs */ 326850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msub=ub+D2U(rhs->digits)-1; /* -> msu of rhs */ 326950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msuc=uc+D2U(set->digits)-1; /* -> msu of result */ 327050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */ 327150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */ 327250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit a, b; /* extract units */ 327350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ua>msua) a=0; 327450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else a=*ua; 327550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ub>msub) b=0; 327650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else b=*ub; 327750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uc=0; /* can now write back */ 327850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a|b) { /* maybe 1 bits to examine */ 327950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i, j; 328050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This loop could be unrolled and/or use BIN2BCD tables */ 328150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i=0; i<DECDPUN; i++) { 328250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((a^b)&1) *uc=*uc+(Unit)powers[i]; /* effect XOR */ 328350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho j=a%10; 328450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=a/10; 328550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho j|=b%10; 328650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=b/10; 328750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (j>1) { 328850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decStatus(res, DEC_Invalid_operation, set); 328950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 329050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 329150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uc==msuc && i==msudigs-1) break; /* just did final digit */ 329250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each digit */ 329350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* non-zero */ 329450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* each unit */ 329550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [here uc-1 is the msu of the result] */ 329650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(res->lsu, uc-res->lsu); 329750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=0; /* integer */ 329850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=0; /* sign=0 */ 329950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; /* [no status to set] */ 330050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberXor */ 330150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 330250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 330350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 330450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Utility routines */ 330550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 330650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 330750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 330850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberClass -- return the decClass of a decNumber */ 330950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn -- the decNumber to test */ 331050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set -- the context to use for Emin */ 331150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns the decClass enum */ 331250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 331350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoenum decClass uprv_decNumberClass(const decNumber *dn, decContext *set) { 331450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsSpecial(dn)) { 331550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsQNaN(dn)) return DEC_CLASS_QNAN; 331650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsSNaN(dn)) return DEC_CLASS_SNAN; 331750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* must be an infinity */ 331850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_INF; 331950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return DEC_CLASS_POS_INF; 332050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 332150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is finite */ 332250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (uprv_decNumberIsNormal(dn, set)) { /* most common */ 332350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_NORMAL; 332450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return DEC_CLASS_POS_NORMAL; 332550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 332650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is subnormal or zero */ 332750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(dn)) { /* most common */ 332850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_ZERO; 332950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return DEC_CLASS_POS_ZERO; 333050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 333150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_SUBNORMAL; 333250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return DEC_CLASS_POS_SUBNORMAL; 333350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberClass */ 333450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 333550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 333650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberClassToString -- convert decClass to a string */ 333750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 333850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* eclass is a valid decClass */ 333950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns a constant string describing the class (max 13+1 chars) */ 334050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 334150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst char *uprv_decNumberClassToString(enum decClass eclass) { 334250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_POS_NORMAL) return DEC_ClassString_PN; 334350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_NEG_NORMAL) return DEC_ClassString_NN; 334450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_POS_ZERO) return DEC_ClassString_PZ; 334550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_NEG_ZERO) return DEC_ClassString_NZ; 334650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_POS_SUBNORMAL) return DEC_ClassString_PS; 334750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_NEG_SUBNORMAL) return DEC_ClassString_NS; 334850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_POS_INF) return DEC_ClassString_PI; 334950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_NEG_INF) return DEC_ClassString_NI; 335050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_QNAN) return DEC_ClassString_QN; 335150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eclass==DEC_CLASS_SNAN) return DEC_ClassString_SN; 335250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return DEC_ClassString_UN; /* Unknown */ 335350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberClassToString */ 335450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 335550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 335650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCopy -- copy a number */ 335750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 335850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dest is the target decNumber */ 335950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* src is the source decNumber */ 336050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns dest */ 336150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 336250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (dest==src is allowed and is a no-op) */ 336350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All fields are updated as required. This is a utility operation, */ 336450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* so special values are unchanged and no error is possible. */ 336550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 336650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCopy(decNumber *dest, const decNumber *src) { 336750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 336850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 336950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (src==NULL) return uprv_decNumberZero(dest); 337050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 337150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 337250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dest==src) return dest; /* no copy required */ 337350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 337450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Use explicit assignments here as structure assignment could copy */ 337550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* more than just the lsu (for small DECDPUN). This would not affect */ 337650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the value of the results, but could disturb test harness spill */ 337750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* checking. */ 337850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dest->bits=src->bits; 337950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dest->exponent=src->exponent; 338050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dest->digits=src->digits; 338150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dest->lsu[0]=src->lsu[0]; 338250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (src->digits>DECDPUN) { /* more Units to come */ 338350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *smsup, *s; /* work */ 338450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *d; /* .. */ 338550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* memcpy for the remaining Units would be safe as they cannot */ 338650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* overlap. However, this explicit loop is faster in short cases. */ 338750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho d=dest->lsu+1; /* -> first destination */ 338850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho smsup=src->lsu+D2U(src->digits); /* -> source msu+1 */ 338950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (s=src->lsu+1; s<smsup; s++, d++) *d=*s; 339050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 339150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dest; 339250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCopy */ 339350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 339450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 339550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCopyAbs -- quiet absolute value operator */ 339650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 339750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This sets C = abs(A) */ 339850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 339950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 340050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 340150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 340250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 340350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No exception or error can occur; this is a quiet bitwise operation.*/ 340450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* See also decNumberAbs for a checking version of this. */ 340550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 340650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCopyAbs(decNumber *res, const decNumber *rhs) { 340750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 340850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res; 340950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 341050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, rhs); 341150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits&=~DECNEG; /* turn off sign */ 341250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 341350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCopyAbs */ 341450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 341550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 341650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCopyNegate -- quiet negate value operator */ 341750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 341850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This sets C = negate(A) */ 341950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 342050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 342150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 342250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 342350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 342450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No exception or error can occur; this is a quiet bitwise operation.*/ 342550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* See also decNumberMinus for a checking version of this. */ 342650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 342750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCopyNegate(decNumber *res, const decNumber *rhs) { 342850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 342950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res; 343050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 343150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, rhs); 343250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits^=DECNEG; /* invert the sign */ 343350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 343450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCopyNegate */ 343550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 343650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 343750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberCopySign -- quiet copy and set sign operator */ 343850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 343950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This sets C = A with the sign of B */ 344050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 344150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 344250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 344350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 344450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 344550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 344650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No exception or error can occur; this is a quiet bitwise operation.*/ 344750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 344850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberCopySign(decNumber *res, const decNumber *lhs, 344950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs) { 345050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte sign; /* rhs sign */ 345150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 345250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res; 345350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 345450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho sign=rhs->bits & DECNEG; /* save sign bit */ 345550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); 345650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits&=~DECNEG; /* clear the sign */ 345750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits|=sign; /* set from rhs */ 345850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 345950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberCopySign */ 346050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 346150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 346250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberGetBCD -- get the coefficient in BCD8 */ 346350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the source decNumber */ 346450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* bcd is the uInt array that will receive dn->digits BCD bytes, */ 346550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* most-significant at offset 0 */ 346650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns bcd */ 346750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 346850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* bcd must have at least dn->digits bytes. No error is possible; if */ 346950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is a NaN or Infinite, digits must be 1 and the coefficient 0. */ 347050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 347150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI uByte * U_EXPORT2 uprv_decNumberGetBCD(const decNumber *dn, uByte *bcd) { 347250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte *ub=bcd+dn->digits-1; /* -> lsd */ 347350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up=dn->lsu; /* Unit pointer, -> lsu */ 347450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 347550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==1 /* trivial simple copy */ 347650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; ub>=bcd; ub--, up++) *ub=*up; 347750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else /* chopping needed */ 347850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt u=*up; /* work */ 347950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt cut=DECDPUN; /* downcounter through unit */ 348050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; ub>=bcd; ub--) { 348150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *ub=(uByte)(u%10); /* [*6554 trick inhibits, here] */ 348250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=u/10; 348350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut--; 348450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut>0) continue; /* more in this unit */ 348550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; 348650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=*up; 348750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN; 348850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 348950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 349050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return bcd; 349150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberGetBCD */ 349250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 349350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 349450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberSetBCD -- set (replace) the coefficient from BCD8 */ 349550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the target decNumber */ 349650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* bcd is the uInt array that will source n BCD bytes, most- */ 349750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* significant at offset 0 */ 349850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* n is the number of digits in the source BCD array (bcd) */ 349950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns dn */ 350050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 350150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn must have space for at least n digits. No error is possible; */ 350250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if dn is a NaN, or Infinite, or is to become a zero, n must be 1 */ 350350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and bcd[0] zero. */ 350450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 350550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberSetBCD(decNumber *dn, const uByte *bcd, uInt n) { 350650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [target pointer] */ 350750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const uByte *ub=bcd; /* -> source msd */ 350850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 350950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==1 /* trivial simple copy */ 351050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; ub<bcd+n; ub++, up--) *up=*ub; 351150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else /* some assembly needed */ 351250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate how many digits in msu, and hence first cut */ 351350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int cut=MSUDIGITS(n); /* [faster than remainder] */ 351450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;up>=dn->lsu; up--) { /* each Unit from msu */ 351550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=0; /* will take <=DECDPUN digits */ 351650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; cut>0; ub++, cut--) *up=X10(*up)+*ub; 351750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN; /* next Unit has all digits */ 351850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 351950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 352050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=n; /* set digit count */ 352150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 352250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberSetBCD */ 352350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 352450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 352550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberIsNormal -- test normality of a decNumber */ 352650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the decNumber to test */ 352750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context to use for Emin */ 352850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns 1 if |dn| is finite and >=Nmin, 0 otherwise */ 352950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 353050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoInt uprv_decNumberIsNormal(const decNumber *dn, decContext *set) { 353150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ae; /* adjusted exponent */ 353250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 353350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0; 353450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 353550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 353650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsSpecial(dn)) return 0; /* not finite */ 353750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(dn)) return 0; /* not non-zero */ 353850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 353950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ae=dn->exponent+dn->digits-1; /* adjusted exponent */ 354050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ae<set->emin) return 0; /* is subnormal */ 354150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1; 354250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberIsNormal */ 354350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 354450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 354550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberIsSubnormal -- test subnormality of a decNumber */ 354650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the decNumber to test */ 354750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context to use for Emin */ 354850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns 1 if |dn| is finite, non-zero, and <Nmin, 0 otherwise */ 354950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 355050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoInt uprv_decNumberIsSubnormal(const decNumber *dn, decContext *set) { 355150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ae; /* adjusted exponent */ 355250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 355350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0; 355450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 355550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 355650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsSpecial(dn)) return 0; /* not finite */ 355750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(dn)) return 0; /* not non-zero */ 355850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 355950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ae=dn->exponent+dn->digits-1; /* adjusted exponent */ 356050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ae<set->emin) return 1; /* is subnormal */ 356150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; 356250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberIsSubnormal */ 356350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 356450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 356550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberTrim -- remove insignificant zeros */ 356650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 356750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to trim */ 356850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns dn */ 356950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 357050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All fields are updated as required. This is a utility operation, */ 357150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* so special values are unchanged and no error is possible. The */ 357250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* zeros are removed unconditionally. */ 357350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 357450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberTrim(decNumber *dn) { 357550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int dropped; /* work */ 357650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext set; /* .. */ 357750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 357850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(DECUNRESU, DECUNUSED, dn, DECUNCONT)) return dn; 357950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 358050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&set, DEC_INIT_BASE); /* clamp=0 */ 358150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return decTrim(dn, &set, 0, 1, &dropped); 358250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberTrim */ 358350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 358450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 358550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberVersion -- return the name and version of this module */ 358650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 358750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No error is possible. */ 358850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 358950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst char * uprv_decNumberVersion(void) { 359050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return DECVERSION; 359150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberVersion */ 359250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 359350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 359450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberZero -- set a number to 0 */ 359550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 359650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to set, with space for one digit */ 359750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns dn */ 359850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 359950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No error is possible. */ 360050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 360150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Memset is not used as it is much slower in some environments. */ 360250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI decNumber * U_EXPORT2 uprv_decNumberZero(decNumber *dn) { 360350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 360450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 360550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn; 360650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 360750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 360850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=0; 360950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=0; 361050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=1; 361150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->lsu[0]=0; 361250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 361350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberZero */ 361450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 361550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 361650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Local routines */ 361750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ================================================================== */ 361850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 361950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 362050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decToString -- lay out a number into a string */ 362150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 362250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to lay out */ 362350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* string is where to lay out the number */ 362450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* eng is 1 if Engineering, 0 if Scientific */ 362550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 362650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* string must be at least dn->digits+14 characters long */ 362750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No error is possible. */ 362850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 362950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Note that this routine can generate a -0 or 0.000. These are */ 363050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* never generated in subset to-number or arithmetic, but can occur */ 363150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* in non-subset arithmetic (e.g., -1*0 or 1.234-1.234). */ 363250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 363350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If DECCHECK is enabled the string "?" is returned if a number is */ 363450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* invalid. */ 363550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decToString(const decNumber *dn, char *string, Flag eng) { 363650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int exp=dn->exponent; /* local copy */ 363750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int e; /* E-part value */ 363850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int pre; /* digits before the '.' */ 363950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int cut; /* for counting digits in a Unit */ 364050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *c=string; /* work [output pointer] */ 364150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [input pointer] */ 364250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt u, pow; /* work */ 364350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 364450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 364550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(DECUNRESU, dn, DECUNUSED, DECUNCONT)) { 364650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho strcpy(string, "?"); 364750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return;} 364850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 364950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 365050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dn)) { /* Negatives get a minus */ 365150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='-'; 365250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; 365350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 365450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECSPECIAL) { /* Is a special value */ 365550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(dn)) { 365650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho strcpy(c, "Inf"); 365750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho strcpy(c+3, "inity"); 365850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return;} 365950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a NaN */ 366050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECSNAN) { /* signalling NaN */ 366150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='s'; 366250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; 366350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 366450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho strcpy(c, "NaN"); 366550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c+=3; /* step past */ 366650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if not a clean non-zero coefficient, that's all there is in a */ 366750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* NaN string */ 366850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exp!=0 || (*dn->lsu==0 && dn->digits==1)) return; 366950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [drop through to add integer] */ 367050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 367150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 367250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate how many digits in msu, and hence first cut */ 367350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=MSUDIGITS(dn->digits); /* [faster than remainder] */ 367450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut--; /* power of ten for digit */ 367550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 367650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exp==0) { /* simple integer [common fastpath] */ 367750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;up>=dn->lsu; up--) { /* each Unit from msu */ 367850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=*up; /* contains DECDPUN digits to lay out */ 367950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; cut>=0; c++, cut--) TODIGIT(u, cut, c, pow); 368050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN-1; /* next Unit has all digits */ 368150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 368250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='\0'; /* terminate the string */ 368350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return;} 368450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 368550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* non-0 exponent -- assume plain form */ 368650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pre=dn->digits+exp; /* digits before '.' */ 368750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho e=0; /* no E */ 368850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((exp>0) || (pre<-5)) { /* need exponential form */ 368950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho e=exp+dn->digits-1; /* calculate E value */ 369050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pre=1; /* assume one digit before '.' */ 369150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (eng && (e!=0)) { /* engineering: may need to adjust */ 369250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int adj; /* adjustment */ 369350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The C remainder operator is undefined for negative numbers, so */ 369450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a positive remainder calculation must be used here */ 369550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (e<0) { 369650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adj=(-e)%3; 369750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adj!=0) adj=3-adj; 369850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 369950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* e>0 */ 370050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adj=e%3; 370150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 370250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho e=e-adj; 370350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if dealing with zero still produce an exponent which is a */ 370450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* multiple of three, as expected, but there will only be the */ 370550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* one zero before the E, still. Otherwise note the padding. */ 370650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!ISZERO(dn)) pre+=adj; 370750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* is zero */ 370850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adj!=0) { /* 0.00Esnn needed */ 370950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho e=e+3; 371050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pre=-(2-adj); 371150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 371250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* zero */ 371350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* eng */ 371450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* need exponent */ 371550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 371650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lay out the digits of the coefficient, adding 0s and . as needed */ 371750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=*up; 371850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pre>0) { /* xxx.xxx or xx00 (engineering) form */ 371950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int n=pre; 372050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; pre>0; pre--, c++, cut--) { 372150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut<0) { /* need new Unit */ 372250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (up==dn->lsu) break; /* out of input digits (pre>digits) */ 372350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up--; 372450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN-1; 372550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=*up; 372650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 372750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho TODIGIT(u, cut, c, pow); 372850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 372950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n<dn->digits) { /* more to come, after '.' */ 373050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='.'; c++; 373150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;; c++, cut--) { 373250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut<0) { /* need new Unit */ 373350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (up==dn->lsu) break; /* out of input digits */ 373450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up--; 373550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN-1; 373650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=*up; 373750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 373850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho TODIGIT(u, cut, c, pow); 373950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 374050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 374150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else for (; pre>0; pre--, c++) *c='0'; /* 0 padding (for engineering) needed */ 374250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 374350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* 0.xxx or 0.000xxx form */ 374450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='0'; c++; 374550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='.'; c++; 374650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; pre<0; pre++, c++) *c='0'; /* add any 0's after '.' */ 374750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; ; c++, cut--) { 374850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut<0) { /* need new Unit */ 374950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (up==dn->lsu) break; /* out of input digits */ 375050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up--; 375150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN-1; 375250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=*up; 375350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 375450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho TODIGIT(u, cut, c, pow); 375550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 375650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 375750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 375850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Finally add the E-part, if needed. It will never be 0, has a 375950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho base maximum and minimum of +999999999 through -999999999, but 376050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho could range down to -1999999998 for anormal numbers */ 376150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (e!=0) { 376250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag had=0; /* 1=had non-zero */ 376350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='E'; c++; 376450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='+'; c++; /* assume positive */ 376550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=e; /* .. */ 376650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (e<0) { 376750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *(c-1)='-'; /* oops, need - */ 376850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=-e; /* uInt, please */ 376950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 377050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lay out the exponent [_itoa or equivalent is not ANSI C] */ 377150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (cut=9; cut>=0; cut--) { 377250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho TODIGIT(u, cut, c, pow); 377350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c=='0' && !had) continue; /* skip leading zeros */ 377450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho had=1; /* had non-0 */ 377550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; /* step for next */ 377650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* cut */ 377750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 377850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c='\0'; /* terminate the string (all paths) */ 377950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 378050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decToString */ 378150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 378250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 378350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decAddOp -- add/subtract operation */ 378450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 378550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A + B */ 378650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 378750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X+X) */ 378850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 378950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 379050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 379150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* negate is DECNEG if rhs should be negated, or 0 otherwise */ 379250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status accumulates status for the caller */ 379350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 379450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 379550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Inexact in status must be 0 for correct Exact zero sign in result */ 379650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 379750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If possible, the coefficient is calculated directly into C. */ 379850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* However, if: */ 379950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -- a digits+1 calculation is needed because the numbers are */ 380050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* unaligned and span more than set->digits digits */ 380150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -- a carry to digits+1 digits looks possible */ 380250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -- C is the same as A or B, and the result would destructively */ 380350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* overlap the A or B coefficient */ 380450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* then the result must be calculated into a temporary buffer. In */ 380550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* this case a local (stack) buffer is used if possible, and only if */ 380650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* too long for that does malloc become the final resort. */ 380750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 380850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Misalignment is handled as follows: */ 380950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Apad: (AExp>BExp) Swap operands and proceed as for BExp>AExp. */ 381050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* BPad: Apply the padding by a combination of shifting (whole */ 381150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* units) and multiplication (part units). */ 381250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 381350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Addition, especially x=x+1, is speed-critical. */ 381450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The static buffer is larger than might be expected to allow for */ 381550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* calls from higher-level funtions (notable exp). */ 381650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 381750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decAddOp(decNumber *res, const decNumber *lhs, 381850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set, 381950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte negate, uInt *status) { 382050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 382150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */ 382250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* .., rhs */ 382350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 382450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int rhsshift; /* working shift (in Units) */ 382550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxdigits; /* longest logical length */ 382650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int mult; /* multiplier */ 382750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue; /* rounding accumulator */ 382850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte bits; /* result bits */ 382950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag diffsign; /* non-0 if arguments have different sign */ 383050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *acc; /* accumulator for result */ 383150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit accbuff[SD2U(DECBUFFER*2+20)]; /* local buffer [*2+20 reduces many */ 383250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* allocations when called from */ 383350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* other operations, notable exp] */ 383450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *allocacc=NULL; /* -> allocated acc buffer, iff allocated */ 383550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int reqdigits=set->digits; /* local copy; requested DIGITS */ 383650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int padding; /* work */ 383750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 383850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 383950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 384050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 384150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 384250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 384350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 384450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 384550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operands and set lostDigits status, as needed */ 384650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>reqdigits) { 384750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloclhs=decRoundOperand(lhs, set, status); 384850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs==NULL) break; 384950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=alloclhs; 385050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 385150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>reqdigits) { 385250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, status); 385350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 385450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 385550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 385650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 385750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 385850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 385950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 386050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* note whether signs differ [used all paths] */ 386150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho diffsign=(Flag)((lhs->bits^rhs->bits^negate)&DECNEG); 386250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 386350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle infinities and NaNs */ 386450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS) { /* a special bit set */ 386550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS & (DECSNAN | DECNAN)) /* a NaN */ 386650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, status); 386750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* one or two infinities */ 386850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(lhs)) { /* LHS is infinity */ 386950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* two infinities with different signs is invalid */ 387050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs) && diffsign) { 387150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 387250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 387350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 387450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=lhs->bits & DECNEG; /* get sign from LHS */ 387550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 387650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else bits=(rhs->bits^negate) & DECNEG;/* RHS must be Infinity */ 387750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits|=DECINF; 387850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 387950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; /* set +/- infinity */ 388050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* an infinity */ 388150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 388250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 388350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 388450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Quick exit for add 0s; return the non-0, modified as need be */ 388550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(lhs)) { 388650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int adjust; /* work */ 388750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int lexp=lhs->exponent; /* save in case LHS==RES */ 388850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=lhs->bits; /* .. */ 388950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* clear accumulator */ 389050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, rhs, set, &residue, status); /* copy (as needed) */ 389150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits^=negate; /* flip if rhs was negated */ 389250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 389350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->extended) { /* exponents on zeros count */ 389450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 389550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* exponent will be the lower of the two */ 389650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adjust=lexp-res->exponent; /* adjustment needed [if -ve] */ 389750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(res)) { /* both 0: special IEEE 754 rules */ 389850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adjust<0) res->exponent=lexp; /* set exponent */ 389950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 0-0 gives +0 unless rounding to -infinity, and -0-0 gives -0 */ 390050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (diffsign) { 390150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->round!=DEC_ROUND_FLOOR) res->bits=0; 390250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else res->bits=DECNEG; /* preserve 0 sign */ 390350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 390450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 390550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* non-0 res */ 390650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adjust<0) { /* 0-padding needed */ 390750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((res->digits-adjust)>set->digits) { 390850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adjust=res->digits-set->digits; /* to fit exactly */ 390950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Rounded; /* [but exact] */ 391050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 391150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, res->digits, -adjust); 391250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent+=adjust; /* set the exponent. */ 391350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 391450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* non-0 res */ 391550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 391650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* extended */ 391750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 391850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* clean and finalize */ 391950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 392050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 392150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) { /* [lhs is non-zero] */ 392250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int adjust; /* work */ 392350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int rexp=rhs->exponent; /* save in case RHS==RES */ 392450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=rhs->bits; /* be clean */ 392550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* clear accumulator */ 392650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, lhs, set, &residue, status); /* copy (as needed) */ 392750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 392850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->extended) { /* exponents on zeros count */ 392950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 393050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* exponent will be the lower of the two */ 393150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [0-0 case handled above] */ 393250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adjust=rexp-res->exponent; /* adjustment needed [if -ve] */ 393350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adjust<0) { /* 0-padding needed */ 393450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((res->digits-adjust)>set->digits) { 393550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adjust=res->digits-set->digits; /* to fit exactly */ 393650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Rounded; /* [but exact] */ 393750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 393850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, res->digits, -adjust); 393950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent+=adjust; /* set the exponent. */ 394050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 394150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 394250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* extended */ 394350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 394450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* clean and finalize */ 394550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 394650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 394750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [NB: both fastpath and mainpath code below assume these cases */ 394850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (notably 0-0) have already been handled] */ 394950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 395050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the padding needed to align the operands */ 395150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho padding=rhs->exponent-lhs->exponent; 395250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 395350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Fastpath cases where the numbers are aligned and normal, the RHS */ 395450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is all in one unit, no operand rounding is needed, and no carry, */ 395550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lengthening, or borrow is needed */ 395650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (padding==0 395750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && rhs->digits<=DECDPUN 395850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && rhs->exponent>=set->emin /* [some normals drop through] */ 395950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && rhs->exponent<=set->emax-set->digits+1 /* [could clamp] */ 396050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && rhs->digits<=reqdigits 396150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && lhs->digits<=reqdigits) { 396250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int partial=*lhs->lsu; 396350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!diffsign) { /* adding */ 396450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho partial+=*rhs->lsu; 396550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((partial<=DECDPUNMAX) /* result fits in unit */ 396650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && (lhs->digits>=DECDPUN || /* .. and no digits-count change */ 396750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho partial<(Int)powers[lhs->digits])) { /* .. */ 396850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res!=lhs) uprv_decNumberCopy(res, lhs); /* not in place */ 396950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=(Unit)partial; /* [copy could have overwritten RHS] */ 397050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 397150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 397250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* else drop out for careful add */ 397350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 397450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* signs differ */ 397550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho partial-=*rhs->lsu; 397650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (partial>0) { /* no borrow needed, and non-0 result */ 397750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res!=lhs) uprv_decNumberCopy(res, lhs); /* not in place */ 397850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=(Unit)partial; 397950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this could have reduced digits [but result>0] */ 398050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(res->lsu, D2U(res->digits)); 398150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 398250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 398350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* else drop out for careful subtract */ 398450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 398550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 398650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 398750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Now align (pad) the lhs or rhs so they can be added or */ 398850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subtracted, as necessary. If one number is much larger than */ 398950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the other (that is, if in plain form there is a least one */ 399050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* digit between the lowest digit of one and the highest of the */ 399150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* other) padding with up to DIGITS-1 trailing zeros may be */ 399250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* needed; then apply rounding (as exotic rounding modes may be */ 399350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* affected by the residue). */ 399450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhsshift=0; /* rhs shift to left (padding) in Units */ 399550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=lhs->bits; /* assume sign is that of LHS */ 399650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mult=1; /* likely multiplier */ 399750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 399850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [if padding==0 the operands are aligned; no padding is needed] */ 399950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (padding!=0) { 400050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* some padding needed; always pad the RHS, as any required */ 400150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* padding can then be effected by a simple combination of */ 400250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* shifts and a multiply */ 400350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag swapped=0; 400450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (padding<0) { /* LHS needs the padding */ 400550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *t; 400650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho padding=-padding; /* will be +ve */ 400750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=(uByte)(rhs->bits^negate); /* assumed sign is now that of RHS */ 400850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t=lhs; lhs=rhs; rhs=t; 400950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho swapped=1; 401050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 401150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 401250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If, after pad, rhs would be longer than lhs by digits+1 or */ 401350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* more then lhs cannot affect the answer, except as a residue, */ 401450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* so only need to pad up to a length of DIGITS+1. */ 401550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits+padding > lhs->digits+reqdigits+1) { 401650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The RHS is sufficient */ 401750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* for residue use the relative sign indication... */ 401850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift=reqdigits-rhs->digits; /* left shift needed */ 401950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=1; /* residue for rounding */ 402050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (diffsign) residue=-residue; /* signs differ */ 402150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* copy, shortening if necessary */ 402250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, rhs, set, &residue, status); 402350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if it was already shorter, then need to pad with zeros */ 402450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift>0) { 402550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, res->digits, shift); 402650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent-=shift; /* adjust the exponent. */ 402750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 402850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* flip the result sign if unswapped and rhs was negated */ 402950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!swapped) res->bits^=negate; 403050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* done */ 403150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 403250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 403350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* LHS digits may affect result */ 403450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhsshift=D2U(padding+1)-1; /* this much by Unit shift .. */ 403550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mult=powers[padding-(rhsshift*DECDPUN)]; /* .. this by multiplication */ 403650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* padding needed */ 403750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 403850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (diffsign) mult=-mult; /* signs differ */ 403950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 404050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* determine the longer operand */ 404150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxdigits=rhs->digits+padding; /* virtual length of RHS */ 404250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>maxdigits) maxdigits=lhs->digits; 404350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 404450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Decide on the result buffer to use; if possible place directly */ 404550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* into result. */ 404650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=res->lsu; /* assume add direct to result */ 404750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If destructive overlap, or the number is too long, or a carry or */ 404850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* borrow to DIGITS+1 might be possible, a buffer must be used. */ 404950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [Might be worth more sophisticated tests when maxdigits==reqdigits] */ 405050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((maxdigits>=reqdigits) /* is, or could be, too large */ 405150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (res==rhs && rhsshift>0)) { /* destructive overlap */ 405250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffer needed, choose it; units for maxdigits digits will be */ 405350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* needed, +1 Unit for carry or borrow */ 405450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int need=D2U(maxdigits)+1; 405550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=accbuff; /* assume use local buffer */ 405650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (need*sizeof(Unit)>sizeof(accbuff)) { 405750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* printf("malloc add %ld %ld\n", need, sizeof(accbuff)); */ 405850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocacc=(Unit *)malloc(need*sizeof(Unit)); 405950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc==NULL) { /* hopeless -- abandon */ 406050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 406150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 406250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=allocacc; 406350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 406450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 406550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 406650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=(uByte)(bits&DECNEG); /* it's now safe to overwrite.. */ 406750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=lhs->exponent; /* .. operands (even if aliased) */ 406850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 406950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 407050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('A', lhs->lsu, D2U(lhs->digits)); 407150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('B', rhs->lsu, D2U(rhs->digits)); 407250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf(" :h: %ld %ld\n", rhsshift, mult); 407350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 407450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 407550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* add [A+B*m] or subtract [A+B*(-m)] */ 407650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decUnitAddSub(lhs->lsu, D2U(lhs->digits), 407750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs->lsu, D2U(rhs->digits), 407850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhsshift, acc, mult) 407950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *DECDPUN; /* [units -> digits] */ 408050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits<0) { /* borrowed... */ 408150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=-res->digits; 408250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits^=DECNEG; /* flip the sign */ 408350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 408450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 408550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('+', acc, D2U(res->digits)); 408650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 408750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 408850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If a buffer was used the result must be copied back, possibly */ 408950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* shortening. (If no buffer was used then the result must have */ 409050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* fit, so can't need rounding and residue must be 0.) */ 409150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* clear accumulator */ 409250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (acc!=res->lsu) { 409350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 409450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->extended) { /* round from first significant digit */ 409550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 409650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* remove leading zeros that were added due to rounding up to */ 409750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* integral Units -- before the test for rounding. */ 409850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits>reqdigits) 409950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(acc, D2U(res->digits)); 410050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetCoeff(res, set, acc, res->digits, &residue, status); 410150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 410250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 410350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* subset arithmetic rounds from original significant digit */ 410450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* May have an underestimate. This only occurs when both */ 410550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* numbers fit in DECDPUN digits and are padding with a */ 410650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative multiple (-10, -100...) and the top digit(s) become */ 410750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 0. (This only matters when using X3.274 rules where the */ 410850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* leading zero could be included in the rounding.) */ 410950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits<maxdigits) { 411050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *(acc+D2U(res->digits))=0; /* ensure leading 0 is there */ 411150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=maxdigits; 411250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 411350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 411450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* remove leading zeros that added due to rounding up to */ 411550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* integral Units (but only those in excess of the original */ 411650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* maxdigits length, unless extended) before test for rounding. */ 411750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits>reqdigits) { 411850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(acc, D2U(res->digits)); 411950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits<maxdigits) res->digits=maxdigits; 412050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 412150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 412250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetCoeff(res, set, acc, res->digits, &residue, status); 412350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Now apply rounding if needed before removing leading zeros. */ 412450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This is safe because subnormals are not a possibility */ 412550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue!=0) { 412650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decApplyRound(res, set, residue, status); 412750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* did what needed to be done */ 412850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 412950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* subset */ 413050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 413150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* used buffer */ 413250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 413350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* strip leading zeros [these were left on in case of subset subtract] */ 413450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(res->lsu, D2U(res->digits)); 413550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 413650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* apply checks and rounding */ 413750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); 413850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 413950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* "When the sum of two operands with opposite signs is exactly */ 414050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* zero, the sign of that sum shall be '+' in all rounding modes */ 414150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* except round toward -Infinity, in which mode that sign shall be */ 414250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* '-'." [Subset zeros also never have '-', set by decFinish.] */ 414350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(res) && diffsign 414450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 414550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && set->extended 414650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 414750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && (*status&DEC_Inexact)==0) { 414850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->round==DEC_ROUND_FLOOR) res->bits|=DECNEG; /* sign - */ 414950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else res->bits&=~DECNEG; /* sign + */ 415050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 415150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 415250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 415350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc!=NULL) free(allocacc); /* drop any storage used */ 415450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 415550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs!=NULL) free(allocrhs); /* .. */ 415650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs!=NULL) free(alloclhs); /* .. */ 415750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 415850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 415950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decAddOp */ 416050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 416150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 416250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decDivideOp -- division operation */ 416350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 416450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine performs the calculations for all four division */ 416550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* operators (divide, divideInteger, remainder, remainderNear). */ 416650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 416750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C=A op B */ 416850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 416950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X/X) */ 417050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 417150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 417250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 417350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* op is DIVIDE, DIVIDEINT, REMAINDER, or REMNEAR respectively. */ 417450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the usual accumulator */ 417550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 417650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 417750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 417850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 417950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The underlying algorithm of this routine is the same as in the */ 418050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 1981 S/370 implementation, that is, non-restoring long division */ 418150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* with bi-unit (rather than bi-digit) estimation for each unit */ 418250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* multiplier. In this pseudocode overview, complications for the */ 418350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Remainder operators and division residues for exact rounding are */ 418450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* omitted for clarity. */ 418550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 418650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Prepare operands and handle special values */ 418750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Test for x/0 and then 0/x */ 418850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Exp =Exp1 - Exp2 */ 418950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Exp =Exp +len(var1) -len(var2) */ 419050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Sign=Sign1 * Sign2 */ 419150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Pad accumulator (Var1) to double-length with 0's (pad1) */ 419250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Pad Var2 to same length as Var1 */ 419350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* msu2pair/plus=1st 2 or 1 units of var2, +1 to allow for round */ 419450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* have=0 */ 419550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Do until (have=digits+1 OR residue=0) */ 419650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if exp<0 then if integer divide/residue then leave */ 419750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* this_unit=0 */ 419850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Do forever */ 419950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* compare numbers */ 420050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if <0 then leave inner_loop */ 420150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if =0 then (* quick exit without subtract *) do */ 420250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* this_unit=this_unit+1; output this_unit */ 420350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* leave outer_loop; end */ 420450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Compare lengths of numbers (mantissae): */ 420550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If same then tops2=msu2pair -- {units 1&2 of var2} */ 420650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* else tops2=msu2plus -- {0, unit 1 of var2} */ 420750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* tops1=first_unit_of_Var1*10**DECDPUN +second_unit_of_var1 */ 420850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* mult=tops1/tops2 -- Good and safe guess at divisor */ 420950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if mult=0 then mult=1 */ 421050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* this_unit=this_unit+mult */ 421150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* subtract */ 421250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end inner_loop */ 421350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if have\=0 | this_unit\=0 then do */ 421450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* output this_unit */ 421550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* have=have+1; end */ 421650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* var2=var2/10 */ 421750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* exp=exp-1 */ 421850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* end outer_loop */ 421950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* exp=exp+1 -- set the proper exponent */ 422050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if have=0 then generate answer=0 */ 422150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Return (Result is defined by Var1) */ 422250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 422350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 422450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Two working buffers are needed during the division; one (digits+ */ 422550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 1) to accumulate the result, and the other (up to 2*digits+1) for */ 422650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* long subtractions. These are acc and var1 respectively. */ 422750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* var1 is a copy of the lhs coefficient, var2 is the rhs coefficient.*/ 422850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The static buffers may be larger than might be expected to allow */ 422950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* for calls from higher-level funtions (notable exp). */ 423050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 423150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decDivideOp(decNumber *res, 423250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *lhs, const decNumber *rhs, 423350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set, Flag op, uInt *status) { 423450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 423550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */ 423650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* .., rhs */ 423750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 423850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit accbuff[SD2U(DECBUFFER+DECDPUN+10)]; /* local buffer */ 423950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *acc=accbuff; /* -> accumulator array for result */ 424050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *allocacc=NULL; /* -> allocated buffer, iff allocated */ 424150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *accnext; /* -> where next digit will go */ 424250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int acclength; /* length of acc needed [Units] */ 424350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int accunits; /* count of units accumulated */ 424450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int accdigits; /* count of digits accumulated */ 424550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 424650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit varbuff[SD2U(DECBUFFER*2+DECDPUN)]; /* buffer for var1 */ 424750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *var1=varbuff; /* -> var1 array for long subtraction */ 424850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *varalloc=NULL; /* -> allocated buffer, iff used */ 424950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *msu1; /* -> msu of var1 */ 425050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 425150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *var2; /* -> var2 array */ 425250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *msu2; /* -> msu of var2 */ 425350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int msu2plus; /* msu2 plus one [does not vary] */ 425450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho eInt msu2pair; /* msu2 pair plus one [does not vary] */ 425550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 425650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int var1units, var2units; /* actual lengths */ 425750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int var2ulen; /* logical length (units) */ 425850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int var1initpad=0; /* var1 initial padding (digits) */ 425950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxdigits; /* longest LHS or required acc length */ 426050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int mult; /* multiplier for subtraction */ 426150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit thisunit; /* current unit being accumulated */ 426250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue; /* for rounding */ 426350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int reqdigits=set->digits; /* requested DIGITS */ 426450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int exponent; /* working exponent */ 426550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxexponent=0; /* DIVIDE maximum exponent if unrounded */ 426650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte bits; /* working sign */ 426750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *target; /* work */ 426850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *source; /* .. */ 426950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt const *pow; /* .. */ 427050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift, cut; /* .. */ 427150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 427250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int dropped; /* work */ 427350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 427450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 427550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 427650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 427750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 427850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 427950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 428050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 428150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 428250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operands and set lostDigits status, as needed */ 428350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>reqdigits) { 428450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloclhs=decRoundOperand(lhs, set, status); 428550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs==NULL) break; 428650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=alloclhs; 428750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 428850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>reqdigits) { 428950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, status); 429050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 429150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 429250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 429350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 429450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 429550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 429650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 429750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=(lhs->bits^rhs->bits)&DECNEG; /* assumed sign for divisions */ 429850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 429950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle infinities and NaNs */ 430050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS) { /* a special bit set */ 430150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */ 430250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, status); 430350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 430450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 430550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* one or two infinities */ 430650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(lhs)) { /* LHS (dividend) is infinite */ 430750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs) || /* two infinities are invalid .. */ 430850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho op & (REMAINDER | REMNEAR)) { /* as is remainder of infinity */ 430950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 431050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 431150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 431250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [Note that infinity/0 raises no exceptions] */ 431350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 431450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits|DECINF; /* set +/- infinity */ 431550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 431650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 431750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* RHS (divisor) is infinite */ 431850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; 431950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&(REMAINDER|REMNEAR)) { 432050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* result is [finished clone of] lhs */ 432150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, lhs, set, &residue, status); 432250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 432350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* a division */ 432450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 432550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; /* set +/- zero */ 432650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* for DIVIDEINT the exponent is always 0. For DIVIDE, result */ 432750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is a 0 with infinitely negative exponent, clamped to minimum */ 432850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&DIVIDE) { 432950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=set->emin-set->digits+1; 433050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Clamped; 433150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 433250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 433350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); 433450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 433550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 433650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 433750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 433850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle 0 rhs (x/0) */ 433950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) { /* x/0 is always exceptional */ 434050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(lhs)) { 434150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* [after lhs test] */ 434250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Division_undefined;/* 0/0 will become NaN */ 434350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 434450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 434550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 434650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&(REMAINDER|REMNEAR)) *status|=DEC_Invalid_operation; 434750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 434850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Division_by_zero; /* x/0 */ 434950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits|DECINF; /* .. is +/- Infinity */ 435050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 435150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 435250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 435350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 435450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle 0 lhs (0/x) */ 435550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(lhs)) { /* 0/x [x!=0] */ 435650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 435750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) uprv_decNumberZero(res); 435850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 435950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 436050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&DIVIDE) { 436150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; 436250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent=lhs->exponent-rhs->exponent; /* ideal exponent */ 436350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); /* [zeros always fit] */ 436450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; /* sign as computed */ 436550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=exponent; /* exponent, too */ 436650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinalize(res, set, &residue, status); /* check exponent */ 436750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 436850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (op&DIVIDEINT) { 436950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* integer 0 */ 437050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; /* sign as computed */ 437150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 437250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* a remainder */ 437350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent=rhs->exponent; /* [save in case overwrite] */ 437450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); /* [zeros always fit] */ 437550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exponent<res->exponent) res->exponent=exponent; /* use lower */ 437650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 437750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 437850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 437950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 438050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 438150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 438250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Precalculate exponent. This starts off adjusted (and hence fits */ 438350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* in 31 bits) and becomes the usual unadjusted exponent as the */ 438450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* division proceeds. The order of evaluation is important, here, */ 438550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* to avoid wrap. */ 438650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent=(lhs->exponent+lhs->digits)-(rhs->exponent+rhs->digits); 438750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 438850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If the working exponent is -ve, then some quick exits are */ 438950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* possible because the quotient is known to be <1 */ 439050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [for REMNEAR, it needs to be < -1, as -0.5 could need work] */ 439150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exponent<0 && !(op==DIVIDE)) { 439250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&DIVIDEINT) { 439350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* integer part is 0 */ 439450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 439550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->extended) 439650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 439750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; /* set +/- zero */ 439850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 439950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* fastpath remainders so long as the lhs has the smaller */ 440050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (or equal) exponent */ 440150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent<=rhs->exponent) { 440250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&REMAINDER || exponent<-1) { 440350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* It is REMAINDER or safe REMNEAR; result is [finished */ 440450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* clone of] lhs (r = x - 0*y) */ 440550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; 440650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, lhs, set, &residue, status); 440750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); 440850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 440950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 441050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [unsafe REMNEAR drops through] */ 441150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 441250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* fastpaths */ 441350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 441450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Long (slow) division is needed; roll up the sleeves... */ 441550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 441650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The accumulator will hold the quotient of the division. */ 441750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If it needs to be too long for stack storage, then allocate. */ 441850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acclength=D2U(reqdigits+DECDPUN); /* in Units */ 441950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (acclength*sizeof(Unit)>sizeof(accbuff)) { 442050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* printf("malloc dvacc %ld units\n", acclength); */ 442150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocacc=(Unit *)malloc(acclength*sizeof(Unit)); 442250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc==NULL) { /* hopeless -- abandon */ 442350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 442450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 442550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=allocacc; /* use the allocated space */ 442650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 442750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 442850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* var1 is the padded LHS ready for subtractions. */ 442950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If it needs to be too long for stack storage, then allocate. */ 443050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The maximum units needed for var1 (long subtraction) is: */ 443150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Enough for */ 443250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (rhs->digits+reqdigits-1) -- to allow full slide to right */ 443350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* or (lhs->digits) -- to allow for long lhs */ 443450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* whichever is larger */ 443550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* +1 -- for rounding of slide to right */ 443650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* +1 -- for leading 0s */ 443750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* +1 -- for pre-adjust if a remainder or DIVIDEINT */ 443850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [Note: unused units do not participate in decUnitAddSub data] */ 443950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxdigits=rhs->digits+reqdigits-1; 444050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>maxdigits) maxdigits=lhs->digits; 444150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var1units=D2U(maxdigits)+2; 444250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* allocate a guard unit above msu1 for REMAINDERNEAR */ 444350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(op&DIVIDE)) var1units++; 444450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((var1units+1)*sizeof(Unit)>sizeof(varbuff)) { 444550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* printf("malloc dvvar %ld units\n", var1units+1); */ 444650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho varalloc=(Unit *)malloc((var1units+1)*sizeof(Unit)); 444750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (varalloc==NULL) { /* hopeless -- abandon */ 444850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 444950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 445050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var1=varalloc; /* use the allocated space */ 445150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 445250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 445350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Extend the lhs and rhs to full long subtraction length. The lhs */ 445450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is truly extended into the var1 buffer, with 0 padding, so a */ 445550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subtract in place is always possible. The rhs (var2) has */ 445650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* virtual padding (implemented by decUnitAddSub). */ 445750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* One guard unit was allocated above msu1 for rem=rem+rem in */ 445850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* REMAINDERNEAR. */ 445950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msu1=var1+var1units-1; /* msu of var1 */ 446050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho source=lhs->lsu+D2U(lhs->digits)-1; /* msu of input array */ 446150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (target=msu1; source>=lhs->lsu; source--, target--) *target=*source; 446250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; target>=var1; target--) *target=0; 446350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 446450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rhs (var2) is left-aligned with var1 at the start */ 446550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var2ulen=var1units; /* rhs logical length (units) */ 446650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var2units=D2U(rhs->digits); /* rhs actual length (units) */ 446750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var2=rhs->lsu; /* -> rhs array */ 446850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msu2=var2+var2units-1; /* -> msu of var2 [never changes] */ 446950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now set up the variables which will be used for estimating the */ 447050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* multiplication factor. If these variables are not exact, add */ 447150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1 to make sure that the multiplier is never overestimated. */ 447250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msu2plus=*msu2; /* it's value .. */ 447350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (var2units>1) msu2plus++; /* .. +1 if any more */ 447450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msu2pair=(eInt)*msu2*(DECDPUNMAX+1);/* top two pair .. */ 447550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (var2units>1) { /* .. [else treat 2nd as 0] */ 447650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msu2pair+=*(msu2-1); /* .. */ 447750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (var2units>2) msu2pair++; /* .. +1 if any more */ 447850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 447950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 448050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The calculation is working in units, which may have leading zeros, */ 448150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* but the exponent was calculated on the assumption that they are */ 448250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* both left-aligned. Adjust the exponent to compensate: add the */ 448350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* number of leading zeros in var1 msu and subtract those in var2 msu. */ 448450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [This is actually done by counting the digits and negating, as */ 448550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lead1=DECDPUN-digits1, and similarly for lead2.] */ 448650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (pow=&powers[1]; *msu1>=*pow; pow++) exponent--; 448750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (pow=&powers[1]; *msu2>=*pow; pow++) exponent++; 448850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 448950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Now, if doing an integer divide or remainder, ensure that */ 449050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the result will be Unit-aligned. To do this, shift the var1 */ 449150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accumulator towards least if need be. (It's much easier to */ 449250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* do this now than to reassemble the residue afterwards, if */ 449350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* doing a remainder.) Also ensure the exponent is not negative. */ 449450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(op&DIVIDE)) { 449550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *u; /* work */ 449650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* save the initial 'false' padding of var1, in digits */ 449750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var1initpad=(var1units-D2U(lhs->digits))*DECDPUN; 449850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Determine the shift to do. */ 449950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exponent<0) cut=-exponent; 450050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else cut=DECDPUN-exponent%DECDPUN; 450150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decShiftToLeast(var1, var1units, cut); 450250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent+=cut; /* maintain numerical value */ 450350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var1initpad-=cut; /* .. and reduce padding */ 450450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* clean any most-significant units which were just emptied */ 450550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (u=msu1; cut>=DECDPUN; cut-=DECDPUN, u--) *u=0; 450650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* align */ 450750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* is DIVIDE */ 450850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxexponent=lhs->exponent-rhs->exponent; /* save */ 450950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* optimization: if the first iteration will just produce 0, */ 451050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* preadjust to skip it [valid for DIVIDE only] */ 451150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*msu1<*msu2) { 451250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var2ulen--; /* shift down */ 451350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent-=DECDPUN; /* update the exponent */ 451450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 451550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 451650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 451750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* ---- start the long-division loops ------------------------------ */ 451850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=0; /* no units accumulated yet */ 451950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accdigits=0; /* .. or digits */ 452050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accnext=acc+acclength-1; /* -> msu of acc [NB: allows digits+1] */ 452150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;;) { /* outer forever loop */ 452250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho thisunit=0; /* current unit assumed 0 */ 452350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* find the next unit */ 452450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;;) { /* inner forever loop */ 452550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* strip leading zero units [from either pre-adjust or from */ 452650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subtract last time around]. Leave at least one unit. */ 452750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; *msu1==0 && msu1>var1; msu1--) var1units--; 452850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 452950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (var1units<var2ulen) break; /* var1 too low for subtract */ 453050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (var1units==var2ulen) { /* unit-by-unit compare needed */ 453150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* compare the two numbers, from msu */ 453250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *pv1, *pv2; 453350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit v2; /* units to compare */ 453450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pv2=msu2; /* -> msu */ 453550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (pv1=msu1; ; pv1--, pv2--) { 453650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* v1=*pv1 -- always OK */ 453750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho v2=0; /* assume in padding */ 453850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pv2>=var2) v2=*pv2; /* in range */ 453950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*pv1!=v2) break; /* no longer the same */ 454050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pv1==var1) break; /* done; leave pv1 as is */ 454150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 454250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here when all inspected or a difference seen */ 454350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*pv1<v2) break; /* var1 too low to subtract */ 454450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*pv1==v2) { /* var1 == var2 */ 454550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reach here if var1 and var2 are identical; subtraction */ 454650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* would increase digit by one, and the residue will be 0 so */ 454750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the calculation is done; leave the loop with residue=0. */ 454850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho thisunit++; /* as though subtracted */ 454950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *var1=0; /* set var1 to 0 */ 455050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var1units=1; /* .. */ 455150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* from inner */ 455250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* var1 == var2 */ 455350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* *pv1>v2. Prepare for real subtraction; the lengths are equal */ 455450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Estimate the multiplier (there's always a msu1-1)... */ 455550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Bring in two units of var2 to provide a good estimate. */ 455650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2pair); 455750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* lengths the same */ 455850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* var1units > var2ulen, so subtraction is safe */ 455950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The var2 msu is one unit towards the lsu of the var1 msu, */ 456050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* so only one unit for var2 can be used. */ 456150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2plus); 456250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 456350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mult==0) mult=1; /* must always be at least 1 */ 456450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subtraction needed; var1 is > var2 */ 456550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho thisunit=(Unit)(thisunit+mult); /* accumulate */ 456650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subtract var1-var2, into var1; only the overlap needs */ 456750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* processing, as this is an in-place calculation */ 456850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho shift=var2ulen-var2units; 456950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 457050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('1', &var1[shift], var1units-shift); 457150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('2', var2, var2units); 457250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("m=%ld\n", -mult); 457350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 457450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decUnitAddSub(&var1[shift], var1units-shift, 457550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var2, var2units, 0, 457650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho &var1[shift], -mult); 457750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 457850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('#', &var1[shift], var1units-shift); 457950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 458050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* var1 now probably has leading zeros; these are removed at the */ 458150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* top of the inner loop. */ 458250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* inner loop */ 458350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 458450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The next unit has been calculated in full; unless it's a */ 458550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* leading zero, add to acc */ 458650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (accunits!=0 || thisunit!=0) { /* is first or non-zero */ 458750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *accnext=thisunit; /* store in accumulator */ 458850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* account exactly for the new digits */ 458950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (accunits==0) { 459050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accdigits++; /* at least one */ 459150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (pow=&powers[1]; thisunit>=*pow; pow++) accdigits++; 459250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 459350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else accdigits+=DECDPUN; 459450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits++; /* update count */ 459550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accnext--; /* ready for next */ 459650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (accdigits>reqdigits) break; /* have enough digits */ 459750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 459850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 459950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if the residue is zero, the operation is done (unless divide */ 460050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* or divideInteger and still not enough digits yet) */ 460150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*var1==0 && var1units==1) { /* residue is 0 */ 460250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&(REMAINDER|REMNEAR)) break; 460350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((op&DIVIDE) && (exponent<=maxexponent)) break; 460450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [drop through if divideInteger] */ 460550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 460650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* also done enough if calculating remainder or integer */ 460750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* divide and just did the last ('units') unit */ 460850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exponent==0 && !(op&DIVIDE)) break; 460950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 461050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* to get here, var1 is less than var2, so divide var2 by the per- */ 461150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Unit power of ten and go for the next digit */ 461250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var2ulen--; /* shift down */ 461350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent-=DECDPUN; /* update the exponent */ 461450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* outer loop */ 461550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 461650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* ---- division is complete --------------------------------------- */ 461750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here: acc has at least reqdigits+1 of good results (or fewer */ 461850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if early stop), starting at accnext+1 (its lsu) */ 461950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* var1 has any residue at the stopping point */ 462050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accunits is the number of digits collected in acc */ 462150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (accunits==0) { /* acc is 0 */ 462250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=1; /* show have a unit .. */ 462350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accdigits=1; /* .. */ 462450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *accnext=0; /* .. whose value is 0 */ 462550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 462650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else accnext++; /* back to last placed */ 462750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accnext now -> lowest unit of result */ 462850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 462950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* assume no residue */ 463050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&DIVIDE) { 463150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* record the presence of any residue, for rounding */ 463250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*var1!=0 || var1units>1) residue=1; 463350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* no residue */ 463450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Had an exact division; clean up spurious trailing 0s. */ 463550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* There will be at most DECDPUN-1, from the final multiply, */ 463650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* and then only if the result is non-0 (and even) and the */ 463750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* exponent is 'loose'. */ 463850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>1 463950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit lsu=*accnext; 464050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!(lsu&0x01) && (lsu!=0)) { 464150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* count the trailing zeros */ 464250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int drop=0; 464350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;; drop++) { /* [will terminate because lsu!=0] */ 464450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exponent>=maxexponent) break; /* don't chop real 0s */ 464550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 464650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((lsu-QUOT10(lsu, drop+1) 464750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *powers[drop+1])!=0) break; /* found non-0 digit */ 464850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 464950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lsu%powers[drop+1]!=0) break; /* found non-0 digit */ 465050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 465150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent++; 465250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 465350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (drop>0) { 465450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=decShiftToLeast(accnext, accunits, drop); 465550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accdigits=decGetDigits(accnext, accunits); 465650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=D2U(accdigits); 465750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [exponent was adjusted in the loop] */ 465850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 465950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* neither odd nor 0 */ 466050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 466150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* exact divide */ 466250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* divide */ 466350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else /* op!=DIVIDE */ { 466450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* check for coefficient overflow */ 466550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (accdigits+exponent>reqdigits) { 466650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Division_impossible; 466750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 466850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 466950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op & (REMAINDER|REMNEAR)) { 467050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [Here, the exponent will be 0, because var1 was adjusted */ 467150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* appropriately.] */ 467250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int postshift; /* work */ 467350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag wasodd=0; /* integer was odd */ 467450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *quotlsu; /* for save */ 467550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int quotdigits; /* .. */ 467650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 467750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=lhs->bits; /* remainder sign is always as lhs */ 467850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 467950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Fastpath when residue is truly 0 is worthwhile [and */ 468050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* simplifies the code below] */ 468150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*var1==0 && var1units==1) { /* residue is 0 */ 468250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int exp=lhs->exponent; /* save min(exponents) */ 468350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->exponent<exp) exp=rhs->exponent; 468450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* 0 coefficient */ 468550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 468650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->extended) 468750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 468850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=exp; /* .. with proper exponent */ 468950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=(uByte)(bits&DECNEG); /* [cleaned] */ 469050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* might clamp */ 469150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 469250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 469350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* note if the quotient was odd */ 469450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*accnext & 0x01) wasodd=1; /* acc is odd */ 469550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quotlsu=accnext; /* save in case need to reinspect */ 469650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quotdigits=accdigits; /* .. */ 469750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 469850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* treat the residue, in var1, as the value to return, via acc */ 469950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the unused zero digits. This is the smaller of: */ 470050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* var1 initial padding (saved above) */ 470150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* var2 residual padding, which happens to be given by: */ 470250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho postshift=var1initpad+exponent-lhs->exponent+rhs->exponent; 470350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [the 'exponent' term accounts for the shifts during divide] */ 470450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (var1initpad<postshift) postshift=var1initpad; 470550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 470650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* shift var1 the requested amount, and adjust its digits */ 470750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho var1units=decShiftToLeast(var1, var1units, postshift); 470850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accnext=var1; 470950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accdigits=decGetDigits(var1, var1units); 471050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=D2U(accdigits); 471150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 471250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent=lhs->exponent; /* exponent is smaller of lhs & rhs */ 471350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->exponent<exponent) exponent=rhs->exponent; 471450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 471550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Now correct the result if doing remainderNear; if it */ 471650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (looking just at coefficients) is > rhs/2, or == rhs/2 and */ 471750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the integer was odd then the result should be rem-rhs. */ 471850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op&REMNEAR) { 471950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int compare, tarunits; /* work */ 472050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up; /* .. */ 472150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate remainder*2 into the var1 buffer (which has */ 472250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 'headroom' of an extra unit and hence enough space) */ 472350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [a dedicated 'double' loop would be faster, here] */ 472450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tarunits=decUnitAddSub(accnext, accunits, accnext, accunits, 472550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0, accnext, 1); 472650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decDumpAr('r', accnext, tarunits); */ 472750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 472850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Here, accnext (var1) holds tarunits Units with twice the */ 472950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* remainder's coefficient, which must now be compared to the */ 473050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* RHS. The remainder's exponent may be smaller than the RHS's. */ 473150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho compare=decUnitCompare(accnext, tarunits, rhs->lsu, D2U(rhs->digits), 473250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs->exponent-exponent); 473350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (compare==BADINT) { /* deep trouble */ 473450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 473550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 473650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 473750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now restore the remainder by dividing by two; the lsu */ 473850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is known to be even. */ 473950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=accnext; up<accnext+tarunits; up++) { 474050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int half; /* half to add to lower unit */ 474150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho half=*up & 0x01; 474250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up/=2; /* [shift] */ 474350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!half) continue; 474450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *(up-1)+=(DECDPUNMAX+1)/2; 474550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 474650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [accunits still describes the original remainder length] */ 474750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 474850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (compare>0 || (compare==0 && wasodd)) { /* adjustment needed */ 474950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int exp, expunits, exprem; /* work */ 475050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This is effectively causing round-up of the quotient, */ 475150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* so if it was the rare case where it was full and all */ 475250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* nines, it would overflow and hence division-impossible */ 475350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* should be raised */ 475450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag allnines=0; /* 1 if quotient all nines */ 475550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (quotdigits==reqdigits) { /* could be borderline */ 475650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=quotlsu; ; up++) { 475750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (quotdigits>DECDPUN) { 475850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=DECDPUNMAX) break;/* non-nines */ 475950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 476050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* this is the last Unit */ 476150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up==powers[quotdigits]-1) allnines=1; 476250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 476350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 476450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quotdigits-=DECDPUN; /* checked those digits */ 476550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* up */ 476650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* borderline check */ 476750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allnines) { 476850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Division_impossible; 476950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 477050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 477150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rem-rhs is needed; the sign will invert. Again, var1 */ 477250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* can safely be used for the working Units array. */ 477350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exp=rhs->exponent-exponent; /* RHS padding needed */ 477450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Calculate units and remainder from exponent. */ 477550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho expunits=exp/DECDPUN; 477650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exprem=exp%DECDPUN; 477750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subtract [A+B*(-m)]; the result will always be negative */ 477850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=-decUnitAddSub(accnext, accunits, 477950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs->lsu, D2U(rhs->digits), 478050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho expunits, accnext, -(Int)powers[exprem]); 478150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accdigits=decGetDigits(accnext, accunits); /* count digits exactly */ 478250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=D2U(accdigits); /* and recalculate the units for copy */ 478350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [exponent is as for original remainder] */ 478450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits^=DECNEG; /* flip the sign */ 478550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 478650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* REMNEAR */ 478750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* REMAINDER or REMNEAR */ 478850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* not DIVIDE */ 478950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 479050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Set exponent and bits */ 479150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=exponent; 479250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=(uByte)(bits&DECNEG); /* [cleaned] */ 479350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 479450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Now the coefficient. */ 479550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetCoeff(res, set, accnext, accdigits, &residue, status); 479650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 479750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* final cleanup */ 479850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 479950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 480050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If a divide then strip trailing zeros if subset [after round] */ 480150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended && (op==DIVIDE)) decTrim(res, set, 0, 1, &dropped); 480250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 480350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 480450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 480550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (varalloc!=NULL) free(varalloc); /* drop any storage used */ 480650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc!=NULL) free(allocacc); /* .. */ 480750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 480850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs!=NULL) free(allocrhs); /* .. */ 480950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs!=NULL) free(alloclhs); /* .. */ 481050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 481150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 481250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decDivideOp */ 481350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 481450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 481550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decMultiplyOp -- multiplication operation */ 481650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 481750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine performs the multiplication C=A x B. */ 481850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 481950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X*X) */ 482050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 482150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 482250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 482350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the usual accumulator */ 482450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 482550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 482650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 482750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 482850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 'Classic' multiplication is used rather than Karatsuba, as the */ 482950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* latter would give only a minor improvement for the short numbers */ 483050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* expected to be handled most (and uses much more memory). */ 483150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 483250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* There are two major paths here: the general-purpose ('old code') */ 483350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* path which handles all DECDPUN values, and a fastpath version */ 483450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* which is used if 64-bit ints are available, DECDPUN<=4, and more */ 483550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* than two calls to decUnitAddSub would be made. */ 483650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 483750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The fastpath version lumps units together into 8-digit or 9-digit */ 483850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* chunks, and also uses a lazy carry strategy to minimise expensive */ 483950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 64-bit divisions. The chunks are then broken apart again into */ 484050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* units for continuing processing. Despite this overhead, the */ 484150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* fastpath can speed up some 16-digit operations by 10x (and much */ 484250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* more for higher-precision calculations). */ 484350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 484450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A buffer always has to be used for the accumulator; in the */ 484550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* fastpath, buffers are also always needed for the chunked copies of */ 484650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of the operand coefficients. */ 484750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Static buffers are larger than needed just for multiply, to allow */ 484850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* for calls from other operations (notably exp). */ 484950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 485050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define FASTMUL (DECUSE64 && DECDPUN<5) 485150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decMultiplyOp(decNumber *res, const decNumber *lhs, 485250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set, 485350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 485450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int accunits; /* Units of accumulator in use */ 485550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int exponent; /* work */ 485650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* rounding residue */ 485750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte bits; /* result sign */ 485850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *acc; /* -> accumulator Unit array */ 485950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int needbytes; /* size calculator */ 486050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho void *allocacc=NULL; /* -> allocated accumulator, iff allocated */ 486150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit accbuff[SD2U(DECBUFFER*4+1)]; /* buffer (+1 for DECBUFFER==0, */ 486250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* *4 for calls from other operations) */ 486350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *mer, *mermsup; /* work */ 486450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int madlength; /* Units in multiplicand */ 486550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift; /* Units to shift multiplicand by */ 486650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 486750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if FASTMUL 486850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if DECDPUN is 1 or 3 work in base 10**9, otherwise */ 486950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (DECDPUN is 2 or 4) then work in base 10**8 */ 487050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN & 1 /* odd */ 487150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define FASTBASE 1000000000 /* base */ 487250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define FASTDIGS 9 /* digits in base */ 487350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define FASTLAZY 18 /* carry resolution point [1->18] */ 487450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 487550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define FASTBASE 100000000 487650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define FASTDIGS 8 487750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define FASTLAZY 1844 /* carry resolution point [1->1844] */ 487850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 487950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* three buffers are used, two for chunked copies of the operands */ 488050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (base 10**8 or base 10**9) and one base 2**64 accumulator with */ 488150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lazy carry evaluation */ 488250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt zlhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */ 488350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *zlhi=zlhibuff; /* -> lhs array */ 488450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *alloclhi=NULL; /* -> allocated buffer, iff allocated */ 488550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt zrhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */ 488650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *zrhi=zrhibuff; /* -> rhs array */ 488750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *allocrhi=NULL; /* -> allocated buffer, iff allocated */ 488850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uLong zaccbuff[(DECBUFFER*2+1)/4+2]; /* buffer (+1 for DECBUFFER==0) */ 488950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [allocacc is shared for both paths, as only one will run] */ 489050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uLong *zacc=zaccbuff; /* -> accumulator array for exact result */ 489150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==1 489250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int zoff; /* accumulator offset */ 489350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 489450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *lip, *rip; /* item pointers */ 489550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *lmsi, *rmsi; /* most significant items */ 489650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ilhs, irhs, iacc; /* item counts in the arrays */ 489750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int lazy; /* lazy carry counter */ 489850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uLong lcarry; /* uLong carry */ 489950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt carry; /* carry (NB not uLong) */ 490050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int count; /* work */ 490150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *cup; /* .. */ 490250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up; /* .. */ 490350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uLong *lp; /* .. */ 490450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int p; /* .. */ 490550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 490650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 490750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 490850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *alloclhs=NULL; /* -> allocated buffer, iff allocated */ 490950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* -> allocated buffer, iff allocated */ 491050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 491150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 491250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 491350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 491450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 491550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 491650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* precalculate result sign */ 491750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bits=(uByte)((lhs->bits^rhs->bits)&DECNEG); 491850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 491950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle infinities and NaNs */ 492050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS) { /* a special bit set */ 492150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */ 492250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, status); 492350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res;} 492450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* one or two infinities; Infinity * 0 is invalid */ 492550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (((lhs->bits & DECINF)==0 && ISZERO(lhs)) 492650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ||((rhs->bits & DECINF)==0 && ISZERO(rhs))) { 492750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 492850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res;} 492950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 493050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits|DECINF; /* infinity */ 493150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res;} 493250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 493350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* For best speed, as in DMSRCN [the original Rexx numerics */ 493450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* module], use the shorter number as the multiplier (rhs) and */ 493550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the longer as the multiplicand (lhs) to minimise the number of */ 493650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* adds (partial products) */ 493750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits<rhs->digits) { /* swap... */ 493850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *hold=lhs; 493950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=rhs; 494050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=hold; 494150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 494250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 494350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 494450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 494550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 494650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operands and set lostDigits status, as needed */ 494750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>set->digits) { 494850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloclhs=decRoundOperand(lhs, set, status); 494950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs==NULL) break; 495050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=alloclhs; 495150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 495250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>set->digits) { 495350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, status); 495450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 495550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 495650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 495750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 495850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 495950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 496050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 496150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if FASTMUL /* fastpath can be used */ 496250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* use the fast path if there are enough digits in the shorter */ 496350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* operand to make the setup and takedown worthwhile */ 496450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define NEEDTWO (DECDPUN*2) /* within two decUnitAddSub calls */ 496550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>NEEDTWO) { /* use fastpath... */ 496650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the number of elements in each array */ 496750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ilhs=(lhs->digits+FASTDIGS-1)/FASTDIGS; /* [ceiling] */ 496850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho irhs=(rhs->digits+FASTDIGS-1)/FASTDIGS; /* .. */ 496950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho iacc=ilhs+irhs; 497050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 497150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* allocate buffers if required, as usual */ 497250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=ilhs*sizeof(uInt); 497350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>(Int)sizeof(zlhibuff)) { 497450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloclhi=(uInt *)malloc(needbytes); 497550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho zlhi=alloclhi;} 497650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=irhs*sizeof(uInt); 497750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>(Int)sizeof(zrhibuff)) { 497850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhi=(uInt *)malloc(needbytes); 497950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho zrhi=allocrhi;} 498050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 498150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Allocating the accumulator space needs a special case when */ 498250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* DECDPUN=1 because when converting the accumulator to Units */ 498350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* after the multiplication each 8-byte item becomes 9 1-byte */ 498450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* units. Therefore iacc extra bytes are needed at the front */ 498550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (rounded up to a multiple of 8 bytes), and the uLong */ 498650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accumulator starts offset the appropriate number of units */ 498750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* to the right to avoid overwrite during the unchunking. */ 498850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=iacc*sizeof(uLong); 498950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==1 499050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho zoff=(iacc+7)/8; /* items to offset by */ 499150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes+=zoff*8; 499250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 499350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>(Int)sizeof(zaccbuff)) { 499450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocacc=(uLong *)malloc(needbytes); 499550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho zacc=(uLong *)allocacc;} 499650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (zlhi==NULL||zrhi==NULL||zacc==NULL) { 499750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 499850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 499950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 500050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=(Unit *)zacc; /* -> target Unit array */ 500150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==1 500250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho zacc+=zoff; /* start uLong accumulator to right */ 500350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 500450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 500550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* assemble the chunked copies of the left and right sides */ 500650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (count=lhs->digits, cup=lhs->lsu, lip=zlhi; count>0; lip++) 500750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (p=0, *lip=0; p<FASTDIGS && count>0; 500850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p+=DECDPUN, cup++, count-=DECDPUN) 500950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *lip+=*cup*powers[p]; 501050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lmsi=lip-1; /* save -> msi */ 501150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (count=rhs->digits, cup=rhs->lsu, rip=zrhi; count>0; rip++) 501250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (p=0, *rip=0; p<FASTDIGS && count>0; 501350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p+=DECDPUN, cup++, count-=DECDPUN) 501450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *rip+=*cup*powers[p]; 501550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rmsi=rip-1; /* save -> msi */ 501650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 501750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* zero the accumulator */ 501850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (lp=zacc; lp<zacc+iacc; lp++) *lp=0; 501950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 502050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Start the multiplication */ 502150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Resolving carries can dominate the cost of accumulating the */ 502250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* partial products, so this is only done when necessary. */ 502350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Each uLong item in the accumulator can hold values up to */ 502450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 2**64-1, and each partial product can be as large as */ 502550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (10**FASTDIGS-1)**2. When FASTDIGS=9, this can be added to */ 502650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* itself 18.4 times in a uLong without overflowing, so during */ 502750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the main calculation resolution is carried out every 18th */ 502850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* add -- every 162 digits. Similarly, when FASTDIGS=8, the */ 502950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* partial products can be added to themselves 1844.6 times in */ 503050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a uLong without overflowing, so intermediate carry */ 503150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* resolution occurs only every 14752 digits. Hence for common */ 503250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* short numbers usually only the one final carry resolution */ 503350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* occurs. */ 503450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (The count is set via FASTLAZY to simplify experiments to */ 503550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* measure the value of this approach: a 35% improvement on a */ 503650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [34x34] multiply.) */ 503750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lazy=FASTLAZY; /* carry delay count */ 503850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (rip=zrhi; rip<=rmsi; rip++) { /* over each item in rhs */ 503950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lp=zacc+(rip-zrhi); /* where to add the lhs */ 504050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (lip=zlhi; lip<=lmsi; lip++, lp++) { /* over each item in lhs */ 504150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *lp+=(uLong)(*lip)*(*rip); /* [this should in-line] */ 504250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* lip loop */ 504350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lazy--; 504450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lazy>0 && rip!=rmsi) continue; 504550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lazy=FASTLAZY; /* reset delay count */ 504650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* spin up the accumulator resolving overflows */ 504750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (lp=zacc; lp<zacc+iacc; lp++) { 504850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*lp<FASTBASE) continue; /* it fits */ 504950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lcarry=*lp/FASTBASE; /* top part [slow divide] */ 505050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lcarry can exceed 2**32-1, so check again; this check */ 505150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* and occasional extra divide (slow) is well worth it, as */ 505250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it allows FASTLAZY to be increased to 18 rather than 4 */ 505350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* in the FASTDIGS=9 case */ 505450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lcarry<FASTBASE) carry=(uInt)lcarry; /* [usual] */ 505550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* two-place carry [fairly rare] */ 505650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt carry2=(uInt)(lcarry/FASTBASE); /* top top part */ 505750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *(lp+2)+=carry2; /* add to item+2 */ 505850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *lp-=((uLong)FASTBASE*FASTBASE*carry2); /* [slow] */ 505950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=(uInt)(lcarry-((uLong)FASTBASE*carry2)); /* [inline] */ 506050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 506150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *(lp+1)+=carry; /* add to item above [inline] */ 506250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *lp-=((uLong)FASTBASE*carry); /* [inline] */ 506350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* carry resolution */ 506450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* rip loop */ 506550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 506650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The multiplication is complete; time to convert back into */ 506750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* units. This can be done in-place in the accumulator and in */ 506850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 32-bit operations, because carries were resolved after the */ 506950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* final add. This needs N-1 divides and multiplies for */ 507050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* each item in the accumulator (which will become up to N */ 507150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* units, where 2<=N<=9). */ 507250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (lp=zacc, up=acc; lp<zacc+iacc; lp++) { 507350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt item=(uInt)*lp; /* decapitate to uInt */ 507450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (p=0; p<FASTDIGS-DECDPUN; p+=DECDPUN, up++) { 507550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt part=item/(DECDPUNMAX+1); 507650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)(item-(part*(DECDPUNMAX+1))); 507750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho item=part; 507850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* p */ 507950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)item; up++; /* [final needs no division] */ 508050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* lp */ 508150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=up-acc; /* count of units */ 508250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 508350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* here to use units directly, without chunking ['old code'] */ 508450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 508550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 508650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if accumulator will be too long for local storage, then allocate */ 508750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=accbuff; /* -> assume buffer for accumulator */ 508850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=(D2U(lhs->digits)+D2U(rhs->digits))*sizeof(Unit); 508950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>(Int)sizeof(accbuff)) { 509050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocacc=(Unit *)malloc(needbytes); 509150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc==NULL) {*status|=DEC_Insufficient_storage; break;} 509250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=(Unit *)allocacc; /* use the allocated space */ 509350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 509450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 509550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Now the main long multiplication loop */ 509650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Unlike the equivalent in the IBM Java implementation, there */ 509750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is no advantage in calculating from msu to lsu. So, do it */ 509850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* by the book, as it were. */ 509950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Each iteration calculates ACC=ACC+MULTAND*MULT */ 510050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=1; /* accumulator starts at '0' */ 510150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *acc=0; /* .. (lsu=0) */ 510250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho shift=0; /* no multiplicand shift at first */ 510350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho madlength=D2U(lhs->digits); /* this won't change */ 510450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mermsup=rhs->lsu+D2U(rhs->digits); /* -> msu+1 of multiplier */ 510550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 510650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (mer=rhs->lsu; mer<mermsup; mer++) { 510750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Here, *mer is the next Unit in the multiplier to use */ 510850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If non-zero [optimization] add it... */ 510950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*mer!=0) accunits=decUnitAddSub(&acc[shift], accunits-shift, 511050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs->lsu, madlength, 0, 511150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho &acc[shift], *mer) 511250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho + shift; 511350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* extend acc with a 0; it will be used shortly */ 511450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *(acc+accunits)=0; /* [this avoids length of <=0 later] */ 511550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits++; 511650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 511750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* multiply multiplicand by 10**DECDPUN for next Unit to left */ 511850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho shift++; /* add this for 'logical length' */ 511950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* n */ 512050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if FASTMUL 512150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* unchunked units */ 512250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 512350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* common end-path */ 512450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 512550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('*', acc, accunits); /* Show exact result */ 512650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 512750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 512850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* acc now contains the exact result of the multiplication, */ 512950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* possibly with a leading zero unit; build the decNumber from */ 513050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it, noting if any residue */ 513150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=bits; /* set sign */ 513250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decGetDigits(acc, accunits); /* count digits exactly */ 513350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 513450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* There can be a 31-bit wrap in calculating the exponent. */ 513550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This can only happen if both input exponents are negative and */ 513650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* both their magnitudes are large. If there was a wrap, set a */ 513750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* safe very negative exponent, from which decFinalize() will */ 513850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* raise a hard underflow shortly. */ 513950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent=lhs->exponent+rhs->exponent; /* calculate exponent */ 514050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent<0 && rhs->exponent<0 && exponent>0) 514150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exponent=-2*DECNUMMAXE; /* force underflow */ 514250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=exponent; /* OK to overwrite now */ 514350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 514450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 514550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Set the coefficient. If any rounding, residue records */ 514650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetCoeff(res, set, acc, res->digits, &residue, status); 514750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* final cleanup */ 514850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 514950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 515050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc!=NULL) free(allocacc); /* drop any storage used */ 515150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 515250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs!=NULL) free(allocrhs); /* .. */ 515350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs!=NULL) free(alloclhs); /* .. */ 515450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 515550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if FASTMUL 515650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhi!=NULL) free(allocrhi); /* .. */ 515750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhi!=NULL) free(alloclhi); /* .. */ 515850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 515950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 516050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decMultiplyOp */ 516150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 516250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 516350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decExpOp -- effect exponentiation */ 516450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 516550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = exp(A) */ 516650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 516750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 516850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 516950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context; note that rounding mode has no effect */ 517050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 517150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. status is updated but */ 517250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* not set. */ 517350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 517450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Restrictions: */ 517550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 517650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* digits, emax, and -emin in the context must be less than */ 517750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 2*DEC_MAX_MATH (1999998), and the rhs must be within these */ 517850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* bounds or a zero. This is an internal routine, so these */ 517950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* restrictions are contractual and not enforced. */ 518050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 518150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */ 518250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* almost always be correctly rounded, but may be up to 1 ulp in */ 518350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* error in rare cases. */ 518450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 518550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Finite results will always be full precision and Inexact, except */ 518650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* when A is a zero or -Infinity (giving 1 or 0 respectively). */ 518750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 518850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This approach used here is similar to the algorithm described in */ 518950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 519050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Variable Precision Exponential Function, T. E. Hull and */ 519150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A. Abrham, ACM Transactions on Mathematical Software, Vol 12 #2, */ 519250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* pp79-91, ACM, June 1986. */ 519350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 519450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* with the main difference being that the iterations in the series */ 519550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* evaluation are terminated dynamically (which does not require the */ 519650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* extra variable-precision variables which are expensive in this */ 519750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* context). */ 519850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 519950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The error analysis in Hull & Abrham's paper applies except for the */ 520050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* round-off error accumulation during the series evaluation. This */ 520150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* code does not precalculate the number of iterations and so cannot */ 520250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* use Horner's scheme. Instead, the accumulation is done at double- */ 520350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* precision, which ensures that the additions of the terms are exact */ 520450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and do not accumulate round-off (and any round-off errors in the */ 520550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* terms themselves move 'to the right' faster than they can */ 520650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* accumulate). This code also extends the calculation by allowing, */ 520750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* in the spirit of other decNumber operators, the input to be more */ 520850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* precise than the result (the precision used is based on the more */ 520950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* precise of the input or requested result). */ 521050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 521150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Implementation notes: */ 521250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 521350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 1. This is separated out as decExpOp so it can be called from */ 521450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* other Mathematical functions (notably Ln) with a wider range */ 521550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* than normal. In particular, it can handle the slightly wider */ 521650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (double) range needed by Ln (which has to be able to calculate */ 521750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* exp(-x) where x can be the tiniest number (Ntiny). */ 521850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 521950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 2. Normalizing x to be <=0.1 (instead of <=1) reduces loop */ 522050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* iterations by appoximately a third with additional (although */ 522150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* diminishing) returns as the range is reduced to even smaller */ 522250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* fractions. However, h (the power of 10 used to correct the */ 522350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* result at the end, see below) must be kept <=8 as otherwise */ 522450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the final result cannot be computed. Hence the leverage is a */ 522550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* sliding value (8-h), where potentially the range is reduced */ 522650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* more for smaller values. */ 522750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 522850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The leverage that can be applied in this way is severely */ 522950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* limited by the cost of the raise-to-the power at the end, */ 523050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* which dominates when the number of iterations is small (less */ 523150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* than ten) or when rhs is short. As an example, the adjustment */ 523250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* x**10,000,000 needs 31 multiplications, all but one full-width. */ 523350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 523450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 3. The restrictions (especially precision) could be raised with */ 523550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* care, but the full decNumber range seems very hard within the */ 523650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 32-bit limits. */ 523750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 523850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 4. The working precisions for the static buffers are twice the */ 523950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* obvious size to allow for calls from decNumberPower. */ 524050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 524150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehodecNumber * decExpOp(decNumber *res, const decNumber *rhs, 524250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set, uInt *status) { 524350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt ignore=0; /* working status */ 524450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int h; /* adjusted exponent for 0.xxxx */ 524550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int p; /* working precision */ 524650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue; /* rounding residue */ 524750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt needbytes; /* for space calculations */ 524850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *x=rhs; /* (may point to safe copy later) */ 524950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext aset, tset, dset; /* working contexts */ 525050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int comp; /* work */ 525150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 525250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the argument is often copied to normalize it, so (unusually) it */ 525350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is treated like other buffers, using DECBUFFER, +1 in case */ 525450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* DECBUFFER is 0 */ 525550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufr[D2N(DECBUFFER*2+1)]; 525650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* non-NULL if rhs buffer allocated */ 525750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 525850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the working precision will be no more than set->digits+8+1 */ 525950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* so for on-stack buffers DECBUFFER+9 is used, +1 in case DECBUFFER */ 526050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is 0 (and twice that for the accumulator) */ 526150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 526250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffer for t, term (working precision plus) */ 526350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber buft[D2N(DECBUFFER*2+9+1)]; 526450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbuft=NULL; /* -> allocated buft, iff allocated */ 526550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *t=buft; /* term */ 526650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffer for a, accumulator (working precision * 2), at least 9 */ 526750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufa[D2N(DECBUFFER*4+18+1)]; 526850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ 526950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *a=bufa; /* accumulator */ 527050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decNumber for the divisor term; this needs at most 9 digits */ 527150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* and so can be fixed size [16 so can use standard context] */ 527250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufd[D2N(16)]; 527350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *d=bufd; /* divisor */ 527450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber numone; /* constant 1 */ 527550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 527650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 527750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int iterations=0; /* for later sanity check */ 527850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 527950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 528050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 528150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 528250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARG) { /* handle infinities and NaNs */ 528350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs)) { /* an infinity */ 528450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) /* -Infinity -> +0 */ 528550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 528650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else uprv_decNumberCopy(res, rhs); /* +Infinity -> self */ 528750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 528850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else decNaNs(res, rhs, NULL, set, status); /* a NaN */ 528950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 529050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 529150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) { /* zeros -> exact 1 */ 529250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* make clean 1 */ 529350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=1; /* .. */ 529450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* [no status to set] */ 529550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 529650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* e**x when 0 < x < 0.66 is < 1+3x/2, hence can fast-path */ 529750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* positive and negative tiny cases which will result in inexact */ 529850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1. This also allows the later add-accumulate to always be */ 529950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* exact (because its length will never be more than twice the */ 530050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* working precision). */ 530150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The comparator (tiny) needs just one digit, so use the */ 530250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decNumber d for it (reused as the divisor, etc., below); its */ 530350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* exponent is such that if x is positive it will have */ 530450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set->digits-1 zeros between the decimal point and the digit, */ 530550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* which is 4, and if x is negative one more zero there as the */ 530650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* more precise result will be of the form 0.9999999 rather than */ 530750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 1.0000001. Hence, tiny will be 0.0000004 if digits=7 and x>0 */ 530850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* or 0.00000004 if digits=7 and x<0. If RHS not larger than */ 530950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this then the result will be 1.000000 */ 531050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(d); /* clean */ 531150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *d->lsu=4; /* set 4 .. */ 531250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho d->exponent=-set->digits; /* * 10**(-d) */ 531350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) d->exponent--; /* negative case */ 531450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho comp=decCompare(d, rhs, 1); /* signless compare */ 531550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (comp==BADINT) { 531650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 531750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 531850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (comp>=0) { /* rhs < d */ 531950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift=set->digits-1; 532050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* set 1 */ 532150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=1; /* .. */ 532250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, 1, shift); 532350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=-shift; /* make 1.0000... */ 532450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Inexact | DEC_Rounded; /* .. inexactly */ 532550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* tiny */ 532650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 532750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set up the context to be used for calculating a, as this is */ 532850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* used on both paths below */ 532950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&aset, DEC_INIT_DECIMAL64); 533050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accumulator bounds are as requested (could underflow) */ 533150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emax=set->emax; /* usual bounds */ 533250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emin=set->emin; /* .. */ 533350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.clamp=0; /* and no concrete format */ 533450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 533550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the adjusted (Hull & Abrham) exponent (where the */ 533650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decimal point is just to the left of the coefficient msd) */ 533750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho h=rhs->exponent+rhs->digits; 533850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if h>8 then 10**h cannot be calculated safely; however, when */ 533950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* h=8 then exp(|rhs|) will be at least exp(1E+7) which is at */ 534050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* least 6.59E+4342944, so (due to the restriction on Emax/Emin) */ 534150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* overflow (or underflow to 0) is guaranteed -- so this case can */ 534250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* be handled by simply forcing the appropriate excess */ 534350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (h>8) { /* overflow/underflow */ 534450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set up here so Power call below will over or underflow to */ 534550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* zero; set accumulator to either 2 or 0.02 */ 534650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [stack buffer for a is always big enough for this] */ 534750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(a); 534850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *a->lsu=2; /* not 1 but < exp(1) */ 534950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) a->exponent=-2; /* make 0.02 */ 535050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho h=8; /* clamp so 10**h computable */ 535150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p=9; /* set a working precision */ 535250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 535350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* h<=8 */ 535450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxlever=(rhs->digits>8?1:0); 535550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [could/should increase this for precisions >40 or so, too] */ 535650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 535750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if h is 8, cannot normalize to a lower upper limit because */ 535850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the final result will not be computable (see notes above), */ 535950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* but leverage can be applied whenever h is less than 8. */ 536050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Apply as much as possible, up to a MAXLEVER digits, which */ 536150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* sets the tradeoff against the cost of the later a**(10**h). */ 536250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* As h is increased, the working precision below also */ 536350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* increases to compensate for the "constant digits at the */ 536450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* front" effect. */ 536550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int lever=MINI(8-h, maxlever); /* leverage attainable */ 536650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int use=-rhs->digits-lever; /* exponent to use for RHS */ 536750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho h+=lever; /* apply leverage selected */ 536850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (h<0) { /* clamp */ 536950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho use+=h; /* [may end up subnormal] */ 537050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho h=0; 537150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 537250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Take a copy of RHS if it needs normalization (true whenever x>=1) */ 537350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->exponent!=use) { 537450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *newrhs=bufr; /* assume will fit on stack */ 537550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit); 537650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufr)) { /* need malloc space */ 537750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=(decNumber *)malloc(needbytes); 537850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) { /* hopeless -- abandon */ 537950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 538050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 538150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho newrhs=allocrhs; /* use the allocated space */ 538250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 538350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(newrhs, rhs); /* copy to safe space */ 538450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho newrhs->exponent=use; /* normalize; now <1 */ 538550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho x=newrhs; /* ready for use */ 538650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decNumberShow(x); */ 538750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 538850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 538950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Now use the usual power series to evaluate exp(x). The */ 539050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* series starts as 1 + x + x^2/2 ... so prime ready for the */ 539150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* third term by setting the term variable t=x, the accumulator */ 539250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a=1, and the divisor d=2. */ 539350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 539450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* First determine the working precision. From Hull & Abrham */ 539550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this is set->digits+h+2. However, if x is 'over-precise' we */ 539650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* need to allow for all its digits to potentially participate */ 539750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (consider an x where all the excess digits are 9s) so in */ 539850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this case use x->digits+h+2 */ 539950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p=MAXI(x->digits, set->digits)+h+2; /* [h<=8] */ 540050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 540150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a and t are variable precision, and depend on p, so space */ 540250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* must be allocated for them if necessary */ 540350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 540450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the accumulator needs to be able to hold 2p digits so that */ 540550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the additions on the second and subsequent iterations are */ 540650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* sufficiently exact. */ 540750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(p*2)-1)*sizeof(Unit); 540850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufa)) { /* need malloc space */ 540950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufa=(decNumber *)malloc(needbytes); 541050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa==NULL) { /* hopeless -- abandon */ 541150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 541250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 541350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=allocbufa; /* use the allocated space */ 541450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 541550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the term needs to be able to hold p digits (which is */ 541650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* guaranteed to be larger than x->digits, so the initial copy */ 541750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is safe); it may also be used for the raise-to-power */ 541850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculation below, which needs an extra two digits */ 541950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(p+2)-1)*sizeof(Unit); 542050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(buft)) { /* need malloc space */ 542150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbuft=(decNumber *)malloc(needbytes); 542250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbuft==NULL) { /* hopeless -- abandon */ 542350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 542450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 542550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t=allocbuft; /* use the allocated space */ 542650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 542750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 542850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(t, x); /* term=x */ 542950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(a); *a->lsu=1; /* accumulator=1 */ 543050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(d); *d->lsu=2; /* divisor=2 */ 543150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&numone); *numone.lsu=1; /* constant 1 for increment */ 543250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 543350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set up the contexts for calculating a, t, and d */ 543450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&tset, DEC_INIT_DECIMAL64); 543550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dset=tset; 543650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accumulator bounds are set above, set precision now */ 543750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=p*2; /* double */ 543850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* term bounds avoid any underflow or overflow */ 543950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tset.digits=p; 544050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tset.emin=DEC_MIN_EMIN; /* [emax is plenty] */ 544150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [dset.digits=16, etc., are sufficient] */ 544250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 544350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* finally ready to roll */ 544450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;;) { 544550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 544650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho iterations++; 544750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 544850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* only the status from the accumulation is interesting */ 544950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [but it should remain unchanged after first add] */ 545050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, a, t, &aset, 0, status); /* a=a+t */ 545150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(t, t, x, &tset, &ignore); /* t=t*x */ 545250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDivideOp(t, t, d, &tset, DIVIDE, &ignore); /* t=t/d */ 545350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the iteration ends when the term cannot affect the result, */ 545450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if rounded to p digits, which is when its value is smaller */ 545550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* than the accumulator by p+1 digits. There must also be */ 545650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* full precision in a. */ 545750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (((a->digits+a->exponent)>=(t->digits+t->exponent+p+1)) 545850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && (a->digits>=p)) break; 545950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(d, d, &numone, &dset, 0, &ignore); /* d=d+1 */ 546050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* iterate */ 546150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 546250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 546350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* just a sanity check; comment out test to show always */ 546450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (iterations>p+3) 546550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Exp iterations=%ld, status=%08lx, p=%ld, d=%ld\n", 546650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (LI)iterations, (LI)*status, (LI)p, (LI)x->digits); 546750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 546850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* h<=8 */ 546950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 547050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* apply postconditioning: a=a**(10**h) -- this is calculated */ 547150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* at a slightly higher precision than Hull & Abrham suggest */ 547250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (h>0) { 547350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int seenbit=0; /* set once a 1-bit is seen */ 547450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i; /* counter */ 547550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int n=powers[h]; /* always positive */ 547650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=p+2; /* sufficient precision */ 547750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* avoid the overhead and many extra digits of decNumberPower */ 547850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* as all that is needed is the short 'multipliers' loop; here */ 547950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accumulate the answer into t */ 548050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(t); *t->lsu=1; /* acc=1 */ 548150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i=1;;i++){ /* for each bit [top bit ignored] */ 548250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* abandon if have had overflow or terminal underflow */ 548350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */ 548450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*status&DEC_Overflow || ISZERO(t)) break;} 548550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho n=n<<1; /* move next bit to testable position */ 548650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (n<0) { /* top bit is set */ 548750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho seenbit=1; /* OK, have a significant bit */ 548850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(t, t, a, &aset, status); /* acc=acc*x */ 548950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 549050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (i==31) break; /* that was the last bit */ 549150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!seenbit) continue; /* no need to square 1 */ 549250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(t, t, t, &aset, status); /* acc=acc*acc [square] */ 549350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /*i*/ /* 32 bits */ 549450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* decNumberShow(t); */ 549550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=t; /* and carry on using t instead of a */ 549650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 549750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 549850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Copy and round the result to res */ 549950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=1; /* indicate dirt to right .. */ 550050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(a)) residue=0; /* .. unless underflowed to 0 */ 550150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=set->digits; /* [use default rounding] */ 550250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */ 550350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* cleanup/set flags */ 550450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 550550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 550650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs !=NULL) free(allocrhs); /* drop any storage used */ 550750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa!=NULL) free(allocbufa); /* .. */ 550850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbuft!=NULL) free(allocbuft); /* .. */ 550950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [status is handled by caller] */ 551050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 551150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decExpOp */ 551250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 551350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 551450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Initial-estimate natural logarithm table */ 551550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 551650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* LNnn -- 90-entry 16-bit table for values from .10 through .99. */ 551750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The result is a 4-digit encode of the coefficient (c=the */ 551850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* top 14 bits encoding 0-9999) and a 2-digit encode of the */ 551950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* exponent (e=the bottom 2 bits encoding 0-3) */ 552050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 552150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The resulting value is given by: */ 552250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 552350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* v = -c * 10**(-e-3) */ 552450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 552550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* where e and c are extracted from entry k = LNnn[x-10] */ 552650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* where x is truncated (NB) into the range 10 through 99, */ 552750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and then c = k>>2 and e = k&3. */ 552850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 552950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst uShort LNnn[90]={9016, 8652, 8316, 8008, 7724, 7456, 7208, 553050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 6972, 6748, 6540, 6340, 6148, 5968, 5792, 5628, 5464, 5312, 553150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 5164, 5020, 4884, 4748, 4620, 4496, 4376, 4256, 4144, 4032, 553250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 39233, 38181, 37157, 36157, 35181, 34229, 33297, 32389, 31501, 30629, 553350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 29777, 28945, 28129, 27329, 26545, 25777, 25021, 24281, 23553, 22837, 553450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 22137, 21445, 20769, 20101, 19445, 18801, 18165, 17541, 16925, 16321, 553550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 15721, 15133, 14553, 13985, 13421, 12865, 12317, 11777, 11241, 10717, 553650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 10197, 9685, 9177, 8677, 8185, 7697, 7213, 6737, 6269, 5801, 553750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 5341, 4889, 4437, 39930, 35534, 31186, 26886, 22630, 18418, 14254, 553850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 10130, 6046, 20055}; 553950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 554050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 554150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decLnOp -- effect natural logarithm */ 554250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 554350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = ln(A) */ 554450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 554550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A */ 554650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is A */ 554750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context; note that rounding mode has no effect */ 554850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 554950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 555050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 555150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Notable cases: */ 555250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A<0 -> Invalid */ 555350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=0 -> -Infinity (Exact) */ 555450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=+Infinity -> +Infinity (Exact) */ 555550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A=1 exactly -> 0 (Exact) */ 555650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 555750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Restrictions (as for Exp): */ 555850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 555950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* digits, emax, and -emin in the context must be less than */ 556050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* DEC_MAX_MATH+11 (1000010), and the rhs must be within these */ 556150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* bounds or a zero. This is an internal routine, so these */ 556250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* restrictions are contractual and not enforced. */ 556350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 556450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */ 556550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* almost always be correctly rounded, but may be up to 1 ulp in */ 556650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* error in rare cases. */ 556750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 556850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The result is calculated using Newton's method, with each */ 556950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* iteration calculating a' = a + x * exp(-a) - 1. See, for example, */ 557050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Epperson 1989. */ 557150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 557250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The iteration ends when the adjustment x*exp(-a)-1 is tiny enough. */ 557350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This has to be calculated at the sum of the precision of x and the */ 557450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* working precision. */ 557550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 557650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Implementation notes: */ 557750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 557850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 1. This is separated out as decLnOp so it can be called from */ 557950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* other Mathematical functions (e.g., Log 10) with a wider range */ 558050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* than normal. In particular, it can handle the slightly wider */ 558150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (+9+2) range needed by a power function. */ 558250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 558350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 2. The speed of this function is about 10x slower than exp, as */ 558450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* it typically needs 4-6 iterations for short numbers, and the */ 558550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* extra precision needed adds a squaring effect, twice. */ 558650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 558750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 3. Fastpaths are included for ln(10) and ln(2), up to length 40, */ 558850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* as these are common requests. ln(10) is used by log10(x). */ 558950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 559050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 4. An iteration might be saved by widening the LNnn table, and */ 559150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* would certainly save at least one if it were made ten times */ 559250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* bigger, too (for truncated fractions 0.100 through 0.999). */ 559350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* However, for most practical evaluations, at least four or five */ 559450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* iterations will be neede -- so this would only speed up by */ 559550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 20-25% and that probably does not justify increasing the table */ 559650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* size. */ 559750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 559850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 5. The static buffers are larger than might be expected to allow */ 559950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* for calls from decNumberPower. */ 560050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 560102c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) 560202c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic push 560302c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic ignored "-Warray-bounds" 560402c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#endif 560550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehodecNumber * decLnOp(decNumber *res, const decNumber *rhs, 560650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set, uInt *status) { 560750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt ignore=0; /* working status accumulator */ 560850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt needbytes; /* for space calculations */ 560950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue; /* rounding residue */ 561050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int r; /* rhs=f*10**r [see below] */ 561150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int p; /* working precision */ 561250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int pp; /* precision for iteration */ 561350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int t; /* work */ 561450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 561550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* buffers for a (accumulator, typically precision+2) and b */ 561650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (adjustment calculator, same size) */ 561750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufa[D2N(DECBUFFER+12)]; 561850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ 561950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *a=bufa; /* accumulator/work */ 562050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber bufb[D2N(DECBUFFER*2+2)]; 562150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocbufb=NULL; /* -> allocated bufa, iff allocated */ 562250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *b=bufb; /* adjustment/work */ 562350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 562450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber numone; /* constant 1 */ 562550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber cmp; /* work */ 562650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext aset, bset; /* working contexts */ 562750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 562850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 562950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int iterations=0; /* for later sanity check */ 563050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; 563150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 563250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 563350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 563450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARG) { /* handle infinities and NaNs */ 563550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs)) { /* an infinity */ 563650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) /* -Infinity -> error */ 563750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 563850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else uprv_decNumberCopy(res, rhs); /* +Infinity -> self */ 563950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 564050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else decNaNs(res, rhs, NULL, set, status); /* a NaN */ 564150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 564250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 564350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) { /* +/- zeros -> -Infinity */ 564450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* make clean */ 564550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=DECINF|DECNEG; /* set - infinity */ 564650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* [no status to set] */ 564750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 564850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Non-zero negatives are bad... */ 564950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(rhs)) { /* -x -> error */ 565050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 565150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 565250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 565350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Here, rhs is positive, finite, and in range */ 565450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 565550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lookaside fastpath code for ln(2) and ln(10) at common lengths */ 565650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->exponent==0 && set->digits<=40) { 565750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==1 565850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->lsu[0]==0 && rhs->lsu[1]==1 && rhs->digits==2) { /* ln(10) */ 565950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 566050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->lsu[0]==10 && rhs->digits==2) { /* ln(10) */ 566150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 566250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset=*set; aset.round=DEC_ROUND_HALF_EVEN; 566350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define LN10 "2.302585092994045684017991454684364207601" 566450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromString(res, LN10, &aset); 566550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=(DEC_Inexact | DEC_Rounded); /* is inexact */ 566650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 566750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->lsu[0]==2 && rhs->digits==1) { /* ln(2) */ 566850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset=*set; aset.round=DEC_ROUND_HALF_EVEN; 566950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #define LN2 "0.6931471805599453094172321214581765680755" 567050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromString(res, LN2, &aset); 567150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=(DEC_Inexact | DEC_Rounded); 567250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 567350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* integer and short */ 567450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 567550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Determine the working precision. This is normally the */ 567650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* requested precision + 2, with a minimum of 9. However, if */ 567750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the rhs is 'over-precise' then allow for all its digits to */ 567850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* potentially participate (consider an rhs where all the excess */ 567950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* digits are 9s) so in this case use rhs->digits+2. */ 568050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p=MAXI(rhs->digits, MAXI(set->digits, 7))+2; 568150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 568250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Allocate space for the accumulator and the high-precision */ 568350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* adjustment calculator, if necessary. The accumulator must */ 568450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* be able to hold p digits, and the adjustment up to */ 568550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* rhs->digits+p digits. They are also made big enough for 16 */ 568650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* digits so that they can be used for calculating the initial */ 568750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* estimate. */ 568850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(MAXI(p,16))-1)*sizeof(Unit); 568950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufa)) { /* need malloc space */ 569050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufa=(decNumber *)malloc(needbytes); 569150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa==NULL) { /* hopeless -- abandon */ 569250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 569350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 569450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a=allocbufa; /* use the allocated space */ 569550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 569650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pp=p+rhs->digits; 569750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needbytes=sizeof(decNumber)+(D2U(MAXI(pp,16))-1)*sizeof(Unit); 569850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needbytes>sizeof(bufb)) { /* need malloc space */ 569950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocbufb=(decNumber *)malloc(needbytes); 570050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufb==NULL) { /* hopeless -- abandon */ 570150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 570250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 570350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b=allocbufb; /* use the allocated space */ 570450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 570550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 570650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Prepare an initial estimate in acc. Calculate this by */ 570750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* considering the coefficient of x to be a normalized fraction, */ 570850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* f, with the decimal point at far left and multiplied by */ 570950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 10**r. Then, rhs=f*10**r and 0.1<=f<1, and */ 571050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* ln(x) = ln(f) + ln(10)*r */ 571150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Get the initial estimate for ln(f) from a small lookup */ 571250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* table (see above) indexed by the first two digits of f, */ 571350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* truncated. */ 571450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 571550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextDefault(&aset, DEC_INIT_DECIMAL64); /* 16-digit extended */ 571650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho r=rhs->exponent+rhs->digits; /* 'normalised' exponent */ 571750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromInt32(a, r); /* a=r */ 571850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromInt32(b, 2302585); /* b=ln(10) (2.302585) */ 571950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b->exponent=-6; /* .. */ 572050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(a, a, b, &aset, &ignore); /* a=a*b */ 572150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now get top two digits of rhs into b by simple truncate and */ 572250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* force to integer */ 572350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* (no residue) */ 572450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=2; aset.round=DEC_ROUND_DOWN; 572550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(b, rhs, &aset, &residue, &ignore); /* copy & shorten */ 572650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b->exponent=0; /* make integer */ 572750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t=decGetInt(b); /* [cannot fail] */ 572850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (t<10) t=X10(t); /* adjust single-digit b */ 572950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t=LNnn[t-10]; /* look up ln(b) */ 573050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberFromInt32(b, t>>2); /* b=ln(b) coefficient */ 573150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b->exponent=-(t&3)-3; /* set exponent */ 573250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b->bits=DECNEG; /* ln(0.10)->ln(0.99) always -ve */ 573350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=16; aset.round=DEC_ROUND_HALF_EVEN; /* restore */ 573450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, a, b, &aset, 0, &ignore); /* acc=a+b */ 573550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the initial estimate is now in a, with up to 4 digits correct. */ 573650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* When rhs is at or near Nmax the estimate will be low, so we */ 573750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* will approach it from below, avoiding overflow when calling exp. */ 573850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 573950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&numone); *numone.lsu=1; /* constant 1 for adjustment */ 574050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 574150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accumulator bounds are as requested (could underflow, but */ 574250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* cannot overflow) */ 574350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emax=set->emax; 574450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.emin=set->emin; 574550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.clamp=0; /* no concrete format */ 574650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set up a context to be used for the multiply and subtract */ 574750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bset=aset; 574850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bset.emax=DEC_MAX_MATH*2; /* use double bounds for the */ 574950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bset.emin=-DEC_MAX_MATH*2; /* adjustment calculation */ 575050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [see decExpOp call below] */ 575150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* for each iteration double the number of digits to calculate, */ 575250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* up to a maximum of p */ 575350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pp=9; /* initial precision */ 575450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [initially 9 as then the sequence starts 7+2, 16+2, and */ 575550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 34+2, which is ideal for standard-sized numbers] */ 575650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=pp; /* working context */ 575750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bset.digits=pp+rhs->digits; /* wider context */ 575850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;;) { /* iterate */ 575950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 576050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho iterations++; 576150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (iterations>24) break; /* consider 9 * 2**24 */ 576250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 576350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* calculate the adjustment (exp(-a)*x-1) into b. This is a */ 576450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* catastrophic subtraction but it really is the difference */ 576550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* from 1 that is of interest. */ 576650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Use the internal entry point to Exp as it allows the double */ 576750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* range for calculating exp(-a) when a is the tiniest subnormal. */ 576850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->bits^=DECNEG; /* make -a */ 576950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decExpOp(b, a, &bset, &ignore); /* b=exp(-a) */ 577050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a->bits^=DECNEG; /* restore sign of a */ 577150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now multiply by rhs and subtract 1, at the wider precision */ 577250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decMultiplyOp(b, b, rhs, &bset, &ignore); /* b=b*rhs */ 577350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(b, b, &numone, &bset, DECNEG, &ignore); /* b=b-1 */ 577450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 577550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the iteration ends when the adjustment cannot affect the */ 577650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* result by >=0.5 ulp (at the requested digits), which */ 577750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* is when its value is smaller than the accumulator by */ 577850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set->digits+1 digits (or it is zero) -- this is a looser */ 577950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* requirement than for Exp because all that happens to the */ 578050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* accumulator after this is the final rounding (but note that */ 578150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* there must also be full precision in a, or a=0). */ 578250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 578350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(b) || 578450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (a->digits+a->exponent)>=(b->digits+b->exponent+set->digits+1)) { 578550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a->digits==p) break; 578650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(a)) { 578750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCompareOp(&cmp, rhs, &numone, &aset, COMPARE, &ignore); /* rhs=1 ? */ 578850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cmp.lsu[0]==0) a->exponent=0; /* yes, exact 0 */ 578950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else *status|=(DEC_Inexact | DEC_Rounded); /* no, inexact */ 579050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 579150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 579250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* force padding if adjustment has gone to 0 before full length */ 579350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsZero(b)) b->exponent=a->exponent-p; 579450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 579550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 579650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* not done yet ... */ 579750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAddOp(a, a, b, &aset, 0, &ignore); /* a=a+b for next estimate */ 579850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pp==p) continue; /* precision is at maximum */ 579950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* lengthen the next calculation */ 580050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pp=pp*2; /* double precision */ 580150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (pp>p) pp=p; /* clamp to maximum */ 580250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=pp; /* working context */ 580350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bset.digits=pp+rhs->digits; /* wider context */ 580450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* Newton's iteration */ 580550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 580650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 580750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* just a sanity check; remove the test to show always */ 580850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (iterations>24) 580950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Ln iterations=%ld, status=%08lx, p=%ld, d=%ld\n", 581050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (LI)iterations, (LI)*status, (LI)p, (LI)rhs->digits); 581150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 581250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 581350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Copy and round the result to res */ 581450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=1; /* indicate dirt to right */ 581550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(a)) residue=0; /* .. unless underflowed to 0 */ 581650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aset.digits=set->digits; /* [use default rounding] */ 581750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */ 581850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); /* cleanup/set flags */ 581950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 582050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 582150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */ 582250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocbufb!=NULL) free(allocbufb); /* .. */ 582350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [status is handled by caller] */ 582450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 582550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decLnOp */ 582602c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) 582702c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#pragma GCC diagnostic pop 582802c1be445f109b3ffe2b10663bff2fd8aaa9bddcclaireho#endif 582950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 583050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 583150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decQuantizeOp -- force exponent to requested value */ 583250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 583350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = op(A, B), where op adjusts the coefficient */ 583450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of C (by rounding or shifting) such that the exponent (-scale) */ 583550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of C has the value B or matches the exponent of B. */ 583650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The numerical value of C will equal A, except for the effects of */ 583750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* any rounding that occurred. */ 583850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 583950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A or B */ 584050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A, the number to adjust */ 584150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B, the requested exponent */ 584250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 584350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* quant is 1 for quantize or 0 for rescale */ 584450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the status accumulator (this can be called without */ 584550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* risk of control loss) */ 584650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 584750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for set->digits digits. */ 584850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 584950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Unless there is an error or the result is infinite, the exponent */ 585050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* after the operation is guaranteed to be that requested. */ 585150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 585250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decQuantizeOp(decNumber *res, const decNumber *lhs, 585350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set, 585450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag quant, uInt *status) { 585550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 585650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */ 585750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* .., rhs */ 585850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 585950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *inrhs=rhs; /* save original rhs */ 586050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int reqdigits=set->digits; /* requested DIGITS */ 586150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int reqexp; /* requested exponent [-scale] */ 586250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* rounding residue */ 586350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int etiny=set->emin-(reqdigits-1); 586450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 586550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 586650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 586750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 586850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 586950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 587050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 587150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 587250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operands and set lostDigits status, as needed */ 587350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>reqdigits) { 587450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloclhs=decRoundOperand(lhs, set, status); 587550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs==NULL) break; 587650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=alloclhs; 587750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 587850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>reqdigits) { /* [this only checks lostDigits] */ 587950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, status); 588050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) break; 588150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 588250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 588350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 588450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 588550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 588650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 588750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Handle special values */ 588850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS) { 588950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* NaNs get usual processing */ 589050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (SPECIALARGS & (DECSNAN | DECNAN)) 589150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, status); 589250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* one infinity but not both is bad */ 589350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if ((lhs->bits ^ rhs->bits) & DECINF) 589450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 589550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* both infinity: return lhs */ 589650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else uprv_decNumberCopy(res, lhs); /* [nop if in place] */ 589750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 589850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 589950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 590050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set requested exponent */ 590150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (quant) reqexp=inrhs->exponent; /* quantize -- match exponents */ 590250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* rescale -- use value of rhs */ 590350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Original rhs must be an integer that fits and is in range, */ 590450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* which could be from -1999999997 to +999999999, thanks to */ 590550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subnormals */ 590650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho reqexp=decGetInt(inrhs); /* [cannot fail] */ 590750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 590850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 590950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 591050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) etiny=set->emin; /* no subnormals */ 591150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 591250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 591350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (reqexp==BADINT /* bad (rescale only) or .. */ 591450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || reqexp==BIGODD || reqexp==BIGEVEN /* very big (ditto) or .. */ 591550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (reqexp<etiny) /* < lowest */ 591650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (reqexp>set->emax)) { /* > emax */ 591750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 591850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 591950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 592050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the RHS has been processed, so it can be overwritten now if necessary */ 592150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(lhs)) { /* zero coefficient unchanged */ 592250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); /* [nop if in place] */ 592350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=reqexp; /* .. just set exponent */ 592450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 592550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) res->bits=0; /* subset specification; no -0 */ 592650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 592750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 592850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* non-zero lhs */ 592950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int adjust=reqexp-lhs->exponent; /* digit adjustment needed */ 593050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if adjusted coefficient will definitely not fit, give up now */ 593150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((lhs->digits-adjust)>reqdigits) { 593250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 593350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 593450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 593550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 593650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adjust>0) { /* increasing exponent */ 593750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this will decrease the length of the coefficient by adjust */ 593850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* digits, and must round as it does so */ 593950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset; /* work */ 594050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset=*set; /* clone rounding, etc. */ 594150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.digits=lhs->digits-adjust; /* set requested length */ 594250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [note that the latter can be <1, here] */ 594350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, lhs, &workset, &residue, status); /* fit to result */ 594450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decApplyRound(res, &workset, residue, status); /* .. and round */ 594550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho residue=0; /* [used] */ 594650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If just rounded a 999s case, exponent will be off by one; */ 594750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* adjust back (after checking space), if so. */ 594850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->exponent>reqexp) { 594950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* re-check needed, e.g., for quantize(0.9999, 0.001) under */ 595050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set->digits==3 */ 595150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits==reqdigits) { /* cannot shift by 1 */ 595250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status&=~(DEC_Inexact | DEC_Rounded); /* [clean these] */ 595350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 595450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 595550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 595650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, res->digits, 1); /* shift */ 595750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent--; /* (re)adjust the exponent. */ 595850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 595950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 596050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(res) && !set->extended) res->bits=0; /* subset; no -0 */ 596150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 596250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* increase */ 596350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else /* adjust<=0 */ { /* decreasing or = exponent */ 596450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this will increase the length of the coefficient by -adjust */ 596550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* digits, by adding zero or more trailing zeros; this is */ 596650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* already checked for fit, above */ 596750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberCopy(res, lhs); /* [it will fit] */ 596850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if padding needed (adjust<0), add it now... */ 596950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adjust<0) { 597050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=decShiftToMost(res->lsu, res->digits, -adjust); 597150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent+=adjust; /* adjust the exponent */ 597250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 597350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decrease */ 597450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* non-zero */ 597550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 597650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Check for overflow [do not use Finalize in this case, as an */ 597750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* overflow here is a "don't fit" situation] */ 597850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->exponent>set->emax-res->digits+1) { /* too big */ 597950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 598050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 598150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 598250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 598350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinalize(res, set, &residue, status); /* set subnormal flags */ 598450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status&=~DEC_Underflow; /* suppress Underflow [as per 754] */ 598550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 598650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 598750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 598850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 598950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs!=NULL) free(allocrhs); /* drop any storage used */ 599050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs!=NULL) free(alloclhs); /* .. */ 599150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 599250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 599350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decQuantizeOp */ 599450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 599550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 599650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCompareOp -- compare, min, or max two Numbers */ 599750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 599850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This computes C = A ? B and carries out one of four operations: */ 599950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMPARE -- returns the signum (as a number) giving the */ 600050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* result of a comparison unless one or both */ 600150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* operands is a NaN (in which case a NaN results) */ 600250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMPSIG -- as COMPARE except that a quiet NaN raises */ 600350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Invalid operation. */ 600450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMPMAX -- returns the larger of the operands, using the */ 600550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 754 maxnum operation */ 600650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMPMAXMAG -- ditto, comparing absolute values */ 600750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMPMIN -- the 754 minnum operation */ 600850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMPMINMAG -- ditto, comparing absolute values */ 600950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMTOTAL -- returns the signum (as a number) giving the */ 601050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* result of a comparison using 754 total ordering */ 601150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 601250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ 601350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is A */ 601450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is B */ 601550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 601650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* op is the operation flag */ 601750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the usual accumulator */ 601850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 601950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C must have space for one digit for COMPARE or set->digits for */ 602050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* COMPMAX, COMPMIN, COMPMAXMAG, or COMPMINMAG. */ 602150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 602250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The emphasis here is on speed for common cases, and avoiding */ 602350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* coefficient comparison if possible. */ 602450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 602550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decCompareOp(decNumber *res, const decNumber *lhs, 602650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set, 602750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag op, uInt *status) { 602850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 602950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */ 603050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *allocrhs=NULL; /* .., rhs */ 603150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 603250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int result=0; /* default result value */ 603350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte merged; /* work */ 603450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 603550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 603650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(res, lhs, rhs, set)) return res; 603750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 603850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 603950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho do { /* protect allocated storage */ 604050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 604150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 604250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* reduce operands and set lostDigits status, as needed */ 604350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits>set->digits) { 604450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloclhs=decRoundOperand(lhs, set, status); 604550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs==NULL) {result=BADINT; break;} 604650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=alloclhs; 604750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 604850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rhs->digits>set->digits) { 604950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocrhs=decRoundOperand(rhs, set, status); 605050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs==NULL) {result=BADINT; break;} 605150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=allocrhs; 605250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 605350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 605450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 605550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [following code does not require input rounding] */ 605650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 605750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If total ordering then handle differing signs 'up front' */ 605850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op==COMPTOTAL) { /* total ordering */ 605950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(lhs) & !decNumberIsNegative(rhs)) { 606050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=-1; 606150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 606250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 606350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!decNumberIsNegative(lhs) & decNumberIsNegative(rhs)) { 606450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=+1; 606550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 606650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 606750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 606850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 606950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* handle NaNs specially; let infinities drop through */ 607050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This assumes sNaN (even just one) leads to NaN. */ 607150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho merged=(lhs->bits | rhs->bits) & (DECSNAN | DECNAN); 607250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (merged) { /* a NaN bit set */ 607350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op==COMPARE); /* result will be NaN */ 607450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (op==COMPSIG) /* treat qNaN as sNaN */ 607550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation | DEC_sNaN; 607650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (op==COMPTOTAL) { /* total ordering, always finite */ 607750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* signs are known to be the same; compute the ordering here */ 607850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* as if the signs are both positive, then invert for negatives */ 607950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!decNumberIsNaN(lhs)) result=-1; 608050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (!decNumberIsNaN(rhs)) result=+1; 608150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here if both NaNs */ 608250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsSNaN(lhs) && decNumberIsQNaN(rhs)) result=-1; 608350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsQNaN(lhs) && decNumberIsSNaN(rhs)) result=+1; 608450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* both NaN or both sNaN */ 608550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now it just depends on the payload */ 608650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=decUnitCompare(lhs->lsu, D2U(lhs->digits), 608750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs->lsu, D2U(rhs->digits), 0); 608850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [Error not possible, as these are 'aligned'] */ 608950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* both same NaNs */ 609050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(lhs)) result=-result; 609150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 609250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* total order */ 609350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 609450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (merged & DECSNAN); /* sNaN -> qNaN */ 609550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* here if MIN or MAX and one or two quiet NaNs */ 609650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* min or max -- 754 rules ignore single NaN */ 609750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!decNumberIsNaN(lhs) || !decNumberIsNaN(rhs)) { 609850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* just one NaN; force choice to be the non-NaN operand */ 609950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho op=COMPMAX; 610050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->bits & DECNAN) result=-1; /* pick rhs */ 610150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else result=+1; /* pick lhs */ 610250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 610350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 610450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* max or min */ 610550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho op=COMPNAN; /* use special path */ 610650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNaNs(res, lhs, rhs, set, status); /* propagate NaN */ 610750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 610850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 610950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* have numbers */ 611050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op==COMPMAXMAG || op==COMPMINMAG) result=decCompare(lhs, rhs, 1); 611150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else result=decCompare(lhs, rhs, 0); /* sign matters */ 611250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } while(0); /* end protected */ 611350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 611450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result==BADINT) *status|=DEC_Insufficient_storage; /* rare */ 611550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 611650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op==COMPARE || op==COMPSIG ||op==COMPTOTAL) { /* returning signum */ 611750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op==COMPTOTAL && result==0) { 611850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* operands are numerically equal or same NaN (and same sign, */ 611950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* tested first); if identical, leave result 0 */ 612050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent!=rhs->exponent) { 612150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent<rhs->exponent) result=-1; 612250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else result=+1; 612350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(lhs)) result=-result; 612450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* lexp!=rexp */ 612550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* total-order by exponent */ 612650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); /* [always a valid result] */ 612750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result!=0) { /* must be -1 or +1 */ 612850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *res->lsu=1; 612950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result<0) res->bits=DECNEG; 613050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 613150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 613250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (op==COMPNAN); /* special, drop through */ 613350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* MAX or MIN, non-NaN result */ 613450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* rounding accumulator */ 613550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* choose the operand for the result */ 613650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *choice; 613750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result==0) { /* operands are numerically equal */ 613850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* choose according to sign then exponent (see 754) */ 613950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte slhs=(lhs->bits & DECNEG); 614050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte srhs=(rhs->bits & DECNEG); 614150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 614250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { /* subset: force left-hand */ 614350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho op=COMPMAX; 614450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=+1; 614550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 614650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else 614750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 614850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (slhs!=srhs) { /* signs differ */ 614950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (slhs) result=-1; /* rhs is max */ 615050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else result=+1; /* lhs is max */ 615150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 615250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (slhs && srhs) { /* both negative */ 615350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent<rhs->exponent) result=+1; 615450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else result=-1; 615550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [if equal, use lhs, technically identical] */ 615650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 615750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* both positive */ 615850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent>rhs->exponent) result=+1; 615950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else result=-1; 616050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [ditto] */ 616150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 616250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* numerically equal */ 616350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here result will be non-0; reverse if looking for MIN */ 616450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (op==COMPMIN || op==COMPMINMAG) result=-result; 616550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho choice=(result>0 ? lhs : rhs); /* choose */ 616650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* copy chosen to result, rounding if need be */ 616750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, choice, set, &residue, status); 616850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinish(res, set, &residue, status); 616950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 617050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 617150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 617250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocrhs!=NULL) free(allocrhs); /* free any storage used */ 617350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloclhs!=NULL) free(alloclhs); /* .. */ 617450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 617550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 617650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decCompareOp */ 617750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 617850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 617950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCompare -- compare two decNumbers by numerical value */ 618050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 618150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine compares A ? B without altering them. */ 618250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 618350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg1 is A, a decNumber which is not a NaN */ 618450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg2 is B, a decNumber which is not a NaN */ 618550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg3 is 1 for a sign-independent compare, 0 otherwise */ 618650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 618750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure */ 618850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (the only possible failure is an allocation error) */ 618950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 619050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decCompare(const decNumber *lhs, const decNumber *rhs, 619150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag abs_c) { 619250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int result; /* result value */ 619350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int sigr; /* rhs signum */ 619450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int compare; /* work */ 619550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 619650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=1; /* assume signum(lhs) */ 619750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(lhs)) result=0; 619850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (abs_c) { 619950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) return result; /* LHS wins or both 0 */ 620050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* RHS is non-zero */ 620150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result==0) return -1; /* LHS is 0; RHS wins */ 620250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [here, both non-zero, result=1] */ 620350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 620450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* signs matter */ 620550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result && decNumberIsNegative(lhs)) result=-1; 620650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho sigr=1; /* compute signum(rhs) */ 620750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(rhs)) sigr=0; 620850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (decNumberIsNegative(rhs)) sigr=-1; 620950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result > sigr) return +1; /* L > R, return 1 */ 621050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result < sigr) return -1; /* L < R, return -1 */ 621150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result==0) return 0; /* both 0 */ 621250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 621350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 621450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* signums are the same; both are non-zero */ 621550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((lhs->bits | rhs->bits) & DECINF) { /* one or more infinities */ 621650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(rhs)) { 621750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(lhs)) result=0;/* both infinite */ 621850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else result=-result; /* only rhs infinite */ 621950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 622050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 622150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 622250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* must compare the coefficients, allowing for exponents */ 622350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->exponent>rhs->exponent) { /* LHS exponent larger */ 622450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* swap sides, and sign */ 622550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *temp=lhs; 622650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=rhs; 622750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs=temp; 622850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=-result; 622950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 623050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho compare=decUnitCompare(lhs->lsu, D2U(lhs->digits), 623150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs->lsu, D2U(rhs->digits), 623250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rhs->exponent-lhs->exponent); 623350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (compare!=BADINT) compare*=result; /* comparison succeeded */ 623450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return compare; 623550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decCompare */ 623650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 623750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 623850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decUnitCompare -- compare two >=0 integers in Unit arrays */ 623950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 624050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine compares A ? B*10**E where A and B are unit arrays */ 624150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A is a plain integer */ 624250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* B has an exponent of E (which must be non-negative) */ 624350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 624450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg1 is A first Unit (lsu) */ 624550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg2 is A length in Units */ 624650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg3 is B first Unit (lsu) */ 624750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg4 is B length in Units */ 624850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg5 is E (0 if the units are aligned) */ 624950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 625050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure */ 625150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (the only possible failure is an allocation error, which can */ 625250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* only occur if E!=0) */ 625350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 625450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decUnitCompare(const Unit *a, Int alength, 625550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *b, Int blength, Int exp) { 625650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *acc; /* accumulator for result */ 625750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit accbuff[SD2U(DECBUFFER*2+1)]; /* local buffer */ 625850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *allocacc=NULL; /* -> allocated acc buffer, iff allocated */ 625950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int accunits, need; /* units in use or needed for acc */ 626050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *l, *r, *u; /* work */ 626150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int expunits, exprem, result; /* .. */ 626250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 626350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exp==0) { /* aligned; fastpath */ 626450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alength>blength) return 1; 626550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alength<blength) return -1; 626650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* same number of units in both -- need unit-by-unit compare */ 626750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho l=a+alength-1; 626850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho r=b+alength-1; 626950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;l>=a; l--, r--) { 627050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*l>*r) return 1; 627150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*l<*r) return -1; 627250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 627350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; /* all units match */ 627450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* aligned */ 627550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 627650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Unaligned. If one is >1 unit longer than the other, padded */ 627750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* approximately, then can return easily */ 627850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alength>blength+(Int)D2U(exp)) return 1; 627950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alength+1<blength+(Int)D2U(exp)) return -1; 628050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 628150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Need to do a real subtract. For this, a result buffer is needed */ 628250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* even though only the sign is of interest. Its length needs */ 628350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* to be the larger of alength and padded blength, +2 */ 628450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho need=blength+D2U(exp); /* maximum real length of B */ 628550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (need<alength) need=alength; 628650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho need+=2; 628750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=accbuff; /* assume use local buffer */ 628850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (need*sizeof(Unit)>sizeof(accbuff)) { 628950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho allocacc=(Unit *)malloc(need*sizeof(Unit)); 629050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc==NULL) return BADINT; /* hopeless -- abandon */ 629150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho acc=allocacc; 629250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 629350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Calculate units and remainder from exponent. */ 629450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho expunits=exp/DECDPUN; 629550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exprem=exp%DECDPUN; 629650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* subtract [A+B*(-m)] */ 629750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho accunits=decUnitAddSub(a, alength, b, blength, expunits, acc, 629850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho -(Int)powers[exprem]); 629950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [UnitAddSub result may have leading zeros, even on zero] */ 630050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (accunits<0) result=-1; /* negative result */ 630150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* non-negative result */ 630250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* check units of the result before freeing any storage */ 630350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (u=acc; u<acc+accunits-1 && *u==0;) u++; 630450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result=(*u==0 ? 0 : +1); 630550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 630650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* clean up and return the result */ 630750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (allocacc!=NULL) free(allocacc); /* drop any storage used */ 630850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 630950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decUnitCompare */ 631050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 631150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 631250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decUnitAddSub -- add or subtract two >=0 integers in Unit arrays */ 631350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 631450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine performs the calculation: */ 631550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 631650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C=A+(B*M) */ 631750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 631850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Where M is in the range -DECDPUNMAX through +DECDPUNMAX. */ 631950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 632050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A may be shorter or longer than B. */ 632150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 632250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Leading zeros are not removed after a calculation. The result is */ 632350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* either the same length as the longer of A and B (adding any */ 632450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* shift), or one Unit longer than that (if a Unit carry occurred). */ 632550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 632650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* A and B content are not altered unless C is also A or B. */ 632750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C may be the same array as A or B, but only if no zero padding is */ 632850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* requested (that is, C may be B only if bshift==0). */ 632950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* C is filled from the lsu; only those units necessary to complete */ 633050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the calculation are referenced. */ 633150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 633250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg1 is A first Unit (lsu) */ 633350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg2 is A length in Units */ 633450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg3 is B first Unit (lsu) */ 633550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg4 is B length in Units */ 633650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg5 is B shift in Units (>=0; pads with 0 units if positive) */ 633750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg6 is C first Unit (lsu) */ 633850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Arg7 is M, the multiplier */ 633950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 634050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns the count of Units written to C, which will be non-zero */ 634150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and negated if the result is negative. That is, the sign of the */ 634250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returned Int is the sign of the result (positive for zero) and */ 634350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the absolute value of the Int is the count of Units. */ 634450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 634550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* It is the caller's responsibility to make sure that C size is */ 634650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* safe, allowing space if necessary for a one-Unit carry. */ 634750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 634850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine is severely performance-critical; *any* change here */ 634950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* must be measured (timed) to assure no performance degradation. */ 635050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* In particular, trickery here tends to be counter-productive, as */ 635150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* increased complexity of code hurts register optimizations on */ 635250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* register-poor architectures. Avoiding divisions is nearly */ 635350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* always a Good Idea, however. */ 635450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 635550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Special thanks to Rick McGuire (IBM Cambridge, MA) and Dave Clark */ 635650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (IBM Warwick, UK) for some of the ideas used in this routine. */ 635750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 635850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decUnitAddSub(const Unit *a, Int alength, 635950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *b, Int blength, Int bshift, 636050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *c, Int m) { 636150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *alsu=a; /* A lsu [need to remember it] */ 636250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *clsu=c; /* C ditto */ 636350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *minC; /* low water mark for C */ 636450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *maxC; /* high water mark for C */ 636550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho eInt carry=0; /* carry integer (could be Long) */ 636650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int add; /* work */ 636750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 /* myriadal, millenary, etc. */ 636850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int est; /* estimated quotient */ 636950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 637050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 637150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 637250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alength<1 || blength<1) 637350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("decUnitAddSub: alen blen m %ld %ld [%ld]\n", alength, blength, m); 637450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 637550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 637650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxC=c+alength; /* A is usually the longer */ 637750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho minC=c+blength; /* .. and B the shorter */ 637850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bshift!=0) { /* B is shifted; low As copy across */ 637950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho minC+=bshift; 638050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if in place [common], skip copy unless there's a gap [rare] */ 638150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a==c && bshift<=alength) { 638250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c+=bshift; 638350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a+=bshift; 638450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 638550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else for (; c<clsu+bshift; a++, c++) { /* copy needed */ 638650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a<alsu+alength) *c=*a; 638750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else *c=0; 638850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 638950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 639050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (minC>maxC) { /* swap */ 639150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *hold=minC; 639250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho minC=maxC; 639350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxC=hold; 639450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 639550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 639650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* For speed, do the addition as two loops; the first where both A */ 639750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* and B contribute, and the second (if necessary) where only one or */ 639850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* other of the numbers contribute. */ 639950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Carry handling is the same (i.e., duplicated) in each case. */ 640050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; c<minC; c++) { 640150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry+=*a; 640250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a++; 640350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry+=((eInt)*b)*m; /* [special-casing m=1/-1 */ 640450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b++; /* here is not a win] */ 640550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here carry is new Unit of digits; it could be +ve or -ve */ 640650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((ueInt)carry<=DECDPUNMAX) { /* fastpath 0-DECDPUNMAX */ 640750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)carry; 640850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=0; 640950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 641050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 641150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==4 /* use divide-by-multiply */ 641250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 641350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>11)*53687)>>18; 641450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ 641550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est; /* likely quotient [89%] */ 641650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* estimate was correct */ 641750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 641850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 641950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 642050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 642150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 642250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 642350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>11)*53687)>>18; 642450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); 642550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est-(DECDPUNMAX+1); /* correctly negative */ 642650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* was OK */ 642750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 642850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 642950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==3 643050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 643150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>3)*16777)>>21; 643250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ 643350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est; /* likely quotient [99%] */ 643450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* estimate was correct */ 643550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 643650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 643750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 643850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 643950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 644050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 644150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>3)*16777)>>21; 644250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); 644350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est-(DECDPUNMAX+1); /* correctly negative */ 644450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* was OK */ 644550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 644650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 644750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN<=2 644850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Can use QUOT10 as carry <= 4 digits */ 644950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 645050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=QUOT10(carry, DECDPUN); 645150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ 645250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est; /* quotient */ 645350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 645450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 645550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 645650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 645750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=QUOT10(carry, DECDPUN); 645850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); 645950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est-(DECDPUNMAX+1); /* correctly negative */ 646050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 646150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* remainder operator is undefined if negative, so must test */ 646250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((ueInt)carry<(DECDPUNMAX+1)*2) { /* fastpath carry +1 */ 646350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-(DECDPUNMAX+1)); /* [helps additions] */ 646450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=1; 646550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 646650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 646750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 646850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry%(DECDPUNMAX+1)); 646950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry/(DECDPUNMAX+1); 647050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 647150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 647250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 647350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 647450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry%(DECDPUNMAX+1)); 647550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1); 647650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 647750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* c */ 647850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 647950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now may have one or other to complete */ 648050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [pretest to avoid loop setup/shutdown] */ 648150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (c<maxC) for (; c<maxC; c++) { 648250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (a<alsu+alength) { /* still in A */ 648350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry+=*a; 648450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho a++; 648550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 648650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* inside B */ 648750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry+=((eInt)*b)*m; 648850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b++; 648950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 649050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here carry is new Unit of digits; it could be +ve or -ve and */ 649150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* magnitude up to DECDPUNMAX squared */ 649250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((ueInt)carry<=DECDPUNMAX) { /* fastpath 0-DECDPUNMAX */ 649350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)carry; 649450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=0; 649550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 649650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 649750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* result for this unit is negative or >DECDPUNMAX */ 649850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==4 /* use divide-by-multiply */ 649950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 650050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>11)*53687)>>18; 650150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ 650250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est; /* likely quotient [79.7%] */ 650350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* estimate was correct */ 650450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 650550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 650650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 650750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 650850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 650950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 651050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>11)*53687)>>18; 651150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); 651250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est-(DECDPUNMAX+1); /* correctly negative */ 651350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* was OK */ 651450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 651550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 651650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==3 651750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 651850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>3)*16777)>>21; 651950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ 652050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est; /* likely quotient [99%] */ 652150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* estimate was correct */ 652250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 652350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 652450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 652550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 652650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 652750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 652850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=(((ueInt)carry>>3)*16777)>>21; 652950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); 653050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est-(DECDPUNMAX+1); /* correctly negative */ 653150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*c<DECDPUNMAX+1) continue; /* was OK */ 653250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry++; 653350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c-=DECDPUNMAX+1; 653450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN<=2 653550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 653650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=QUOT10(carry, DECDPUN); 653750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ 653850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est; /* quotient */ 653950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 654050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 654150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 654250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 654350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho est=QUOT10(carry, DECDPUN); 654450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-est*(DECDPUNMAX+1)); 654550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=est-(DECDPUNMAX+1); /* correctly negative */ 654650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 654750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((ueInt)carry<(DECDPUNMAX+1)*2){ /* fastpath carry 1 */ 654850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry-(DECDPUNMAX+1)); 654950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=1; 655050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 655150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 655250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* remainder operator is undefined if negative, so must test */ 655350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>=0) { 655450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry%(DECDPUNMAX+1)); 655550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry/(DECDPUNMAX+1); 655650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 655750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 655850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* negative case */ 655950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ 656050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(carry%(DECDPUNMAX+1)); 656150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1); 656250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 656350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* c */ 656450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 656550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* OK, all A and B processed; might still have carry or borrow */ 656650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* return number of Units in the result, negated if a borrow */ 656750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry==0) return c-clsu; /* no carry, so no more to do */ 656850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (carry>0) { /* positive carry */ 656950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)carry; /* place as new unit */ 657050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; /* .. */ 657150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return c-clsu; 657250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 657350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* -ve carry: it's a borrow; complement needed */ 657450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho add=1; /* temporary carry... */ 657550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (c=clsu; c<maxC; c++) { 657650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho add=DECDPUNMAX+add-*c; 657750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (add<=DECDPUNMAX) { 657850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)add; 657950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho add=0; 658050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 658150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 658250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=0; 658350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho add=1; 658450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 658550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 658650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* add an extra unit iff it would be non-zero */ 658750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 658850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("UAS borrow: add %ld, carry %ld\n", add, carry); 658950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 659050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((add-carry-1)!=0) { 659150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *c=(Unit)(add-carry-1); 659250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c++; /* interesting, include it */ 659350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 659450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return clsu-c; /* -ve result indicates borrowed */ 659550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decUnitAddSub */ 659650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 659750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 659850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decTrim -- trim trailing zeros or normalize */ 659950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 660050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to trim or normalize */ 660150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context to use to check for clamp */ 660250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* all is 1 to remove all trailing zeros, 0 for just fraction ones */ 660350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* noclamp is 1 to unconditional (unclamped) trim */ 660450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dropped returns the number of discarded trailing zeros */ 660550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns dn */ 660650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 660750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If clamp is set in the context then the number of zeros trimmed */ 660850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* may be limited if the exponent is high. */ 660950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All fields are updated as required. This is a utility operation, */ 661050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* so special values are unchanged and no error is possible. */ 661150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 661250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decTrim(decNumber *dn, decContext *set, Flag all, 661350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag noclamp, Int *dropped) { 661450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int d, exp; /* work */ 661550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt cut; /* .. */ 661650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up; /* -> current Unit */ 661750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 661850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 661950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn; 662050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 662150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 662250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *dropped=0; /* assume no zeros dropped */ 662350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((dn->bits & DECSPECIAL) /* fast exit if special .. */ 662450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (*dn->lsu & 0x01)) return dn; /* .. or odd */ 662550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(dn)) { /* .. or 0 */ 662650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=0; /* (sign is preserved) */ 662750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 662850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 662950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 663050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* have a finite number which is even */ 663150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exp=dn->exponent; 663250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=1; /* digit (1-DECDPUN) in Unit */ 663350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=dn->lsu; /* -> current Unit */ 663450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (d=0; d<dn->digits-1; d++) { /* [don't strip the final digit] */ 663550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* slice by powers */ 663650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 663750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt quot=QUOT10(*up, cut); 663850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((*up-quot*powers[cut])!=0) break; /* found non-0 digit */ 663950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 664050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up%powers[cut]!=0) break; /* found non-0 digit */ 664150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 664250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* have a trailing 0 */ 664350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!all) { /* trimming */ 664450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [if exp>0 then all trailing 0s are significant for trim] */ 664550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exp<=0) { /* if digit might be significant */ 664650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (exp==0) break; /* then quit */ 664750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exp++; /* next digit might be significant */ 664850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 664950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 665050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut++; /* next power */ 665150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut>DECDPUN) { /* need new Unit */ 665250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; 665350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=1; 665450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 665550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* d */ 665650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (d==0) return dn; /* none to drop */ 665750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 665850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* may need to limit drop if clamping */ 665950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->clamp && !noclamp) { 666050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int maxd=set->emax-set->digits+1-dn->exponent; 666150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (maxd<=0) return dn; /* nothing possible */ 666250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (d>maxd) d=maxd; 666350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 666450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 666550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* effect the drop */ 666650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decShiftToLeast(dn->lsu, D2U(dn->digits), d); 666750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent+=d; /* maintain numerical value */ 666850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits-=d; /* new length */ 666950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *dropped=d; /* report the count */ 667050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 667150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decTrim */ 667250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 667350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 667450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decReverse -- reverse a Unit array in place */ 667550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 667650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ulo is the start of the array */ 667750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* uhi is the end of the array (highest Unit to include) */ 667850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 667950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The units ulo through uhi are reversed in place (if the number */ 668050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* of units is odd, the middle one is untouched). Note that the */ 668150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* digit(s) in each unit are unaffected. */ 668250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 668350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decReverse(Unit *ulo, Unit *uhi) { 668450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit temp; 668550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; ulo<uhi; ulo++, uhi--) { 668650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho temp=*ulo; 668750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *ulo=*uhi; 668850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uhi=temp; 668950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 669050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 669150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decReverse */ 669250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 669350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 669450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decShiftToMost -- shift digits in array towards most significant */ 669550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 669650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* uar is the array */ 669750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* digits is the count of digits in use in the array */ 669850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* shift is the number of zeros to pad with (least significant); */ 669950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* it must be zero or positive */ 670050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 670150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns the new length of the integer in the array, in digits */ 670250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 670350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* No overflow is permitted (that is, the uar array must be known to */ 670450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* be large enough to hold the result, after shifting). */ 670550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 670650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decShiftToMost(Unit *uar, Int digits, Int shift) { 670750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *target, *source, *first; /* work */ 670850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int cut; /* odd 0's to add */ 670950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt next; /* work */ 671050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 671150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift==0) return digits; /* [fastpath] nothing to do */ 671250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((digits+shift)<=DECDPUN) { /* [fastpath] single-unit case */ 671350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uar=(Unit)(*uar*powers[shift]); 671450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return digits+shift; 671550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 671650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 671750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho next=0; /* all paths */ 671850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho source=uar+D2U(digits)-1; /* where msu comes from */ 671950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho target=source+D2U(shift); /* where upper part of first cut goes */ 672050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=DECDPUN-MSUDIGITS(shift); /* where to slice */ 672150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut==0) { /* unit-boundary case */ 672250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; source>=uar; source--, target--) *target=*source; 672350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 672450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 672550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho first=uar+D2U(digits+shift)-1; /* where msu of source will end up */ 672650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; source>=uar; source--, target--) { 672750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* split the source Unit and accumulate remainder for next */ 672850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 672950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt quot=QUOT10(*source, cut); 673050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt rem=*source-quot*powers[cut]; 673150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho next+=quot; 673250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 673350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt rem=*source%powers[cut]; 673450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho next+=*source/powers[cut]; 673550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 673650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (target<=first) *target=(Unit)next; /* write to target iff valid */ 673750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho next=rem*powers[DECDPUN-cut]; /* save remainder for next Unit */ 673850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 673950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* shift-move */ 674050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 674150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* propagate any partial unit to one below and clear the rest */ 674250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; target>=uar; target--) { 674350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *target=(Unit)next; 674450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho next=0; 674550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 674650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return digits+shift; 674750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decShiftToMost */ 674850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 674950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 675050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decShiftToLeast -- shift digits in array towards least significant */ 675150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 675250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* uar is the array */ 675350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* units is length of the array, in units */ 675450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* shift is the number of digits to remove from the lsu end; it */ 675550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* must be zero or positive and <= than units*DECDPUN. */ 675650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 675750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns the new length of the integer in the array, in units */ 675850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 675950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Removed digits are discarded (lost). Units not required to hold */ 676050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the final result are unchanged. */ 676150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 676250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decShiftToLeast(Unit *uar, Int units, Int shift) { 676350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *target, *up; /* work */ 676450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int cut, count; /* work */ 676550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int quot, rem; /* for division */ 676650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 676750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift==0) return units; /* [fastpath] nothing to do */ 676850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (shift==units*DECDPUN) { /* [fastpath] little to do */ 676950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *uar=0; /* all digits cleared gives zero */ 677050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1; /* leaves just the one */ 677150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 677250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 677350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho target=uar; /* both paths */ 677450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=MSUDIGITS(shift); 677550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut==DECDPUN) { /* unit-boundary case; easy */ 677650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=uar+D2U(shift); 677750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; up<uar+units; target++, up++) *target=*up; 677850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return target-uar; 677950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 678050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 678150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* messier */ 678250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=uar+D2U(shift-cut); /* source; correct to whole Units */ 678350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count=units*DECDPUN-shift; /* the maximum new length */ 678450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 678550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=QUOT10(*up, cut); 678650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 678750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=*up/powers[cut]; 678850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 678950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; ; target++) { 679050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *target=(Unit)quot; 679150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=(DECDPUN-cut); 679250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count<=0) break; 679350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; 679450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=*up; 679550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 679650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=QUOT10(quot, cut); 679750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=*up-quot*powers[cut]; 679850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 679950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=quot%powers[cut]; 680050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=quot/powers[cut]; 680150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 680250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *target=(Unit)(*target+rem*powers[DECDPUN-cut]); 680350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=cut; 680450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count<=0) break; 680550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 680650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return target-uar+1; 680750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decShiftToLeast */ 680850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 680950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECSUBSET 681050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 681150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decRoundOperand -- round an operand [used for subset only] */ 681250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 681350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to round (dn->digits is > set->digits) */ 681450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the relevant context */ 681550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the status accumulator */ 681650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 681750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns an allocated decNumber with the rounded result. */ 681850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 681950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lostDigits and other status may be set by this. */ 682050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 682150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Since the input is an operand, it must not be modified. */ 682250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Instead, return an allocated decNumber, rounded as required. */ 682350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* It is the caller's responsibility to free the allocated storage. */ 682450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 682550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If no storage is available then the result cannot be used, so NULL */ 682650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* is returned. */ 682750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 682850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber *decRoundOperand(const decNumber *dn, decContext *set, 682950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 683050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber *res; /* result structure */ 683150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt newstatus=0; /* status from round */ 683250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int residue=0; /* rounding accumulator */ 683350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 683450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Allocate storage for the returned decNumber, big enough for the */ 683550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* length specified by the context */ 683650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res=(decNumber *)malloc(sizeof(decNumber) 683750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho +(D2U(set->digits)-1)*sizeof(Unit)); 683850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res==NULL) { 683950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; 684050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return NULL; 684150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 684250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decCopyFit(res, dn, set, &residue, &newstatus); 684350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decApplyRound(res, set, residue, &newstatus); 684450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 684550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* If that set Inexact then "lost digits" is raised... */ 684650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (newstatus & DEC_Inexact) newstatus|=DEC_Lost_digits; 684750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=newstatus; 684850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 684950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decRoundOperand */ 685050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 685150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 685250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 685350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCopyFit -- copy a number, truncating the coefficient if needed */ 685450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 685550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dest is the target decNumber */ 685650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* src is the source decNumber */ 685750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context [used for length (digits) and rounding mode] */ 685850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* residue is the residue accumulator */ 685950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status contains the current status to be updated */ 686050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 686150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (dest==src is allowed and will be a no-op if fits) */ 686250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All fields are updated as required. */ 686350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 686450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decCopyFit(decNumber *dest, const decNumber *src, 686550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext *set, Int *residue, uInt *status) { 686650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dest->bits=src->bits; 686750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dest->exponent=src->exponent; 686850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetCoeff(dest, set, src->lsu, src->digits, residue, status); 686950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decCopyFit */ 687050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 687150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 687250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decSetCoeff -- set the coefficient of a number */ 687350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 687450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number whose coefficient array is to be set. */ 687550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* It must have space for set->digits digits */ 687650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context [for size] */ 687750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lsu -> lsu of the source coefficient [may be dn->lsu] */ 687850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* len is digits in the source coefficient [may be dn->digits] */ 687950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* residue is the residue accumulator. This has values as in */ 688050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decApplyRound, and will be unchanged unless the */ 688150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* target size is less than len. In this case, the */ 688250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* coefficient is truncated and the residue is updated to */ 688350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* reflect the previous residue and the dropped digits. */ 688450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the status accumulator, as usual */ 688550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 688650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The coefficient may already be in the number, or it can be an */ 688750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* external intermediate array. If it is in the number, lsu must == */ 688850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn->lsu and len must == dn->digits. */ 688950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 689050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Note that the coefficient length (len) may be < set->digits, and */ 689150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* in this case this merely copies the coefficient (or is a no-op */ 689250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if dn->lsu==lsu). */ 689350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 689450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Note also that (only internally, from decQuantizeOp and */ 689550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decSetSubnormal) the value of set->digits may be less than one, */ 689650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* indicating a round to left. This routine handles that case */ 689750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* correctly; caller ensures space. */ 689850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 689950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn->digits, dn->lsu (and as required), and dn->exponent are */ 690050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* updated as necessary. dn->bits (sign) is unchanged. */ 690150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 690250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* DEC_Rounded status is set if any digits are discarded. */ 690350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* DEC_Inexact status is set if any non-zero digits are discarded, or */ 690450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* incoming residue was non-0 (implies rounded) */ 690550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 690650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* mapping array: maps 0-9 to canonical residues, so that a residue */ 690750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* can be adjusted in the range [-1, +1] and achieve correct rounding */ 690850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 0 1 2 3 4 5 6 7 8 9 */ 690950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const uByte resmap[10]={0, 3, 3, 3, 3, 5, 7, 7, 7, 7}; 691050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetCoeff(decNumber *dn, decContext *set, const Unit *lsu, 691150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int len, Int *residue, uInt *status) { 691250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int discard; /* number of digits to discard */ 691350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt cut; /* cut point in Unit */ 691450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up; /* work */ 691550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *target; /* .. */ 691650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int count; /* .. */ 691750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 691850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt temp; /* .. */ 691950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 692050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 692150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho discard=len-set->digits; /* digits to discard */ 692250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (discard<=0) { /* no digits are being discarded */ 692350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->lsu!=lsu) { /* copy needed */ 692450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* copy the coefficient array to the result number; no shift needed */ 692550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count=len; /* avoids D2U */ 692650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=lsu; 692750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN) 692850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *target=*up; 692950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=len; /* set the new length */ 693050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 693150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* dn->exponent and residue are unchanged, record any inexactitude */ 693250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue!=0) *status|=(DEC_Inexact | DEC_Rounded); 693350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 693450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 693550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 693650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* some digits must be discarded ... */ 693750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent+=discard; /* maintain numerical value */ 693850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Rounded; /* accumulate Rounded status */ 693950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue>1) *residue=1; /* previous residue now to right, so reduce */ 694050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 694150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (discard>len) { /* everything, +1, is being discarded */ 694250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* guard digit is 0 */ 694350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* residue is all the number [NB could be all 0s] */ 694450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue<=0) { /* not already positive */ 694550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count=len; /* avoids D2U */ 694650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=lsu; count>0; up++, count-=DECDPUN) if (*up!=0) { /* found non-0 */ 694750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *residue=1; 694850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* no need to check any others */ 694950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 695050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 695150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */ 695250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *dn->lsu=0; /* coefficient will now be 0 */ 695350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=1; /* .. */ 695450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 695550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* total discard */ 695650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 695750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* partial discard [most common case] */ 695850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here, at least the first (most significant) discarded digit exists */ 695950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 696050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* spin up the number, noting residue during the spin, until get to */ 696150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the Unit with the first discarded digit. When reach it, extract */ 696250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it and remember its position */ 696350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count=0; 696450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=lsu;; up++) { 696550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count+=DECDPUN; 696650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count>=discard) break; /* full ones all checked */ 696750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=0) *residue=1; 696850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* up */ 696950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 697050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here up -> Unit with first discarded digit */ 697150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=discard-(count-DECDPUN)-1; 697250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut==DECDPUN-1) { /* unit-boundary case (fast) */ 697350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit half=(Unit)powers[DECDPUN]>>1; 697450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* set residue directly */ 697550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up>=half) { 697650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up>half) *residue=7; 697750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else *residue+=5; /* add sticky bit */ 697850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 697950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* <half */ 698050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=0) *residue=3; /* [else is 0, leave as sticky bit] */ 698150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 698250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->digits<=0) { /* special for Quantize/Subnormal :-( */ 698350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *dn->lsu=0; /* .. result is 0 */ 698450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=1; /* .. */ 698550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 698650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* shift to least */ 698750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count=set->digits; /* now digits to end up with */ 698850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=count; /* set the new length */ 698950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; /* move to next */ 699050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* on unit boundary, so shift-down copy loop is simple */ 699150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN) 699250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *target=*up; 699350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 699450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* unit-boundary case */ 699550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 699650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* discard digit is in low digit(s), and not top digit */ 699750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt discard1; /* first discarded digit */ 699850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt quot, rem; /* for divisions */ 699950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut==0) quot=*up; /* is at bottom of unit */ 700050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else /* cut>0 */ { /* it's not at bottom of unit */ 700150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 700250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=QUOT10(*up, cut); 700350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=*up-quot*powers[cut]; 700450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 700550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=*up%powers[cut]; 700650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=*up/powers[cut]; 700750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 700850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rem!=0) *residue=1; 700950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 701050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* discard digit is now at bottom of quot */ 701150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 701250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho temp=(quot*6554)>>16; /* fast /10 */ 701350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Vowels algorithm here not a win (9 instructions) */ 701450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho discard1=quot-X10(temp); 701550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=temp; 701650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 701750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho discard1=quot%10; 701850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=quot/10; 701950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 702050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here, discard1 is the guard digit, and residue is everything */ 702150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* else [use mapping array to accumulate residue safely] */ 702250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *residue+=resmap[discard1]; 702350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut++; /* update cut */ 702450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here: up -> Unit of the array with bottom digit */ 702550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* cut is the division point for each Unit */ 702650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* quot holds the uncut high-order digits for the current unit */ 702750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->digits<=0) { /* special for Quantize/Subnormal :-( */ 702850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *dn->lsu=0; /* .. result is 0 */ 702950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=1; /* .. */ 703050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 703150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* shift to least needed */ 703250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count=set->digits; /* now digits to end up with */ 703350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=count; /* set the new length */ 703450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* shift-copy the coefficient array to the result number */ 703550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (target=dn->lsu; ; target++) { 703650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *target=(Unit)quot; 703750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=(DECDPUN-cut); 703850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count<=0) break; 703950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; 704050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=*up; 704150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 704250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=QUOT10(quot, cut); 704350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=*up-quot*powers[cut]; 704450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 704550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=quot%powers[cut]; 704650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho quot=quot/powers[cut]; 704750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 704850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *target=(Unit)(*target+rem*powers[DECDPUN-cut]); 704950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=cut; 705050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count<=0) break; 705150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* shift-copy loop */ 705250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* shift to least */ 705350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* not unit boundary */ 705450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 705550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */ 705650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 705750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decSetCoeff */ 705850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 705950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 706050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decApplyRound -- apply pending rounding to a number */ 706150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 706250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number, with space for set->digits digits */ 706350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context [for size and rounding mode] */ 706450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* residue indicates pending rounding, being any accumulated */ 706550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* guard and sticky information. It may be: */ 706650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 6-9: rounding digit is >5 */ 706750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 5: rounding digit is exactly half-way */ 706850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 1-4: rounding digit is <5 and >0 */ 706950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 0: the coefficient is exact */ 707050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -1: as 1, but the hidden digits are subtractive, that */ 707150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* is, of the opposite sign to dn. In this case the */ 707250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* coefficient must be non-0. This case occurs when */ 707350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* subtracting a small number (which can be reduced to */ 707450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* a sticky bit); see decAddOp. */ 707550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the status accumulator, as usual */ 707650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 707750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine applies rounding while keeping the length of the */ 707850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* coefficient constant. The exponent and status are unchanged */ 707950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* except if: */ 708050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 708150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -- the coefficient was increased and is all nines (in which */ 708250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* case Overflow could occur, and is handled directly here so */ 708350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the caller does not need to re-test for overflow) */ 708450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 708550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* -- the coefficient was decreased and becomes all nines (in which */ 708650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* case Underflow could occur, and is also handled directly). */ 708750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 708850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All fields in dn are updated as required. */ 708950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 709050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 709150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decApplyRound(decNumber *dn, decContext *set, Int residue, 709250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 709350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int bump; /* 1 if coefficient needs to be incremented */ 709450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* -1 if coefficient needs to be decremented */ 709550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 709650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue==0) return; /* nothing to apply */ 709750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 709850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bump=0; /* assume a smooth ride */ 709950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 710050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now decide whether, and how, to round, depending on mode */ 710150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho switch (set->round) { 710250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_05UP: { /* round zero or five up (for reround) */ 710350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This is the same as DEC_ROUND_DOWN unless there is a */ 710450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* positive residue and the lsd of dn is 0 or 5, in which case */ 710550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it is bumped; when residue is <0, the number is therefore */ 710650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* bumped down unless the final digit was 1 or 6 (in which */ 710750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* case it is bumped down and then up -- a no-op) */ 710850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int lsd5=*dn->lsu%5; /* get lsd and quintate */ 710950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue<0 && lsd5!=1) bump=-1; 711050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (residue>0 && lsd5==0) bump=1; 711150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [bump==1 could be applied directly; use common path for clarity] */ 711250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-05 */ 711350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 711450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_DOWN: { 711550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* no change, except if negative residue */ 711650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue<0) bump=-1; 711750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-d */ 711850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 711950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_HALF_DOWN: { 712050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue>5) bump=1; 712150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-h-d */ 712250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 712350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_HALF_EVEN: { 712450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue>5) bump=1; /* >0.5 goes up */ 712550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (residue==5) { /* exactly 0.5000... */ 712650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 0.5 goes up iff [new] lsd is odd */ 712750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*dn->lsu & 0x01) bump=1; 712850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 712950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-h-e */ 713050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 713150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_HALF_UP: { 713250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue>=5) bump=1; 713350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-h-u */ 713450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 713550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_UP: { 713650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue>0) bump=1; 713750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-u */ 713850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 713950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_CEILING: { 714050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* same as _UP for positive numbers, and as _DOWN for negatives */ 714150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [negative residue cannot occur on 0] */ 714250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dn)) { 714350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue<0) bump=-1; 714450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 714550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 714650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue>0) bump=1; 714750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 714850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-c */ 714950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 715050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_FLOOR: { 715150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* same as _UP for negative numbers, and as _DOWN for positive */ 715250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [negative residue cannot occur on 0] */ 715350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!decNumberIsNegative(dn)) { 715450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue<0) bump=-1; 715550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 715650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 715750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (residue>0) bump=1; 715850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 715950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-f */ 716050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 716150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho default: { /* e.g., DEC_ROUND_MAX */ 716250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_context; 716350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || (DECCHECK && DECVERB) 716450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Unknown rounding mode: %d\n", set->round); 716550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 716650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} 716750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* switch */ 716850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 716950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now bump the number, up or down, if need be */ 717050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bump==0) return; /* no action required */ 717150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 717250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Simply use decUnitAddSub unless bumping up and the number is */ 717350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* all nines. In this special case set to 100... explicitly */ 717450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* and adjust the exponent by one (as otherwise could overflow */ 717550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* the array) */ 717650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Similarly handle all-nines result if bumping down. */ 717750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bump>0) { 717850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up; /* work */ 717950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt count=dn->digits; /* digits to be checked */ 718050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=dn->lsu; ; up++) { 718150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count<=DECDPUN) { 718250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this is the last Unit (the msu) */ 718350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=powers[count]-1) break; /* not still 9s */ 718450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here if it, too, is all nines */ 718550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)powers[count-1]; /* here 999 -> 100 etc. */ 718650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=up-1; up>=dn->lsu; up--) *up=0; /* others all to 0 */ 718750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent++; /* and bump exponent */ 718850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [which, very rarely, could cause Overflow...] */ 718950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((dn->exponent+dn->digits)>set->emax+1) { 719050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetOverflow(dn, set, status); 719150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 719250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; /* done */ 719350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 719450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a full unit to check, with more to come */ 719550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=DECDPUNMAX) break; /* not still 9s */ 719650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=DECDPUN; 719750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* up */ 719850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* bump>0 */ 719950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* -1 */ 720050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here checking for a pre-bump of 1000... (leading 1, all */ 720150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* other digits zero) */ 720250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up, *sup; /* work */ 720350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt count=dn->digits; /* digits to be checked */ 720450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=dn->lsu; ; up++) { 720550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count<=DECDPUN) { 720650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this is the last Unit (the msu) */ 720750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=powers[count-1]) break; /* not 100.. */ 720850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here if have the 1000... case */ 720950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho sup=up; /* save msu pointer */ 721050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)powers[count]-1; /* here 100 in msu -> 999 */ 721150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* others all to all-nines, too */ 721250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=up-1; up>=dn->lsu; up--) *up=(Unit)powers[DECDPUN]-1; 721350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent--; /* and bump exponent */ 721450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 721550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* iff the number was at the subnormal boundary (exponent=etiny) */ 721650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* then the exponent is now out of range, so it will in fact get */ 721750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* clamped to etiny and the final 9 dropped. */ 721850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* printf(">> emin=%d exp=%d sdig=%d\n", set->emin, */ 721950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* dn->exponent, set->digits); */ 722050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent+1==set->emin-set->digits+1) { 722150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count==1 && dn->digits==1) *sup=0; /* here 9 -> 0[.9] */ 722250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 722350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *sup=(Unit)powers[count-1]-1; /* here 999.. in msu -> 99.. */ 722450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits--; 722550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 722650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent++; 722750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded; 722850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 722950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; /* done */ 723050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 723150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 723250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* a full unit to check, with more to come */ 723350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=0) break; /* not still 0s */ 723450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=DECDPUN; 723550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* up */ 723650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 723750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* bump<0 */ 723850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 723950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Actual bump needed. Do it. */ 724050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decUnitAddSub(dn->lsu, D2U(dn->digits), uarrone, 1, 0, dn->lsu, bump); 724150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decApplyRound */ 724250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 724350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECSUBSET 724450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 724550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decFinish -- finish processing a number */ 724650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 724750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number */ 724850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 724950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* residue is the rounding accumulator (as in decApplyRound) */ 725050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the accumulator */ 725150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 725250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This finishes off the current number by: */ 725350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 1. If not extended: */ 725450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* a. Converting a zero result to clean '0' */ 725550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* b. Reducing positive exponents to 0, if would fit in digits */ 725650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 2. Checking for overflow and subnormals (always) */ 725750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Note this is just Finalize when no subset arithmetic. */ 725850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All fields are updated as required. */ 725950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 726050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decFinish(decNumber *dn, decContext *set, Int *residue, 726150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 726250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 726350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ISZERO(dn) { /* value is zero */ 726450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=0; /* clean exponent .. */ 726550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=0; /* .. and sign */ 726650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; /* no error possible */ 726750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 726850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent>=0) { /* non-negative exponent */ 726950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* >0; reduce to integer if possible */ 727050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->digits >= (dn->exponent+dn->digits)) { 727150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=decShiftToMost(dn->lsu, dn->digits, dn->exponent); 727250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=0; 727350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 727450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 727550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* !extended */ 727650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 727750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decFinalize(dn, set, residue, status); 727850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decFinish */ 727950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 728050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 728150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 728250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decFinalize -- final check, clamp, and round of a number */ 728350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 728450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number */ 728550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 728650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* residue is the rounding accumulator (as in decApplyRound) */ 728750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is the status accumulator */ 728850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 728950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This finishes off the current number by checking for subnormal */ 729050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* results, applying any pending rounding, checking for overflow, */ 729150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* and applying any clamping. */ 729250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Underflow and overflow conditions are raised as appropriate. */ 729350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All fields are updated as required. */ 729450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 729550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decFinalize(decNumber *dn, decContext *set, Int *residue, 729650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 729750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int shift; /* shift needed if clamping */ 729850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int tinyexp=set->emin-dn->digits+1; /* precalculate subnormal boundary */ 729950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 730050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Must be careful, here, when checking the exponent as the */ 730150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* adjusted exponent could overflow 31 bits [because it may already */ 730250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* be up to twice the expected]. */ 730350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 730450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* First test for subnormal. This must be done before any final */ 730550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* round as the result could be rounded to Nmin or 0. */ 730650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent<=tinyexp) { /* prefilter */ 730750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int comp; 730850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decNumber nmin; 730950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* A very nasty case here is dn == Nmin and residue<0 */ 731050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent<tinyexp) { 731150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Go handle subnormals; this will apply round if needed. */ 731250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetSubnormal(dn, set, residue, status); 731350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 731450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 731550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Equals case: only subnormal if dn=Nmin and negative residue */ 731650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(&nmin); 731750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho nmin.lsu[0]=1; 731850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho nmin.exponent=set->emin; 731950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho comp=decCompare(dn, &nmin, 1); /* (signless compare) */ 732050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (comp==BADINT) { /* oops */ 732150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Insufficient_storage; /* abandon... */ 732250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 732350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 732450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue<0 && comp==0) { /* neg residue and dn==Nmin */ 732550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decApplyRound(dn, set, *residue, status); /* might force down */ 732650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetSubnormal(dn, set, residue, status); 732750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 732850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 732950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 733050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 733150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now apply any pending round (this could raise overflow). */ 733250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue!=0) decApplyRound(dn, set, *residue, status); 733350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 733450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Check for overflow [redundant in the 'rare' case] or clamp */ 733550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent<=set->emax-set->digits+1) return; /* neither needed */ 733650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 733750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 733850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here when might have an overflow or clamp to do */ 733950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent>set->emax-dn->digits+1) { /* too big */ 734050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetOverflow(dn, set, status); 734150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 734250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 734350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here when the result is normal but in clamp range */ 734450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->clamp) return; 734550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 734650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* here when need to apply the IEEE exponent clamp (fold-down) */ 734750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho shift=dn->exponent-(set->emax-set->digits+1); 734850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 734950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* shift coefficient (if non-zero) */ 735050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!ISZERO(dn)) { 735150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=decShiftToMost(dn->lsu, dn->digits, shift); 735250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 735350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent-=shift; /* adjust the exponent to match */ 735450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Clamped; /* and record the dirty deed */ 735550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 735650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decFinalize */ 735750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 735850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 735950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decSetOverflow -- set number to proper overflow value */ 736050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 736150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number (used for sign [only] and result) */ 736250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context [used for the rounding mode, etc.] */ 736350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status contains the current status to be updated */ 736450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 736550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This sets the sign of a number and sets its value to either */ 736650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Infinity or the maximum finite value, depending on the sign of */ 736750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn and the rounding mode, following IEEE 754 rules. */ 736850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 736950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetOverflow(decNumber *dn, decContext *set, uInt *status) { 737050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag needmax=0; /* result is maximum finite value */ 737150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte sign=dn->bits&DECNEG; /* clean and save sign bit */ 737250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 737350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(dn)) { /* zero does not overflow magnitude */ 737450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int emax=set->emax; /* limit value */ 737550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->clamp) emax-=set->digits-1; /* lower if clamping */ 737650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent>emax) { /* clamp required */ 737750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=emax; 737850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Clamped; 737950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 738050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 738150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 738250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 738350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(dn); 738450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho switch (set->round) { 738550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_DOWN: { 738650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needmax=1; /* never Infinity */ 738750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-d */ 738850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_05UP: { 738950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho needmax=1; /* never Infinity */ 739050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-05 */ 739150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_CEILING: { 739250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (sign) needmax=1; /* Infinity if non-negative */ 739350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-c */ 739450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case DEC_ROUND_FLOOR: { 739550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!sign) needmax=1; /* Infinity if negative */ 739650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break;} /* r-f */ 739750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho default: break; /* Infinity in all other cases */ 739850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 739950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (needmax) { 740050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetMaxValue(dn, set); 740150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=sign; /* set sign */ 740250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 740350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else dn->bits=sign|DECINF; /* Value is +/-Infinity */ 740450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Overflow | DEC_Inexact | DEC_Rounded; 740550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decSetOverflow */ 740650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 740750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 740850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decSetMaxValue -- set number to +Nmax (maximum normal value) */ 740950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 741050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to set */ 741150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context [used for digits and emax] */ 741250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 741350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This sets the number to the maximum positive value. */ 741450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 741550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetMaxValue(decNumber *dn, decContext *set) { 741650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up; /* work */ 741750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int count=set->digits; /* nines to add */ 741850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=count; 741950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* fill in all nines to set maximum value */ 742050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=dn->lsu; ; up++) { 742150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count>DECDPUN) *up=DECDPUNMAX; /* unit full o'nines */ 742250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* this is the msu */ 742350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *up=(Unit)(powers[count]-1); 742450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 742550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 742650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=DECDPUN; /* filled those digits */ 742750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* up */ 742850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=0; /* + sign */ 742950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=set->emax-set->digits+1; 743050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decSetMaxValue */ 743150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 743250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 743350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decSetSubnormal -- process value whose exponent is <Emin */ 743450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 743550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number (used as input as well as output; it may have */ 743650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* an allowed subnormal value, which may need to be rounded) */ 743750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context [used for the rounding mode] */ 743850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* residue is any pending residue */ 743950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status contains the current status to be updated */ 744050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 744150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If subset mode, set result to zero and set Underflow flags. */ 744250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 744350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Value may be zero with a low exponent; this does not set Subnormal */ 744450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* but the exponent will be clamped to Etiny. */ 744550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 744650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Otherwise ensure exponent is not out of range, and round as */ 744750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* necessary. Underflow is set if the result is Inexact. */ 744850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 744950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decSetSubnormal(decNumber *dn, decContext *set, Int *residue, 745050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 745150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decContext workset; /* work */ 745250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int etiny, adjust; /* .. */ 745350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 745450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECSUBSET 745550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* simple set to zero and 'hard underflow' for subset */ 745650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!set->extended) { 745750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(dn); 745850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* always full overflow */ 745950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded; 746050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 746150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 746250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 746350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 746450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Full arithmetic -- allow subnormals, rounded to minimum exponent */ 746550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (Etiny) if needed */ 746650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho etiny=set->emin-(set->digits-1); /* smallest allowed exponent */ 746750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 746850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ISZERO(dn) { /* value is zero */ 746950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* residue can never be non-zero here */ 747050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 747150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*residue!=0) { 747250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("++ Subnormal 0 residue %ld\n", (LI)*residue); 747350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation; 747450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 747550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 747650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent<etiny) { /* clamp required */ 747750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent=etiny; 747850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Clamped; 747950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 748050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 748150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 748250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 748350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Subnormal; /* have a non-zero subnormal */ 748450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adjust=etiny-dn->exponent; /* calculate digits to remove */ 748550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (adjust<=0) { /* not out of range; unrounded */ 748650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* residue can never be non-zero here, except in the Nmin-residue */ 748750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* case (which is a subnormal result), so can take fast-path here */ 748850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it may already be inexact (from setting the coefficient) */ 748950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*status&DEC_Inexact) *status|=DEC_Underflow; 749050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 749150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 749250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 749350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* adjust>0, so need to rescale the result so exponent becomes Etiny */ 749450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [this code is similar to that in rescale] */ 749550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset=*set; /* clone rounding, etc. */ 749650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.digits=dn->digits-adjust; /* set requested length */ 749750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho workset.emin-=adjust; /* and adjust emin to match */ 749850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [note that the latter can be <1, here, similar to Rescale case] */ 749950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decSetCoeff(dn, &workset, dn->lsu, dn->digits, residue, status); 750050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decApplyRound(dn, &workset, *residue, status); 750150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 750250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Use 754 default rule: Underflow is set iff Inexact */ 750350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [independent of whether trapped] */ 750450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*status&DEC_Inexact) *status|=DEC_Underflow; 750550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 750650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if rounded up a 999s case, exponent will be off by one; adjust */ 750750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* back if so [it will fit, because it was shortened earlier] */ 750850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent>etiny) { 750950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=decShiftToMost(dn->lsu, dn->digits, 1); 751050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->exponent--; /* (re)adjust the exponent. */ 751150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 751250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 751350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if rounded to zero, it is by definition clamped... */ 751450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(dn)) *status|=DEC_Clamped; 751550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decSetSubnormal */ 751650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 751750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 751850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCheckMath - check entry conditions for a math function */ 751950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 752050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This checks the context and the operand */ 752150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 752250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is the operand to check */ 752350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context to check */ 752450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status is unchanged if both are good */ 752550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 752650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns non-zero if status is changed, 0 otherwise */ 752750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 752850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Restrictions enforced: */ 752950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 753050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* digits, emax, and -emin in the context must be less than */ 753150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* DEC_MAX_MATH (999999), and A must be within these bounds if */ 753250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* non-zero. Invalid_operation is set in the status if a */ 753350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* restriction is violated. */ 753450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 753550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic uInt decCheckMath(const decNumber *rhs, decContext *set, 753650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 753750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt save=*status; /* record */ 753850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set->digits>DEC_MAX_MATH 753950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || set->emax>DEC_MAX_MATH 754050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || -set->emin>DEC_MAX_MATH) *status|=DEC_Invalid_context; 754150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if ((rhs->digits>DEC_MAX_MATH 754250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || rhs->exponent+rhs->digits>DEC_MAX_MATH+1 754350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || rhs->exponent+rhs->digits<2*(1-DEC_MAX_MATH)) 754450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && !ISZERO(rhs)) *status|=DEC_Invalid_operation; 754550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return (*status!=save); 754650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decCheckMath */ 754750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 754850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 754950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decGetInt -- get integer from a number */ 755050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 755150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number [which will not be altered] */ 755250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 755350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns one of: */ 755450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* BADINT if there is a non-zero fraction */ 755550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the converted integer */ 755650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* BIGEVEN if the integer is even and magnitude > 2*10**9 */ 755750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* BIGODD if the integer is odd and magnitude > 2*10**9 */ 755850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 755950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This checks and gets a whole number from the input decNumber. */ 756050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The sign can be determined from dn by the caller when BIGEVEN or */ 756150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* BIGODD is returned. */ 756250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 756350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decGetInt(const decNumber *dn) { 756450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int theInt; /* result accumulator */ 756550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up; /* work */ 756650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int got; /* digits (real or not) processed */ 756750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ilength=dn->digits+dn->exponent; /* integral length */ 756850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag neg=decNumberIsNegative(dn); /* 1 if -ve */ 756950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 757050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The number must be an integer that fits in 10 digits */ 757150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Assert, here, that 10 is enough for any rescale Etiny */ 757250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DEC_MAX_EMAX > 999999999 757350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #error GetInt may need updating [for Emax] 757450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 757550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DEC_MIN_EMIN < -999999999 757650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #error GetInt may need updating [for Emin] 757750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 757850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ISZERO(dn)) return 0; /* zeros are OK, with any exponent */ 757950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 758050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=dn->lsu; /* ready for lsu */ 758150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho theInt=0; /* ready to accumulate */ 758250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent>=0) { /* relatively easy */ 758350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* no fractional part [usual]; allow for positive exponent */ 758450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho got=dn->exponent; 758550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 758650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* -ve exponent; some fractional part to check and discard */ 758750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int count=-dn->exponent; /* digits to discard */ 758850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* spin up whole units until reach the Unit with the unit digit */ 758950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; count>=DECDPUN; up++) { 759050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up!=0) return BADINT; /* non-zero Unit to discard */ 759150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho count-=DECDPUN; 759250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 759350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (count==0) got=0; /* [a multiple of DECDPUN] */ 759450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* [not multiple of DECDPUN] */ 759550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int rem; /* work */ 759650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* slice off fraction digits and check for non-zero */ 759750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN<=4 759850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho theInt=QUOT10(*up, count); 759950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=*up-theInt*powers[count]; 760050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 760150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho rem=*up%powers[count]; /* slice off discards */ 760250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho theInt=*up/powers[count]; 760350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 760450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (rem!=0) return BADINT; /* non-zero fraction */ 760550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* it looks good */ 760650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho got=DECDPUN-count; /* number of digits so far */ 760750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up++; /* ready for next */ 760850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 760950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 761050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now it's known there's no fractional part */ 761150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 761250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* tricky code now, to accumulate up to 9.3 digits */ 761350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (got==0) {theInt=*up; got+=DECDPUN; up++;} /* ensure lsu is there */ 761450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 761550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ilength<11) { 761650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int save=theInt; 761750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* collect any remaining unit(s) */ 761850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; got<ilength; up++) { 761950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho theInt+=*up*powers[got]; 762050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho got+=DECDPUN; 762150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 762250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ilength==10) { /* need to check for wrap */ 762350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (theInt/(Int)powers[got-DECDPUN]!=(Int)*(up-1)) ilength=11; 762450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [that test also disallows the BADINT result case] */ 762550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (neg && theInt>1999999997) ilength=11; 762650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (!neg && theInt>999999999) ilength=11; 762750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ilength==11) theInt=save; /* restore correct low bit */ 762850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 762950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 763050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 763150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ilength>10) { /* too big */ 763250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (theInt&1) return BIGODD; /* bottom bit 1 */ 763350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return BIGEVEN; /* bottom bit 0 */ 763450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 763550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 763650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (neg) theInt=-theInt; /* apply sign */ 763750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return theInt; 763850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decGetInt */ 763950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 764050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 764150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decDecap -- decapitate the coefficient of a number */ 764250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 764350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to be decapitated */ 764450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* drop is the number of digits to be removed from the left of dn; */ 764550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* this must be <= dn->digits (if equal, the coefficient is */ 764650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set to 0) */ 764750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 764850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Returns dn; dn->digits will be <= the initial digits less drop */ 764950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* (after removing drop digits there may be leading zero digits */ 765050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* which will also be removed). Only dn->lsu and dn->digits change. */ 765150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 765250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber *decDecap(decNumber *dn, Int drop) { 765350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *msu; /* -> target cut point */ 765450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int cut; /* work */ 765550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (drop>=dn->digits) { /* losing the whole thing */ 765650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 765750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (drop>dn->digits) 765850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("decDecap called with drop>digits [%ld>%ld]\n", 765950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (LI)drop, (LI)dn->digits); 766050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 766150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->lsu[0]=0; 766250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=1; 766350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 766450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 766550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho msu=dn->lsu+D2U(dn->digits-drop)-1; /* -> likely msu */ 766650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cut=MSUDIGITS(dn->digits-drop); /* digits to be in use in msu */ 766750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cut!=DECDPUN) *msu%=powers[cut]; /* clear left digits */ 766850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* that may have left leading zero digits, so do a proper count... */ 766950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->digits=decGetDigits(dn->lsu, msu-dn->lsu+1); 767050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return dn; 767150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decDecap */ 767250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 767350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 767450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decBiStr -- compare string with pairwise options */ 767550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 767650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* targ is the string to compare */ 767750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* str1 is one of the strings to compare against (length may be 0) */ 767850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* str2 is the other; it must be the same length as str1 */ 767950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 768050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns 1 if strings compare equal, (that is, it is the same */ 768150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* length as str1 and str2, and each character of targ is in either */ 768250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* str1 or str2 in the corresponding position), or 0 otherwise */ 768350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 768450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This is used for generic caseless compare, including the awkward */ 768550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* case of the Turkish dotted and dotless Is. Use as (for example): */ 768650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* if (decBiStr(test, "mike", "MIKE")) ... */ 768750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 768850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Flag decBiStr(const char *targ, const char *str1, const char *str2) { 768950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (;;targ++, str1++, str2++) { 769050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*targ!=*str1 && *targ!=*str2) return 0; 769150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* *targ has a match in one (or both, if terminator) */ 769250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*targ=='\0') break; 769350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* forever */ 769450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1; 769550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decBiStr */ 769650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 769750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 769850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNaNs -- handle NaN operand or operands */ 769950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 770050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is the result number */ 770150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is the first operand */ 770250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is the second operand, or NULL if none */ 770350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* context is used to limit payload length */ 770450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status contains the current status */ 770550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns res in case convenient */ 770650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 770750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Called when one or both operands is a NaN, and propagates the */ 770850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* appropriate result to res. When an sNaN is found, it is changed */ 770950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* to a qNaN and Invalid operation is set. */ 771050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 771150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic decNumber * decNaNs(decNumber *res, const decNumber *lhs, 771250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set, 771350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt *status) { 771450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This decision tree ends up with LHS being the source pointer, */ 771550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* and status updated if need be */ 771650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->bits & DECSNAN) 771750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation | DEC_sNaN; 771850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (rhs==NULL); 771950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (rhs->bits & DECSNAN) { 772050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lhs=rhs; 772150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status|=DEC_Invalid_operation | DEC_sNaN; 772250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 772350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (lhs->bits & DECNAN); 772450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else lhs=rhs; 772550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 772650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* propagate the payload */ 772750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lhs->digits<=set->digits) uprv_decNumberCopy(res, lhs); /* easy */ 772850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* too long */ 772950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *ul; 773050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *ur, *uresp1; 773150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* copy safe number of units, then decapitate */ 773250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=lhs->bits; /* need sign etc. */ 773350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uresp1=res->lsu+D2U(set->digits); 773450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (ur=res->lsu, ul=lhs->lsu; ur<uresp1; ur++, ul++) *ur=*ul; 773550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->digits=D2U(set->digits)*DECDPUN; 773650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* maybe still too long */ 773750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->digits>set->digits) decDecap(res, res->digits-set->digits); 773850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 773950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 774050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits&=~DECSNAN; /* convert any sNaN to NaN, while */ 774150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits|=DECNAN; /* .. preserving sign */ 774250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->exponent=0; /* clean exponent */ 774350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* [coefficient was copied/decapitated] */ 774450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 774550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNaNs */ 774650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 774750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 774850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decStatus -- apply non-zero status */ 774950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 775050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to set if error */ 775150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* status contains the current status (not yet in context) */ 775250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context */ 775350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 775450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* If the status is an error status, the number is set to a NaN, */ 775550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* unless the error was an overflow, divide-by-zero, or underflow, */ 775650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* in which case the number will have already been set. */ 775750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 775850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The context status is then updated with the new status. Note that */ 775950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* this may raise a signal, so control may never return from this */ 776050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* routine (hence resources must be recovered before it is called). */ 776150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 776250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decStatus(decNumber *dn, uInt status, decContext *set) { 776350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status & DEC_NaNs) { /* error status -> NaN */ 776450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if cause was an sNaN, clear and propagate [NaN is already set up] */ 776550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status & DEC_sNaN) status&=~DEC_sNaN; 776650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 776750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(dn); /* other error: clean throughout */ 776850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dn->bits=DECNAN; /* and make a quiet NaN */ 776950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 777050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 777150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextSetStatus(set, status); /* [may not return] */ 777250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 777350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decStatus */ 777450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 777550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 777650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decGetDigits -- count digits in a Units array */ 777750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 777850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* uar is the Unit array holding the number (this is often an */ 777950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* accumulator of some sort) */ 778050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* len is the length of the array in units [>=1] */ 778150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 778250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns the number of (significant) digits in the array */ 778350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 778450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* All leading zeros are excluded, except the last if the array has */ 778550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* only zero Units. */ 778650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 778750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This may be called twice during some operations. */ 778850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Int decGetDigits(Unit *uar, Int len) { 778950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Unit *up=uar+(len-1); /* -> msu */ 779050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int digits=(len-1)*DECDPUN+1; /* possible digits excluding msu */ 779150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>4 779250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt const *pow; /* work */ 779350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 779450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (at least 1 in final msu) */ 779550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECCHECK 779650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (len<1) printf("decGetDigits called with len<1 [%ld]\n", (LI)len); 779750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 779850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 779950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; up>=uar; up--) { 780050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up==0) { /* unit is all 0s */ 780150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (digits==1) break; /* a zero has one digit */ 780250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho digits-=DECDPUN; /* adjust for 0 unit */ 780350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue;} 780450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* found the first (most significant) non-zero Unit */ 780550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>1 /* not done yet */ 780650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up<10) break; /* is 1-9 */ 780750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho digits++; 780850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>2 /* not done yet */ 780950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up<100) break; /* is 10-99 */ 781050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho digits++; 781150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>3 /* not done yet */ 781250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up<1000) break; /* is 100-999 */ 781350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho digits++; 781450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN>4 /* count the rest ... */ 781550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (pow=&powers[4]; *up>=*pow; pow++) digits++; 781650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 781750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 781850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 781950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 782050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 782150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* up */ 782250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return digits; 782350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decGetDigits */ 782450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 782550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECTRACE | DECCHECK 782650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 782750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decNumberShow -- display a number [debug aid] */ 782850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to show */ 782950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 783050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Shows: sign, exponent, coefficient (msu first), digits */ 783150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* or: sign, special-value */ 783250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 783350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* this is public so other modules can use it */ 783450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid uprv_decNumberShow(const decNumber *dn) { 783550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up; /* work */ 783650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt u, d; /* .. */ 783750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int cut; /* .. */ 783850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char isign='+'; /* main sign */ 783950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn==NULL) { 784050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("NULL\n"); 784150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return;} 784250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsNegative(dn)) isign='-'; 784350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf(" >> %c ", isign); 784450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECSPECIAL) { /* Is a special value */ 784550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(dn)) printf("Infinity"); 784650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* a NaN */ 784750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits&DECSNAN) printf("sNaN"); /* signalling NaN */ 784850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else printf("NaN"); 784950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 785050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* if coefficient and exponent are 0, no more to do */ 785150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent==0 && dn->digits==1 && *dn->lsu==0) { 785250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("\n"); 785350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return;} 785450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* drop through to report other information */ 785550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf(" "); 785650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 785750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 785850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* now carefully display the coefficient */ 785950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho up=dn->lsu+D2U(dn->digits)-1; /* msu */ 786050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("%ld", (LI)*up); 786150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=up-1; up>=dn->lsu; up--) { 786250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u=*up; 786350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf(":"); 786450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (cut=DECDPUN-1; cut>=0; cut--) { 786550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho d=u/powers[cut]; 786650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u-=d*powers[cut]; 786750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("%ld", (LI)d); 786850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* cut */ 786950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* up */ 787050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent!=0) { 787150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char esign='+'; 787250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent<0) esign='-'; 787350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf(" E%c%ld", esign, (LI)abs(dn->exponent)); 787450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 787550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf(" [%ld]\n", (LI)dn->digits); 787650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decNumberShow */ 787750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 787850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 787950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECTRACE || DECCHECK 788050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 788150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decDumpAr -- display a unit array [debug/check aid] */ 788250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* name is a single-character tag name */ 788350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ar is the array to display */ 788450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* len is the length of the array in Units */ 788550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 788650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decDumpAr(char name, const Unit *ar, Int len) { 788750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int i; 788850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *spec; 788950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECDPUN==9 789050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%09d "; 789150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==8 789250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%08d "; 789350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==7 789450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%07d "; 789550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==6 789650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%06d "; 789750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==5 789850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%05d "; 789950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==4 790050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%04d "; 790150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==3 790250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%03d "; 790350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #elif DECDPUN==2 790450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%02d "; 790550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 790650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho spec="%d "; 790750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 790850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf(" :%c: ", name); 790950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i=len-1; i>=0; i--) { 791050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (i==len-1) printf("%ld ", (LI)ar[i]); 791150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else printf(spec, ar[i]); 791250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 791350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("\n"); 791450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return;} 791550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 791650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 791750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECCHECK 791850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 791950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCheckOperands -- check operand(s) to a routine */ 792050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* res is the result structure (not checked; it will be set to */ 792150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* quiet NaN if error found (and it is not NULL)) */ 792250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* lhs is the first operand (may be DECUNRESU) */ 792350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* rhs is the second (may be DECUNUSED) */ 792450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context (may be DECUNCONT) */ 792550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns 0 if both operands, and the context are clean, or 1 */ 792650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* otherwise (in which case the context will show an error, */ 792750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* unless NULL). Note that res is not cleaned; caller should */ 792850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* handle this so res=NULL case is safe. */ 792950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The caller is expected to abandon immediately if 1 is returned. */ 793050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 793150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Flag decCheckOperands(decNumber *res, const decNumber *lhs, 793250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const decNumber *rhs, decContext *set) { 793350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Flag bad=0; 793450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set==NULL) { /* oops; hopeless */ 793550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 793650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Reference to context is NULL.\n"); 793750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 793850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bad=1; 793950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 794050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else if (set!=DECUNCONT 794150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && (set->digits<1 || set->round>=DEC_ROUND_MAX)) { 794250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bad=1; 794350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 794450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Bad context [digits=%ld round=%ld].\n", 794550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (LI)set->digits, (LI)set->round); 794650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 794750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 794850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { 794950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res==NULL) { 795050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bad=1; 795150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 795250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this one not DECVERB as standard tests include NULL */ 795350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Reference to result is NULL.\n"); 795450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 795550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 795650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!bad && lhs!=DECUNUSED) bad=(decCheckNumber(lhs)); 795750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!bad && rhs!=DECUNUSED) bad=(decCheckNumber(rhs)); 795850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 795950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bad) { 796050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (set!=DECUNCONT) uprv_decContextSetStatus(set, DEC_Invalid_operation); 796150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res!=DECUNRESU && res!=NULL) { 796250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberZero(res); 796350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->bits=DECNAN; /* qNaN */ 796450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 796550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 796650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return bad; 796750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decCheckOperands */ 796850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 796950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 797050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCheckNumber -- check a number */ 797150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to check */ 797250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* returns 0 if the number is clean, or 1 otherwise */ 797350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 797450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The number is considered valid if it could be a result from some */ 797550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* operation in some valid context. */ 797650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 797750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic Flag decCheckNumber(const decNumber *dn) { 797850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const Unit *up; /* work */ 797950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt maxuint; /* .. */ 798050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int ae, d, digits; /* .. */ 798150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Int emin, emax; /* .. */ 798250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 798350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn==NULL) { /* hopeless */ 798450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE 798550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this one not DECVERB as standard tests include NULL */ 798650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Reference to decNumber is NULL.\n"); 798750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 798850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 798950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 799050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* check special values */ 799150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->bits & DECSPECIAL) { 799250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->exponent!=0) { 799350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 799450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Exponent %ld (not 0) for a special value [%02x].\n", 799550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (LI)dn->exponent, dn->bits); 799650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 799750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 799850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 799950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 2003.09.08: NaNs may now have coefficients, so next tests Inf only */ 800050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (decNumberIsInfinite(dn)) { 800150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->digits!=1) { 800250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 800350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Digits %ld (not 1) for an infinity.\n", (LI)dn->digits); 800450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 800550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 800650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*dn->lsu!=0) { 800750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 800850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("LSU %ld (not 0) for an infinity.\n", (LI)*dn->lsu); 800950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 801050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decDumpAr('I', dn->lsu, D2U(dn->digits)); 801150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 801250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* Inf */ 801350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 2002.12.26: negative NaNs can now appear through proposed IEEE */ 801450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* concrete formats (decimal64, etc.). */ 801550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; 801650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 801750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 801850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* check the coefficient */ 801950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->digits<1 || dn->digits>DECNUMMAXP) { 802050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 802150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Digits %ld in number.\n", (LI)dn->digits); 802250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 802350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 802450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 802550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho d=dn->digits; 802650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 802750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (up=dn->lsu; d>0; up++) { 802850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (d>DECDPUN) maxuint=DECDPUNMAX; 802950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho else { /* reached the msu */ 803050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxuint=powers[d]-1; 803150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn->digits>1 && *up<powers[d-1]) { 803250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 803350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Leading 0 in number.\n"); 803450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberShow(dn); 803550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 803650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 803750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 803850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*up>maxuint) { 803950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 804050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Bad Unit [%08lx] in %ld-digit number at offset %ld [maxuint %ld].\n", 804150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (LI)*up, (LI)dn->digits, (LI)(up-dn->lsu), (LI)maxuint); 804250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 804350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 804450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho d-=DECDPUN; 804550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 804650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 804750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* check the exponent. Note that input operands can have exponents */ 804850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* which are out of the set->emin/set->emax and set->digits range */ 804950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* (just as they can have more digits than set->digits). */ 805050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ae=dn->exponent+dn->digits-1; /* adjusted exponent */ 805150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho emax=DECNUMMAXE; 805250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho emin=DECNUMMINE; 805350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho digits=DECNUMMAXP; 805450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ae<emin-(digits-1)) { 805550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 805650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Adjusted exponent underflow [%ld].\n", (LI)ae); 805750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberShow(dn); 805850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 805950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 806050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ae>+emax) { 806150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 806250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Adjusted exponent overflow [%ld].\n", (LI)ae); 806350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberShow(dn); 806450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 806550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1;} 806650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 806750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; /* it's OK */ 806850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decCheckNumber */ 806950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 807050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 807150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decCheckInexact -- check a normal finite inexact result has digits */ 807250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* dn is the number to check */ 807350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* set is the context (for status and precision) */ 807450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* sets Invalid operation, etc., if some digits are missing */ 807550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* [this check is not made for DECSUBSET compilation or when */ 807650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* subnormal is not set] */ 807750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 807850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decCheckInexact(const decNumber *dn, decContext *set) { 807950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if !DECSUBSET && DECEXTFLAG 808050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((set->status & (DEC_Inexact|DEC_Subnormal))==DEC_Inexact 808150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && (set->digits!=dn->digits) && !(dn->bits & DECSPECIAL)) { 808250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #if DECTRACE || DECVERB 808350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("Insufficient digits [%ld] on normal Inexact result.\n", 808450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (LI)dn->digits); 808550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decNumberShow(dn); 808650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 808750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_decContextSetStatus(set, DEC_Invalid_operation); 808850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 808950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #else 809050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* next is a noop for quiet compiler */ 809150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dn!=NULL && dn->digits==0) set->status|=DEC_Invalid_operation; 809250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho #endif 809350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 809450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decCheckInexact */ 809550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 809650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 809750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if DECALLOC 809850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#undef malloc 809950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#undef free 810050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 810150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decMalloc -- accountable allocation routine */ 810250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* n is the number of bytes to allocate */ 810350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 810450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Semantics is the same as the stdlib malloc routine, but bytes */ 810550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* allocated are accounted for globally, and corruption fences are */ 810650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* added before and after the 'actual' storage. */ 810750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 810850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine allocates storage with an extra twelve bytes; 8 are */ 810950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* at the start and hold: */ 811050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 0-3 the original length requested */ 811150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 4-7 buffer corruption detection fence (DECFENCE, x4) */ 811250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The 4 bytes at the end also hold a corruption fence (DECFENCE, x4) */ 811350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 811450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void *decMalloc(size_t n) { 811550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt size=n+12; /* true size */ 811650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho void *alloc; /* -> allocated storage */ 811750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte *b, *b0; /* work */ 811850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt uiwork; /* for macros */ 811950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 812050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alloc=malloc(size); /* -> allocated storage */ 812150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloc==NULL) return NULL; /* out of strorage */ 812250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b0=(uByte *)alloc; /* as bytes */ 812350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAllocBytes+=n; /* account for storage */ 812450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBFROMUI(alloc, n); /* save n */ 812550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* printf(" alloc ++ dAB: %ld (%ld)\n", (LI)decAllocBytes, (LI)n); */ 812650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (b=b0+4; b<b0+8; b++) *b=DECFENCE; 812750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (b=b0+n+8; b<b0+n+12; b++) *b=DECFENCE; 812850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return b0+8; /* -> play area */ 812950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decMalloc */ 813050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 813150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 813250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* decFree -- accountable free routine */ 813350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* alloc is the storage to free */ 813450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* */ 813550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* Semantics is the same as the stdlib malloc routine, except that */ 813650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* the global storage accounting is updated and the fences are */ 813750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* checked to ensure that no routine has written 'out of bounds'. */ 813850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 813950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* This routine first checks that the fences have not been corrupted. */ 814050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* It then frees the storage using the 'truw' storage address (that */ 814150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* is, offset by 8). */ 814250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* ------------------------------------------------------------------ */ 814350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void decFree(void *alloc) { 814450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt n; /* original length */ 814550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uByte *b, *b0; /* work */ 814650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uInt uiwork; /* for macros */ 814750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 814850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (alloc==NULL) return; /* allowed; it's a nop */ 814950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b0=(uByte *)alloc; /* as bytes */ 815050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b0-=8; /* -> true start of storage */ 815150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho n=UBTOUI(b0); /* lift length */ 815250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (b=b0+4; b<b0+8; b++) if (*b!=DECFENCE) 815350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("=== Corrupt byte [%02x] at offset %d from %ld ===\n", *b, 815450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b-b0-8, (LI)b0); 815550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (b=b0+n+8; b<b0+n+12; b++) if (*b!=DECFENCE) 815650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho printf("=== Corrupt byte [%02x] at offset +%d from %ld, n=%ld ===\n", *b, 815750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho b-b0-8, (LI)b0, (LI)n); 815850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho free(b0); /* drop the storage */ 815950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho decAllocBytes-=n; /* account for storage */ 816050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* printf(" free -- dAB: %d (%d)\n", decAllocBytes, -n); */ 816150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } /* decFree */ 816250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define malloc(a) decMalloc(a) 816350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define free(a) decFree(a) 816450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 8165