Add decNumber library

The library adds support for decimal numbers of arbitrary length.
Downloaded from ICU, under ICU 1.8.1 license
http://download.icu-project.org/files/decNumber/decNumber-icu-368.zip
This commit is contained in:
Leonid S. Usov authored and William Langford committed 2019-04-03 22:01:24 -04:00
1 parent 4f58a59f4d
commit b9d2d1f666
36 files changed
+20503

No files matched your search

+38
View File
@@ -68,3 +68,41 @@ WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
jq uses parts of the open source C library "decNumber", which is distribured
under the following license:
ICU License - ICU 1.8.1 and later
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1995-2005 International Business Machines Corporation and others
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, provided that the above
copyright notice(s) and this permission notice appear in all copies of
the Software and that both the above copyright notice(s) and this
permission notice appear in supporting documentation.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Except as contained in this notice, the name of a copyright holder
shall not be used in advertising or otherwise to promote the sale, use
or other dealings in this Software without prior written authorization
of the copyright holder.
+4
View File
@@ -13,6 +13,10 @@ body:
jq is licensed under the MIT license. For all of the gory
details, read the file `COPYING` in the source distribution.
jq uses a C library for decimal number support. This is an ICU 1.8.1
licensed code obtained from the ICU downloads archive
http://download.icu-project.org/files/decNumber/decNumber-icu-368.zip.
### Linux
+45
View File
@@ -0,0 +1,45 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></meta>
<title>ICU License - ICU 1.8.1 and later</title>
</head>
<body>
<h1>ICU License - ICU 1.8.1 and later</h1>
<pre>
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1995-2005 International Business Machines Corporation and others
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, provided that the above
copyright notice(s) and this permission notice appear in all copies of
the Software and that both the above copyright notice(s) and this
permission notice appear in supporting documentation.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Except as contained in this notice, the name of a copyright holder
shall not be used in advertising or otherwise to promote the sale, use
or other dealings in this Software without prior written authorization
of the copyright holder.
--------------------------------------------------------------------------------
All trademarks and registered trademarks mentioned herein are the property of their respective owners.
</pre>
</body>
</html>
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+437
View File
@@ -0,0 +1,437 @@
/* ------------------------------------------------------------------ */
/* Decimal Context module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2009. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises the routines for handling arithmetic */
/* context structures. */
/* ------------------------------------------------------------------ */
#include <string.h> // for strcmp
#include <stdio.h> // for printf if DECCHECK
#include "decContext.h" // context and base types
#include "decNumberLocal.h" // decNumber local types, etc.
/* compile-time endian tester [assumes sizeof(Int)>1] */
static const Int mfcone=1; // constant 1
static const Flag *mfctop=(const Flag *)&mfcone; // -> top byte
#define LITEND *mfctop // named flag; 1=little-endian
/* ------------------------------------------------------------------ */
/* round-for-reround digits */
/* ------------------------------------------------------------------ */
const uByte DECSTICKYTAB[10]={1,1,2,3,4,6,6,7,8,9}; /* used if sticky */
/* ------------------------------------------------------------------ */
/* Powers of ten (powers[n]==10**n, 0<=n<=9) */
/* ------------------------------------------------------------------ */
const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000,
10000000, 100000000, 1000000000};
/* ------------------------------------------------------------------ */
/* decContextClearStatus -- clear bits in current status */
/* */
/* context is the context structure to be queried */
/* mask indicates the bits to be cleared (the status bit that */
/* corresponds to each 1 bit in the mask is cleared) */
/* returns context */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decContext *decContextClearStatus(decContext *context, uInt mask) {
context->status&=~mask;
return context;
} // decContextClearStatus
/* ------------------------------------------------------------------ */
/* decContextDefault -- initialize a context structure */
/* */
/* context is the structure to be initialized */
/* kind selects the required set of default values, one of: */
/* DEC_INIT_BASE -- select ANSI X3-274 defaults */
/* DEC_INIT_DECIMAL32 -- select IEEE 754 defaults, 32-bit */
/* DEC_INIT_DECIMAL64 -- select IEEE 754 defaults, 64-bit */
/* DEC_INIT_DECIMAL128 -- select IEEE 754 defaults, 128-bit */
/* For any other value a valid context is returned, but with */
/* Invalid_operation set in the status field. */
/* returns a context structure with the appropriate initial values. */
/* ------------------------------------------------------------------ */
decContext * decContextDefault(decContext *context, Int kind) {
// set defaults...
context->digits=9; // 9 digits
context->emax=DEC_MAX_EMAX; // 9-digit exponents
context->emin=DEC_MIN_EMIN; // .. balanced
context->round=DEC_ROUND_HALF_UP; // 0.5 rises
context->traps=DEC_Errors; // all but informational
context->status=0; // cleared
context->clamp=0; // no clamping
#if DECSUBSET
context->extended=0; // cleared
#endif
switch (kind) {
case DEC_INIT_BASE:
// [use defaults]
break;
case DEC_INIT_DECIMAL32:
context->digits=7; // digits
context->emax=96; // Emax
context->emin=-95; // Emin
context->round=DEC_ROUND_HALF_EVEN; // 0.5 to nearest even
context->traps=0; // no traps set
context->clamp=1; // clamp exponents
#if DECSUBSET
context->extended=1; // set
#endif
break;
case DEC_INIT_DECIMAL64:
context->digits=16; // digits
context->emax=384; // Emax
context->emin=-383; // Emin
context->round=DEC_ROUND_HALF_EVEN; // 0.5 to nearest even
context->traps=0; // no traps set
context->clamp=1; // clamp exponents
#if DECSUBSET
context->extended=1; // set
#endif
break;
case DEC_INIT_DECIMAL128:
context->digits=34; // digits
context->emax=6144; // Emax
context->emin=-6143; // Emin
context->round=DEC_ROUND_HALF_EVEN; // 0.5 to nearest even
context->traps=0; // no traps set
context->clamp=1; // clamp exponents
#if DECSUBSET
context->extended=1; // set
#endif
break;
default: // invalid Kind
// use defaults, and ..
decContextSetStatus(context, DEC_Invalid_operation); // trap
}
return context;} // decContextDefault
/* ------------------------------------------------------------------ */
/* decContextGetRounding -- return current rounding mode */
/* */
/* context is the context structure to be queried */
/* returns the rounding mode */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
enum rounding decContextGetRounding(decContext *context) {
return context->round;
} // decContextGetRounding
/* ------------------------------------------------------------------ */
/* decContextGetStatus -- return current status */
/* */
/* context is the context structure to be queried */
/* returns status */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
uInt decContextGetStatus(decContext *context) {
return context->status;
} // decContextGetStatus
/* ------------------------------------------------------------------ */
/* decContextRestoreStatus -- restore bits in current status */
/* */
/* context is the context structure to be updated */
/* newstatus is the source for the bits to be restored */
/* mask indicates the bits to be restored (the status bit that */
/* corresponds to each 1 bit in the mask is set to the value of */
/* the correspnding bit in newstatus) */
/* returns context */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decContext *decContextRestoreStatus(decContext *context,
uInt newstatus, uInt mask) {
context->status&=~mask; // clear the selected bits
context->status|=(mask&newstatus); // or in the new bits
return context;
} // decContextRestoreStatus
/* ------------------------------------------------------------------ */
/* decContextSaveStatus -- save bits in current status */
/* */
/* context is the context structure to be queried */
/* mask indicates the bits to be saved (the status bits that */
/* correspond to each 1 bit in the mask are saved) */
/* returns the AND of the mask and the current status */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
uInt decContextSaveStatus(decContext *context, uInt mask) {
return context->status&mask;
} // decContextSaveStatus
/* ------------------------------------------------------------------ */
/* decContextSetRounding -- set current rounding mode */
/* */
/* context is the context structure to be updated */
/* newround is the value which will replace the current mode */
/* returns context */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decContext *decContextSetRounding(decContext *context,
enum rounding newround) {
context->round=newround;
return context;
} // decContextSetRounding
/* ------------------------------------------------------------------ */
/* decContextSetStatus -- set status and raise trap if appropriate */
/* */
/* context is the context structure to be updated */
/* status is the DEC_ exception code */
/* returns the context structure */
/* */
/* Control may never return from this routine, if there is a signal */
/* handler and it takes a long jump. */
/* ------------------------------------------------------------------ */
decContext * decContextSetStatus(decContext *context, uInt status) {
context->status|=status;
if (status & context->traps) raise(SIGFPE);
return context;} // decContextSetStatus
/* ------------------------------------------------------------------ */
/* decContextSetStatusFromString -- set status from a string + trap */
/* */
/* context is the context structure to be updated */
/* string is a string exactly equal to one that might be returned */
/* by decContextStatusToString */
/* */
/* The status bit corresponding to the string is set, and a trap */
/* is raised if appropriate. */
/* */
/* returns the context structure, unless the string is equal to */
/* DEC_Condition_MU or is not recognized. In these cases NULL is */
/* returned. */
/* ------------------------------------------------------------------ */
decContext * decContextSetStatusFromString(decContext *context,
const char *string) {
if (strcmp(string, DEC_Condition_CS)==0)
return decContextSetStatus(context, DEC_Conversion_syntax);
if (strcmp(string, DEC_Condition_DZ)==0)
return decContextSetStatus(context, DEC_Division_by_zero);
if (strcmp(string, DEC_Condition_DI)==0)
return decContextSetStatus(context, DEC_Division_impossible);
if (strcmp(string, DEC_Condition_DU)==0)
return decContextSetStatus(context, DEC_Division_undefined);
if (strcmp(string, DEC_Condition_IE)==0)
return decContextSetStatus(context, DEC_Inexact);
if (strcmp(string, DEC_Condition_IS)==0)
return decContextSetStatus(context, DEC_Insufficient_storage);
if (strcmp(string, DEC_Condition_IC)==0)
return decContextSetStatus(context, DEC_Invalid_context);
if (strcmp(string, DEC_Condition_IO)==0)
return decContextSetStatus(context, DEC_Invalid_operation);
#if DECSUBSET
if (strcmp(string, DEC_Condition_LD)==0)
return decContextSetStatus(context, DEC_Lost_digits);
#endif
if (strcmp(string, DEC_Condition_OV)==0)
return decContextSetStatus(context, DEC_Overflow);
if (strcmp(string, DEC_Condition_PA)==0)
return decContextSetStatus(context, DEC_Clamped);
if (strcmp(string, DEC_Condition_RO)==0)
return decContextSetStatus(context, DEC_Rounded);
if (strcmp(string, DEC_Condition_SU)==0)
return decContextSetStatus(context, DEC_Subnormal);
if (strcmp(string, DEC_Condition_UN)==0)
return decContextSetStatus(context, DEC_Underflow);
if (strcmp(string, DEC_Condition_ZE)==0)
return context;
return NULL; // Multiple status, or unknown
} // decContextSetStatusFromString
/* ------------------------------------------------------------------ */
/* decContextSetStatusFromStringQuiet -- set status from a string */
/* */
/* context is the context structure to be updated */
/* string is a string exactly equal to one that might be returned */
/* by decContextStatusToString */
/* */
/* The status bit corresponding to the string is set; no trap is */
/* raised. */
/* */
/* returns the context structure, unless the string is equal to */
/* DEC_Condition_MU or is not recognized. In these cases NULL is */
/* returned. */
/* ------------------------------------------------------------------ */
decContext * decContextSetStatusFromStringQuiet(decContext *context,
const char *string) {
if (strcmp(string, DEC_Condition_CS)==0)
return decContextSetStatusQuiet(context, DEC_Conversion_syntax);
if (strcmp(string, DEC_Condition_DZ)==0)
return decContextSetStatusQuiet(context, DEC_Division_by_zero);
if (strcmp(string, DEC_Condition_DI)==0)
return decContextSetStatusQuiet(context, DEC_Division_impossible);
if (strcmp(string, DEC_Condition_DU)==0)
return decContextSetStatusQuiet(context, DEC_Division_undefined);
if (strcmp(string, DEC_Condition_IE)==0)
return decContextSetStatusQuiet(context, DEC_Inexact);
if (strcmp(string, DEC_Condition_IS)==0)
return decContextSetStatusQuiet(context, DEC_Insufficient_storage);
if (strcmp(string, DEC_Condition_IC)==0)
return decContextSetStatusQuiet(context, DEC_Invalid_context);
if (strcmp(string, DEC_Condition_IO)==0)
return decContextSetStatusQuiet(context, DEC_Invalid_operation);
#if DECSUBSET
if (strcmp(string, DEC_Condition_LD)==0)
return decContextSetStatusQuiet(context, DEC_Lost_digits);
#endif
if (strcmp(string, DEC_Condition_OV)==0)
return decContextSetStatusQuiet(context, DEC_Overflow);
if (strcmp(string, DEC_Condition_PA)==0)
return decContextSetStatusQuiet(context, DEC_Clamped);
if (strcmp(string, DEC_Condition_RO)==0)
return decContextSetStatusQuiet(context, DEC_Rounded);
if (strcmp(string, DEC_Condition_SU)==0)
return decContextSetStatusQuiet(context, DEC_Subnormal);
if (strcmp(string, DEC_Condition_UN)==0)
return decContextSetStatusQuiet(context, DEC_Underflow);
if (strcmp(string, DEC_Condition_ZE)==0)
return context;
return NULL; // Multiple status, or unknown
} // decContextSetStatusFromStringQuiet
/* ------------------------------------------------------------------ */
/* decContextSetStatusQuiet -- set status without trap */
/* */
/* context is the context structure to be updated */
/* status is the DEC_ exception code */
/* returns the context structure */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decContext * decContextSetStatusQuiet(decContext *context, uInt status) {
context->status|=status;
return context;} // decContextSetStatusQuiet
/* ------------------------------------------------------------------ */
/* decContextStatusToString -- convert status flags to a string */
/* */
/* context is a context with valid status field */
/* */
/* returns a constant string describing the condition. If multiple */
/* (or no) flags are set, a generic constant message is returned. */
/* ------------------------------------------------------------------ */
const char *decContextStatusToString(const decContext *context) {
Int status=context->status;
// test the five IEEE first, as some of the others are ambiguous when
// DECEXTFLAG=0
if (status==DEC_Invalid_operation ) return DEC_Condition_IO;
if (status==DEC_Division_by_zero ) return DEC_Condition_DZ;
if (status==DEC_Overflow ) return DEC_Condition_OV;
if (status==DEC_Underflow ) return DEC_Condition_UN;
if (status==DEC_Inexact ) return DEC_Condition_IE;
if (status==DEC_Division_impossible ) return DEC_Condition_DI;
if (status==DEC_Division_undefined ) return DEC_Condition_DU;
if (status==DEC_Rounded ) return DEC_Condition_RO;
if (status==DEC_Clamped ) return DEC_Condition_PA;
if (status==DEC_Subnormal ) return DEC_Condition_SU;
if (status==DEC_Conversion_syntax ) return DEC_Condition_CS;
if (status==DEC_Insufficient_storage ) return DEC_Condition_IS;
if (status==DEC_Invalid_context ) return DEC_Condition_IC;
#if DECSUBSET
if (status==DEC_Lost_digits ) return DEC_Condition_LD;
#endif
if (status==0 ) return DEC_Condition_ZE;
return DEC_Condition_MU; // Multiple errors
} // decContextStatusToString
/* ------------------------------------------------------------------ */
/* decContextTestEndian -- test whether DECLITEND is set correctly */
/* */
/* quiet is 1 to suppress message; 0 otherwise */
/* returns 0 if DECLITEND is correct */
/* 1 if DECLITEND is incorrect and should be 1 */
/* -1 if DECLITEND is incorrect and should be 0 */
/* */
/* A message is displayed if the return value is not 0 and quiet==0. */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
Int decContextTestEndian(Flag quiet) {
Int res=0; // optimist
uInt dle=(uInt)DECLITEND; // unsign
if (dle>1) dle=1; // ensure 0 or 1
if (LITEND!=DECLITEND) {
if (!quiet) { // always refer to this
#if DECPRINT
const char *adj;
if (LITEND) adj="little";
else adj="big";
printf("Warning: DECLITEND is set to %d, but this computer appears to be %s-endian\n",
DECLITEND, adj);
#endif
}
res=(Int)LITEND-dle;
}
return res;
} // decContextTestEndian
/* ------------------------------------------------------------------ */
/* decContextTestSavedStatus -- test bits in saved status */
/* */
/* oldstatus is the status word to be tested */
/* mask indicates the bits to be tested (the oldstatus bits that */
/* correspond to each 1 bit in the mask are tested) */
/* returns 1 if any of the tested bits are 1, or 0 otherwise */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
uInt decContextTestSavedStatus(uInt oldstatus, uInt mask) {
return (oldstatus&mask)!=0;
} // decContextTestSavedStatus
/* ------------------------------------------------------------------ */
/* decContextTestStatus -- test bits in current status */
/* */
/* context is the context structure to be updated */
/* mask indicates the bits to be tested (the status bits that */
/* correspond to each 1 bit in the mask are tested) */
/* returns 1 if any of the tested bits are 1, or 0 otherwise */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
uInt decContextTestStatus(decContext *context, uInt mask) {
return (context->status&mask)!=0;
} // decContextTestStatus
/* ------------------------------------------------------------------ */
/* decContextZeroStatus -- clear all status bits */
/* */
/* context is the context structure to be updated */
/* returns context */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decContext *decContextZeroStatus(decContext *context) {
context->status=0;
return context;
} // decContextZeroStatus
+254
View File
@@ -0,0 +1,254 @@
/* ------------------------------------------------------------------ */
/* Decimal Context module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* */
/* Context variables must always have valid values: */
/* */
/* status -- [any bits may be cleared, but not set, by user] */
/* round -- must be one of the enumerated rounding modes */
/* */
/* The following variables are implied for fixed size formats (i.e., */
/* they are ignored) but should still be set correctly in case used */
/* with decNumber functions: */
/* */
/* clamp -- must be either 0 or 1 */
/* digits -- must be in the range 1 through 999999999 */
/* emax -- must be in the range 0 through 999999999 */
/* emin -- must be in the range 0 through -999999999 */
/* extended -- must be either 0 or 1 [present only if DECSUBSET] */
/* traps -- only defined bits may be set */
/* */
/* ------------------------------------------------------------------ */
#if !defined(DECCONTEXT)
#define DECCONTEXT
#define DECCNAME "decContext" /* Short name */
#define DECCFULLNAME "Decimal Context Descriptor" /* Verbose name */
#define DECCAUTHOR "Mike Cowlishaw" /* Who to blame */
#if !defined(int32_t)
#include <stdint.h> /* C99 standard integers */
#endif
#include <stdio.h> /* for printf, etc. */
#include <signal.h> /* for traps */
/* Extended flags setting -- set this to 0 to use only IEEE flags */
#if !defined(DECEXTFLAG)
#define DECEXTFLAG 1 /* 1=enable extended flags */
#endif
/* Conditional code flag -- set this to 0 for best performance */
#if !defined(DECSUBSET)
#define DECSUBSET 0 /* 1=enable subset arithmetic */
#endif
/* Context for operations, with associated constants */
enum rounding {
DEC_ROUND_CEILING, /* round towards +infinity */
DEC_ROUND_UP, /* round away from 0 */
DEC_ROUND_HALF_UP, /* 0.5 rounds up */
DEC_ROUND_HALF_EVEN, /* 0.5 rounds to nearest even */
DEC_ROUND_HALF_DOWN, /* 0.5 rounds down */
DEC_ROUND_DOWN, /* round towards 0 (truncate) */
DEC_ROUND_FLOOR, /* round towards -infinity */
DEC_ROUND_05UP, /* round for reround */
DEC_ROUND_MAX /* enum must be less than this */
};
#define DEC_ROUND_DEFAULT DEC_ROUND_HALF_EVEN;
typedef struct {
int32_t digits; /* working precision */
int32_t emax; /* maximum positive exponent */
int32_t emin; /* minimum negative exponent */
enum rounding round; /* rounding mode */
uint32_t traps; /* trap-enabler flags */
uint32_t status; /* status flags */
uint8_t clamp; /* flag: apply IEEE exponent clamp */
#if DECSUBSET
uint8_t extended; /* flag: special-values allowed */
#endif
} decContext;
/* Maxima and Minima for context settings */
#define DEC_MAX_DIGITS 999999999
#define DEC_MIN_DIGITS 1
#define DEC_MAX_EMAX 999999999
#define DEC_MIN_EMAX 0
#define DEC_MAX_EMIN 0
#define DEC_MIN_EMIN -999999999
#define DEC_MAX_MATH 999999 /* max emax, etc., for math funcs. */
/* Classifications for decimal numbers, aligned with 754 (note that */
/* 'normal' and 'subnormal' are meaningful only with a decContext */
/* or a fixed size format). */
enum decClass {
DEC_CLASS_SNAN,
DEC_CLASS_QNAN,
DEC_CLASS_NEG_INF,
DEC_CLASS_NEG_NORMAL,
DEC_CLASS_NEG_SUBNORMAL,
DEC_CLASS_NEG_ZERO,
DEC_CLASS_POS_ZERO,
DEC_CLASS_POS_SUBNORMAL,
DEC_CLASS_POS_NORMAL,
DEC_CLASS_POS_INF
};
/* Strings for the decClasses */
#define DEC_ClassString_SN "sNaN"
#define DEC_ClassString_QN "NaN"
#define DEC_ClassString_NI "-Infinity"
#define DEC_ClassString_NN "-Normal"
#define DEC_ClassString_NS "-Subnormal"
#define DEC_ClassString_NZ "-Zero"
#define DEC_ClassString_PZ "+Zero"
#define DEC_ClassString_PS "+Subnormal"
#define DEC_ClassString_PN "+Normal"
#define DEC_ClassString_PI "+Infinity"
#define DEC_ClassString_UN "Invalid"
/* Trap-enabler and Status flags (exceptional conditions), and */
/* their names. The top byte is reserved for internal use */
#if DECEXTFLAG
/* Extended flags */
#define DEC_Conversion_syntax 0x00000001
#define DEC_Division_by_zero 0x00000002
#define DEC_Division_impossible 0x00000004
#define DEC_Division_undefined 0x00000008
#define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */
#define DEC_Inexact 0x00000020
#define DEC_Invalid_context 0x00000040
#define DEC_Invalid_operation 0x00000080
#if DECSUBSET
#define DEC_Lost_digits 0x00000100
#endif
#define DEC_Overflow 0x00000200
#define DEC_Clamped 0x00000400
#define DEC_Rounded 0x00000800
#define DEC_Subnormal 0x00001000
#define DEC_Underflow 0x00002000
#else
/* IEEE flags only */
#define DEC_Conversion_syntax 0x00000010
#define DEC_Division_by_zero 0x00000002
#define DEC_Division_impossible 0x00000010
#define DEC_Division_undefined 0x00000010
#define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */
#define DEC_Inexact 0x00000001
#define DEC_Invalid_context 0x00000010
#define DEC_Invalid_operation 0x00000010
#if DECSUBSET
#define DEC_Lost_digits 0x00000000
#endif
#define DEC_Overflow 0x00000008
#define DEC_Clamped 0x00000000
#define DEC_Rounded 0x00000000
#define DEC_Subnormal 0x00000000
#define DEC_Underflow 0x00000004
#endif
/* IEEE 754 groupings for the flags */
/* [DEC_Clamped, DEC_Lost_digits, DEC_Rounded, and DEC_Subnormal */
/* are not in IEEE 754] */
#define DEC_IEEE_754_Division_by_zero (DEC_Division_by_zero)
#if DECSUBSET
#define DEC_IEEE_754_Inexact (DEC_Inexact | DEC_Lost_digits)
#else
#define DEC_IEEE_754_Inexact (DEC_Inexact)
#endif
#define DEC_IEEE_754_Invalid_operation (DEC_Conversion_syntax | \
DEC_Division_impossible | \
DEC_Division_undefined | \
DEC_Insufficient_storage | \
DEC_Invalid_context | \
DEC_Invalid_operation)
#define DEC_IEEE_754_Overflow (DEC_Overflow)
#define DEC_IEEE_754_Underflow (DEC_Underflow)
/* flags which are normally errors (result is qNaN, infinite, or 0) */
#define DEC_Errors (DEC_IEEE_754_Division_by_zero | \
DEC_IEEE_754_Invalid_operation | \
DEC_IEEE_754_Overflow | DEC_IEEE_754_Underflow)
/* flags which cause a result to become qNaN */
#define DEC_NaNs DEC_IEEE_754_Invalid_operation
/* flags which are normally for information only (finite results) */
#if DECSUBSET
#define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact \
| DEC_Lost_digits)
#else
#define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact)
#endif
/* IEEE 854 names (for compatibility with older decNumber versions) */
#define DEC_IEEE_854_Division_by_zero DEC_IEEE_754_Division_by_zero
#define DEC_IEEE_854_Inexact DEC_IEEE_754_Inexact
#define DEC_IEEE_854_Invalid_operation DEC_IEEE_754_Invalid_operation
#define DEC_IEEE_854_Overflow DEC_IEEE_754_Overflow
#define DEC_IEEE_854_Underflow DEC_IEEE_754_Underflow
/* Name strings for the exceptional conditions */
#define DEC_Condition_CS "Conversion syntax"
#define DEC_Condition_DZ "Division by zero"
#define DEC_Condition_DI "Division impossible"
#define DEC_Condition_DU "Division undefined"
#define DEC_Condition_IE "Inexact"
#define DEC_Condition_IS "Insufficient storage"
#define DEC_Condition_IC "Invalid context"
#define DEC_Condition_IO "Invalid operation"
#if DECSUBSET
#define DEC_Condition_LD "Lost digits"
#endif
#define DEC_Condition_OV "Overflow"
#define DEC_Condition_PA "Clamped"
#define DEC_Condition_RO "Rounded"
#define DEC_Condition_SU "Subnormal"
#define DEC_Condition_UN "Underflow"
#define DEC_Condition_ZE "No status"
#define DEC_Condition_MU "Multiple status"
#define DEC_Condition_Length 21 /* length of the longest string, */
/* including terminator */
/* Initialization descriptors, used by decContextDefault */
#define DEC_INIT_BASE 0
#define DEC_INIT_DECIMAL32 32
#define DEC_INIT_DECIMAL64 64
#define DEC_INIT_DECIMAL128 128
/* Synonyms */
#define DEC_INIT_DECSINGLE DEC_INIT_DECIMAL32
#define DEC_INIT_DECDOUBLE DEC_INIT_DECIMAL64
#define DEC_INIT_DECQUAD DEC_INIT_DECIMAL128
/* decContext routines */
extern decContext * decContextClearStatus(decContext *, uint32_t);
extern decContext * decContextDefault(decContext *, int32_t);
extern enum rounding decContextGetRounding(decContext *);
extern uint32_t decContextGetStatus(decContext *);
extern decContext * decContextRestoreStatus(decContext *, uint32_t, uint32_t);
extern uint32_t decContextSaveStatus(decContext *, uint32_t);
extern decContext * decContextSetRounding(decContext *, enum rounding);
extern decContext * decContextSetStatus(decContext *, uint32_t);
extern decContext * decContextSetStatusFromString(decContext *, const char *);
extern decContext * decContextSetStatusFromStringQuiet(decContext *, const char *);
extern decContext * decContextSetStatusQuiet(decContext *, uint32_t);
extern const char * decContextStatusToString(const decContext *);
extern int32_t decContextTestEndian(uint8_t);
extern uint32_t decContextTestSavedStatus(uint32_t, uint32_t);
extern uint32_t decContextTestStatus(decContext *, uint32_t);
extern decContext * decContextZeroStatus(decContext *);
#endif
File diff suppressed because it is too large. Load diff
+140
View File
@@ -0,0 +1,140 @@
/* ------------------------------------------------------------------ */
/* decDouble.c -- decDouble operations module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is included in the package as decNumber.pdf. This */
/* document is also available in HTML, together with specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises decDouble operations (including conversions) */
/* ------------------------------------------------------------------ */
#include "decContext.h" // public includes
#include "decDouble.h" // ..
/* Constant mappings for shared code */
#define DECPMAX DECDOUBLE_Pmax
#define DECEMIN DECDOUBLE_Emin
#define DECEMAX DECDOUBLE_Emax
#define DECEMAXD DECDOUBLE_EmaxD
#define DECBYTES DECDOUBLE_Bytes
#define DECSTRING DECDOUBLE_String
#define DECECONL DECDOUBLE_EconL
#define DECBIAS DECDOUBLE_Bias
#define DECLETS DECDOUBLE_Declets
#define DECQTINY (-DECDOUBLE_Bias)
// parameters of next-wider format
#define DECWBYTES DECQUAD_Bytes
#define DECWPMAX DECQUAD_Pmax
#define DECWECONL DECQUAD_EconL
#define DECWBIAS DECQUAD_Bias
/* Type and function mappings for shared code */
#define decFloat decDouble // Type name
#define decFloatWider decQuad // Type name
// Utilities and conversions (binary results, extractors, etc.)
#define decFloatFromBCD decDoubleFromBCD
#define decFloatFromInt32 decDoubleFromInt32
#define decFloatFromPacked decDoubleFromPacked
#define decFloatFromPackedChecked decDoubleFromPackedChecked
#define decFloatFromString decDoubleFromString
#define decFloatFromUInt32 decDoubleFromUInt32
#define decFloatFromWider decDoubleFromWider
#define decFloatGetCoefficient decDoubleGetCoefficient
#define decFloatGetExponent decDoubleGetExponent
#define decFloatSetCoefficient decDoubleSetCoefficient
#define decFloatSetExponent decDoubleSetExponent
#define decFloatShow decDoubleShow
#define decFloatToBCD decDoubleToBCD
#define decFloatToEngString decDoubleToEngString
#define decFloatToInt32 decDoubleToInt32
#define decFloatToInt32Exact decDoubleToInt32Exact
#define decFloatToPacked decDoubleToPacked
#define decFloatToString decDoubleToString
#define decFloatToUInt32 decDoubleToUInt32
#define decFloatToUInt32Exact decDoubleToUInt32Exact
#define decFloatToWider decDoubleToWider
#define decFloatZero decDoubleZero
// Computational (result is a decFloat)
#define decFloatAbs decDoubleAbs
#define decFloatAdd decDoubleAdd
#define decFloatAnd decDoubleAnd
#define decFloatDivide decDoubleDivide
#define decFloatDivideInteger decDoubleDivideInteger
#define decFloatFMA decDoubleFMA
#define decFloatInvert decDoubleInvert
#define decFloatLogB decDoubleLogB
#define decFloatMax decDoubleMax
#define decFloatMaxMag decDoubleMaxMag
#define decFloatMin decDoubleMin
#define decFloatMinMag decDoubleMinMag
#define decFloatMinus decDoubleMinus
#define decFloatMultiply decDoubleMultiply
#define decFloatNextMinus decDoubleNextMinus
#define decFloatNextPlus decDoubleNextPlus
#define decFloatNextToward decDoubleNextToward
#define decFloatOr decDoubleOr
#define decFloatPlus decDoublePlus
#define decFloatQuantize decDoubleQuantize
#define decFloatReduce decDoubleReduce
#define decFloatRemainder decDoubleRemainder
#define decFloatRemainderNear decDoubleRemainderNear
#define decFloatRotate decDoubleRotate
#define decFloatScaleB decDoubleScaleB
#define decFloatShift decDoubleShift
#define decFloatSubtract decDoubleSubtract
#define decFloatToIntegralValue decDoubleToIntegralValue
#define decFloatToIntegralExact decDoubleToIntegralExact
#define decFloatXor decDoubleXor
// Comparisons
#define decFloatCompare decDoubleCompare
#define decFloatCompareSignal decDoubleCompareSignal
#define decFloatCompareTotal decDoubleCompareTotal
#define decFloatCompareTotalMag decDoubleCompareTotalMag
// Copies
#define decFloatCanonical decDoubleCanonical
#define decFloatCopy decDoubleCopy
#define decFloatCopyAbs decDoubleCopyAbs
#define decFloatCopyNegate decDoubleCopyNegate
#define decFloatCopySign decDoubleCopySign
// Non-computational
#define decFloatClass decDoubleClass
#define decFloatClassString decDoubleClassString
#define decFloatDigits decDoubleDigits
#define decFloatIsCanonical decDoubleIsCanonical
#define decFloatIsFinite decDoubleIsFinite
#define decFloatIsInfinite decDoubleIsInfinite
#define decFloatIsInteger decDoubleIsInteger
#define decFloatIsLogical decDoubleIsLogical
#define decFloatIsNaN decDoubleIsNaN
#define decFloatIsNegative decDoubleIsNegative
#define decFloatIsNormal decDoubleIsNormal
#define decFloatIsPositive decDoubleIsPositive
#define decFloatIsSignaling decDoubleIsSignaling
#define decFloatIsSignalling decDoubleIsSignalling
#define decFloatIsSigned decDoubleIsSigned
#define decFloatIsSubnormal decDoubleIsSubnormal
#define decFloatIsZero decDoubleIsZero
#define decFloatRadix decDoubleRadix
#define decFloatSameQuantum decDoubleSameQuantum
#define decFloatVersion decDoubleVersion
#include "decNumberLocal.h" // local includes (need DECPMAX)
#include "decCommon.c" // non-arithmetic decFloat routines
#include "decBasic.c" // basic formats routines
+155
View File
@@ -0,0 +1,155 @@
/* ------------------------------------------------------------------ */
/* decDouble.h -- Decimal 64-bit format module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is included in the package as decNumber.pdf. This */
/* document is also available in HTML, together with specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
#if !defined(DECDOUBLE)
#define DECDOUBLE
#define DECDOUBLENAME "decimalDouble" /* Short name */
#define DECDOUBLETITLE "Decimal 64-bit datum" /* Verbose name */
#define DECDOUBLEAUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decDoubles */
#define DECDOUBLE_Bytes 8 /* length */
#define DECDOUBLE_Pmax 16 /* maximum precision (digits) */
#define DECDOUBLE_Emin -383 /* minimum adjusted exponent */
#define DECDOUBLE_Emax 384 /* maximum adjusted exponent */
#define DECDOUBLE_EmaxD 3 /* maximum exponent digits */
#define DECDOUBLE_Bias 398 /* bias for the exponent */
#define DECDOUBLE_String 25 /* maximum string length, +1 */
#define DECDOUBLE_EconL 8 /* exponent continuation length */
#define DECDOUBLE_Declets 5 /* count of declets */
/* highest biased exponent (Elimit-1) */
#define DECDOUBLE_Ehigh (DECDOUBLE_Emax + DECDOUBLE_Bias - (DECDOUBLE_Pmax-1))
/* Required includes */
#include "decContext.h"
#include "decQuad.h"
/* The decDouble decimal 64-bit type, accessible by all sizes */
typedef union {
uint8_t bytes[DECDOUBLE_Bytes]; /* fields: 1, 5, 8, 50 bits */
uint16_t shorts[DECDOUBLE_Bytes/2];
uint32_t words[DECDOUBLE_Bytes/4];
#if DECUSE64
uint64_t longs[DECDOUBLE_Bytes/8];
#endif
} decDouble;
/* ---------------------------------------------------------------- */
/* Routines -- implemented as decFloat routines in common files */
/* ---------------------------------------------------------------- */
/* Utilities and conversions, extractors, etc.) */
extern decDouble * decDoubleFromBCD(decDouble *, int32_t, const uint8_t *, int32_t);
extern decDouble * decDoubleFromInt32(decDouble *, int32_t);
extern decDouble * decDoubleFromPacked(decDouble *, int32_t, const uint8_t *);
extern decDouble * decDoubleFromPackedChecked(decDouble *, int32_t, const uint8_t *);
extern decDouble * decDoubleFromString(decDouble *, const char *, decContext *);
extern decDouble * decDoubleFromUInt32(decDouble *, uint32_t);
extern decDouble * decDoubleFromWider(decDouble *, const decQuad *, decContext *);
extern int32_t decDoubleGetCoefficient(const decDouble *, uint8_t *);
extern int32_t decDoubleGetExponent(const decDouble *);
extern decDouble * decDoubleSetCoefficient(decDouble *, const uint8_t *, int32_t);
extern decDouble * decDoubleSetExponent(decDouble *, decContext *, int32_t);
extern void decDoubleShow(const decDouble *, const char *);
extern int32_t decDoubleToBCD(const decDouble *, int32_t *, uint8_t *);
extern char * decDoubleToEngString(const decDouble *, char *);
extern int32_t decDoubleToInt32(const decDouble *, decContext *, enum rounding);
extern int32_t decDoubleToInt32Exact(const decDouble *, decContext *, enum rounding);
extern int32_t decDoubleToPacked(const decDouble *, int32_t *, uint8_t *);
extern char * decDoubleToString(const decDouble *, char *);
extern uint32_t decDoubleToUInt32(const decDouble *, decContext *, enum rounding);
extern uint32_t decDoubleToUInt32Exact(const decDouble *, decContext *, enum rounding);
extern decQuad * decDoubleToWider(const decDouble *, decQuad *);
extern decDouble * decDoubleZero(decDouble *);
/* Computational (result is a decDouble) */
extern decDouble * decDoubleAbs(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleAdd(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleAnd(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleDivide(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleDivideInteger(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleFMA(decDouble *, const decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleInvert(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleLogB(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleMax(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleMaxMag(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleMin(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleMinMag(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleMinus(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleMultiply(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleNextMinus(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleNextPlus(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleNextToward(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleOr(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoublePlus(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleQuantize(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleReduce(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleRemainder(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleRemainderNear(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleRotate(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleScaleB(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleShift(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleSubtract(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleToIntegralValue(decDouble *, const decDouble *, decContext *, enum rounding);
extern decDouble * decDoubleToIntegralExact(decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleXor(decDouble *, const decDouble *, const decDouble *, decContext *);
/* Comparisons */
extern decDouble * decDoubleCompare(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleCompareSignal(decDouble *, const decDouble *, const decDouble *, decContext *);
extern decDouble * decDoubleCompareTotal(decDouble *, const decDouble *, const decDouble *);
extern decDouble * decDoubleCompareTotalMag(decDouble *, const decDouble *, const decDouble *);
/* Copies */
extern decDouble * decDoubleCanonical(decDouble *, const decDouble *);
extern decDouble * decDoubleCopy(decDouble *, const decDouble *);
extern decDouble * decDoubleCopyAbs(decDouble *, const decDouble *);
extern decDouble * decDoubleCopyNegate(decDouble *, const decDouble *);
extern decDouble * decDoubleCopySign(decDouble *, const decDouble *, const decDouble *);
/* Non-computational */
extern enum decClass decDoubleClass(const decDouble *);
extern const char * decDoubleClassString(const decDouble *);
extern uint32_t decDoubleDigits(const decDouble *);
extern uint32_t decDoubleIsCanonical(const decDouble *);
extern uint32_t decDoubleIsFinite(const decDouble *);
extern uint32_t decDoubleIsInfinite(const decDouble *);
extern uint32_t decDoubleIsInteger(const decDouble *);
extern uint32_t decDoubleIsLogical(const decDouble *);
extern uint32_t decDoubleIsNaN(const decDouble *);
extern uint32_t decDoubleIsNegative(const decDouble *);
extern uint32_t decDoubleIsNormal(const decDouble *);
extern uint32_t decDoubleIsPositive(const decDouble *);
extern uint32_t decDoubleIsSignaling(const decDouble *);
extern uint32_t decDoubleIsSignalling(const decDouble *);
extern uint32_t decDoubleIsSigned(const decDouble *);
extern uint32_t decDoubleIsSubnormal(const decDouble *);
extern uint32_t decDoubleIsZero(const decDouble *);
extern uint32_t decDoubleRadix(const decDouble *);
extern uint32_t decDoubleSameQuantum(const decDouble *, const decDouble *);
extern const char * decDoubleVersion(void);
/* decNumber conversions; these are implemented as macros so as not */
/* to force a dependency on decimal64 and decNumber in decDouble. */
/* decDoubleFromNumber returns a decimal64 * to avoid warnings. */
#define decDoubleToNumber(dq, dn) decimal64ToNumber((decimal64 *)(dq), dn)
#define decDoubleFromNumber(dq, dn, set) decimal64FromNumber((decimal64 *)(dq), dn, set)
#endif
File diff suppressed because it is too large. Load diff
+182
View File
@@ -0,0 +1,182 @@
/* ------------------------------------------------------------------ */
/* Decimal Number arithmetic module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
#if !defined(DECNUMBER)
#define DECNUMBER
#define DECNAME "decNumber" /* Short name */
#define DECFULLNAME "Decimal Number Module" /* Verbose name */
#define DECAUTHOR "Mike Cowlishaw" /* Who to blame */
#if !defined(DECCONTEXT)
#include "decContext.h"
#endif
/* Bit settings for decNumber.bits */
#define DECNEG 0x80 /* Sign; 1=negative, 0=positive or zero */
#define DECINF 0x40 /* 1=Infinity */
#define DECNAN 0x20 /* 1=NaN */
#define DECSNAN 0x10 /* 1=sNaN */
/* The remaining bits are reserved; they must be 0 */
#define DECSPECIAL (DECINF|DECNAN|DECSNAN) /* any special value */
/* Define the decNumber data structure. The size and shape of the */
/* units array in the structure is determined by the following */
/* constant. This must not be changed without recompiling the */
/* decNumber library modules. */
#define DECDPUN 3 /* DECimal Digits Per UNit [must be >0 */
/* and <10; 3 or powers of 2 are best]. */
/* DECNUMDIGITS is the default number of digits that can be held in */
/* the structure. If undefined, 1 is assumed and it is assumed */
/* that the structure will be immediately followed by extra space, */
/* as required. DECNUMDIGITS is always >0. */
#if !defined(DECNUMDIGITS)
#define DECNUMDIGITS 1
#endif
/* The size (integer data type) of each unit is determined by the */
/* number of digits it will hold. */
#if DECDPUN<=2
#define decNumberUnit uint8_t
#elif DECDPUN<=4
#define decNumberUnit uint16_t
#else
#define decNumberUnit uint32_t
#endif
/* The number of units needed is ceil(DECNUMDIGITS/DECDPUN) */
#define DECNUMUNITS ((DECNUMDIGITS+DECDPUN-1)/DECDPUN)
/* The data structure... */
typedef struct {
int32_t digits; /* Count of digits in the coefficient; >0 */
int32_t exponent; /* Unadjusted exponent, unbiased, in */
/* range: -1999999997 through 999999999 */
uint8_t bits; /* Indicator bits (see above) */
/* Coefficient, from least significant unit */
decNumberUnit lsu[DECNUMUNITS];
} decNumber;
/* Notes: */
/* 1. If digits is > DECDPUN then there will one or more */
/* decNumberUnits immediately following the first element of lsu.*/
/* These contain the remaining (more significant) digits of the */
/* number, and may be in the lsu array, or may be guaranteed by */
/* some other mechanism (such as being contained in another */
/* structure, or being overlaid on dynamically allocated */
/* storage). */
/* */
/* Each integer of the coefficient (except potentially the last) */
/* contains DECDPUN digits (e.g., a value in the range 0 through */
/* 99999999 if DECDPUN is 8, or 0 through 999 if DECDPUN is 3). */
/* */
/* 2. A decNumber converted to a string may need up to digits+14 */
/* characters. The worst cases (non-exponential and exponential */
/* formats) are -0.00000{9...}# and -9.{9...}E+999999999# */
/* (where # is '\0') */
/* ---------------------------------------------------------------- */
/* decNumber public functions and macros */
/* ---------------------------------------------------------------- */
/* Conversions */
decNumber * decNumberFromInt32(decNumber *, int32_t);
decNumber * decNumberFromUInt32(decNumber *, uint32_t);
decNumber * decNumberFromString(decNumber *, const char *, decContext *);
char * decNumberToString(const decNumber *, char *);
char * decNumberToEngString(const decNumber *, char *);
uint32_t decNumberToUInt32(const decNumber *, decContext *);
int32_t decNumberToInt32(const decNumber *, decContext *);
uint8_t * decNumberGetBCD(const decNumber *, uint8_t *);
decNumber * decNumberSetBCD(decNumber *, const uint8_t *, uint32_t);
/* Operators and elementary functions */
decNumber * decNumberAbs(decNumber *, const decNumber *, decContext *);
decNumber * decNumberAdd(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberAnd(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberCompare(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberCompareSignal(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberCompareTotal(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberCompareTotalMag(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberDivide(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberDivideInteger(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberExp(decNumber *, const decNumber *, decContext *);
decNumber * decNumberFMA(decNumber *, const decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberInvert(decNumber *, const decNumber *, decContext *);
decNumber * decNumberLn(decNumber *, const decNumber *, decContext *);
decNumber * decNumberLogB(decNumber *, const decNumber *, decContext *);
decNumber * decNumberLog10(decNumber *, const decNumber *, decContext *);
decNumber * decNumberMax(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberMaxMag(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberMin(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberMinMag(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberMinus(decNumber *, const decNumber *, decContext *);
decNumber * decNumberMultiply(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberNormalize(decNumber *, const decNumber *, decContext *);
decNumber * decNumberOr(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberPlus(decNumber *, const decNumber *, decContext *);
decNumber * decNumberPower(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberQuantize(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberReduce(decNumber *, const decNumber *, decContext *);
decNumber * decNumberRemainder(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberRemainderNear(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberRescale(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberRotate(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberSameQuantum(decNumber *, const decNumber *, const decNumber *);
decNumber * decNumberScaleB(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberShift(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberSquareRoot(decNumber *, const decNumber *, decContext *);
decNumber * decNumberSubtract(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberToIntegralExact(decNumber *, const decNumber *, decContext *);
decNumber * decNumberToIntegralValue(decNumber *, const decNumber *, decContext *);
decNumber * decNumberXor(decNumber *, const decNumber *, const decNumber *, decContext *);
/* Utilities */
enum decClass decNumberClass(const decNumber *, decContext *);
const char * decNumberClassToString(enum decClass);
decNumber * decNumberCopy(decNumber *, const decNumber *);
decNumber * decNumberCopyAbs(decNumber *, const decNumber *);
decNumber * decNumberCopyNegate(decNumber *, const decNumber *);
decNumber * decNumberCopySign(decNumber *, const decNumber *, const decNumber *);
decNumber * decNumberNextMinus(decNumber *, const decNumber *, decContext *);
decNumber * decNumberNextPlus(decNumber *, const decNumber *, decContext *);
decNumber * decNumberNextToward(decNumber *, const decNumber *, const decNumber *, decContext *);
decNumber * decNumberTrim(decNumber *);
const char * decNumberVersion(void);
decNumber * decNumberZero(decNumber *);
/* Functions for testing decNumbers (normality depends on context) */
int32_t decNumberIsNormal(const decNumber *, decContext *);
int32_t decNumberIsSubnormal(const decNumber *, decContext *);
/* Macros for testing decNumber *dn */
#define decNumberIsCanonical(dn) (1) /* All decNumbers are saintly */
#define decNumberIsFinite(dn) (((dn)->bits&DECSPECIAL)==0)
#define decNumberIsInfinite(dn) (((dn)->bits&DECINF)!=0)
#define decNumberIsNaN(dn) (((dn)->bits&(DECNAN|DECSNAN))!=0)
#define decNumberIsNegative(dn) (((dn)->bits&DECNEG)!=0)
#define decNumberIsQNaN(dn) (((dn)->bits&(DECNAN))!=0)
#define decNumberIsSNaN(dn) (((dn)->bits&(DECSNAN))!=0)
#define decNumberIsSpecial(dn) (((dn)->bits&DECSPECIAL)!=0)
#define decNumberIsZero(dn) (*(dn)->lsu==0 \
&& (dn)->digits==1 \
&& (((dn)->bits&DECSPECIAL)==0))
#define decNumberRadix(dn) (10)
#endif
+757
View File
@@ -0,0 +1,757 @@
/* ------------------------------------------------------------------ */
/* decNumber package local type, tuning, and macro definitions */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This header file is included by all modules in the decNumber */
/* library, and contains local type definitions, tuning parameters, */
/* etc. It should not need to be used by application programs. */
/* decNumber.h or one of decDouble (etc.) must be included first. */
/* ------------------------------------------------------------------ */
#if !defined(DECNUMBERLOC)
#define DECNUMBERLOC
#define DECVERSION "decNumber 3.68" /* Package Version [16 max.] */
#define DECNLAUTHOR "Mike Cowlishaw" /* Who to blame */
#include <stdlib.h> /* for abs */
#include <string.h> /* for memset, strcpy */
/* Conditional code flag -- set this to match hardware platform */
#if !defined(DECLITEND)
#define DECLITEND 1 /* 1=little-endian, 0=big-endian */
#endif
/* Conditional code flag -- set this to 1 for best performance */
#if !defined(DECUSE64)
#define DECUSE64 1 /* 1=use int64s, 0=int32 & smaller only */
#endif
/* Conditional code flag -- set this to 0 to exclude printf calls */
#if !defined(DECPRINT)
#define DECPRINT 1 /* 1=allow printf calls; 0=no printf */
#endif
/* Conditional check flags -- set these to 0 for best performance */
#if !defined(DECCHECK)
#define DECCHECK 0 /* 1 to enable robust checking */
#endif
#if !defined(DECALLOC)
#define DECALLOC 0 /* 1 to enable memory accounting */
#endif
#if !defined(DECTRACE)
#define DECTRACE 0 /* 1 to trace certain internals, etc. */
#endif
/* Tuning parameter for decNumber (arbitrary precision) module */
#if !defined(DECBUFFER)
#define DECBUFFER 36 /* Size basis for local buffers. This */
/* should be a common maximum precision */
/* rounded up to a multiple of 4; must */
/* be zero or positive. */
#endif
/* ---------------------------------------------------------------- */
/* Check parameter dependencies */
/* ---------------------------------------------------------------- */
#if DECCHECK & !DECPRINT
#error DECCHECK needs DECPRINT to be useful
#endif
#if DECALLOC & !DECPRINT
#error DECALLOC needs DECPRINT to be useful
#endif
#if DECTRACE & !DECPRINT
#error DECTRACE needs DECPRINT to be useful
#endif
/* ---------------------------------------------------------------- */
/* Definitions for all modules (general-purpose) */
/* ---------------------------------------------------------------- */
/* Local names for common types -- for safety, decNumber modules do */
/* not use int or long directly. */
#define Flag uint8_t
#define Byte int8_t
#define uByte uint8_t
#define Short int16_t
#define uShort uint16_t
#define Int int32_t
#define uInt uint32_t
#define Unit decNumberUnit
#if DECUSE64
#define Long int64_t
#define uLong uint64_t
#endif
/* Development-use definitions */
typedef long int LI; /* for printf arguments only */
#define DECNOINT 0 /* 1 to check no internal use of 'int' */
/* or stdint types */
#if DECNOINT
/* if these interfere with your C includes, do not set DECNOINT */
#define int ? /* enable to ensure that plain C 'int' */
#define long ?? /* .. or 'long' types are not used */
#endif
/* Shared lookup tables */
extern const uByte DECSTICKYTAB[10]; /* re-round digits if sticky */
extern const uInt DECPOWERS[10]; /* powers of ten table */
/* The following are included from decDPD.h */
extern const uShort DPD2BIN[1024]; /* DPD -> 0-999 */
extern const uShort BIN2DPD[1000]; /* 0-999 -> DPD */
extern const uInt DPD2BINK[1024]; /* DPD -> 0-999000 */
extern const uInt DPD2BINM[1024]; /* DPD -> 0-999000000 */
extern const uByte DPD2BCD8[4096]; /* DPD -> ddd + len */
extern const uByte BIN2BCD8[4000]; /* 0-999 -> ddd + len */
extern const uShort BCD2DPD[2458]; /* 0-0x999 -> DPD (0x999=2457)*/
/* LONGMUL32HI -- set w=(u*v)>>32, where w, u, and v are uInts */
/* (that is, sets w to be the high-order word of the 64-bit result; */
/* the low-order word is simply u*v.) */
/* This version is derived from Knuth via Hacker's Delight; */
/* it seems to optimize better than some others tried */
#define LONGMUL32HI(w, u, v) { \
uInt u0, u1, v0, v1, w0, w1, w2, t; \
u0=u & 0xffff; u1=u>>16; \
v0=v & 0xffff; v1=v>>16; \
w0=u0*v0; \
t=u1*v0 + (w0>>16); \
w1=t & 0xffff; w2=t>>16; \
w1=u0*v1 + w1; \
(w)=u1*v1 + w2 + (w1>>16);}
/* ROUNDUP -- round an integer up to a multiple of n */
#define ROUNDUP(i, n) ((((i)+(n)-1)/n)*n)
#define ROUNDUP4(i) (((i)+3)&~3) /* special for n=4 */
/* ROUNDDOWN -- round an integer down to a multiple of n */
#define ROUNDDOWN(i, n) (((i)/n)*n)
#define ROUNDDOWN4(i) ((i)&~3) /* special for n=4 */
/* References to multi-byte sequences under different sizes; these */
/* require locally declared variables, but do not violate strict */
/* aliasing or alignment (as did the UINTAT simple cast to uInt). */
/* Variables needed are uswork, uiwork, etc. [so do not use at same */
/* level in an expression, e.g., UBTOUI(x)==UBTOUI(y) may fail]. */
/* Return a uInt, etc., from bytes starting at a char* or uByte* */
#define UBTOUS(b) (memcpy((void *)&uswork, b, 2), uswork)
#define UBTOUI(b) (memcpy((void *)&uiwork, b, 4), uiwork)
/* Store a uInt, etc., into bytes starting at a char* or uByte*. */
/* Returns i, evaluated, for convenience; has to use uiwork because */
/* i may be an expression. */
#define UBFROMUS(b, i) (uswork=(i), memcpy(b, (void *)&uswork, 2), uswork)
#define UBFROMUI(b, i) (uiwork=(i), memcpy(b, (void *)&uiwork, 4), uiwork)
/* X10 and X100 -- multiply integer i by 10 or 100 */
/* [shifts are usually faster than multiply; could be conditional] */
#define X10(i) (((i)<<1)+((i)<<3))
#define X100(i) (((i)<<2)+((i)<<5)+((i)<<6))
/* MAXI and MINI -- general max & min (not in ANSI) for integers */
#define MAXI(x,y) ((x)<(y)?(y):(x))
#define MINI(x,y) ((x)>(y)?(y):(x))
/* Useful constants */
#define BILLION 1000000000 /* 10**9 */
/* CHARMASK: 0x30303030 for ASCII/UTF8; 0xF0F0F0F0 for EBCDIC */
#define CHARMASK ((((((((uInt)'0')<<8)+'0')<<8)+'0')<<8)+'0')
/* ---------------------------------------------------------------- */
/* Definitions for arbitary-precision modules (only valid after */
/* decNumber.h has been included) */
/* ---------------------------------------------------------------- */
/* Limits and constants */
#define DECNUMMAXP 999999999 /* maximum precision code can handle */
#define DECNUMMAXE 999999999 /* maximum adjusted exponent ditto */
#define DECNUMMINE -999999999 /* minimum adjusted exponent ditto */
#if (DECNUMMAXP != DEC_MAX_DIGITS)
#error Maximum digits mismatch
#endif
#if (DECNUMMAXE != DEC_MAX_EMAX)
#error Maximum exponent mismatch
#endif
#if (DECNUMMINE != DEC_MIN_EMIN)
#error Minimum exponent mismatch
#endif
/* Set DECDPUNMAX -- the maximum integer that fits in DECDPUN */
/* digits, and D2UTABLE -- the initializer for the D2U table */
#if DECDPUN==1
#define DECDPUNMAX 9
#define D2UTABLE {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17, \
18,19,20,21,22,23,24,25,26,27,28,29,30,31,32, \
33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, \
48,49}
#elif DECDPUN==2
#define DECDPUNMAX 99
#define D2UTABLE {0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10, \
11,11,12,12,13,13,14,14,15,15,16,16,17,17,18, \
18,19,19,20,20,21,21,22,22,23,23,24,24,25}
#elif DECDPUN==3
#define DECDPUNMAX 999
#define D2UTABLE {0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7, \
8,8,8,9,9,9,10,10,10,11,11,11,12,12,12,13,13, \
13,14,14,14,15,15,15,16,16,16,17}
#elif DECDPUN==4
#define DECDPUNMAX 9999
#define D2UTABLE {0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6, \
6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,11, \
11,11,11,12,12,12,12,13}
#elif DECDPUN==5
#define DECDPUNMAX 99999
#define D2UTABLE {0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5, \
5,5,5,5,6,6,6,6,6,7,7,7,7,7,8,8,8,8,8,9,9,9, \
9,9,10,10,10,10}
#elif DECDPUN==6
#define DECDPUNMAX 999999
#define D2UTABLE {0,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4, \
4,4,4,5,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,8, \
8,8,8,8,8,9}
#elif DECDPUN==7
#define DECDPUNMAX 9999999
#define D2UTABLE {0,1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,3, \
4,4,4,4,4,4,4,5,5,5,5,5,5,5,6,6,6,6,6,6,6,7, \
7,7,7,7,7,7}
#elif DECDPUN==8
#define DECDPUNMAX 99999999
#define D2UTABLE {0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3, \
3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6, \
6,6,6,6,6,7}
#elif DECDPUN==9
#define DECDPUNMAX 999999999
#define D2UTABLE {0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3, \
3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5, \
5,5,6,6,6,6}
#elif defined(DECDPUN)
#error DECDPUN must be in the range 1-9
#endif
/* ----- Shared data (in decNumber.c) ----- */
/* Public lookup table used by the D2U macro (see below) */
#define DECMAXD2U 49
extern const uByte d2utable[DECMAXD2U+1];
/* ----- Macros ----- */
/* ISZERO -- return true if decNumber dn is a zero */
/* [performance-critical in some situations] */
#define ISZERO(dn) decNumberIsZero(dn) /* now just a local name */
/* D2U -- return the number of Units needed to hold d digits */
/* (runtime version, with table lookaside for small d) */
#if DECDPUN==8
#define D2U(d) ((unsigned)((d)<=DECMAXD2U?d2utable[d]:((d)+7)>>3))
#elif DECDPUN==4
#define D2U(d) ((unsigned)((d)<=DECMAXD2U?d2utable[d]:((d)+3)>>2))
#else
#define D2U(d) ((d)<=DECMAXD2U?d2utable[d]:((d)+DECDPUN-1)/DECDPUN)
#endif
/* SD2U -- static D2U macro (for compile-time calculation) */
#define SD2U(d) (((d)+DECDPUN-1)/DECDPUN)
/* MSUDIGITS -- returns digits in msu, from digits, calculated */
/* using D2U */
#define MSUDIGITS(d) ((d)-(D2U(d)-1)*DECDPUN)
/* D2N -- return the number of decNumber structs that would be */
/* needed to contain that number of digits (and the initial */
/* decNumber struct) safely. Note that one Unit is included in the */
/* initial structure. Used for allocating space that is aligned on */
/* a decNumber struct boundary. */
#define D2N(d) \
((((SD2U(d)-1)*sizeof(Unit))+sizeof(decNumber)*2-1)/sizeof(decNumber))
/* TODIGIT -- macro to remove the leading digit from the unsigned */
/* integer u at column cut (counting from the right, LSD=0) and */
/* place it as an ASCII character into the character pointed to by */
/* c. Note that cut must be <= 9, and the maximum value for u is */
/* 2,000,000,000 (as is needed for negative exponents of */
/* subnormals). The unsigned integer pow is used as a temporary */
/* variable. */
#define TODIGIT(u, cut, c, pow) { \
*(c)='0'; \
pow=DECPOWERS[cut]*2; \
if ((u)>pow) { \
pow*=4; \
if ((u)>=pow) {(u)-=pow; *(c)+=8;} \
pow/=2; \
if ((u)>=pow) {(u)-=pow; *(c)+=4;} \
pow/=2; \
} \
if ((u)>=pow) {(u)-=pow; *(c)+=2;} \
pow/=2; \
if ((u)>=pow) {(u)-=pow; *(c)+=1;} \
}
/* ---------------------------------------------------------------- */
/* Definitions for fixed-precision modules (only valid after */
/* decSingle.h, decDouble.h, or decQuad.h has been included) */
/* ---------------------------------------------------------------- */
/* bcdnum -- a structure describing a format-independent finite */
/* number, whose coefficient is a string of bcd8 uBytes */
typedef struct {
uByte *msd; /* -> most significant digit */
uByte *lsd; /* -> least ditto */
uInt sign; /* 0=positive, DECFLOAT_Sign=negative */
Int exponent; /* Unadjusted signed exponent (q), or */
/* DECFLOAT_NaN etc. for a special */
} bcdnum;
/* Test if exponent or bcdnum exponent must be a special, etc. */
#define EXPISSPECIAL(exp) ((exp)>=DECFLOAT_MinSp)
#define EXPISINF(exp) (exp==DECFLOAT_Inf)
#define EXPISNAN(exp) (exp==DECFLOAT_qNaN || exp==DECFLOAT_sNaN)
#define NUMISSPECIAL(num) (EXPISSPECIAL((num)->exponent))
/* Refer to a 32-bit word or byte in a decFloat (df) by big-endian */
/* (array) notation (the 0 word or byte contains the sign bit), */
/* automatically adjusting for endianness; similarly address a word */
/* in the next-wider format (decFloatWider, or dfw) */
#define DECWORDS (DECBYTES/4)
#define DECWWORDS (DECWBYTES/4)
#if DECLITEND
#define DFBYTE(df, off) ((df)->bytes[DECBYTES-1-(off)])
#define DFWORD(df, off) ((df)->words[DECWORDS-1-(off)])
#define DFWWORD(dfw, off) ((dfw)->words[DECWWORDS-1-(off)])
#else
#define DFBYTE(df, off) ((df)->bytes[off])
#define DFWORD(df, off) ((df)->words[off])
#define DFWWORD(dfw, off) ((dfw)->words[off])
#endif
/* Tests for sign or specials, directly on DECFLOATs */
#define DFISSIGNED(df) ((DFWORD(df, 0)&0x80000000)!=0)
#define DFISSPECIAL(df) ((DFWORD(df, 0)&0x78000000)==0x78000000)
#define DFISINF(df) ((DFWORD(df, 0)&0x7c000000)==0x78000000)
#define DFISNAN(df) ((DFWORD(df, 0)&0x7c000000)==0x7c000000)
#define DFISQNAN(df) ((DFWORD(df, 0)&0x7e000000)==0x7c000000)
#define DFISSNAN(df) ((DFWORD(df, 0)&0x7e000000)==0x7e000000)
/* Shared lookup tables */
extern const uInt DECCOMBMSD[64]; /* Combination field -> MSD */
extern const uInt DECCOMBFROM[48]; /* exp+msd -> Combination */
/* Private generic (utility) routine */
#if DECCHECK || DECTRACE
extern void decShowNum(const bcdnum *, const char *);
#endif
/* Format-dependent macros and constants */
#if defined(DECPMAX)
/* Useful constants */
#define DECPMAX9 (ROUNDUP(DECPMAX, 9)/9) /* 'Pmax' in 10**9s */
/* Top words for a zero */
#define SINGLEZERO 0x22500000
#define DOUBLEZERO 0x22380000
#define QUADZERO 0x22080000
/* [ZEROWORD is defined to be one of these in the DFISZERO macro] */
/* Format-dependent common tests: */
/* DFISZERO -- test for (any) zero */
/* DFISCCZERO -- test for coefficient continuation being zero */
/* DFISCC01 -- test for coefficient contains only 0s and 1s */
/* DFISINT -- test for finite and exponent q=0 */
/* DFISUINT01 -- test for sign=0, finite, exponent q=0, and */
/* MSD=0 or 1 */
/* ZEROWORD is also defined here. */
/* */
/* In DFISZERO the first test checks the least-significant word */
/* (most likely to be non-zero); the penultimate tests MSD and */
/* DPDs in the signword, and the final test excludes specials and */
/* MSD>7. DFISINT similarly has to allow for the two forms of */
/* MSD codes. DFISUINT01 only has to allow for one form of MSD */
/* code. */
#if DECPMAX==7
#define ZEROWORD SINGLEZERO
/* [test macros not needed except for Zero] */
#define DFISZERO(df) ((DFWORD(df, 0)&0x1c0fffff)==0 \
&& (DFWORD(df, 0)&0x60000000)!=0x60000000)
#elif DECPMAX==16
#define ZEROWORD DOUBLEZERO
#define DFISZERO(df) ((DFWORD(df, 1)==0 \
&& (DFWORD(df, 0)&0x1c03ffff)==0 \
&& (DFWORD(df, 0)&0x60000000)!=0x60000000))
#define DFISINT(df) ((DFWORD(df, 0)&0x63fc0000)==0x22380000 \
||(DFWORD(df, 0)&0x7bfc0000)==0x6a380000)
#define DFISUINT01(df) ((DFWORD(df, 0)&0xfbfc0000)==0x22380000)
#define DFISCCZERO(df) (DFWORD(df, 1)==0 \
&& (DFWORD(df, 0)&0x0003ffff)==0)
#define DFISCC01(df) ((DFWORD(df, 0)&~0xfffc9124)==0 \
&& (DFWORD(df, 1)&~0x49124491)==0)
#elif DECPMAX==34
#define ZEROWORD QUADZERO
#define DFISZERO(df) ((DFWORD(df, 3)==0 \
&& DFWORD(df, 2)==0 \
&& DFWORD(df, 1)==0 \
&& (DFWORD(df, 0)&0x1c003fff)==0 \
&& (DFWORD(df, 0)&0x60000000)!=0x60000000))
#define DFISINT(df) ((DFWORD(df, 0)&0x63ffc000)==0x22080000 \
||(DFWORD(df, 0)&0x7bffc000)==0x6a080000)
#define DFISUINT01(df) ((DFWORD(df, 0)&0xfbffc000)==0x22080000)
#define DFISCCZERO(df) (DFWORD(df, 3)==0 \
&& DFWORD(df, 2)==0 \
&& DFWORD(df, 1)==0 \
&& (DFWORD(df, 0)&0x00003fff)==0)
#define DFISCC01(df) ((DFWORD(df, 0)&~0xffffc912)==0 \
&& (DFWORD(df, 1)&~0x44912449)==0 \
&& (DFWORD(df, 2)&~0x12449124)==0 \
&& (DFWORD(df, 3)&~0x49124491)==0)
#endif
/* Macros to test if a certain 10 bits of a uInt or pair of uInts */
/* are a canonical declet [higher or lower bits are ignored]. */
/* declet is at offset 0 (from the right) in a uInt: */
#define CANONDPD(dpd) (((dpd)&0x300)==0 || ((dpd)&0x6e)!=0x6e)
/* declet is at offset k (a multiple of 2) in a uInt: */
#define CANONDPDOFF(dpd, k) (((dpd)&(0x300<<(k)))==0 \
|| ((dpd)&(((uInt)0x6e)<<(k)))!=(((uInt)0x6e)<<(k)))
/* declet is at offset k (a multiple of 2) in a pair of uInts: */
/* [the top 2 bits will always be in the more-significant uInt] */
#define CANONDPDTWO(hi, lo, k) (((hi)&(0x300>>(32-(k))))==0 \
|| ((hi)&(0x6e>>(32-(k))))!=(0x6e>>(32-(k))) \
|| ((lo)&(((uInt)0x6e)<<(k)))!=(((uInt)0x6e)<<(k)))
/* Macro to test whether a full-length (length DECPMAX) BCD8 */
/* coefficient, starting at uByte u, is all zeros */
/* Test just the LSWord first, then the remainder as a sequence */
/* of tests in order to avoid same-level use of UBTOUI */
#if DECPMAX==7
#define ISCOEFFZERO(u) ( \
UBTOUI((u)+DECPMAX-4)==0 \
&& UBTOUS((u)+DECPMAX-6)==0 \
&& *(u)==0)
#elif DECPMAX==16
#define ISCOEFFZERO(u) ( \
UBTOUI((u)+DECPMAX-4)==0 \
&& UBTOUI((u)+DECPMAX-8)==0 \
&& UBTOUI((u)+DECPMAX-12)==0 \
&& UBTOUI(u)==0)
#elif DECPMAX==34
#define ISCOEFFZERO(u) ( \
UBTOUI((u)+DECPMAX-4)==0 \
&& UBTOUI((u)+DECPMAX-8)==0 \
&& UBTOUI((u)+DECPMAX-12)==0 \
&& UBTOUI((u)+DECPMAX-16)==0 \
&& UBTOUI((u)+DECPMAX-20)==0 \
&& UBTOUI((u)+DECPMAX-24)==0 \
&& UBTOUI((u)+DECPMAX-28)==0 \
&& UBTOUI((u)+DECPMAX-32)==0 \
&& UBTOUS(u)==0)
#endif
/* Macros and masks for the sign, exponent continuation, and MSD */
/* Get the sign as DECFLOAT_Sign or 0 */
#define GETSIGN(df) (DFWORD(df, 0)&0x80000000)
/* Get the exponent continuation from a decFloat *df as an Int */
#define GETECON(df) ((Int)((DFWORD((df), 0)&0x03ffffff)>>(32-6-DECECONL)))
/* Ditto, from the next-wider format */
#define GETWECON(df) ((Int)((DFWWORD((df), 0)&0x03ffffff)>>(32-6-DECWECONL)))
/* Get the biased exponent similarly */
#define GETEXP(df) ((Int)(DECCOMBEXP[DFWORD((df), 0)>>26]+GETECON(df)))
/* Get the unbiased exponent similarly */
#define GETEXPUN(df) ((Int)GETEXP(df)-DECBIAS)
/* Get the MSD similarly (as uInt) */
#define GETMSD(df) (DECCOMBMSD[DFWORD((df), 0)>>26])
/* Compile-time computes of the exponent continuation field masks */
/* full exponent continuation field: */
#define ECONMASK ((0x03ffffff>>(32-6-DECECONL))<<(32-6-DECECONL))
/* same, not including its first digit (the qNaN/sNaN selector): */
#define ECONNANMASK ((0x01ffffff>>(32-6-DECECONL))<<(32-6-DECECONL))
/* Macros to decode the coefficient in a finite decFloat *df into */
/* a BCD string (uByte *bcdin) of length DECPMAX uBytes. */
/* In-line sequence to convert least significant 10 bits of uInt */
/* dpd to three BCD8 digits starting at uByte u. Note that an */
/* extra byte is written to the right of the three digits because */
/* four bytes are moved at a time for speed; the alternative */
/* macro moves exactly three bytes (usually slower). */
#define dpd2bcd8(u, dpd) memcpy(u, &DPD2BCD8[((dpd)&0x3ff)*4], 4)
#define dpd2bcd83(u, dpd) memcpy(u, &DPD2BCD8[((dpd)&0x3ff)*4], 3)
/* Decode the declets. After extracting each one, it is decoded */
/* to BCD8 using a table lookup (also used for variable-length */
/* decode). Each DPD decode is 3 bytes BCD8 plus a one-byte */
/* length which is not used, here). Fixed-length 4-byte moves */
/* are fast, however, almost everywhere, and so are used except */
/* for the final three bytes (to avoid overrun). The code below */
/* is 36 instructions for Doubles and about 70 for Quads, even */
/* on IA32. */
/* Two macros are defined for each format: */
/* GETCOEFF extracts the coefficient of the current format */
/* GETWCOEFF extracts the coefficient of the next-wider format. */
/* The latter is a copy of the next-wider GETCOEFF using DFWWORD. */
#if DECPMAX==7
#define GETCOEFF(df, bcd) { \
uInt sourhi=DFWORD(df, 0); \
*(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \
dpd2bcd8(bcd+1, sourhi>>10); \
dpd2bcd83(bcd+4, sourhi);}
#define GETWCOEFF(df, bcd) { \
uInt sourhi=DFWWORD(df, 0); \
uInt sourlo=DFWWORD(df, 1); \
*(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \
dpd2bcd8(bcd+1, sourhi>>8); \
dpd2bcd8(bcd+4, (sourhi<<2) | (sourlo>>30)); \
dpd2bcd8(bcd+7, sourlo>>20); \
dpd2bcd8(bcd+10, sourlo>>10); \
dpd2bcd83(bcd+13, sourlo);}
#elif DECPMAX==16
#define GETCOEFF(df, bcd) { \
uInt sourhi=DFWORD(df, 0); \
uInt sourlo=DFWORD(df, 1); \
*(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \
dpd2bcd8(bcd+1, sourhi>>8); \
dpd2bcd8(bcd+4, (sourhi<<2) | (sourlo>>30)); \
dpd2bcd8(bcd+7, sourlo>>20); \
dpd2bcd8(bcd+10, sourlo>>10); \
dpd2bcd83(bcd+13, sourlo);}
#define GETWCOEFF(df, bcd) { \
uInt sourhi=DFWWORD(df, 0); \
uInt sourmh=DFWWORD(df, 1); \
uInt sourml=DFWWORD(df, 2); \
uInt sourlo=DFWWORD(df, 3); \
*(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \
dpd2bcd8(bcd+1, sourhi>>4); \
dpd2bcd8(bcd+4, ((sourhi)<<6) | (sourmh>>26)); \
dpd2bcd8(bcd+7, sourmh>>16); \
dpd2bcd8(bcd+10, sourmh>>6); \
dpd2bcd8(bcd+13, ((sourmh)<<4) | (sourml>>28)); \
dpd2bcd8(bcd+16, sourml>>18); \
dpd2bcd8(bcd+19, sourml>>8); \
dpd2bcd8(bcd+22, ((sourml)<<2) | (sourlo>>30)); \
dpd2bcd8(bcd+25, sourlo>>20); \
dpd2bcd8(bcd+28, sourlo>>10); \
dpd2bcd83(bcd+31, sourlo);}
#elif DECPMAX==34
#define GETCOEFF(df, bcd) { \
uInt sourhi=DFWORD(df, 0); \
uInt sourmh=DFWORD(df, 1); \
uInt sourml=DFWORD(df, 2); \
uInt sourlo=DFWORD(df, 3); \
*(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \
dpd2bcd8(bcd+1, sourhi>>4); \
dpd2bcd8(bcd+4, ((sourhi)<<6) | (sourmh>>26)); \
dpd2bcd8(bcd+7, sourmh>>16); \
dpd2bcd8(bcd+10, sourmh>>6); \
dpd2bcd8(bcd+13, ((sourmh)<<4) | (sourml>>28)); \
dpd2bcd8(bcd+16, sourml>>18); \
dpd2bcd8(bcd+19, sourml>>8); \
dpd2bcd8(bcd+22, ((sourml)<<2) | (sourlo>>30)); \
dpd2bcd8(bcd+25, sourlo>>20); \
dpd2bcd8(bcd+28, sourlo>>10); \
dpd2bcd83(bcd+31, sourlo);}
#define GETWCOEFF(df, bcd) {??} /* [should never be used] */
#endif
/* Macros to decode the coefficient in a finite decFloat *df into */
/* a base-billion uInt array, with the least-significant */
/* 0-999999999 'digit' at offset 0. */
/* Decode the declets. After extracting each one, it is decoded */
/* to binary using a table lookup. Three tables are used; one */
/* the usual DPD to binary, the other two pre-multiplied by 1000 */
/* and 1000000 to avoid multiplication during decode. These */
/* tables can also be used for multiplying up the MSD as the DPD */
/* code for 0 through 9 is the identity. */
#define DPD2BIN0 DPD2BIN /* for prettier code */
#if DECPMAX==7
#define GETCOEFFBILL(df, buf) { \
uInt sourhi=DFWORD(df, 0); \
(buf)[0]=DPD2BIN0[sourhi&0x3ff] \
+DPD2BINK[(sourhi>>10)&0x3ff] \
+DPD2BINM[DECCOMBMSD[sourhi>>26]];}
#elif DECPMAX==16
#define GETCOEFFBILL(df, buf) { \
uInt sourhi, sourlo; \
sourlo=DFWORD(df, 1); \
(buf)[0]=DPD2BIN0[sourlo&0x3ff] \
+DPD2BINK[(sourlo>>10)&0x3ff] \
+DPD2BINM[(sourlo>>20)&0x3ff]; \
sourhi=DFWORD(df, 0); \
(buf)[1]=DPD2BIN0[((sourhi<<2) | (sourlo>>30))&0x3ff] \
+DPD2BINK[(sourhi>>8)&0x3ff] \
+DPD2BINM[DECCOMBMSD[sourhi>>26]];}
#elif DECPMAX==34
#define GETCOEFFBILL(df, buf) { \
uInt sourhi, sourmh, sourml, sourlo; \
sourlo=DFWORD(df, 3); \
(buf)[0]=DPD2BIN0[sourlo&0x3ff] \
+DPD2BINK[(sourlo>>10)&0x3ff] \
+DPD2BINM[(sourlo>>20)&0x3ff]; \
sourml=DFWORD(df, 2); \
(buf)[1]=DPD2BIN0[((sourml<<2) | (sourlo>>30))&0x3ff] \
+DPD2BINK[(sourml>>8)&0x3ff] \
+DPD2BINM[(sourml>>18)&0x3ff]; \
sourmh=DFWORD(df, 1); \
(buf)[2]=DPD2BIN0[((sourmh<<4) | (sourml>>28))&0x3ff] \
+DPD2BINK[(sourmh>>6)&0x3ff] \
+DPD2BINM[(sourmh>>16)&0x3ff]; \
sourhi=DFWORD(df, 0); \
(buf)[3]=DPD2BIN0[((sourhi<<6) | (sourmh>>26))&0x3ff] \
+DPD2BINK[(sourhi>>4)&0x3ff] \
+DPD2BINM[DECCOMBMSD[sourhi>>26]];}
#endif
/* Macros to decode the coefficient in a finite decFloat *df into */
/* a base-thousand uInt array (of size DECLETS+1, to allow for */
/* the MSD), with the least-significant 0-999 'digit' at offset 0.*/
/* Decode the declets. After extracting each one, it is decoded */
/* to binary using a table lookup. */
#if DECPMAX==7
#define GETCOEFFTHOU(df, buf) { \
uInt sourhi=DFWORD(df, 0); \
(buf)[0]=DPD2BIN[sourhi&0x3ff]; \
(buf)[1]=DPD2BIN[(sourhi>>10)&0x3ff]; \
(buf)[2]=DECCOMBMSD[sourhi>>26];}
#elif DECPMAX==16
#define GETCOEFFTHOU(df, buf) { \
uInt sourhi, sourlo; \
sourlo=DFWORD(df, 1); \
(buf)[0]=DPD2BIN[sourlo&0x3ff]; \
(buf)[1]=DPD2BIN[(sourlo>>10)&0x3ff]; \
(buf)[2]=DPD2BIN[(sourlo>>20)&0x3ff]; \
sourhi=DFWORD(df, 0); \
(buf)[3]=DPD2BIN[((sourhi<<2) | (sourlo>>30))&0x3ff]; \
(buf)[4]=DPD2BIN[(sourhi>>8)&0x3ff]; \
(buf)[5]=DECCOMBMSD[sourhi>>26];}
#elif DECPMAX==34
#define GETCOEFFTHOU(df, buf) { \
uInt sourhi, sourmh, sourml, sourlo; \
sourlo=DFWORD(df, 3); \
(buf)[0]=DPD2BIN[sourlo&0x3ff]; \
(buf)[1]=DPD2BIN[(sourlo>>10)&0x3ff]; \
(buf)[2]=DPD2BIN[(sourlo>>20)&0x3ff]; \
sourml=DFWORD(df, 2); \
(buf)[3]=DPD2BIN[((sourml<<2) | (sourlo>>30))&0x3ff]; \
(buf)[4]=DPD2BIN[(sourml>>8)&0x3ff]; \
(buf)[5]=DPD2BIN[(sourml>>18)&0x3ff]; \
sourmh=DFWORD(df, 1); \
(buf)[6]=DPD2BIN[((sourmh<<4) | (sourml>>28))&0x3ff]; \
(buf)[7]=DPD2BIN[(sourmh>>6)&0x3ff]; \
(buf)[8]=DPD2BIN[(sourmh>>16)&0x3ff]; \
sourhi=DFWORD(df, 0); \
(buf)[9]=DPD2BIN[((sourhi<<6) | (sourmh>>26))&0x3ff]; \
(buf)[10]=DPD2BIN[(sourhi>>4)&0x3ff]; \
(buf)[11]=DECCOMBMSD[sourhi>>26];}
#endif
/* Macros to decode the coefficient in a finite decFloat *df and */
/* add to a base-thousand uInt array (as for GETCOEFFTHOU). */
/* After the addition then most significant 'digit' in the array */
/* might have a value larger then 10 (with a maximum of 19). */
#if DECPMAX==7
#define ADDCOEFFTHOU(df, buf) { \
uInt sourhi=DFWORD(df, 0); \
(buf)[0]+=DPD2BIN[sourhi&0x3ff]; \
if (buf[0]>999) {buf[0]-=1000; buf[1]++;} \
(buf)[1]+=DPD2BIN[(sourhi>>10)&0x3ff]; \
if (buf[1]>999) {buf[1]-=1000; buf[2]++;} \
(buf)[2]+=DECCOMBMSD[sourhi>>26];}
#elif DECPMAX==16
#define ADDCOEFFTHOU(df, buf) { \
uInt sourhi, sourlo; \
sourlo=DFWORD(df, 1); \
(buf)[0]+=DPD2BIN[sourlo&0x3ff]; \
if (buf[0]>999) {buf[0]-=1000; buf[1]++;} \
(buf)[1]+=DPD2BIN[(sourlo>>10)&0x3ff]; \
if (buf[1]>999) {buf[1]-=1000; buf[2]++;} \
(buf)[2]+=DPD2BIN[(sourlo>>20)&0x3ff]; \
if (buf[2]>999) {buf[2]-=1000; buf[3]++;} \
sourhi=DFWORD(df, 0); \
(buf)[3]+=DPD2BIN[((sourhi<<2) | (sourlo>>30))&0x3ff]; \
if (buf[3]>999) {buf[3]-=1000; buf[4]++;} \
(buf)[4]+=DPD2BIN[(sourhi>>8)&0x3ff]; \
if (buf[4]>999) {buf[4]-=1000; buf[5]++;} \
(buf)[5]+=DECCOMBMSD[sourhi>>26];}
#elif DECPMAX==34
#define ADDCOEFFTHOU(df, buf) { \
uInt sourhi, sourmh, sourml, sourlo; \
sourlo=DFWORD(df, 3); \
(buf)[0]+=DPD2BIN[sourlo&0x3ff]; \
if (buf[0]>999) {buf[0]-=1000; buf[1]++;} \
(buf)[1]+=DPD2BIN[(sourlo>>10)&0x3ff]; \
if (buf[1]>999) {buf[1]-=1000; buf[2]++;} \
(buf)[2]+=DPD2BIN[(sourlo>>20)&0x3ff]; \
if (buf[2]>999) {buf[2]-=1000; buf[3]++;} \
sourml=DFWORD(df, 2); \
(buf)[3]+=DPD2BIN[((sourml<<2) | (sourlo>>30))&0x3ff]; \
if (buf[3]>999) {buf[3]-=1000; buf[4]++;} \
(buf)[4]+=DPD2BIN[(sourml>>8)&0x3ff]; \
if (buf[4]>999) {buf[4]-=1000; buf[5]++;} \
(buf)[5]+=DPD2BIN[(sourml>>18)&0x3ff]; \
if (buf[5]>999) {buf[5]-=1000; buf[6]++;} \
sourmh=DFWORD(df, 1); \
(buf)[6]+=DPD2BIN[((sourmh<<4) | (sourml>>28))&0x3ff]; \
if (buf[6]>999) {buf[6]-=1000; buf[7]++;} \
(buf)[7]+=DPD2BIN[(sourmh>>6)&0x3ff]; \
if (buf[7]>999) {buf[7]-=1000; buf[8]++;} \
(buf)[8]+=DPD2BIN[(sourmh>>16)&0x3ff]; \
if (buf[8]>999) {buf[8]-=1000; buf[9]++;} \
sourhi=DFWORD(df, 0); \
(buf)[9]+=DPD2BIN[((sourhi<<6) | (sourmh>>26))&0x3ff]; \
if (buf[9]>999) {buf[9]-=1000; buf[10]++;} \
(buf)[10]+=DPD2BIN[(sourhi>>4)&0x3ff]; \
if (buf[10]>999) {buf[10]-=1000; buf[11]++;} \
(buf)[11]+=DECCOMBMSD[sourhi>>26];}
#endif
/* Set a decFloat to the maximum positive finite number (Nmax) */
#if DECPMAX==7
#define DFSETNMAX(df) \
{DFWORD(df, 0)=0x77f3fcff;}
#elif DECPMAX==16
#define DFSETNMAX(df) \
{DFWORD(df, 0)=0x77fcff3f; \
DFWORD(df, 1)=0xcff3fcff;}
#elif DECPMAX==34
#define DFSETNMAX(df) \
{DFWORD(df, 0)=0x77ffcff3; \
DFWORD(df, 1)=0xfcff3fcf; \
DFWORD(df, 2)=0xf3fcff3f; \
DFWORD(df, 3)=0xcff3fcff;}
#endif
/* [end of format-dependent macros and constants] */
#endif
#else
#error decNumberLocal included more than once
#endif
+220
View File
@@ -0,0 +1,220 @@
/* ------------------------------------------------------------------ */
/* Packed Decimal conversion module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2002. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises the routines for Packed Decimal format */
/* numbers. Conversions are supplied to and from decNumber, which in */
/* turn supports: */
/* conversions to and from string */
/* arithmetic routines */
/* utilities. */
/* Conversions from decNumber to and from densely packed decimal */
/* formats are provided by the decimal32 through decimal128 modules. */
/* ------------------------------------------------------------------ */
#include <string.h> // for NULL
#include "decNumber.h" // base number library
#include "decPacked.h" // packed decimal
#include "decNumberLocal.h" // decNumber local types, etc.
/* ------------------------------------------------------------------ */
/* decPackedFromNumber -- convert decNumber to BCD Packed Decimal */
/* */
/* bcd is the BCD bytes */
/* length is the length of the BCD array */
/* scale is the scale result */
/* dn is the decNumber */
/* returns bcd, or NULL if error */
/* */
/* The number is converted to a BCD packed decimal byte array, */
/* right aligned in the bcd array, whose length is indicated by the */
/* second parameter. The final 4-bit nibble in the array will be a */
/* sign nibble, C (1100) for + and D (1101) for -. Unused bytes and */
/* nibbles to the left of the number are set to 0. */
/* */
/* scale is set to the scale of the number (this is the exponent, */
/* negated). To force the number to a specified scale, first use the */
/* decNumberRescale routine, which will round and change the exponent */
/* as necessary. */
/* */
/* If there is an error (that is, the decNumber has too many digits */
/* to fit in length bytes, or it is a NaN or Infinity), NULL is */
/* returned and the bcd and scale results are unchanged. Otherwise */
/* bcd is returned. */
/* ------------------------------------------------------------------ */
uByte * decPackedFromNumber(uByte *bcd, Int length, Int *scale,
const decNumber *dn) {
const Unit *up=dn->lsu; // Unit array pointer
uByte obyte, *out; // current output byte, and where it goes
Int indigs=dn->digits; // digits processed
uInt cut=DECDPUN; // downcounter per Unit
uInt u=*up; // work
uInt nib; // ..
#if DECDPUN<=4
uInt temp; // ..
#endif
if (dn->digits>length*2-1 // too long ..
||(dn->bits & DECSPECIAL)) return NULL; // .. or special -- hopeless
if (dn->bits&DECNEG) obyte=DECPMINUS; // set the sign ..
else obyte=DECPPLUS;
*scale=-dn->exponent; // .. and scale
// loop from lowest (rightmost) byte
out=bcd+length-1; // -> final byte
for (; out>=bcd; out--) {
if (indigs>0) {
if (cut==0) {
up++;
u=*up;
cut=DECDPUN;
}
#if DECDPUN<=4
temp=(u*6554)>>16; // fast /10
nib=u-X10(temp);
u=temp;
#else
nib=u%10; // cannot use *6554 trick :-(
u=u/10;
#endif
obyte|=(nib<<4);
indigs--;
cut--;
}
*out=obyte;
obyte=0; // assume 0
if (indigs>0) {
if (cut==0) {
up++;
u=*up;
cut=DECDPUN;
}
#if DECDPUN<=4
temp=(u*6554)>>16; // as above
obyte=(uByte)(u-X10(temp));
u=temp;
#else
obyte=(uByte)(u%10);
u=u/10;
#endif
indigs--;
cut--;
}
} // loop
return bcd;
} // decPackedFromNumber
/* ------------------------------------------------------------------ */
/* decPackedToNumber -- convert BCD Packed Decimal to a decNumber */
/* */
/* bcd is the BCD bytes */
/* length is the length of the BCD array */
/* scale is the scale associated with the BCD integer */
/* dn is the decNumber [with space for length*2 digits] */
/* returns dn, or NULL if error */
/* */
/* The BCD packed decimal byte array, together with an associated */
/* scale, is converted to a decNumber. The BCD array is assumed full */
/* of digits, and must be ended by a 4-bit sign nibble in the least */
/* significant four bits of the final byte. */
/* */
/* The scale is used (negated) as the exponent of the decNumber. */
/* Note that zeros may have a sign and/or a scale. */
/* */
/* The decNumber structure is assumed to have sufficient space to */
/* hold the converted number (that is, up to length*2-1 digits), so */
/* no error is possible unless the adjusted exponent is out of range, */
/* no sign nibble was found, or a sign nibble was found before the */
/* final nibble. In these error cases, NULL is returned and the */
/* decNumber will be 0. */
/* ------------------------------------------------------------------ */
decNumber * decPackedToNumber(const uByte *bcd, Int length,
const Int *scale, decNumber *dn) {
const uByte *last=bcd+length-1; // -> last byte
const uByte *first; // -> first non-zero byte
uInt nib; // work nibble
Unit *up=dn->lsu; // output pointer
Int digits; // digits count
Int cut=0; // phase of output
decNumberZero(dn); // default result
last=&bcd[length-1];
nib=*last & 0x0f; // get the sign
if (nib==DECPMINUS || nib==DECPMINUSALT) dn->bits=DECNEG;
else if (nib<=9) return NULL; // not a sign nibble
// skip leading zero bytes [final byte is always non-zero, due to sign]
for (first=bcd; *first==0;) first++;
digits=(last-first)*2+1; // calculate digits ..
if ((*first & 0xf0)==0) digits--; // adjust for leading zero nibble
if (digits!=0) dn->digits=digits; // count of actual digits [if 0,
// leave as 1]
// check the adjusted exponent; note that scale could be unbounded
dn->exponent=-*scale; // set the exponent
if (*scale>=0) { // usual case
if ((dn->digits-*scale-1)<-DECNUMMAXE) { // underflow
decNumberZero(dn);
return NULL;}
}
else { // -ve scale; +ve exponent
// need to be careful to avoid wrap, here, also BADINT case
if ((*scale<-DECNUMMAXE) // overflow even without digits
|| ((dn->digits-*scale-1)>DECNUMMAXE)) { // overflow
decNumberZero(dn);
return NULL;}
}
if (digits==0) return dn; // result was zero
// copy the digits to the number's units, starting at the lsu
// [unrolled]
for (;;) { // forever
// left nibble first
nib=(unsigned)(*last & 0xf0)>>4;
// got a digit, in nib
if (nib>9) {decNumberZero(dn); return NULL;}
if (cut==0) *up=(Unit)nib;
else *up=(Unit)(*up+nib*DECPOWERS[cut]);
digits--;
if (digits==0) break; // got them all
cut++;
if (cut==DECDPUN) {
up++;
cut=0;
}
last--; // ready for next
nib=*last & 0x0f; // get right nibble
if (nib>9) {decNumberZero(dn); return NULL;}
// got a digit, in nib
if (cut==0) *up=(Unit)nib;
else *up=(Unit)(*up+nib*DECPOWERS[cut]);
digits--;
if (digits==0) break; // got them all
cut++;
if (cut==DECDPUN) {
up++;
cut=0;
}
} // forever
return dn;
} // decPackedToNumber
+52
View File
@@ -0,0 +1,52 @@
/* ------------------------------------------------------------------ */
/* Packed Decimal conversion module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
#if !defined(DECPACKED)
#define DECPACKED
#define DECPNAME "decPacked" /* Short name */
#define DECPFULLNAME "Packed Decimal conversions" /* Verbose name */
#define DECPAUTHOR "Mike Cowlishaw" /* Who to blame */
#define DECPACKED_DefP 32 /* default precision */
#ifndef DECNUMDIGITS
#define DECNUMDIGITS DECPACKED_DefP /* size if not already defined*/
#endif
#include "decNumber.h" /* context and number library */
/* Sign nibble constants */
#if !defined(DECPPLUSALT)
#define DECPPLUSALT 0x0A /* alternate plus nibble */
#define DECPMINUSALT 0x0B /* alternate minus nibble */
#define DECPPLUS 0x0C /* preferred plus nibble */
#define DECPMINUS 0x0D /* preferred minus nibble */
#define DECPPLUSALT2 0x0E /* alternate plus nibble */
#define DECPUNSIGNED 0x0F /* alternate plus nibble (unsigned) */
#endif
/* ---------------------------------------------------------------- */
/* decPacked public routines */
/* ---------------------------------------------------------------- */
/* Conversions */
uint8_t * decPackedFromNumber(uint8_t *, int32_t, int32_t *,
const decNumber *);
decNumber * decPackedToNumber(const uint8_t *, int32_t, const int32_t *,
decNumber *);
#endif
+135
View File
@@ -0,0 +1,135 @@
/* ------------------------------------------------------------------ */
/* decQuad.c -- decQuad operations module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is included in the package as decNumber.pdf. This */
/* document is also available in HTML, together with specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises decQuad operations (including conversions) */
/* ------------------------------------------------------------------ */
/* Constant mappings for shared code */
#define DECPMAX DECQUAD_Pmax
#define DECEMIN DECQUAD_Emin
#define DECEMAX DECQUAD_Emax
#define DECEMAXD DECQUAD_EmaxD
#define DECBYTES DECQUAD_Bytes
#define DECSTRING DECQUAD_String
#define DECECONL DECQUAD_EconL
#define DECBIAS DECQUAD_Bias
#define DECLETS DECQUAD_Declets
#define DECQTINY (-DECQUAD_Bias)
/* Type and function mappings for shared code */
#define decFloat decQuad // Type name
// Utilities and conversions (binary results, extractors, etc.)
#define decFloatFromBCD decQuadFromBCD
#define decFloatFromInt32 decQuadFromInt32
#define decFloatFromPacked decQuadFromPacked
#define decFloatFromPackedChecked decQuadFromPackedChecked
#define decFloatFromString decQuadFromString
#define decFloatFromUInt32 decQuadFromUInt32
#define decFloatFromWider decQuadFromWider
#define decFloatGetCoefficient decQuadGetCoefficient
#define decFloatGetExponent decQuadGetExponent
#define decFloatSetCoefficient decQuadSetCoefficient
#define decFloatSetExponent decQuadSetExponent
#define decFloatShow decQuadShow
#define decFloatToBCD decQuadToBCD
#define decFloatToEngString decQuadToEngString
#define decFloatToInt32 decQuadToInt32
#define decFloatToInt32Exact decQuadToInt32Exact
#define decFloatToPacked decQuadToPacked
#define decFloatToString decQuadToString
#define decFloatToUInt32 decQuadToUInt32
#define decFloatToUInt32Exact decQuadToUInt32Exact
#define decFloatToWider decQuadToWider
#define decFloatZero decQuadZero
// Computational (result is a decFloat)
#define decFloatAbs decQuadAbs
#define decFloatAdd decQuadAdd
#define decFloatAnd decQuadAnd
#define decFloatDivide decQuadDivide
#define decFloatDivideInteger decQuadDivideInteger
#define decFloatFMA decQuadFMA
#define decFloatInvert decQuadInvert
#define decFloatLogB decQuadLogB
#define decFloatMax decQuadMax
#define decFloatMaxMag decQuadMaxMag
#define decFloatMin decQuadMin
#define decFloatMinMag decQuadMinMag
#define decFloatMinus decQuadMinus
#define decFloatMultiply decQuadMultiply
#define decFloatNextMinus decQuadNextMinus
#define decFloatNextPlus decQuadNextPlus
#define decFloatNextToward decQuadNextToward
#define decFloatOr decQuadOr
#define decFloatPlus decQuadPlus
#define decFloatQuantize decQuadQuantize
#define decFloatReduce decQuadReduce
#define decFloatRemainder decQuadRemainder
#define decFloatRemainderNear decQuadRemainderNear
#define decFloatRotate decQuadRotate
#define decFloatScaleB decQuadScaleB
#define decFloatShift decQuadShift
#define decFloatSubtract decQuadSubtract
#define decFloatToIntegralValue decQuadToIntegralValue
#define decFloatToIntegralExact decQuadToIntegralExact
#define decFloatXor decQuadXor
// Comparisons
#define decFloatCompare decQuadCompare
#define decFloatCompareSignal decQuadCompareSignal
#define decFloatCompareTotal decQuadCompareTotal
#define decFloatCompareTotalMag decQuadCompareTotalMag
// Copies
#define decFloatCanonical decQuadCanonical
#define decFloatCopy decQuadCopy
#define decFloatCopyAbs decQuadCopyAbs
#define decFloatCopyNegate decQuadCopyNegate
#define decFloatCopySign decQuadCopySign
// Non-computational
#define decFloatClass decQuadClass
#define decFloatClassString decQuadClassString
#define decFloatDigits decQuadDigits
#define decFloatIsCanonical decQuadIsCanonical
#define decFloatIsFinite decQuadIsFinite
#define decFloatIsInfinite decQuadIsInfinite
#define decFloatIsInteger decQuadIsInteger
#define decFloatIsLogical decQuadIsLogical
#define decFloatIsNaN decQuadIsNaN
#define decFloatIsNegative decQuadIsNegative
#define decFloatIsNormal decQuadIsNormal
#define decFloatIsPositive decQuadIsPositive
#define decFloatIsSignaling decQuadIsSignaling
#define decFloatIsSignalling decQuadIsSignalling
#define decFloatIsSigned decQuadIsSigned
#define decFloatIsSubnormal decQuadIsSubnormal
#define decFloatIsZero decQuadIsZero
#define decFloatRadix decQuadRadix
#define decFloatSameQuantum decQuadSameQuantum
#define decFloatVersion decQuadVersion
/* And now the code itself */
#include "decContext.h" // public includes
#include "decQuad.h" // ..
#include "decNumberLocal.h" // local includes (need DECPMAX)
#include "decCommon.c" // non-arithmetic decFloat routines
#include "decBasic.c" // basic formats routines
+177
View File
@@ -0,0 +1,177 @@
/* ------------------------------------------------------------------ */
/* decQuad.h -- Decimal 128-bit format module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2010. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is included in the package as decNumber.pdf. This */
/* document is also available in HTML, together with specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This include file is always included by decSingle and decDouble, */
/* and therefore also holds useful constants used by all three. */
#if !defined(DECQUAD)
#define DECQUAD
#define DECQUADNAME "decimalQuad" /* Short name */
#define DECQUADTITLE "Decimal 128-bit datum" /* Verbose name */
#define DECQUADAUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decQuads */
#define DECQUAD_Bytes 16 /* length */
#define DECQUAD_Pmax 34 /* maximum precision (digits) */
#define DECQUAD_Emin -6143 /* minimum adjusted exponent */
#define DECQUAD_Emax 6144 /* maximum adjusted exponent */
#define DECQUAD_EmaxD 4 /* maximum exponent digits */
#define DECQUAD_Bias 6176 /* bias for the exponent */
#define DECQUAD_String 43 /* maximum string length, +1 */
#define DECQUAD_EconL 12 /* exponent continuation length */
#define DECQUAD_Declets 11 /* count of declets */
/* highest biased exponent (Elimit-1) */
#define DECQUAD_Ehigh (DECQUAD_Emax + DECQUAD_Bias - (DECQUAD_Pmax-1))
/* Required include */
#include "decContext.h"
/* The decQuad decimal 128-bit type, accessible by all sizes */
typedef union {
uint8_t bytes[DECQUAD_Bytes]; /* fields: 1, 5, 12, 110 bits */
uint16_t shorts[DECQUAD_Bytes/2];
uint32_t words[DECQUAD_Bytes/4];
#if DECUSE64
uint64_t longs[DECQUAD_Bytes/8];
#endif
} decQuad;
/* ---------------------------------------------------------------- */
/* Shared constants */
/* ---------------------------------------------------------------- */
/* sign and special values [top 32-bits; last two bits are don't-care
for Infinity on input, last bit don't-care for NaNs] */
#define DECFLOAT_Sign 0x80000000 /* 1 00000 00 Sign */
#define DECFLOAT_NaN 0x7c000000 /* 0 11111 00 NaN generic */
#define DECFLOAT_qNaN 0x7c000000 /* 0 11111 00 qNaN */
#define DECFLOAT_sNaN 0x7e000000 /* 0 11111 10 sNaN */
#define DECFLOAT_Inf 0x78000000 /* 0 11110 00 Infinity */
#define DECFLOAT_MinSp 0x78000000 /* minimum special value */
/* [specials are all >=MinSp] */
/* Sign nibble constants */
#if !defined(DECPPLUSALT)
#define DECPPLUSALT 0x0A /* alternate plus nibble */
#define DECPMINUSALT 0x0B /* alternate minus nibble */
#define DECPPLUS 0x0C /* preferred plus nibble */
#define DECPMINUS 0x0D /* preferred minus nibble */
#define DECPPLUSALT2 0x0E /* alternate plus nibble */
#define DECPUNSIGNED 0x0F /* alternate plus nibble (unsigned) */
#endif
/* ---------------------------------------------------------------- */
/* Routines -- implemented as decFloat routines in common files */
/* ---------------------------------------------------------------- */
/* Utilities and conversions, extractors, etc.) */
extern decQuad * decQuadFromBCD(decQuad *, int32_t, const uint8_t *, int32_t);
extern decQuad * decQuadFromInt32(decQuad *, int32_t);
extern decQuad * decQuadFromPacked(decQuad *, int32_t, const uint8_t *);
extern decQuad * decQuadFromPackedChecked(decQuad *, int32_t, const uint8_t *);
extern decQuad * decQuadFromString(decQuad *, const char *, decContext *);
extern decQuad * decQuadFromUInt32(decQuad *, uint32_t);
extern int32_t decQuadGetCoefficient(const decQuad *, uint8_t *);
extern int32_t decQuadGetExponent(const decQuad *);
extern decQuad * decQuadSetCoefficient(decQuad *, const uint8_t *, int32_t);
extern decQuad * decQuadSetExponent(decQuad *, decContext *, int32_t);
extern void decQuadShow(const decQuad *, const char *);
extern int32_t decQuadToBCD(const decQuad *, int32_t *, uint8_t *);
extern char * decQuadToEngString(const decQuad *, char *);
extern int32_t decQuadToInt32(const decQuad *, decContext *, enum rounding);
extern int32_t decQuadToInt32Exact(const decQuad *, decContext *, enum rounding);
extern int32_t decQuadToPacked(const decQuad *, int32_t *, uint8_t *);
extern char * decQuadToString(const decQuad *, char *);
extern uint32_t decQuadToUInt32(const decQuad *, decContext *, enum rounding);
extern uint32_t decQuadToUInt32Exact(const decQuad *, decContext *, enum rounding);
extern decQuad * decQuadZero(decQuad *);
/* Computational (result is a decQuad) */
extern decQuad * decQuadAbs(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadAdd(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadAnd(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadDivide(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadDivideInteger(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadFMA(decQuad *, const decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadInvert(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadLogB(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadMax(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadMaxMag(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadMin(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadMinMag(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadMinus(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadMultiply(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadNextMinus(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadNextPlus(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadNextToward(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadOr(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadPlus(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadQuantize(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadReduce(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadRemainder(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadRemainderNear(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadRotate(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadScaleB(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadShift(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadSubtract(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadToIntegralValue(decQuad *, const decQuad *, decContext *, enum rounding);
extern decQuad * decQuadToIntegralExact(decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadXor(decQuad *, const decQuad *, const decQuad *, decContext *);
/* Comparisons */
extern decQuad * decQuadCompare(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadCompareSignal(decQuad *, const decQuad *, const decQuad *, decContext *);
extern decQuad * decQuadCompareTotal(decQuad *, const decQuad *, const decQuad *);
extern decQuad * decQuadCompareTotalMag(decQuad *, const decQuad *, const decQuad *);
/* Copies */
extern decQuad * decQuadCanonical(decQuad *, const decQuad *);
extern decQuad * decQuadCopy(decQuad *, const decQuad *);
extern decQuad * decQuadCopyAbs(decQuad *, const decQuad *);
extern decQuad * decQuadCopyNegate(decQuad *, const decQuad *);
extern decQuad * decQuadCopySign(decQuad *, const decQuad *, const decQuad *);
/* Non-computational */
extern enum decClass decQuadClass(const decQuad *);
extern const char * decQuadClassString(const decQuad *);
extern uint32_t decQuadDigits(const decQuad *);
extern uint32_t decQuadIsCanonical(const decQuad *);
extern uint32_t decQuadIsFinite(const decQuad *);
extern uint32_t decQuadIsInteger(const decQuad *);
extern uint32_t decQuadIsLogical(const decQuad *);
extern uint32_t decQuadIsInfinite(const decQuad *);
extern uint32_t decQuadIsNaN(const decQuad *);
extern uint32_t decQuadIsNegative(const decQuad *);
extern uint32_t decQuadIsNormal(const decQuad *);
extern uint32_t decQuadIsPositive(const decQuad *);
extern uint32_t decQuadIsSignaling(const decQuad *);
extern uint32_t decQuadIsSignalling(const decQuad *);
extern uint32_t decQuadIsSigned(const decQuad *);
extern uint32_t decQuadIsSubnormal(const decQuad *);
extern uint32_t decQuadIsZero(const decQuad *);
extern uint32_t decQuadRadix(const decQuad *);
extern uint32_t decQuadSameQuantum(const decQuad *, const decQuad *);
extern const char * decQuadVersion(void);
/* decNumber conversions; these are implemented as macros so as not */
/* to force a dependency on decimal128 and decNumber in decQuad. */
/* decQuadFromNumber returns a decimal128 * to avoid warnings. */
#define decQuadToNumber(dq, dn) decimal128ToNumber((decimal128 *)(dq), dn)
#define decQuadFromNumber(dq, dn, set) decimal128FromNumber((decimal128 *)(dq), dn, set)
#endif
+71
View File
@@ -0,0 +1,71 @@
/* ------------------------------------------------------------------ */
/* decSingle.c -- decSingle operations module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2008. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is included in the package as decNumber.pdf. This */
/* document is also available in HTML, together with specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises decSingle operations (including conversions) */
/* ------------------------------------------------------------------ */
#include "decContext.h" // public includes
#include "decSingle.h" // public includes
/* Constant mappings for shared code */
#define DECPMAX DECSINGLE_Pmax
#define DECEMIN DECSINGLE_Emin
#define DECEMAX DECSINGLE_Emax
#define DECEMAXD DECSINGLE_EmaxD
#define DECBYTES DECSINGLE_Bytes
#define DECSTRING DECSINGLE_String
#define DECECONL DECSINGLE_EconL
#define DECBIAS DECSINGLE_Bias
#define DECLETS DECSINGLE_Declets
#define DECQTINY (-DECSINGLE_Bias)
// parameters of next-wider format
#define DECWBYTES DECDOUBLE_Bytes
#define DECWPMAX DECDOUBLE_Pmax
#define DECWECONL DECDOUBLE_EconL
#define DECWBIAS DECDOUBLE_Bias
/* Type and function mappings for shared code */
#define decFloat decSingle // Type name
#define decFloatWider decDouble // Type name
// Utility (binary results, extractors, etc.)
#define decFloatFromBCD decSingleFromBCD
#define decFloatFromPacked decSingleFromPacked
#define decFloatFromPackedChecked decSingleFromPackedChecked
#define decFloatFromString decSingleFromString
#define decFloatFromWider decSingleFromWider
#define decFloatGetCoefficient decSingleGetCoefficient
#define decFloatGetExponent decSingleGetExponent
#define decFloatSetCoefficient decSingleSetCoefficient
#define decFloatSetExponent decSingleSetExponent
#define decFloatShow decSingleShow
#define decFloatToBCD decSingleToBCD
#define decFloatToEngString decSingleToEngString
#define decFloatToPacked decSingleToPacked
#define decFloatToString decSingleToString
#define decFloatToWider decSingleToWider
#define decFloatZero decSingleZero
// Non-computational
#define decFloatRadix decSingleRadix
#define decFloatVersion decSingleVersion
#include "decNumberLocal.h" // local includes (need DECPMAX)
#include "decCommon.c" // non-basic decFloat routines
// [Do not include decBasic.c for decimal32]
+86
View File
@@ -0,0 +1,86 @@
/* ------------------------------------------------------------------ */
/* decSingle.h -- Decimal 32-bit format module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2008. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is included in the package as decNumber.pdf. This */
/* document is also available in HTML, together with specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
#if !defined(DECSINGLE)
#define DECSINGLE
#define DECSINGLENAME "decSingle" /* Short name */
#define DECSINGLETITLE "Decimal 32-bit datum" /* Verbose name */
#define DECSINGLEAUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decSingles */
#define DECSINGLE_Bytes 4 /* length */
#define DECSINGLE_Pmax 7 /* maximum precision (digits) */
#define DECSINGLE_Emin -95 /* minimum adjusted exponent */
#define DECSINGLE_Emax 96 /* maximum adjusted exponent */
#define DECSINGLE_EmaxD 3 /* maximum exponent digits */
#define DECSINGLE_Bias 101 /* bias for the exponent */
#define DECSINGLE_String 16 /* maximum string length, +1 */
#define DECSINGLE_EconL 6 /* exponent continuation length */
#define DECSINGLE_Declets 2 /* count of declets */
/* highest biased exponent (Elimit-1) */
#define DECSINGLE_Ehigh (DECSINGLE_Emax + DECSINGLE_Bias - (DECSINGLE_Pmax-1))
/* Required includes */
#include "decContext.h"
#include "decQuad.h"
#include "decDouble.h"
/* The decSingle decimal 32-bit type, accessible by all sizes */
typedef union {
uint8_t bytes[DECSINGLE_Bytes]; /* fields: 1, 5, 6, 20 bits */
uint16_t shorts[DECSINGLE_Bytes/2];
uint32_t words[DECSINGLE_Bytes/4];
} decSingle;
/* ---------------------------------------------------------------- */
/* Routines -- implemented as decFloat routines in common files */
/* ---------------------------------------------------------------- */
/* Utilities (binary argument(s) or result, extractors, etc.) */
extern decSingle * decSingleFromBCD(decSingle *, int32_t, const uint8_t *, int32_t);
extern decSingle * decSingleFromPacked(decSingle *, int32_t, const uint8_t *);
extern decSingle * decSingleFromPackedChecked(decSingle *, int32_t, const uint8_t *);
extern decSingle * decSingleFromString(decSingle *, const char *, decContext *);
extern decSingle * decSingleFromWider(decSingle *, const decDouble *, decContext *);
extern int32_t decSingleGetCoefficient(const decSingle *, uint8_t *);
extern int32_t decSingleGetExponent(const decSingle *);
extern decSingle * decSingleSetCoefficient(decSingle *, const uint8_t *, int32_t);
extern decSingle * decSingleSetExponent(decSingle *, decContext *, int32_t);
extern void decSingleShow(const decSingle *, const char *);
extern int32_t decSingleToBCD(const decSingle *, int32_t *, uint8_t *);
extern char * decSingleToEngString(const decSingle *, char *);
extern int32_t decSingleToPacked(const decSingle *, int32_t *, uint8_t *);
extern char * decSingleToString(const decSingle *, char *);
extern decDouble * decSingleToWider(const decSingle *, decDouble *);
extern decSingle * decSingleZero(decSingle *);
/* (No Arithmetic routines for decSingle) */
/* Non-computational */
extern uint32_t decSingleRadix(const decSingle *);
extern const char * decSingleVersion(void);
/* decNumber conversions; these are implemented as macros so as not */
/* to force a dependency on decimal32 and decNumber in decSingle. */
/* decSingleFromNumber returns a decimal32 * to avoid warnings. */
#define decSingleToNumber(dq, dn) decimal32ToNumber((decimal32 *)(dq), dn)
#define decSingleFromNumber(dq, dn, set) decimal32FromNumber((decimal32 *)(dq), dn, set)
#endif
+553
View File
@@ -0,0 +1,553 @@
/* ------------------------------------------------------------------ */
/* Decimal 128-bit format module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2008. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises the routines for decimal128 format numbers. */
/* Conversions are supplied to and from decNumber and String. */
/* */
/* This is used when decNumber provides operations, either for all */
/* operations or as a proxy between decNumber and decSingle. */
/* */
/* Error handling is the same as decNumber (qv.). */
/* ------------------------------------------------------------------ */
#include <string.h> // [for memset/memcpy]
#include <stdio.h> // [for printf]
#define DECNUMDIGITS 34 // make decNumbers with space for 34
#include "decNumber.h" // base number library
#include "decNumberLocal.h" // decNumber local types, etc.
#include "decimal128.h" // our primary include
/* Utility routines and tables [in decimal64.c] */
// DPD2BIN and the reverse are renamed to prevent link-time conflict
// if decQuad is also built in the same executable
#define DPD2BIN DPD2BINx
#define BIN2DPD BIN2DPDx
extern const uInt COMBEXP[32], COMBMSD[32];
extern const uShort DPD2BIN[1024];
extern const uShort BIN2DPD[1000]; // [not used]
extern const uByte BIN2CHAR[4001];
extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
extern void decDigitsToDPD(const decNumber *, uInt *, Int);
#if DECTRACE || DECCHECK
void decimal128Show(const decimal128 *); // for debug
extern void decNumberShow(const decNumber *); // ..
#endif
/* Useful macro */
// Clear a structure (e.g., a decNumber)
#define DEC_clear(d) memset(d, 0, sizeof(*d))
/* ------------------------------------------------------------------ */
/* decimal128FromNumber -- convert decNumber to decimal128 */
/* */
/* ds is the target decimal128 */
/* dn is the source number (assumed valid) */
/* set is the context, used only for reporting errors */
/* */
/* The set argument is used only for status reporting and for the */
/* rounding mode (used if the coefficient is more than DECIMAL128_Pmax*/
/* digits or an overflow is detected). If the exponent is out of the */
/* valid range then Overflow or Underflow will be raised. */
/* After Underflow a subnormal result is possible. */
/* */
/* DEC_Clamped is set if the number has to be 'folded down' to fit, */
/* by reducing its exponent and multiplying the coefficient by a */
/* power of ten, or if the exponent on a zero had to be clamped. */
/* ------------------------------------------------------------------ */
decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn,
decContext *set) {
uInt status=0; // status accumulator
Int ae; // adjusted exponent
decNumber dw; // work
decContext dc; // ..
uInt comb, exp; // ..
uInt uiwork; // for macros
uInt targar[4]={0,0,0,0}; // target 128-bit
#define targhi targar[3] // name the word with the sign
#define targmh targar[2] // name the words
#define targml targar[1] // ..
#define targlo targar[0] // ..
// If the number has too many digits, or the exponent could be
// out of range then reduce the number under the appropriate
// constraints. This could push the number to Infinity or zero,
// so this check and rounding must be done before generating the
// decimal128]
ae=dn->exponent+dn->digits-1; // [0 if special]
if (dn->digits>DECIMAL128_Pmax // too many digits
|| ae>DECIMAL128_Emax // likely overflow
|| ae<DECIMAL128_Emin) { // likely underflow
decContextDefault(&dc, DEC_INIT_DECIMAL128); // [no traps]
dc.round=set->round; // use supplied rounding
decNumberPlus(&dw, dn, &dc); // (round and check)
// [this changes -0 to 0, so enforce the sign...]
dw.bits|=dn->bits&DECNEG;
status=dc.status; // save status
dn=&dw; // use the work number
} // maybe out of range
if (dn->bits&DECSPECIAL) { // a special value
if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
else { // sNaN or qNaN
if ((*dn->lsu!=0 || dn->digits>1) // non-zero coefficient
&& (dn->digits<DECIMAL128_Pmax)) { // coefficient fits
decDigitsToDPD(dn, targar, 0);
}
if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24;
else targhi|=DECIMAL_sNaN<<24;
} // a NaN
} // special
else { // is finite
if (decNumberIsZero(dn)) { // is a zero
// set and clamp exponent
if (dn->exponent<-DECIMAL128_Bias) {
exp=0; // low clamp
status|=DEC_Clamped;
}
else {
exp=dn->exponent+DECIMAL128_Bias; // bias exponent
if (exp>DECIMAL128_Ehigh) { // top clamp
exp=DECIMAL128_Ehigh;
status|=DEC_Clamped;
}
}
comb=(exp>>9) & 0x18; // msd=0, exp top 2 bits ..
}
else { // non-zero finite number
uInt msd; // work
Int pad=0; // coefficient pad digits
// the dn is known to fit, but it may need to be padded
exp=(uInt)(dn->exponent+DECIMAL128_Bias); // bias exponent
if (exp>DECIMAL128_Ehigh) { // fold-down case
pad=exp-DECIMAL128_Ehigh;
exp=DECIMAL128_Ehigh; // [to maximum]
status|=DEC_Clamped;
}
// [fastpath for common case is not a win, here]
decDigitsToDPD(dn, targar, pad);
// save and clear the top digit
msd=targhi>>14;
targhi&=0x00003fff;
// create the combination field
if (msd>=8) comb=0x18 | ((exp>>11) & 0x06) | (msd & 0x01);
else comb=((exp>>9) & 0x18) | msd;
}
targhi|=comb<<26; // add combination field ..
targhi|=(exp&0xfff)<<14; // .. and exponent continuation
} // finite
if (dn->bits&DECNEG) targhi|=0x80000000; // add sign bit
// now write to storage; this is endian
if (DECLITEND) {
// lo -> hi
UBFROMUI(d128->bytes, targlo);
UBFROMUI(d128->bytes+4, targml);
UBFROMUI(d128->bytes+8, targmh);
UBFROMUI(d128->bytes+12, targhi);
}
else {
// hi -> lo
UBFROMUI(d128->bytes, targhi);
UBFROMUI(d128->bytes+4, targmh);
UBFROMUI(d128->bytes+8, targml);
UBFROMUI(d128->bytes+12, targlo);
}
if (status!=0) decContextSetStatus(set, status); // pass on status
// decimal128Show(d128);
return d128;
} // decimal128FromNumber
/* ------------------------------------------------------------------ */
/* decimal128ToNumber -- convert decimal128 to decNumber */
/* d128 is the source decimal128 */
/* dn is the target number, with appropriate space */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
uInt msd; // coefficient MSD
uInt exp; // exponent top two bits
uInt comb; // combination field
Int need; // work
uInt uiwork; // for macros
uInt sourar[4]; // source 128-bit
#define sourhi sourar[3] // name the word with the sign
#define sourmh sourar[2] // and the mid-high word
#define sourml sourar[1] // and the mod-low word
#define sourlo sourar[0] // and the lowest word
// load source from storage; this is endian
if (DECLITEND) {
sourlo=UBTOUI(d128->bytes ); // directly load the low int
sourml=UBTOUI(d128->bytes+4 ); // then the mid-low
sourmh=UBTOUI(d128->bytes+8 ); // then the mid-high
sourhi=UBTOUI(d128->bytes+12); // then the high int
}
else {
sourhi=UBTOUI(d128->bytes ); // directly load the high int
sourmh=UBTOUI(d128->bytes+4 ); // then the mid-high
sourml=UBTOUI(d128->bytes+8 ); // then the mid-low
sourlo=UBTOUI(d128->bytes+12); // then the low int
}
comb=(sourhi>>26)&0x1f; // combination field
decNumberZero(dn); // clean number
if (sourhi&0x80000000) dn->bits=DECNEG; // set sign if negative
msd=COMBMSD[comb]; // decode the combination field
exp=COMBEXP[comb]; // ..
if (exp==3) { // is a special
if (msd==0) {
dn->bits|=DECINF;
return dn; // no coefficient needed
}
else if (sourhi&0x02000000) dn->bits|=DECSNAN;
else dn->bits|=DECNAN;
msd=0; // no top digit
}
else { // is a finite number
dn->exponent=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; // unbiased
}
// get the coefficient
sourhi&=0x00003fff; // clean coefficient continuation
if (msd) { // non-zero msd
sourhi|=msd<<14; // prefix to coefficient
need=12; // process 12 declets
}
else { // msd=0
if (sourhi) need=11; // declets to process
else if (sourmh) need=10;
else if (sourml) need=7;
else if (sourlo) need=4;
else return dn; // easy: coefficient is 0
} //msd=0
decDigitsFromDPD(dn, sourar, need); // process declets
// decNumberShow(dn);
return dn;
} // decimal128ToNumber
/* ------------------------------------------------------------------ */
/* to-scientific-string -- conversion to numeric string */
/* to-engineering-string -- conversion to numeric string */
/* */
/* decimal128ToString(d128, string); */
/* decimal128ToEngString(d128, string); */
/* */
/* d128 is the decimal128 format number to convert */
/* string is the string where the result will be laid out */
/* */
/* string must be at least 24 characters */
/* */
/* No error is possible, and no status can be set. */
/* ------------------------------------------------------------------ */
char * decimal128ToEngString(const decimal128 *d128, char *string){
decNumber dn; // work
decimal128ToNumber(d128, &dn);
decNumberToEngString(&dn, string);
return string;
} // decimal128ToEngString
char * decimal128ToString(const decimal128 *d128, char *string){
uInt msd; // coefficient MSD
Int exp; // exponent top two bits or full
uInt comb; // combination field
char *cstart; // coefficient start
char *c; // output pointer in string
const uByte *u; // work
char *s, *t; // .. (source, target)
Int dpd; // ..
Int pre, e; // ..
uInt uiwork; // for macros
uInt sourar[4]; // source 128-bit
#define sourhi sourar[3] // name the word with the sign
#define sourmh sourar[2] // and the mid-high word
#define sourml sourar[1] // and the mod-low word
#define sourlo sourar[0] // and the lowest word
// load source from storage; this is endian
if (DECLITEND) {
sourlo=UBTOUI(d128->bytes ); // directly load the low int
sourml=UBTOUI(d128->bytes+4 ); // then the mid-low
sourmh=UBTOUI(d128->bytes+8 ); // then the mid-high
sourhi=UBTOUI(d128->bytes+12); // then the high int
}
else {
sourhi=UBTOUI(d128->bytes ); // directly load the high int
sourmh=UBTOUI(d128->bytes+4 ); // then the mid-high
sourml=UBTOUI(d128->bytes+8 ); // then the mid-low
sourlo=UBTOUI(d128->bytes+12); // then the low int
}
c=string; // where result will go
if (((Int)sourhi)<0) *c++='-'; // handle sign
comb=(sourhi>>26)&0x1f; // combination field
msd=COMBMSD[comb]; // decode the combination field
exp=COMBEXP[comb]; // ..
if (exp==3) {
if (msd==0) { // infinity
strcpy(c, "Inf");
strcpy(c+3, "inity");
return string; // easy
}
if (sourhi&0x02000000) *c++='s'; // sNaN
strcpy(c, "NaN"); // complete word
c+=3; // step past
if (sourlo==0 && sourml==0 && sourmh==0
&& (sourhi&0x0003ffff)==0) return string; // zero payload
// otherwise drop through to add integer; set correct exp
exp=0; msd=0; // setup for following code
}
else exp=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; // unbiased
// convert 34 digits of significand to characters
cstart=c; // save start of coefficient
if (msd) *c++='0'+(char)msd; // non-zero most significant digit
// Now decode the declets. After extracting each one, it is
// decoded to binary and then to a 4-char sequence by table lookup;
// the 4-chars are a 1-char length (significant digits, except 000
// has length 0). This allows us to left-align the first declet
// with non-zero content, then remaining ones are full 3-char
// length. We use fixed-length memcpys because variable-length
// causes a subroutine call in GCC. (These are length 4 for speed
// and are safe because the array has an extra terminator byte.)
#define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \
if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \
else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}
dpd=(sourhi>>4)&0x3ff; // declet 1
dpd2char;
dpd=((sourhi&0xf)<<6) | (sourmh>>26); // declet 2
dpd2char;
dpd=(sourmh>>16)&0x3ff; // declet 3
dpd2char;
dpd=(sourmh>>6)&0x3ff; // declet 4
dpd2char;
dpd=((sourmh&0x3f)<<4) | (sourml>>28); // declet 5
dpd2char;
dpd=(sourml>>18)&0x3ff; // declet 6
dpd2char;
dpd=(sourml>>8)&0x3ff; // declet 7
dpd2char;
dpd=((sourml&0xff)<<2) | (sourlo>>30); // declet 8
dpd2char;
dpd=(sourlo>>20)&0x3ff; // declet 9
dpd2char;
dpd=(sourlo>>10)&0x3ff; // declet 10
dpd2char;
dpd=(sourlo)&0x3ff; // declet 11
dpd2char;
if (c==cstart) *c++='0'; // all zeros -- make 0
if (exp==0) { // integer or NaN case -- easy
*c='\0'; // terminate
return string;
}
/* non-0 exponent */
e=0; // assume no E
pre=c-cstart+exp;
// [here, pre-exp is the digits count (==1 for zero)]
if (exp>0 || pre<-5) { // need exponential form
e=pre-1; // calculate E value
pre=1; // assume one digit before '.'
} // exponential form
/* modify the coefficient, adding 0s, '.', and E+nn as needed */
s=c-1; // source (LSD)
if (pre>0) { // ddd.ddd (plain), perhaps with E
char *dotat=cstart+pre;
if (dotat<c) { // if embedded dot needed...
t=c; // target
for (; s>=dotat; s--, t--) *t=*s; // open the gap; leave t at gap
*t='.'; // insert the dot
c++; // length increased by one
}
// finally add the E-part, if needed; it will never be 0, and has
// a maximum length of 4 digits
if (e!=0) {
*c++='E'; // starts with E
*c++='+'; // assume positive
if (e<0) {
*(c-1)='-'; // oops, need '-'
e=-e; // uInt, please
}
if (e<1000) { // 3 (or fewer) digits case
u=&BIN2CHAR[e*4]; // -> length byte
memcpy(c, u+4-*u, 4); // copy fixed 4 characters [is safe]
c+=*u; // bump pointer appropriately
}
else { // 4-digits
Int thou=((e>>3)*1049)>>17; // e/1000
Int rem=e-(1000*thou); // e%1000
*c++='0'+(char)thou;
u=&BIN2CHAR[rem*4]; // -> length byte
memcpy(c, u+1, 4); // copy fixed 3+1 characters [is safe]
c+=3; // bump pointer, always 3 digits
}
}
*c='\0'; // add terminator
//printf("res %s\n", string);
return string;
} // pre>0
/* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
t=c+1-pre;
*(t+1)='\0'; // can add terminator now
for (; s>=cstart; s--, t--) *t=*s; // shift whole coefficient right
c=cstart;
*c++='0'; // always starts with 0.
*c++='.';
for (; pre<0; pre++) *c++='0'; // add any 0's after '.'
//printf("res %s\n", string);
return string;
} // decimal128ToString
/* ------------------------------------------------------------------ */
/* to-number -- conversion from numeric string */
/* */
/* decimal128FromString(result, string, set); */
/* */
/* result is the decimal128 format number which gets the result of */
/* the conversion */
/* *string is the character string which should contain a valid */
/* number (which may be a special value) */
/* set is the context */
/* */
/* The context is supplied to this routine is used for error handling */
/* (setting of status and traps) and for the rounding mode, only. */
/* If an error occurs, the result will be a valid decimal128 NaN. */
/* ------------------------------------------------------------------ */
decimal128 * decimal128FromString(decimal128 *result, const char *string,
decContext *set) {
decContext dc; // work
decNumber dn; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL128); // no traps, please
dc.round=set->round; // use supplied rounding
decNumberFromString(&dn, string, &dc); // will round if needed
decimal128FromNumber(result, &dn, &dc);
if (dc.status!=0) { // something happened
decContextSetStatus(set, dc.status); // .. pass it on
}
return result;
} // decimal128FromString
/* ------------------------------------------------------------------ */
/* decimal128IsCanonical -- test whether encoding is canonical */
/* d128 is the source decimal128 */
/* returns 1 if the encoding of d128 is canonical, 0 otherwise */
/* No error is possible. */
/* ------------------------------------------------------------------ */
uInt decimal128IsCanonical(const decimal128 *d128) {
decNumber dn; // work
decimal128 canon; // ..
decContext dc; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL128);
decimal128ToNumber(d128, &dn);
decimal128FromNumber(&canon, &dn, &dc);// canon will now be canonical
return memcmp(d128, &canon, DECIMAL128_Bytes)==0;
} // decimal128IsCanonical
/* ------------------------------------------------------------------ */
/* decimal128Canonical -- copy an encoding, ensuring it is canonical */
/* d128 is the source decimal128 */
/* result is the target (may be the same decimal128) */
/* returns result */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) {
decNumber dn; // work
decContext dc; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL128);
decimal128ToNumber(d128, &dn);
decimal128FromNumber(result, &dn, &dc);// result will now be canonical
return result;
} // decimal128Canonical
#if DECTRACE || DECCHECK
/* Macros for accessing decimal128 fields. These assume the argument
is a reference (pointer) to the decimal128 structure, and the
decimal128 is in network byte order (big-endian) */
// Get sign
#define decimal128Sign(d) ((unsigned)(d)->bytes[0]>>7)
// Get combination field
#define decimal128Comb(d) (((d)->bytes[0] & 0x7c)>>2)
// Get exponent continuation [does not remove bias]
#define decimal128ExpCon(d) ((((d)->bytes[0] & 0x03)<<10) \
| ((unsigned)(d)->bytes[1]<<2) \
| ((unsigned)(d)->bytes[2]>>6))
// Set sign [this assumes sign previously 0]
#define decimal128SetSign(d, b) { \
(d)->bytes[0]|=((unsigned)(b)<<7);}
// Set exponent continuation [does not apply bias]
// This assumes range has been checked and exponent previously 0;
// type of exponent must be unsigned
#define decimal128SetExpCon(d, e) { \
(d)->bytes[0]|=(uByte)((e)>>10); \
(d)->bytes[1] =(uByte)(((e)&0x3fc)>>2); \
(d)->bytes[2]|=(uByte)(((e)&0x03)<<6);}
/* ------------------------------------------------------------------ */
/* decimal128Show -- display a decimal128 in hexadecimal [debug aid] */
/* d128 -- the number to show */
/* ------------------------------------------------------------------ */
// Also shows sign/cob/expconfields extracted
void decimal128Show(const decimal128 *d128) {
char buf[DECIMAL128_Bytes*2+1];
Int i, j=0;
if (DECLITEND) {
for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
sprintf(&buf[j], "%02x", d128->bytes[15-i]);
}
printf(" D128> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
d128->bytes[15]>>7, (d128->bytes[15]>>2)&0x1f,
((d128->bytes[15]&0x3)<<10)|(d128->bytes[14]<<2)|
(d128->bytes[13]>>6));
}
else {
for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
sprintf(&buf[j], "%02x", d128->bytes[i]);
}
printf(" D128> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
decimal128Sign(d128), decimal128Comb(d128),
decimal128ExpCon(d128));
}
} // decimal128Show
#endif
+81
View File
@@ -0,0 +1,81 @@
/* ------------------------------------------------------------------ */
/* Decimal 128-bit format module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
#if !defined(DECIMAL128)
#define DECIMAL128
#define DEC128NAME "decimal128" /* Short name */
#define DEC128FULLNAME "Decimal 128-bit Number" /* Verbose name */
#define DEC128AUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decimal128s */
#define DECIMAL128_Bytes 16 /* length */
#define DECIMAL128_Pmax 34 /* maximum precision (digits) */
#define DECIMAL128_Emax 6144 /* maximum adjusted exponent */
#define DECIMAL128_Emin -6143 /* minimum adjusted exponent */
#define DECIMAL128_Bias 6176 /* bias for the exponent */
#define DECIMAL128_String 43 /* maximum string length, +1 */
#define DECIMAL128_EconL 12 /* exp. continuation length */
/* highest biased exponent (Elimit-1) */
#define DECIMAL128_Ehigh (DECIMAL128_Emax+DECIMAL128_Bias-DECIMAL128_Pmax+1)
/* check enough digits, if pre-defined */
#if defined(DECNUMDIGITS)
#if (DECNUMDIGITS<DECIMAL128_Pmax)
#error decimal128.h needs pre-defined DECNUMDIGITS>=34 for safe use
#endif
#endif
#ifndef DECNUMDIGITS
#define DECNUMDIGITS DECIMAL128_Pmax /* size if not already defined*/
#endif
#ifndef DECNUMBER
#include "decNumber.h" /* context and number library */
#endif
/* Decimal 128-bit type, accessible by bytes */
typedef struct {
uint8_t bytes[DECIMAL128_Bytes]; /* decimal128: 1, 5, 12, 110 bits*/
} decimal128;
/* special values [top byte excluding sign bit; last two bits are */
/* don't-care for Infinity on input, last bit don't-care for NaN] */
#if !defined(DECIMAL_NaN)
#define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */
#define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */
#define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */
#endif
/* ---------------------------------------------------------------- */
/* Routines */
/* ---------------------------------------------------------------- */
/* String conversions */
decimal128 * decimal128FromString(decimal128 *, const char *, decContext *);
char * decimal128ToString(const decimal128 *, char *);
char * decimal128ToEngString(const decimal128 *, char *);
/* decNumber conversions */
decimal128 * decimal128FromNumber(decimal128 *, const decNumber *,
decContext *);
decNumber * decimal128ToNumber(const decimal128 *, decNumber *);
/* Format-dependent utilities */
uint32_t decimal128IsCanonical(const decimal128 *);
decimal128 * decimal128Canonical(decimal128 *, const decimal128 *);
#endif
+476
View File
@@ -0,0 +1,476 @@
/* ------------------------------------------------------------------ */
/* Decimal 32-bit format module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2008. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises the routines for decimal32 format numbers. */
/* Conversions are supplied to and from decNumber and String. */
/* */
/* This is used when decNumber provides operations, either for all */
/* operations or as a proxy between decNumber and decSingle. */
/* */
/* Error handling is the same as decNumber (qv.). */
/* ------------------------------------------------------------------ */
#include <string.h> // [for memset/memcpy]
#include <stdio.h> // [for printf]
#define DECNUMDIGITS 7 // make decNumbers with space for 7
#include "decNumber.h" // base number library
#include "decNumberLocal.h" // decNumber local types, etc.
#include "decimal32.h" // our primary include
/* Utility tables and routines [in decimal64.c] */
// DPD2BIN and the reverse are renamed to prevent link-time conflict
// if decQuad is also built in the same executable
#define DPD2BIN DPD2BINx
#define BIN2DPD BIN2DPDx
extern const uInt COMBEXP[32], COMBMSD[32];
extern const uShort DPD2BIN[1024];
extern const uShort BIN2DPD[1000];
extern const uByte BIN2CHAR[4001];
extern void decDigitsToDPD(const decNumber *, uInt *, Int);
extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
#if DECTRACE || DECCHECK
void decimal32Show(const decimal32 *); // for debug
extern void decNumberShow(const decNumber *); // ..
#endif
/* Useful macro */
// Clear a structure (e.g., a decNumber)
#define DEC_clear(d) memset(d, 0, sizeof(*d))
/* ------------------------------------------------------------------ */
/* decimal32FromNumber -- convert decNumber to decimal32 */
/* */
/* ds is the target decimal32 */
/* dn is the source number (assumed valid) */
/* set is the context, used only for reporting errors */
/* */
/* The set argument is used only for status reporting and for the */
/* rounding mode (used if the coefficient is more than DECIMAL32_Pmax */
/* digits or an overflow is detected). If the exponent is out of the */
/* valid range then Overflow or Underflow will be raised. */
/* After Underflow a subnormal result is possible. */
/* */
/* DEC_Clamped is set if the number has to be 'folded down' to fit, */
/* by reducing its exponent and multiplying the coefficient by a */
/* power of ten, or if the exponent on a zero had to be clamped. */
/* ------------------------------------------------------------------ */
decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn,
decContext *set) {
uInt status=0; // status accumulator
Int ae; // adjusted exponent
decNumber dw; // work
decContext dc; // ..
uInt comb, exp; // ..
uInt uiwork; // for macros
uInt targ=0; // target 32-bit
// If the number has too many digits, or the exponent could be
// out of range then reduce the number under the appropriate
// constraints. This could push the number to Infinity or zero,
// so this check and rounding must be done before generating the
// decimal32]
ae=dn->exponent+dn->digits-1; // [0 if special]
if (dn->digits>DECIMAL32_Pmax // too many digits
|| ae>DECIMAL32_Emax // likely overflow
|| ae<DECIMAL32_Emin) { // likely underflow
decContextDefault(&dc, DEC_INIT_DECIMAL32); // [no traps]
dc.round=set->round; // use supplied rounding
decNumberPlus(&dw, dn, &dc); // (round and check)
// [this changes -0 to 0, so enforce the sign...]
dw.bits|=dn->bits&DECNEG;
status=dc.status; // save status
dn=&dw; // use the work number
} // maybe out of range
if (dn->bits&DECSPECIAL) { // a special value
if (dn->bits&DECINF) targ=DECIMAL_Inf<<24;
else { // sNaN or qNaN
if ((*dn->lsu!=0 || dn->digits>1) // non-zero coefficient
&& (dn->digits<DECIMAL32_Pmax)) { // coefficient fits
decDigitsToDPD(dn, &targ, 0);
}
if (dn->bits&DECNAN) targ|=DECIMAL_NaN<<24;
else targ|=DECIMAL_sNaN<<24;
} // a NaN
} // special
else { // is finite
if (decNumberIsZero(dn)) { // is a zero
// set and clamp exponent
if (dn->exponent<-DECIMAL32_Bias) {
exp=0; // low clamp
status|=DEC_Clamped;
}
else {
exp=dn->exponent+DECIMAL32_Bias; // bias exponent
if (exp>DECIMAL32_Ehigh) { // top clamp
exp=DECIMAL32_Ehigh;
status|=DEC_Clamped;
}
}
comb=(exp>>3) & 0x18; // msd=0, exp top 2 bits ..
}
else { // non-zero finite number
uInt msd; // work
Int pad=0; // coefficient pad digits
// the dn is known to fit, but it may need to be padded
exp=(uInt)(dn->exponent+DECIMAL32_Bias); // bias exponent
if (exp>DECIMAL32_Ehigh) { // fold-down case
pad=exp-DECIMAL32_Ehigh;
exp=DECIMAL32_Ehigh; // [to maximum]
status|=DEC_Clamped;
}
// fastpath common case
if (DECDPUN==3 && pad==0) {
targ=BIN2DPD[dn->lsu[0]];
if (dn->digits>3) targ|=(uInt)(BIN2DPD[dn->lsu[1]])<<10;
msd=(dn->digits==7 ? dn->lsu[2] : 0);
}
else { // general case
decDigitsToDPD(dn, &targ, pad);
// save and clear the top digit
msd=targ>>20;
targ&=0x000fffff;
}
// create the combination field
if (msd>=8) comb=0x18 | ((exp>>5) & 0x06) | (msd & 0x01);
else comb=((exp>>3) & 0x18) | msd;
}
targ|=comb<<26; // add combination field ..
targ|=(exp&0x3f)<<20; // .. and exponent continuation
} // finite
if (dn->bits&DECNEG) targ|=0x80000000; // add sign bit
// now write to storage; this is endian
UBFROMUI(d32->bytes, targ); // directly store the int
if (status!=0) decContextSetStatus(set, status); // pass on status
// decimal32Show(d32);
return d32;
} // decimal32FromNumber
/* ------------------------------------------------------------------ */
/* decimal32ToNumber -- convert decimal32 to decNumber */
/* d32 is the source decimal32 */
/* dn is the target number, with appropriate space */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) {
uInt msd; // coefficient MSD
uInt exp; // exponent top two bits
uInt comb; // combination field
uInt sour; // source 32-bit
uInt uiwork; // for macros
// load source from storage; this is endian
sour=UBTOUI(d32->bytes); // directly load the int
comb=(sour>>26)&0x1f; // combination field
decNumberZero(dn); // clean number
if (sour&0x80000000) dn->bits=DECNEG; // set sign if negative
msd=COMBMSD[comb]; // decode the combination field
exp=COMBEXP[comb]; // ..
if (exp==3) { // is a special
if (msd==0) {
dn->bits|=DECINF;
return dn; // no coefficient needed
}
else if (sour&0x02000000) dn->bits|=DECSNAN;
else dn->bits|=DECNAN;
msd=0; // no top digit
}
else { // is a finite number
dn->exponent=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; // unbiased
}
// get the coefficient
sour&=0x000fffff; // clean coefficient continuation
if (msd) { // non-zero msd
sour|=msd<<20; // prefix to coefficient
decDigitsFromDPD(dn, &sour, 3); // process 3 declets
return dn;
}
// msd=0
if (!sour) return dn; // easy: coefficient is 0
if (sour&0x000ffc00) // need 2 declets?
decDigitsFromDPD(dn, &sour, 2); // process 2 declets
else
decDigitsFromDPD(dn, &sour, 1); // process 1 declet
return dn;
} // decimal32ToNumber
/* ------------------------------------------------------------------ */
/* to-scientific-string -- conversion to numeric string */
/* to-engineering-string -- conversion to numeric string */
/* */
/* decimal32ToString(d32, string); */
/* decimal32ToEngString(d32, string); */
/* */
/* d32 is the decimal32 format number to convert */
/* string is the string where the result will be laid out */
/* */
/* string must be at least 24 characters */
/* */
/* No error is possible, and no status can be set. */
/* ------------------------------------------------------------------ */
char * decimal32ToEngString(const decimal32 *d32, char *string){
decNumber dn; // work
decimal32ToNumber(d32, &dn);
decNumberToEngString(&dn, string);
return string;
} // decimal32ToEngString
char * decimal32ToString(const decimal32 *d32, char *string){
uInt msd; // coefficient MSD
Int exp; // exponent top two bits or full
uInt comb; // combination field
char *cstart; // coefficient start
char *c; // output pointer in string
const uByte *u; // work
char *s, *t; // .. (source, target)
Int dpd; // ..
Int pre, e; // ..
uInt uiwork; // for macros
uInt sour; // source 32-bit
// load source from storage; this is endian
sour=UBTOUI(d32->bytes); // directly load the int
c=string; // where result will go
if (((Int)sour)<0) *c++='-'; // handle sign
comb=(sour>>26)&0x1f; // combination field
msd=COMBMSD[comb]; // decode the combination field
exp=COMBEXP[comb]; // ..
if (exp==3) {
if (msd==0) { // infinity
strcpy(c, "Inf");
strcpy(c+3, "inity");
return string; // easy
}
if (sour&0x02000000) *c++='s'; // sNaN
strcpy(c, "NaN"); // complete word
c+=3; // step past
if ((sour&0x000fffff)==0) return string; // zero payload
// otherwise drop through to add integer; set correct exp
exp=0; msd=0; // setup for following code
}
else exp=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; // unbiased
// convert 7 digits of significand to characters
cstart=c; // save start of coefficient
if (msd) *c++='0'+(char)msd; // non-zero most significant digit
// Now decode the declets. After extracting each one, it is
// decoded to binary and then to a 4-char sequence by table lookup;
// the 4-chars are a 1-char length (significant digits, except 000
// has length 0). This allows us to left-align the first declet
// with non-zero content, then remaining ones are full 3-char
// length. We use fixed-length memcpys because variable-length
// causes a subroutine call in GCC. (These are length 4 for speed
// and are safe because the array has an extra terminator byte.)
#define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \
if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \
else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}
dpd=(sour>>10)&0x3ff; // declet 1
dpd2char;
dpd=(sour)&0x3ff; // declet 2
dpd2char;
if (c==cstart) *c++='0'; // all zeros -- make 0
if (exp==0) { // integer or NaN case -- easy
*c='\0'; // terminate
return string;
}
/* non-0 exponent */
e=0; // assume no E
pre=c-cstart+exp;
// [here, pre-exp is the digits count (==1 for zero)]
if (exp>0 || pre<-5) { // need exponential form
e=pre-1; // calculate E value
pre=1; // assume one digit before '.'
} // exponential form
/* modify the coefficient, adding 0s, '.', and E+nn as needed */
s=c-1; // source (LSD)
if (pre>0) { // ddd.ddd (plain), perhaps with E
char *dotat=cstart+pre;
if (dotat<c) { // if embedded dot needed...
t=c; // target
for (; s>=dotat; s--, t--) *t=*s; // open the gap; leave t at gap
*t='.'; // insert the dot
c++; // length increased by one
}
// finally add the E-part, if needed; it will never be 0, and has
// a maximum length of 3 digits (E-101 case)
if (e!=0) {
*c++='E'; // starts with E
*c++='+'; // assume positive
if (e<0) {
*(c-1)='-'; // oops, need '-'
e=-e; // uInt, please
}
u=&BIN2CHAR[e*4]; // -> length byte
memcpy(c, u+4-*u, 4); // copy fixed 4 characters [is safe]
c+=*u; // bump pointer appropriately
}
*c='\0'; // add terminator
//printf("res %s\n", string);
return string;
} // pre>0
/* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
t=c+1-pre;
*(t+1)='\0'; // can add terminator now
for (; s>=cstart; s--, t--) *t=*s; // shift whole coefficient right
c=cstart;
*c++='0'; // always starts with 0.
*c++='.';
for (; pre<0; pre++) *c++='0'; // add any 0's after '.'
//printf("res %s\n", string);
return string;
} // decimal32ToString
/* ------------------------------------------------------------------ */
/* to-number -- conversion from numeric string */
/* */
/* decimal32FromString(result, string, set); */
/* */
/* result is the decimal32 format number which gets the result of */
/* the conversion */
/* *string is the character string which should contain a valid */
/* number (which may be a special value) */
/* set is the context */
/* */
/* The context is supplied to this routine is used for error handling */
/* (setting of status and traps) and for the rounding mode, only. */
/* If an error occurs, the result will be a valid decimal32 NaN. */
/* ------------------------------------------------------------------ */
decimal32 * decimal32FromString(decimal32 *result, const char *string,
decContext *set) {
decContext dc; // work
decNumber dn; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL32); // no traps, please
dc.round=set->round; // use supplied rounding
decNumberFromString(&dn, string, &dc); // will round if needed
decimal32FromNumber(result, &dn, &dc);
if (dc.status!=0) { // something happened
decContextSetStatus(set, dc.status); // .. pass it on
}
return result;
} // decimal32FromString
/* ------------------------------------------------------------------ */
/* decimal32IsCanonical -- test whether encoding is canonical */
/* d32 is the source decimal32 */
/* returns 1 if the encoding of d32 is canonical, 0 otherwise */
/* No error is possible. */
/* ------------------------------------------------------------------ */
uInt decimal32IsCanonical(const decimal32 *d32) {
decNumber dn; // work
decimal32 canon; // ..
decContext dc; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL32);
decimal32ToNumber(d32, &dn);
decimal32FromNumber(&canon, &dn, &dc);// canon will now be canonical
return memcmp(d32, &canon, DECIMAL32_Bytes)==0;
} // decimal32IsCanonical
/* ------------------------------------------------------------------ */
/* decimal32Canonical -- copy an encoding, ensuring it is canonical */
/* d32 is the source decimal32 */
/* result is the target (may be the same decimal32) */
/* returns result */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) {
decNumber dn; // work
decContext dc; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL32);
decimal32ToNumber(d32, &dn);
decimal32FromNumber(result, &dn, &dc);// result will now be canonical
return result;
} // decimal32Canonical
#if DECTRACE || DECCHECK
/* Macros for accessing decimal32 fields. These assume the argument
is a reference (pointer) to the decimal32 structure, and the
decimal32 is in network byte order (big-endian) */
// Get sign
#define decimal32Sign(d) ((unsigned)(d)->bytes[0]>>7)
// Get combination field
#define decimal32Comb(d) (((d)->bytes[0] & 0x7c)>>2)
// Get exponent continuation [does not remove bias]
#define decimal32ExpCon(d) ((((d)->bytes[0] & 0x03)<<4) \
| ((unsigned)(d)->bytes[1]>>4))
// Set sign [this assumes sign previously 0]
#define decimal32SetSign(d, b) { \
(d)->bytes[0]|=((unsigned)(b)<<7);}
// Set exponent continuation [does not apply bias]
// This assumes range has been checked and exponent previously 0;
// type of exponent must be unsigned
#define decimal32SetExpCon(d, e) { \
(d)->bytes[0]|=(uByte)((e)>>4); \
(d)->bytes[1]|=(uByte)(((e)&0x0F)<<4);}
/* ------------------------------------------------------------------ */
/* decimal32Show -- display a decimal32 in hexadecimal [debug aid] */
/* d32 -- the number to show */
/* ------------------------------------------------------------------ */
// Also shows sign/cob/expconfields extracted - valid bigendian only
void decimal32Show(const decimal32 *d32) {
char buf[DECIMAL32_Bytes*2+1];
Int i, j=0;
if (DECLITEND) {
for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
sprintf(&buf[j], "%02x", d32->bytes[3-i]);
}
printf(" D32> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
d32->bytes[3]>>7, (d32->bytes[3]>>2)&0x1f,
((d32->bytes[3]&0x3)<<4)| (d32->bytes[2]>>4));
}
else {
for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
sprintf(&buf[j], "%02x", d32->bytes[i]);
}
printf(" D32> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
decimal32Sign(d32), decimal32Comb(d32), decimal32ExpCon(d32));
}
} // decimal32Show
#endif
+81
View File
@@ -0,0 +1,81 @@
/* ------------------------------------------------------------------ */
/* Decimal 32-bit format module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2006. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
#if !defined(DECIMAL32)
#define DECIMAL32
#define DEC32NAME "decimal32" /* Short name */
#define DEC32FULLNAME "Decimal 32-bit Number" /* Verbose name */
#define DEC32AUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decimal32s */
#define DECIMAL32_Bytes 4 /* length */
#define DECIMAL32_Pmax 7 /* maximum precision (digits) */
#define DECIMAL32_Emax 96 /* maximum adjusted exponent */
#define DECIMAL32_Emin -95 /* minimum adjusted exponent */
#define DECIMAL32_Bias 101 /* bias for the exponent */
#define DECIMAL32_String 15 /* maximum string length, +1 */
#define DECIMAL32_EconL 6 /* exp. continuation length */
/* highest biased exponent (Elimit-1) */
#define DECIMAL32_Ehigh (DECIMAL32_Emax+DECIMAL32_Bias-DECIMAL32_Pmax+1)
/* check enough digits, if pre-defined */
#if defined(DECNUMDIGITS)
#if (DECNUMDIGITS<DECIMAL32_Pmax)
#error decimal32.h needs pre-defined DECNUMDIGITS>=7 for safe use
#endif
#endif
#ifndef DECNUMDIGITS
#define DECNUMDIGITS DECIMAL32_Pmax /* size if not already defined*/
#endif
#ifndef DECNUMBER
#include "decNumber.h" /* context and number library */
#endif
/* Decimal 32-bit type, accessible by bytes */
typedef struct {
uint8_t bytes[DECIMAL32_Bytes]; /* decimal32: 1, 5, 6, 20 bits*/
} decimal32;
/* special values [top byte excluding sign bit; last two bits are */
/* don't-care for Infinity on input, last bit don't-care for NaN] */
#if !defined(DECIMAL_NaN)
#define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */
#define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */
#define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */
#endif
/* ---------------------------------------------------------------- */
/* Routines */
/* ---------------------------------------------------------------- */
/* String conversions */
decimal32 * decimal32FromString(decimal32 *, const char *, decContext *);
char * decimal32ToString(const decimal32 *, char *);
char * decimal32ToEngString(const decimal32 *, char *);
/* decNumber conversions */
decimal32 * decimal32FromNumber(decimal32 *, const decNumber *,
decContext *);
decNumber * decimal32ToNumber(const decimal32 *, decNumber *);
/* Format-dependent utilities */
uint32_t decimal32IsCanonical(const decimal32 *);
decimal32 * decimal32Canonical(decimal32 *, const decimal32 *);
#endif
+839
View File
@@ -0,0 +1,839 @@
/* ------------------------------------------------------------------ */
/* Decimal 64-bit format module */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2009. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
/* This module comprises the routines for decimal64 format numbers. */
/* Conversions are supplied to and from decNumber and String. */
/* */
/* This is used when decNumber provides operations, either for all */
/* operations or as a proxy between decNumber and decSingle. */
/* */
/* Error handling is the same as decNumber (qv.). */
/* ------------------------------------------------------------------ */
#include <string.h> // [for memset/memcpy]
#include <stdio.h> // [for printf]
#define DECNUMDIGITS 16 // make decNumbers with space for 16
#include "decNumber.h" // base number library
#include "decNumberLocal.h" // decNumber local types, etc.
#include "decimal64.h" // our primary include
/* Utility routines and tables [in decimal64.c]; externs for C++ */
// DPD2BIN and the reverse are renamed to prevent link-time conflict
// if decQuad is also built in the same executable
#define DPD2BIN DPD2BINx
#define BIN2DPD BIN2DPDx
extern const uInt COMBEXP[32], COMBMSD[32];
extern const uShort DPD2BIN[1024];
extern const uShort BIN2DPD[1000];
extern const uByte BIN2CHAR[4001];
extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
extern void decDigitsToDPD(const decNumber *, uInt *, Int);
#if DECTRACE || DECCHECK
void decimal64Show(const decimal64 *); // for debug
extern void decNumberShow(const decNumber *); // ..
#endif
/* Useful macro */
// Clear a structure (e.g., a decNumber)
#define DEC_clear(d) memset(d, 0, sizeof(*d))
/* define and include the tables to use for conversions */
#define DEC_BIN2CHAR 1
#define DEC_DPD2BIN 1
#define DEC_BIN2DPD 1 // used for all sizes
#include "decDPD.h" // lookup tables
/* ------------------------------------------------------------------ */
/* decimal64FromNumber -- convert decNumber to decimal64 */
/* */
/* ds is the target decimal64 */
/* dn is the source number (assumed valid) */
/* set is the context, used only for reporting errors */
/* */
/* The set argument is used only for status reporting and for the */
/* rounding mode (used if the coefficient is more than DECIMAL64_Pmax */
/* digits or an overflow is detected). If the exponent is out of the */
/* valid range then Overflow or Underflow will be raised. */
/* After Underflow a subnormal result is possible. */
/* */
/* DEC_Clamped is set if the number has to be 'folded down' to fit, */
/* by reducing its exponent and multiplying the coefficient by a */
/* power of ten, or if the exponent on a zero had to be clamped. */
/* ------------------------------------------------------------------ */
decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn,
decContext *set) {
uInt status=0; // status accumulator
Int ae; // adjusted exponent
decNumber dw; // work
decContext dc; // ..
uInt comb, exp; // ..
uInt uiwork; // for macros
uInt targar[2]={0, 0}; // target 64-bit
#define targhi targar[1] // name the word with the sign
#define targlo targar[0] // and the other
// If the number has too many digits, or the exponent could be
// out of range then reduce the number under the appropriate
// constraints. This could push the number to Infinity or zero,
// so this check and rounding must be done before generating the
// decimal64]
ae=dn->exponent+dn->digits-1; // [0 if special]
if (dn->digits>DECIMAL64_Pmax // too many digits
|| ae>DECIMAL64_Emax // likely overflow
|| ae<DECIMAL64_Emin) { // likely underflow
decContextDefault(&dc, DEC_INIT_DECIMAL64); // [no traps]
dc.round=set->round; // use supplied rounding
decNumberPlus(&dw, dn, &dc); // (round and check)
// [this changes -0 to 0, so enforce the sign...]
dw.bits|=dn->bits&DECNEG;
status=dc.status; // save status
dn=&dw; // use the work number
} // maybe out of range
if (dn->bits&DECSPECIAL) { // a special value
if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
else { // sNaN or qNaN
if ((*dn->lsu!=0 || dn->digits>1) // non-zero coefficient
&& (dn->digits<DECIMAL64_Pmax)) { // coefficient fits
decDigitsToDPD(dn, targar, 0);
}
if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24;
else targhi|=DECIMAL_sNaN<<24;
} // a NaN
} // special
else { // is finite
if (decNumberIsZero(dn)) { // is a zero
// set and clamp exponent
if (dn->exponent<-DECIMAL64_Bias) {
exp=0; // low clamp
status|=DEC_Clamped;
}
else {
exp=dn->exponent+DECIMAL64_Bias; // bias exponent
if (exp>DECIMAL64_Ehigh) { // top clamp
exp=DECIMAL64_Ehigh;
status|=DEC_Clamped;
}
}
comb=(exp>>5) & 0x18; // msd=0, exp top 2 bits ..
}
else { // non-zero finite number
uInt msd; // work
Int pad=0; // coefficient pad digits
// the dn is known to fit, but it may need to be padded
exp=(uInt)(dn->exponent+DECIMAL64_Bias); // bias exponent
if (exp>DECIMAL64_Ehigh) { // fold-down case
pad=exp-DECIMAL64_Ehigh;
exp=DECIMAL64_Ehigh; // [to maximum]
status|=DEC_Clamped;
}
// fastpath common case
if (DECDPUN==3 && pad==0) {
uInt dpd[6]={0,0,0,0,0,0};
uInt i;
Int d=dn->digits;
for (i=0; d>0; i++, d-=3) dpd[i]=BIN2DPD[dn->lsu[i]];
targlo =dpd[0];
targlo|=dpd[1]<<10;
targlo|=dpd[2]<<20;
if (dn->digits>6) {
targlo|=dpd[3]<<30;
targhi =dpd[3]>>2;
targhi|=dpd[4]<<8;
}
msd=dpd[5]; // [did not really need conversion]
}
else { // general case
decDigitsToDPD(dn, targar, pad);
// save and clear the top digit
msd=targhi>>18;
targhi&=0x0003ffff;
}
// create the combination field
if (msd>=8) comb=0x18 | ((exp>>7) & 0x06) | (msd & 0x01);
else comb=((exp>>5) & 0x18) | msd;
}
targhi|=comb<<26; // add combination field ..
targhi|=(exp&0xff)<<18; // .. and exponent continuation
} // finite
if (dn->bits&DECNEG) targhi|=0x80000000; // add sign bit
// now write to storage; this is now always endian
if (DECLITEND) {
// lo int then hi
UBFROMUI(d64->bytes, targar[0]);
UBFROMUI(d64->bytes+4, targar[1]);
}
else {
// hi int then lo
UBFROMUI(d64->bytes, targar[1]);
UBFROMUI(d64->bytes+4, targar[0]);
}
if (status!=0) decContextSetStatus(set, status); // pass on status
// decimal64Show(d64);
return d64;
} // decimal64FromNumber
/* ------------------------------------------------------------------ */
/* decimal64ToNumber -- convert decimal64 to decNumber */
/* d64 is the source decimal64 */
/* dn is the target number, with appropriate space */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) {
uInt msd; // coefficient MSD
uInt exp; // exponent top two bits
uInt comb; // combination field
Int need; // work
uInt uiwork; // for macros
uInt sourar[2]; // source 64-bit
#define sourhi sourar[1] // name the word with the sign
#define sourlo sourar[0] // and the lower word
// load source from storage; this is endian
if (DECLITEND) {
sourlo=UBTOUI(d64->bytes ); // directly load the low int
sourhi=UBTOUI(d64->bytes+4); // then the high int
}
else {
sourhi=UBTOUI(d64->bytes ); // directly load the high int
sourlo=UBTOUI(d64->bytes+4); // then the low int
}
comb=(sourhi>>26)&0x1f; // combination field
decNumberZero(dn); // clean number
if (sourhi&0x80000000) dn->bits=DECNEG; // set sign if negative
msd=COMBMSD[comb]; // decode the combination field
exp=COMBEXP[comb]; // ..
if (exp==3) { // is a special
if (msd==0) {
dn->bits|=DECINF;
return dn; // no coefficient needed
}
else if (sourhi&0x02000000) dn->bits|=DECSNAN;
else dn->bits|=DECNAN;
msd=0; // no top digit
}
else { // is a finite number
dn->exponent=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; // unbiased
}
// get the coefficient
sourhi&=0x0003ffff; // clean coefficient continuation
if (msd) { // non-zero msd
sourhi|=msd<<18; // prefix to coefficient
need=6; // process 6 declets
}
else { // msd=0
if (!sourhi) { // top word 0
if (!sourlo) return dn; // easy: coefficient is 0
need=3; // process at least 3 declets
if (sourlo&0xc0000000) need++; // process 4 declets
// [could reduce some more, here]
}
else { // some bits in top word, msd=0
need=4; // process at least 4 declets
if (sourhi&0x0003ff00) need++; // top declet!=0, process 5
}
} //msd=0
decDigitsFromDPD(dn, sourar, need); // process declets
return dn;
} // decimal64ToNumber
/* ------------------------------------------------------------------ */
/* to-scientific-string -- conversion to numeric string */
/* to-engineering-string -- conversion to numeric string */
/* */
/* decimal64ToString(d64, string); */
/* decimal64ToEngString(d64, string); */
/* */
/* d64 is the decimal64 format number to convert */
/* string is the string where the result will be laid out */
/* */
/* string must be at least 24 characters */
/* */
/* No error is possible, and no status can be set. */
/* ------------------------------------------------------------------ */
char * decimal64ToEngString(const decimal64 *d64, char *string){
decNumber dn; // work
decimal64ToNumber(d64, &dn);
decNumberToEngString(&dn, string);
return string;
} // decimal64ToEngString
char * decimal64ToString(const decimal64 *d64, char *string){
uInt msd; // coefficient MSD
Int exp; // exponent top two bits or full
uInt comb; // combination field
char *cstart; // coefficient start
char *c; // output pointer in string
const uByte *u; // work
char *s, *t; // .. (source, target)
Int dpd; // ..
Int pre, e; // ..
uInt uiwork; // for macros
uInt sourar[2]; // source 64-bit
#define sourhi sourar[1] // name the word with the sign
#define sourlo sourar[0] // and the lower word
// load source from storage; this is endian
if (DECLITEND) {
sourlo=UBTOUI(d64->bytes ); // directly load the low int
sourhi=UBTOUI(d64->bytes+4); // then the high int
}
else {
sourhi=UBTOUI(d64->bytes ); // directly load the high int
sourlo=UBTOUI(d64->bytes+4); // then the low int
}
c=string; // where result will go
if (((Int)sourhi)<0) *c++='-'; // handle sign
comb=(sourhi>>26)&0x1f; // combination field
msd=COMBMSD[comb]; // decode the combination field
exp=COMBEXP[comb]; // ..
if (exp==3) {
if (msd==0) { // infinity
strcpy(c, "Inf");
strcpy(c+3, "inity");
return string; // easy
}
if (sourhi&0x02000000) *c++='s'; // sNaN
strcpy(c, "NaN"); // complete word
c+=3; // step past
if (sourlo==0 && (sourhi&0x0003ffff)==0) return string; // zero payload
// otherwise drop through to add integer; set correct exp
exp=0; msd=0; // setup for following code
}
else exp=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias;
// convert 16 digits of significand to characters
cstart=c; // save start of coefficient
if (msd) *c++='0'+(char)msd; // non-zero most significant digit
// Now decode the declets. After extracting each one, it is
// decoded to binary and then to a 4-char sequence by table lookup;
// the 4-chars are a 1-char length (significant digits, except 000
// has length 0). This allows us to left-align the first declet
// with non-zero content, then remaining ones are full 3-char
// length. We use fixed-length memcpys because variable-length
// causes a subroutine call in GCC. (These are length 4 for speed
// and are safe because the array has an extra terminator byte.)
#define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \
if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \
else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}
dpd=(sourhi>>8)&0x3ff; // declet 1
dpd2char;
dpd=((sourhi&0xff)<<2) | (sourlo>>30); // declet 2
dpd2char;
dpd=(sourlo>>20)&0x3ff; // declet 3
dpd2char;
dpd=(sourlo>>10)&0x3ff; // declet 4
dpd2char;
dpd=(sourlo)&0x3ff; // declet 5
dpd2char;
if (c==cstart) *c++='0'; // all zeros -- make 0
if (exp==0) { // integer or NaN case -- easy
*c='\0'; // terminate
return string;
}
/* non-0 exponent */
e=0; // assume no E
pre=c-cstart+exp;
// [here, pre-exp is the digits count (==1 for zero)]
if (exp>0 || pre<-5) { // need exponential form
e=pre-1; // calculate E value
pre=1; // assume one digit before '.'
} // exponential form
/* modify the coefficient, adding 0s, '.', and E+nn as needed */
s=c-1; // source (LSD)
if (pre>0) { // ddd.ddd (plain), perhaps with E
char *dotat=cstart+pre;
if (dotat<c) { // if embedded dot needed...
t=c; // target
for (; s>=dotat; s--, t--) *t=*s; // open the gap; leave t at gap
*t='.'; // insert the dot
c++; // length increased by one
}
// finally add the E-part, if needed; it will never be 0, and has
// a maximum length of 3 digits
if (e!=0) {
*c++='E'; // starts with E
*c++='+'; // assume positive
if (e<0) {
*(c-1)='-'; // oops, need '-'
e=-e; // uInt, please
}
u=&BIN2CHAR[e*4]; // -> length byte
memcpy(c, u+4-*u, 4); // copy fixed 4 characters [is safe]
c+=*u; // bump pointer appropriately
}
*c='\0'; // add terminator
//printf("res %s\n", string);
return string;
} // pre>0
/* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
t=c+1-pre;
*(t+1)='\0'; // can add terminator now
for (; s>=cstart; s--, t--) *t=*s; // shift whole coefficient right
c=cstart;
*c++='0'; // always starts with 0.
*c++='.';
for (; pre<0; pre++) *c++='0'; // add any 0's after '.'
//printf("res %s\n", string);
return string;
} // decimal64ToString
/* ------------------------------------------------------------------ */
/* to-number -- conversion from numeric string */
/* */
/* decimal64FromString(result, string, set); */
/* */
/* result is the decimal64 format number which gets the result of */
/* the conversion */
/* *string is the character string which should contain a valid */
/* number (which may be a special value) */
/* set is the context */
/* */
/* The context is supplied to this routine is used for error handling */
/* (setting of status and traps) and for the rounding mode, only. */
/* If an error occurs, the result will be a valid decimal64 NaN. */
/* ------------------------------------------------------------------ */
decimal64 * decimal64FromString(decimal64 *result, const char *string,
decContext *set) {
decContext dc; // work
decNumber dn; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL64); // no traps, please
dc.round=set->round; // use supplied rounding
decNumberFromString(&dn, string, &dc); // will round if needed
decimal64FromNumber(result, &dn, &dc);
if (dc.status!=0) { // something happened
decContextSetStatus(set, dc.status); // .. pass it on
}
return result;
} // decimal64FromString
/* ------------------------------------------------------------------ */
/* decimal64IsCanonical -- test whether encoding is canonical */
/* d64 is the source decimal64 */
/* returns 1 if the encoding of d64 is canonical, 0 otherwise */
/* No error is possible. */
/* ------------------------------------------------------------------ */
uInt decimal64IsCanonical(const decimal64 *d64) {
decNumber dn; // work
decimal64 canon; // ..
decContext dc; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL64);
decimal64ToNumber(d64, &dn);
decimal64FromNumber(&canon, &dn, &dc);// canon will now be canonical
return memcmp(d64, &canon, DECIMAL64_Bytes)==0;
} // decimal64IsCanonical
/* ------------------------------------------------------------------ */
/* decimal64Canonical -- copy an encoding, ensuring it is canonical */
/* d64 is the source decimal64 */
/* result is the target (may be the same decimal64) */
/* returns result */
/* No error is possible. */
/* ------------------------------------------------------------------ */
decimal64 * decimal64Canonical(decimal64 *result, const decimal64 *d64) {
decNumber dn; // work
decContext dc; // ..
decContextDefault(&dc, DEC_INIT_DECIMAL64);
decimal64ToNumber(d64, &dn);
decimal64FromNumber(result, &dn, &dc);// result will now be canonical
return result;
} // decimal64Canonical
#if DECTRACE || DECCHECK
/* Macros for accessing decimal64 fields. These assume the
argument is a reference (pointer) to the decimal64 structure,
and the decimal64 is in network byte order (big-endian) */
// Get sign
#define decimal64Sign(d) ((unsigned)(d)->bytes[0]>>7)
// Get combination field
#define decimal64Comb(d) (((d)->bytes[0] & 0x7c)>>2)
// Get exponent continuation [does not remove bias]
#define decimal64ExpCon(d) ((((d)->bytes[0] & 0x03)<<6) \
| ((unsigned)(d)->bytes[1]>>2))
// Set sign [this assumes sign previously 0]
#define decimal64SetSign(d, b) { \
(d)->bytes[0]|=((unsigned)(b)<<7);}
// Set exponent continuation [does not apply bias]
// This assumes range has been checked and exponent previously 0;
// type of exponent must be unsigned
#define decimal64SetExpCon(d, e) { \
(d)->bytes[0]|=(uByte)((e)>>6); \
(d)->bytes[1]|=(uByte)(((e)&0x3F)<<2);}
/* ------------------------------------------------------------------ */
/* decimal64Show -- display a decimal64 in hexadecimal [debug aid] */
/* d64 -- the number to show */
/* ------------------------------------------------------------------ */
// Also shows sign/cob/expconfields extracted
void decimal64Show(const decimal64 *d64) {
char buf[DECIMAL64_Bytes*2+1];
Int i, j=0;
if (DECLITEND) {
for (i=0; i<DECIMAL64_Bytes; i++, j+=2) {
sprintf(&buf[j], "%02x", d64->bytes[7-i]);
}
printf(" D64> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
d64->bytes[7]>>7, (d64->bytes[7]>>2)&0x1f,
((d64->bytes[7]&0x3)<<6)| (d64->bytes[6]>>2));
}
else { // big-endian
for (i=0; i<DECIMAL64_Bytes; i++, j+=2) {
sprintf(&buf[j], "%02x", d64->bytes[i]);
}
printf(" D64> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
decimal64Sign(d64), decimal64Comb(d64), decimal64ExpCon(d64));
}
} // decimal64Show
#endif
/* ================================================================== */
/* Shared utility routines and tables */
/* ================================================================== */
// define and include the conversion tables to use for shared code
#if DECDPUN==3
#define DEC_DPD2BIN 1
#else
#define DEC_DPD2BCD 1
#endif
#include "decDPD.h" // lookup tables
// The maximum number of decNumberUnits needed for a working copy of
// the units array is the ceiling of digits/DECDPUN, where digits is
// the maximum number of digits in any of the formats for which this
// is used. decimal128.h must not be included in this module, so, as
// a very special case, that number is defined as a literal here.
#define DECMAX754 34
#define DECMAXUNITS ((DECMAX754+DECDPUN-1)/DECDPUN)
/* ------------------------------------------------------------------ */
/* Combination field lookup tables (uInts to save measurable work) */
/* */
/* COMBEXP - 2-bit most-significant-bits of exponent */
/* [11 if an Infinity or NaN] */
/* COMBMSD - 4-bit most-significant-digit */
/* [0=Infinity, 1=NaN if COMBEXP=11] */
/* */
/* Both are indexed by the 5-bit combination field (0-31) */
/* ------------------------------------------------------------------ */
const uInt COMBEXP[32]={0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2,
0, 0, 1, 1, 2, 2, 3, 3};
const uInt COMBMSD[32]={0, 1, 2, 3, 4, 5, 6, 7,
0, 1, 2, 3, 4, 5, 6, 7,
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 8, 9, 8, 9, 0, 1};
/* ------------------------------------------------------------------ */
/* decDigitsToDPD -- pack coefficient into DPD form */
/* */
/* dn is the source number (assumed valid, max DECMAX754 digits) */
/* targ is 1, 2, or 4-element uInt array, which the caller must */
/* have cleared to zeros */
/* shift is the number of 0 digits to add on the right (normally 0) */
/* */
/* The coefficient must be known small enough to fit. The full */
/* coefficient is copied, including the leading 'odd' digit. This */
/* digit is retrieved and packed into the combination field by the */
/* caller. */
/* */
/* The target uInts are altered only as necessary to receive the */
/* digits of the decNumber. When more than one uInt is needed, they */
/* are filled from left to right (that is, the uInt at offset 0 will */
/* end up with the least-significant digits). */
/* */
/* shift is used for 'fold-down' padding. */
/* */
/* No error is possible. */
/* ------------------------------------------------------------------ */
#if DECDPUN<=4
// Constant multipliers for divide-by-power-of five using reciprocal
// multiply, after removing powers of 2 by shifting, and final shift
// of 17 [we only need up to **4]
static const uInt multies[]={131073, 26215, 5243, 1049, 210};
// QUOT10 -- macro to return the quotient of unit u divided by 10**n
#define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17)
#endif
void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) {
Int cut; // work
Int n; // output bunch counter
Int digits=dn->digits; // digit countdown
uInt dpd; // densely packed decimal value
uInt bin; // binary value 0-999
uInt *uout=targ; // -> current output uInt
uInt uoff=0; // -> current output offset [from right]
const Unit *inu=dn->lsu; // -> current input unit
Unit uar[DECMAXUNITS]; // working copy of units, iff shifted
#if DECDPUN!=3 // not fast path
Unit in; // current unit
#endif
if (shift!=0) { // shift towards most significant required
// shift the units array to the left by pad digits and copy
// [this code is a special case of decShiftToMost, which could
// be used instead if exposed and the array were copied first]
const Unit *source; // ..
Unit *target, *first; // ..
uInt next=0; // work
source=dn->lsu+D2U(digits)-1; // where msu comes from
target=uar+D2U(digits)-1+D2U(shift);// where upper part of first cut goes
cut=DECDPUN-MSUDIGITS(shift); // where to slice
if (cut==0) { // unit-boundary case
for (; source>=dn->lsu; source--, target--) *target=*source;
}
else {
first=uar+D2U(digits+shift)-1; // where msu will end up
for (; source>=dn->lsu; source--, target--) {
// split the source Unit and accumulate remainder for next
#if DECDPUN<=4
uInt quot=QUOT10(*source, cut);
uInt rem=*source-quot*DECPOWERS[cut];
next+=quot;
#else
uInt rem=*source%DECPOWERS[cut];
next+=*source/DECPOWERS[cut];
#endif
if (target<=first) *target=(Unit)next; // write to target iff valid
next=rem*DECPOWERS[DECDPUN-cut]; // save remainder for next Unit
}
} // shift-move
// propagate remainder to one below and clear the rest
for (; target>=uar; target--) {
*target=(Unit)next;
next=0;
}
digits+=shift; // add count (shift) of zeros added
inu=uar; // use units in working array
}
/* now densely pack the coefficient into DPD declets */
#if DECDPUN!=3 // not fast path
in=*inu; // current unit
cut=0; // at lowest digit
bin=0; // [keep compiler quiet]
#endif
for(n=0; digits>0; n++) { // each output bunch
#if DECDPUN==3 // fast path, 3-at-a-time
bin=*inu; // 3 digits ready for convert
digits-=3; // [may go negative]
inu++; // may need another
#else // must collect digit-by-digit
Unit dig; // current digit
Int j; // digit-in-declet count
for (j=0; j<3; j++) {
#if DECDPUN<=4
Unit temp=(Unit)((uInt)(in*6554)>>16);
dig=(Unit)(in-X10(temp));
in=temp;
#else
dig=in%10;
in=in/10;
#endif
if (j==0) bin=dig;
else if (j==1) bin+=X10(dig);
else /* j==2 */ bin+=X100(dig);
digits--;
if (digits==0) break; // [also protects *inu below]
cut++;
if (cut==DECDPUN) {inu++; in=*inu; cut=0;}
}
#endif
// here there are 3 digits in bin, or have used all input digits
dpd=BIN2DPD[bin];
// write declet to uInt array
*uout|=dpd<<uoff;
uoff+=10;
if (uoff<32) continue; // no uInt boundary cross
uout++;
uoff-=32;
*uout|=dpd>>(10-uoff); // collect top bits
} // n declets
return;
} // decDigitsToDPD
/* ------------------------------------------------------------------ */
/* decDigitsFromDPD -- unpack a format's coefficient */
/* */
/* dn is the target number, with 7, 16, or 34-digit space. */
/* sour is a 1, 2, or 4-element uInt array containing only declets */
/* declets is the number of (right-aligned) declets in sour to */
/* be processed. This may be 1 more than the obvious number in */
/* a format, as any top digit is prefixed to the coefficient */
/* continuation field. It also may be as small as 1, as the */
/* caller may pre-process leading zero declets. */
/* */
/* When doing the 'extra declet' case care is taken to avoid writing */
/* extra digits when there are leading zeros, as these could overflow */
/* the units array when DECDPUN is not 3. */
/* */
/* The target uInts are used only as necessary to process declets */
/* declets into the decNumber. When more than one uInt is needed, */
/* they are used from left to right (that is, the uInt at offset 0 */
/* provides the least-significant digits). */
/* */
/* dn->digits is set, but not the sign or exponent. */
/* No error is possible [the redundant 888 codes are allowed]. */
/* ------------------------------------------------------------------ */
void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) {
uInt dpd; // collector for 10 bits
Int n; // counter
Unit *uout=dn->lsu; // -> current output unit
Unit *last=uout; // will be unit containing msd
const uInt *uin=sour; // -> current input uInt
uInt uoff=0; // -> current input offset [from right]
#if DECDPUN!=3
uInt bcd; // BCD result
uInt nibble; // work
Unit out=0; // accumulator
Int cut=0; // power of ten in current unit
#endif
#if DECDPUN>4
uInt const *pow; // work
#endif
// Expand the densely-packed integer, right to left
for (n=declets-1; n>=0; n--) { // count down declets of 10 bits
dpd=*uin>>uoff;
uoff+=10;
if (uoff>32) { // crossed uInt boundary
uin++;
uoff-=32; // [if using this code for wider, check this]
dpd|=*uin<<(10-uoff); // get waiting bits
}
dpd&=0x3ff; // clear uninteresting bits
#if DECDPUN==3
if (dpd==0) *uout=0;
else {
*uout=DPD2BIN[dpd]; // convert 10 bits to binary 0-999
last=uout; // record most significant unit
}
uout++;
} // n
#else // DECDPUN!=3
if (dpd==0) { // fastpath [e.g., leading zeros]
// write out three 0 digits (nibbles); out may have digit(s)
cut++;
if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
if (n==0) break; // [as below, works even if MSD=0]
cut++;
if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
cut++;
if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
continue;
}
bcd=DPD2BCD[dpd]; // convert 10 bits to 12 bits BCD
// now accumulate the 3 BCD nibbles into units
nibble=bcd & 0x00f;
if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]);
cut++;
if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
bcd>>=4;
// if this is the last declet and the remaining nibbles in bcd
// are 00 then process no more nibbles, because this could be
// the 'odd' MSD declet and writing any more Units would then
// overflow the unit array
if (n==0 && !bcd) break;
nibble=bcd & 0x00f;
if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]);
cut++;
if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
bcd>>=4;
nibble=bcd & 0x00f;
if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]);
cut++;
if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
} // n
if (cut!=0) { // some more left over
*uout=out; // write out final unit
if (out) last=uout; // and note if non-zero
}
#endif
// here, last points to the most significant unit with digits;
// inspect it to get the final digits count -- this is essentially
// the same code as decGetDigits in decNumber.c
dn->digits=(last-dn->lsu)*DECDPUN+1; // floor of digits, plus
// must be at least 1 digit
#if DECDPUN>1
if (*last<10) return; // common odd digit or 0
dn->digits++; // must be 2 at least
#if DECDPUN>2
if (*last<100) return; // 10-99
dn->digits++; // must be 3 at least
#if DECDPUN>3
if (*last<1000) return; // 100-999
dn->digits++; // must be 4 at least
#if DECDPUN>4
for (pow=&DECPOWERS[4]; *last>=*pow; pow++) dn->digits++;
#endif
#endif
#endif
#endif
return;
} //decDigitsFromDPD
+83
View File
@@ -0,0 +1,83 @@
/* ------------------------------------------------------------------ */
/* Decimal 64-bit format module header */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */
/* */
/* This software is made available under the terms of the */
/* ICU License -- ICU 1.8.1 and later. */
/* */
/* The description and User's Guide ("The decNumber C Library") for */
/* this software is called decNumber.pdf. This document is */
/* available, together with arithmetic and format specifications, */
/* testcases, and Web links, on the General Decimal Arithmetic page. */
/* */
/* Please send comments, suggestions, and corrections to the author: */
/* mfc@uk.ibm.com */
/* Mike Cowlishaw, IBM Fellow */
/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */
/* ------------------------------------------------------------------ */
#if !defined(DECIMAL64)
#define DECIMAL64
#define DEC64NAME "decimal64" /* Short name */
#define DEC64FULLNAME "Decimal 64-bit Number" /* Verbose name */
#define DEC64AUTHOR "Mike Cowlishaw" /* Who to blame */
/* parameters for decimal64s */
#define DECIMAL64_Bytes 8 /* length */
#define DECIMAL64_Pmax 16 /* maximum precision (digits) */
#define DECIMAL64_Emax 384 /* maximum adjusted exponent */
#define DECIMAL64_Emin -383 /* minimum adjusted exponent */
#define DECIMAL64_Bias 398 /* bias for the exponent */
#define DECIMAL64_String 24 /* maximum string length, +1 */
#define DECIMAL64_EconL 8 /* exp. continuation length */
/* highest biased exponent (Elimit-1) */
#define DECIMAL64_Ehigh (DECIMAL64_Emax+DECIMAL64_Bias-DECIMAL64_Pmax+1)
/* check enough digits, if pre-defined */
#if defined(DECNUMDIGITS)
#if (DECNUMDIGITS<DECIMAL64_Pmax)
#error decimal64.h needs pre-defined DECNUMDIGITS>=16 for safe use
#endif
#endif
#ifndef DECNUMDIGITS
#define DECNUMDIGITS DECIMAL64_Pmax /* size if not already defined*/
#endif
#ifndef DECNUMBER
#include "decNumber.h" /* context and number library */
#endif
/* Decimal 64-bit type, accessible by bytes */
typedef struct {
uint8_t bytes[DECIMAL64_Bytes]; /* decimal64: 1, 5, 8, 50 bits*/
} decimal64;
/* special values [top byte excluding sign bit; last two bits are */
/* don't-care for Infinity on input, last bit don't-care for NaN] */
#if !defined(DECIMAL_NaN)
#define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */
#define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */
#define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */
#endif
/* ---------------------------------------------------------------- */
/* Routines */
/* ---------------------------------------------------------------- */
/* String conversions */
decimal64 * decimal64FromString(decimal64 *, const char *, decContext *);
char * decimal64ToString(const decimal64 *, char *);
char * decimal64ToEngString(const decimal64 *, char *);
/* decNumber conversions */
decimal64 * decimal64FromNumber(decimal64 *, const decNumber *,
decContext *);
decNumber * decimal64ToNumber(const decimal64 *, decNumber *);
/* Format-dependent utilities */
uint32_t decimal64IsCanonical(const decimal64 *);
decimal64 * decimal64Canonical(decimal64 *, const decimal64 *);
#endif
Binary file not shown.
+38
View File
@@ -0,0 +1,38 @@
/* ------------------------------------------------------------------ */
/* Decimal Number Library Demonstration program */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2001, 2007. All rights reserved. */
/* ----------------------------------------------------------------+- */
/* right margin -->| */
// example1.c -- convert the first two argument words to decNumber,
// add them together, and display the result
#define DECNUMDIGITS 34 // work with up to 34 digits
#include "decNumber.h" // base number library
#include <stdio.h> // for printf
int main(int argc, char *argv[]) {
decNumber a, b; // working numbers
decContext set; // working context
char string[DECNUMDIGITS+14]; // conversion buffer
decContextTestEndian(0); // warn if DECLITEND is wrong
if (argc<3) { // not enough words
printf("Please supply two numbers to add.\n");
return 1;
}
decContextDefault(&set, DEC_INIT_BASE); // initialize
set.traps=0; // no traps, thank you
set.digits=DECNUMDIGITS; // set precision
decNumberFromString(&a, argv[1], &set);
decNumberFromString(&b, argv[2], &set);
decNumberAdd(&a, &a, &b, &set); // a=a+b
decNumberToString(&a, string);
printf("%s + %s => %s\n", argv[1], argv[2], string);
return 0;
} // main
+52
View File
@@ -0,0 +1,52 @@
/* ------------------------------------------------------------------ */
/* Decimal Number Library Demonstration program */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2001. All rights reserved. */
/* ----------------------------------------------------------------+- */
/* right margin -->| */
// example2.c -- calculate compound interest
// Arguments are investment, rate (%), and years
#define DECNUMDIGITS 38 // work with up to 38 digits
#include "decNumber.h" // base number library
#include <stdio.h> // for printf
int main(int argc, char *argv[]) {
int need=3;
if (argc<need+1) { // not enough words
printf("Please supply %d number(s).\n", need);
return 1;
}
{ // excerpt for User's Guide starts here--------------------------|
decNumber one, mtwo, hundred; // constants
decNumber start, rate, years; // parameters
decNumber total; // result
decContext set; // working context
char string[DECNUMDIGITS+14]; // conversion buffer
decContextDefault(&set, DEC_INIT_BASE); // initialize
set.traps=0; // no traps
set.digits=25; // precision 25
decNumberFromString(&one, "1", &set); // set constants
decNumberFromString(&mtwo, "-2", &set);
decNumberFromString(&hundred, "100", &set);
decNumberFromString(&start, argv[1], &set); // parameter words
decNumberFromString(&rate, argv[2], &set);
decNumberFromString(&years, argv[3], &set);
decNumberDivide(&rate, &rate, &hundred, &set); // rate=rate/100
decNumberAdd(&rate, &rate, &one, &set); // rate=rate+1
decNumberPower(&rate, &rate, &years, &set); // rate=rate^years
decNumberMultiply(&total, &rate, &start, &set); // total=rate*start
decNumberRescale(&total, &total, &mtwo, &set); // two digits please
decNumberToString(&total, string);
printf("%s at %s%% for %s years => %s\n",
argv[1], argv[2], argv[3], string);
} //---------------------------------------------------------------|
return 0;
} // main
+64
View File
@@ -0,0 +1,64 @@
/* ------------------------------------------------------------------ */
/* Decimal Number Library Demonstration program */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2001. All rights reserved. */
/* ----------------------------------------------------------------+- */
/* right margin -->| */
// example3.c -- calculate compound interest, passive checking
// Arguments are investment, rate (%), and years
#define DECNUMDIGITS 38 // work with up to 38 digits
#include "decNumber.h" // base number library
#include <stdio.h> // for printf
int main(int argc, char *argv[]) {
int need=3;
if (argc<need+1) { // not enough words
printf("Please supply %d number(s).\n", need);
return 1;
}
{ // start of Example 2 segment
decNumber one, mtwo, hundred; // constants
decNumber start, rate, years; // parameters
decNumber total; // result
decContext set; // working context
char string[DECNUMDIGITS+14]; // conversion buffer
decContextDefault(&set, DEC_INIT_BASE); // initialize
set.traps=0; // no traps
set.digits=25; // precision 25
decNumberFromString(&one, "1", &set); // set constants
decNumberFromString(&mtwo, "-2", &set);
decNumberFromString(&hundred, "100", &set);
// [snip...
decNumberFromString(&start, argv[1], &set); // parameter words
decNumberFromString(&rate, argv[2], &set);
decNumberFromString(&years, argv[3], &set);
if (set.status & DEC_Errors) {
printf("An input argument word was invalid [%s]\n",
decContextStatusToString(&set));
return 1;
}
decNumberDivide(&rate, &rate, &hundred, &set); // rate=rate/100
decNumberAdd(&rate, &rate, &one, &set); // rate=rate+1
decNumberPower(&rate, &rate, &years, &set); // rate=rate^years
decNumberMultiply(&total, &rate, &start, &set); // total=rate*start
decNumberRescale(&total, &total, &mtwo, &set); // two digits please
if (set.status & DEC_Errors) {
set.status &= DEC_Errors; // keep only errors
printf("Result could not be calculated [%s]\n",
decContextStatusToString(&set));
return 1;
}
// ...snip]
decNumberToString(&total, string);
printf("%s at %s%% for %s years => %s\n",
argv[1], argv[2], argv[3], string);
} //---------------------------------------------------------------|
return 0;
} // main
+61
View File
@@ -0,0 +1,61 @@
/* ------------------------------------------------------------------ */
/* Decimal Number Library Demonstration program */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2001. All rights reserved. */
/* ----------------------------------------------------------------+- */
/* right margin -->| */
// example4.c -- add two numbers, active error handling
// Arguments are two numbers
#define DECNUMDIGITS 38 // work with up to 38 digits
#include "decNumber.h" // base number library
#include <stdio.h> // for printf
// [snip...
#include <signal.h> // signal handling
#include <setjmp.h> // setjmp/longjmp
jmp_buf preserve; // stack snapshot
void signalHandler(int); // prototype for GCC
void signalHandler(int sig) {
signal(SIGFPE, signalHandler); // re-enable
longjmp(preserve, sig); // branch to preserved point
}
// ...snip]
int main(int argc, char *argv[]) {
decNumber a, b; // working numbers
decContext set; // working context
char string[DECNUMDIGITS+14]; // conversion buffer
int value; // work variable
if (argc<3) { // not enough words
printf("Please supply two numbers to add.\n");
return 1;
}
decContextDefault(&set, DEC_INIT_BASE); // initialize
// [snip...
signal(SIGFPE, signalHandler); // set up signal handler
value=setjmp(preserve); // preserve and test environment
if (value) { // (non-0 after longjmp)
set.status &= DEC_Errors; // keep only errors
printf("Signal trapped [%s].\n", decContextStatusToString(&set));
return 1;
}
// ...snip]
// [change from Example 1, here]
// leave traps enabled
set.digits=DECNUMDIGITS; // set precision
decNumberFromString(&a, argv[1], &set);
decNumberFromString(&b, argv[2], &set);
decNumberAdd(&a, &a, &b, &set); // A=A+B
decNumberToString(&a, string);
printf("%s + %s => %s\n", argv[1], argv[2], string);
return 0;
} // main
+36
View File
@@ -0,0 +1,36 @@
/* ------------------------------------------------------------------ */
/* Decimal Number Library Demonstration program */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2001, 2007. All rights reserved. */
/* ----------------------------------------------------------------+- */
/* right margin -->| */
// example5.c -- decimal64 conversions
#include "decimal64.h" // decimal64 and decNumber library
#include <stdio.h> // for (s)printf
int main(int argc, char *argv[]) {
decimal64 a; // working decimal64 number
decNumber d; // working number
decContext set; // working context
char string[DECIMAL64_String]; // number->string buffer
char hexes[25]; // decimal64->hex buffer
int i; // counter
if (argc<2) { // not enough words
printf("Please supply a number.\n");
return 1;
}
decContextDefault(&set, DEC_INIT_DECIMAL64); // initialize
decimal64FromString(&a, argv[1], &set);
// lay out the decimal64 as eight hexadecimal pairs
for (i=0; i<8; i++) {
sprintf(&hexes[i*3], "%02x ", a.bytes[i]);
}
decimal64ToNumber(&a, &d);
decNumberToString(&d, string);
printf("%s => %s=> %s\n", argv[1], hexes, string);
return 0;
} // main
+61
View File
@@ -0,0 +1,61 @@
/* ------------------------------------------------------------------ */
/* Decimal Number Library Demonstration program */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2001. All rights reserved. */
/* ----------------------------------------------------------------+- */
/* right margin -->| */
// example6.c -- calculate compound interest, using Packed Decimal
// Values are investment, rate (%), and years
#include "decPacked.h" // base number library
#include <stdio.h> // for printf
int main(int argc, char *argv[]) {
{ // excerpt for User's Guide starts here--------------------------|
decNumber one, mtwo, hundred; // constants
decNumber start, rate, years; // parameters
decNumber total; // result
decContext set; // working context
uint8_t startpack[]={0x01, 0x00, 0x00, 0x0C}; // investment=100000
int32_t startscale=0;
uint8_t ratepack[]={0x06, 0x5C}; // rate=6.5%
int32_t ratescale=1;
uint8_t yearspack[]={0x02, 0x0C}; // years=20
int32_t yearsscale=0;
uint8_t respack[16]; // result, packed
int32_t resscale; // ..
char hexes[49]; // for packed->hex
int i; // counter
if (argc<0) printf("%s", argv[1]); // noop for warning
decContextDefault(&set, DEC_INIT_BASE); // initialize
set.traps=0; // no traps
set.digits=25; // precision 25
decNumberFromString(&one, "1", &set); // set constants
decNumberFromString(&mtwo, "-2", &set);
decNumberFromString(&hundred, "100", &set);
decPackedToNumber(startpack, sizeof(startpack), &startscale, &start);
decPackedToNumber(ratepack, sizeof(ratepack), &ratescale, &rate);
decPackedToNumber(yearspack, sizeof(yearspack), &yearsscale, &years);
decNumberDivide(&rate, &rate, &hundred, &set); // rate=rate/100
decNumberAdd(&rate, &rate, &one, &set); // rate=rate+1
decNumberPower(&rate, &rate, &years, &set); // rate=rate^years
decNumberMultiply(&total, &rate, &start, &set); // total=rate*start
decNumberRescale(&total, &total, &mtwo, &set); // two digits please
decPackedFromNumber(respack, sizeof(respack), &resscale, &total);
// lay out the total as sixteen hexadecimal pairs
for (i=0; i<16; i++) {
sprintf(&hexes[i*3], "%02x ", respack[i]);
}
printf("Result: %s (scale=%ld)\n", hexes, (long int)resscale);
} //---------------------------------------------------------------|
return 0;
} // main
+35
View File
@@ -0,0 +1,35 @@
/* ------------------------------------------------------------------ */
/* Decimal Number Library Demonstration program */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2001, 2008. All rights reserved. */
/* ----------------------------------------------------------------+- */
/* right margin -->| */
// example7.c -- using decQuad to add two numbers together
// compile: example7.c decContext.c decQuad.c
#include "decQuad.h" // decQuad library
#include <stdio.h> // for printf
int main(int argc, char *argv[]) {
decQuad a, b; // working decQuads
decContext set; // working context
char string[DECQUAD_String]; // number->string buffer
decContextTestEndian(0); // warn if DECLITEND is wrong
if (argc<3) { // not enough words
printf("Please supply two numbers to add.\n");
return 1;
}
decContextDefault(&set, DEC_INIT_DECQUAD); // initialize
decQuadFromString(&a, argv[1], &set);
decQuadFromString(&b, argv[2], &set);
decQuadAdd(&a, &a, &b, &set); // a=a+b
decQuadToString(&a, string);
printf("%s + %s => %s\n", argv[1], argv[2], string);
return 0;
} // main
+39
View File
@@ -0,0 +1,39 @@
/* ------------------------------------------------------------------ */
/* Decimal Number Library Demonstration program */
/* ------------------------------------------------------------------ */
/* Copyright (c) IBM Corporation, 2001, 2007. All rights reserved. */
/* ----------------------------------------------------------------+- */
/* right margin -->| */
// example8.c -- using decQuad with the decNumber module
// compile: example8.c decContext.c decQuad.c
// and: decNumber.c decimal128.c decimal64.c
#include "decQuad.h" // decQuad library
#include "decimal128.h" // interface to decNumber
#include <stdio.h> // for printf
int main(int argc, char *argv[]) {
decQuad a; // working decQuad
decNumber numa, numb; // working decNumbers
decContext set; // working context
char string[DECQUAD_String]; // number->string buffer
if (argc<3) { // not enough words
printf("Please supply two numbers for power(2*a, b).\n");
return 1;
}
decContextDefault(&set, DEC_INIT_DECQUAD); // initialize
decQuadFromString(&a, argv[1], &set); // get a
decQuadAdd(&a, &a, &a, &set); // double a
decQuadToNumber(&a, &numa); // convert to decNumber
decNumberFromString(&numb, argv[2], &set);
decNumberPower(&numa, &numa, &numb, &set); // numa=numa**numb
decQuadFromNumber(&a, &numa, &set); // back via a Quad
decQuadToString(&a, string); // ..
printf("power(2*%s, %s) => %s\n", argv[1], argv[2], string);
return 0;
} // main
+81
View File
@@ -0,0 +1,81 @@
This is the readme.txt for the decNumber package. It includes
instructions for compiling and testing the package; please read them.
---------------------------------------------------------------------
decNumber is distributed in two forms; as a complete package from
the International Components for Unicode (ICU) site (under an as-is
license), or as a collection of Open Source files from the GCC source
repository (under the GPL license).
If you are using the GCC files, you can obtain the documentation, the
example files mentioned below, and this readme from the General
Decimal Arithmetic web page -- http://speleotrove.com/decimal/ (the
URL for the open source files is also linked from there).
The ICU package
---------------
The ICU package includes the files:
* readme.txt (this file)
* ICU-license.html
* decNumber.pdf (documentation)
* The .c and .h file for each module in the package (see the
decNumber documentation), together with other included files.
* The .c files for each of the examples (example1.c through
example8.c).
The ICU package is made available under the terms of the ICU License
(ICU 1.8.1 and later) included in the package as ICU-license.html.
Your use of that package indicates your acceptance of the terms and
conditions of that Agreement.
To use and check decNumber
--------------------------
Please read the appropriate license and documentation before using
this package. If you are upgrading an existing use of decNumber
(with version <= 3.37) please read the Changes Appendix for later
versions -- you may need to change the DECLITEND flag.
1. Compile and link example1.c, decNumber.c, and decContext.c
For instance, use:
gcc -o example1 example1.c decNumber.c decContext.c
Note: If your compiler does not provide stdint.h or if your C
compiler does not handle line comments (// ...), then see the
User's Guide section in the documentation for further information
(including a sample minimal stdint.h).
The use of compiler optimization is strongly recommended (e.g.,
-O3 for GCC or /O2 for Visual Studio).
2. Run example1 with two numeric arguments, for example:
example1 1.23 1.27
this should display:
1.23 + 1.27 => 2.50
3. Similarly, try the other examples, at will.
Examples 2->4 require three files to be compiled, like Example 1.
Example 5 requires decimal64.c in addition to the core modules.
Example 6 requires decPacked.c in addition to the core modules.
Example 7 requires only example7.c decContext.c and decQuad.c
Example 8 requires example8.c, decContext.c, and decQuad.c, plus
decNumber.c, decimal128.c, and decimal64.c (the latter
for shared tables and code)
+101
View File
@@ -0,0 +1,101 @@
Skipped 9 tests
Testing '.[0]' at line number 37
Hit the number of tests limit (1), breaking
1 of 1 tests passed (0 malformed)
==9681== 17 bytes in 1 blocks are definitely lost in loss record 4 of 45
==9681== at 0x100180545: malloc (vg_replace_malloc.c:302)
==9681== by 0x1000240D8: jv_mem_alloc (jv_alloc.c:122)
==9681== by 0x10001F425: jv_number_with_literal (jv.c:193)
==9681== by 0x10002F9C8: check_literal (jv_parse.c:508)
==9681== by 0x10002EAA4: jv_parser_next (jv_parse.c:797)
==9681== by 0x10002FBF2: jv_parse_sized (jv_parse.c:830)
==9681== by 0x10003544B: jq_yylex (lexer.l:90)
==9681== by 0x100036FB4: yylex (parser.y:153)
==9681== by 0x100037352: yyparse (parser.c:2292)
==9681== by 0x10003B0FD: jq_parse (parser.y:967)
==9681== by 0x100032CD4: load_program (linker.c:374)
==9681== by 0x10001C5B3: jq_compile_args (execute.c:1172)
==9681==
Skipped 10 tests
Testing '.[2]' at line number 41
Hit the number of tests limit (1), breaking
1 of 1 tests passed (0 malformed)
==9690== 17 bytes in 1 blocks are definitely lost in loss record 4 of 45
==9690== at 0x100180545: malloc (vg_replace_malloc.c:302)
==9690== by 0x1000240D8: jv_mem_alloc (jv_alloc.c:122)
==9690== by 0x10001F425: jv_number_with_literal (jv.c:193)
==9690== by 0x10002F9C8: check_literal (jv_parse.c:508)
==9690== by 0x10002EAA4: jv_parser_next (jv_parse.c:797)
==9690== by 0x10002FBF2: jv_parse_sized (jv_parse.c:830)
==9690== by 0x10003544B: jq_yylex (lexer.l:90)
==9690== by 0x100036FB4: yylex (parser.y:153)
==9690== by 0x100037352: yyparse (parser.c:2292)
==9690== by 0x10003B0FD: jq_parse (parser.y:967)
==9690== by 0x100032CD4: load_program (linker.c:374)
==9690== by 0x10001C5B3: jq_compile_args (execute.c:1172)
==9690==
Skipped 12 tests
Testing '.[2:4]' at line number 49
Hit the number of tests limit (1), breaking
1 of 1 tests passed (0 malformed)
==9713== 34 bytes in 2 blocks are definitely lost in loss record 15 of 45
==9713== at 0x100180545: malloc (vg_replace_malloc.c:302)
==9713== by 0x1000240D8: jv_mem_alloc (jv_alloc.c:122)
==9713== by 0x10001F425: jv_number_with_literal (jv.c:193)
==9713== by 0x10002F9C8: check_literal (jv_parse.c:508)
==9713== by 0x10002EAA4: jv_parser_next (jv_parse.c:797)
==9713== by 0x10002FBF2: jv_parse_sized (jv_parse.c:830)
==9713== by 0x10003544B: jq_yylex (lexer.l:90)
==9713== by 0x100036FB4: yylex (parser.y:153)
==9713== by 0x100037352: yyparse (parser.c:2292)
==9713== by 0x10003B0FD: jq_parse (parser.y:967)
==9713== by 0x100032CD4: load_program (linker.c:374)
==9713== by 0x10001C5B3: jq_compile_args (execute.c:1172)
==9713==
Skipped 13 tests
Testing '.[2:4]' at line number 53
Hit the number of tests limit (1), breaking
1 of 1 tests passed (0 malformed)
==9714== 34 bytes in 2 blocks are definitely lost in loss record 15 of 45
==9714== at 0x100180545: malloc (vg_replace_malloc.c:302)
==9714== by 0x1000240D8: jv_mem_alloc (jv_alloc.c:122)
==9714== by 0x10001F425: jv_number_with_literal (jv.c:193)
==9714== by 0x10002F9C8: check_literal (jv_parse.c:508)
==9714== by 0x10002EAA4: jv_parser_next (jv_parse.c:797)
==9714== by 0x10002FBF2: jv_parse_sized (jv_parse.c:830)
==9714== by 0x10003544B: jq_yylex (lexer.l:90)
==9714== by 0x100036FB4: yylex (parser.y:153)
==9714== by 0x100037352: yyparse (parser.c:2292)
==9714== by 0x10003B0FD: jq_parse (parser.y:967)
==9714== by 0x100032CD4: load_program (linker.c:374)
==9714== by 0x10001C5B3: jq_compile_args (execute.c:1172)
==9714==
Skipped 14 tests
Testing '.[:3]' at line number 57
Hit the number of tests limit (1), breaking
1 of 1 tests passed (0 malformed)
==9715== 17 bytes in 1 blocks are definitely lost in loss record 4 of 45
==9715== at 0x100180545: malloc (vg_replace_malloc.c:302)
==9715== by 0x1000240D8: jv_mem_alloc (jv_alloc.c:122)
==9715== by 0x10001F425: jv_number_with_literal (jv.c:193)
==9715== by 0x10002F9C8: check_literal (jv_parse.c:508)
==9715== by 0x10002EAA4: jv_parser_next (jv_parse.c:797)
==9715== by 0x10002FBF2: jv_parse_sized (jv_parse.c:830)
==9715== by 0x10003544B: jq_yylex (lexer.l:90)
==9715== by 0x100036FB4: yylex (parser.y:153)
==9715== by 0x100037352: yyparse (parser.c:2292)
==9715== by 0x10003B0FD: jq_parse (parser.y:967)
==9715== by 0x100032CD4: load_program (linker.c:374)
==9715== by 0x10001C5B3: jq_compile_args (execute.c:1172)
==9715==
Skipped 19 tests
Testing '.foo, .bar' at line number 78
Hit the number of tests limit (1), breaking
1 of 1 tests passed (0 malformed)