7#include "xfa/fgas/crt/cfgas_decimal.h"
15#include "core/fxcrt/check.h"
16#include "core/fxcrt/compiler_specific.h"
17#include "core/fxcrt/fx_extension.h"
19#define FXMATH_DECIMAL_SCALELIMIT 0x1c
20#define FXMATH_DECIMAL_RSHIFT32BIT(x) ((x) >> 0x10
>> 0x10
)
21#define FXMATH_DECIMAL_LSHIFT32BIT(x) ((x) << 0x10
<< 0x10
)
25inline uint8_t decimal_helper_div10(uint64_t& phi,
38inline uint8_t decimal_helper_div10_any(uint64_t nums[], uint8_t numcount) {
41 for (
int i = numcount - 1; i > 0; i--) {
47 retVal = nums[0] % 0xA;
53inline void decimal_helper_mul10(uint64_t& phi, uint64_t& pmid, uint64_t& plo) {
58 pmid = (uint32_t)pmid;
61inline void decimal_helper_mul10_any(uint64_t nums[], uint8_t numcount) {
64 for (
int i = 1; i < numcount; i++) {
66 nums[i - 1] = (uint32_t)nums[i - 1];
71inline void decimal_helper_normalize(uint64_t& phi,
75 pmid = (uint32_t)pmid;
79 pmid = (uint32_t)pmid;
82inline void decimal_helper_normalize_any(uint64_t nums[], uint8_t len) {
84 for (
int i = len - 2; i > 0; i--) {
86 nums[i] = (uint32_t)nums[i];
88 for (
int i = 0; i < len - 1; i++) {
90 nums[i] = (uint32_t)nums[i];
95inline int8_t decimal_helper_raw_compare_any(uint64_t a[],
101 for (
int i =
std::max(al - 1, bl - 1); i >= 0; i--) {
102 uint64_t l = (i >= al ? 0 : a[i]), r = (i >= bl ? 0 : b[i]);
103 retVal += (l > r ? 1 : (l < r ? -1 : 0));
112inline void decimal_helper_dec_any(uint64_t a[], uint8_t al) {
114 for (
int i = 0; i < al; i++) {
122inline void decimal_helper_inc_any(uint64_t a[], uint8_t al) {
124 for (
int i = 0; i < al; i++) {
126 if ((uint32_t)a[i] == a[i]) {
134inline void decimal_helper_raw_mul(uint64_t a[],
142 for (
int i = 0; i < cl; i++) {
146 for (
int i = 0; i < al; i++) {
147 for (
int j = 0; j < bl; j++) {
148 uint64_t m = (uint64_t)a[i] * b[j];
149 c[i + j] += (uint32_t)m;
153 for (
int i = 0; i < cl - 1; i++) {
155 c[i] = (uint32_t)c[i];
157 for (
int i = 0; i < cl; i++) {
158 c[i] = (uint32_t)c[i];
163inline void decimal_helper_raw_div(uint64_t a[],
170 for (
int i = 0; i < cl; i++) {
174 uint64_t left[16] = {0};
175 uint64_t right[16] = {0};
177 for (
int i = 0; i < al; i++) {
182 while (decimal_helper_raw_compare_any(left, al, right, al) <= 0) {
184 for (
int i = 0; i < al; i++) {
185 cur[i] = left[i] + right[i];
188 for (
int i = al - 1; i >= 0; i--) {
195 decimal_helper_raw_mul(cur, al, b, bl, tmp, 16);
196 switch (decimal_helper_raw_compare_any(tmp, 16, a, al)) {
198 for (
int i = 0; i < 16; i++) {
203 decimal_helper_normalize_any(left, al);
206 for (
int i = 0; i < 16; i++) {
209 decimal_helper_dec_any(right, al);
212 for (
int i = 0; i <
std::min(al, cl); i++) {
218 for (
int i = 0; i <
std::min(al, cl); i++) {
224inline bool decimal_helper_outofrange(uint64_t a[], uint8_t al, uint8_t goal) {
226 for (
int i = goal; i < al; i++) {
235inline void decimal_helper_shrinkintorange(uint64_t a[],
239 bool bRoundUp =
false;
241 decimal_helper_outofrange(a, al, goal))) {
242 bRoundUp = decimal_helper_div10_any(a, al) >= 5;
246 decimal_helper_normalize_any(a, goal);
247 decimal_helper_inc_any(a, goal);
251inline void decimal_helper_truncate(uint64_t& phi,
255 uint8_t minscale = 0) {
256 while (scale > minscale) {
257 uint64_t thi = phi, tmid = pmid, tlo = plo;
258 if (decimal_helper_div10(thi, tmid, tlo) != 0)
274 m_uLo(
static_cast<uint32_t>(val)) {}
277 : m_uLo(
static_cast<uint32_t>(val)) {}
293 }
else if (val ==
std::numeric_limits<int32_t>::min()) {
303 float newval = fabs(val);
304 float divisor = powf(2.0, 64.0f);
305 uint64_t bottom64 =
static_cast<uint64_t>(fmodf(newval, divisor));
306 uint64_t top64 =
static_cast<uint64_t>(newval / divisor);
307 uint64_t plo = bottom64 & 0xFFFFFFFF;
308 uint64_t pmid = bottom64 >> 32;
309 uint64_t phi = top64 & 0xFFFFFFFF;
311 newval = fmodf(newval, 1.0f);
312 for (uint8_t iter = 0; iter < scale; iter++) {
313 decimal_helper_mul10(phi, pmid, plo);
315 plo +=
static_cast<uint64_t>(newval);
316 newval = fmodf(newval, 1.0f);
320 decimal_helper_normalize(phi, pmid, plo);
321 m_uHi =
static_cast<uint32_t>(phi);
322 m_uMid =
static_cast<uint32_t>(pmid);
323 m_uLo =
static_cast<uint32_t>(plo);
329 bool pointmet =
false;
333 while (str.Front() ==
' ') {
336 if (str.Front() ==
'-') {
339 }
else if (str.Front() ==
'+') {
343 if (str.Front() ==
'.') {
353 m_uLo = m_uLo * 0xA + (str.Front() -
'0');
366 uint64_t phi = m_uHi;
367 uint64_t pmid = m_uMid;
368 uint64_t plo = m_uLo;
369 while (phi || pmid || plo)
370 tmpbuf
+= decimal_helper_div10(phi, pmid, plo) +
'0';
372 uint8_t outputlen = (uint8_t)tmpbuf.GetLength();
373 uint8_t scale = m_uScale;
374 while (scale >= outputlen) {
381 for (uint8_t idx = 0; idx < outputlen; idx++) {
382 if (idx == (outputlen - scale) && scale != 0)
384 retString += tmpbuf[outputlen - 1 - idx];
394 double pow = (
double)(1 << 16) * (1 << 16);
395 double base =
static_cast<
double>(m_uHi) * pow * pow +
396 static_cast<
double>(m_uMid) * pow +
static_cast<
double>(m_uLo);
397 return (m_bNeg ? -1 : 1) * base * powf(10.0f, -m_uScale);
401 uint8_t oldscale = m_uScale;
402 if (oldscale == newscale)
405 uint64_t phi = m_uHi;
406 uint64_t pmid = m_uMid;
407 uint64_t plo = m_uLo;
408 if (newscale > oldscale) {
409 for (uint8_t iter = 0; iter < newscale - oldscale; iter++)
410 decimal_helper_mul10(phi, pmid, plo);
412 m_uHi =
static_cast<uint32_t>(phi);
413 m_uMid =
static_cast<uint32_t>(pmid);
414 m_uLo =
static_cast<uint32_t>(plo);
418 uint64_t point5_hi = 0;
419 uint64_t point5_mid = 0;
420 uint64_t point5_lo = 5;
421 for (uint8_t iter = 0; iter < oldscale - newscale - 1; iter++)
422 decimal_helper_mul10(point5_hi, point5_mid, point5_lo);
427 decimal_helper_normalize(phi, pmid, plo);
428 for (uint8_t iter = 0; iter < oldscale - newscale; iter++)
429 decimal_helper_div10(phi, pmid, plo);
431 m_uHi =
static_cast<uint32_t>(phi);
432 m_uMid =
static_cast<uint32_t>(pmid);
433 m_uLo =
static_cast<uint32_t>(plo);
444 uint64_t a[3] = {m_uLo, m_uMid, m_uHi},
445 b[3] = {val.m_uLo, val.m_uMid, val.m_uHi};
447 decimal_helper_raw_mul(a, 3, b, 3, c, 6);
448 bool neg = m_bNeg ^ val.m_bNeg;
449 uint8_t scale = m_uScale + val.m_uScale;
450 decimal_helper_shrinkintorange(c, 6, 3, scale);
451 return CFGAS_Decimal(
static_cast<uint32_t>(c[0]),
static_cast<uint32_t>(c[1]),
452 static_cast<uint32_t>(c[2]), neg, scale);
459 bool neg = m_bNeg ^ val.m_bNeg;
460 uint64_t a[7] = {m_uLo, m_uMid, m_uHi},
461 b[3] = {val.m_uLo, val.m_uMid, val.m_uHi}, c[7] = {0};
463 if (m_uScale < val.m_uScale) {
464 for (
int i = val.m_uScale - m_uScale; i > 0; i--)
465 decimal_helper_mul10_any(a, 7);
467 scale = m_uScale - val.m_uScale;
470 uint8_t minscale = scale;
475 decimal_helper_mul10_any(a, 7);
479 decimal_helper_div10_any(a, 7);
481 decimal_helper_raw_div(a, 6, b, 3, c, 7);
482 decimal_helper_shrinkintorange(c, 6, 3, scale);
483 decimal_helper_truncate(c[2], c[1], c[0], scale, minscale);
484 return CFGAS_Decimal(
static_cast<uint32_t>(c[0]),
static_cast<uint32_t>(c[1]),
485 static_cast<uint32_t>(c[2]), neg, scale);
#define FXMATH_DECIMAL_SCALELIMIT
#define FXMATH_DECIMAL_RSHIFT32BIT(x)
#define FXMATH_DECIMAL_LSHIFT32BIT(x)
void SetScale(uint8_t newScale)
CFGAS_Decimal(uint64_t val)
CFGAS_Decimal(float val, uint8_t scale)
CFGAS_Decimal(WideStringView str)
CFGAS_Decimal operator*(const CFGAS_Decimal &val) const
CFGAS_Decimal(uint32_t val)
WideString ToWideString() const
CFGAS_Decimal operator/(const CFGAS_Decimal &val) const
CFGAS_Decimal(int32_t val)
WideString & operator+=(wchar_t ch)
bool FXSYS_IsDecimalDigit(wchar_t c)
int FXSYS_roundf(float f)
fxcrt::WideStringView WideStringView
fxcrt::WideString WideString