Implements interface Decimal.
Decimal impl | Implements interface Decimal. |
Copyright | This program is free software. |
Files | |
C-kern/ | Header file Decimal. |
C-kern/ | Implementation file Decimal impl. |
Types | |
struct decimal_frombigint_t | Export decimal_frombigint_t into global namespace. |
struct decimal_frombigint_state_t | Export decimal_frombigint_state_t into global namespace. |
struct alignedexpandshift_t | Export alignedexpandshift_t into global namespace. |
struct decimal_divstate_t | Export decimal_divstate_t into global namespace. |
shiftleft10p_f | A function which computes the decimal left shift of digit. |
alignedexpandshift_t | Stores an exponent of DIGITSBASE and a reference to a shift-left function. |
decimal_frombigint_state_t | Holds the modulo result of a division of a bigint_t. |
Variables | |
big | A preallocated bigint_t. |
tabidx | References a divisor in s_decimal_powbase. |
decimal_frombigint_t | Type holding state for conversion from bigint_t into decimal_t. |
Variables | |
state | state[0] holds the result of the first division. |
decimal_divstate_t | Used in div_decimalhelper to store current state of division computation. |
decimal_t | |
static variables | |
s_decimal_errtimer | Simulates an error in different functions. |
s_decimal_powbase | Tables of powers of pow(10,9) used to convert bigint_t, float, double, into decimal_t. |
decimal_powbase | |
tableindex_decimalpowbase | Returns index into table s_decimal_powbase. |
tableindexfromdecsize_decimalpowbase | Returns index into table s_decimal_powbase. |
decsize_decimalpowbase | Returns size of decimal_t needed to represent <s_decimal_powbase>[tableindex]. |
decimal_frombigint_t | |
helper | |
DIGITSBASE | The base of a digit in array decimal_t.digits. |
BIGINT_MAXSIZE | The number of digits of bigint_t which may be converted to decimal_t without overflow. |
power10_decimalhelper | Calculates pow(10, exponent) for 0 <= exponent <= 9. |
determinehshiftleft_decimalhelper | Returns shiftleft10p_f for argument decimal_exponent_x. |
alignexponent_decimalhelper | Returns the difference between decimal_exponent and the aligned exponent. |
allocate_decimalhelper | Does the real allocation / reallocation. |
add_decimalhelper | Implements adding of two decimal numbers. |
sub_decimalhelper | Implements subtraction of two decimal numbers. |
mult_decimalhelper | Multiplies two decimal numbers and returns the positive result. |
addsplit_decimalhelper | Implements adding of two positive decimal numbers. |
multsplit_decimalhelper | Multiplies two decimal numbers and returns the positive result. |
div3by2digits_decimalhelper | Computes ((dividend * DIGITSBASE + nextdigit) / divisor). |
submul_decimalhelper | Computes »ldigits[*]-=nextdigit*rdigits[*]« and corrects nextdigit with -1 if necessary. |
div_decimalhelper | Divides two decimal numbers and returns the positive quotient. |
divi32_decimalhelper | Divides decimal number by integer and returns the positive quotient. |
nrzerobits2nrdigits_decimalhelper | Returns the nr of zero decimal digits calculated from the number of zero bits. |
nrzerobits2decsize_decimalhelper | See nrzerobits2nrdigits_decimalhelper. |
nrzerodigits2nrbits_decimalhelper | Returns the nr of zero bits calculated from the number of zero decimal digits. |
calcfractionsize_decimalhelper | Calculates the number of digits needed to represent a binary fraction. |
digit2str_decimalhelper | Writes a decimal representation of digit into string str. |
lifetime | |
query | |
assign | |
ternary operations | |
test | |
test_example1 | Evaluate f(a = 77617, b = 33096) |
This program is free software. You can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
© 2012 Jörg Seebohn
Header file Decimal.
Implementation file Decimal impl.
typedef struct decimal_frombigint_t decimal_frombigint_t
Export decimal_frombigint_t into global namespace.
typedef struct decimal_frombigint_state_t decimal_frombigint_state_t
Export decimal_frombigint_state_t into global namespace.
typedef struct alignedexpandshift_t alignedexpandshift_t
Export alignedexpandshift_t into global namespace.
typedef struct decimal_divstate_t decimal_divstate_t
Export decimal_divstate_t into global namespace.
typedef uint32_t ( * shiftleft10p_f ) (/*inout*/uint32_t * shiftcarry, uint32_t shiftdigit)
A function which computes the decimal left shift of digit. The computed return value is:
shiftcarry + (shiftdigit % pow(10,9-x)) * pow(10,x)
Where x is number of decimal digits this function shifts to the left. The processing order for a left shift is from least significant first up to most significant last. Before return parameter shiftcarry is set to:
shiftdigit / pow(10,9-x)
which becomes the next shiftcarry.
unsigned tabidx
References a divisor in s_decimal_powbase.
decimal_frombigint_state_t state[7]
state[0] holds the result of the first division.
--------------------------------------------------------------- | state[0] | state[1] | ... | 1 == size_bigint(state[X]->big) | ---------------------------------------------------------------
The division process is repeated until the quotient becomes a number in the range [0 .. DIGITSBASE-1].
struct decimal_divstate_t
Used in div_decimalhelper to store current state of division computation.
static variables | |
s_decimal_errtimer | Simulates an error in different functions. |
s_decimal_powbase | Tables of powers of pow(10,9) used to convert bigint_t, float, double, into decimal_t. |
decimal_powbase | |
tableindex_decimalpowbase | Returns index into table s_decimal_powbase. |
tableindexfromdecsize_decimalpowbase | Returns index into table s_decimal_powbase. |
decsize_decimalpowbase | Returns size of decimal_t needed to represent <s_decimal_powbase>[tableindex]. |
decimal_frombigint_t | |
helper | |
DIGITSBASE | The base of a digit in array decimal_t.digits. |
BIGINT_MAXSIZE | The number of digits of bigint_t which may be converted to decimal_t without overflow. |
power10_decimalhelper | Calculates pow(10, exponent) for 0 <= exponent <= 9. |
determinehshiftleft_decimalhelper | Returns shiftleft10p_f for argument decimal_exponent_x. |
alignexponent_decimalhelper | Returns the difference between decimal_exponent and the aligned exponent. |
allocate_decimalhelper | Does the real allocation / reallocation. |
add_decimalhelper | Implements adding of two decimal numbers. |
sub_decimalhelper | Implements subtraction of two decimal numbers. |
mult_decimalhelper | Multiplies two decimal numbers and returns the positive result. |
addsplit_decimalhelper | Implements adding of two positive decimal numbers. |
multsplit_decimalhelper | Multiplies two decimal numbers and returns the positive result. |
div3by2digits_decimalhelper | Computes ((dividend * DIGITSBASE + nextdigit) / divisor). |
submul_decimalhelper | Computes »ldigits[*]-=nextdigit*rdigits[*]« and corrects nextdigit with -1 if necessary. |
div_decimalhelper | Divides two decimal numbers and returns the positive quotient. |
divi32_decimalhelper | Divides decimal number by integer and returns the positive quotient. |
nrzerobits2nrdigits_decimalhelper | Returns the nr of zero decimal digits calculated from the number of zero bits. |
nrzerobits2decsize_decimalhelper | See nrzerobits2nrdigits_decimalhelper. |
nrzerodigits2nrbits_decimalhelper | Returns the nr of zero bits calculated from the number of zero decimal digits. |
calcfractionsize_decimalhelper | Calculates the number of digits needed to represent a binary fraction. |
digit2str_decimalhelper | Writes a decimal representation of digit into string str. |
lifetime | |
query | |
assign | |
ternary operations | |
test | |
test_example1 | Evaluate f(a = 77617, b = 33096) |
static inline unsigned tableindex_decimalpowbase( uint32_t bigintsize )
Returns index into table s_decimal_powbase. The index is calculated from the size of the bigint_t. Check the returned index if it is < lengthof(s_decimal_powbase). If it is out of range than bigintsize is too big.
1. bigintsize <= BIGINT_MAXSIZE The highest index ti is returned for which the following is true. size_bigint(s_decimal_powbase[ti)) <= bigintsize 2. bigintsize > BIGINT_MAXSIZE Returns index ti overflowing size of s_decimal_powbase.
static inline unsigned tableindexfromdecsize_decimalpowbase( uint32_t decsize )
Returns index into table s_decimal_powbase. If the preconditions are not met the returned index is either wrong or out of range.
Preconditions are not checked.
1. decsize >= 1 2. decsize <= 64 (64*9 == 576)
#define DIGITSBASE ( (uint32_t)1000000000 )
The base of a digit in array decimal_t.digits. To calculate the value of a single digit use the formula:
decimal_t * dec = ... ; double digit_value[size_decimal(dec)] ; for (unsigned i = 0; i < size_decimal(dec); ++i) digit_value[i] = dec->digits[i] * pow(DIGITSBASE, i) * pow(10, dec->decimal_exponent) ;
static shiftleft10p_f determinehshiftleft_decimalhelper( uint32_t shiftcount )
Returns shiftleft10p_f for argument decimal_exponent_x. The argument must be a value between 0 and 8. The value 0 calls a function which returns an unshifted number.
static inline int alignexponent_decimalhelper( /*out*/uint32_t * exponent_correction, int32_t decimal_exponent )
Returns the difference between decimal_exponent and the aligned exponent. If you subtract the returned value in exponent_correction from the decimal exponent you get the aligned exponent.
static int allocate_decimalhelper( decimal_t *restrict * dec, uint32_t size_allocate )
Does the real allocation / reallocation. In case parameter dec does not point to a NULL pointer, it is considered to point to a valid reference to a decimal_t previously allocated by this function. In this case a reallocation is done - if allocate_digits is higher than decimal_t.size_allocated.
static void mult_decimalhelper( decimal_t * dec, uint8_t lsize, const uint32_t * ldigits, uint8_t rsize, const uint32_t * rdigits, int16_t exponent )
Multiplies two decimal numbers and returns the positive result. The numbers are represented with their size and digits array. This allows for splitting the nummbers without allocating a new decimal_t.
1. | result must be allocated with size == (lsize + rsize) |
2. | (lsize > 0 && rsize > 0) |
3. | lsize <= rsize |
4. | ldigits[lsize-1] != 0 && rdigits[rsize-1] != 0 |
static void addsplit_decimalhelper( decimal_t * restrict result, uint8_t digitsoffset, uint8_t lsize, const uint32_t * ldigits, uint8_t rsize, const uint32_t * rdigits )
Implements adding of two positive decimal numbers.
1. | result must be allocated with size >= (lsize + rsize) |
2. | (lsize > 0 && rsize > 0) |
3. | ldigits[lsize-1] != 0 && rdigits[rsize-1] != 0 |
4. | Either ldigits[0] != 0 || rdigits[0] != 0 => result->baseexponent == 0 ! |
static int multsplit_decimalhelper( decimal_t * restrict * result, uint8_t lsize, const uint32_t * ldigits, uint8_t rsize, const uint32_t * rdigits )
Multiplies two decimal numbers and returns the positive result. The multiplication is done with splitting of numbers to save one multiplication.
1. | result must be allocated with size == (lsize + rsize) |
2. | After skipping of trailing zeros: (lsize > 0 && rsize > 0) |
3. | (ldigits[lsize-1] != 0 && rdigits[rsize-1] != 0) |
static void div3by2digits_decimalhelper( decimal_divstate_t * state )
Computes ((dividend * DIGITSBASE + nextdigit) / divisor). The value returned in nextdigit is always in range [1..DIGITSBASE-1] (in case preconditions are met).
1. nextdigit contains result of (dividend * DIGITSBASE + nextdigit) / dividend 2. dividend contains result of (dividend * DIGITSBASE + nextdigit) % dividend
1. | divisor < DIGITSBASE*DIGITSBASE && dividend < DIGITSBASE*DIGITSBASE && nextdigit < DIGITSBASE |
2. | divisor > dividend |
3. | divisor < (dividend * DIGITSBASE + nextdigit) |
static void submul_decimalhelper( decimal_divstate_t * state )
Computes »ldigits[*]-=nextdigit*rdigits[*]« and corrects nextdigit with -1 if necessary.
No multiplication is done.
No multiplication is done.
1. | nextdigit > 0 && nextdigit < DIGITSBASE |
2. | ldigits[loffset] == 0 && ldigits[loffset+1] == 0 |
3. | dividend contains the result of ldigits[“top digits”]-=nextdigit*rdigits[“top digits”] |
static int div_decimalhelper( decimal_t *restrict result, bool isNegSign, int32_t exponent, const uint8_t lsize, uint32_t * const ldigits, const uint8_t rsize, const uint32_t * const rdigits, const uint8_t result_size )
Divides two decimal numbers and returns the positive quotient. The division is done as you have learned in school. The content of ldigits is destroyed.
1. | result must be allocated with result_size && result_size > 0 |
2. | lsize >= rsize && rsize >= 2 |
3. | lsize[lsize-1] != 0 && rsize[rsize-1] != 0 |
4. | exponent must be in range of int16_t |
static int divi32_decimalhelper( decimal_t *restrict result, bool isNegSign, int32_t exponent, uint8_t lsize, const uint32_t * ldigits, uint32_t divisor, const uint32_t result_size )
Divides decimal number by integer and returns the positive quotient. The division is done as you have learned in school.
1. | result must be allocated with result_size && result_size > 0 |
2. | lsize > 0 && ldigits[lsize-1] != 0 |
3. | divisor < DIGITSBASE |
4. | exponent must be in range of int16_t |
static inline uint32_t nrzerobits2nrdigits_decimalhelper( uint32_t nrleadingzerobits )
Returns the nr of zero decimal digits calculated from the number of zero bits. The binary number “0b0.0000111111” has 4 zero bits after the binamal point and this function returns the number of zero digits “0.0009” which would translate into the binary number. The returned number is valid for a 64(or bigger) bit mantissa. For smaller mantissa the nr of leading zero decimal digits returned could be too small by one.
pow(10,294912) needs 32 * 30615 bits to be stored Tested only up to 1080 bits.
static inline uint32_t nrzerobits2decsize_decimalhelper( uint32_t nrleadingzerobits )
See nrzerobits2nrdigits_decimalhelper. The difference is that nrzerobits2decsize_decimalhelper returns nrzerobits2nrdigits_decimalhelper divided by <digitsperint_decimal>().
static uint32_t nrzerodigits2nrbits_decimalhelper( uint32_t nrleadingzerodigits )
Returns the nr of zero bits calculated from the number of zero decimal digits. The decimal number “0.0000999” has 4 zero digits after the decimal point and this function returns the number of zero bits “0b0.00...001” which would translate into the decimal number. The returned number is valid for a 1 bit mantissa. For bigger mantissa the nr of leading zero bits returned could be too small by one.
pow(10,294912) needs 32 * 30615 bits to be stored Tested only up to 1080 bits.
static uint32_t calcfractionsize_decimalhelper( /*out*/uint32_t * leadingzerosize, uint32_t fractionalbits, uint32_t nrleadingzerobits )
Calculates the number of digits needed to represent a binary fraction. The binary fraction 0.00000...0111...1 has fractionalbits digits after the binamal point. This function assumes that all digits are 1 except for the first nrleadingzerobits. After return the parameter leadingzerosize contains the nr of full integer digits which are zero.
Export decimal_frombigint_t into global namespace.
typedef struct decimal_frombigint_t decimal_frombigint_t
Type holding state for conversion from bigint_t into decimal_t.
struct decimal_frombigint_t
Export decimal_frombigint_state_t into global namespace.
typedef struct decimal_frombigint_state_t decimal_frombigint_state_t
Holds the modulo result of a division of a bigint_t.
struct decimal_frombigint_state_t
Export alignedexpandshift_t into global namespace.
typedef struct alignedexpandshift_t alignedexpandshift_t
Stores an exponent of DIGITSBASE and a reference to a shift-left function.
struct alignedexpandshift_t
Export decimal_divstate_t into global namespace.
typedef struct decimal_divstate_t decimal_divstate_t
Used in div_decimalhelper to store current state of division computation.
struct decimal_divstate_t
A function which computes the decimal left shift of digit.
typedef uint32_t ( * shiftleft10p_f ) (/*inout*/uint32_t * shiftcarry, uint32_t shiftdigit)
Big integer object type.
struct bigint_t
A preallocated bigint_t.
bigint_t * big
References a divisor in s_decimal_powbase.
unsigned tabidx
Tables of powers of pow(10,9) used to convert bigint_t, float, double, into decimal_t.
static const bigint_t * s_decimal_powbase[7]
state[0] holds the result of the first division.
decimal_frombigint_state_t state[7]
Divides two decimal numbers and returns the positive quotient.
static int div_decimalhelper( decimal_t *restrict result, bool isNegSign, int32_t exponent, const uint8_t lsize, uint32_t * const ldigits, const uint8_t rsize, const uint32_t * const rdigits, const uint8_t result_size )
Simulates an error in different functions.
static test_errortimer_t s_decimal_errtimer
Returns index into table s_decimal_powbase.
static inline unsigned tableindex_decimalpowbase( uint32_t bigintsize )
Returns index into table s_decimal_powbase.
static inline unsigned tableindexfromdecsize_decimalpowbase( uint32_t decsize )
Returns size of decimal_t needed to represent <s_decimal_powbase>[tableindex].
static inline unsigned decsize_decimalpowbase( unsigned tableindex )
The base of a digit in array decimal_t.digits.
#define DIGITSBASE ( (uint32_t)1000000000 )
9 decimal digits encoded as integer are stored per digit (uint32_t).
uint32_t digits[/*0..size_allocated-1*/]
The number of digits of bigint_t which may be converted to decimal_t without overflow.
#define BIGINT_MAXSIZE ( (uint32_t)119 )
Calculates pow(10, exponent) for 0 <= exponent <= 9.
static inline uint32_t power10_decimalhelper( unsigned exponent )
Returns shiftleft10p_f for argument decimal_exponent_x.
static shiftleft10p_f determinehshiftleft_decimalhelper( uint32_t shiftcount )
Returns the difference between decimal_exponent and the aligned exponent.
static inline int alignexponent_decimalhelper( /*out*/uint32_t * exponent_correction, int32_t decimal_exponent )
Does the real allocation / reallocation.
static int allocate_decimalhelper( decimal_t *restrict * dec, uint32_t size_allocate )
Implements adding of two decimal numbers.
static int add_decimalhelper( decimal_t *restrict * result, const decimal_t * ldec, const decimal_t * rdec )
Implements subtraction of two decimal numbers.
static int sub_decimalhelper( decimal_t *restrict * result, const decimal_t * ldec, const decimal_t * rdec )
Multiplies two decimal numbers and returns the positive result.
static void mult_decimalhelper( decimal_t * dec, uint8_t lsize, const uint32_t * ldigits, uint8_t rsize, const uint32_t * rdigits, int16_t exponent )
Implements adding of two positive decimal numbers.
static void addsplit_decimalhelper( decimal_t * restrict result, uint8_t digitsoffset, uint8_t lsize, const uint32_t * ldigits, uint8_t rsize, const uint32_t * rdigits )
Multiplies two decimal numbers and returns the positive result.
static int multsplit_decimalhelper( decimal_t * restrict * result, uint8_t lsize, const uint32_t * ldigits, uint8_t rsize, const uint32_t * rdigits )
Computes ((dividend * DIGITSBASE + nextdigit) / divisor).
static void div3by2digits_decimalhelper( decimal_divstate_t * state )
Computes »ldigits[*]-=nextdigit*rdigits[*]« and corrects nextdigit with -1 if necessary.
static void submul_decimalhelper( decimal_divstate_t * state )
Divides decimal number by integer and returns the positive quotient.
static int divi32_decimalhelper( decimal_t *restrict result, bool isNegSign, int32_t exponent, uint8_t lsize, const uint32_t * ldigits, uint32_t divisor, const uint32_t result_size )
Returns the nr of zero decimal digits calculated from the number of zero bits.
static inline uint32_t nrzerobits2nrdigits_decimalhelper( uint32_t nrleadingzerobits )
See nrzerobits2nrdigits_decimalhelper.
static inline uint32_t nrzerobits2decsize_decimalhelper( uint32_t nrleadingzerobits )
Returns the nr of zero bits calculated from the number of zero decimal digits.
static uint32_t nrzerodigits2nrbits_decimalhelper( uint32_t nrleadingzerodigits )
Calculates the number of digits needed to represent a binary fraction.
static uint32_t calcfractionsize_decimalhelper( /*out*/uint32_t * leadingzerosize, uint32_t fractionalbits, uint32_t nrleadingzerobits )
Writes a decimal representation of digit into string str.
static inline void digit2str_decimalhelper( uint8_t * str, uint32_t digit, uint8_t digitsize )
Evaluate f(a = 77617, b = 33096)
static int test_example1( void )
The number of allocated integers in digits.
uint8_t size_allocated