103
99
implementation-defined.
108
#include <drizzled/definitions.h>
109
#include <drizzled/internal/m_string.h>
110
#include <drizzled/charset_info.h>
111
#include <drizzled/type/decimal.h>
113
#include <plugin/myisam/myisampack.h>
114
#include <drizzled/util/test.h>
122
#include <drizzled/current_session.h>
123
#include <drizzled/error.h>
124
#include <drizzled/field.h>
125
#include <drizzled/internal/my_sys.h>
132
report result of decimal operation.
134
@param result decimal library return code (E_DEC_* see include/decimal.h)
143
int decimal_operation_results(int result)
148
case E_DEC_TRUNCATED:
149
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
150
ER_WARN_DATA_TRUNCATED, ER(ER_WARN_DATA_TRUNCATED),
154
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
155
ER_TRUNCATED_WRONG_VALUE,
156
ER(ER_TRUNCATED_WRONG_VALUE),
160
my_error(ER_DIVISION_BY_ZERO, MYF(0));
163
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
164
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
165
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
166
"decimal", "", "", (long)-1);
169
my_error(ER_OUT_OF_RESOURCES, MYF(0));
179
@brief Converting decimal to string
181
@details Convert given type::Decimal to String; allocate buffer as needed.
183
@param[in] mask what problems to warn on (mask of E_DEC_* values)
184
@param[in] d the decimal to print
185
@param[in] fixed_prec overall number of digits if ZEROFILL, 0 otherwise
186
@param[in] fixed_dec number of decimal places (if fixed_prec != 0)
187
@param[in] filler what char to pad with (ZEROFILL et al.)
188
@param[out] *str where to store the resulting string
192
@retval E_DEC_TRUNCATED
193
@retval E_DEC_OVERFLOW
197
int class_decimal2string(const type::Decimal *d,
198
uint32_t fixed_dec, String *str)
200
uint32_t mask= E_DEC_FATAL_ERROR;
203
Calculate the size of the string: For DECIMAL(a,b), fixed_prec==a
204
holds true iff the type is also ZEROFILL, which in turn implies
205
UNSIGNED. Hence the buffer for a ZEROFILLed value is the length
206
the user requested, plus one for a possible decimal point, plus
207
one if the user only wanted decimal places, but we force a leading
208
zero on them. Because the type is implicitly UNSIGNED, we do not
209
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
211
instead to calculate the required size of the buffer.
214
? (uint32_t)(((0 == fixed_dec) ? 1 : 0) + 1)
215
: (uint32_t)d->string_length());
217
if (str->alloc(length))
218
return check_result(mask, E_DEC_OOM);
220
result= decimal2string((decimal_t*) d, (char*) str->ptr(),
221
&length, (int)0, fixed_dec,
224
return check_result(mask, result);
229
@brief Convert from decimal to binary representation
231
@param[in] mask error processing mask
232
@param[in] d number for conversion
233
@param[out] bin pointer to buffer where to write result
234
@param[in] prec overall number of decimal digits
235
@param[in] scale number of decimal digits after decimal point
238
Before conversion we round number if it need but produce truncation
243
@retval E_DEC_TRUNCATED
244
@retval E_DEC_OVERFLOW
249
int Decimal::val_binary(uint32_t mask, unsigned char *bin, int prec, int scale) const
251
int err1= E_DEC_OK, err2;
252
type::Decimal rounded;
253
class_decimal2decimal(this, &rounded);
254
rounded.frac= decimal_actual_fraction(&rounded);
255
if (scale < rounded.frac)
257
err1= E_DEC_TRUNCATED;
258
/* decimal_round can return only E_DEC_TRUNCATED */
259
decimal_round(&rounded, &rounded, scale, HALF_UP);
261
err2= decimal2bin(&rounded, bin, prec, scale);
264
return check_result(mask, err2);
271
@brief Convert string for decimal when string can be in some multibyte charset
273
@param mask error processing mask
274
@param from string to process
275
@param length length of given string
276
@param charset charset of given string
280
@retval E_DEC_TRUNCATED
281
@retval E_DEC_OVERFLOW
282
@retval E_DEC_BAD_NUM
286
int type::Decimal::store(uint32_t mask, const char *from, uint32_t length, const CHARSET_INFO * charset)
288
char *end, *from_end;
290
char buff[STRING_BUFFER_USUAL_SIZE];
291
String tmp(buff, sizeof(buff), &my_charset_bin);
292
if (charset->mbminlen > 1)
295
tmp.copy(from, length, charset, &my_charset_utf8_general_ci, &dummy_errors);
297
length= tmp.length();
298
charset= &my_charset_bin;
300
from_end= end= (char*) from+length;
301
err= string2decimal((char *)from, (decimal_t*) this, &end);
302
if (end != from_end && !err)
304
/* Give warning if there is something other than end space */
305
for ( ; end < from_end; end++)
307
if (!my_isspace(&my_charset_utf8_general_ci, *end))
309
err= E_DEC_TRUNCATED;
314
check_result_and_overflow(mask, err);
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)
326
date = (ltime->year*100L + ltime->month)*100L + ltime->day;
327
if (ltime->time_type > type::DRIZZLE_TIMESTAMP_DATE)
328
date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second;
330
if (int2_class_decimal(E_DEC_FATAL_ERROR, date, false, dec))
333
if (ltime->second_part)
335
dec->buf[(dec->intg-1) / 9 + 1]= ltime->second_part * 1000;
343
void class_decimal_trim(uint32_t *precision, uint32_t *scale)
345
if (!(*precision) && !(*scale))
102
#include <my_global.h>
104
#include <myisampack.h>
105
#include <my_sys.h> /* for my_alloca */
106
#include <m_string.h>
355
110
Internally decimal numbers are stored base 10^9 (see DIG_BASE below)
388
138
999900000, 999990000, 999999000,
389
139
999999900, 999999990 };
392
#define sanity(d) assert((d)->len > 0)
142
#define sanity(d) DBUG_ASSERT((d)->len > 0)
394
#define sanity(d) assert((d)->len >0 && ((d)->buf[0] | \
144
#define sanity(d) DBUG_ASSERT((d)->len >0 && ((d)->buf[0] | \
395
145
(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)))
465
@brief Get maximum value for given precision and scale
467
@param precision/scale see decimal_bin_size() below
468
@param to decimal where where the result will be stored
148
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) \
151
if (unlikely(intg1+frac1 > (len))) \
153
if (unlikely(intg1 > (len))) \
157
error=E_DEC_OVERFLOW; \
162
error=E_DEC_TRUNCATED; \
169
#define ADD(to, from1, from2, carry) /* assume carry <= 1 */ \
172
dec1 a=(from1)+(from2)+(carry); \
173
DBUG_ASSERT((carry) <= 1); \
174
if (((carry)= a >= DIG_BASE)) /* no division here! */ \
179
#define ADD2(to, from1, from2, carry) \
182
dec2 a=((dec2)(from1))+(from2)+(carry); \
183
if (((carry)= a >= DIG_BASE)) \
185
if (unlikely(a >= DIG_BASE)) \
193
#define SUB(to, from1, from2, carry) /* to=from1-from2 */ \
196
dec1 a=(from1)-(from2)-(carry); \
197
if (((carry)= a < 0)) \
202
#define SUB2(to, from1, from2, carry) /* to=from1-from2 */ \
205
dec1 a=(from1)-(from2)-(carry); \
206
if (((carry)= a < 0)) \
208
if (unlikely(a < 0)) \
217
Get maximum value for given precision and scale
221
precision/scale - see decimal_bin_size() below
222
to - decimal where where the result will be stored
469
223
to->buf and to->len must be set.
552
@brief Convert decimal to its printable string representation
308
Convert decimal to its printable string representation
554
@param from value to convert
555
@param to points to buffer where string representation
557
@param to_len in: size of to buffer
558
out: length of the actually written string
559
@param fixed_precision 0 if representation can be variable length and
312
from - value to convert
313
to - points to buffer where string representation
315
*to_len - in: size of to buffer
316
out: length of the actually written string
317
fixed_precision - 0 if representation can be variable length and
560
318
fixed_decimals will not be checked in this case.
561
319
Put number as with fixed point position with this
562
320
number of digits (sign counted and decimal point is
564
@param fixed_decimals number digits after point.
565
@param filler character to fill gaps in case of fixed_precision > 0
322
fixed_decimals - number digits after point.
323
filler - character to fill gaps in case of fixed_precision > 0
569
@retval E_DEC_TRUNCATED
570
@retval E_DEC_OVERFLOW
326
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
572
int decimal2string(const decimal_t *from, char *to, int *to_len,
329
int decimal2string(decimal_t *from, char *to, int *to_len,
573
330
int fixed_precision, int fixed_decimals,
741
@param Left shift for alignment of data in buffer
743
@param dec pointer to decimal number which have to be shifted
744
@param shift number of decimal digits on which it should be shifted
745
@param beg beginning of decimal digits (see digits_bounds())
746
@param end end of decimal digits (see digits_bounds())
749
Result fitting in the buffer should be garanted.
750
'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
752
@todo Above note is unclear - is 'garanted' a typo for 'guaranteed'
501
Left shift for alignment of data in buffer
505
dec pointer to decimal number which have to be shifted
506
shift number of decimal digits on which it should be shifted
507
beg/end bounds of decimal digits (see digits_bounds())
510
Result fitting in the buffer should be garanted.
511
'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
755
514
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;
516
dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
517
dec1 *end= dec->buf + ROUND_UP(last) - 1;
759
518
int c_shift= DIG_PER_DEC1 - shift;
760
assert(from >= dec->buf);
761
assert(end < dec->buf + dec->len);
519
DBUG_ASSERT(from >= dec->buf);
520
DBUG_ASSERT(end < dec->buf + dec->len);
762
521
if (beg % DIG_PER_DEC1 < shift)
763
522
*(from - 1)= (*from) / powers10[c_shift];
764
523
for(; from < end; from++)
772
@brief Right shift for alignment of data in buffer
774
@param dec pointer to decimal number which have to be shifted
775
@param shift number of decimal digits on which it should be shifted
776
@param beg beginning of decimal digits (see digits_bounds())
777
@param end end of decimal digits (see digits_bounds())
531
Right shift for alignment of data in buffer
535
dec pointer to decimal number which have to be shifted
536
shift number of decimal digits on which it should be shifted
537
beg/end bounds of decimal digits (see digits_bounds())
780
540
Result fitting in the buffer should be garanted.
781
541
'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
783
544
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;
546
dec1 *from= dec->buf + ROUND_UP(last) - 1;
547
dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1;
787
548
int c_shift= DIG_PER_DEC1 - shift;
788
assert(from < dec->buf + dec->len);
789
assert(end >= dec->buf);
549
DBUG_ASSERT(from < dec->buf + dec->len);
550
DBUG_ASSERT(end >= dec->buf);
790
551
if (DIG_PER_DEC1 - ((last - 1) % DIG_PER_DEC1 + 1) < shift)
791
552
*(from + 1)= (*from % powers10[shift]) * powers10[c_shift];
792
553
for(; from > end; from--)
1004
@brief Convert string to decimal
765
Convert string to decimal
1006
@param from value to convert. Doesn't have to be \0 terminated!
1007
@param to decimal where where the result will be stored
769
from - value to convert. Doesn't have to be \0 terminated!
770
to - decimal where where the result will be stored
1008
771
to->buf and to->len must be set.
1009
@param end Pointer to pointer to end of string. Will on return be
772
end - Pointer to pointer to end of string. Will on return be
1010
773
set to the char after the last used character
1011
@param fixed use to->intg, to->frac as limits for input number
774
fixed - use to->intg, to->frac as limits for input number
1014
777
to->intg and to->frac can be modified even when fixed=1
1015
778
(but only decreased, in this case)
1018
781
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_BAD_NUM/E_DEC_OOM
1019
782
In case of E_DEC_FATAL_ERROR *to is set to decimal zero
1020
783
(to make error handling easier)
1023
internal_str2dec(char *from, decimal_t *to, char **end, bool fixed)
787
internal_str2dec(const char *from, decimal_t *to, char **end, my_bool fixed)
1026
char *end_of_string = *end;
789
const char *s= from, *s1, *endp, *end_of_string= *end;
1028
790
int i, intg, frac, error, intg1, frac1;
1032
794
error= E_DEC_BAD_NUM; /* In case of bad number */
1033
while (s < end_of_string && my_isspace(&my_charset_utf8_general_ci, *s))
795
while (s < end_of_string && my_isspace(&my_charset_latin1, *s))
1035
797
if (s == end_of_string)
1036
798
goto fatal_error;
1187
951
rc = decimal2string(from, strbuf, &len, 0, 0, 0);
1188
952
end= strbuf + len;
954
DBUG_PRINT("info", ("interm.: %s", strbuf));
1190
*to= internal::my_strtod(strbuf, &end, &error);
956
*to= my_strtod(strbuf, &end, &error);
958
DBUG_PRINT("info", ("result: %f (%lx)", *to, *(ulong *)to));
1192
960
return (rc != E_DEC_OK) ? rc : (error ? E_DEC_OVERFLOW : E_DEC_OK);
1196
@param Convert double to decimal
1198
@param[in] from value to convert
1199
@param[out] to result will be stored there
964
Convert double to decimal
968
from - value to convert
969
to - result will be stored there
1202
972
E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
1205
int double2decimal(const double from, decimal_t *to)
975
int double2decimal(double from, decimal_t *to)
1207
977
char buff[FLOATING_POINT_BUFFER], *end;
1209
end= buff + internal::my_gcvt(from,
1210
internal::MY_GCVT_ARG_DOUBLE,
1211
sizeof(buff) - 1, buff, NULL);
979
DBUG_ENTER("double2decimal");
980
end= buff + my_gcvt(from, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
1212
981
res= string2decimal(buff, to, &end);
982
DBUG_PRINT("exit", ("res: %d", res));
1501
1271
case 2: mi_int2store(to, x); break;
1502
1272
case 3: mi_int3store(to, x); break;
1503
1273
case 4: mi_int4store(to, x); break;
1274
default: DBUG_ASSERT(0);
1508
1278
if (fsize0 > fsize1)
1510
unsigned char *to_end= orig_to + orig_fsize0 + orig_isize0;
1280
uchar *to_end= orig_to + orig_fsize0 + orig_isize0;
1512
1282
while (fsize0-- > fsize1 && to < to_end)
1513
*to++= (unsigned char)mask;
1515
1285
orig_to[0]^= 0x80;
1517
1287
/* Check that we have written the whole decimal and nothing more */
1518
assert(to == orig_to + orig_fsize0 + orig_isize0);
1288
DBUG_ASSERT(to == orig_to + orig_fsize0 + orig_isize0);
1523
@brief Restores decimal from its binary fixed-length representation
1525
@param from value to convert
1527
@param precision see decimal_bin_size() below
1528
@param scale see decimal_bin_size() below
1293
Restores decimal from its binary fixed-length representation
1297
from - value to convert
1299
precision/scale - see decimal_bin_size() below
1531
1302
see decimal2bin()
1532
1303
the buffer is assumed to be of the size decimal_bin_size(precision, scale)
1535
1306
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1537
int bin2decimal(const unsigned char *from, decimal_t *to, int precision, int scale)
1309
int bin2decimal(const uchar *from, decimal_t *to, int precision, int scale)
1539
1311
int error=E_DEC_OK, intg=precision-scale,
1540
1312
intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
1541
1313
intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1,
1542
1314
intg1=intg0+(intg0x>0), frac1=frac0+(frac0x>0);
1543
1315
dec1 *buf=to->buf, mask=(*from & 0x80) ? 0 : -1;
1544
const unsigned char *stop;
1545
unsigned char *d_copy;
1546
1318
int bin_size= decimal_bin_size(precision, scale);
1549
d_copy= (unsigned char*) alloca(bin_size);
1321
d_copy= (uchar*) my_alloca(bin_size);
1550
1322
memcpy(d_copy, from, bin_size);
1551
1323
d_copy[0]^= 0x80;
1554
fix_intg_frac_error(to->len, intg1, frac1, error);
1326
FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1555
1327
if (unlikely(error))
1557
1329
if (intg1 < intg0+(intg0x>0))
1622
1394
case 2: x=mi_sint2korr(from); break;
1623
1395
case 3: x=mi_sint3korr(from); break;
1624
1396
case 4: x=mi_sint4korr(from); break;
1397
default: DBUG_ASSERT(0);
1627
1399
*buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x];
1628
if (((uint32_t)*buf) > DIG_MAX)
1400
if (((uint32)*buf) > DIG_MAX)
1409
decimal_make_zero(((decimal_t*) to));
1636
1410
return(E_DEC_BAD_NUM);
1640
@brief Returns the size of array to hold a binary representation of a decimal
1642
@return Size in bytes
1414
Returns the size of array to hold a decimal with given precision and scale
1418
(multiply by sizeof(dec1) to get the size if bytes)
1421
int decimal_size(int precision, int scale)
1423
DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
1424
return ROUND_UP(precision-scale)+ROUND_UP(scale);
1428
Returns the size of array to hold a binary representation of a decimal
1644
1434
int decimal_bin_size(int precision, int scale)
1646
1436
int intg=precision-scale,
1647
1437
intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
1648
1438
intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1;
1650
assert(scale >= 0 && precision > 0 && scale <= precision);
1440
DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
1651
1441
return intg0*sizeof(dec1)+dig2bytes[intg0x]+
1652
1442
frac0*sizeof(dec1)+dig2bytes[frac0x];
1656
@brief Rounds the decimal to "scale" digits
1658
@param from - decimal to round,
1659
@param to - result buffer. from==to is allowed
1660
@param scale - to what position to round. can be negative!
1661
@param mode - round to nearest even or truncate
1446
Rounds the decimal to "scale" digits
1450
from - decimal to round,
1451
to - result buffer. from==to is allowed
1452
scale - to what position to round. can be negative!
1453
mode - round to nearest even or truncate
1664
1456
scale can be negative !
1665
1457
one TRUNCATED error (line XXX below) isn't treated very logical :(
1668
1460
E_DEC_OK/E_DEC_TRUNCATED
1671
decimal_round(const decimal_t *from, decimal_t *to, int scale,
1464
decimal_round(decimal_t *from, decimal_t *to, int scale,
1672
1465
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 +
1467
int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
1468
frac1=ROUND_UP(from->frac), round_digit= 0,
1469
intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
1470
intg1=ROUND_UP(from->intg +
1678
1471
(((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
1679
1472
dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
1863
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),
1657
Returns the size of the result of the operation
1660
decimal_result_size()
1661
from1 - operand of the unary operation or first operand of the
1663
from2 - second operand of the binary operation
1664
op - operation. one char '+', '-', '*', '/' are allowed
1665
others may be added later
1666
param - extra param to the operation. unused for '+', '-', '*'
1667
scale increment for '/'
1670
returned valued may be larger than the actual buffer requred
1671
in the operation, as decimal_result_size, by design, operates on
1672
precision/scale values only and not on the actual decimal number
1675
size of to->buf array in dec1 elements. to get size in bytes
1676
multiply by sizeof(dec1)
1679
int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param)
1683
return ROUND_UP(max(from1->intg, from2->intg)) +
1684
ROUND_UP(max(from1->frac, from2->frac));
1686
return ROUND_UP(max(from1->intg, from2->intg)+1) +
1687
ROUND_UP(max(from1->frac, from2->frac));
1689
return ROUND_UP(from1->intg+from2->intg)+
1690
ROUND_UP(from1->frac)+ROUND_UP(from2->frac);
1692
return ROUND_UP(from1->intg+from2->intg+1+from1->frac+from2->frac+param);
1693
default: DBUG_ASSERT(0);
1695
return -1; /* shut up the warning */
1698
static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
1700
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1701
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1867
1702
frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
1868
1703
dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
1918
1753
while (buf1 > stop)
1919
1754
*--buf0=*--buf1;
1921
/* part 2 - cmin(frac) ... cmin(intg) */
1756
/* part 2 - min(frac) ... min(intg) */
1923
1758
while (buf1 > stop2)
1925
add(*--buf0, *--buf1, *--buf2, carry);
1760
ADD(*--buf0, *--buf1, *--buf2, carry);
1928
/* part 3 - cmin(intg) ... cmax(intg) */
1763
/* part 3 - min(intg) ... max(intg) */
1929
1764
buf1= intg1 > intg2 ? ((stop=from1->buf)+intg1-intg2) :
1930
1765
((stop=from2->buf)+intg2-intg1) ;
1931
1766
while (buf1 > stop)
1933
add(*--buf0, *--buf1, 0, carry);
1768
ADD(*--buf0, *--buf1, 0, carry);
1936
1771
if (unlikely(carry))
1938
assert(buf0 == to->buf || buf0 == to->buf+1);
1773
DBUG_ASSERT(buf0 == to->buf || buf0 == to->buf+1);
1943
1778
/* to=from1-from2.
1944
1779
if to==0, return -1/0/+1 - the result of the comparison */
1945
static int do_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1780
static int do_sub(decimal_t *from1, 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);
1782
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1783
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
1949
1784
int frac0=max(frac1, frac2), error;
1950
1785
dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
2090
int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1923
int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
2092
1925
if (likely(from1->sign == from2->sign))
2093
1926
return do_add(from1, from2, to);
2094
1927
return do_sub(from1, from2, to);
2097
int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1930
int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
2099
1932
if (likely(from1->sign == from2->sign))
2100
1933
return do_sub(from1, from2, to);
2101
1934
return do_add(from1, from2, to);
2104
int decimal_cmp(const decimal_t *from1, const decimal_t *from2)
1937
int decimal_cmp(decimal_t *from1, decimal_t *from2)
2106
1939
if (likely(from1->sign == from2->sign))
2107
1940
return do_sub(from1, from2, 0);
2108
1941
return from1->sign > from2->sign ? -1 : 1;
2111
int decimal_t::isZero() const
1944
int decimal_is_zero(decimal_t *from)
2114
*end= buf1 +round_up(intg) +round_up(frac);
1946
dec1 *buf1=from->buf,
1947
*end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
2116
1948
while (buf1 < end)
2128
@brief multiply two decimals
2130
@param[in] from1 First factor
2131
@param[in] from2 Second factor
2132
@param[out] to product
1955
multiply two decimals
1959
from1, from2 - factors
2135
1963
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW;
2138
1966
in this implementation, with sizeof(dec1)=4 we have DIG_PER_DEC1=9,
2139
1967
and 63-digit number will take only 7 dec1 words (basically a 7-digit
2140
1968
"base 999999999" number). Thus there's no need in fast multiplication
2144
1972
XXX if this library is to be used with huge numbers of thousands of
2145
1973
digits, fast multiplication must be implemented.
2147
int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1975
int decimal_mul(decimal_t *from1, 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),
1977
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1978
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1979
intg0=ROUND_UP(from1->intg+from2->intg),
2152
1980
frac0=frac1+frac2, error, i, j, d_to_move;
2153
1981
dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
2154
1982
*start2, *stop2, *stop1, *start0, carry;
2254
2082
naive division algorithm (Knuth's Algorithm D in 4.3.1) -
2255
2083
it's ok for short numbers
2256
2084
also we're using alloca() to allocate a temporary buffer
2259
If this library is to be used with huge numbers of thousands of
2086
XXX if this library is to be used with huge numbers of thousands of
2260
2087
digits, fast division must be implemented and alloca should be
2261
2088
changed to malloc (or at least fallback to malloc if alloca() fails)
2262
2089
but then, decimal_mul() should be rewritten too :(
2264
static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
2091
static int do_div_mod(decimal_t *from1, decimal_t *from2,
2265
2092
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,
2094
int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2095
frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2269
2096
error= 0, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2270
2097
dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2271
2098
*start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2495
2322
to->frac=frac0*DIG_PER_DEC1;
2496
2323
error=E_DEC_TRUNCATED;
2498
assert(buf0 + (stop1 - start1) <= to->buf + to->len);
2325
DBUG_ASSERT(buf0 + (stop1 - start1) <= to->buf + to->len);
2499
2326
while (start1 < stop1)
2500
2327
*buf0++=*start1++;
2507
@brief division of two decimals
2509
@param[in] from1 dividend
2510
@param[in] from2 divisor
2511
@param[out] to quotient
2335
division of two decimals
2514
2344
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2517
2347
see do_div_mod()
2520
decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to, int scale_incr)
2351
decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, int scale_incr)
2522
2353
return do_div_mod(from1, from2, to, 0, scale_incr);
2528
the modulus R in R = M mod N
2534
R = M - k*N, where k is integer
2536
thus, there's no requirement for M or N to be integers
2539
@param from1 dividend
2540
@param from2 divisor
2544
2366
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2547
2369
see do_div_mod()
2372
the modulus R in R = M mod N
2378
R = M - k*N, where k is integer
2380
thus, there's no requirement for M or N to be integers
2550
int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
2383
int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to)
2552
2385
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
} /* namespace drizzled */