Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
4a23117f
Commit
4a23117f
authored
Nov 01, 2004
by
unknown
Browse files
Options
Browse Files
Download
Plain Diff
Merge mysql.com:/home/timka/mysql/src/5.0-virgin
into mysql.com:/home/timka/mysql/src/5.0-dbg
parents
de691e17
a2e7a90b
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
47 additions
and
29 deletions
+47
-29
include/decimal.h
include/decimal.h
+3
-3
strings/decimal.c
strings/decimal.c
+44
-26
No files found.
include/decimal.h
View file @
4a23117f
...
@@ -19,7 +19,7 @@
...
@@ -19,7 +19,7 @@
#include <my_global.h>
#include <my_global.h>
typedef
enum
{
TRUNCATE
=
0
,
EVEN
}
dec
_round_mode
;
typedef
enum
{
TRUNCATE
=
0
,
HALF_EVEN
,
HALF_UP
}
decimal
_round_mode
;
typedef
int32
decimal_digit
;
typedef
int32
decimal_digit
;
typedef
struct
st_decimal
{
typedef
struct
st_decimal
{
...
@@ -50,7 +50,7 @@ int decimal_cmp(decimal *from1, decimal *from2);
...
@@ -50,7 +50,7 @@ int decimal_cmp(decimal *from1, decimal *from2);
int
decimal_mul
(
decimal
*
from1
,
decimal
*
from2
,
decimal
*
to
);
int
decimal_mul
(
decimal
*
from1
,
decimal
*
from2
,
decimal
*
to
);
int
decimal_div
(
decimal
*
from1
,
decimal
*
from2
,
decimal
*
to
,
int
scale_incr
);
int
decimal_div
(
decimal
*
from1
,
decimal
*
from2
,
decimal
*
to
,
int
scale_incr
);
int
decimal_mod
(
decimal
*
from1
,
decimal
*
from2
,
decimal
*
to
);
int
decimal_mod
(
decimal
*
from1
,
decimal
*
from2
,
decimal
*
to
);
int
decimal_round
(
decimal
*
from
,
decimal
*
to
,
int
new_scale
,
dec_round_mode
mode
);
int
decimal_round
(
decimal
*
from
,
decimal
*
to
,
int
new_scale
,
dec
imal
_round_mode
mode
);
/*
/*
the following works only on special "zero" decimal, not on any
the following works only on special "zero" decimal, not on any
...
@@ -76,7 +76,7 @@ int decimal_round(decimal *from, decimal *to, int new_scale, dec_round_mode mode
...
@@ -76,7 +76,7 @@ int decimal_round(decimal *from, decimal *to, int new_scale, dec_round_mode mode
#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) + 1)
/* negate a decimal */
/* negate a decimal */
#define decimal_neg(dec) do { (dec)->sign
=!(dec)->sign
; } while(0)
#define decimal_neg(dec) do { (dec)->sign
^=1
; } while(0)
/*
/*
conventions:
conventions:
...
...
strings/decimal.c
View file @
4a23117f
...
@@ -115,6 +115,9 @@ static const dec1 powers10[DIG_PER_DEC1+1]={
...
@@ -115,6 +115,9 @@ static const dec1 powers10[DIG_PER_DEC1+1]={
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 3, 4, 4};
static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 3, 4, 4};
#define sanity(d) DBUG_ASSERT((d)->len >0 && ((d)->buf[0] | \
(d)->buf[(d)->len-1] | 1))
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) \
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) \
do \
do \
{ \
{ \
...
@@ -206,7 +209,7 @@ int decimal2string(decimal *from, char *to, int *to_len)
...
@@ -206,7 +209,7 @@ int decimal2string(decimal *from, char *to, int *to_len)
DBUG_ASSERT(*to_len > 2+from->sign);
DBUG_ASSERT(*to_len > 2+from->sign);
/* removing leading zeroes */
/* removing leading zeroes */
i
=
intg
%
DIG_PER_DEC
1
;
i=
((intg-1) % DIG_PER_DEC1)+
1;
while (intg > 0 && *buf0 == 0)
while (intg > 0 && *buf0 == 0)
{
{
intg-=i;
intg-=i;
...
@@ -306,6 +309,8 @@ static int str2dec(char *from, decimal *to, char **end, my_bool fixed)
...
@@ -306,6 +309,8 @@ static int str2dec(char *from, decimal *to, char **end, my_bool fixed)
int i, intg, frac, error, intg1, frac1;
int i, intg, frac, error, intg1, frac1;
dec1 x,*buf;
dec1 x,*buf;
sanity(to);
while (my_isspace(&my_charset_latin1, *s))
while (my_isspace(&my_charset_latin1, *s))
s++;
s++;
if ((to->sign= (*s == '-')))
if ((to->sign= (*s == '-')))
...
@@ -461,7 +466,9 @@ static int ull2dec(ulonglong from, decimal *to)
...
@@ -461,7 +466,9 @@ static int ull2dec(ulonglong from, decimal *to)
ulonglong x=from;
ulonglong x=from;
dec1 *buf;
dec1 *buf;
for
(
intg1
=
1
;
from
>
DIG_BASE
;
intg1
++
,
from
/=
DIG_BASE
);
sanity(to);
for (intg1=1; from >= DIG_BASE; intg1++, from/=DIG_BASE);
if (unlikely(intg1 > to->len))
if (unlikely(intg1 > to->len))
{
{
intg1=to->len;
intg1=to->len;
...
@@ -684,6 +691,8 @@ int bin2decimal(char *from, decimal *to, int precision, int scale)
...
@@ -684,6 +691,8 @@ int bin2decimal(char *from, decimal *to, int precision, int scale)
dec1 *buf=to->buf, mask=(*from <0) ? -1 : 0;
dec1 *buf=to->buf, mask=(*from <0) ? -1 : 0;
char *stop;
char *stop;
sanity(to);
FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
if (unlikely(error))
if (unlikely(error))
{
{
...
@@ -807,12 +816,14 @@ int decimal_bin_size(int precision, int scale)
...
@@ -807,12 +816,14 @@ int decimal_bin_size(int precision, int scale)
E_DEC_OK/E_DEC_TRUNCATED
E_DEC_OK/E_DEC_TRUNCATED
*/
*/
int
decimal_round
(
decimal
*
from
,
decimal
*
to
,
int
scale
,
dec_round_mode
mode
)
int decimal_round(decimal *from, decimal *to, int scale, dec
imal
_round_mode mode)
{
{
int frac0=ROUND_UP(scale), frac1=ROUND_UP(from->frac),
int frac0=ROUND_UP(scale), frac1=ROUND_UP(from->frac),
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);
if (unlikely(frac0+intg0 > len))
if (unlikely(frac0+intg0 > len))
{
{
frac0=len-intg0;
frac0=len-intg0;
...
@@ -856,7 +867,7 @@ int decimal_round(decimal *from, decimal *to, int scale, dec_round_mode mode)
...
@@ -856,7 +867,7 @@ int decimal_round(decimal *from, decimal *to, int scale, dec_round_mode mode)
if (mode != TRUNCATE)
if (mode != TRUNCATE)
{
{
x=buf0[1]/DIG_MASK;
x=buf0[1]/DIG_MASK;
if
(
x
>
5
||
(
x
==
5
&&
*
buf0
&
1
))
if (x > 5 || (x == 5 &&
(mode == HALF_UP || *buf0 & 1)
))
(*buf1)++;
(*buf1)++;
}
}
}
}
...
@@ -867,22 +878,19 @@ int decimal_round(decimal *from, decimal *to, int scale, dec_round_mode mode)
...
@@ -867,22 +878,19 @@ int decimal_round(decimal *from, decimal *to, int scale, dec_round_mode mode)
{
{
x=*buf1 / powers10[pos];
x=*buf1 / powers10[pos];
y=x % 10;
y=x % 10;
if
(
y
>
5
||
(
y
==
5
&&
(
x
/
10
)
&
1
))
if (y > 5 || (y == 5 && (
mode == HALF_UP || (x/10) & 1)
))
x+=10;
x+=10;
*
buf1
=
x
*
powers10
[
pos
]
-
y
;
*buf1=
powers10[pos]*(x-y)
;
}
}
else
else
*buf1=(*buf1/powers10[pos+1])*powers10[pos+1];
*buf1=(*buf1/powers10[pos+1])*powers10[pos+1];
}
}
if
(
*
buf1
>
DIG_BASE
)
if (*buf1 >
=
DIG_BASE)
{
{
carry=1;
carry=1;
*buf1-=DIG_BASE;
*buf1-=DIG_BASE;
while
(
carry
&&
buf1
>=
to
->
buf
)
while (carry && --buf1 >= to->buf)
{
ADD(*buf1, *buf1, 0, carry);
ADD(*buf1, *buf1, 0, carry);
buf1
--
;
}
if (unlikely(carry))
if (unlikely(carry))
{
{
/* shifting the number to create space for new digit */
/* shifting the number to create space for new digit */
...
@@ -955,6 +963,8 @@ static int do_add(decimal *from1, decimal *from2, decimal *to)
...
@@ -955,6 +963,8 @@ static int do_add(decimal *from1, decimal *from2, decimal *to)
frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
sanity(to);
/* is there a need for extra word because of carry ? */
/* is there a need for extra word because of carry ? */
x=intg1 > intg2 ? from1->buf[0] :
x=intg1 > intg2 ? from1->buf[0] :
intg2 > intg1 ? from2->buf[0] :
intg2 > intg1 ? from2->buf[0] :
...
@@ -1072,6 +1082,8 @@ static int do_sub(decimal *from1, decimal *from2, decimal *to)
...
@@ -1072,6 +1082,8 @@ static int do_sub(decimal *from1, decimal *from2, decimal *to)
if (to == 0) /* decimal_cmp() */
if (to == 0) /* decimal_cmp() */
return carry == from1->sign ? 1 : -1;
return carry == from1->sign ? 1 : -1;
sanity(to);
to->sign=from1->sign;
to->sign=from1->sign;
/* ensure that always from1 > from2 (and intg1 >= intg2) */
/* ensure that always from1 > from2 (and intg1 >= intg2) */
...
@@ -1190,6 +1202,8 @@ int decimal_mul(decimal *from1, decimal *from2, decimal *to)
...
@@ -1190,6 +1202,8 @@ int decimal_mul(decimal *from1, decimal *from2, decimal *to)
dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
*start2, *stop2, *stop1, *start0, carry;
*start2, *stop2, *stop1, *start0, carry;
sanity(to);
i=intg0;
i=intg0;
j=frac0;
j=frac0;
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
...
@@ -1265,8 +1279,10 @@ static int do_div_mod(decimal *from1, decimal *from2,
...
@@ -1265,8 +1279,10 @@ static int do_div_mod(decimal *from1, decimal *from2,
if (mod)
if (mod)
to=mod;
to=mod;
sanity(to);
/* removing all the leading zeroes */
/* removing all the leading zeroes */
i
=
prec1
%
DIG_PER_DEC
1
;
i=
((prec1-1) % DIG_PER_DEC1)+
1;
while (prec1 > 0 && *buf1 == 0)
while (prec1 > 0 && *buf1 == 0)
{
{
prec1-=i;
prec1-=i;
...
@@ -1281,7 +1297,7 @@ static int do_div_mod(decimal *from1, decimal *from2,
...
@@ -1281,7 +1297,7 @@ static int do_div_mod(decimal *from1, decimal *from2,
for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ;
for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ;
DBUG_ASSERT(prec1 > 0);
DBUG_ASSERT(prec1 > 0);
i
=
prec2
%
DIG_PER_DEC
1
;
i=
((prec2-1) % DIG_PER_DEC1)+
1;
while (prec2 > 0 && *buf2 == 0)
while (prec2 > 0 && *buf2 == 0)
{
{
prec2-=i;
prec2-=i;
...
@@ -1388,7 +1404,7 @@ static int do_div_mod(decimal *from1, decimal *from2,
...
@@ -1388,7 +1404,7 @@ static int do_div_mod(decimal *from1, decimal *from2,
dlen1=len2;
dlen1=len2;
}
}
guess=(norm_factor*x+norm_factor*y/DIG_BASE)/norm2;
guess=(norm_factor*x+norm_factor*y/DIG_BASE)/norm2;
if
(
unlikely
(
guess
>
DIG_BASE
))
if (unlikely(guess >
=
DIG_BASE))
guess=DIG_BASE-1;
guess=DIG_BASE-1;
if (likely(len2>1))
if (likely(len2>1))
{
{
...
@@ -1792,7 +1808,7 @@ void test_md(char *s1, char *s2)
...
@@ -1792,7 +1808,7 @@ void test_md(char *s1, char *s2)
printf("\n");
printf("\n");
}
}
void
test_ro
(
char
*
s1
,
int
n
,
dec_round_mode
mode
)
void test_ro(char *s1, int n, dec
imal
_round_mode mode)
{
{
char s[100];
char s[100];
int res;
int res;
...
@@ -1874,6 +1890,7 @@ main()
...
@@ -1874,6 +1890,7 @@ main()
printf("==== do_add ====\n");
printf("==== do_add ====\n");
test_da(".00012345000098765" ,"123.45");
test_da(".00012345000098765" ,"123.45");
test_da(".1" ,".45");
test_da("1234500009876.5" ,".00012345000098765");
test_da("1234500009876.5" ,".00012345000098765");
test_da("9999909999999.5" ,".555");
test_da("9999909999999.5" ,".555");
test_da("99999999" ,"1");
test_da("99999999" ,"1");
...
@@ -1921,17 +1938,18 @@ main()
...
@@ -1921,17 +1938,18 @@ main()
test_dv("0", "987");
test_dv("0", "987");
printf("==== decimal_round ====\n");
printf("==== decimal_round ====\n");
test_ro
(
"15.1"
,
0
,
EVEN
);
test_ro("15.1",0,HALF_UP);
test_ro
(
"15.5"
,
0
,
EVEN
);
test_ro("15.5",0,HALF_UP);
test_ro
(
"15.9"
,
0
,
EVEN
);
test_ro("15.5",0,HALF_UP);
test_ro
(
"-15.1"
,
0
,
EVEN
);
test_ro("15.9",0,HALF_UP);
test_ro
(
"-15.5"
,
0
,
EVEN
);
test_ro("-15.1",0,HALF_UP);
test_ro
(
"-15.9"
,
0
,
EVEN
);
test_ro("-15.5",0,HALF_UP);
test_ro
(
"15.1"
,
1
,
EVEN
);
test_ro("-15.9",0,HALF_UP);
test_ro
(
"-15.1"
,
1
,
EVEN
);
test_ro("15.1",1,HALF_UP);
test_ro
(
"15.17"
,
1
,
EVEN
);
test_ro("-15.1",1,HALF_UP);
test_ro
(
"15.4"
,
-
1
,
EVEN
);
test_ro("15.17",1,HALF_UP);
test_ro
(
"-15.4"
,
-
1
,
EVEN
);
test_ro("15.4",-1,HALF_UP);
test_ro("-15.4",-1,HALF_UP);
test_ro("5678.123451",-4,TRUNCATE);
test_ro("5678.123451",-4,TRUNCATE);
test_ro("5678.123451",-3,TRUNCATE);
test_ro("5678.123451",-3,TRUNCATE);
test_ro("5678.123451",-2,TRUNCATE);
test_ro("5678.123451",-2,TRUNCATE);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment