ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
mdl_state_decimal.c File Reference

Exact locale-free conversion for legacy decimal state values. More...

#include <stdint.h>
#include <string.h>
#include "mdl_state_internal.h"
#include "ra8_attributes.h"
Include dependency graph for mdl_state_decimal.c:

Go to the source code of this file.

Data Structures

struct  mdl_state_big_t
 Little-endian base-2^32 unsigned integer. More...

Enumerations

enum  mdl_state_big_limit_t : uint8_t { k_state_big_words = 48 }
 Fixed storage is sufficient for 17 digits multiplied or divided by 10^400. More...
enum  mdl_state_decimal_limit_t : int32_t {
  k_state_decimal_prime = 5 ,
  k_state_decimal_scale_max = 400 ,
  k_state_divide_bits = 64 ,
  k_state_binary64_fraction_bits = 52 ,
  k_state_binary64_precision_bits = 53 ,
  k_state_binary64_sign_shift = 63 ,
  k_state_binary64_exponent_bias = 1023 ,
  k_state_binary64_exponent_max = 1023 ,
  k_state_binary64_exponent_min = -1022 ,
  k_state_binary64_subnormal_scale = 1074
}
 Exact decimal and binary64 representation constants. More...

Functions

static void internal_mdl_state_big_init (mdl_state_big_t *big, uint64_t value)
 Initialize a fixed integer from one uint64 value.
static void internal_mdl_state_big_trim (mdl_state_big_t *big)
 Remove unused high words while retaining one zero word.
static uint16_t internal_mdl_state_big_bits (const mdl_state_big_t *big)
 Return the significant bit count of a fixed integer.
static bool internal_mdl_state_big_mul (mdl_state_big_t *big, uint32_t factor)
 Multiply a fixed integer by one small factor.
static bool internal_mdl_state_big_shift (const mdl_state_big_t *src, uint16_t shift, mdl_state_big_t *dst)
 Copy one fixed integer shifted left by an exact bit count.
static int internal_mdl_state_big_compare (const mdl_state_big_t *lhs, const mdl_state_big_t *rhs)
 Compare two normalized fixed integers.
static void internal_mdl_state_big_subtract (mdl_state_big_t *lhs, const mdl_state_big_t *rhs)
 Subtract a no-larger fixed integer from another.
static int internal_mdl_state_compare_power (const mdl_state_big_t *numerator, const mdl_state_big_t *denominator, int32_t binary_scale, int32_t exponent)
 Compare a scaled rational against one exact power of two.
static bool internal_mdl_state_divide (const mdl_state_big_t *numerator, const mdl_state_big_t *denominator, int32_t binary_shift, uint64_t *out)
 Divide one scaled rational and round to nearest-even.
static bool internal_mdl_state_build_rational (uint64_t mantissa, int32_t decimal_scale, mdl_state_big_t *numerator, mdl_state_big_t *denominator)
 Build the odd rational factors for a decimal value.
static bool internal_mdl_state_encode (uint64_t quotient, int32_t exponent, bool negative, bool normal, double *out)
 Encode one rounded quotient as finite binary64.
bool priv_mdl_state_decimal_to_binary64 (uint64_t mantissa, int32_t decimal_scale, bool negative, double *out)
 Convert one exact bounded decimal rational to binary64.

Detailed Description

Exact locale-free conversion for legacy decimal state values.

Uses fixed-capacity integers to round bounded schema-v2 decimals to binary64.

Definition in file mdl_state_decimal.c.

Enumeration Type Documentation

◆ mdl_state_big_limit_t

enum mdl_state_big_limit_t : uint8_t

Fixed storage is sufficient for 17 digits multiplied or divided by 10^400.

Enumerator
k_state_big_words 

Capacity of one fixed unsigned integer.

Definition at line 15 of file mdl_state_decimal.c.

◆ mdl_state_decimal_limit_t

enum mdl_state_decimal_limit_t : int32_t

Exact decimal and binary64 representation constants.

