modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/misc/ieee754.c (about)

     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.
    10  **
    11  ******************************************************************************
    12  **
    13  ** This SQLite extension implements functions for the exact display
    14  ** and input of IEEE754 Binary64 floating-point numbers.
    15  **
    16  **   ieee754(X)
    17  **   ieee754(Y,Z)
    18  **
    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).
    22  **
    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).
    26  **
    27  ** Examples:
    28  **
    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
    33  */
    34  #include "sqlite3ext.h"
    35  SQLITE_EXTENSION_INIT1
    36  #include <assert.h>
    37  #include <string.h>
    38  
    39  /*
    40  ** Implementation of the ieee754() function
    41  */
    42  static void ieee754func(
    43    sqlite3_context *context,
    44    int argc,
    45    sqlite3_value **argv
    46  ){
    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;
    61      }
    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++;
    73        }
    74        if( isNeg ) m = -m;
    75      }
    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;
    92      }
    93      while( (m>>32)&0xffe00000 ){
    94        m >>= 1;
    95        e++;
    96      }
    97      while( m!=0 && ((m>>32)&0xfff00000)==0 ){
    98        m <<= 1;
    99        e--;
   100      }
   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);
   109    }
   110  }
   111  
   112  
   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
   120  ){
   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);
   129    }
   130    return rc;
   131  }