From c8c4a6a284eb1b9393f84f4c99e235748981b01c Mon Sep 17 00:00:00 2001 From: furo Date: Sun, 14 Nov 2021 23:14:27 +0100 Subject: [PATCH] Windows DLLS LMAO --- math-func.c | 1947 +++++++++++++++++++++++++++++++++++++++++++++++++ math-func.dll | Bin 0 -> 74392 bytes 2 files changed, 1947 insertions(+) create mode 100644 math-func.c create mode 100644 math-func.dll diff --git a/math-func.c b/math-func.c new file mode 100644 index 0000000..2bdd194 --- /dev/null +++ b/math-func.c @@ -0,0 +1,1947 @@ +/* +This library will provide common mathematical and string functions in +SQL queries using the operating system libraries or provided +definitions. It includes the following functions: + +Math: acos, asin, atan, atn2, atan2, acosh, asinh, atanh, difference, +degrees, radians, cos, sin, tan, cot, cosh, sinh, tanh, coth, exp, +log, log10, power, sign, sqrt, square, ceil, floor, pi. + +String: replicate, charindex, leftstr, rightstr, ltrim, rtrim, trim, +replace, reverse, proper, padl, padr, padc, strfilter. + +Aggregate: stdev, variance, mode, median, lower_quartile, +upper_quartile. + +The string functions ltrim, rtrim, trim, replace are included in +recent versions of SQLite and so by default do not build. + +Compilation instructions: + Compile this C source file into a dynamic library as follows: + * Linux: + gcc -fPIC -lm -shared extension-functions.c -o libsqlitefunctions.so + * Mac OS X: + gcc -fno-common -dynamiclib extension-functions.c -o libsqlitefunctions.dylib + (You may need to add flags + -I /opt/local/include/ -L/opt/local/lib -lsqlite3 + if your sqlite3 is installed from Mac ports, or + -I /sw/include/ -L/sw/lib -lsqlite3 + if installed with Fink.) + * Windows: + 1. Install MinGW (http://www.mingw.org/) and you will get the gcc + (gnu compiler collection) + 2. add the path to your path variable (isn't done during the + installation!) + 3. compile: + gcc -shared -I "path" -o libsqlitefunctions.so extension-functions.c + (path = path of sqlite3ext.h; i.e. C:\programs\sqlite) + +Usage instructions for applications calling the sqlite3 API functions: + In your application, call sqlite3_enable_load_extension(db,1) to + allow loading external libraries. Then load the library libsqlitefunctions + using sqlite3_load_extension; the third argument should be 0. + See http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions. + Select statements may now use these functions, as in + SELECT cos(radians(inclination)) FROM satsum WHERE satnum = 25544; + +Usage instructions for the sqlite3 program: + If the program is built so that loading extensions is permitted, + the following will work: + sqlite> SELECT load_extension('./libsqlitefunctions.so'); + sqlite> select cos(radians(45)); + 0.707106781186548 + Note: Loading extensions is by default prohibited as a + security measure; see "Security Considerations" in + http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions. + If the sqlite3 program and library are built this + way, you cannot use these functions from the program, you + must write your own program using the sqlite3 API, and call + sqlite3_enable_load_extension as described above, or else + rebuilt the sqlite3 program to allow loadable extensions. + +Alterations: +The instructions are for Linux, Mac OS X, and Windows; users of other +OSes may need to modify this procedure. In particular, if your math +library lacks one or more of the needed trig or log functions, comment +out the appropriate HAVE_ #define at the top of file. If you do not +wish to make a loadable module, comment out the define for +COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE. If you are using a +version of SQLite without the trim functions and replace, comment out +the HAVE_TRIM #define. + +Liam Healy + +History: +2010-01-06 Correct check for argc in squareFunc, and add Windows +compilation instructions. +2009-06-24 Correct check for argc in properFunc. +2008-09-14 Add check that memory was actually allocated after +sqlite3_malloc or sqlite3StrDup, call sqlite3_result_error_nomem if +not. Thanks to Robert Simpson. +2008-06-13 Change to instructions to indicate use of the math library +and that program might work. +2007-10-01 Minor clarification to instructions. +2007-09-29 Compilation as loadable module is optional with +COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE. +2007-09-28 Use sqlite3_extension_init and macros +SQLITE_EXTENSION_INIT1, SQLITE_EXTENSION_INIT2, so that it works with +sqlite3_load_extension. Thanks to Eric Higashino and Joe Wilson. +New instructions for Mac compilation. +2007-09-17 With help from Joe Wilson and Nuno Luca, made use of +external interfaces so that compilation is no longer dependent on +SQLite source code. Merged source, header, and README into a single +file. Added casts so that Mac will compile without warnings (unsigned +and signed char). +2007-09-05 Included some definitions from sqlite 3.3.13 so that this +will continue to work in newer versions of sqlite. Completed +description of functions available. +2007-03-27 Revised description. +2007-03-23 Small cleanup and a bug fix on the code. This was mainly +letting errno flag errors encountered in the math library and checking +the result, rather than pre-checking. This fixes a bug in power that +would cause an error if any non-positive number was raised to any +power. +2007-02-07 posted by Mikey C to sqlite mailing list. +Original code 2006 June 05 by relicoder. + +*/ + +//#include "config.h" + +#define COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE 1 +#define HAVE_ACOSH 1 +#define HAVE_ASINH 1 +#define HAVE_ATANH 1 +#define HAVE_SINH 1 +#define HAVE_COSH 1 +#define HAVE_TANH 1 +#define HAVE_LOG10 1 +#define HAVE_ISBLANK 1 +#define SQLITE_SOUNDEX 1 +#define HAVE_TRIM 1 /* LMH 2007-03-25 if sqlite has trim functions */ + +#ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE +#include "sqlite3ext.h" +SQLITE_EXTENSION_INIT1 +#else +#include "sqlite3.h" +#endif + +#include +/* relicoder */ +#include +#include +#include +#include /* LMH 2007-03-25 */ + +#include +#include + +#ifndef _MAP_H_ +#define _MAP_H_ + +#include + +/* +** Simple binary tree implementation to use in median, mode and quartile calculations +** Tree is not necessarily balanced. That would require something like red&black trees of AVL +*/ + +typedef int(*cmp_func)(const void *, const void *); +typedef void(*map_iterator)(void*, int64_t, void*); + +typedef struct node{ + struct node *l; + struct node *r; + void* data; + int64_t count; +} node; + +typedef struct map{ + node *base; + cmp_func cmp; + short free; +} map; + +/* +** creates a map given a comparison function +*/ +map map_make(cmp_func cmp); + +/* +** inserts the element e into map m +*/ +void map_insert(map *m, void *e); + +/* +** executes function iter over all elements in the map, in key increasing order +*/ +void map_iterate(map *m, map_iterator iter, void* p); + +/* +** frees all memory used by a map +*/ +void map_destroy(map *m); + +/* +** compares 2 integers +** to use with map_make +*/ +int int_cmp(const void *a, const void *b); + +/* +** compares 2 doubles +** to use with map_make +*/ +int double_cmp(const void *a, const void *b); + +#endif /* _MAP_H_ */ + +typedef uint8_t u8; +typedef uint16_t u16; +typedef int64_t i64; + +static char *sqlite3StrDup( const char *z ) { + char *res = sqlite3_malloc( strlen(z)+1 ); + return strcpy( res, z ); +} + +/* +** These are copied verbatim from fun.c so as to not have the names exported +*/ + +/* LMH from sqlite3 3.3.13 */ +/* +** This table maps from the first byte of a UTF-8 character to the number +** of trailing bytes expected. A value '4' indicates that the table key +** is not a legal first byte for a UTF-8 character. +*/ +static const u8 xtra_utf8_bytes[256] = { +/* 0xxxxxxx */ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* 10wwwwww */ +4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, +4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, +4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, +4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + +/* 110yyyyy */ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + +/* 1110zzzz */ +2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + +/* 11110yyy */ +3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, +}; + + +/* +** This table maps from the number of trailing bytes in a UTF-8 character +** to an integer constant that is effectively calculated for each character +** read by a naive implementation of a UTF-8 character reader. The code +** in the READ_UTF8 macro explains things best. +*/ +static const int xtra_utf8_bits[] = { + 0, + 12416, /* (0xC0 << 6) + (0x80) */ + 925824, /* (0xE0 << 12) + (0x80 << 6) + (0x80) */ + 63447168 /* (0xF0 << 18) + (0x80 << 12) + (0x80 << 6) + 0x80 */ +}; + +/* +** If a UTF-8 character contains N bytes extra bytes (N bytes follow +** the initial byte so that the total character length is N+1) then +** masking the character with utf8_mask[N] must produce a non-zero +** result. Otherwise, we have an (illegal) overlong encoding. +*/ +static const int utf_mask[] = { + 0x00000000, + 0xffffff80, + 0xfffff800, + 0xffff0000, +}; + +/* LMH salvaged from sqlite3 3.3.13 source code src/utf.c */ +#define READ_UTF8(zIn, c) { \ + int xtra; \ + c = *(zIn)++; \ + xtra = xtra_utf8_bytes[c]; \ + switch( xtra ){ \ + case 4: c = (int)0xFFFD; break; \ + case 3: c = (c<<6) + *(zIn)++; \ + case 2: c = (c<<6) + *(zIn)++; \ + case 1: c = (c<<6) + *(zIn)++; \ + c -= xtra_utf8_bits[xtra]; \ + if( (utf_mask[xtra]&c)==0 \ + || (c&0xFFFFF800)==0xD800 \ + || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ + } \ +} + +static int sqlite3ReadUtf8(const unsigned char *z){ + int c; + READ_UTF8(z, c); + return c; +} + +#define SKIP_UTF8(zIn) { \ + zIn += (xtra_utf8_bytes[*(u8 *)zIn] + 1); \ +} + +/* +** pZ is a UTF-8 encoded unicode string. If nByte is less than zero, +** return the number of unicode characters in pZ up to (but not including) +** the first 0x00 byte. If nByte is not less than zero, return the +** number of unicode characters in the first nByte of pZ (or up to +** the first 0x00, whichever comes first). +*/ +static int sqlite3Utf8CharLen(const char *z, int nByte){ + int r = 0; + const char *zTerm; + if( nByte>=0 ){ + zTerm = &z[nByte]; + }else{ + zTerm = (const char *)(-1); + } + assert( z<=zTerm ); + while( *z!=0 && z 0) ? 1: ( iVal < 0 ) ? -1: 0; + sqlite3_result_int64(context, iVal); + break; + } + case SQLITE_NULL: { + sqlite3_result_null(context); + break; + } + default: { + /* 2nd change below. Line for abs was: if( rVal<0 ) rVal = rVal * -1.0; */ + + rVal = sqlite3_value_double(argv[0]); + rVal = ( rVal > 0) ? 1: ( rVal < 0 ) ? -1: 0; + sqlite3_result_double(context, rVal); + break; + } + } +} + + +/* +** smallest integer value not less than argument +*/ +static void ceilFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + double rVal=0.0; + i64 iVal=0; + assert( argc==1 ); + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_INTEGER: { + i64 iVal = sqlite3_value_int64(argv[0]); + sqlite3_result_int64(context, iVal); + break; + } + case SQLITE_NULL: { + sqlite3_result_null(context); + break; + } + default: { + rVal = sqlite3_value_double(argv[0]); + sqlite3_result_int64(context, (i64) ceil(rVal)); + break; + } + } +} + +/* +** largest integer value not greater than argument +*/ +static void floorFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + double rVal=0.0; + i64 iVal=0; + assert( argc==1 ); + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_INTEGER: { + i64 iVal = sqlite3_value_int64(argv[0]); + sqlite3_result_int64(context, iVal); + break; + } + case SQLITE_NULL: { + sqlite3_result_null(context); + break; + } + default: { + rVal = sqlite3_value_double(argv[0]); + sqlite3_result_int64(context, (i64) floor(rVal)); + break; + } + } +} + +/* +** Given a string (s) in the first argument and an integer (n) in the second returns the +** string that constains s contatenated n times +*/ +static void replicateFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + unsigned char *z; /* input string */ + unsigned char *zo; /* result string */ + i64 iCount; /* times to repeat */ + i64 nLen; /* length of the input string (no multibyte considerations) */ + i64 nTLen; /* length of the result string (no multibyte considerations) */ + i64 i=0; + + if( argc!=2 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) + return; + + iCount = sqlite3_value_int64(argv[1]); + + if( iCount<0 ){ + sqlite3_result_error(context, "domain error", -1); + }else{ + + nLen = sqlite3_value_bytes(argv[0]); + nTLen = nLen*iCount; + z=sqlite3_malloc(nTLen+1); + zo=sqlite3_malloc(nLen+1); + if (!z || !zo){ + sqlite3_result_error_nomem(context); + if (z) sqlite3_free(z); + if (zo) sqlite3_free(zo); + return; + } + strcpy((char*)zo, (char*)sqlite3_value_text(argv[0])); + + for(i=0; i=n it's a NOP +** padl(NULL) = NULL +*/ +static void padlFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + i64 ilen; /* length to pad to */ + i64 zl; /* length of the input string (UTF-8 chars) */ + int i = 0; + const char *zi; /* input string */ + char *zo; /* output string */ + char *zt; + + assert( argc==2 ); + + if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ + sqlite3_result_null(context); + }else{ + zi = (char *)sqlite3_value_text(argv[0]); + ilen = sqlite3_value_int64(argv[1]); + /* check domain */ + if(ilen<0){ + sqlite3_result_error(context, "domain error", -1); + return; + } + zl = sqlite3Utf8CharLen(zi, -1); + if( zl>=ilen ){ + /* string is longer than the requested pad length, return the same string (dup it) */ + zo = sqlite3StrDup(zi); + if (!zo){ + sqlite3_result_error_nomem(context); + return; + } + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + }else{ + zo = sqlite3_malloc(strlen(zi)+ilen-zl+1); + if (!zo){ + sqlite3_result_error_nomem(context); + return; + } + zt = zo; + for(i=1; i+zl<=ilen; ++i){ + *(zt++)=' '; + } + /* no need to take UTF-8 into consideration here */ + strcpy(zt,zi); + } + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + sqlite3_free(zo); + } +} + +/* +** given an input string (s) and an integer (n) appends spaces at the end of s +** until it has a length of n characters. +** When s has a length >=n it's a NOP +** padl(NULL) = NULL +*/ +static void padrFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + i64 ilen; /* length to pad to */ + i64 zl; /* length of the input string (UTF-8 chars) */ + i64 zll; /* length of the input string (bytes) */ + int i = 0; + const char *zi; /* input string */ + char *zo; /* output string */ + char *zt; + + assert( argc==2 ); + + if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ + sqlite3_result_null(context); + }else{ + zi = (char *)sqlite3_value_text(argv[0]); + ilen = sqlite3_value_int64(argv[1]); + /* check domain */ + if(ilen<0){ + sqlite3_result_error(context, "domain error", -1); + return; + } + zl = sqlite3Utf8CharLen(zi, -1); + if( zl>=ilen ){ + /* string is longer than the requested pad length, return the same string (dup it) */ + zo = sqlite3StrDup(zi); + if (!zo){ + sqlite3_result_error_nomem(context); + return; + } + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + }else{ + zll = strlen(zi); + zo = sqlite3_malloc(zll+ilen-zl+1); + if (!zo){ + sqlite3_result_error_nomem(context); + return; + } + zt = strcpy(zo,zi)+zll; + for(i=1; i+zl<=ilen; ++i){ + *(zt++) = ' '; + } + *zt = '\0'; + } + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + sqlite3_free(zo); + } +} + +/* +** given an input string (s) and an integer (n) appends spaces at the end of s +** and adds spaces at the begining of s until it has a length of n characters. +** Tries to add has many characters at the left as at the right. +** When s has a length >=n it's a NOP +** padl(NULL) = NULL +*/ +static void padcFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + i64 ilen; /* length to pad to */ + i64 zl; /* length of the input string (UTF-8 chars) */ + i64 zll; /* length of the input string (bytes) */ + int i = 0; + const char *zi; /* input string */ + char *zo; /* output string */ + char *zt; + + assert( argc==2 ); + + if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ + sqlite3_result_null(context); + }else{ + zi = (char *)sqlite3_value_text(argv[0]); + ilen = sqlite3_value_int64(argv[1]); + /* check domain */ + if(ilen<0){ + sqlite3_result_error(context, "domain error", -1); + return; + } + zl = sqlite3Utf8CharLen(zi, -1); + if( zl>=ilen ){ + /* string is longer than the requested pad length, return the same string (dup it) */ + zo = sqlite3StrDup(zi); + if (!zo){ + sqlite3_result_error_nomem(context); + return; + } + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + }else{ + zll = strlen(zi); + zo = sqlite3_malloc(zll+ilen-zl+1); + if (!zo){ + sqlite3_result_error_nomem(context); + return; + } + zt = zo; + for(i=1; 2*i+zl<=ilen; ++i){ + *(zt++) = ' '; + } + strcpy(zt, zi); + zt+=zll; + for(; i+zl<=ilen; ++i){ + *(zt++) = ' '; + } + *zt = '\0'; + } + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + sqlite3_free(zo); + } +} + +/* +** given 2 string (s1,s2) returns the string s1 with the characters NOT in s2 removed +** assumes strings are UTF-8 encoded +*/ +static void strfilterFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *zi1; /* first parameter string (searched string) */ + const char *zi2; /* second parameter string (vcontains valid characters) */ + const char *z1; + const char *z21; + const char *z22; + char *zo; /* output string */ + char *zot; + int c1 = 0; + int c2 = 0; + + assert( argc==2 ); + + if( sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL ){ + sqlite3_result_null(context); + }else{ + zi1 = (char *)sqlite3_value_text(argv[0]); + zi2 = (char *)sqlite3_value_text(argv[1]); + /* + ** maybe I could allocate less, but that would imply 2 passes, rather waste + ** (possibly) some memory + */ + zo = sqlite3_malloc(strlen(zi1)+1); + if (!zo){ + sqlite3_result_error_nomem(context); + return; + } + zot = zo; + z1 = zi1; + while( (c1=sqliteCharVal((unsigned char *)z1))!=0 ){ + z21=zi2; + while( (c2=sqliteCharVal((unsigned char *)z21))!=0 && c2!=c1 ){ + sqliteNextChar(z21); + } + if( c2!=0){ + z22=z21; + sqliteNextChar(z22); + strncpy(zot, z21, z22-z21); + zot+=z22-z21; + } + sqliteNextChar(z1); + } + *zot = '\0'; + + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + sqlite3_free(zo); + } +} + +/* +** Given a string z1, retutns the (0 based) index of it's first occurence +** in z2 after the first s characters. +** Returns -1 when there isn't a match. +** updates p to point to the character where the match occured. +** This is an auxiliary function. +*/ +static int _substr(const char* z1, const char* z2, int s, const char** p){ + int c = 0; + int rVal=-1; + const char* zt1; + const char* zt2; + int c1,c2; + + if( '\0'==*z1 ){ + return -1; + } + + while( (sqliteCharVal((unsigned char *)z2) != 0) && (c++)=0 ? rVal+s : rVal; +} + +/* +** given 2 input strings (s1,s2) and an integer (n) searches from the nth character +** for the string s1. Returns the position where the match occured. +** Characters are counted from 1. +** 0 is returned when no match occurs. +*/ + +static void charindexFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + const u8 *z1; /* s1 string */ + u8 *z2; /* s2 string */ + int s=0; + int rVal=0; + + assert( argc==3 ||argc==2); + + if( SQLITE_NULL==sqlite3_value_type(argv[0]) || SQLITE_NULL==sqlite3_value_type(argv[1])){ + sqlite3_result_null(context); + return; + } + + z1 = sqlite3_value_text(argv[0]); + if( z1==0 ) return; + z2 = (u8*) sqlite3_value_text(argv[1]); + if(argc==3){ + s = sqlite3_value_int(argv[2])-1; + if(s<0){ + s=0; + } + }else{ + s = 0; + } + + rVal = _substr((char *)z1,(char *)z2,s,NULL); + sqlite3_result_int(context, rVal+1); +} + +/* +** given a string (s) and an integer (n) returns the n leftmost (UTF-8) characters +** if the string has a length<=n or is NULL this function is NOP +*/ +static void leftFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + int c=0; + int cc=0; + int l=0; + const unsigned char *z; /* input string */ + const unsigned char *zt; + unsigned char *rz; /* output string */ + + assert( argc==2); + + if( SQLITE_NULL==sqlite3_value_type(argv[0]) || SQLITE_NULL==sqlite3_value_type(argv[1])){ + sqlite3_result_null(context); + return; + } + + z = sqlite3_value_text(argv[0]); + l = sqlite3_value_int(argv[1]); + zt = z; + + while( sqliteCharVal(zt) && c++ 0 ){ + sqliteNextChar(zt); + } + + rz = sqlite3_malloc(ze-zt+1); + if (!rz){ + sqlite3_result_error_nomem(context); + return; + } + strcpy((char*) rz, (char*) (zt)); + sqlite3_result_text(context, (char*)rz, -1, SQLITE_TRANSIENT); + sqlite3_free(rz); +} + +#ifndef HAVE_TRIM +/* +** removes the whitespaces at the begining of a string. +*/ +const char* ltrim(const char* s){ + while( *s==' ' ) + ++s; + return s; +} + +/* +** removes the whitespaces at the end of a string. +** !mutates the input string! +*/ +void rtrim(char* s){ + char* ss = s+strlen(s)-1; + while( ss>=s && *ss==' ' ) + --ss; + *(ss+1)='\0'; +} + +/* +** Removes the whitespace at the begining of a string +*/ +static void ltrimFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *z; + + assert( argc==1); + + if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){ + sqlite3_result_null(context); + return; + } + z = sqlite3_value_text(argv[0]); + sqlite3_result_text(context, ltrim(z), -1, SQLITE_TRANSIENT); +} + +/* +** Removes the whitespace at the end of a string +*/ +static void rtrimFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *z; + char *rz; + /* try not to change data in argv */ + + assert( argc==1); + + if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){ + sqlite3_result_null(context); + return; + } + z = sqlite3_value_text(argv[0]); + rz = sqlite3StrDup(z); + rtrim(rz); + sqlite3_result_text(context, rz, -1, SQLITE_TRANSIENT); + sqlite3_free(rz); +} + +/* +** Removes the whitespace at the begining and end of a string +*/ +static void trimFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *z; + char *rz; + /* try not to change data in argv */ + + assert( argc==1); + + if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){ + sqlite3_result_null(context); + return; + } + z = sqlite3_value_text(argv[0]); + rz = sqlite3StrDup(z); + rtrim(rz); + sqlite3_result_text(context, ltrim(rz), -1, SQLITE_TRANSIENT); + sqlite3_free(rz); +} +#endif + +/* +** given a pointer to a string s1, the length of that string (l1), a new string (s2) +** and it's length (l2) appends s2 to s1. +** All lengths in bytes. +** This is just an auxiliary function +*/ +// static void _append(char **s1, int l1, const char *s2, int l2){ +// *s1 = realloc(*s1, (l1+l2+1)*sizeof(char)); +// strncpy((*s1)+l1, s2, l2); +// *(*(s1)+l1+l2) = '\0'; +// } + +#ifndef HAVE_TRIM + +/* +** given strings s, s1 and s2 replaces occurrences of s1 in s by s2 +*/ +static void replaceFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *z1; /* string s (first parameter) */ + const char *z2; /* string s1 (second parameter) string to look for */ + const char *z3; /* string s2 (third parameter) string to replace occurrences of s1 with */ + int lz1; + int lz2; + int lz3; + int lzo=0; + char *zo=0; + int ret=0; + const char *zt1; + const char *zt2; + + assert( 3==argc ); + + if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){ + sqlite3_result_null(context); + return; + } + + z1 = sqlite3_value_text(argv[0]); + z2 = sqlite3_value_text(argv[1]); + z3 = sqlite3_value_text(argv[2]); + /* handle possible null values */ + if( 0==z2 ){ + z2=""; + } + if( 0==z3 ){ + z3=""; + } + + lz1 = strlen(z1); + lz2 = strlen(z2); + lz3 = strlen(z3); + +#if 0 + /* special case when z2 is empty (or null) nothing will be changed */ + if( 0==lz2 ){ + sqlite3_result_text(context, z1, -1, SQLITE_TRANSIENT); + return; + } +#endif + + zt1=z1; + zt2=z1; + + while(1){ + ret=_substr(z2,zt1 , 0, &zt2); + + if( ret<0 ) + break; + + _append(&zo, lzo, zt1, zt2-zt1); + lzo+=zt2-zt1; + _append(&zo, lzo, z3, lz3); + lzo+=lz3; + + zt1=zt2+lz2; + } + _append(&zo, lzo, zt1, lz1-(zt1-z1)); + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + sqlite3_free(zo); +} +#endif + +/* +** given a string returns the same string but with the characters in reverse order +*/ +static void reverseFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *z; + const char *zt; + char *rz; + char *rzt; + int l = 0; + int i = 0; + + assert( 1==argc ); + + if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){ + sqlite3_result_null(context); + return; + } + z = (char *)sqlite3_value_text(argv[0]); + l = strlen(z); + rz = sqlite3_malloc(l+1); + if (!rz){ + sqlite3_result_error_nomem(context); + return; + } + rzt = rz+l; + *(rzt--) = '\0'; + + zt=z; + while( sqliteCharVal((unsigned char *)zt)!=0 ){ + z=zt; + sqliteNextChar(zt); + for(i=1; zt-i>=z; ++i){ + *(rzt--)=*(zt-i); + } + } + + sqlite3_result_text(context, rz, -1, SQLITE_TRANSIENT); + sqlite3_free(rz); +} + +/* +** An instance of the following structure holds the context of a +** stdev() or variance() aggregate computation. +** implementaion of http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Algorithm_II +** less prone to rounding errors +*/ +typedef struct StdevCtx StdevCtx; +struct StdevCtx { + double rM; + double rS; + i64 cnt; /* number of elements */ +}; + +/* +** An instance of the following structure holds the context of a +** mode() or median() aggregate computation. +** Depends on structures defined in map.c (see map & map) +** These aggregate functions only work for integers and floats although +** they could be made to work for strings. This is usually considered meaningless. +** Only usuall order (for median), no use of collation functions (would this even make sense?) +*/ +typedef struct ModeCtx ModeCtx; +struct ModeCtx { + i64 riM; /* integer value found so far */ + double rdM; /* double value found so far */ + i64 cnt; /* number of elements so far */ + double pcnt; /* number of elements smaller than a percentile */ + i64 mcnt; /* maximum number of occurrences (for mode) */ + i64 mn; /* number of occurrences (for mode and percentiles) */ + i64 is_double; /* whether the computation is being done for doubles (>0) or integers (=0) */ + map* m; /* map structure used for the computation */ + int done; /* whether the answer has been found */ +}; + +/* +** called for each value received during a calculation of stdev or variance +*/ +static void varianceStep(sqlite3_context *context, int argc, sqlite3_value **argv){ + StdevCtx *p; + + double delta; + double x; + + assert( argc==1 ); + p = sqlite3_aggregate_context(context, sizeof(*p)); + /* only consider non-null values */ + if( SQLITE_NULL != sqlite3_value_numeric_type(argv[0]) ){ + p->cnt++; + x = sqlite3_value_double(argv[0]); + delta = (x-p->rM); + p->rM += delta/p->cnt; + p->rS += delta*(x-p->rM); + } +} + +/* +** called for each value received during a calculation of mode of median +*/ +static void modeStep(sqlite3_context *context, int argc, sqlite3_value **argv){ + ModeCtx *p; + i64 xi=0; + double xd=0.0; + i64 *iptr; + double *dptr; + int type; + + assert( argc==1 ); + type = sqlite3_value_numeric_type(argv[0]); + + if( type == SQLITE_NULL) + return; + + p = sqlite3_aggregate_context(context, sizeof(*p)); + + if( 0==(p->m) ){ + p->m = calloc(1, sizeof(map)); + if( type==SQLITE_INTEGER ){ + /* map will be used for integers */ + *(p->m) = map_make(int_cmp); + p->is_double = 0; + }else{ + p->is_double = 1; + /* map will be used for doubles */ + *(p->m) = map_make(double_cmp); + } + } + + ++(p->cnt); + + if( 0==p->is_double ){ + xi = sqlite3_value_int64(argv[0]); + iptr = (i64*)calloc(1,sizeof(i64)); + *iptr = xi; + map_insert(p->m, iptr); + }else{ + xd = sqlite3_value_double(argv[0]); + dptr = (double*)calloc(1,sizeof(double)); + *dptr = xd; + map_insert(p->m, dptr); + } +} + +/* +** Auxiliary function that iterates all elements in a map and finds the mode +** (most frequent value) +*/ +static void modeIterate(void* e, i64 c, void* pp){ + i64 ei; + double ed; + ModeCtx *p = (ModeCtx*)pp; + + if( 0==p->is_double ){ + ei = *(int*)(e); + + if( p->mcnt==c ){ + ++p->mn; + }else if( p->mcntriM = ei; + p->mcnt = c; + p->mn=1; + } + }else{ + ed = *(double*)(e); + + if( p->mcnt==c ){ + ++p->mn; + }else if(p->mcntrdM = ed; + p->mcnt = c; + p->mn=1; + } + } +} + +/* +** Auxiliary function that iterates all elements in a map and finds the median +** (the value such that the number of elements smaller is equal the the number of +** elements larger) +*/ +static void medianIterate(void* e, i64 c, void* pp){ + i64 ei; + double ed; + double iL; + double iR; + int il; + int ir; + ModeCtx *p = (ModeCtx*)pp; + + if(p->done>0) + return; + + iL = p->pcnt; + iR = p->cnt - p->pcnt; + il = p->mcnt + c; + ir = p->cnt - p->mcnt; + + if( il >= iL ){ + if( ir >= iR ){ + ++p->mn; + if( 0==p->is_double ){ + ei = *(int*)(e); + p->riM += ei; + }else{ + ed = *(double*)(e); + p->rdM += ed; + } + }else{ + p->done=1; + } + } + p->mcnt+=c; +} + +/* +** Returns the mode value +*/ +static void modeFinalize(sqlite3_context *context){ + ModeCtx *p; + p = sqlite3_aggregate_context(context, 0); + if( p && p->m ){ + map_iterate(p->m, modeIterate, p); + map_destroy(p->m); + free(p->m); + + if( 1==p->mn ){ + if( 0==p->is_double ) + sqlite3_result_int64(context, p->riM); + else + sqlite3_result_double(context, p->rdM); + } + } +} + +/* +** auxiliary function for percentiles +*/ +static void _medianFinalize(sqlite3_context *context){ + ModeCtx *p; + p = (ModeCtx*) sqlite3_aggregate_context(context, 0); + if( p && p->m ){ + p->done=0; + map_iterate(p->m, medianIterate, p); + map_destroy(p->m); + free(p->m); + + if( 0==p->is_double ) + if( 1==p->mn ) + sqlite3_result_int64(context, p->riM); + else + sqlite3_result_double(context, p->riM*1.0/p->mn); + else + sqlite3_result_double(context, p->rdM/p->mn); + } +} + +/* +** Returns the median value +*/ +static void medianFinalize(sqlite3_context *context){ + ModeCtx *p; + p = (ModeCtx*) sqlite3_aggregate_context(context, 0); + if( p!=0 ){ + p->pcnt = (p->cnt)/2.0; + _medianFinalize(context); + } +} + +/* +** Returns the lower_quartile value +*/ +static void lower_quartileFinalize(sqlite3_context *context){ + ModeCtx *p; + p = (ModeCtx*) sqlite3_aggregate_context(context, 0); + if( p!=0 ){ + p->pcnt = (p->cnt)/4.0; + _medianFinalize(context); + } +} + +/* +** Returns the upper_quartile value +*/ +static void upper_quartileFinalize(sqlite3_context *context){ + ModeCtx *p; + p = (ModeCtx*) sqlite3_aggregate_context(context, 0); + if( p!=0 ){ + p->pcnt = (p->cnt)*3/4.0; + _medianFinalize(context); + } +} + +/* +** Returns the stdev value +*/ +static void stdevFinalize(sqlite3_context *context){ + StdevCtx *p; + p = sqlite3_aggregate_context(context, 0); + if( p && p->cnt>1 ){ + sqlite3_result_double(context, sqrt(p->rS/(p->cnt-1))); + }else{ + sqlite3_result_double(context, 0.0); + } +} + +/* +** Returns the variance value +*/ +static void varianceFinalize(sqlite3_context *context){ + StdevCtx *p; + p = sqlite3_aggregate_context(context, 0); + if( p && p->cnt>1 ){ + sqlite3_result_double(context, p->rS/(p->cnt-1)); + }else{ + sqlite3_result_double(context, 0.0); + } +} + +#ifdef SQLITE_SOUNDEX + +/* relicoder factored code */ +/* +** Calculates the soundex value of a string +*/ + +static void soundex(const u8 *zIn, char *zResult){ + int i, j; + static const unsigned char iCode[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, + 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, + 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, + }; + + for(i=0; zIn[i] && !isalpha(zIn[i]); i++){} + if( zIn[i] ){ + zResult[0] = toupper(zIn[i]); + for(j=1; j<4 && zIn[i]; i++){ + int code = iCode[zIn[i]&0x7f]; + if( code>0 ){ + zResult[j++] = code + '0'; + } + } + while( j<4 ){ + zResult[j++] = '0'; + } + zResult[j] = 0; + }else{ + strcpy(zResult, "?000"); + } +} + +/* +** computes the number of different characters between the soundex value fo 2 strings +*/ +static void differenceFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + char zResult1[8]; + char zResult2[8]; + char *zR1 = zResult1; + char *zR2 = zResult2; + int rVal = 0; + int i = 0; + const u8 *zIn1; + const u8 *zIn2; + + assert( argc==2 ); + + if( sqlite3_value_type(argv[0])==SQLITE_NULL || sqlite3_value_type(argv[1])==SQLITE_NULL ){ + sqlite3_result_null(context); + return; + } + + zIn1 = (u8*)sqlite3_value_text(argv[0]); + zIn2 = (u8*)sqlite3_value_text(argv[1]); + + soundex(zIn1, zR1); + soundex(zIn2, zR2); + + for(i=0; i<4; ++i){ + if( sqliteCharVal((unsigned char *)zR1)==sqliteCharVal((unsigned char *)zR2) ) + ++rVal; + sqliteNextChar(zR1); + sqliteNextChar(zR2); + } + sqlite3_result_int(context, rVal); +} +#endif + +/* +** This function registered all of the above C functions as SQL +** functions. This should be the only routine in this file with +** external linkage. +*/ +int RegisterExtensionFunctions(sqlite3 *db){ + static const struct FuncDef { + char *zName; + signed char nArg; + u8 argType; /* 0: none. 1: db 2: (-1) */ + u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */ + u8 needCollSeq; + void (*xFunc)(sqlite3_context*,int,sqlite3_value **); + } aFuncs[] = { + /* math.h */ + { "acos", 1, 0, SQLITE_UTF8, 0, acosFunc }, + { "asin", 1, 0, SQLITE_UTF8, 0, asinFunc }, + { "atan", 1, 0, SQLITE_UTF8, 0, atanFunc }, + { "atn2", 2, 0, SQLITE_UTF8, 0, atn2Func }, + /* XXX alias */ + { "atan2", 2, 0, SQLITE_UTF8, 0, atn2Func }, + { "acosh", 1, 0, SQLITE_UTF8, 0, acoshFunc }, + { "asinh", 1, 0, SQLITE_UTF8, 0, asinhFunc }, + { "atanh", 1, 0, SQLITE_UTF8, 0, atanhFunc }, + + { "difference", 2, 0, SQLITE_UTF8, 0, differenceFunc}, + { "degrees", 1, 0, SQLITE_UTF8, 0, rad2degFunc }, + { "radians", 1, 0, SQLITE_UTF8, 0, deg2radFunc }, + + { "cos", 1, 0, SQLITE_UTF8, 0, cosFunc }, + { "sin", 1, 0, SQLITE_UTF8, 0, sinFunc }, + { "tan", 1, 0, SQLITE_UTF8, 0, tanFunc }, + { "cot", 1, 0, SQLITE_UTF8, 0, cotFunc }, + { "cosh", 1, 0, SQLITE_UTF8, 0, coshFunc }, + { "sinh", 1, 0, SQLITE_UTF8, 0, sinhFunc }, + { "tanh", 1, 0, SQLITE_UTF8, 0, tanhFunc }, + { "coth", 1, 0, SQLITE_UTF8, 0, cothFunc }, + + { "exp", 1, 0, SQLITE_UTF8, 0, expFunc }, + { "log", 1, 0, SQLITE_UTF8, 0, logFunc }, + { "log10", 1, 0, SQLITE_UTF8, 0, log10Func }, + { "power", 2, 0, SQLITE_UTF8, 0, powerFunc }, + { "sign", 1, 0, SQLITE_UTF8, 0, signFunc }, + { "sqrt", 1, 0, SQLITE_UTF8, 0, sqrtFunc }, + { "square", 1, 0, SQLITE_UTF8, 0, squareFunc }, + + { "ceil", 1, 0, SQLITE_UTF8, 0, ceilFunc }, + { "floor", 1, 0, SQLITE_UTF8, 0, floorFunc }, + + { "pi", 0, 0, SQLITE_UTF8, 1, piFunc }, + + + /* string */ + { "replicate", 2, 0, SQLITE_UTF8, 0, replicateFunc }, + { "charindex", 2, 0, SQLITE_UTF8, 0, charindexFunc }, + { "charindex", 3, 0, SQLITE_UTF8, 0, charindexFunc }, + { "leftstr", 2, 0, SQLITE_UTF8, 0, leftFunc }, + { "rightstr", 2, 0, SQLITE_UTF8, 0, rightFunc }, +#ifndef HAVE_TRIM + { "ltrim", 1, 0, SQLITE_UTF8, 0, ltrimFunc }, + { "rtrim", 1, 0, SQLITE_UTF8, 0, rtrimFunc }, + { "trim", 1, 0, SQLITE_UTF8, 0, trimFunc }, + { "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc }, +#endif + { "reverse", 1, 0, SQLITE_UTF8, 0, reverseFunc }, + { "proper", 1, 0, SQLITE_UTF8, 0, properFunc }, + { "padl", 2, 0, SQLITE_UTF8, 0, padlFunc }, + { "padr", 2, 0, SQLITE_UTF8, 0, padrFunc }, + { "padc", 2, 0, SQLITE_UTF8, 0, padcFunc }, + { "strfilter", 2, 0, SQLITE_UTF8, 0, strfilterFunc }, + + }; + /* Aggregate functions */ + static const struct FuncDefAgg { + char *zName; + signed char nArg; + u8 argType; + u8 needCollSeq; + void (*xStep)(sqlite3_context*,int,sqlite3_value**); + void (*xFinalize)(sqlite3_context*); + } aAggs[] = { + { "stdev", 1, 0, 0, varianceStep, stdevFinalize }, + { "variance", 1, 0, 0, varianceStep, varianceFinalize }, + { "mode", 1, 0, 0, modeStep, modeFinalize }, + { "median", 1, 0, 0, modeStep, medianFinalize }, + { "lower_quartile", 1, 0, 0, modeStep, lower_quartileFinalize }, + { "upper_quartile", 1, 0, 0, modeStep, upper_quartileFinalize }, + }; + int i; + + for(i=0; ineedCollSeq = 1; + } + } +#endif + } + + for(i=0; ineedCollSeq = 1; + } + } +#endif + } + return 0; +} + +#ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE +int sqlite3_extension_init( + sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi){ + SQLITE_EXTENSION_INIT2(pApi); + RegisterExtensionFunctions(db); + return 0; +} +#endif /* COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE */ + +map map_make(cmp_func cmp){ + map r; + r.cmp=cmp; + r.base = 0; + + return r; +} + +void* xcalloc(size_t nmemb, size_t size, char* s){ + void* ret = calloc(nmemb, size); + return ret; +} + +void xfree(void* p){ + free(p); +} + +void node_insert(node** n, cmp_func cmp, void *e){ + int c; + node* nn; + if(*n==0){ + nn = (node*)xcalloc(1,sizeof(node), "for node"); + nn->data = e; + nn->count = 1; + *n=nn; + }else{ + c=cmp((*n)->data,e); + if(0==c){ + ++((*n)->count); + xfree(e); + }else if(c>0){ + /* put it right here */ + node_insert(&((*n)->l), cmp, e); + }else{ + node_insert(&((*n)->r), cmp, e); + } + } +} + +void map_insert(map *m, void *e){ + node_insert(&(m->base), m->cmp, e); +} + +void node_iterate(node *n, map_iterator iter, void* p){ + if(n){ + if(n->l) + node_iterate(n->l, iter, p); + iter(n->data, n->count, p); + if(n->r) + node_iterate(n->r, iter, p); + } +} + +void map_iterate(map *m, map_iterator iter, void* p){ + node_iterate(m->base, iter, p); +} + +void node_destroy(node *n){ + if(0!=n){ + xfree(n->data); + if(n->l) + node_destroy(n->l); + if(n->r) + node_destroy(n->r); + + xfree(n); + } +} + +void map_destroy(map *m){ + node_destroy(m->base); +} + +int int_cmp(const void *a, const void *b){ + int64_t aa = *(int64_t *)(a); + int64_t bb = *(int64_t *)(b); + /* printf("cmp %d <=> %d\n",aa,bb); */ + if(aa==bb) + return 0; + else if(aa %d\n",aa,bb); */ + if(aa==bb) + return 0; + else if(aa %lld\n", ee,c); +} + diff --git a/math-func.dll b/math-func.dll new file mode 100644 index 0000000000000000000000000000000000000000..973c878bf0f08949ab0973b2cfbce7404c57cfc8 GIT binary patch literal 74392 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 W`V#i8pe);YE3SrYH{YpQZT4TJPWBA| literal 0 HcmV?d00001