#include <my_global.h>#include <m_ctype.h>#include <myisampack.h>#include <my_sys.h>#include <m_string.h>#include <decimal.h>Include dependency graph for decimal.c:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
Defines | |
| #define | DIG_PER_DEC1 9 |
| #define | DIG_MASK 100000000 |
| #define | DIG_BASE 1000000000 |
| #define | DIG_MAX (DIG_BASE-1) |
| #define | DIG_BASE2 ((dec2)DIG_BASE * (dec2)DIG_BASE) |
| #define | ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1) |
| #define | sanity(d) |
| #define | FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) |
| #define | ADD(to, from1, from2, carry) |
| #define | ADD2(to, from1, from2, carry) |
| #define | SUB(to, from1, from2, carry) |
| #define | SUB2(to, from1, from2, carry) |
Typedefs | |
| typedef decimal_digit_t | dec1 |
| typedef longlong | dec2 |
Functions | |
| void | max_decimal (int precision, int frac, decimal_t *to) |
| static dec1 * | remove_leading_zeroes (decimal_t *from, int *intg_result) |
| int | decimal_actual_fraction (decimal_t *from) |
| int | decimal2string (decimal_t *from, char *to, int *to_len, int fixed_precision, int fixed_decimals, char filler) |
| static void | digits_bounds (decimal_t *from, int *start_result, int *end_result) |
| void | do_mini_left_shift (decimal_t *dec, int shift, int beg, int last) |
| void | do_mini_right_shift (decimal_t *dec, int shift, int beg, int last) |
| int | decimal_shift (decimal_t *dec, int shift) |
| int | internal_str2dec (const char *from, decimal_t *to, char **end, my_bool fixed) |
| int | decimal2double (decimal_t *from, double *to) |
| int | double2decimal (double from, decimal_t *to) |
| static int | ull2dec (ulonglong from, decimal_t *to) |
| int | ulonglong2decimal (ulonglong from, decimal_t *to) |
| int | longlong2decimal (longlong from, decimal_t *to) |
| int | decimal2ulonglong (decimal_t *from, ulonglong *to) |
| int | decimal2longlong (decimal_t *from, longlong *to) |
| int | decimal2bin (decimal_t *from, char *to, int precision, int frac) |
| int | bin2decimal (char *from, decimal_t *to, int precision, int scale) |
| int | decimal_size (int precision, int scale) |
| int | decimal_bin_size (int precision, int scale) |
| int | decimal_round (decimal_t *from, decimal_t *to, int scale, decimal_round_mode mode) |
| int | decimal_result_size (decimal_t *from1, decimal_t *from2, char op, int param) |
| static int | do_add (decimal_t *from1, decimal_t *from2, decimal_t *to) |
| static int | do_sub (decimal_t *from1, decimal_t *from2, decimal_t *to) |
| int | decimal_intg (decimal_t *from) |
| int | decimal_add (decimal_t *from1, decimal_t *from2, decimal_t *to) |
| int | decimal_sub (decimal_t *from1, decimal_t *from2, decimal_t *to) |
| int | decimal_cmp (decimal_t *from1, decimal_t *from2) |
| int | decimal_is_zero (decimal_t *from) |
| int | decimal_mul (decimal_t *from1, decimal_t *from2, decimal_t *to) |
| static int | do_div_mod (decimal_t *from1, decimal_t *from2, decimal_t *to, decimal_t *mod, int scale_incr) |
| int | decimal_div (decimal_t *from1, decimal_t *from2, decimal_t *to, int scale_incr) |
| int | decimal_mod (decimal_t *from1, decimal_t *from2, decimal_t *to) |
Variables | |
| static const dec1 | powers10 [DIG_PER_DEC1+1] |
| static const int | dig2bytes [DIG_PER_DEC1+1] = {0, 1, 1, 2, 2, 3, 3, 4, 4, 4} |
| static const dec1 | frac_max [DIG_PER_DEC1-1] |
| #define ADD | ( | to, | |||
| from1, | |||||
| from2, | |||||
| carry | ) |
Value:
/* assume carry <= 1 */ \ do \ { \ dec1 a=(from1)+(from2)+(carry); \ DBUG_ASSERT((carry) <= 1); \ if (((carry)= a >= DIG_BASE)) /* no division here! */ \ a-=DIG_BASE; \ (to)=a; \ } while(0)
Definition at line 170 of file decimal.c.
Referenced by decimal_mul(), decimal_round(), do_add(), and do_div_mod().
| #define ADD2 | ( | to, | |||
| from1, | |||||
| from2, | |||||
| carry | ) |
| #define DIG_BASE 1000000000 |
Definition at line 130 of file decimal.c.
Referenced by decimal2double(), decimal2longlong(), decimal2ulonglong(), decimal_mul(), decimal_round(), do_div_mod(), and ull2dec().
| #define DIG_MASK 100000000 |
| #define DIG_MAX (DIG_BASE-1) |
Definition at line 131 of file decimal.c.
Referenced by bin2decimal(), decimal_round(), do_add(), and max_decimal().
| #define DIG_PER_DEC1 9 |
Definition at line 128 of file decimal.c.
Referenced by bin2decimal(), decimal2bin(), decimal2double(), decimal2longlong(), decimal2string(), decimal2ulonglong(), decimal_actual_fraction(), decimal_bin_size(), decimal_mul(), decimal_round(), decimal_shift(), digits_bounds(), do_add(), do_div_mod(), do_mini_left_shift(), do_mini_right_shift(), do_sub(), internal_str2dec(), max_decimal(), and remove_leading_zeroes().
| #define FIX_INTG_FRAC_ERROR | ( | len, | |||
| intg1, | |||||
| frac1, | |||||
| error | ) |
Value:
do \ { \ if (unlikely(intg1+frac1 > (len))) \ { \ if (unlikely(intg1 > (len))) \ { \ intg1=(len); \ frac1=0; \ error=E_DEC_OVERFLOW; \ } \ else \ { \ frac1=(len)-intg1; \ error=E_DEC_TRUNCATED; \ } \ } \ else \ error=E_DEC_OK; \ } while(0)
Definition at line 149 of file decimal.c.
Referenced by bin2decimal(), decimal_mul(), do_add(), do_div_mod(), do_sub(), and internal_str2dec().
| #define ROUND_UP | ( | X | ) | (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1) |
Definition at line 133 of file decimal.c.
Referenced by decimal2string(), decimal_actual_fraction(), decimal_is_zero(), decimal_mul(), decimal_result_size(), decimal_round(), decimal_shift(), decimal_size(), digits_bounds(), do_add(), do_div_mod(), do_mini_left_shift(), do_mini_right_shift(), do_sub(), internal_str2dec(), and print_decimal().
| #define sanity | ( | d | ) |
Value:
DBUG_ASSERT((d)->len >0 && ((d)->buf[0] | \ (d)->buf[(d)->len-1] | 1))
Definition at line 145 of file decimal.c.
Referenced by bin2decimal(), decimal_mul(), decimal_round(), do_add(), do_div_mod(), do_sub(), internal_str2dec(), and ull2dec().
| #define SUB | ( | to, | |||
| from1, | |||||
| from2, | |||||
| carry | ) |
| #define SUB2 | ( | to, | |||
| from1, | |||||
| from2, | |||||
| carry | ) |
| typedef decimal_digit_t dec1 |
| int bin2decimal | ( | char * | from, | |
| decimal_t * | to, | |||
| int | precision, | |||
| int | scale | |||
| ) |
Definition at line 1306 of file decimal.c.
Referenced by binary2my_decimal().
01307 { 01308 int error=E_DEC_OK, intg=precision-scale, 01309 intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1, 01310 intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1, 01311 intg1=intg0+(intg0x>0), frac1=frac0+(frac0x>0); 01312 dec1 *buf=to->buf, mask=(*from & 0x80) ? 0 : -1; 01313 char *stop; 01314 char *d_copy; 01315 int bin_size= decimal_bin_size(precision, scale); 01316 01317 sanity(to); 01318 d_copy= (char *)my_alloca(bin_size); 01319 memcpy(d_copy, from, bin_size); 01320 d_copy[0]^= 0x80; 01321 from= d_copy; 01322 01323 FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error); 01324 if (unlikely(error)) 01325 { 01326 if (intg1 < intg0+(intg0x>0)) 01327 { 01328 from+=dig2bytes[intg0x]+sizeof(dec1)*(intg0-intg1); 01329 frac0=frac0x=intg0x=0; 01330 intg0=intg1; 01331 } 01332 else 01333 { 01334 frac0x=0; 01335 frac0=frac1; 01336 } 01337 } 01338 01339 to->sign=(mask != 0); 01340 to->intg=intg0*DIG_PER_DEC1+intg0x; 01341 to->frac=frac0*DIG_PER_DEC1+frac0x; 01342 01343 if (intg0x) 01344 { 01345 int i=dig2bytes[intg0x]; 01346 dec1 x; 01347 switch (i) 01348 { 01349 case 1: x=mi_sint1korr(from); break; 01350 case 2: x=mi_sint2korr(from); break; 01351 case 3: x=mi_sint3korr(from); break; 01352 case 4: x=mi_sint4korr(from); break; 01353 default: DBUG_ASSERT(0); 01354 } 01355 from+=i; 01356 *buf=x ^ mask; 01357 if (((ulonglong)*buf) >= (ulonglong) powers10[intg0x+1]) 01358 goto err; 01359 if (buf > to->buf || *buf != 0) 01360 buf++; 01361 else 01362 to->intg-=intg0x; 01363 } 01364 for (stop=from+intg0*sizeof(dec1); from < stop; from+=sizeof(dec1)) 01365 { 01366 DBUG_ASSERT(sizeof(dec1) == 4); 01367 *buf=mi_sint4korr(from) ^ mask; 01368 if (((uint32)*buf) > DIG_MAX) 01369 goto err; 01370 if (buf > to->buf || *buf != 0) 01371 buf++; 01372 else 01373 to->intg-=DIG_PER_DEC1; 01374 } 01375 DBUG_ASSERT(to->intg >=0); 01376 for (stop=from+frac0*sizeof(dec1); from < stop; from+=sizeof(dec1)) 01377 { 01378 DBUG_ASSERT(sizeof(dec1) == 4); 01379 *buf=mi_sint4korr(from) ^ mask; 01380 if (((uint32)*buf) > DIG_MAX) 01381 goto err; 01382 buf++; 01383 } 01384 if (frac0x) 01385 { 01386 int i=dig2bytes[frac0x]; 01387 dec1 x; 01388 switch (i) 01389 { 01390 case 1: x=mi_sint1korr(from); break; 01391 case 2: x=mi_sint2korr(from); break; 01392 case 3: x=mi_sint3korr(from); break; 01393 case 4: x=mi_sint4korr(from); break; 01394 default: DBUG_ASSERT(0); 01395 } 01396 *buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x]; 01397 if (((uint32)*buf) > DIG_MAX) 01398 goto err; 01399 buf++; 01400 } 01401 my_afree(d_copy); 01402 return error; 01403 01404 err: 01405 my_afree(d_copy); 01406 decimal_make_zero(((decimal_t*) to)); 01407 return(E_DEC_BAD_NUM); 01408 }
Here is the caller graph for this function:

| int decimal2bin | ( | decimal_t * | from, | |
| char * | to, | |||
| int | precision, | |||
| int | frac | |||
| ) |
Definition at line 1171 of file decimal.c.
Referenced by my_decimal2binary(), and User_var_log_event::write().
01172 { 01173 dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1; 01174 int error=E_DEC_OK, intg=precision-frac, 01175 isize1, intg1, intg1x, from_intg, 01176 intg0=intg/DIG_PER_DEC1, 01177 frac0=frac/DIG_PER_DEC1, 01178 intg0x=intg-intg0*DIG_PER_DEC1, 01179 frac0x=frac-frac0*DIG_PER_DEC1, 01180 frac1=from->frac/DIG_PER_DEC1, 01181 frac1x=from->frac-frac1*DIG_PER_DEC1, 01182 isize0=intg0*sizeof(dec1)+dig2bytes[intg0x], 01183 fsize0=frac0*sizeof(dec1)+dig2bytes[frac0x], 01184 fsize1=frac1*sizeof(dec1)+dig2bytes[frac1x]; 01185 const int orig_isize0= isize0; 01186 const int orig_fsize0= fsize0; 01187 char *orig_to= to; 01188 01189 buf1= remove_leading_zeroes(from, &from_intg); 01190 01191 if (unlikely(from_intg+fsize1==0)) 01192 { 01193 mask=0; /* just in case */ 01194 intg=1; 01195 buf1=&mask; 01196 } 01197 01198 intg1=from_intg/DIG_PER_DEC1; 01199 intg1x=from_intg-intg1*DIG_PER_DEC1; 01200 isize1=intg1*sizeof(dec1)+dig2bytes[intg1x]; 01201 01202 if (intg < from_intg) 01203 { 01204 buf1+=intg1-intg0+(intg1x>0)-(intg0x>0); 01205 intg1=intg0; intg1x=intg0x; 01206 error=E_DEC_OVERFLOW; 01207 } 01208 else if (isize0 > isize1) 01209 { 01210 while (isize0-- > isize1) 01211 *to++= (char)mask; 01212 } 01213 if (fsize0 < fsize1) 01214 { 01215 frac1=frac0; frac1x=frac0x; 01216 error=E_DEC_TRUNCATED; 01217 } 01218 else if (fsize0 > fsize1 && frac1x) 01219 { 01220 if (frac0 == frac1) 01221 { 01222 frac1x=frac0x; 01223 fsize0= fsize1; 01224 } 01225 else 01226 { 01227 frac1++; 01228 frac1x=0; 01229 } 01230 } 01231 01232 /* intg1x part */ 01233 if (intg1x) 01234 { 01235 int i=dig2bytes[intg1x]; 01236 dec1 x=(*buf1++ % powers10[intg1x]) ^ mask; 01237 switch (i) 01238 { 01239 case 1: mi_int1store(to, x); break; 01240 case 2: mi_int2store(to, x); break; 01241 case 3: mi_int3store(to, x); break; 01242 case 4: mi_int4store(to, x); break; 01243 default: DBUG_ASSERT(0); 01244 } 01245 to+=i; 01246 } 01247 01248 /* intg1+frac1 part */ 01249 for (stop1=buf1+intg1+frac1; buf1 < stop1; to+=sizeof(dec1)) 01250 { 01251 dec1 x=*buf1++ ^ mask; 01252 DBUG_ASSERT(sizeof(dec1) == 4); 01253 mi_int4store(to, x); 01254 } 01255 01256 /* frac1x part */ 01257 if (frac1x) 01258 { 01259 dec1 x; 01260 int i=dig2bytes[frac1x], 01261 lim=(frac1 < frac0 ? DIG_PER_DEC1 : frac0x); 01262 while (frac1x < lim && dig2bytes[frac1x] == i) 01263 frac1x++; 01264 x=(*buf1 / powers10[DIG_PER_DEC1 - frac1x]) ^ mask; 01265 switch (i) 01266 { 01267 case 1: mi_int1store(to, x); break; 01268 case 2: mi_int2store(to, x); break; 01269 case 3: mi_int3store(to, x); break; 01270 case 4: mi_int4store(to, x); break; 01271 default: DBUG_ASSERT(0); 01272 } 01273 to+=i; 01274 } 01275 if (fsize0 > fsize1) 01276 { 01277 char *to_end= orig_to + orig_fsize0 + orig_isize0; 01278 01279 while (fsize0-- > fsize1 && to < to_end) 01280 *to++=(uchar)mask; 01281 } 01282 orig_to[0]^= 0x80; 01283 01284 /* Check that we have written the whole decimal and nothing more */ 01285 DBUG_ASSERT(to == orig_to + orig_fsize0 + orig_isize0); 01286 return error; 01287 }
Here is the caller graph for this function:

| int decimal2double | ( | decimal_t * | from, | |
| double * | to | |||
| ) |
Definition at line 947 of file decimal.c.
Referenced by my_decimal2double().
00948 { 00949 double x=0, t=DIG_BASE; 00950 int intg, frac; 00951 dec1 *buf=from->buf; 00952 00953 for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1) 00954 x=x*DIG_BASE + *buf++; 00955 for (frac=from->frac; frac > 0; frac-=DIG_PER_DEC1, t*=DIG_BASE) 00956 x+=*buf++/t; 00957 *to=from->sign ? -x : x; 00958 return E_DEC_OK; 00959 }
Here is the caller graph for this function:

Definition at line 1056 of file decimal.c.
Referenced by my_decimal2int().
01057 { 01058 dec1 *buf=from->buf; 01059 longlong x=0; 01060 int intg, frac; 01061 01062 for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1) 01063 { 01064 longlong y=x; 01065 /* 01066 Attention: trick! 01067 we're calculating -|from| instead of |from| here 01068 because |LONGLONG_MIN| > LONGLONG_MAX 01069 so we can convert -9223372036854775808 correctly 01070 */ 01071 x=x*DIG_BASE - *buf++; 01072 if (unlikely(y < (LONGLONG_MIN/DIG_BASE) || x > y)) 01073 { 01074 *to= from->sign ? y : -y; 01075 return E_DEC_OVERFLOW; 01076 } 01077 } 01078 /* boundary case: 9223372036854775808 */ 01079 if (unlikely(from->sign==0 && x == LONGLONG_MIN)) 01080 { 01081 *to= LONGLONG_MAX; 01082 return E_DEC_OVERFLOW; 01083 } 01084 01085 *to=from->sign ? x : -x; 01086 for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1) 01087 if (*buf++) 01088 return E_DEC_TRUNCATED; 01089 return E_DEC_OK; 01090 }
Here is the caller graph for this function:

| int decimal2string | ( | decimal_t * | from, | |
| char * | to, | |||
| int * | to_len, | |||
| int | fixed_precision, | |||
| int | fixed_decimals, | |||
| char | filler | |||
| ) |
Definition at line 332 of file decimal.c.
Referenced by dbug_decimal_as_string(), and my_decimal2string().
00335 { 00336 int len, intg, frac= from->frac, i, intg_len, frac_len, fill; 00337 /* number digits before decimal point */ 00338 int fixed_intg= (fixed_precision ? 00339 (fixed_precision - fixed_decimals) : 0); 00340 int error=E_DEC_OK; 00341 char *s=to; 00342 dec1 *buf, *buf0=from->buf, tmp; 00343 00344 DBUG_ASSERT(*to_len >= 2+from->sign); 00345 00346 /* removing leading zeroes */ 00347 buf0= remove_leading_zeroes(from, &intg); 00348 if (unlikely(intg+frac==0)) 00349 { 00350 intg=1; 00351 tmp=0; 00352 buf0=&tmp; 00353 } 00354 00355 if (!(intg_len= fixed_precision ? fixed_intg : intg)) 00356 intg_len= 1; 00357 frac_len= fixed_precision ? fixed_decimals : frac; 00358 len= from->sign + intg_len + test(frac) + frac_len; 00359 if (fixed_precision) 00360 { 00361 if (frac > fixed_decimals) 00362 { 00363 error= E_DEC_TRUNCATED; 00364 frac= fixed_decimals; 00365 } 00366 if (intg > fixed_intg) 00367 { 00368 error= E_DEC_OVERFLOW; 00369 intg= fixed_intg; 00370 } 00371 } 00372 else if (unlikely(len > --*to_len)) /* reserve one byte for \0 */ 00373 { 00374 int i=len-*to_len; 00375 error= (frac && i <= frac + 1) ? E_DEC_TRUNCATED : E_DEC_OVERFLOW; 00376 if (frac && i >= frac + 1) i--; 00377 if (i > frac) 00378 { 00379 intg-= i-frac; 00380 frac= 0; 00381 } 00382 else 00383 frac-=i; 00384 len= from->sign + intg_len + test(frac) + frac_len; 00385 } 00386 *to_len=len; 00387 s[len]=0; 00388 00389 if (from->sign) 00390 *s++='-'; 00391 00392 if (frac) 00393 { 00394 char *s1= s + intg_len; 00395 fill= frac_len - frac; 00396 buf=buf0+ROUND_UP(intg); 00397 *s1++='.'; 00398 for (; frac>0; frac-=DIG_PER_DEC1) 00399 { 00400 dec1 x=*buf++; 00401 for (i=min(frac, DIG_PER_DEC1); i; i--) 00402 { 00403 dec1 y=x/DIG_MASK; 00404 *s1++='0'+(uchar)y; 00405 x-=y*DIG_MASK; 00406 x*=10; 00407 } 00408 } 00409 for(; fill; fill--) 00410 *s1++=filler; 00411 } 00412 00413 fill= intg_len - intg; 00414 if (intg == 0) 00415 fill--; /* symbol 0 before digital point */ 00416 for(; fill; fill--) 00417 *s++=filler; 00418 if (intg) 00419 { 00420 s+=intg; 00421 for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1) 00422 { 00423 dec1 x=*--buf; 00424 for (i=min(intg, DIG_PER_DEC1); i; i--) 00425 { 00426 dec1 y=x/10; 00427 *--s='0'+(uchar)(x-y*10); 00428 x=y; 00429 } 00430 } 00431 } 00432 else 00433 *s= '0'; 00434 return error; 00435 }
Here is the caller graph for this function:

Definition at line 1027 of file decimal.c.
Referenced by my_decimal2int().
01028 { 01029 dec1 *buf=from->buf; 01030 ulonglong x=0; 01031 int intg, frac; 01032 01033 if (from->sign) 01034 { 01035 *to=ULL(0); 01036 return E_DEC_OVERFLOW; 01037 } 01038 01039 for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1) 01040 { 01041 ulonglong y=x; 01042 x=x*DIG_BASE + *buf++; 01043 if (unlikely(y > ((ulonglong) ULONGLONG_MAX/DIG_BASE) || x < y)) 01044 { 01045 *to=y; 01046 return E_DEC_OVERFLOW; 01047 } 01048 } 01049 *to=x; 01050 for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1) 01051 if (*buf++) 01052 return E_DEC_TRUNCATED; 01053 return E_DEC_OK; 01054 }
Here is the caller graph for this function:

| int decimal_actual_fraction | ( | decimal_t * | from | ) |
Definition at line 285 of file decimal.c.
Referenced by my_decimal2binary().
00286 { 00287 int frac= from->frac, i; 00288 dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1; 00289 00290 if (frac == 0) 00291 return 0; 00292 00293 i= ((frac - 1) % DIG_PER_DEC1 + 1); 00294 while (frac > 0 && *buf0 == 0) 00295 { 00296 frac-= i; 00297 i= DIG_PER_DEC1; 00298 buf0--; 00299 } 00300 if (frac > 0) 00301 { 00302 for (i= DIG_PER_DEC1 - ((frac - 1) % DIG_PER_DEC1); 00303 *buf0 % powers10[i++] == 0; 00304 frac--); 00305 } 00306 return frac; 00307 }
Here is the caller graph for this function:

| int decimal_bin_size | ( | int | precision, | |
| int | scale | |||
| ) |
Definition at line 1431 of file decimal.c.
Referenced by bin2decimal(), my_decimal_get_binary_size(), and User_var_log_event::write().
01432 { 01433 int intg=precision-scale, 01434 intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1, 01435 intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1; 01436 01437 DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision); 01438 return intg0*sizeof(dec1)+dig2bytes[intg0x]+ 01439 frac0*sizeof(dec1)+dig2bytes[frac0x]; 01440 }
Here is the caller graph for this function:

Definition at line 2336 of file decimal.c.
Referenced by my_decimal_div().
02337 { 02338 return do_div_mod(from1, from2, to, 0, scale_incr); 02339 }
Here is the caller graph for this function:

| int decimal_intg | ( | decimal_t * | from | ) |
Definition at line 1899 of file decimal.c.
Referenced by my_decimal_intg().
01900 { 01901 int res; 01902 dec1 *tmp_res; 01903 tmp_res= remove_leading_zeroes(from, &res); 01904 return res; 01905 }
Here is the caller graph for this function:

| int decimal_is_zero | ( | decimal_t * | from | ) |
Definition at line 1928 of file decimal.c.
Referenced by field_decimal::add(), my_decimal_is_zero(), and my_decimal_neg().
01929 { 01930 dec1 *buf1=from->buf, 01931 *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac); 01932 while (buf1 < end) 01933 if (*buf1++) 01934 return 0; 01935 return 1; 01936 }
Here is the caller graph for this function:

Definition at line 2368 of file decimal.c.
Referenced by my_decimal_mod().
02369 { 02370 return do_div_mod(from1, from2, 0, to, 0); 02371 }
Here is the caller graph for this function:

Definition at line 1959 of file decimal.c.
Referenced by my_decimal_mul().
01960 { 01961 int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg), 01962 frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac), 01963 intg0=ROUND_UP(from1->intg+from2->intg), 01964 frac0=frac1+frac2, error, i, j, d_to_move; 01965 dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0, 01966 *start2, *stop2, *stop1, *start0, carry; 01967 01968 sanity(to); 01969 01970 i=intg0; 01971 j=frac0; 01972 FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error); 01973 to->sign=from1->sign != from2->sign; 01974 to->frac=from1->frac+from2->frac; 01975 to->intg=intg0*DIG_PER_DEC1; 01976 01977 if (unlikely(error)) 01978 { 01979 set_if_smaller(to->frac, frac0*DIG_PER_DEC1); 01980 set_if_smaller(to->intg, intg0*DIG_PER_DEC1); 01981 if (unlikely(i > intg0)) 01982 { 01983 i-=intg0; 01984 j=i >> 1; 01985 intg1-= j; 01986 intg2-=i-j; 01987 frac1=frac2=0; /* frac0 is already 0 here */ 01988 } 01989 else 01990 { 01991 j-=frac0; 01992 i=j >> 1; 01993 frac1-= i; 01994 frac2-=j-i; 01995 } 01996 } 01997 start0=to->buf+intg0+frac0-1; 01998 start2=buf2+frac2-1; 01999 stop1=buf1-intg1; 02000 stop2=buf2-intg2; 02001 02002 bzero(to->buf, (intg0+frac0)*sizeof(dec1)); 02003 02004 for (buf1+=frac1-1; buf1 >= stop1; buf1--, start0--) 02005 { 02006 carry=0; 02007 for (buf0=start0, buf2=start2; buf2 >= stop2; buf2--, buf0--) 02008 { 02009 dec1 hi, lo; 02010 dec2 p= ((dec2)*buf1) * ((dec2)*buf2); 02011 hi=(dec1)(p/DIG_BASE); 02012 lo=(dec1)(p-((dec2)hi)*DIG_BASE); 02013 ADD2(*buf0, *buf0, lo, carry); 02014 carry+=hi; 02015 } 02016 if (carry) 02017 { 02018 if (buf0 < to->buf) 02019 return E_DEC_OVERFLOW; 02020 ADD2(*buf0, *buf0, 0, carry); 02021 } 02022 for (buf0--; carry; buf0--) 02023 { 02024 if (buf0 < to->buf) 02025 return E_DEC_OVERFLOW; 02026 ADD(*buf0, *buf0, 0, carry); 02027 } 02028 } 02029 02030 /* Now we have to check for -0.000 case */ 02031 if (to->sign) 02032 { 02033 dec1 *buf= to->buf; 02034 dec1 *end= to->buf + intg0 + frac0; 02035 DBUG_ASSERT(buf != end); 02036 for (;;) 02037 { 02038 if (*buf) 02039 break; 02040 if (++buf == end) 02041 { 02042 /* We got decimal zero */ 02043 decimal_make_zero(to); 02044 break; 02045 } 02046 } 02047 } 02048 buf1= to->buf; 02049 d_to_move= intg0 + ROUND_UP(to->frac); 02050 while (!*buf1 && (to->intg > DIG_PER_DEC1)) 02051 { 02052 buf1++; 02053 to->intg-= DIG_PER_DEC1; 02054 d_to_move--; 02055 } 02056 if (to->buf < buf1) 02057 { 02058 dec1 *cur_d= to->buf; 02059 for (; d_to_move--; cur_d++, buf1++) 02060 *cur_d= *buf1; 02061 } 02062 return error; 02063 }
Here is the caller graph for this function:

Definition at line 1663 of file decimal.c.
01664 { 01665 switch (op) { 01666 case '-': 01667 return ROUND_UP(max(from1->intg, from2->intg)) + 01668 ROUND_UP(max(from1->frac, from2->frac)); 01669 case '+': 01670 return ROUND_UP(max(from1->intg, from2->intg)+1) + 01671 ROUND_UP(max(from1->frac, from2->frac)); 01672 case '*': 01673 return ROUND_UP(from1->intg+from2->intg)+ 01674 ROUND_UP(from1->frac)+ROUND_UP(from2->frac); 01675 case '/': 01676 return ROUND_UP(from1->intg+from2->intg+1+from1->frac+from2->frac+param); 01677 default: DBUG_ASSERT(0); 01678 } 01679 return -1; /* shut up the warning */ 01680 }
| int decimal_round | ( | decimal_t * | from, | |
| decimal_t * | to, | |||
| int | scale, | |||
| decimal_round_mode | mode | |||
| ) |
Definition at line 1461 of file decimal.c.
Referenced by decimal_shift(), my_decimal2binary(), my_decimal2int(), my_decimal_ceiling(), my_decimal_floor(), and my_decimal_round().
01463 { 01464 int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1, 01465 frac1=ROUND_UP(from->frac), round_digit, 01466 intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len, 01467 intg1=ROUND_UP(from->intg + 01468 (((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX))); 01469 dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0; 01470 int first_dig; 01471 01472 sanity(to); 01473 01474 switch (mode) { 01475 case HALF_UP: 01476 case HALF_EVEN: round_digit=5; break; 01477 case CEILING: round_digit= from->sign ? 10 : 0; break; 01478 case FLOOR: round_digit= from->sign ? 0 : 10; break; 01479 case TRUNCATE: round_digit=10; break; 01480 default: DBUG_ASSERT(0); 01481 } 01482 01483 if (unlikely(frac0+intg0 > len)) 01484 { 01485 frac0=len-intg0; 01486 scale=frac0*DIG_PER_DEC1; 01487 error=E_DEC_TRUNCATED; 01488 } 01489 01490 if (scale+from->intg < 0) 01491 { 01492 decimal_make_zero(to); 01493 return E_DEC_OK; 01494 } 01495 01496 if (to != from || intg1>intg0) 01497 { 01498 dec1 *p0= buf0+intg0+max(frac1, frac0); 01499 dec1 *p1= buf1+intg1+max(frac1, frac0); 01500 01501 to->buf[0]= 0; 01502 while (buf0 < p0) 01503 *(--p1) = *(--p0); 01504 01505 intg0= intg1; 01506 buf0=to->buf; 01507 buf1=to->buf; 01508 to->sign=from->sign; 01509 to->intg=min(intg0, len)*DIG_PER_DEC1; 01510 } 01511 01512 if (frac0 > frac1) 01513 { 01514 buf1+=intg0+frac1; 01515 while (frac0-- > frac1) 01516 *buf1++=0; 01517 goto done; 01518 } 01519 01520 if (scale >= from->frac) 01521 goto done; /* nothing to do */ 01522 01523 buf0+=intg0+frac0-1; 01524 buf1+=intg0+frac0-1; 01525 if (scale == frac0*DIG_PER_DEC1) 01526 { 01527 int do_inc= FALSE; 01528 DBUG_ASSERT(frac0+intg0 >= 0); 01529 switch (round_digit) { 01530 case 0: 01531 { 01532 dec1 *p0= buf0 + (frac1-frac0); 01533 for (; p0 > buf0; p0--) 01534 { 01535 if (*p0) 01536 { 01537 do_inc= TRUE; 01538 break; 01539 } 01540 } 01541 break; 01542 } 01543 case 5: 01544 { 01545 x= buf0[1]/DIG_MASK; 01546 do_inc= (x>5) || ((x == 5) && 01547 (mode == HALF_UP || (frac0+intg0 > 0 && *buf0 & 1))); 01548 break; 01549 } 01550 default: 01551 break; 01552 } 01553 if (do_inc) 01554 { 01555 if (frac0+intg0>0) 01556 (*buf1)++; 01557 else 01558 *(++buf1)=DIG_BASE; 01559 } 01560 else if (frac0+intg0==0) 01561 { 01562 decimal_make_zero(to); 01563 return E_DEC_OK; 01564 } 01565 } 01566 else 01567 { 01568 /* TODO - fix this code as it won't work for CEILING mode */ 01569 int pos=frac0*DIG_PER_DEC1-scale-1; 01570 DBUG_ASSERT(frac0+intg0 > 0); 01571 x=*buf1 / powers10[pos]; 01572 y=x % 10; 01573 if (y > round_digit || 01574 (round_digit == 5 && y == 5 && (mode == HALF_UP || (x/10) & 1))) 01575 x+=10; 01576 *buf1=powers10[pos]*(x-y); 01577 } 01578 if (frac0 < 0) 01579 { 01580 dec1 *end=to->buf+intg0, *buf=buf1+1; 01581 while (buf < end) 01582 *buf++=0; 01583 } 01584 if (*buf1 >= DIG_BASE) 01585 { 01586 carry=1; 01587 *buf1-=DIG_BASE; 01588 while (carry && --buf1 >= to->buf) 01589 ADD(*buf1, *buf1, 0, carry); 01590 if (unlikely(carry)) 01591 { 01592 /* shifting the number to create space for new digit */ 01593 if (frac0+intg0 >= len) 01594 { 01595 frac0--; 01596 scale=frac0*DIG_PER_DEC1; 01597 error=E_DEC_TRUNCATED; /* XXX */ 01598 } 01599 for (buf1=to->buf+intg0+max(frac0,0); buf1 > to->buf; buf1--) 01600 { 01601 buf1[0]=buf1[-1]; 01602 } 01603 *buf1=1; 01604 to->intg++; 01605 } 01606 } 01607 else 01608 { 01609 for (;;) 01610 { 01611 if (likely(*buf1)) 01612 break; 01613 if (buf1-- == to->buf) 01614 { 01615 /* making 'zero' with the proper scale */ 01616 dec1 *p0= to->buf + frac0 + 1; 01617 to->intg=1; 01618 to->frac= max(scale, 0); 01619 to->sign= 0; 01620 for (buf1= to->buf; buf1<p0; buf1++) 01621 *buf1= 0; 01622 return E_DEC_OK; 01623 } 01624 } 01625 } 01626 01627 /* Here we check 999.9 -> 1000 case when we need to increase intg */ 01628 first_dig= to->intg % DIG_PER_DEC1; 01629 if (first_dig && (*buf1 >= powers10[first_dig])) 01630 to->intg++; 01631 01632 if (scale<0) 01633 scale=0; 01634 01635 done: 01636 to->frac=scale; 01637 return error; 01638 }
Here is the caller graph for this function:

| int decimal_shift | ( | decimal_t * | dec, | |
| int | shift | |||
| ) |
Definition at line 580 of file decimal.c.
References buf, st_decimal_t::buf, DBUG_ASSERT, decimal_make_zero, decimal_round(), DIG_PER_DEC1, digits_bounds(), do_mini_left_shift(), do_mini_right_shift(), E_DEC_OK, E_DEC_OVERFLOW, E_DEC_TRUNCATED, err, st_decimal_t::frac, HALF_UP, st_decimal_t::intg, st_decimal_t::len, ROUND_UP, set_if_bigger, and to.
Referenced by internal_str2dec().
00581 { 00582 /* index of first non zero digit (all indexes from 0) */ 00583 int beg; 00584 /* index of position after last decimal digit */ 00585 int end; 00586 /* index of digit position just after point */ 00587 int point= ROUND_UP(dec->intg) * DIG_PER_DEC1; 00588 /* new point position */ 00589 int new_point= point + shift; 00590 /* number of digits in result */ 00591 int digits_int, digits_frac; 00592 /* length of result and new fraction in big digits*/ 00593 int new_len, new_frac_len; 00594 /* return code */ 00595 int err= E_DEC_OK; 00596 int new_front; 00597 00598 if (shift == 0) 00599 return E_DEC_OK; 00600 00601 digits_bounds(dec, &beg, &end); 00602 00603 if (beg == end) 00604 { 00605 decimal_make_zero(dec); 00606 return E_DEC_OK; 00607 } 00608 00609 digits_int= new_point - beg; 00610 set_if_bigger(digits_int, 0); 00611 digits_frac= end - new_point; 00612 set_if_bigger(digits_frac, 0); 00613 00614 if ((new_len= ROUND_UP(digits_int) + (new_frac_len= ROUND_UP(digits_frac))) > 00615 dec->len) 00616 { 00617 int lack= new_len - dec->len; 00618 int diff; 00619 00620 if (new_frac_len < lack) 00621 return E_DEC_OVERFLOW; /* lack more then we have in fraction */ 00622 00623 /* cat off fraction part to allow new number to fit in our buffer */ 00624 err= E_DEC_TRUNCATED; 00625 new_frac_len-= lack; 00626 diff= digits_frac - (new_frac_len * DIG_PER_DEC1); 00627 /* Make rounding method as parameter? */ 00628 decimal_round(dec, dec, end - point - diff, HALF_UP); 00629 end-= diff; 00630 digits_frac= new_frac_len * DIG_PER_DEC1; 00631 00632 if (end <= beg) 00633 { 00634 /* 00635 we lost all digits (they will be shifted out of buffer), so we can 00636 just return 0 00637 */ 00638 decimal_make_zero(dec); 00639 return E_DEC_TRUNCATED; 00640 } 00641 } 00642 00643 if (shift % DIG_PER_DEC1) 00644 { 00645 int l_mini_shift, r_mini_shift, mini_shift; 00646 int do_left; 00647 /* 00648 Calculate left/right shift to align decimal digits inside our bug 00649 digits correctly 00650 */ 00651 if (shift > 0) 00652 { 00653 l_mini_shift= shift % DIG_PER_DEC1; 00654 r_mini_shift= DIG_PER_DEC1 - l_mini_shift; 00655 /* 00656 It is left shift so prefer left shift, but if we have not place from 00657 left, we have to have it from right, because we checked length of 00658 result 00659 */ 00660 do_left= l_mini_shift <= beg; 00661 DBUG_ASSERT(do_left || (dec->len * DIG_PER_DEC1 - end) >= r_mini_shift); 00662 } 00663 else 00664 { 00665 r_mini_shift= (-shift) % DIG_PER_DEC1; 00666 l_mini_shift= DIG_PER_DEC1 - r_mini_shift; 00667 /* see comment above */ 00668 do_left= !((dec->len * DIG_PER_DEC1 - end) >= r_mini_shift); 00669 DBUG_ASSERT(!do_left || l_mini_shift <= beg); 00670 } 00671 if (do_left) 00672 { 00673 do_mini_left_shift(dec, l_mini_shift, beg, end); 00674 mini_shift=- l_mini_shift; 00675 } 00676 else 00677 { 00678 do_mini_right_shift(dec, r_mini_shift, beg, end); 00679 mini_shift= r_mini_shift; 00680 } 00681 new_point+= mini_shift; 00682 /* 00683 If number is shifted and correctly aligned in buffer we can 00684 finish 00685 */ 00686 if (!(shift+= mini_shift) && (new_point - digits_int) < DIG_PER_DEC1) 00687 { 00688 dec->intg= digits_int; 00689 dec->frac= digits_frac; 00690 return err; /* already shifted as it should be */ 00691 } 00692 beg+= mini_shift; 00693 end+= mini_shift; 00694 } 00695 00696 /* if new 'decimal front' is in first digit, we do not need move digits */ 00697 if ((new_front= (new_point - digits_int)) >= DIG_PER_DEC1 || 00698 new_front < 0) 00699 { 00700 /* need to move digits */ 00701 int d_shift; 00702 dec1 *to, *barier; 00703 if (new_front > 0) 00704 { 00705 /* move left */ 00706 d_shift= new_front / DIG_PER_DEC1; 00707 to= dec->buf + (ROUND_UP(beg + 1) - 1 - d_shift); 00708 barier= dec->buf + (ROUND_UP(end) - 1 - d_shift); 00709 DBUG_ASSERT(to >= dec->buf); 00710 DBUG_ASSERT(barier + d_shift < dec->buf + dec->len); 00711 for(; to <= barier; to++) 00712 *to= *(to + d_shift); 00713 for(barier+= d_shift; to <= barier; to++) 00714 *to= 0; 00715 d_shift= -d_shift; 00716 } 00717 else 00718 { 00719 /* move right */ 00720 d_shift= (1 - new_front) / DIG_PER_DEC1; 00721 to= dec->buf + ROUND_UP(end) - 1 + d_shift; 00722 barier= dec->buf + ROUND_UP(beg + 1) - 1 + d_shift; 00723 DBUG_ASSERT(to < dec->buf + dec->len); 00724 DBUG_ASSERT(barier - d_shift >= dec->buf); 00725 for(; to >= barier; to--) 00726 *to= *(to - d_shift); 00727 for(barier-= d_shift; to >= barier; to--) 00728 *to= 0; 00729 } 00730 d_shift*= DIG_PER_DEC1; 00731 beg+= d_shift; 00732 end+= d_shift; 00733 new_point+= d_shift; 00734 } 00735 00736 /* 00737 If there are gaps then fill ren with 0. 00738 00739 Only one of following 'for' loops will work becouse beg <= end 00740 */ 00741 beg= ROUND_UP(beg + 1) - 1; 00742 end= ROUND_UP(end) - 1; 00743 DBUG_ASSERT(new_point >= 0); 00744 00745 /* We don't want negative new_point below */ 00746 if (new_point != 0) 00747 new_point= ROUND_UP(new_point) - 1; 00748 00749 if (new_point > end) 00750 { 00751 do 00752 { 00753 dec->buf[new_point]=0; 00754 } while (--new_point > end); 00755 } 00756 else 00757 { 00758 for (; new_point < beg; new_point++) 00759 dec->buf[new_point]= 0; 00760 } 00761 dec->intg= digits_int; 00762 dec->frac= digits_frac; 00763 return err; 00764 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int decimal_size | ( | int | precision, | |
| int | scale | |||
| ) |
Definition at line 1418 of file decimal.c.
Referenced by my_decimal_size().
01419 { 01420 DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision); 01421 return ROUND_UP(precision-scale)+ROUND_UP(scale); 01422 }
Here is the caller graph for this function:

| static void digits_bounds | ( | decimal_t * | from, | |
| int * | start_result, | |||
| int * | end_result | |||
| ) | [static] |
Definition at line 450 of file decimal.c.
References DIG_PER_DEC1, from, int(), powers10, ROUND_UP, start(), and stop().
Referenced by decimal_shift().
00451 { 00452 int start, stop, i; 00453 dec1 *buf_beg= from->buf; 00454 dec1 *end= from->buf + ROUND_UP(from->intg) + ROUND_UP(from->frac); 00455 dec1 *buf_end= end - 1; 00456 00457 /* find non-zero digit from number begining */ 00458 while (buf_beg < end && *buf_beg == 0) 00459 buf_beg++; 00460 00461 if (buf_beg >= end) 00462 { 00463 /* it is zero */ 00464 *start_result= *end_result= 0; 00465 return; 00466 } 00467 00468 /* find non-zero decimal digit from number begining */ 00469 if (buf_beg == from->buf && from->intg) 00470 { 00471 start= DIG_PER_DEC1 - (i= ((from->intg-1) % DIG_PER_DEC1 + 1)); 00472 i--; 00473 } 00474 else 00475 { 00476 i= DIG_PER_DEC1 - 1; 00477 start= (int) ((buf_beg - from->buf) * DIG_PER_DEC1); 00478 } 00479 if (buf_beg < end) 00480 for (; *buf_beg < powers10[i--]; start++) ; 00481 *start_result= start; /* index of first decimal digit (from 0) */ 00482 00483 /* find non-zero digit at the end */ 00484 while (buf_end > buf_beg && *buf_end == 0) 00485 buf_end--; 00486 /* find non-zero decimal digit from the end */ 00487 if (buf_end == end - 1 && from->frac) 00488 { 00489 stop= (int) (((buf_end - from->buf) * DIG_PER_DEC1 + 00490 (i= ((from->frac - 1) % DIG_PER_DEC1 + 1)))); 00491 i= DIG_PER_DEC1 - i + 1; 00492 } 00493 else 00494 { 00495 stop= (int) ((buf_end - from->buf + 1) * DIG_PER_DEC1); 00496 i= 1; 00497 } 00498 for (; *buf_end % powers10[i++] == 0; stop--); 00499 *end_result= stop; /* index of position after last decimal digit (from 0) */ 00500 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1682 of file decimal.c.
References ADD, st_decimal_t::buf, DBUG_ASSERT, DIG_MAX, DIG_PER_DEC1, E_DEC_OVERFLOW, error, FIX_INTG_FRAC_ERROR, st_decimal_t::frac, st_decimal_t::intg, max, max_decimal(), ROUND_UP, sanity, set_if_smaller, st_decimal_t::sign, stop(), to, unlikely, and x.
Referenced by decimal_add(), and decimal_sub().
01683 { 01684 int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg), 01685 frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac), 01686 frac0=max(frac1, frac2), intg0=max(intg1, intg2), error; 01687 dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry; 01688 01689 sanity(to); 01690 01691 /* is there a need for extra word because of carry ? */ 01692 x=intg1 > intg2 ? from1->buf[0] : 01693 intg2 > intg1 ? from2->buf[0] : 01694 from1->buf[0] + from2->buf[0] ; 01695 if (unlikely(x > DIG_MAX-1)) /* yes, there is */ 01696 { 01697 intg0++; 01698 to->buf[0]=0; /* safety */ 01699 } 01700 01701 FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error); 01702 if (unlikely(error == E_DEC_OVERFLOW)) 01703 { 01704 max_decimal(to->len * DIG_PER_DEC1, 0, to); 01705 return error; 01706 } 01707 01708 buf0=to->buf+intg0+frac0; 01709 01710 to->sign=from1->sign; 01711 to->frac=max(from1->frac, from2->frac); 01712 to->intg=intg0*DIG_PER_DEC1; 01713 if (unlikely(error)) 01714 { 01715 set_if_smaller(to->frac, frac0*DIG_PER_DEC1); 01716 set_if_smaller(frac1, frac0); 01717 set_if_smaller(frac2, frac0); 01718 set_if_smaller(intg1, intg0); 01719 set_if_smaller(intg2, intg0); 01720 } 01721 01722 /* part 1 - max(frac) ... min (frac) */ 01723 if (frac1 > frac2) 01724 { 01725 buf1=from1->buf+intg1+frac1; 01726 stop=from1->buf+intg1+frac2; 01727 buf2=from2->buf+intg2+frac2; 01728 stop2=from1->buf+(intg1 > intg2 ? intg1-intg2 : 0); 01729 } 01730 else 01731 { 01732 buf1=from2->buf+intg2+frac2; 01733 stop=from2->buf+intg2+frac1; 01734 buf2=from1->buf+intg1+frac1; 01735 stop2=from2->buf+(intg2 > intg1 ? intg2-intg1 : 0); 01736 } 01737 while (buf1 > stop) 01738 *--buf0=*--buf1; 01739 01740 /* part 2 - min(frac) ... min(intg) */ 01741 carry=0; 01742 while (buf1 > stop2) 01743 { 01744 ADD(*--buf0, *--buf1, *--buf2, carry); 01745 } 01746 01747 /* part 3 - min(intg) ... max(intg) */ 01748 buf1= intg1 > intg2 ? ((stop=from1->buf)+intg1-intg2) : 01749 ((stop=from2->buf)+intg2-intg1) ; 01750 while (buf1 > stop) 01751 { 01752 ADD(*--buf0, *--buf1, 0, carry); 01753 } 01754 01755 if (unlikely(carry)) 01756 *--buf0=1; 01757 DBUG_ASSERT(buf0 == to->buf || buf0 == to->buf+1); 01758 01759 return error; 01760 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int do_div_mod | ( | decimal_t * | from1, | |
| decimal_t * | from2, | |||
| decimal_t * | to, | |||
| decimal_t * | mod, | |||
| int | scale_incr | |||
| ) | [static] |
Definition at line 2075 of file decimal.c.
References ADD, st_decimal_t::buf, bzero, DBUG_ASSERT, decimal_make_zero, DIG_BASE, DIG_PER_DEC1, E_DEC_DIV_ZERO, E_DEC_OK, E_DEC_OOM, E_DEC_OVERFLOW, E_DEC_TRUNCATED, error, FIX_INTG_FRAC_ERROR, st_decimal_t::frac, int(), st_decimal_t::intg, likely, LINT_INIT, max, memcpy, min, my_afree, my_alloca, powers10, ROUND_UP, sanity, set_if_bigger, st_decimal_t::sign, SUB2, to, unlikely, and x.
Referenced by decimal_div(), and decimal_mod().
02077 { 02078 int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1, 02079 frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2, 02080 error, i, intg0, frac0, len1, len2, dintg, div=(!mod); 02081 dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1, 02082 *start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry; 02083 dec2 norm_factor, x, guess, y; 02084 02085 LINT_INIT(error); 02086 02087 if (mod) 02088 to=mod; 02089 02090 sanity(to); 02091 02092 /* removing all the leading zeroes */ 02093 i= ((prec2 - 1) % DIG_PER_DEC1) + 1; 02094 while (prec2 > 0 && *buf2 == 0) 02095 { 02096 prec2-= i; 02097 i= DIG_PER_DEC1; 02098 buf2++; 02099 } 02100 if (prec2 <= 0) /* short-circuit everything: from2 == 0 */ 02101 return E_DEC_DIV_ZERO; 02102 for (i= (prec2 - 1) % DIG_PER_DEC1; *buf2 < powers10[i--]; prec2--) ; 02103 DBUG_ASSERT(prec2 > 0); 02104 02105 i=((prec1-1) % DIG_PER_DEC1)+1; 02106 while (prec1 > 0 && *buf1 == 0) 02107 { 02108 prec1-=i; 02109 i=DIG_PER_DEC1; 02110 buf1++; 02111 } 02112 if (prec1 <= 0) 02113 { /* short-circuit everything: from1 == 0 */ 02114 decimal_make_zero(to); 02115 return E_DEC_OK; 02116 } 02117 for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ; 02118 DBUG_ASSERT(prec1 > 0); 02119 02120 /* let's fix scale_incr, taking into account frac1,frac2 increase */ 02121 if ((scale_incr-= frac1 - from1->frac + frac2 - from2->frac) < 0) 02122 scale_incr=0; 02123 02124 dintg=(prec1-frac1)-(prec2-frac2)+(*buf1 >= *buf2); 02125 if (dintg < 0) 02126 { 02127 dintg/=DIG_PER_DEC1; 02128 intg0=0; 02129 } 02130 else 02131 intg0=ROUND_UP(dintg); 02132 if (mod) 02133 { 02134 /* we're calculating N1 % N2. 02135 The result will have 02136 frac=max(frac1, frac2), as for subtraction 02137 intg=intg2 02138 */ 02139 to->sign=from1->sign; 02140 to->frac=max(from1->frac, from2->frac); 02141 frac0=0; 02142 } 02143 else 02144 { 02145 /* 02146 we're calculating N1/N2. N1 is in the buf1, has prec1 digits 02147 N2 is in the buf2, has prec2 digits. Scales are frac1 and 02148 frac2 accordingly. 02149 Thus, the result will have 02150 frac = ROUND_UP(frac1+frac2+scale_incr) 02151 and 02152 intg = (prec1-frac1) - (prec2-frac2) + 1 02153 prec = intg+frac 02154 */ 02155 frac0=ROUND_UP(frac1+frac2+scale_incr); 02156 FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error); 02157 to->sign=from1->sign != from2->sign; 02158 to->intg=intg0*DIG_PER_DEC1; 02159 to->frac=frac0*DIG_PER_DEC1; 02160 } 02161 buf0=to->buf; 02162 stop0=buf0+intg0+frac0; 02163 if (likely(div)) 02164 while (dintg++ < 0) 02165 *buf0++=0; 02166 02167 len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1) + 1; 02168 set_if_bigger(len1, 3); 02169 if (!(tmp1=(dec1 *)my_alloca(len1*sizeof(dec1)))) 02170 return E_DEC_OOM; 02171 memcpy(tmp1, buf1, i*sizeof(dec1)); 02172 bzero(tmp1+i, (len1-i)*sizeof(dec1)); 02173 02174 start1=tmp1; 02175 stop1=start1+len1; 02176 start2=buf2; 02177 stop2=buf2+ROUND_UP(prec2)-1; 02178 02179 /* removing end zeroes */ 02180 while (*stop2 == 0 && stop2 >= start2) 02181 stop2--; 02182 len2= (int) (stop2++ - start2); 02183 02184 /* 02185 calculating norm2 (normalized *start2) - we need *start2 to be large 02186 (at least > DIG_BASE/2), but unlike Knuth's Alg. D we don't want to 02187 normalize input numbers (as we don't make a copy of the divisor). 02188 Thus we normalize first dec1 of buf2 only, and we'll normalize *start1 02189 on the fly for the purpose of guesstimation only. 02190 It's also faster, as we're saving on normalization of buf2 02191 */ 02192 norm_factor=DIG_BASE/(*start2+1); 02193 norm2=(dec1)(norm_factor*start2[0]); 02194 if (likely(len2>0)) 02195 norm2+=(dec1)(norm_factor*start2[1]/DIG_BASE); 02196 02197 if (*start1 < *start2) 02198 dcarry=*start1++; 02199 else 02200 dcarry=0; 02201 02202 /* main loop */ 02203 for (; buf0 < stop0; buf0++) 02204 { 02205 /* short-circuit, if possible */ 02206 if (unlikely(dcarry == 0 && *start1 < *start2)) 02207 guess=0; 02208 else 02209 { 02210 /* D3: make a guess */ 02211 x=start1[0]+((dec2)dcarry)*DIG_BASE; 02212 y=start1[1]; 02213 guess=(norm_factor*x+norm_factor*y/DIG_BASE)/norm2; 02214 if (unlikely(guess >= DIG_BASE)) 02215 guess=DIG_BASE-1; 02216 if (likely(len2>0)) 02217 { 02218 /* hmm, this is a suspicious trick - I removed normalization here */ 02219 if (start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y) 02220 guess--; 02221 if (unlikely(start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y)) 02222 guess--; 02223 DBUG_ASSERT(start2[1]*guess <= (x-guess*start2[0])*DIG_BASE+y); 02224 } 02225 02226 /* D4: multiply and subtract */ 02227 buf2=stop2; 02228 buf1=start1+len2; 02229 DBUG_ASSERT(buf1 < stop1); 02230 for (carry=0; buf2 > start2; buf1--) 02231 { 02232 dec1 hi, lo; 02233 x=guess * (*--buf2); 02234 hi=(dec1)(x/DIG_BASE); 02235 lo=(dec1)(x-((dec2)hi)*DIG_BASE); 02236 SUB2(*buf1, *buf1, lo, carry); 02237 carry+=hi; 02238 } 02239 carry= dcarry < carry; 02240 02241 /* D5: check the remainder */ 02242 if (unlikely(carry)) 02243 { 02244 /* D6: correct the guess */ 02245 guess--; 02246 buf2=stop2; 02247 buf1=start1+len2; 02248 for (carry=0; buf2 > start2; buf1--) 02249 { 02250 ADD(*buf1, *buf1, *--buf2, carry); 02251 } 02252 } 02253 } 02254 if (likely(div)) 02255 *buf0=(dec1)guess; 02256 dcarry= *start1; 02257 start1++; 02258 } 02259 if (mod) 02260 { 02261 /* 02262 now the result is in tmp1, it has 02263 intg=prec1-frac1 02264 frac=max(frac1, frac2)=to->frac 02265 */ 02266 if (dcarry) 02267 *--start1=dcarry; 02268 buf0=to->buf; 02269 intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1)); 02270 frac0=ROUND_UP(to->frac); 02271 error=E_DEC_OK; 02272 if (unlikely(frac0==0 && intg0==0)) 02273 { 02274 decimal_make_zero(to); 02275 goto done; 02276 } 02277 if (intg0<=0) 02278 { 02279 if (unlikely(-intg0 >= to->len)) 02280 { 02281 decimal_make_zero(to); 02282 error=E_DEC_TRUNCATED; 02283 goto done; 02284 } 02285 stop1=start1+frac0; 02286 frac0+=intg0; 02287 to->intg=0; 02288 while (intg0++ < 0) 02289 *buf0++=0; 02290 } 02291 else 02292 { 02293 if (unlikely(intg0 > to->len)) 02294 { 02295 frac0=0; 02296 intg0=to->len; 02297 error=E_DEC_OVERFLOW; 02298 goto done; 02299 } 02300 DBUG_ASSERT(intg0 <= ROUND_UP(from2->intg)); 02301 stop1=start1+frac0+intg0; 02302 to->intg=min(intg0*DIG_PER_DEC1, from2->intg); 02303 } 02304 if (unlikely(intg0+frac0 > to->len)) 02305 { 02306 stop1-=to->len-frac0-intg0; 02307 frac0=to->len-intg0; 02308 to->frac=frac0*DIG_PER_DEC1; 02309 error=E_DEC_TRUNCATED; 02310 } 02311 while (start1 < stop1) 02312 *buf0++=*start1++; 02313 } 02314 done: 02315 my_afree(tmp1); 02316 return error; 02317 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void do_mini_left_shift | ( | decimal_t * | dec, | |
| int | shift, | |||
| int | beg, | |||
| int | last | |||
| ) |
Definition at line 517 of file decimal.c.
References buf, st_decimal_t::buf, DBUG_ASSERT, DIG_PER_DEC1, from, st_decimal_t::len, powers10, and ROUND_UP.
Referenced by decimal_shift().
00518 { 00519 dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1; 00520 dec1 *end= dec->buf + ROUND_UP(last) - 1; 00521 int c_shift= DIG_PER_DEC1 - shift; 00522 DBUG_ASSERT(from >= dec->buf); 00523 DBUG_ASSERT(end < dec->buf + dec->len); 00524 if (beg % DIG_PER_DEC1 < shift) 00525 *(from - 1)= (*from) / powers10[c_shift]; 00526 for(; from < end; from++) 00527 *from= ((*from % powers10[c_shift]) * powers10[shift] + 00528 (*(from + 1)) / powers10[c_shift]); 00529 *from= (*from % powers10[c_shift]) * powers10[shift]; 00530 }
Here is the caller graph for this function:

| void do_mini_right_shift | ( | decimal_t * | dec, | |
| int | shift, | |||
| int | beg, | |||
| int | last | |||
| ) |
Definition at line 547 of file decimal.c.
References buf, st_decimal_t::buf, DBUG_ASSERT, DIG_PER_DEC1, from, st_decimal_t::len, powers10, and ROUND_UP.
Referenced by decimal_shift().
00548 { 00549 dec1 *from= dec->buf + ROUND_UP(last) - 1; 00550 dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1; 00551 int c_shift= DIG_PER_DEC1 - shift; 00552 DBUG_ASSERT(from < dec->buf + dec->len); 00553 DBUG_ASSERT(end >= dec->buf); 00554 if (DIG_PER_DEC1 - ((last - 1) % DIG_PER_DEC1 + 1) < shift) 00555 *(from + 1)= (*from % powers10[shift]) * powers10[c_shift]; 00556 for(; from > end; from--) 00557 *from= (*from / powers10[shift] + 00558 (*(from - 1) % powers10[shift]) * powers10[c_shift]); 00559 *from= *from / powers10[shift]; 00560 }
Here is the caller graph for this function:

Definition at line 1764 of file decimal.c.
References st_decimal_t::buf, decimal_make_zero, DIG_PER_DEC1, E_DEC_OK, error, FIX_INTG_FRAC_ERROR, st_decimal_t::frac, int(), st_decimal_t::intg, max, ROUND_UP, sanity, set_if_smaller, st_decimal_t::sign, SUB, swap_variables, to, and unlikely.
Referenced by decimal_add(), decimal_cmp(), and decimal_sub().
01765 { 01766 int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg), 01767 frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac); 01768 int frac0=max(frac1, frac2), error; 01769 dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0; 01770 01771 /* let carry:=1 if from2 > from1 */ 01772 start1=buf1=from1->buf; stop1=buf1+intg1; 01773 start2=buf2=from2->buf; stop2=buf2+intg2; 01774 if (unlikely(*buf1 == 0)) 01775 { 01776 while (buf1 < stop1 && *buf1 == 0) 01777 buf1++; 01778 start1=buf1; 01779 intg1= (int) (stop1-buf1); 01780 } 01781 if (unlikely(*buf2 == 0)) 01782 { 01783 while (buf2 < stop2 && *buf2 == 0) 01784 buf2++; 01785 start2=buf2; 01786 intg2= (int) (stop2-buf2); 01787 } 01788 if (intg2 > intg1) 01789 carry=1; 01790 else if (intg2 == intg1) 01791 { 01792 dec1 *end1= stop1 + (frac1 - 1); 01793 dec1 *end2= stop2 + (frac2 - 1); 01794 while (unlikely((buf1 <= end1) && (*end1 == 0))) 01795 end1--; 01796 while (unlikely((buf2 <= end2) && (*end2 == 0))) 01797 end2--; 01798 frac1= (int) (end1 - stop1) + 1; 01799 frac2= (int) (end2 - stop2) + 1; 01800 while (buf1 <=end1 && buf2 <= end2 && *buf1 == *buf2) 01801 buf1++, buf2++; 01802 if (buf1 <= end1) 01803 { 01804 if (buf2 <= end2) 01805 carry= *buf2 > *buf1; 01806 else 01807 carry= 0; 01808 } 01809 else 01810 { 01811 if (buf2 <= end2) 01812 carry=1; 01813 else /* short-circuit everything: from1 == from2 */ 01814 { 01815 if (to == 0) /* decimal_cmp() */ 01816 return 0; 01817 decimal_make_zero(to); 01818 return E_DEC_OK; 01819 } 01820 } 01821 } 01822 01823 if (to == 0) /* decimal_cmp() */ 01824 return carry == from1->sign ? 1 : -1; 01825 01826 sanity(to); 01827 01828 to->sign=from1->sign; 01829 01830 /* ensure that always from1 > from2 (and intg1 >= intg2) */ 01831 if (carry) 01832 { 01833 swap_variables(decimal_t *,from1,from1); 01834 swap_variables(dec1 *,start1, start2); 01835 swap_variables(int,intg1,intg2); 01836 swap_variables(int,frac1,frac2); 01837 to->sign= 1 - to->sign; 01838 } 01839 01840 FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error); 01841 buf0=to->buf+intg1+frac0; 01842 01843 to->frac=max(from1->frac, from2->frac); 01844 to->intg=intg1*DIG_PER_DEC1; 01845 if (unlikely(error)) 01846 { 01847 set_if_smaller(to->frac, frac0*DIG_PER_DEC1); 01848 set_if_smaller(frac1, frac0); 01849 set_if_smaller(frac2, frac0); 01850 set_if_smaller(intg2, intg1); 01851 } 01852 carry=0; 01853 01854 /* part 1 - max(frac) ... min (frac) */ 01855 if (frac1 > frac2) 01856 { 01857 buf1=start1+intg1+frac1; 01858 stop1=start1+intg1+frac2; 01859 buf2=start2+intg2+frac2; 01860 while (frac0-- > frac1) 01861 *--buf0=0; 01862 while (buf1 > stop1) 01863 *--buf0=*--buf1; 01864 } 01865 else 01866 { 01867 buf1=start1+intg1+frac1; 01868 buf2=start2+intg2+frac2; 01869 stop2=start2+intg2+frac1; 01870 while (frac0-- > frac2) 01871 *--buf0=0; 01872 while (buf2 > stop2) 01873 { 01874 SUB(*--buf0, 0, *--buf2, carry); 01875 } 01876 } 01877 01878 /* part 2 - min(frac) ... intg2 */ 01879 while (buf2 > start2) 01880 { 01881 SUB(*--buf0, *--buf1, *--buf2, carry); 01882 } 01883 01884 /* part 3 - intg2 ... intg1 */ 01885 while (carry && buf1 > start1) 01886 { 01887 SUB(*--buf0, *--buf1, 0, carry); 01888 } 01889 01890 while (buf1 > start1) 01891 *--buf0=*--buf1; 01892 01893 while (buf0 > to->buf) 01894 *--buf0=0; 01895 01896 return error; 01897 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int double2decimal | ( | double | from, | |
| decimal_t * | to | |||
| ) |
Definition at line 973 of file decimal.c.
Referenced by double2my_decimal().
00974 { 00975 /* TODO: fix it, when we'll have dtoa */ 00976 char buff[400], *end; 00977 int length, res; 00978 DBUG_ENTER("double2decimal"); 00979 length= my_sprintf(buff, (buff, "%.16G", from)); 00980 DBUG_PRINT("info",("from: %g from_as_str: %s", from, buff)); 00981 end= buff+length; 00982 res= string2decimal(buff, to, &end); 00983 DBUG_PRINT("exit", ("res: %d", res)); 00984 DBUG_RETURN(res); 00985 }
Here is the caller graph for this function:

Definition at line 790 of file decimal.c.
00791 { 00792 const char *s= from, *s1, *endp, *end_of_string= *end; 00793 int i, intg, frac, error, intg1, frac1; 00794 dec1 x,*buf; 00795 sanity(to); 00796 00797 error= E_DEC_BAD_NUM; /* In case of bad number */ 00798 while (s < end_of_string && my_isspace(&my_charset_latin1, *s)) 00799 s++; 00800 if (s == end_of_string) 00801 goto fatal_error; 00802 00803 if ((to->sign= (*s == '-'))) 00804 s++; 00805 else if (*s == '+') 00806 s++; 00807 00808 s1=s; 00809 while (s < end_of_string && my_isdigit(&my_charset_latin1, *s)) 00810 s++; 00811 intg= (int) (s-s1); 00812 if (s < end_of_string && *s=='.') 00813 { 00814 endp= s+1; 00815 while (endp < end_of_string && my_isdigit(&my_charset_latin1, *endp)) 00816 endp++; 00817 frac= (int) (endp - s - 1); 00818 } 00819 else 00820 { 00821 frac= 0; 00822 endp= s; 00823 } 00824 00825 *end= (char*) endp; 00826 00827 if (frac+intg == 0) 00828 goto fatal_error; 00829 00830 error= 0; 00831 if (fixed) 00832 { 00833 if (frac > to->frac) 00834 { 00835 error=E_DEC_TRUNCATED; 00836 frac=to->frac; 00837 } 00838 if (intg > to->intg) 00839 { 00840 error=E_DEC_OVERFLOW; 00841 intg=to->intg; 00842 } 00843 intg1=ROUND_UP(intg); 00844 frac1=ROUND_UP(frac); 00845 if (intg1+frac1 > to->len) 00846 { 00847 error= E_DEC_OOM; 00848 goto fatal_error; 00849 } 00850 } 00851 else 00852 { 00853 intg1=ROUND_UP(intg); 00854 frac1=ROUND_UP(frac); 00855 FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error); 00856 if (unlikely(error)) 00857 { 00858 frac=frac1*DIG_PER_DEC1; 00859 if (error == E_DEC_OVERFLOW) 00860 intg=intg1*DIG_PER_DEC1; 00861 } 00862 } 00863 /* Error is guranteed to be set here */ 00864 to->intg=intg; 00865 to->frac=frac; 00866 00867 buf=to->buf+intg1; 00868 s1=s; 00869 00870 for (x=0, i=0; intg; intg--) 00871 { 00872 x+= (*--s - '0')*powers10[i]; 00873 00874 if (unlikely(++i == DIG_PER_DEC1)) 00875 { 00876 *--buf=x; 00877 x=0; 00878 i=0; 00879 } 00880 } 00881 if (i) 00882 *--buf=x; 00883 00884 buf=to->buf+intg1; 00885 for (x=0, i=0; frac; frac--) 00886 { 00887 x= (*++s1 - '0') + x*10; 00888 00889 if (unlikely(++i == DIG_PER_DEC1)) 00890 { 00891 *buf++=x; 00892 x=0; 00893 i=0; 00894 } 00895 } 00896 if (i) 00897 *buf=x*powers10[DIG_PER_DEC1-i]; 00898 00899 /* Handle exponent */ 00900 if (endp+1 < end_of_string && (*endp == 'e' || *endp == 'E')) 00901 { 00902 int str_error; 00903 longlong exp= my_strtoll10(endp+1, (char**) &end_of_string, &str_error); 00904 00905 if (end_of_string != endp +1) /* If at least one digit */ 00906 { 00907 *end= (char*) end_of_string; 00908 if (str_error > 0) 00909 { 00910 error= E_DEC_BAD_NUM; 00911 goto fatal_error; 00912 } 00913 if (exp > INT_MAX/2 || (str_error == 0 && exp < 0)) 00914 { 00915 error= E_DEC_OVERFLOW; 00916 goto fatal_error; 00917 } 00918 if (exp < INT_MIN/2 && error != E_DEC_OVERFLOW) 00919 { 00920 error= E_DEC_TRUNCATED; 00921 goto fatal_error; 00922 } 00923 if (error != E_DEC_OVERFLOW) 00924 error= decimal_shift(to, (int) exp); 00925 } 00926 } 00927 return error; 00928 00929 fatal_error: 00930 decimal_make_zero(to); 00931 return error; 00932 }
| void max_decimal | ( | int | precision, | |
| int | frac, | |||
| decimal_t * | to | |||
| ) |
Definition at line 227 of file decimal.c.
Referenced by do_add(), and max_my_decimal().
00228 { 00229 int intpart; 00230 dec1 *buf= to->buf; 00231 DBUG_ASSERT(precision && precision >= frac); 00232 00233 to->sign= 0; 00234 if ((intpart= to->intg= (precision - frac))) 00235 { 00236 int firstdigits= intpart % DIG_PER_DEC1; 00237 if (firstdigits) 00238 *buf++= powers10[firstdigits] - 1; /* get 9 99 999 ... */ 00239 for(intpart/= DIG_PER_DEC1; intpart; intpart--) 00240 *buf++= DIG_MAX; 00241 } 00242 00243 if ((to->frac= frac)) 00244 { 00245 int lastdigits= frac % DIG_PER_DEC1; 00246 for(frac/= DIG_PER_DEC1; frac; frac--) 00247 *buf++= DIG_MAX; 00248 if (lastdigits) 00249 *buf= frac_max[lastdigits - 1]; 00250 } 00251 }
Here is the caller graph for this function:

