NAME
Locale::Unicode::RBNF::Util - Numeric helpers for Locale::Unicode::RBNF
SYNOPSIS
use Locale::Unicode::RBNF::Util qw( :all );
my $n = to_i64( pow_u64( 10, 19 ) );
my $q = idiv( -7, 2 );
# -3
VERSION
v0.1.0
DESCRIPTION
Internal module. It reproduces the int64_t, uint64_t and double behaviour that ICU4C's rule-based number format relies upon, so that results are identical to ICU, including its overflow behaviour.
EXPORTS
Nothing is exported by default. All the functions below can be imported individually, or all at once with the tag :all.
VARIABLES
$MAX_MANTISSA2^54 - 1, the value of ICU
uprv_maxMantissa().$INT64_MAXand$INT64_MINThe limits of an
int64_t.$UINT64_MOD2^64, as a Math::BigInt object.
FUNCTIONS
dbl_to_i32
my $i = dbl_to_i32( $double );
This is static_cast<int32_t> of a double. Out of range, this is undefined behaviour in C++: x86 yields INT32_MIN, while aarch64 saturates, as does the (int) cast of Java in ICU4J. The defined Java semantics are used: the value is truncated towards zero, saturated to the int32_t range, and NaN yields 0.
dec_from_number
my $dec = dec_from_number( $number, $is_int );
Returns the decimal representation of a number as an hash reference with the keys neg, digits and scale, where the value is digits times 10 to the power of scale, and digits neither starts nor ends with a zero. Zero has empty digits.
If $is_int is true, the number is taken digit for digit, so that integers beyond 2^53 keep their precision. Otherwise, the shortest representation of the double that round-trips is used, which is what ICU DecimalQuantity::setToDouble() produces.
dec_get_digit
my $digit = dec_get_digit( $dec, $magnitude );
This is ICU DecimalQuantity::getDigit(): it returns the digit at the given power of ten, or 0 outside the digits stored.
dec_is_zero
my $bool = dec_is_zero( $dec );
Returns true if the decimal representation is zero.
dec_lower_display_magnitude
my $magnitude = dec_lower_display_magnitude( $dec );
This is ICU DecimalQuantity::getLowerDisplayMagnitude() for a quantity with no minimum fraction digits: the power of ten of the last fraction digit, or 0 if there is none.
dec_round
my $ok = dec_round( $dec, $magnitude, $mode );
This is ICU DecimalQuantity::roundToMagnitude(): it rounds the decimal representation, in place, to the given power of ten, with one of the rounding modes ceiling, floor, down, up, half_even (the default), half_down, half_up, half_odd, half_ceiling, half_floor and unnecessary.
It returns false when the mode is unnecessary and rounding would have changed the value, in which case the value is left unchanged, and ICU sets U_FORMAT_INEXACT_ERROR. It returns true otherwise.
dec_to_number
my $number = dec_to_number( $dec );
Returns the decimal representation as a Perl number.
from_double
my $int = from_double( $double );
This is ICU util64_fromDouble(): the double is clamped to plus or minus uprv_maxMantissa(), 2^54 - 1, then truncated towards zero. NaN yields 0.
idiv
my $q = idiv( $x, $y );
Returns the integer division of $x by $y with C semantics, that is truncated towards zero.
imod
my $r = imod( $x, $y );
Returns the remainder of the integer division of $x by $y with C semantics, that is with the sign of $x.
is_infinite
my $bool = is_infinite( $number );
Returns true if the number is defined and is a positive or negative infinity.
is_nan
my $bool = is_nan( $number );
Returns true if the number is defined and is NaN.
is_pattern_ws
my $bool = is_pattern_ws( $char );
This is ICU PatternProps::isWhiteSpace(): it returns true if the character belongs to the Pattern_White_Space set. That set is immutable by Unicode policy, so it is spelled out in the code.
lcm
my $lcm = lcm( $x, $y );
This is util_lcm() of ICU nfrs.cpp: the least common multiple, computed with the binary gcd of Knuth, then x / gcd * y, all in int64_t arithmetic. It returns 0 if the gcd is 0.
pow_u64
my $n = pow_u64( $base, $exponent );
This is ICU util64_pow(): it raises the base to the power of the exponent in uint64_t arithmetic, so that the result wraps modulo 2^64 as the C++ code does. Beyond 2^53, the exact wrapped value is computed with Math::BigInt. The result is unsigned; use "to_i64" where ICU stores it in an int64_t.
str_insert
str_insert( \$string, $pos, $text );
This is ICU UnicodeString::insert(): it inserts the text into the string referenced, at the position given, pinned within the string.
to_i32
my $i = to_i32( $integer );
This is static_cast<int32_t> of an integral value: two's complement truncation.
to_i64
my $i = to_i64( $unsigned );
Converts a uint64_t value to an int64_t (two's complement), as happens implicitly in ICU.
SEE ALSO
AUTHOR
Jacques Deguest <jack@deguest.jp>
COPYRIGHT & LICENSE
Copyright(c) 2026 DEGUEST Pte. Ltd.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.