Artifact Content
Not logged in

Artifact b9c7a7ecb2f37381ef67e263f3b940b2eb77c439:

A common internal format is used to represent all numbers in SQLite4.
This format is able to losslessly represent all integer values from 
the maximum unsigned 64-bit integer down to the smallest (most negative)
signed 64-bit integer.  The format is also able to represent floating
point numbers spanning a greater range and precision than IEEE 754

SQLite4 makes no distinction between integer and floating point numbers.
It does, however, distinguish between exact and approximate numbers.  In
C/C++, integers are exact and floating point numbers are approximate.
But this is not necessarily true of SQLite4.  Floating point numbers can
be exact in SQLite4.  Integers that can be represented in 64-bits are 
always exact in SQLite4 but larger integers might be approximate.

The SQLite4 numeric format is for internal use.  Numbers can be translated
between integers or doubles for input and output.  The on-disk storage
space required for SQLite4 numbers varies from between 1 and 10 bytes, 
depending on the magnitude and the number of significant digits in the

The SQLite4 numeric format is a decimal floating point format.  
The significant is a 18-digit decimal number, represented internally as
an unsigned 64-bit integer.  A base-10 exponent with 3-digits of precision
is used, represented internally as an unsigned 11-bit integer.  Both the
significant and the exponent can be signed, of course.  This gives a
maximum value of:

  999,999,999,999,999,999 e 999

Infinities are represented by any non-zero number with an exponent of
1000 or more.  A zero significant with an exponent of 1000 or more
is a NaN.

The IEEE 754 decimal representation was considered as the format for SQLite4
but was rejected as having insufficient precision and being overly complex.

Because a base-10 exponent is used, there are no round-off error problems
when converting the fractional part between decimal and the internal 
representation.  Furthermore, this format can exactly represent any 
signed 64-bit integer, which IEEE 754 binary64 cannot do.  Any decimal
floating point number with an 3-digit exponent and 18 or fewer significant
digits can be represented exactly in this representation.

The on-disk storage format for numbers uses between 1 and 13 bytes of
space, depending on the magnitude of the number.  Numbers with fewer
significant digits require less storage than numbers with more significant
digits.  There are two encoding format, one for keys (that must sort in
lexicographical order) and another for data.

A proposed interface to decimal math routines is as follows:

   typedef struct sqlite4_num sqlite4_num;
   struct sqlite4_num {
     unsigned char sign;     /* Sign of the overall value */
     unsigned char approx;   /* True if the value is approximate */
     signed short e;         /* The exponent. */
     sqlite4_uint64 m;       /* The significant */
   sqlite4_num sqlite4_num_add(sqlite4_num, sqlite4_num);
   sqlite4_num sqlite4_num_sub(sqlite4_num, sqlite4_num);
   sqlite4_num sqlite4_num_mul(sqlite4_num, sqlite4_num);
   sqlite4_num sqlite4_num_div(sqlite4_num, sqlite4_num);
   int sqlite4_num_isinf(sqlite4_num);
   int sqlite4_num_isnan(sqlite4_num);
   sqlite4_num sqlite4_num_round(sqltie4_num, int iDigit);
   int sqlite4_num_compare(sqlite4_num, sqlite4_num);
   sqlite4_num sqlite4_num_from_string(const char*, int n, int *pUsed);
   sqlite4_num sqlite4_num_from_int64(sqlite4_int64);
   sqlite4_num sqlite4_num_from_double(double);
   int sqlite4_num_to_int32(sqlite4_num, int*);
   int sqlite4_num_to_int64(sqlite4_num, sqlite4_int64*);
   double sqlite4_num_to_double(sqlite4_num);

Use the sqlite4_*printf() routines to render sqlite4_num objects
as decimal.