DEC64

dec64.asm

dec64.asm is a software implementation of elementary operators of DEC64 for x64 processors. (obj listing)

dec64.h includes C function prototypes for these functions:

Three types are provided:

These constants are also provided:

The comparison functions will return either DEC64_ONE or DEC64_ZERO.

nan

nan (not-a-number) is a popular but poorly named concept in floating-point systems. It is a number value that represents numbers that are undefined or not representable. DEC64 has 72 057 594 037 927 936 possible nan values. When these functions return a nan value, they will always return DEC64_NAN, the normal nan, regardless of the input.

The remaining nan values may be used to hold object pointers or other useful values.

These operations will produce a result of DEC64_NAN:

dec64_abs(nan)
dec64_ceiling(nan)
dec64_dec(nan)
dec64_floor(nan)
dec64_half(nan)
dec64_inc(nan)
dec64_int(nan)
dec64_neg(nan)
dec64_normal(nan)
dec64_not(nan)
dec64_signum(nan)

These operations will produce a result of DEC64_ZERO for all values of n, even if n is nan:

dec64_divide(0, n)
dec64_integer_divide(0, n)
dec64_modulo(0, n)
dec64_multiply(0, n)
dec64_multiply(n, 0)

These operations will produce a result of DEC64_NAN for all values of n except 0:

dec64_divide(n, 0)
dec64_divide(n, nan)
dec64_integer_divide(n, 0)
dec64_integer_divide(n, nan)
dec64_modulo(n, 0)
dec64_modulo(n, nan)
dec64_multiply(n, nan)
dec64_multiply(nan, n)

These operations will produce a result of DEC64_NAN for all values of n:

dec64_add(n, nan)
dec64_add(nan, n)
dec64_divide(nan, n)
dec64_integer_divide(nan, n)
dec64_less(n, nan)
dec64_less(nan, n)
dec64_modulo(nan, n)
dec64_round(n, nan)
dec64_round(nan, n)
dec64_subtract(n, nan)
dec64_subtract(nan, n)

Zero

DEC64 has 255 zero values. They are all equal to each other. The only zero value returned from these functions is the normal zero, DEC64_ZERO, which is the same as the native int64 zero, 0.

Functions

Rounding is to the nearest value. Ties are rounded away from zero. Integer division is floored. The result of dec64_modulo has the sign of the divisor. There is no negative zero.

dec64_abs(number: dec64) returns absolution: dec64

The absolute value function removes the sign from a number value.

If number is   return
  nan DEC64_NAN
  zero DEC64_ZERO
  positive number
  negative -number

dec64_add(augend: dec64, addend: dec64) returns sum: dec64

The add function adds an augend and an addend and returns the sum. If either is nan, or if the sum is not representable, then the result is DEC64_NAN.

dec64_ceiling(number: dec64) returns integer: dec64

The ceiling function returns the smallest integer that is greater than or equal to the number. If the number is nan, the result is DEC64_NAN. If the number is zero, the result is DEC64_ZERO. If the number is an integer, the result is the number.

dec64_coefficient(number: dec64) returns coefficient: int64

A DEC64 number is made up of two parts: a coefficient and an exponent.

63 87 0
coefficient exponent

This function returns the coefficient part as an int64.

dec64_coefficient(DEC64_NAN)

returns 0.

dec64_dec(augend: dec64) returns difference: dec64

The decrement function subtracts 1 from a number. That can be faster than

dec64_subtract(augend, DEC64_ONE)

dec64_divide(dividend: dec64, divisor: dec64) returns quotient: dec64

This function divides the dividend by the divisor.

dec64_equal(comparahend: dec64, comparator: dec64) returns comparison: dec64

Compare two numbers. If either is nan, return DEC64_NAN. If they are exactly equal, return DEC64_ONE, otherwise return DEC64_ZERO. Denormal zeros are equal but denormal nans are not.

dec64_exponent(number: dec64) returns exponent: int64

A DEC64 number is made up of two parts: a coefficient and an exponent.

63 87 0
coefficient exponent

This function returns the exponent part as an int64.

dec64_exponent(nan)

returns -128.

dec64_floor(number: dec64) returns integer: dec64