Enumerator
k_state_decimal_prime 

Odd factor of decimal radix.

k_state_decimal_scale_max 

Accepted absolute decimal scale.

k_state_divide_bits 

Width of the bounded quotient.

k_state_binary64_fraction_bits 

Stored binary64 fraction width.

k_state_binary64_precision_bits 

Binary64 significand precision.

k_state_binary64_sign_shift 

Binary64 sign-bit position.

k_state_binary64_exponent_bias 

Binary64 exponent bias.

k_state_binary64_exponent_max 

Largest finite unbiased exponent.

k_state_binary64_exponent_min 

Smallest normal unbiased exponent.

k_state_binary64_subnormal_scale 

Scale selecting subnormal units.

Definition at line 20 of file mdl_state_decimal.c.

Function Documentation

◆ internal_mdl_state_big_bits()

uint16_t internal_mdl_state_big_bits ( const mdl_state_big_t * big)
static

Return the significant bit count of a fixed integer.

Parameters
[in]bigNormalized integer.
Returns
Magnitude bit length.
Return values
0The integer is zero.
Precondition
big is non-NULL.
Its used count is normalized and in range.
Postcondition
The integer is unchanged.
A nonzero result fits the fixed capacity.
Note
Uses only defined unsigned shifts.
Since
0.1.0

Definition at line 75 of file mdl_state_decimal.c.

References RA8_INTERNAL, mdl_state_big_t::used, and mdl_state_big_t::word.

Referenced by internal_mdl_state_divide(), and priv_mdl_state_decimal_to_binary64().

◆ internal_mdl_state_big_compare()

int internal_mdl_state_big_compare ( const mdl_state_big_t * lhs,
const mdl_state_big_t * rhs )
static

Compare two normalized fixed integers.

Parameters
[in]lhsLeft operand.
[in]rhsRight operand.
Returns
Three-way ordering.
Return values
0Magnitudes are equal.
Precondition
Both pointers are non-NULL.
Both used counts are normalized.
Postcondition
Both operands are unchanged.
The sign of the result matches unsigned ordering.
Note
Comparison starts at the highest word.
Since
0.1.0

Definition at line 152 of file mdl_state_decimal.c.

References RA8_INTERNAL, mdl_state_big_t::used, and mdl_state_big_t::word.

Referenced by internal_mdl_state_compare_power(), and internal_mdl_state_divide().

◆ internal_mdl_state_big_init()

void internal_mdl_state_big_init ( mdl_state_big_t * big,
uint64_t value )
static

Initialize a fixed integer from one uint64 value.

Parameters
[out]bigDestination integer.
[in]valueInitial magnitude.
Precondition
big is non-NULL.
Its storage has the declared word capacity.
Postcondition
Every unused word is zero.
The used count is one or two.
Note
Initialization is constant-time with respect to capacity.
Since
0.1.0

Definition at line 46 of file mdl_state_decimal.c.

References memset(), RA8_INTERNAL, mdl_state_big_t::used, and mdl_state_big_t::word.

Referenced by internal_mdl_state_build_rational().

◆ internal_mdl_state_big_mul()

bool internal_mdl_state_big_mul ( mdl_state_big_t * big,
uint32_t factor )
static

Multiply a fixed integer by one small factor.

Parameters
[in,out]bigInteger operand.
[in]factorSmall multiplier.
Returns
Capacity result.
Return values
falseThe product exceeds fixed storage.
Precondition
big is non-NULL.
Its used count is normalized and in range.
Postcondition
Success stores the exact product.
Failure never writes outside the array.
Note
Carry arithmetic uses uint64.
Since
0.1.0

Definition at line 96 of file mdl_state_decimal.c.

References k_state_big_words, RA8_INTERNAL, mdl_state_big_t::used, and mdl_state_big_t::word.

Referenced by internal_mdl_state_build_rational().

◆ internal_mdl_state_big_shift()

bool internal_mdl_state_big_shift ( const mdl_state_big_t * src,
uint16_t shift,
mdl_state_big_t * dst )
static

