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
24b608b2
Commit
24b608b2
authored
Oct 19, 2004
by
unknown
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
decimal to/from bin, and utility functions
strings/Makefile.am: cleanup
parent
bd5bafe1
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
314 additions
and
29 deletions
+314
-29
include/decimal.h
include/decimal.h
+24
-15
strings/Makefile.am
strings/Makefile.am
+4
-5
strings/decimal.c
strings/decimal.c
+286
-9
No files found.
include/decimal.h
View file @
24b608b2
...
@@ -18,11 +18,9 @@
...
@@ -18,11 +18,9 @@
#define _decimal_h
#define _decimal_h
#include <my_global.h>
#include <my_global.h>
#include <m_ctype.h>
#include <my_sys.h>
/* for my_alloca */
typedef
enum
{
TRUNCATE
=
0
,
EVEN
}
dec_round_mode
;
typedef
enum
{
TRUNCATE
=
0
,
EVEN
}
dec_round_mode
;
typedef
u
int32
decimal_digit
;
typedef
int32
decimal_digit
;
typedef
struct
st_decimal
{
typedef
struct
st_decimal
{
int
intg
,
frac
,
len
;
int
intg
,
frac
,
len
;
...
@@ -30,7 +28,7 @@ typedef struct st_decimal {
...
@@ -30,7 +28,7 @@ typedef struct st_decimal {
decimal_digit
*
buf
;
decimal_digit
*
buf
;
}
decimal
;
}
decimal
;
int
decimal2string
(
decimal
*
from
,
char
*
to
,
u
int
*
to_len
);
int
decimal2string
(
decimal
*
from
,
char
*
to
,
int
*
to_len
);
int
string2decimal
(
char
*
from
,
decimal
*
to
,
char
**
end
);
int
string2decimal
(
char
*
from
,
decimal
*
to
,
char
**
end
);
int
decimal2ulonglong
(
decimal
*
from
,
ulonglong
*
to
);
int
decimal2ulonglong
(
decimal
*
from
,
ulonglong
*
to
);
int
ulonglong2decimal
(
ulonglong
from
,
decimal
*
to
);
int
ulonglong2decimal
(
ulonglong
from
,
decimal
*
to
);
...
@@ -38,31 +36,42 @@ int decimal2longlong(decimal *from, longlong *to);
...
@@ -38,31 +36,42 @@ int decimal2longlong(decimal *from, longlong *to);
int
longlong2decimal
(
longlong
from
,
decimal
*
to
);
int
longlong2decimal
(
longlong
from
,
decimal
*
to
);
int
decimal2double
(
decimal
*
from
,
double
*
to
);
int
decimal2double
(
decimal
*
from
,
double
*
to
);
int
double2decimal
(
double
from
,
decimal
*
to
);
int
double2decimal
(
double
from
,
decimal
*
to
);
int
decimal2bin
(
decimal
*
from
,
char
*
to
,
int
precision
,
int
scale
);
int
bin2decimal
(
char
*
from
,
decimal
*
to
,
int
precision
,
int
scale
);
int
decimal_size
(
int
precision
,
int
scale
);
int
decimal_bin_size
(
int
precision
,
int
scale
);
int
decimal_result_size
(
decimal
*
from1
,
decimal
*
from2
,
char
op
,
int
param
);
int
decimal_add
(
decimal
*
from1
,
decimal
*
from2
,
decimal
*
to
);
int
decimal_add
(
decimal
*
from1
,
decimal
*
from2
,
decimal
*
to
);
int
decimal_sub
(
decimal
*
from1
,
decimal
*
from2
,
decimal
*
to
);
int
decimal_sub
(
decimal
*
from1
,
decimal
*
from2
,
decimal
*
to
);
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_result_size
(
decimal
*
from1
,
decimal
*
from2
,
char
op
,
int
param
);
int
decimal_round
(
decimal
*
dec
,
int
new_scale
,
dec_round_mode
mode
);
int
decimal_round
(
decimal
*
dec
,
int
new_scale
,
dec_round_mode
mode
);
/*
the following works only on special "zero" decimal, not on any
decimal that happen to evaluate to zero
*/
#define decimal_is_zero(dec) ((dec)->intg1==1 && (dec)->frac1==0 && (dec)->buf[0]==0)
/*
/*
conventions:
conventions:
decimal_smth() == 0 -- everything's ok
decimal_smth() == 0 -- everything's ok
decimal_smth() <=
0 -- result is usable,
precision loss is possible
decimal_smth() <=
1 -- result is usable, but
precision loss is possible
decimal_smth() <=
1 -- result is unusable, but
most significant digits
decimal_smth() <=
2 -- result can be unusable,
most significant digits
c
an be
lost
c
ould've been
lost
decimal_smth() >
1
-- no result was generated
decimal_smth() >
2
-- no result was generated
*/
*/
#define E_DEC_TRUNCATED -1
#define E_DEC_OK 0
#define E_DEC_OK 0
#define E_DEC_OVERFLOW 1
#define E_DEC_TRUNCATED 1
#define E_DEC_DIV_ZERO 2
#define E_DEC_OVERFLOW 2
#define E_DEC_BAD_NUM 3
#define E_DEC_DIV_ZERO 3
#define E_DEC_OOM 4
#define E_DEC_BAD_NUM 4
#define E_DEC_OOM 5
#endif
#endif
strings/Makefile.am
View file @
24b608b2
...
@@ -74,14 +74,13 @@ if ASSEMBLER
...
@@ -74,14 +74,13 @@ if ASSEMBLER
endif
endif
FLAGS
=
$(DEFS)
$(INCLUDES)
$(CPPFLAGS)
$(CFLAGS)
@NOINST_LDFLAGS@
FLAGS
=
$(DEFS)
$(INCLUDES)
$(CPPFLAGS)
$(CFLAGS)
@NOINST_LDFLAGS@
LIBS
=
libmystrings.a
str_test
:
str_test.c $(LIBRARIES)
str_test
:
str_test.c $(
pkglib_
LIBRARIES)
$(LINK)
$(FLAGS)
-DMAIN
$(INCLUDES)
$(srcdir)
/str_test.c
$(LDADD)
$(
LIBS)
$(
pkglib_LIBRARIES)
$(LINK)
$(FLAGS)
-DMAIN
$(INCLUDES)
$(srcdir)
/str_test.c
$(LDADD)
$(pkglib_LIBRARIES)
test_decimal$(EXEEXT)
:
decimal.c $(LIBRARIES)
test_decimal$(EXEEXT)
:
decimal.c $(
pkglib_
LIBRARIES)
$(CP)
$(srcdir)
/decimal.c ./test_decimal.c
$(CP)
$(srcdir)
/decimal.c ./test_decimal.c
$(LINK)
$(FLAGS)
-DMAIN
./test_decimal.c
$(LDADD)
$(
LIB
S)
$(LINK)
$(FLAGS)
-DMAIN
./test_decimal.c
$(LDADD)
$(
pkglib_LIBRARIE
S)
$(RM)
-f
./test_decimal.c
$(RM)
-f
./test_decimal.c
# Don't update the files from bitkeeper
# Don't update the files from bitkeeper
...
...
strings/decimal.c
View file @
24b608b2
...
@@ -99,6 +99,9 @@
...
@@ -99,6 +99,9 @@
*/
*/
#include <decimal.h>
#include <decimal.h>
#include <m_ctype.h>
#include <myisampack.h>
#include <my_sys.h>
/* for my_alloca */
typedef
decimal_digit
dec1
;
typedef
decimal_digit
dec1
;
typedef
longlong
dec2
;
typedef
longlong
dec2
;
...
@@ -110,6 +113,7 @@ typedef longlong dec2;
...
@@ -110,6 +113,7 @@ typedef longlong dec2;
#define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
#define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
static
const
dec1
powers10
[
DIG_PER_DEC1
+
1
]
=
{
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
};
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) \
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) \
do \
do \
...
@@ -186,7 +190,7 @@ static const dec1 powers10[DIG_PER_DEC1+1]={
...
@@ -186,7 +190,7 @@ static const dec1 powers10[DIG_PER_DEC1+1]={
} while(0)
} while(0)
/*
/*
Convert decimal to its string representation
Convert decimal to its
printable
string representation
SYNOPSIS
SYNOPSIS
decimal2string()
decimal2string()
...
@@ -199,7 +203,7 @@ static const dec1 powers10[DIG_PER_DEC1+1]={
...
@@ -199,7 +203,7 @@ static const dec1 powers10[DIG_PER_DEC1+1]={
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
*/
*/
int
decimal2string
(
decimal
*
from
,
char
*
to
,
u
int
*
to_len
)
int
decimal2string
(
decimal
*
from
,
char
*
to
,
int
*
to_len
)
{
{
int
len
,
intg
=
from
->
intg
,
frac
=
from
->
frac
,
i
;
int
len
,
intg
=
from
->
intg
,
frac
=
from
->
frac
,
i
;
int
error
=
E_DEC_OK
;
int
error
=
E_DEC_OK
;
...
@@ -209,9 +213,11 @@ int decimal2string(decimal *from, char *to, uint *to_len)
...
@@ -209,9 +213,11 @@ int decimal2string(decimal *from, char *to, uint *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_DEC1
;
while
(
intg
>
0
&&
*
buf0
==
0
)
while
(
intg
>
0
&&
*
buf0
==
0
)
{
{
intg
-=
DIG_PER_DEC1
;
intg
-=
i
;
i
=
DIG_PER_DEC1
;
buf0
++
;
buf0
++
;
}
}
if
(
intg
>
0
)
if
(
intg
>
0
)
...
@@ -231,7 +237,7 @@ int decimal2string(decimal *from, char *to, uint *to_len)
...
@@ -231,7 +237,7 @@ int decimal2string(decimal *from, char *to, uint *to_len)
len
=
from
->
sign
+
intg
+
test
(
frac
)
+
frac
;
len
=
from
->
sign
+
intg
+
test
(
frac
)
+
frac
;
if
(
unlikely
(
len
>
--*
to_len
))
/* reserve one byte for \0 */
if
(
unlikely
(
len
>
--*
to_len
))
/* reserve one byte for \0 */
{
{
u
int
i
=
len
-*
to_len
;
int
i
=
len
-*
to_len
;
error
=
(
frac
&&
i
<=
frac
+
1
)
?
E_DEC_TRUNCATED
:
E_DEC_OVERFLOW
;
error
=
(
frac
&&
i
<=
frac
+
1
)
?
E_DEC_TRUNCATED
:
E_DEC_OVERFLOW
;
if
(
frac
&&
i
>=
frac
+
1
)
i
--
;
if
(
frac
&&
i
>=
frac
+
1
)
i
--
;
if
(
i
>
frac
)
if
(
i
>
frac
)
...
@@ -517,6 +523,244 @@ int decimal2longlong(decimal *from, longlong *to)
...
@@ -517,6 +523,244 @@ int decimal2longlong(decimal *from, longlong *to)
return
from
->
frac
?
E_DEC_TRUNCATED
:
E_DEC_OK
;
return
from
->
frac
?
E_DEC_TRUNCATED
:
E_DEC_OK
;
}
}
/*
Convert decimal to its binary fixed-length representation
two representations of the same length can be compared with memcmp
with the correct -1/0/+1 result
SYNOPSIS
decimal2bin()
from - value to convert
to - points to buffer where string representation should be stored
precision/scale - see decimal_bin_size() below
NOTE
the buffer is assumed to be of the size decimal_bin_size(precision, scale)
RETURN VALUE
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
*/
int
decimal2bin
(
decimal
*
from
,
char
*
to
,
int
precision
,
int
frac
)
{
dec1
mask
=
from
->
sign
?
-
1
:
0
,
*
buf1
=
from
->
buf
,
*
stop1
;
int
error
=
E_DEC_OK
,
intg
=
precision
-
frac
,
intg0
=
intg
/
DIG_PER_DEC1
,
frac0
=
frac
/
DIG_PER_DEC1
,
intg0x
=
intg
-
intg0
*
DIG_PER_DEC1
,
frac0x
=
frac
-
frac0
*
DIG_PER_DEC1
,
intg1
=
from
->
intg
/
DIG_PER_DEC1
,
frac1
=
from
->
frac
/
DIG_PER_DEC1
,
intg1x
=
from
->
intg
-
intg1
*
DIG_PER_DEC1
,
frac1x
=
from
->
frac
-
frac1
*
DIG_PER_DEC1
,
isize0
=
intg0
*
sizeof
(
dec1
)
+
dig2bytes
[
intg0x
],
fsize0
=
frac0
*
sizeof
(
dec1
)
+
dig2bytes
[
frac0x
],
isize1
=
intg1
*
sizeof
(
dec1
)
+
dig2bytes
[
intg1x
],
fsize1
=
frac1
*
sizeof
(
dec1
)
+
dig2bytes
[
frac1x
];
if
(
isize0
<
isize1
)
{
buf1
+=
intg1
-
intg0
+
(
intg1x
>
0
)
-
(
intg0x
>
0
);
intg1
=
intg0
;
intg1x
=
intg0x
;
error
=
E_DEC_OVERFLOW
;
}
else
if
(
isize0
>
isize1
)
{
while
(
isize0
--
>
isize1
)
*
to
++=
(
char
)
mask
;
}
if
(
fsize0
<
fsize1
)
{
frac1
=
frac0
;
frac1x
=
frac0x
;
error
=
E_DEC_TRUNCATED
;
}
else
if
(
fsize0
>
fsize1
&&
frac1x
)
{
if
(
frac0
==
frac1
)
frac1x
=
frac0x
;
else
{
frac1
++
;
frac1x
=
0
;
}
}
/* intg1x part */
if
(
intg1x
)
{
int
i
=
dig2bytes
[
intg1x
];
dec1
x
=
(
*
buf1
++
%
powers10
[
intg1x
])
^
mask
;
switch
(
i
)
{
case
1
:
mi_int1store
(
to
,
x
);
break
;
case
2
:
mi_int2store
(
to
,
x
);
break
;
case
3
:
mi_int3store
(
to
,
x
);
break
;
case
4
:
mi_int4store
(
to
,
x
);
break
;
default:
DBUG_ASSERT
(
0
);
}
to
+=
i
;
}
/* intg1+frac1 part */
for
(
stop1
=
buf1
+
intg1
+
frac1
;
buf1
<
stop1
;
to
+=
sizeof
(
dec1
))
{
dec1
x
=*
buf1
++
^
mask
;
DBUG_ASSERT
(
sizeof
(
dec1
)
==
4
);
mi_int4store
(
to
,
x
);
}
/* frac1x part */
if
(
frac1x
)
{
int
i
=
dig2bytes
[
frac1x
];
dec1
x
=
(
*
buf1
/
powers10
[
DIG_PER_DEC1
-
frac1x
])
^
mask
;
switch
(
i
)
{
case
1
:
mi_int1store
(
to
,
x
);
break
;
case
2
:
mi_int2store
(
to
,
x
);
break
;
case
3
:
mi_int3store
(
to
,
x
);
break
;
case
4
:
mi_int4store
(
to
,
x
);
break
;
default:
DBUG_ASSERT
(
0
);
}
to
+=
i
;
}
if
(
fsize0
>
fsize1
)
{
while
(
fsize0
--
>
fsize1
)
*
to
++=
(
uchar
)
mask
;
}
return
error
;
}
/*
Restores decimal from its binary fixed-length representation
SYNOPSIS
bin2decimal()
from - value to convert
to - result
precision/scale - see decimal_bin_size() below
NOTE
see decimal2bin()
the buffer is assumed to be of the size decimal_bin_size(precision, scale)
RETURN VALUE
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
*/
int
bin2decimal
(
char
*
from
,
decimal
*
to
,
int
precision
,
int
scale
)
{
int
error
=
E_DEC_OK
,
intg
=
precision
-
scale
,
intg0
=
intg
/
DIG_PER_DEC1
,
frac0
=
scale
/
DIG_PER_DEC1
,
intg0x
=
intg
-
intg0
*
DIG_PER_DEC1
,
frac0x
=
scale
-
frac0
*
DIG_PER_DEC1
,
intg1
=
intg0
+
(
intg0x
>
0
),
frac1
=
frac0
+
(
frac0x
>
0
);
dec1
*
buf
=
to
->
buf
,
mask
=
(
*
from
<
0
)
?
-
1
:
0
;
char
*
stop
;
FIX_INTG_FRAC_ERROR
(
to
->
len
,
intg1
,
frac1
,
error
);
if
(
unlikely
(
error
))
{
if
(
intg1
<
intg0
+
(
intg0x
>
0
))
{
from
+=
dig2bytes
[
intg0x
]
+
sizeof
(
dec1
)
*
(
intg0
-
intg1
);
frac0
=
frac0x
=
intg0x
=
0
;
intg0
=
intg1
;
}
else
{
frac0x
=
0
;
frac0
=
frac1
;
}
}
to
->
sign
=
(
mask
!=
0
);
to
->
intg
=
intg0
*
DIG_PER_DEC1
+
intg0x
;
to
->
frac
=
frac0
*
DIG_PER_DEC1
+
frac0x
;
if
(
intg0x
)
{
int
i
=
dig2bytes
[
intg0x
];
dec1
x
;
switch
(
i
)
{
case
1
:
x
=
mi_sint1korr
(
from
);
break
;
case
2
:
x
=
mi_sint2korr
(
from
);
break
;
case
3
:
x
=
mi_sint3korr
(
from
);
break
;
case
4
:
x
=
mi_sint4korr
(
from
);
break
;
default:
DBUG_ASSERT
(
0
);
}
from
+=
i
;
*
buf
=
x
^
mask
;
if
(
buf
>
to
->
buf
||
*
buf
!=
0
)
buf
++
;
else
to
->
intg
-=
intg0x
;
}
for
(
stop
=
from
+
intg0
*
sizeof
(
dec1
);
from
<
stop
;
from
+=
sizeof
(
dec1
))
{
DBUG_ASSERT
(
sizeof
(
dec1
)
==
4
);
*
buf
=
mi_sint4korr
(
from
)
^
mask
;
if
(
buf
>
to
->
buf
||
*
buf
!=
0
)
buf
++
;
else
to
->
intg
-=
DIG_PER_DEC1
;
}
DBUG_ASSERT
(
to
->
intg
>=
0
);
for
(
stop
=
from
+
frac0
*
sizeof
(
dec1
);
from
<
stop
;
from
+=
sizeof
(
dec1
))
{
DBUG_ASSERT
(
sizeof
(
dec1
)
==
4
);
*
buf
=
mi_sint4korr
(
from
)
^
mask
;
buf
++
;
}
if
(
frac0x
)
{
int
i
=
dig2bytes
[
frac0x
];
dec1
x
;
switch
(
i
)
{
case
1
:
x
=
mi_sint1korr
(
from
);
break
;
case
2
:
x
=
mi_sint2korr
(
from
);
break
;
case
3
:
x
=
mi_sint3korr
(
from
);
break
;
case
4
:
x
=
mi_sint4korr
(
from
);
break
;
default:
DBUG_ASSERT
(
0
);
}
*
buf
=
(
x
^
mask
)
*
powers10
[
DIG_PER_DEC1
-
frac0x
];
buf
++
;
}
return
error
;
}
/*
Returns the size of array to hold a decimal with given precision and scale
RETURN VALUE
size in dec1
(multiply by sizeof(dec1) to get the size if bytes)
*/
int
decimal_size
(
int
precision
,
int
scale
)
{
DBUG_ASSERT
(
scale
>=
0
&&
precision
>
0
&&
scale
<=
precision
);
return
ROUND_UP
(
precision
-
scale
)
+
ROUND_UP
(
scale
);
}
/*
Returns the size of array to hold a binary representation of a decimal
RETURN VALUE
size in bytes
*/
int
decimal_bin_size
(
int
precision
,
int
scale
)
{
int
intg
=
precision
-
scale
,
intg0
=
intg
/
DIG_PER_DEC1
,
frac0
=
scale
/
DIG_PER_DEC1
,
intg0x
=
intg
-
intg0
*
DIG_PER_DEC1
,
frac0x
=
scale
-
frac0
*
DIG_PER_DEC1
;
DBUG_ASSERT
(
scale
>=
0
&&
precision
>
0
&&
scale
<=
precision
);
return
intg0
*
sizeof
(
dec1
)
+
dig2bytes
[
intg0x
]
+
frac0
*
sizeof
(
dec1
)
+
dig2bytes
[
frac0x
];
}
/*
/*
Rounds the decimal to "scale" digits
Rounds the decimal to "scale" digits
...
@@ -538,7 +782,7 @@ int decimal2longlong(decimal *from, longlong *to)
...
@@ -538,7 +782,7 @@ int decimal2longlong(decimal *from, longlong *to)
int
decimal_round
(
decimal
*
dec
,
int
scale
,
dec_round_mode
mode
)
int
decimal_round
(
decimal
*
dec
,
int
scale
,
dec_round_mode
mode
)
{
{
int
frac0
=
ROUND_UP
(
scale
),
frac1
=
ROUND_UP
(
dec
->
frac
),
int
frac0
=
ROUND_UP
(
scale
),
frac1
=
ROUND_UP
(
dec
->
frac
),
intg0
=
ROUND_UP
(
dec
->
intg
),
error
=
E_DEC_OK
,
pos
,
len
=
dec
->
len
;
intg0
=
ROUND_UP
(
dec
->
intg
),
error
=
E_DEC_OK
,
len
=
dec
->
len
;
dec1
*
buf
=
dec
->
buf
,
x
,
y
,
carry
=
0
;
dec1
*
buf
=
dec
->
buf
,
x
,
y
,
carry
=
0
;
DBUG_ASSERT
(
intg0
+
frac1
<=
len
);
DBUG_ASSERT
(
intg0
+
frac1
<=
len
);
...
@@ -659,18 +903,19 @@ int decimal_result_size(decimal *from1, decimal *from2, char op, int param)
...
@@ -659,18 +903,19 @@ int decimal_result_size(decimal *from1, decimal *from2, char op, int param)
}
}
case
'*'
:
case
'*'
:
return
ROUND_UP
(
from1
->
intg
+
from2
->
intg
)
+
return
ROUND_UP
(
from1
->
intg
+
from2
->
intg
)
+
ROUND_UP
(
from1
->
frac
+
from2
->
frac
);
ROUND_UP
(
from1
->
frac
)
+
ROUND_UP
(
from2
->
frac
);
case
'/'
:
case
'/'
:
return
ROUND_UP
(
from1
->
intg
+
from2
->
intg
+
1
+
from1
->
frac
+
from2
->
frac
+
param
);
return
ROUND_UP
(
from1
->
intg
+
from2
->
intg
+
1
+
from1
->
frac
+
from2
->
frac
+
param
);
default:
DBUG_ASSERT
(
0
);
default:
DBUG_ASSERT
(
0
);
}
}
return
-
1
;
/* shut up the warning */
}
}
static
int
do_add
(
decimal
*
from1
,
decimal
*
from2
,
decimal
*
to
)
static
int
do_add
(
decimal
*
from1
,
decimal
*
from2
,
decimal
*
to
)
{
{
int
intg1
=
ROUND_UP
(
from1
->
intg
),
intg2
=
ROUND_UP
(
from2
->
intg
),
int
intg1
=
ROUND_UP
(
from1
->
intg
),
intg2
=
ROUND_UP
(
from2
->
intg
),
frac1
=
ROUND_UP
(
from1
->
frac
),
frac2
=
ROUND_UP
(
from2
->
frac
),
frac1
=
ROUND_UP
(
from1
->
frac
),
frac2
=
ROUND_UP
(
from2
->
frac
),
frac0
=
max
(
frac1
,
frac2
),
intg0
=
max
(
intg1
,
intg2
),
error
,
i
;
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
;
/* is there a need for extra word because of carry ? */
/* is there a need for extra word because of carry ? */
...
@@ -743,8 +988,8 @@ static int do_sub(decimal *from1, decimal *from2, decimal *to)
...
@@ -743,8 +988,8 @@ static int do_sub(decimal *from1, decimal *from2, decimal *to)
{
{
int
intg1
=
ROUND_UP
(
from1
->
intg
),
intg2
=
ROUND_UP
(
from2
->
intg
),
int
intg1
=
ROUND_UP
(
from1
->
intg
),
intg2
=
ROUND_UP
(
from2
->
intg
),
frac1
=
ROUND_UP
(
from1
->
frac
),
frac2
=
ROUND_UP
(
from2
->
frac
);
frac1
=
ROUND_UP
(
from1
->
frac
),
frac2
=
ROUND_UP
(
from2
->
frac
);
int
frac0
=
max
(
frac1
,
frac2
),
error
,
i
;
int
frac0
=
max
(
frac1
,
frac2
),
error
;
dec1
*
buf1
,
*
buf2
,
*
buf0
,
*
stop1
,
*
stop2
,
*
start1
,
*
start2
,
x
,
carry
=
0
;
dec1
*
buf1
,
*
buf2
,
*
buf0
,
*
stop1
,
*
stop2
,
*
start1
,
*
start2
,
carry
=
0
;
to
->
sign
=
from1
->
sign
;
to
->
sign
=
from1
->
sign
;
...
@@ -1333,6 +1578,27 @@ void test_d2f(char *s)
...
@@ -1333,6 +1578,27 @@ void test_d2f(char *s)
printf
(
"%-40s => res=%d %.*g
\n
"
,
s1
,
res
,
a
.
intg
+
a
.
frac
,
x
);
printf
(
"%-40s => res=%d %.*g
\n
"
,
s1
,
res
,
a
.
intg
+
a
.
frac
,
x
);
}
}
void
test_d2b2d
(
char
*
str
,
int
p
,
int
s
)
{
char
s1
[
100
],
buf
[
100
];
double
x
;
int
res
,
i
,
size
=
decimal_bin_size
(
p
,
s
);
sprintf
(
s1
,
"'%s'"
,
str
);
string2decimal
(
str
,
&
a
,
0
);
res
=
decimal2bin
(
&
a
,
buf
,
p
,
s
);
printf
(
"%-31s {%2d, %2d} => res=%d size=%-2d "
,
s1
,
p
,
s
,
res
,
size
);
if
(
full
)
{
printf
(
"0x"
);
for
(
i
=
0
;
i
<
size
;
i
++
)
printf
(
"%02x"
,
((
uchar
*
)
buf
)[
i
]);
}
res
=
bin2decimal
(
buf
,
&
a
,
p
,
s
);
printf
(
" => res=%d "
,
res
);
print_decimal
(
&
a
);
printf
(
"
\n
"
);
}
void
test_f2d
(
double
from
)
void
test_f2d
(
double
from
)
{
{
int
res
;
int
res
;
...
@@ -1622,6 +1888,17 @@ main()
...
@@ -1622,6 +1888,17 @@ main()
test_md
(
"-234.567"
,
"10.555"
);
test_md
(
"-234.567"
,
"10.555"
);
test_md
(
"234.567"
,
"-10.555"
);
test_md
(
"234.567"
,
"-10.555"
);
printf
(
"==== decimal2bin/bin2decimal ====
\n
"
);
test_d2b2d
(
"12345"
,
5
,
0
);
test_d2b2d
(
"12345"
,
10
,
3
);
test_d2b2d
(
"123.45"
,
10
,
3
);
test_d2b2d
(
"-123.45"
,
20
,
10
);
test_d2b2d
(
".00012345000098765"
,
15
,
14
);
test_d2b2d
(
".00012345000098765"
,
22
,
20
);
test_d2b2d
(
".12345000098765"
,
30
,
20
);
test_d2b2d
(
"-.000000012345000098765"
,
30
,
20
);
test_d2b2d
(
"1234500009876.5"
,
30
,
5
);
return
0
;
return
0
;
}
}
#endif
#endif
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