363
363
#define DIG_MASK 100000000
364
364
#define DIG_BASE 1000000000
365
365
#define DIG_MAX (DIG_BASE-1)
366
#define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
368
inline static T round_up(const T &x)
370
return (x+DIG_PER_DEC1-1)/DIG_PER_DEC1;
367
373
static const dec1 powers10[DIG_PER_DEC1+1]={
368
374
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
369
375
static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
379
385
(d)->buf[(d)->len-1] | 1))
382
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) \
385
if (unlikely(intg1+frac1 > (len))) \
387
if (unlikely(intg1 > (len))) \
391
error=E_DEC_OVERFLOW; \
396
error=E_DEC_TRUNCATED; \
403
#define ADD(to, from1, from2, carry) /* assume carry <= 1 */ \
406
dec1 a=(from1)+(from2)+(carry); \
407
assert((carry) <= 1); \
408
if (((carry)= a >= DIG_BASE)) /* no division here! */ \
413
#define ADD2(to, from1, from2, carry) \
416
dec2 a=((dec2)(from1))+(from2)+(carry); \
417
if (((carry)= a >= DIG_BASE)) \
419
if (unlikely(a >= DIG_BASE)) \
427
#define SUB(to, from1, from2, carry) /* to=from1-from2 */ \
430
dec1 a=(from1)-(from2)-(carry); \
431
if (((carry)= a < 0)) \
436
#define SUB2(to, from1, from2, carry) /* to=from1-from2 */ \
439
dec1 a=(from1)-(from2)-(carry); \
440
if (((carry)= a < 0)) \
442
if (unlikely(a < 0)) \
451
Swap the contents of two variables.
453
#define swap_variables(TYPE, a, b) \
388
inline static void fix_intg_frac_error(const int len, int &intg1, int &frac1, int &error)
390
if (unlikely(intg1+frac1 > len))
392
if (unlikely(intg1 > len))
396
error=E_DEC_OVERFLOW;
401
error=E_DEC_TRUNCATED;
408
/* assume carry <= 1 */
409
inline static void add(dec1 &to, const dec1 &from1, const dec1& from2, dec1 &carry)
411
dec1 a=from1+from2+carry;
413
if ((carry= (a >= DIG_BASE))) /* no division here! */
418
inline static void add2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
420
dec2 a=dec2(from1)+from2+carry;
421
if ((carry= (a >= DIG_BASE)))
423
if (unlikely(a >= DIG_BASE))
432
inline static void sub(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
434
dec1 a=from1-from2-carry;
435
if ((carry= (a < 0)))
441
inline static void sub2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
443
dec1 a=from1-from2-carry;
444
if ((carry= (a < 0)))
464
455
@brief Get maximum value for given precision and scale
754
745
static void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last)
756
dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
757
dec1 *end= dec->buf + ROUND_UP(last) - 1;
747
dec1 *from= dec->buf + round_up(beg + 1) - 1;
748
dec1 *end= dec->buf + round_up(last) - 1;
758
749
int c_shift= DIG_PER_DEC1 - shift;
759
750
assert(from >= dec->buf);
760
751
assert(end < dec->buf + dec->len);
782
773
static void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last)
784
dec1 *from= dec->buf + ROUND_UP(last) - 1;
785
dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1;
775
dec1 *from= dec->buf + round_up(last) - 1;
776
dec1 *end= dec->buf + round_up(beg + 1) - 1;
786
777
int c_shift= DIG_PER_DEC1 - shift;
787
778
assert(from < dec->buf + dec->len);
788
779
assert(end >= dec->buf);
818
809
/* index of position after last decimal digit */
820
811
/* index of digit position just after point */
821
int point= ROUND_UP(dec->intg) * DIG_PER_DEC1;
812
int point= round_up(dec->intg) * DIG_PER_DEC1;
822
813
/* new point position */
823
814
int new_point= point + shift;
824
815
/* number of digits in result */
940
931
d_shift= new_front / DIG_PER_DEC1;
941
to= dec->buf + (ROUND_UP(beg + 1) - 1 - d_shift);
942
barier= dec->buf + (ROUND_UP(end) - 1 - d_shift);
932
to= dec->buf + (round_up(beg + 1) - 1 - d_shift);
933
barier= dec->buf + (round_up(end) - 1 - d_shift);
943
934
assert(to >= dec->buf);
944
935
assert(barier + d_shift < dec->buf + dec->len);
945
936
for(; to <= barier; to++)
954
945
d_shift= (1 - new_front) / DIG_PER_DEC1;
955
to= dec->buf + ROUND_UP(end) - 1 + d_shift;
956
barier= dec->buf + ROUND_UP(beg + 1) - 1 + d_shift;
946
to= dec->buf + round_up(end) - 1 + d_shift;
947
barier= dec->buf + round_up(beg + 1) - 1 + d_shift;
957
948
assert(to < dec->buf + dec->len);
958
949
assert(barier - d_shift >= dec->buf);
959
950
for(; to >= barier; to--)
973
964
Only one of following 'for' loops will work becouse beg <= end
975
beg= ROUND_UP(beg + 1) - 1;
976
end= ROUND_UP(end) - 1;
966
beg= round_up(beg + 1) - 1;
967
end= round_up(end) - 1;
977
968
assert(new_point >= 0);
979
970
/* We don't want negative new_point below */
980
971
if (new_point != 0)
981
new_point= ROUND_UP(new_point) - 1;
972
new_point= round_up(new_point) - 1;
983
974
if (new_point > end)
1669
1660
decimal_round(const decimal_t *from, decimal_t *to, int scale,
1670
1661
decimal_round_mode mode)
1672
int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
1673
frac1=ROUND_UP(from->frac), round_digit= 0,
1674
intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
1675
intg1=ROUND_UP(from->intg +
1663
int frac0=scale>0 ? round_up(scale) : scale/DIG_PER_DEC1,
1664
frac1=round_up(from->frac), round_digit= 0,
1665
intg0=round_up(from->intg), error=E_DEC_OK, len=to->len,
1666
intg1=round_up(from->intg +
1676
1667
(((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
1677
1668
dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
1808
1799
*buf1-=DIG_BASE;
1809
1800
while (carry && --buf1 >= to->buf)
1810
ADD(*buf1, *buf1, 0, carry);
1801
add(*buf1, *buf1, 0, carry);
1811
1802
if (unlikely(carry))
1813
1804
/* shifting the number to create space for new digit */
1861
1852
static int do_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1863
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1864
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1854
int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
1855
frac1=round_up(from1->frac), frac2=round_up(from2->frac),
1865
1856
frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
1866
1857
dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
1877
1868
to->buf[0]=0; /* safety */
1880
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
1871
fix_intg_frac_error(to->len, intg0, frac0, error);
1881
1872
if (unlikely(error == E_DEC_OVERFLOW))
1883
1874
max_decimal(to->len * DIG_PER_DEC1, 0, to);
1942
1933
if to==0, return -1/0/+1 - the result of the comparison */
1943
1934
static int do_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1945
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1946
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
1936
int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
1937
frac1=round_up(from1->frac), frac2=round_up(from2->frac);
1947
1938
int frac0=max(frac1, frac2), error;
1948
1939
dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
2009
2000
/* ensure that always from1 > from2 (and intg1 >= intg2) */
2012
swap_variables(const decimal_t *,from1, from2);
2013
swap_variables(dec1 *,start1, start2);
2014
swap_variables(int,intg1,intg2);
2015
swap_variables(int,frac1,frac2);
2004
swap(start1, start2);
2016
2007
to->sign= 1 - to->sign;
2019
FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error);
2010
fix_intg_frac_error(to->len, intg1, frac0, error);
2020
2011
buf0=to->buf+intg1+frac0;
2022
2013
to->frac=max(from1->frac, from2->frac);
2051
2042
while (buf2 > stop2)
2053
SUB(*--buf0, 0, *--buf2, carry);
2044
sub(*--buf0, 0, *--buf2, carry);
2057
2048
/* part 2 - cmin(frac) ... intg2 */
2058
2049
while (buf2 > start2)
2060
SUB(*--buf0, *--buf1, *--buf2, carry);
2051
sub(*--buf0, *--buf1, *--buf2, carry);
2063
2054
/* part 3 - intg2 ... intg1 */
2064
2055
while (carry && buf1 > start1)
2066
SUB(*--buf0, *--buf1, 0, carry);
2057
sub(*--buf0, *--buf1, 0, carry);
2069
2060
while (buf1 > start1)
2137
2128
int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
2139
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
2140
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
2141
intg0=ROUND_UP(from1->intg+from2->intg),
2130
int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
2131
frac1=round_up(from1->frac), frac2=round_up(from2->frac),
2132
intg0=round_up(from1->intg+from2->intg),
2142
2133
frac0=frac1+frac2, error, i, j, d_to_move;
2143
2134
dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
2144
2135
*start2, *stop2, *stop1, *start0, carry;
2150
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2141
fix_intg_frac_error(to->len, intg0, frac0, error);
2151
2142
to->sign=from1->sign != from2->sign;
2152
2143
to->frac=from1->frac+from2->frac;
2153
2144
to->intg=intg0*DIG_PER_DEC1;
2188
2179
dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
2189
2180
hi=(dec1)(p/DIG_BASE);
2190
2181
lo=(dec1)(p-((dec2)hi)*DIG_BASE);
2191
ADD2(*buf0, *buf0, lo, carry);
2182
add2(*buf0, *buf0, lo, carry);
2196
2187
if (buf0 < to->buf)
2197
2188
return E_DEC_OVERFLOW;
2198
ADD2(*buf0, *buf0, 0, carry);
2189
add2(*buf0, *buf0, 0, carry);
2200
2191
for (buf0--; carry; buf0--)
2202
2193
if (buf0 < to->buf)
2203
2194
return E_DEC_OVERFLOW;
2204
ADD(*buf0, *buf0, 0, carry);
2195
add(*buf0, *buf0, 0, carry);
2254
2245
static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
2255
2246
decimal_t *to, decimal_t *mod, int scale_incr)
2257
int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2258
frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2248
int frac1=round_up(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2249
frac2=round_up(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2259
2250
error= 0, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2260
2251
dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2261
2252
*start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2324
2315
N2 is in the buf2, has prec2 digits. Scales are frac1 and
2325
2316
frac2 accordingly.
2326
2317
Thus, the result will have
2327
frac = ROUND_UP(frac1+frac2+scale_incr)
2318
frac = round_up(frac1+frac2+scale_incr)
2329
2320
intg = (prec1-frac1) - (prec2-frac2) + 1
2330
2321
prec = intg+frac
2332
frac0=ROUND_UP(frac1+frac2+scale_incr);
2333
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2323
frac0=round_up(frac1+frac2+scale_incr);
2324
fix_intg_frac_error(to->len, intg0, frac0, error);
2334
2325
to->sign=from1->sign != from2->sign;
2335
2326
to->intg=intg0*DIG_PER_DEC1;
2336
2327
to->frac=frac0*DIG_PER_DEC1;
2556
2547
printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
2557
for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
2548
for (i=0; i < round_up(d->frac)+round_up(d->intg)-1; i++)
2558
2549
printf("%09d, ", d->buf[i]);
2559
2550
printf("%09d} */ ", d->buf[i]);