Copy one fixed integer shifted left by an exact bit count.

Parameters
[in]srcSource integer.
[in]shiftBit count.
[out]dstDestination.
Returns
Capacity result.
Return values
falseThe shifted value does not fit.
Precondition
Source and destination are non-NULL and distinct.
Source used count is valid.
Postcondition
Success stores the exact normalized shift.
Failure writes no out-of-bounds word.
Note
Zero remains normalized.
Since
0.1.0

Definition at line 122 of file mdl_state_decimal.c.

References internal_mdl_state_big_trim(), k_state_big_words, memset(), mdl_state_big_t::used, and mdl_state_big_t::word.

Referenced by internal_mdl_state_compare_power(), and internal_mdl_state_divide().

◆ internal_mdl_state_big_subtract()

void internal_mdl_state_big_subtract ( mdl_state_big_t * lhs,
const mdl_state_big_t * rhs )
static

Subtract a no-larger fixed integer from another.

Parameters
[in,out]lhsMinuend and result.
[in]rhsSubtrahend.
Precondition
Both pointers are non-NULL.
lhs is at least rhs.
Postcondition
lhs stores the exact normalized difference.
rhs is unchanged.
Note
Borrow arithmetic remains unsigned.
Since
0.1.0

Definition at line 173 of file mdl_state_decimal.c.

References internal_mdl_state_big_trim(), RA8_INTERNAL, mdl_state_big_t::used, and mdl_state_big_t::word.

Referenced by internal_mdl_state_divide().

◆ internal_mdl_state_big_trim()

void internal_mdl_state_big_trim ( mdl_state_big_t * big)
static

Remove unused high words while retaining one zero word.

Parameters
[in,out]bigInteger to normalize.
Precondition
big is non-NULL.
Its used count is within capacity.
Postcondition
The high used word is nonzero unless the value is zero.
Zero retains one word.
Note
Magnitude words are otherwise unchanged.
Since
0.1.0

Definition at line 61 of file mdl_state_decimal.c.

References RA8_INTERNAL, mdl_state_big_t::used, and mdl_state_big_t::word.

Referenced by internal_mdl_state_big_shift(), and internal_mdl_state_big_subtract().

◆ internal_mdl_state_build_rational()

bool internal_mdl_state_build_rational ( uint64_t mantissa,
int32_t decimal_scale,
mdl_state_big_t * numerator,
mdl_state_big_t * denominator )
static

Build the odd rational factors for a decimal value.

Parameters
[in]mantissaDecimal significand.
[in]decimal_scaleSigned power of ten.
[out]numeratorNumerator factor.
[out]denominatorDenominator factor.
Returns
Capacity result.
Return values
falseA factor exceeds fixed storage.
Precondition
Output pointers are non-NULL and distinct.
Decimal scale is within the public bound.
Postcondition
Success represents mantissa * 5^scale.
The remaining 2^scale stays explicit.
Note
Exactly one side is multiplied by five.
Since
0.1.0

Definition at line 272 of file mdl_state_decimal.c.

References internal_mdl_state_big_init(), internal_mdl_state_big_mul(), k_state_decimal_prime, and RA8_INTERNAL.

Referenced by priv_mdl_state_decimal_to_binary64().

◆ internal_mdl_state_compare_power()

int internal_mdl_state_compare_power ( const mdl_state_big_t * numerator,
const mdl_state_big_t * denominator,
int32_t binary_scale,
int32_t exponent )
static

Compare a scaled rational against one exact power of two.

Parameters
[in]numeratorRational numerator.
[in]denominatorRational denominator.
[in]binary_scaleNumerator power-of-two scale.
[in]exponentCompared exponent.
Returns
Three-way ordering.
Return values
0Values are equal.
Precondition
Integer pointers are non-NULL.
Denominator is positive and normalized.
Postcondition
Inputs remain unchanged.
Capacity overflow returns the mathematically forced ordering.
Note
At most one temporary fixed integer is used.
Since
0.1.0

