summaryrefslogtreecommitdiff
path: root/strings/decimal.c
diff options
context:
space:
mode:
authorunknown <serg@serg.mylan>2005-02-20 17:25:22 +0100
committerunknown <serg@serg.mylan>2005-02-20 17:25:22 +0100
commit10db96fe432886f15bc489b6f27540b6fa3463a7 (patch)
treed649bf2e74e1fa2b14ca98b52fa4e6d5ea69d8bc /strings/decimal.c
parent1683fc96734d449980b7489bbf2afad63c4ae853 (diff)
downloadmariadb-git-10db96fe432886f15bc489b6f27540b6fa3463a7.tar.gz
decimal format documented
Diffstat (limited to 'strings/decimal.c')
-rw-r--r--strings/decimal.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/strings/decimal.c b/strings/decimal.c
index 28c6ace658f..e6d2d9b14dd 100644
--- a/strings/decimal.c
+++ b/strings/decimal.c
@@ -107,6 +107,21 @@
#include <m_string.h>
#include <decimal.h>
+/*
+ Internally decimal numbers are stored base 10^9 (see DIG_BASE below)
+ So one "decimal_digit" is
+
+ 0 < decimal_digit <= DIG_MAX < DIG_BASE
+
+ in the struct st_decimal:
+
+ intg is the number of *decimal* digits (NOT number of decimal_digit's !)
+ before the point
+ frac - number of decimal digits after the point
+ buf is an array of decimal_digit's
+ len is the length of buf (length of allocated space) in decimal_digit's,
+ not in bytes
+*/
typedef decimal_digit dec1;
typedef longlong dec2;
@@ -1073,6 +1088,68 @@ int decimal2longlong(decimal *from, longlong *to)
RETURN VALUE
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
+
+ DESCRIPTION
+ for storage decimal numbers are converted to the "binary" format.
+
+ This format has the following properties:
+ 1. length of the binary representation depends on the {precision, scale}
+ as provided by the caller and NOT on the intg/frac of the decimal to
+ convert.
+ 2. binary representations of the same {precision, scale} can be compared
+ with memcmp - with the same result as decimal_cmp() of the original
+ decimals (not taking into account possible precision loss during
+ conversion).
+
+ This binary format is as follows:
+ 1. First the number is converted to have a requested precision and scale.
+ 2. Every full DIG_PER_DEC1 digits of intg part are stored in 4 bytes
+ as is
+ 3. The first intg % DIG_PER_DEC1 digits are stored in the reduced
+ number of bytes (enough bytes to store this number of digits -
+ see dig2bytes)
+ 4. same for frac - full decimal_digit's are stored as is,
+ the last frac % DIG_PER_DEC1 digits - in the reduced number of bytes.
+ 5. If the number is negative - every byte is inversed.
+ 5. The very first bit of the resulting byte array is inverted (because
+ memcmp compares unsigned bytes, see property 2 above)
+
+ Example:
+
+ 1234567890.1234
+
+ internally is represented as 3 decimal_digit's
+
+ 1 234567890 123400000
+
+ (assuming we want a binary representation with precision=14, scale=4)
+ in hex it's
+
+ 00-00-00-01 0D-FB-38-D2 07-5A-EF-40
+
+ now, middle decimal_digit is full - it stores 9 decimal digits. It goes
+ into binary representation as is:
+
+
+ ........... 0D-FB-38-D2 ............
+
+ First decimal_digit has only one decimal digit. We can store one digit in
+ one byte, no need to waste four:
+
+ 01 0D-FB-38-D2 ............
+
+ now, last digit. It's 123400000. We can store 1234 in two bytes:
+
+ 01 0D-FB-38-D2 04-D2
+
+ So, we've packed 12 bytes number in 7 bytes.
+ And now we invert the highest bit to get the final result:
+
+ 81 0D FB 38 D2 04 D2
+
+ And for -1234567890.1234 it would be
+
+ 7E F2 04 37 2D FB 2D
*/
int decimal2bin(decimal *from, char *to, int precision, int frac)
{