Enhance the command-line completion extension to return the names of
[sqlite.git] / ext / misc / ieee754.c
blob20c5e6143347ca712183145a3ea7f23a4288fc72
1 /*
2 ** 2013-04-17
3 **
4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
6 **
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.
16 ** ieee754(X)
17 ** ieee754(Y,Z)
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).
27 ** Examples:
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 #include "sqlite3ext.h"
35 SQLITE_EXTENSION_INIT1
36 #include <assert.h>
37 #include <string.h>
40 ** Implementation of the ieee754() function
42 static void ieee754func(
43 sqlite3_context *context,
44 int argc,
45 sqlite3_value **argv
47 if( argc==1 ){
48 sqlite3_int64 m, a;
49 double r;
50 int e;
51 int isNeg;
52 char zResult[100];
53 assert( sizeof(m)==sizeof(r) );
54 if( sqlite3_value_type(argv[0])!=SQLITE_FLOAT ) return;
55 r = sqlite3_value_double(argv[0]);
56 if( r<0.0 ){
57 isNeg = 1;
58 r = -r;
59 }else{
60 isNeg = 0;
62 memcpy(&a,&r,sizeof(a));
63 if( a==0 ){
64 e = 0;
65 m = 0;
66 }else{
67 e = a>>52;
68 m = a & ((((sqlite3_int64)1)<<52)-1);
69 m |= ((sqlite3_int64)1)<<52;
70 while( e<1075 && m>0 && (m&1)==0 ){
71 m >>= 1;
72 e++;
74 if( isNeg ) m = -m;
76 sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)",
77 m, e-1075);
78 sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT);
79 }else if( argc==2 ){
80 sqlite3_int64 m, e, a;
81 double r;
82 int isNeg = 0;
83 m = sqlite3_value_int64(argv[0]);
84 e = sqlite3_value_int64(argv[1]);
85 if( m<0 ){
86 isNeg = 1;
87 m = -m;
88 if( m<0 ) return;
89 }else if( m==0 && e>1000 && e<1000 ){
90 sqlite3_result_double(context, 0.0);
91 return;
93 while( (m>>32)&0xffe00000 ){
94 m >>= 1;
95 e++;
97 while( m!=0 && ((m>>32)&0xfff00000)==0 ){
98 m <<= 1;
99 e--;
101 e += 1075;
102 if( e<0 ) e = m = 0;
103 if( e>0x7ff ) e = 0x7ff;
104 a = m & ((((sqlite3_int64)1)<<52)-1);
105 a |= e<<52;
106 if( isNeg ) a |= ((sqlite3_uint64)1)<<63;
107 memcpy(&r, &a, sizeof(r));
108 sqlite3_result_double(context, r);
113 #ifdef _WIN32
114 __declspec(dllexport)
115 #endif
116 int sqlite3_ieee_init(
117 sqlite3 *db,
118 char **pzErrMsg,
119 const sqlite3_api_routines *pApi
121 int rc = SQLITE_OK;
122 SQLITE_EXTENSION_INIT2(pApi);
123 (void)pzErrMsg; /* Unused parameter */
124 rc = sqlite3_create_function(db, "ieee754", 1, SQLITE_UTF8, 0,
125 ieee754func, 0, 0);
126 if( rc==SQLITE_OK ){
127 rc = sqlite3_create_function(db, "ieee754", 2, SQLITE_UTF8, 0,
128 ieee754func, 0, 0);
130 return rc;