arbitrary precision binary-coded decimal arithmetic More...
#include "cgul_common.h"
#include "cgul_exception.h"
#include "cgul_string.h"
#include "cgul_big_integer.h"
Typedefs | |
typedef typedefCGUL_BEGIN_C struct cgul_bcd * | cgul_bcd_t |
Basic arbitrary precision arithmetic using binary-coded decimal (BCD). This is especially useful when you already have a large string of binary digits (perhaps in a text file) that you want to perform a few basic operations on before you write out the new value. You can do the arithmetic in binary-coded decimal without having the overhead of converting to base-2 in order to do the arithmetic and then back to base-10 in order to write out the result (at least that is the theory).
typedef typedefCGUL_BEGIN_C struct cgul_bcd* cgul_bcd_t |
Opaque pointer to a cgul_bcd
instance.
CGUL_END_C CGUL_BEGIN_C CGUL_EXPORT cgul_bcd_t cgul_bcd__new | ( | cgul_exception_t * | cex | ) |
Create a new cgul_bcd
instance initialized to positive 0. The caller is responsible for calling cgul_bcd__delete()
on the value returned. If memory allocation fails, NULL
is returned, and an exception is thrown.
[in,out] | cex | c-style exception |
cgul_bcd
instance CGUL_EXPORT cgul_bcd_t cgul_bcd__new_from_bcd | ( | cgul_exception_t * | cex, |
cgul_bcd_t | value | ||
) |
Create a new cgul_bcd
instance initialized to value
. The caller is responsible for calling cgul_bcd__delete()
on the value returned. If memory allocation fails, NULL
is returned, and an exception is thrown.
[in,out] | cex | c-style exception |
[in] | value | initial value |
cgul_bcd
instance CGUL_EXPORT cgul_bcd_t cgul_bcd__new_from_long | ( | cgul_exception_t * | cex, |
long | value | ||
) |
Create a new cgul_bcd
instance initialized to value
. The caller is responsible for calling cgul_bcd__delete()
on the value returned. If memory allocation fails, NULL
is returned, and an exception is thrown.
[in,out] | cex | c-style exception |
[in] | value | initial value |
cgul_bcd
instance CGUL_EXPORT cgul_bcd_t cgul_bcd__new_from_unsigned_long | ( | cgul_exception_t * | cex, |
unsigned long | value | ||
) |
Create a new cgul_bcd
instance initialized to value
. The caller is responsible for calling cgul_bcd__delete()
on the value returned. If memory allocation fails, NULL
is returned, and an exception is thrown.
[in,out] | cex | c-style exception |
[in] | value | initial value |
cgul_bcd
instance CGUL_EXPORT cgul_bcd_t cgul_bcd__new_from_size_type | ( | cgul_exception_t * | cex, |
size_t | value | ||
) |
Create a new cgul_bcd
instance initialized to value
. The caller is responsible for calling cgul_bcd__delete()
on the value returned. If memory allocation fails, NULL
is returned, and an exception is thrown.
[in,out] | cex | c-style exception |
[in] | value | initial value |
cgul_bcd
instance CGUL_EXPORT cgul_bcd_t cgul_bcd__new_from_string | ( | cgul_exception_t * | cex, |
const char * | s | ||
) |
Create a new cgul_bcd
instance initialized from the string s
. The caller is responsible for calling cgul_bcd__delete()
on the value returned. If an error occurs, NULL
is returned, and an exception is thrown.
[in,out] | cex | c-style exception |
[in] | s | initial value |
cgul_bcd
instance CGUL_EXPORT void cgul_bcd__delete | ( | cgul_bcd_t | bcd | ) |
Delete the cgul_bcd
object in bcd
. The client must not use bcd
after calling this method.
[in] | bcd | cgul_bcd instance |
CGUL_EXPORT int cgul_bcd__is_positive | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd | ||
) |
Return 1 if bcd
is positive. Return 0 if it is not.
[in] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
bcd
is positive CGUL_EXPORT int cgul_bcd__is_negative | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd | ||
) |
Return 1 if bcd
is negative. Return 0 if it is not.
[in] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
bcd
is negative CGUL_EXPORT int cgul_bcd__is_zero | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd | ||
) |
Return 1 if bcd
is zero. Return 0 if it is not.
[in] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
bcd
is zero CGUL_EXPORT void cgul_bcd__set_to_zero | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd | ||
) |
Set the value of bcd
to zero.
[in] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
CGUL_EXPORT int cgul_bcd__is_one | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd | ||
) |
Return 1 if bcd
is one. Return 0 if it is not.
[in] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
bcd
is one CGUL_EXPORT void cgul_bcd__set_to_one | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd | ||
) |
Set the value of bcd
to one.
[in] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
CGUL_EXPORT int cgul_bcd__is_even | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd | ||
) |
Return whether bcd
is even.
[in] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
bcd
is even CGUL_EXPORT int cgul_bcd__is_odd | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd | ||
) |
Return whether bcd
is odd.
[in] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
bcd
is odd CGUL_EXPORT void cgul_bcd__assign | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
cgul_bcd_t | rhs | ||
) |
Assign rhs
to lhs
. It is safe for rhs
and lhs
to point to the same underlying cgul_bcd
object.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | rhs | right-hand side |
CGUL_EXPORT void cgul_bcd__assign_from_long | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
long | rhs | ||
) |
Assign long in rhs
to lhs
.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | rhs | right-hand side |
CGUL_EXPORT void cgul_bcd__assign_from_unsigned_long | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
unsigned long | rhs | ||
) |
Assign unsigned long in rhs
to lhs
.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | rhs | right-hand side |
CGUL_EXPORT void cgul_bcd__assign_from_size_type | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
size_t | rhs | ||
) |
Assign size type in rhs
to lhs
.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | rhs | right-hand side |
CGUL_EXPORT void cgul_bcd__assign_from_string | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
const char * | rhs | ||
) |
Assign the string of decimal digits in rhs
to lhs
. Only assigning from a string of decimal digits is supported. If you need to support other common bases, you should use the cgul_big_integer
class instead. If an error occurs, an exception is thrown.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | rhs | right-hand side |
rhs
parsed CGUL_EXPORT void cgul_bcd__negate | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
cgul_bcd_t | rhs | ||
) |
Assign the negative of rhs
to lhs
. It is safe and efficient for rhs
and lhs
to point to the same underlying cgul_bcd
object.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | rhs | right-hand side |
CGUL_EXPORT void cgul_bcd__abs | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
cgul_bcd_t | rhs | ||
) |
Assign the absolute value of rhs
to lhs
. It is safe and efficient for rhs
and lhs
to point to the same underlying cgul_bcd
object.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | rhs | right-hand side |
CGUL_EXPORT void cgul_bcd__add | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
cgul_bcd_t | rhs1, | ||
cgul_bcd_t | rhs2 | ||
) |
Add rhs1
to rhs2
and store the result in lhs
. It is safe for rhs1
or rhs2
and lhs
to point to the same underlying cgul_bcd
object.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | rhs1 | first right-hand side value |
[in] | rhs2 | second right-hand side value |
CGUL_EXPORT void cgul_bcd__subtract | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
cgul_bcd_t | rhs1, | ||
cgul_bcd_t | rhs2 | ||
) |
Subtract rhs2
from rhs1
and store the result in lhs
. It is safe for rhs1
or rhs2
and lhs
to point to the same underlying cgul_bcd
object.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | rhs1 | first right-hand side value |
[in] | rhs2 | second right-hand side value |
CGUL_EXPORT void cgul_bcd__multiply | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
cgul_bcd_t | rhs1, | ||
cgul_bcd_t | rhs2 | ||
) |
Multiply rhs1
with rhs2
and store the result in lhs
. It is safe for rhs1
or rhs2
and lhs
to point to the same underlying cgul_bcd
object.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | rhs1 | first right-hand side value |
[in] | rhs2 | second right-hand side value |
CGUL_EXPORT void cgul_bcd__divide | ( | cgul_exception_t * | cex, |
cgul_bcd_t | quotient, | ||
cgul_bcd_t | remainder, | ||
cgul_bcd_t | dividend, | ||
cgul_bcd_t | divisor | ||
) |
Divide dividend
by divisor
and store the result in quotient
and remainder
. It is safe for dividend
or divisor
and quotient
or remainder
to point to the same underlying cgul_bcd
object. This method throws an exception if division by zero is attempted or if memory cannot be allocated.
[in,out] | cex | c-style exception |
[out] | quotient | quotient |
[out] | remainder | remainder |
[in] | dividend | dividend |
[in] | divisor | divisor |
CGUL_EXPORT void cgul_bcd__power | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
cgul_bcd_t | base, | ||
cgul_bcd_t | exponent | ||
) |
This method calculates base
raised to the power of exponent
and saves the result in lhs
. If exponent
is negative, an exception is thrown. If the program runs out of memory, an exception is thrown.
This method is not as effecient as cgul_bcd__power_modulo()
when the client is only interested in the modulo and not the power.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | base | base |
[in] | exponent | exponent |
CGUL_EXPORT void cgul_bcd__power_modulo | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
cgul_bcd_t | base, | ||
cgul_bcd_t | exponent, | ||
cgul_bcd_t | modulus | ||
) |
This method calculates the modulo of base
to the power of exponent
using modulus
as the modulus. If exponent
is negative, an exception is thrown. If the program runs out of memory, an exception is thrown.
This method is much more effecient than cgul_bcd__power()
when the client is only interested in the modulo and not the power because the modulo operation is used at each stage of the calculation to keep the size of the numbers within reason.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | base | base |
[in] | exponent | exponent |
[in] | modulus | modulus |
CGUL_EXPORT int cgul_bcd__is_probably_prime | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd, | ||
unsigned int | count | ||
) |
This method uses the Miller-Rabin Primality Test to determine whether bcd
is probably prime. The error per iteration for Miller-Rabin is bound by 1/4. This method performs count
iterations. The following table shows the theoretical upper bound for the error associated with different values of count
:
count | error ------------------------ 10 | 9.54e-7 25 | 8.88e-16 50 | 7.89e-31 100 | 6.22e-61 500 | 9.33e-302 1000 | 8.71e-603
If an exception is not thrown, this method returns 1
if bcd
is probably prime and 0
if it is definitely composite.
This method throws an exception if bcd
is negative. It also throws an exception if the program runs out of memory. If an exception is thrown, 0
is returned.
[in,out] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
[in] | count | number of times test is independently executed |
bcd
is probably prime CGUL_EXPORT void cgul_bcd__shift_left | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
cgul_bcd_t | rhs, | ||
size_t | digit_count | ||
) |
Shift rhs
left by digit_count
and put the result in lhs
. It is safe for rhs
and lhs
to point to the same underlying cgul_bcd
object.
Note that this method is a base-10 shift that shifts individual decimal digits. Contrast this method with cgul_big_integer__shift_left()
which shifts individual base-2 bits instead.
This method can be used as a fast way to multiply by a power of 10.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | rhs | right-hand side |
[in] | digit_count | how far to shift rhs |
CGUL_EXPORT void cgul_bcd__shift_right | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
cgul_bcd_t | rhs, | ||
size_t | digit_count | ||
) |
Shift rhs
right by digit_count
and put the result in lhs
. It is safe for rhs
and lhs
to point to the same underlying cgul_bcd
object.
Note that this method is a base-10 shift that shifts individual decimal digits. Contrast this method with cgul_big_integer__shift_right()
which shifts individual base-2 bits instead.
This method can be used as a fast way to divide by a power of 10.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | rhs | right-hand side |
[in] | digit_count | how far to shift rhs |
CGUL_EXPORT int cgul_bcd__compare | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
cgul_bcd_t | rhs | ||
) |
Return less than zero if lhs
is less than rhs
, return zero if lhs
equals rhs
, and return greater than zero if lhs
is greater than rhs
.
[in] | cex | c-style exception |
[in] | lhs | left-hand side |
[in] | rhs | right-hand side |
lhs
and rhs
CGUL_EXPORT void cgul_bcd__gcd | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
cgul_bcd_t | rhs1, | ||
cgul_bcd_t | rhs2 | ||
) |
This method finds the greatest common divisor (GCD) of rhs1
and rhs2
and saves the result in lhs
. If an error occurs, an exception is thrown.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | rhs1 | first right-hand side value |
[in] | rhs2 | second right-hand side value |
CGUL_EXPORT void cgul_bcd__lcm | ( | cgul_exception_t * | cex, |
cgul_bcd_t | lhs, | ||
cgul_bcd_t | rhs1, | ||
cgul_bcd_t | rhs2 | ||
) |
This method finds the least common multiple (LCM) of rhs1
and rhs2
and saves the result in lhs
. The value returned is often used as the lowest common denominator (LCD). If an error occurs, an exception is thrown.
[in,out] | cex | c-style exception |
[out] | lhs | left-hand side |
[in] | rhs1 | first right-hand side value |
[in] | rhs2 | second right-hand side value |
CGUL_EXPORT void cgul_bcd__swap | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd_1, | ||
cgul_bcd_t | bcd_2 | ||
) |
Swap the internal data quickly without copying.
[in] | cex | c-style exception |
[in] | bcd_1 | first cgul_bcd instance |
[in] | bcd_2 | second cgul_bcd instance |
CGUL_EXPORT int cgul_bcd__as_long | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd, | ||
long int * | value | ||
) |
Convert the value of bcd
to a long. This function returns 1 if the conversion can be accomplished without losing any significant bits; otherwise, it returns 0.
[in] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
[out] | value | converted value |
CGUL_EXPORT int cgul_bcd__as_unsigned_long | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd, | ||
unsigned long int * | value | ||
) |
Convert the value of bcd
to an unsigned long. This function returns 1 if the conversion can be accomplished without losing any significant bits; otherwise, it returns 0.
[in] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
[out] | value | converted value |
CGUL_EXPORT void cgul_bcd__as_big_integer | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd, | ||
cgul_big_integer_t | big_integer | ||
) |
This method converts bcd
to a cgul_big_integer
object and saves the conversion to big_integer
which the caller has already instantiated. If an error occurs, an exception is thrown, and big_integer
is not altered.
[in,out] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
[out] | big_integer | cgul_big_integer instance |
CGUL_EXPORT char* cgul_bcd__as_binary | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd | ||
) |
Return a char*
object that holds the string representation of bcd
as a radix-2 number. The caller is responsible for calling free()
on the pointer returned.
[in,out] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
bcd
as binary CGUL_EXPORT void cgul_bcd__append_as_binary | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd, | ||
cgul_string_t | s | ||
) |
Append the binary representation of bcd
to s
.
[in,out] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
[in] | s | where to append the string representation |
CGUL_EXPORT char* cgul_bcd__as_octal | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd | ||
) |
Return a char*
that holds the string representation of bcd
as a radix-8 number. The caller is responsible for calling free()
on the pointer returned.
[in,out] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
bcd
as octal CGUL_EXPORT void cgul_bcd__append_as_octal | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd, | ||
cgul_string_t | s | ||
) |
Append the octal representation of bcd
to s
.
[in,out] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
[in] | s | where to append the string representation |
CGUL_EXPORT char* cgul_bcd__as_decimal | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd | ||
) |
Return a char*
object that holds the string representation of the decimal digits in bcd
. The caller is responsible for calling free()
on the pointer returned.
Producing a string in base-10 is extremely efficient because the internal format of this class is binary-coded decimal.
[in,out] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
bcd
as decimal CGUL_EXPORT void cgul_bcd__append_as_decimal | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd, | ||
cgul_string_t | s | ||
) |
Append the decimal digits in bcd
to s
.
Producing a string in base-10 is extremely efficient because the internal format of this class is binary-coded decimal.
[in,out] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
[in] | s | where to append the string representation |
CGUL_EXPORT char* cgul_bcd__as_hexadecimal | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd | ||
) |
Return a char*
object that holds the string representation of bcd
as a radix-16 number. The caller is responsible for calling free()
on the pointer returned.
[in,out] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
bcd
as hexadecimal CGUL_EXPORT void cgul_bcd__append_as_hexadecimal | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd, | ||
cgul_string_t | s | ||
) |
Append the hexadecimal representation of bcd
to s
.
[in,out] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
[in] | s | where to append the string representation |
CGUL_EXPORT void cgul_bcd__print_as_binary | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd, | ||
FILE * | f | ||
) |
Print the string representation of bcd
as a radix-2 number on f
.
[in,out] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
[in] | f | output file |
CGUL_EXPORT void cgul_bcd__print_as_octal | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd, | ||
FILE * | f | ||
) |
Print the string representation of bcd
as a radix-8 number on f
.
[in,out] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
[in] | f | output file |
CGUL_EXPORT void cgul_bcd__print_as_decimal | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd, | ||
FILE * | f | ||
) |
Print the string representation of bcd
as a radix-10 number on f
.
Producing a string in base-10 is extremely efficient because the internal format of this class is binary-coded decimal.
[in,out] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
[in] | f | output file |
CGUL_EXPORT void cgul_bcd__print_as_hexadecimal | ( | cgul_exception_t * | cex, |
cgul_bcd_t | bcd, | ||
FILE * | f | ||
) |
Print the string representation of bcd
as a radix-16 number on f
.
[in,out] | cex | c-style exception |
[in] | bcd | cgul_bcd instance |
[in] | f | output file |