mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
error codes chaged to bitmap (for easier testing with masks)
two more round() modes - CEILING and FLOOR
This commit is contained in:
@ -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 {
|
||||||
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user