Produce the largest integer that is less than or equal to the number. This is sometimes called the entier function. In the result, the exponent will be greater than or equal to zero unless it is DEC64_NAN. Numbers with positive exponents will not be modified, even if the numbers are outside of the safe integer range.

dec64_half(dividend: dec64) returns quotient: dec64

Divide a dec64 number by two. This will always be faster than

dec64_divide(dividend, dec64_new(2, 0))

dec64_inc(augend: dec64) returns sum: dec64

The increment function adds 1 to a number. That can be faster than

dec64_add(augend, DEC64_ONE)

dec64_int(number: dec64) returns integer: dec64

Convert the number such that the exponent will be zero, discarding the fraction part. It will produce nan if the result cannot be represented in 56 signed bits. This is used to extract an int56 from a dec64 for bitwise operations. It accepts a broader range than the safe integer range:

-36028797018963968 thru 72057594037927935

dec64_integer_divide(dividend: dec64, divisor: dec64) returns quotient: dec64

Divide, with a floored integer result. It produces the same result as

 dec64_floor(dec64_divide(dividend, divisor))

but can sometimes produce that result more quickly.

dec64_is_any_nan(number: dec64) returns comparison: dec64

If the number is any nan, return DEC64_ONE, otherwise return DEC64_ZERO. To test if a number is the normal DEC64_NAN, just use ==.

dec64_is_integer(number: dec64) returns comparison: dec64

If the number contains a non-zero fractional part or if it is nan, return DEC64_ZERO. Otherwise, return DEC64_ONE.

dec64_is_zero(number: dec64) returns comparison: dec64

If the number is any zero, return DEC64_ONE, otherwise return DEC64_ZERO. To test if a number is DEC64_ZERO, use ==.

dec64_less(comparahend: dec64, comparator: dec64) returns comparison: dec64

Compare two numbers. If either argument is any nan, then the result is DEC64_NAN. If the comparahend is less than the comparator, return DEC64_ONE, otherwise return DEC64_ZERO.

The other 3 comparison functions are easily implemented with dec64_less:

dec64_greater(a, b)          => dec64_less(b, a)
dec64_greater_or_equal(a, b) => dec64_not(dec64_less(a, b))
dec64_less_or_equal(a, b)    => dec64_not(dec64_less(b, a))

dec64_modulo(dividend: dec64, divisor: dec64) returns modulus: dec64

The modulo function produces the same result as

dec64_subtract(
    dividend,
    dec64_multiply(
        dec64_integer_divide(dividend, divisor),
        divisor
    )
)

dec64_multiply(multiplicand: dec64, multiplier: dec64) returns product: dec64

Multiply two numbers.

dec64_neg(number: dec64) returns negation: dec64

Negate a number.

dec64_new(coefficient: int64, exponent: int64) returns number: dec64

A DEC64 number is made up of two parts: a coefficient and an exponent.

63 87 0
coefficient exponent

Construct a new dec64 number with a coefficient and an exponent.

dec64_normal(number: dec64) returns normalization: dec64

Normalize the number by making the exponent as close to zero as possible without losing any signficance. Usually normalization is not needed since it does not materially change the value of a number.

dec64_not(boolean: dec64) returns notation: dec64

If the boolean is DEC64_ONE, the result is DEC64_ZERO. If the boolean is DEC64_ZERO, the result is DEC64_ONE. Otherwise, the result is DEC64_NAN.

dec64_round(number: dec64, place: dec64) returns quantization: dec64

Round the number. Ties are rounded away from zero.

The place determines which decimal place to round to. The place should be between -16 and 16.

place round to nearest
-2 cent
0 integer
3 thousand
6 million
9 billion

dec64_signum(number: dec64) returns signature: dec64

If the number is nan, the result is DEC64_NAN. If the number is less than zero, the result is DEC64_NEGATIVE_ONE. If the number is zero, the result is DEC64_ZERO. If the number is greater than zero, the result is DEC64_ONE.

dec64_subtract(minuend: dec64, subtrahend: dec64) returns difference: dec64

Subtract a subtrahend from from a minuend.

MASM

This file can be processed with Microsoft's ML64.exe. Visual Studio does not have good defaults for building with MASM, and apparently provides no documentation. These hints may be useful:

Platform > x64
Solution Explorer > dec64 > Build Dependencies > Build Customizations... > masm

There might be other assemblers that can process this file, but that has not been tested yet.