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
574023ba
Commit
574023ba
authored
Mar 31, 2005
by
unknown
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
decimal_div bug#9501
parent
b8aa173e
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
64 additions
and
69 deletions
+64
-69
mysql-test/r/type_newdecimal.result
mysql-test/r/type_newdecimal.result
+3
-0
mysql-test/t/type_newdecimal.test
mysql-test/t/type_newdecimal.test
+6
-1
strings/decimal.c
strings/decimal.c
+55
-68
No files found.
mysql-test/r/type_newdecimal.result
View file @
574023ba
...
...
@@ -839,3 +839,6 @@ Error 1365 Division by 0
INSERT INTO Sow6_2f VALUES ('a59b');
ERROR HY000: Incorrect decimal value: 'a59b' for column 'col1' at row 1
drop table Sow6_2f;
select 10.3330000000000/12.34500000;
10.3330000000000/12.34500000
0.8370190360469825840421223160000
mysql-test/t/type_newdecimal.test
View file @
574023ba
...
...
@@ -748,7 +748,7 @@ select 1 / 0;
#+-------+
#| 1 / 0 |
#+-------+
#| NULL |
#| NULL
|
#+-------+
#1 row in set, 1 warning (0.00 sec)
#
...
...
@@ -864,3 +864,8 @@ SELECT MOD(col1,0) FROM Sow6_2f;
INSERT
INTO
Sow6_2f
VALUES
(
'a59b'
);
#-- should return SQLSTATE 22018 invalid character value for cast
drop
table
Sow6_2f
;
#
# bug#9501
#
select
10.3330000000000
/
12.34500000
;
strings/decimal.c
View file @
574023ba
...
...
@@ -1933,16 +1933,16 @@ int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
XXX if this library is to be used with huge numbers of thousands of
digits, fast division must be implemented and alloca should be
changed to malloc (or at least fallback to malloc if alloca() fails)
but then, decimal_m
od
() should be rewritten too :(
but then, decimal_m
ul
() should be rewritten too :(
*/
static
int
do_div_mod
(
decimal_t
*
from1
,
decimal_t
*
from2
,
decimal_t
*
to
,
decimal_t
*
mod
,
int
scale_incr
)
{
int
frac1
=
ROUND_UP
(
from1
->
frac
)
*
DIG_PER_DEC1
,
prec1
=
from1
->
intg
+
frac1
,
frac2
=
ROUND_UP
(
from2
->
frac
)
*
DIG_PER_DEC1
,
prec2
=
from2
->
intg
+
frac2
,
error
,
i
,
intg0
,
frac0
,
len1
,
len2
,
d
len1
,
d
intg
,
div
=
(
!
mod
);
error
,
i
,
intg0
,
frac0
,
len1
,
len2
,
dintg
,
div
=
(
!
mod
);
dec1
*
buf0
,
*
buf1
=
from1
->
buf
,
*
buf2
=
from2
->
buf
,
*
tmp1
,
*
start2
,
*
stop2
,
*
stop1
,
*
stop0
,
norm2
,
carry
,
*
start1
;
*
start2
,
*
stop2
,
*
stop1
,
*
stop0
,
norm2
,
carry
,
*
start1
,
dcarry
;
dec2
norm_factor
,
x
,
guess
,
y
;
LINT_INIT
(
error
);
...
...
@@ -2043,7 +2043,7 @@ static int do_div_mod(decimal_t *from1, decimal_t *from2,
/* removing end zeroes */
while
(
*
stop2
==
0
&&
stop2
>=
start2
)
stop2
--
;
len2
=
++
stop2
-
start2
;
len2
=
stop2
++
-
start2
;
/*
calculating norm2 (normalized *start2) - we need *start2 to be large
...
...
@@ -2055,87 +2055,70 @@ static int do_div_mod(decimal_t *from1, decimal_t *from2,
*/
norm_factor
=
DIG_BASE
/
(
*
start2
+
1
);
norm2
=
(
dec1
)(
norm_factor
*
start2
[
0
]);
if
(
likely
(
len2
>
1
))
if
(
likely
(
len2
>
0
))
norm2
+=
(
dec1
)(
norm_factor
*
start2
[
1
]
/
DIG_BASE
);
if
(
*
start1
<
*
start2
)
dcarry
=*
start1
++
;
else
dcarry
=
0
;
/* main loop */
for
(
;
buf0
<
stop0
;
buf0
++
)
for
(;
buf0
<
stop0
;
buf0
++
)
{
/* short-circuit, if possible */
if
(
unlikely
(
*
start1
==
0
))
{
start1
++
;
if
(
likely
(
div
))
*
buf0
=
0
;
continue
;
}
/* D3: make a guess */
if
(
*
start1
>=
*
start2
)
{
x
=
start1
[
0
];
y
=
start1
[
1
];
dlen1
=
len2
-
1
;
}
if
(
unlikely
(
dcarry
==
0
&&
*
start1
<
*
start2
))
guess
=
0
;
else
{
x
=
((
dec2
)
start1
[
0
])
*
DIG_BASE
+
start1
[
1
];
y
=
start1
[
2
];
dlen1
=
len2
;
}
guess
=
(
norm_factor
*
x
+
norm_factor
*
y
/
DIG_BASE
)
/
norm2
;
if
(
unlikely
(
guess
>=
DIG_BASE
))
guess
=
DIG_BASE
-
1
;
if
(
likely
(
len2
>
1
))
{
/* hmm, this is a suspicious trick - I removed normalization here */
if
(
start2
[
1
]
*
guess
>
(
x
-
guess
*
start2
[
0
])
*
DIG_BASE
+
y
)
guess
--
;
if
(
unlikely
(
start2
[
1
]
*
guess
>
(
x
-
guess
*
start2
[
0
])
*
DIG_BASE
+
y
))
guess
--
;
DBUG_ASSERT
(
start2
[
1
]
*
guess
<=
(
x
-
guess
*
start2
[
0
])
*
DIG_BASE
+
y
);
}
/* D4: multiply and subtract */
buf2
=
stop2
;
buf1
=
start1
+
dlen1
;
DBUG_ASSERT
(
buf1
<
stop1
);
for
(
carry
=
0
;
buf2
>
start2
;
buf1
--
)
{
dec1
hi
,
lo
;
x
=
guess
*
(
*--
buf2
);
hi
=
(
dec1
)(
x
/
DIG_BASE
);
lo
=
(
dec1
)(
x
-
((
dec2
)
hi
)
*
DIG_BASE
);
SUB2
(
*
buf1
,
*
buf1
,
lo
,
carry
);
carry
+=
hi
;
}
for
(;
buf1
>=
start1
;
buf1
--
)
{
SUB2
(
*
buf1
,
*
buf1
,
0
,
carry
);
}
/* D3: make a guess */
x
=
start1
[
0
]
+
((
dec2
)
dcarry
)
*
DIG_BASE
;
y
=
start1
[
1
];
guess
=
(
norm_factor
*
x
+
norm_factor
*
y
/
DIG_BASE
)
/
norm2
;
if
(
unlikely
(
guess
>=
DIG_BASE
))
guess
=
DIG_BASE
-
1
;
if
(
likely
(
len2
>
0
))
{
/* hmm, this is a suspicious trick - I removed normalization here */
if
(
start2
[
1
]
*
guess
>
(
x
-
guess
*
start2
[
0
])
*
DIG_BASE
+
y
)
guess
--
;
if
(
unlikely
(
start2
[
1
]
*
guess
>
(
x
-
guess
*
start2
[
0
])
*
DIG_BASE
+
y
))
guess
--
;
DBUG_ASSERT
(
start2
[
1
]
*
guess
<=
(
x
-
guess
*
start2
[
0
])
*
DIG_BASE
+
y
);
}
/* D5: check the remainder */
if
(
unlikely
(
carry
))
{
DBUG_ASSERT
(
carry
==
1
);
/* D6: correct the guess */
guess
--
;
/* D4: multiply and subtract */
buf2
=
stop2
;
buf1
=
start1
+
dlen1
;
buf1
=
start1
+
len2
;
DBUG_ASSERT
(
buf1
<
stop1
);
for
(
carry
=
0
;
buf2
>
start2
;
buf1
--
)
{
ADD
(
*
buf1
,
*
buf1
,
*--
buf2
,
carry
);
dec1
hi
,
lo
;
x
=
guess
*
(
*--
buf2
);
hi
=
(
dec1
)(
x
/
DIG_BASE
);
lo
=
(
dec1
)(
x
-
((
dec2
)
hi
)
*
DIG_BASE
);
SUB2
(
*
buf1
,
*
buf1
,
lo
,
carry
);
carry
+=
hi
;
}
for
(;
buf1
>=
start1
;
buf1
--
)
carry
=
dcarry
<
carry
;
/* D5: check the remainder */
if
(
unlikely
(
carry
))
{
SUB2
(
*
buf1
,
*
buf1
,
0
,
carry
);
/* D6: correct the guess */
guess
--
;
buf2
=
stop2
;
buf1
=
start1
+
len2
;
for
(
carry
=
0
;
buf2
>
start2
;
buf1
--
)
{
ADD
(
*
buf1
,
*
buf1
,
*--
buf2
,
carry
);
}
}
DBUG_ASSERT
(
carry
==
1
);
}
if
(
likely
(
div
))
*
buf0
=
(
dec1
)
guess
;
if
(
*
start1
==
0
)
start1
++
;
dcarry
=
*
start1
;
start1
++
;
}
if
(
mod
)
{
...
...
@@ -2144,6 +2127,8 @@ static int do_div_mod(decimal_t *from1, decimal_t *from2,
intg=prec1-frac1
frac=max(frac1, frac2)=to->frac
*/
if
(
dcarry
)
*--
start1
=
dcarry
;
buf0
=
to
->
buf
;
intg0
=
ROUND_UP
(
prec1
-
frac1
)
-
(
start1
-
tmp1
);
frac0
=
ROUND_UP
(
to
->
frac
);
...
...
@@ -2753,6 +2738,8 @@ int main()
test_dv
(
"1.000000000000"
,
"3"
,
"0.333333333333333333"
,
0
);
test_dv
(
"1"
,
"1"
,
"1.000000000"
,
0
);
test_dv
(
"0.0123456789012345678912345"
,
"9999999999"
,
"0.000000000001234567890246913578148141"
,
0
);
test_dv
(
"10.333000000"
,
"12.34500"
,
"0.837019036046982584042122316"
,
0
);
test_dv
(
"10.000000000060"
,
"2"
,
"5.000000000030000000"
,
0
);
printf
(
"==== decimal_mod ====
\n
"
);
test_md
(
"234"
,
"10"
,
"4"
,
0
);
...
...
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