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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
2323a3dc
Commit
2323a3dc
authored
Nov 01, 2004
by
timour@mysql.com
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
157dfcf4
b0045f9e
Changes
2
Show 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 @
2323a3dc
...
@@ -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 @
2323a3dc
...
@@ -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