Definition at line 193 of file mdl_state_decimal.c.

References internal_mdl_state_big_compare(), internal_mdl_state_big_shift(), and RA8_INTERNAL.

Referenced by priv_mdl_state_decimal_to_binary64().

◆ internal_mdl_state_divide()

bool internal_mdl_state_divide ( const mdl_state_big_t * numerator,
const mdl_state_big_t * denominator,
int32_t binary_shift,
uint64_t * out )
static

Divide one scaled rational and round to nearest-even.

Parameters
[in]numeratorNumerator.
[in]denominatorDenominator.
[in]binary_shiftNumerator binary scale.
[out]outRounded quotient.
Returns
Capacity result.
Return values
falseIntermediate or quotient width exceeds bounds.
Precondition
All pointers are non-NULL.
Denominator is positive and normalized.
Postcondition
Success initializes out exactly.
Inputs remain unchanged.
Note
Long division emits at most 64 quotient bits.
Since
0.1.0

Definition at line 219 of file mdl_state_decimal.c.

References internal_mdl_state_big_bits(), internal_mdl_state_big_compare(), internal_mdl_state_big_shift(), internal_mdl_state_big_subtract(), k_state_divide_bits, and RA8_INTERNAL.

Referenced by priv_mdl_state_decimal_to_binary64().

◆ internal_mdl_state_encode()

bool internal_mdl_state_encode ( uint64_t quotient,
int32_t exponent,
bool negative,
bool normal,
double * out )
static

Encode one rounded quotient as finite binary64.

Parameters
[in]quotientRounded significand.
[in]exponentUnbiased exponent.
[in]negativeSign.
[in]normalNormal/subnormal selector.
[out]outEncoded value.
Returns
Encoding result.
Return values
falseOverflow, underflow, or invalid quotient.
Precondition
out is non-NULL.
Quotient and exponent came from exact division.
Postcondition
Success initializes finite binary64 bits.
Rounding carry is normalized once.
Note
Bit transfer uses memcpy.
Since
0.1.0

Definition at line 296 of file mdl_state_decimal.c.

References k_state_binary64_exponent_bias, k_state_binary64_exponent_max, k_state_binary64_fraction_bits, k_state_binary64_precision_bits, k_state_binary64_sign_shift, memcpy(), and RA8_INTERNAL.

Referenced by priv_mdl_state_decimal_to_binary64().

◆ priv_mdl_state_decimal_to_binary64()

bool priv_mdl_state_decimal_to_binary64 ( uint64_t mantissa,
int32_t decimal_scale,
bool negative,
double * out )

Convert one exact bounded decimal rational to binary64.

Uses fixed-capacity integer division and nearest-even rounding without libc conversion.

Parameters
[in]mantissaUnsigned decimal significand (at most 17 digits).
[in]decimal_scaleSigned power of ten applied to mantissa.
[in]negativeWhether to set the binary64 sign bit.
[out]outConverted finite binary64 value.
Returns
Whether the exact value rounds to a non-underflowing finite binary64.
Return values
falseScale, capacity, overflow, or nonzero underflow is invalid.
Precondition
out is non-NULL and decimal_scale is in [-400, 400].
mantissa carries at most 17 decimal digits.
Postcondition
Success is correctly rounded to nearest, ties to even without locale or libc conversion.
Failure publishes no numeric result contract.
Note
Signed zero is preserved.
Since
0.1.0

Definition at line 330 of file mdl_state_decimal.c.

References internal_mdl_state_big_bits(), internal_mdl_state_build_rational(), internal_mdl_state_compare_power(), internal_mdl_state_divide(), internal_mdl_state_encode(), k_state_binary64_exponent_max, k_state_binary64_exponent_min, k_state_binary64_fraction_bits, k_state_binary64_sign_shift, k_state_binary64_subnormal_scale, k_state_decimal_scale_max, memcpy(), and RA8_PRIV.

Referenced by internal_mdl_state_parse_double_field().