4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
7 ** May you do good and not evil.
8 ** May you find forgiveness for yourself and forgive others.
9 ** May you share freely, never taking more than you give.
11 ******************************************************************************
13 ** This SQLite extension implements functions for the exact display
14 ** and input of IEEE754 Binary64 floating-point numbers.
19 ** In the first form, the value X should be a floating-point number.
20 ** The function will return a string of the form 'ieee754(Y,Z)' where
21 ** Y and Z are integers such that X==Y*pow(2,Z).
23 ** In the second form, Y and Z are integers which are the mantissa and
24 ** base-2 exponent of a new floating point number. The function returns
25 ** a floating-point value equal to Y*pow(2,Z).
29 ** ieee754(2.0) -> 'ieee754(2,0)'
30 ** ieee754(45.25) -> 'ieee754(181,-2)'
31 ** ieee754(2, 0) -> 2.0
32 ** ieee754(181, -2) -> 45.25
34 ** Two additional functions break apart the one-argument ieee754()
35 ** result into separate integer values:
37 ** ieee754_mantissa(45.25) -> 181
38 ** ieee754_exponent(45.25) -> -2
40 ** These functions convert binary64 numbers into blobs and back again.
42 ** ieee754_from_blob(x'3ff0000000000000') -> 1.0
43 ** ieee754_to_blob(1.0) -> x'3ff0000000000000'
45 ** In all single-argument functions, if the argument is an 8-byte blob
46 ** then that blob is interpreted as a big-endian binary64 value.
49 ** EXACT DECIMAL REPRESENTATION OF BINARY64 VALUES
50 ** -----------------------------------------------
52 ** This extension in combination with the separate 'decimal' extension
53 ** can be used to compute the exact decimal representation of binary64
54 ** values. To begin, first compute a table of exponent values:
56 ** CREATE TABLE pow2(x INTEGER PRIMARY KEY, v TEXT);
57 ** WITH RECURSIVE c(x,v) AS (
60 ** SELECT x+1, decimal_mul(v,'2') FROM c WHERE x+1<=971
61 ** ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
62 ** WITH RECURSIVE c(x,v) AS (
65 ** SELECT x-1, decimal_mul(v,'0.5') FROM c WHERE x-1>=-1075
66 ** ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
68 ** Then, to compute the exact decimal representation of a floating
69 ** point value (the value 47.49 is used in the example) do:
71 ** WITH c(n) AS (VALUES(47.49))
72 ** ---------------^^^^^---- Replace with whatever you want
73 ** SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v)
74 ** FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n);
76 ** Here is a query to show various boundry values for the binary64
79 ** WITH c(name,bin) AS (VALUES
80 ** ('minimum positive value', x'0000000000000001'),
81 ** ('maximum subnormal value', x'000fffffffffffff'),
82 ** ('mininum positive nornal value', x'0010000000000000'),
83 ** ('maximum value', x'7fefffffffffffff'))
84 ** SELECT c.name, decimal_mul(ieee754_mantissa(c.bin),pow2.v)
85 ** FROM pow2, c WHERE pow2.x=ieee754_exponent(c.bin);
88 #include "sqlite3ext.h"
89 SQLITE_EXTENSION_INIT1
93 /* Mark a function parameter as unused, to suppress nuisance compiler
95 #ifndef UNUSED_PARAMETER
96 # define UNUSED_PARAMETER(X) (void)(X)
100 ** Implementation of the ieee754() function
102 static void ieee754func(
103 sqlite3_context
*context
,
113 assert( sizeof(m
)==sizeof(r
) );
114 if( sqlite3_value_type(argv
[0])==SQLITE_BLOB
115 && sqlite3_value_bytes(argv
[0])==sizeof(r
)
117 const unsigned char *x
= sqlite3_value_blob(argv
[0]);
119 sqlite3_uint64 v
= 0;
120 for(i
=0; i
<sizeof(r
); i
++){
123 memcpy(&r
, &v
, sizeof(r
));
125 r
= sqlite3_value_double(argv
[0]);
133 memcpy(&a
,&r
,sizeof(a
));
139 m
= a
& ((((sqlite3_int64
)1)<<52)-1);
143 m
|= ((sqlite3_int64
)1)<<52;
145 while( e
<1075 && m
>0 && (m
&1)==0 ){
151 switch( *(int*)sqlite3_user_data(context
) ){
153 sqlite3_snprintf(sizeof(zResult
), zResult
, "ieee754(%lld,%d)",
155 sqlite3_result_text(context
, zResult
, -1, SQLITE_TRANSIENT
);
158 sqlite3_result_int64(context
, m
);
161 sqlite3_result_int(context
, e
-1075);
165 sqlite3_int64 m
, e
, a
;
168 m
= sqlite3_value_int64(argv
[0]);
169 e
= sqlite3_value_int64(argv
[1]);
171 /* Limit the range of e. Ticket 22dea1cfdb9151e4 2021-03-02 */
174 }else if( e
<-10000 ){
182 }else if( m
==0 && e
>-1000 && e
<1000 ){
183 sqlite3_result_double(context
, 0.0);
186 while( (m
>>32)&0xffe00000 ){
190 while( m
!=0 && ((m
>>32)&0xfff00000)==0 ){
206 a
= m
& ((((sqlite3_int64
)1)<<52)-1);
208 if( isNeg
) a
|= ((sqlite3_uint64
)1)<<63;
209 memcpy(&r
, &a
, sizeof(r
));
210 sqlite3_result_double(context
, r
);
215 ** Functions to convert between blobs and floats.
217 static void ieee754func_from_blob(
218 sqlite3_context
*context
,
222 UNUSED_PARAMETER(argc
);
223 if( sqlite3_value_type(argv
[0])==SQLITE_BLOB
224 && sqlite3_value_bytes(argv
[0])==sizeof(double)
227 const unsigned char *x
= sqlite3_value_blob(argv
[0]);
229 sqlite3_uint64 v
= 0;
230 for(i
=0; i
<sizeof(r
); i
++){
233 memcpy(&r
, &v
, sizeof(r
));
234 sqlite3_result_double(context
, r
);
237 static void ieee754func_to_blob(
238 sqlite3_context
*context
,
242 UNUSED_PARAMETER(argc
);
243 if( sqlite3_value_type(argv
[0])==SQLITE_FLOAT
244 || sqlite3_value_type(argv
[0])==SQLITE_INTEGER
246 double r
= sqlite3_value_double(argv
[0]);
248 unsigned char a
[sizeof(r
)];
250 memcpy(&v
, &r
, sizeof(r
));
251 for(i
=1; i
<=sizeof(r
); i
++){
252 a
[sizeof(r
)-i
] = v
&0xff;
255 sqlite3_result_blob(context
, a
, sizeof(r
), SQLITE_TRANSIENT
);
261 __declspec(dllexport
)
263 int sqlite3_ieee_init(
266 const sqlite3_api_routines
*pApi
268 static const struct {
272 void (*xFunc
)(sqlite3_context
*,int,sqlite3_value
**);
274 { "ieee754", 1, 0, ieee754func
},
275 { "ieee754", 2, 0, ieee754func
},
276 { "ieee754_mantissa", 1, 1, ieee754func
},
277 { "ieee754_exponent", 1, 2, ieee754func
},
278 { "ieee754_to_blob", 1, 0, ieee754func_to_blob
},
279 { "ieee754_from_blob", 1, 0, ieee754func_from_blob
},
284 SQLITE_EXTENSION_INIT2(pApi
);
285 (void)pzErrMsg
; /* Unused parameter */
286 for(i
=0; i
<sizeof(aFunc
)/sizeof(aFunc
[0]) && rc
==SQLITE_OK
; i
++){
287 rc
= sqlite3_create_function(db
, aFunc
[i
].zFName
, aFunc
[i
].nArg
,
288 SQLITE_UTF8
|SQLITE_INNOCUOUS
,
289 (void*)&aFunc
[i
].iAux
,
290 aFunc
[i
].xFunc
, 0, 0);