Definition at line 254 of file decimal.c.
References DBUG_ASSERT, DIG_PER_DEC1, from, and powers10.
Referenced by decimal2bin(), decimal2string(), and decimal_intg().
00255 { 00256 int intg= from->intg, i; 00257 dec1 *buf0= from->buf; 00258 i= ((intg - 1) % DIG_PER_DEC1) + 1; 00259 while (intg > 0 && *buf0 == 0) 00260 { 00261 intg-= i; 00262 i= DIG_PER_DEC1; 00263 buf0++; 00264 } 00265 if (intg > 0) 00266 { 00267 for (i= (intg - 1) % DIG_PER_DEC1; *buf0 < powers10[i--]; intg--) ; 00268 DBUG_ASSERT(intg > 0); 00269 } 00270 else 00271 intg=0; 00272 *intg_result= intg; 00273 return buf0; 00274 }
Here is the caller graph for this function:

Definition at line 988 of file decimal.c.
References buf, DIG_BASE, E_DEC_OK, E_DEC_OVERFLOW, error, sanity, to, unlikely, and x.
Referenced by longlong2decimal(), and ulonglong2decimal().
00989 { 00990 int intg1, error=E_DEC_OK; 00991 ulonglong x=from; 00992 dec1 *buf; 00993 00994 sanity(to); 00995 00996 for (intg1=1; from >= DIG_BASE; intg1++, from/=DIG_BASE); 00997 if (unlikely(intg1 > to->len)) 00998 { 00999 intg1=to->len; 01000 error=E_DEC_OVERFLOW; 01001 } 01002 to->frac=0; 01003 to->intg=intg1*DIG_PER_DEC1; 01004 01005 for (buf=to->buf+intg1; intg1; intg1--) 01006 { 01007 ulonglong y=x/DIG_BASE; 01008 *--buf=(dec1)(x-y*DIG_BASE); 01009 x=y; 01010 } 01011 return error; 01012 }
Here is the caller graph for this function:

const int dig2bytes[DIG_PER_DEC1+1] = {0, 1, 1, 2, 2, 3, 3, 4, 4, 4} [static] |
Definition at line 136 of file decimal.c.
Referenced by bin2decimal(), decimal2bin(), and decimal_bin_size().
Initial value:
{
900000000, 990000000, 999000000,
999900000, 999990000, 999999000,
999999900, 999999990 }
Definition at line 137 of file decimal.c.
Referenced by max_decimal().
Initial value:
{
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}
Definition at line 134 of file decimal.c.
Referenced by bin2decimal(), decimal2bin(), decimal_actual_fraction(), decimal_round(), digits_bounds(), do_div_mod(), do_mini_left_shift(), do_mini_right_shift(), internal_str2dec(), max_decimal(), and remove_leading_zeroes().
1.4.7

