108
108
#include "drizzled/definitions.h"
109
109
#include "drizzled/internal/m_string.h"
110
110
#include "drizzled/charset_info.h"
111
#include "drizzled/type/decimal.h"
111
#include "drizzled/decimal.h"
113
113
#include <plugin/myisam/myisampack.h>
114
114
#include <drizzled/util/test.h>
194
194
@retval E_DEC_OOM
197
int class_decimal2string(const type::Decimal *d,
198
uint32_t fixed_dec, String *str)
197
int my_decimal2string(uint32_t mask, const my_decimal *d,
198
uint32_t fixed_prec, uint32_t fixed_dec,
199
char filler, String *str)
200
uint32_t mask= E_DEC_FATAL_ERROR;
203
202
Calculate the size of the string: For DECIMAL(a,b), fixed_prec==a
204
203
holds true iff the type is also ZEROFILL, which in turn implies
207
206
one if the user only wanted decimal places, but we force a leading
208
207
zero on them. Because the type is implicitly UNSIGNED, we do not
209
208
need to reserve a character for the sign. For all other cases,
210
fixed_prec will be 0, and class_decimal_string_length() will be called
209
fixed_prec will be 0, and my_decimal_string_length() will be called
211
210
instead to calculate the required size of the buffer.
214
? (uint32_t)(((0 == fixed_dec) ? 1 : 0) + 1)
215
: (uint32_t)d->string_length());
212
int length= (fixed_prec
213
? (fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1)
214
: my_decimal_string_length(d));
217
216
if (str->alloc(length))
218
217
return check_result(mask, E_DEC_OOM);
220
218
result= decimal2string((decimal_t*) d, (char*) str->ptr(),
221
&length, (int)0, fixed_dec,
219
&length, (int)fixed_prec, fixed_dec,
223
221
str->length(length);
224
222
return check_result(mask, result);
244
242
@retval E_DEC_OVERFLOW
249
int Decimal::val_binary(uint32_t mask, unsigned char *bin, int prec, int scale) const
245
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
251
248
int err1= E_DEC_OK, err2;
252
type::Decimal rounded;
253
class_decimal2decimal(this, &rounded);
250
my_decimal2decimal(d, &rounded);
254
251
rounded.frac= decimal_actual_fraction(&rounded);
255
252
if (scale < rounded.frac)
283
279
@retval E_DEC_OOM
286
int type::Decimal::store(uint32_t mask, const char *from, uint32_t length, const CHARSET_INFO * charset)
282
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
283
const CHARSET_INFO * charset, my_decimal *decimal_value)
288
285
char *end, *from_end;
298
295
charset= &my_charset_bin;
300
297
from_end= end= (char*) from+length;
301
err= string2decimal((char *)from, (decimal_t*) this, &end);
298
err= string2decimal((char *)from, (decimal_t*) decimal_value, &end);
302
299
if (end != from_end && !err)
304
301
/* Give warning if there is something other than end space */
314
check_result_and_overflow(mask, err);
311
check_result_and_overflow(mask, err, decimal_value);
318
void type::Decimal::convert(double &result) const
320
decimal2double(static_cast<const decimal_t*>(this), &result);
323
type::Decimal *date2_class_decimal(type::Time *ltime, type::Decimal *dec)
316
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec)
326
319
date = (ltime->year*100L + ltime->month)*100L + ltime->day;
327
if (ltime->time_type > type::DRIZZLE_TIMESTAMP_DATE)
320
if (ltime->time_type > DRIZZLE_TIMESTAMP_DATE)
328
321
date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second;
330
if (int2_class_decimal(E_DEC_FATAL_ERROR, date, false, dec))
322
if (int2my_decimal(E_DEC_FATAL_ERROR, date, false, dec))
333
324
if (ltime->second_part)
335
326
dec->buf[(dec->intg-1) / 9 + 1]= ltime->second_part * 1000;
343
void class_decimal_trim(uint32_t *precision, uint32_t *scale)
333
void my_decimal_trim(uint32_t *precision, uint32_t *scale)
345
335
if (!(*precision) && !(*scale))
373
363
#define DIG_MASK 100000000
374
364
#define DIG_BASE 1000000000
375
365
#define DIG_MAX (DIG_BASE-1)
378
inline static T round_up(const T &x)
380
return (x+DIG_PER_DEC1-1)/DIG_PER_DEC1;
366
#define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
383
367
static const dec1 powers10[DIG_PER_DEC1+1]={
384
368
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
385
369
static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
395
379
(d)->buf[(d)->len-1] | 1))
398
inline static void fix_intg_frac_error(const int len, int &intg1, int &frac1, int &error)
400
if (unlikely(intg1+frac1 > len))
402
if (unlikely(intg1 > len))
406
error=E_DEC_OVERFLOW;
411
error=E_DEC_TRUNCATED;
418
/* assume carry <= 1 */
419
inline static void add(dec1 &to, const dec1 &from1, const dec1& from2, dec1 &carry)
421
dec1 a=from1+from2+carry;
423
if ((carry= (a >= DIG_BASE))) /* no division here! */
428
inline static void add2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
430
dec2 a=dec2(from1)+from2+carry;
431
if ((carry= (a >= DIG_BASE)))
433
if (unlikely(a >= DIG_BASE))
442
inline static void sub(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
444
dec1 a=from1-from2-carry;
445
if ((carry= (a < 0)))
451
inline static void sub2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
453
dec1 a=from1-from2-carry;
454
if ((carry= (a < 0)))
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) \
465
464
@brief Get maximum value for given precision and scale
755
754
static void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last)
757
dec1 *from= dec->buf + round_up(beg + 1) - 1;
758
dec1 *end= dec->buf + round_up(last) - 1;
756
dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
757
dec1 *end= dec->buf + ROUND_UP(last) - 1;
759
758
int c_shift= DIG_PER_DEC1 - shift;
760
759
assert(from >= dec->buf);
761
760
assert(end < dec->buf + dec->len);
783
782
static void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last)
785
dec1 *from= dec->buf + round_up(last) - 1;
786
dec1 *end= dec->buf + round_up(beg + 1) - 1;
784
dec1 *from= dec->buf + ROUND_UP(last) - 1;
785
dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1;
787
786
int c_shift= DIG_PER_DEC1 - shift;
788
787
assert(from < dec->buf + dec->len);
789
788
assert(end >= dec->buf);
819
818
/* index of position after last decimal digit */
821
820
/* index of digit position just after point */
822
int point= round_up(dec->intg) * DIG_PER_DEC1;
821
int point= ROUND_UP(dec->intg) * DIG_PER_DEC1;
823
822
/* new point position */
824
823
int new_point= point + shift;
825
824
/* number of digits in result */
942
940
d_shift= new_front / DIG_PER_DEC1;
943
to= dec->buf + (round_up(beg + 1) - 1 - d_shift);
944
barier= dec->buf + (round_up(end) - 1 - d_shift);
941
to= dec->buf + (ROUND_UP(beg + 1) - 1 - d_shift);
942
barier= dec->buf + (ROUND_UP(end) - 1 - d_shift);
945
943
assert(to >= dec->buf);
946
944
assert(barier + d_shift < dec->buf + dec->len);
947
945
for(; to <= barier; to++)
956
954
d_shift= (1 - new_front) / DIG_PER_DEC1;
957
to= dec->buf + round_up(end) - 1 + d_shift;
958
barier= dec->buf + round_up(beg + 1) - 1 + d_shift;
955
to= dec->buf + ROUND_UP(end) - 1 + d_shift;
956
barier= dec->buf + ROUND_UP(beg + 1) - 1 + d_shift;
959
957
assert(to < dec->buf + dec->len);
960
958
assert(barier - d_shift >= dec->buf);
961
959
for(; to >= barier; to--)
975
973
Only one of following 'for' loops will work becouse beg <= end
977
beg= round_up(beg + 1) - 1;
978
end= round_up(end) - 1;
975
beg= ROUND_UP(beg + 1) - 1;
976
end= ROUND_UP(end) - 1;
979
977
assert(new_point >= 0);
981
979
/* We don't want negative new_point below */
982
980
if (new_point != 0)
983
new_point= round_up(new_point) - 1;
981
new_point= ROUND_UP(new_point) - 1;
985
983
if (new_point > end)
1671
1669
decimal_round(const decimal_t *from, decimal_t *to, int scale,
1672
1670
decimal_round_mode mode)
1674
int frac0=scale>0 ? round_up(scale) : scale/DIG_PER_DEC1,
1675
frac1=round_up(from->frac), round_digit= 0,
1676
intg0=round_up(from->intg), error=E_DEC_OK, len=to->len,
1677
intg1=round_up(from->intg +
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 +
1678
1676
(((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
1679
1677
dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
1810
1808
*buf1-=DIG_BASE;
1811
1809
while (carry && --buf1 >= to->buf)
1812
add(*buf1, *buf1, 0, carry);
1810
ADD(*buf1, *buf1, 0, carry);
1813
1811
if (unlikely(carry))
1815
1813
/* shifting the number to create space for new digit */
1863
1861
static int do_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1865
int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
1866
frac1=round_up(from1->frac), frac2=round_up(from2->frac),
1863
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1864
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1867
1865
frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
1868
1866
dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
1879
1877
to->buf[0]=0; /* safety */
1882
fix_intg_frac_error(to->len, intg0, frac0, error);
1880
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
1883
1881
if (unlikely(error == E_DEC_OVERFLOW))
1885
1883
max_decimal(to->len * DIG_PER_DEC1, 0, to);
1944
1942
if to==0, return -1/0/+1 - the result of the comparison */
1945
1943
static int do_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1947
int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
1948
frac1=round_up(from1->frac), frac2=round_up(from2->frac);
1945
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1946
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
1949
1947
int frac0=max(frac1, frac2), error;
1950
1948
dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
2013
2009
/* ensure that always from1 > from2 (and intg1 >= intg2) */
2017
swap(start1, start2);
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);
2020
2016
to->sign= 1 - to->sign;
2023
fix_intg_frac_error(to->len, intg1, frac0, error);
2019
FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error);
2024
2020
buf0=to->buf+intg1+frac0;
2026
2022
to->frac=max(from1->frac, from2->frac);
2055
2051
while (buf2 > stop2)
2057
sub(*--buf0, 0, *--buf2, carry);
2053
SUB(*--buf0, 0, *--buf2, carry);
2061
2057
/* part 2 - cmin(frac) ... intg2 */
2062
2058
while (buf2 > start2)
2064
sub(*--buf0, *--buf1, *--buf2, carry);
2060
SUB(*--buf0, *--buf1, *--buf2, carry);
2067
2063
/* part 3 - intg2 ... intg1 */
2068
2064
while (carry && buf1 > start1)
2070
sub(*--buf0, *--buf1, 0, carry);
2066
SUB(*--buf0, *--buf1, 0, carry);
2073
2069
while (buf1 > start1)
2147
2137
int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
2149
int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
2150
frac1=round_up(from1->frac), frac2=round_up(from2->frac),
2151
intg0=round_up(from1->intg+from2->intg),
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),
2152
2142
frac0=frac1+frac2, error, i, j, d_to_move;
2153
2143
dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
2154
2144
*start2, *stop2, *stop1, *start0, carry;
2160
fix_intg_frac_error(to->len, intg0, frac0, error);
2150
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2161
2151
to->sign=from1->sign != from2->sign;
2162
2152
to->frac=from1->frac+from2->frac;
2163
2153
to->intg=intg0*DIG_PER_DEC1;
2198
2188
dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
2199
2189
hi=(dec1)(p/DIG_BASE);
2200
2190
lo=(dec1)(p-((dec2)hi)*DIG_BASE);
2201
add2(*buf0, *buf0, lo, carry);
2191
ADD2(*buf0, *buf0, lo, carry);
2206
2196
if (buf0 < to->buf)
2207
2197
return E_DEC_OVERFLOW;
2208
add2(*buf0, *buf0, 0, carry);
2198
ADD2(*buf0, *buf0, 0, carry);
2210
2200
for (buf0--; carry; buf0--)
2212
2202
if (buf0 < to->buf)
2213
2203
return E_DEC_OVERFLOW;
2214
add(*buf0, *buf0, 0, carry);
2204
ADD(*buf0, *buf0, 0, carry);
2264
2254
static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
2265
2255
decimal_t *to, decimal_t *mod, int scale_incr)
2267
int frac1=round_up(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2268
frac2=round_up(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
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,
2269
2259
error= 0, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2270
2260
dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2271
2261
*start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2334
2324
N2 is in the buf2, has prec2 digits. Scales are frac1 and
2335
2325
frac2 accordingly.
2336
2326
Thus, the result will have
2337
frac = round_up(frac1+frac2+scale_incr)
2327
frac = ROUND_UP(frac1+frac2+scale_incr)
2339
2329
intg = (prec1-frac1) - (prec2-frac2) + 1
2340
2330
prec = intg+frac
2342
frac0=round_up(frac1+frac2+scale_incr);
2343
fix_intg_frac_error(to->len, intg0, frac0, error);
2332
frac0=ROUND_UP(frac1+frac2+scale_incr);
2333
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2344
2334
to->sign=from1->sign != from2->sign;
2345
2335
to->intg=intg0*DIG_PER_DEC1;
2346
2336
to->frac=frac0*DIG_PER_DEC1;
2454
2444
*--start1=dcarry;
2456
intg0=(int) (round_up(prec1-frac1)-(start1-tmp1));
2457
frac0=round_up(to->frac);
2446
intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1));
2447
frac0=ROUND_UP(to->frac);
2458
2448
error=E_DEC_OK;
2459
2449
if (unlikely(frac0==0 && intg0==0))
2451
decimal_make_zero(to);
2466
2456
if (unlikely(-intg0 >= to->len))
2458
decimal_make_zero(to);
2469
2459
error=E_DEC_TRUNCATED;
2552
2542
return do_div_mod(from1, from2, 0, to, 0);
2555
std::ostream& operator<<(std::ostream& output, const type::Decimal &dec)
2557
drizzled::String str;
2559
class_decimal2string(&dec, 0, &str);
2561
output << "type::Decimal:(";
2562
output << str.c_ptr();
2565
return output; // for multiple << operators.
2568
2545
} /* namespace drizzled */
2579
2556
printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
2580
for (i=0; i < round_up(d->frac)+round_up(d->intg)-1; i++)
2557
for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
2581
2558
printf("%09d, ", d->buf[i]);
2582
2559
printf("%09d} */ ", d->buf[i]);