Merge mskold@bk-internal.mysql.com:/home/bk/mysql-5.0

into mysql.com:/usr/local/home/marty/MySQL/test/mysql-5.0-ndb
This commit is contained in:
mskold@mysql.com 2004-11-04 08:21:45 +01:00
commit f395228afe
2 changed files with 67 additions and 52 deletions

View File

@ -19,7 +19,7 @@
#include <my_global.h> #include <my_global.h>
typedef enum {TRUNCATE=0, HALF_EVEN, HALF_UP} decimal_round_mode; typedef enum {TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR} decimal_round_mode;
typedef int32 decimal_digit; typedef int32 decimal_digit;
typedef struct st_decimal { typedef struct st_decimal {
@ -70,10 +70,10 @@ int decimal_round(decimal *from, decimal *to, int new_scale, decimal_round_mode
/* /*
returns the length of the buffer to hold string representation returns the length of the buffer to hold string representation
of the decimal of the decimal (including decimal dot, possible sign and \0)
*/ */
#define decimal_string_size(dec) ((dec)->intg + (dec)->frac + ((dec)->frac > 0) + 1) #define decimal_string_size(dec) ((dec)->intg + (dec)->frac + ((dec)->frac > 0) + 2)
/* negate a decimal */ /* negate a decimal */
#define decimal_neg(dec) do { (dec)->sign^=1; } while(0) #define decimal_neg(dec) do { (dec)->sign^=1; } while(0)
@ -91,9 +91,12 @@ int decimal_round(decimal *from, decimal *to, int new_scale, decimal_round_mode
#define E_DEC_OK 0 #define E_DEC_OK 0
#define E_DEC_TRUNCATED 1 #define E_DEC_TRUNCATED 1
#define E_DEC_OVERFLOW 2 #define E_DEC_OVERFLOW 2
#define E_DEC_DIV_ZERO 3 #define E_DEC_DIV_ZERO 4
#define E_DEC_BAD_NUM 4 #define E_DEC_BAD_NUM 8
#define E_DEC_OOM 5 #define E_DEC_OOM 16
#define E_DEC_ERROR 31
#define E_DEC_FATAL_ERROR 30
#endif #endif

View File

@ -819,12 +819,21 @@ int decimal_bin_size(int precision, int scale)
int decimal_round(decimal *from, decimal *to, int scale, decimal_round_mode mode) int decimal_round(decimal *from, decimal *to, int scale, decimal_round_mode mode)
{ {
int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1, int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
frac1=ROUND_UP(from->frac), frac1=ROUND_UP(from->frac), round_digit,
intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len; intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len;
dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0; dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
sanity(to); sanity(to);
switch (mode) {
case HALF_UP:
case HALF_EVEN: round_digit=5; break;
case CEILING: round_digit= from->sign ? 10 : 0; break;
case FLOOR: round_digit= from->sign ? 0 : 10; break;
case TRUNCATE: round_digit=10; break;
default: DBUG_ASSERT(0);
}
if (unlikely(frac0+intg0 > len)) if (unlikely(frac0+intg0 > len))
{ {
frac0=len-intg0; frac0=len-intg0;
@ -865,26 +874,20 @@ int decimal_round(decimal *from, decimal *to, int scale, decimal_round_mode mode
buf1+=intg0+frac0-1; buf1+=intg0+frac0-1;
if (scale == frac0*DIG_PER_DEC1) if (scale == frac0*DIG_PER_DEC1)
{ {
if (mode != TRUNCATE) x=buf0[1]/DIG_MASK;
{ if (x > round_digit ||
x=buf0[1]/DIG_MASK; (round_digit == 5 && x == 5 && (mode == HALF_UP || *buf0 & 1)))
if (x > 5 || (x == 5 && (mode == HALF_UP || *buf0 & 1))) (*buf1)++;
(*buf1)++;
}
} }
else else
{ {
int pos=frac0*DIG_PER_DEC1-scale-1; int pos=frac0*DIG_PER_DEC1-scale-1;
if (mode != TRUNCATE) x=*buf1 / powers10[pos];
{ y=x % 10;
x=*buf1 / powers10[pos]; if (y > round_digit ||
y=x % 10; (round_digit == 5 && y == 5 && (mode == HALF_UP || (x/10) & 1)))
if (y > 5 || (y == 5 && (mode == HALF_UP || (x/10) & 1))) x+=10;
x+=10; *buf1=powers10[pos]*(x-y);
*buf1=powers10[pos]*(x-y);
}
else
*buf1=(*buf1/powers10[pos+1])*powers10[pos+1];
} }
if (*buf1 >= DIG_BASE) if (*buf1 >= DIG_BASE)
{ {
@ -1820,12 +1823,13 @@ void test_md(char *s1, char *s2)
printf("\n"); printf("\n");
} }
char *round_mode[]={"TRUNCATE", "HALF_EVEN", "HALF_UP", "CEILING", "FLOOR"};
void test_ro(char *s1, int n, decimal_round_mode mode) void test_ro(char *s1, int n, decimal_round_mode mode)
{ {
char s[100]; char s[100];
int res; int res;
sprintf(s, "%s('%s', %d)", (mode == TRUNCATE ? "truncate" : "round"), sprintf(s, "'%s', %d, %s", s1, n, round_mode[mode]);
s1, n);
string2decimal(s1, &a, 0); string2decimal(s1, &a, 0);
res=decimal_round(&a, &b, n, mode); res=decimal_round(&a, &b, n, mode);
printf("%-40s => res=%d ", s, res); printf("%-40s => res=%d ", s, res);
@ -1953,33 +1957,6 @@ main()
test_dv("1", "1"); test_dv("1", "1");
test_dv("0.0123456789012345678912345", "9999999999"); test_dv("0.0123456789012345678912345", "9999999999");
printf("==== decimal_round ====\n");
test_ro("15.1",0,HALF_UP);
test_ro("15.5",0,HALF_UP);
test_ro("15.5",0,HALF_UP);
test_ro("15.9",0,HALF_UP);
test_ro("-15.1",0,HALF_UP);
test_ro("-15.5",0,HALF_UP);
test_ro("-15.9",0,HALF_UP);
test_ro("15.1",1,HALF_UP);
test_ro("-15.1",1,HALF_UP);
test_ro("15.17",1,HALF_UP);
test_ro("15.4",-1,HALF_UP);
test_ro("-15.4",-1,HALF_UP);
test_ro("5678.123451",-4,TRUNCATE);
test_ro("5678.123451",-3,TRUNCATE);
test_ro("5678.123451",-2,TRUNCATE);
test_ro("5678.123451",-1,TRUNCATE);
test_ro("5678.123451",0,TRUNCATE);
test_ro("5678.123451",1,TRUNCATE);
test_ro("5678.123451",2,TRUNCATE);
test_ro("5678.123451",3,TRUNCATE);
test_ro("5678.123451",4,TRUNCATE);
test_ro("5678.123451",5,TRUNCATE);
test_ro("5678.123451",6,TRUNCATE);
test_ro("-5678.123451",-4,TRUNCATE);
test_ro("99999999999999999999999999999999999999",-31,TRUNCATE);
printf("==== decimal_mod ====\n"); printf("==== decimal_mod ====\n");
test_md("234","10"); test_md("234","10");
test_md("234.567","10.555"); test_md("234.567","10.555");
@ -2008,6 +1985,41 @@ main()
test_dc("0","12"); test_dc("0","12");
test_dc("-10","0"); test_dc("-10","0");
test_dc("4","4"); test_dc("4","4");
printf("==== decimal_round ====\n");
test_ro("5678.123451",-4,TRUNCATE);
test_ro("5678.123451",-3,TRUNCATE);
test_ro("5678.123451",-2,TRUNCATE);
test_ro("5678.123451",-1,TRUNCATE);
test_ro("5678.123451",0,TRUNCATE);
test_ro("5678.123451",1,TRUNCATE);
test_ro("5678.123451",2,TRUNCATE);
test_ro("5678.123451",3,TRUNCATE);
test_ro("5678.123451",4,TRUNCATE);
test_ro("5678.123451",5,TRUNCATE);
test_ro("5678.123451",6,TRUNCATE);
test_ro("-5678.123451",-4,TRUNCATE);
test_ro("99999999999999999999999999999999999999",-31,TRUNCATE);
test_ro("15.1",0,HALF_UP);
test_ro("15.5",0,HALF_UP);
test_ro("15.9",0,HALF_UP);
test_ro("-15.1",0,HALF_UP);
test_ro("-15.5",0,HALF_UP);
test_ro("-15.9",0,HALF_UP);
test_ro("15.1",1,HALF_UP);
test_ro("-15.1",1,HALF_UP);
test_ro("15.17",1,HALF_UP);
test_ro("15.4",-1,HALF_UP);
test_ro("-15.4",-1,HALF_UP);
test_ro("15.1",0,HALF_EVEN);
test_ro("15.5",0,HALF_EVEN);
test_ro("14.5",0,HALF_EVEN);
test_ro("15.9",0,HALF_EVEN);
test_ro("15.1",0,CEILING);
test_ro("-15.1",0,CEILING);
test_ro("15.1",0,FLOOR);
test_ro("-15.1",0,FLOOR);
return 0; return 0;
} }
#endif #endif