xref: /sqlite-3.40.0/ext/misc/zorder.c (revision 510fea88)
1 /*
2 ** 2018-02-09
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 ** SQL functions for z-order (Morton code) transformations.
14 **
15 **      zorder(X0,X0,..,xN)      Generate an N+1 dimension Morton code
16 **
17 **      unzorder(Z,N,I)          Extract the I-th dimension from N-dimensional
18 **                               Morton code Z.
19 */
20 #include "sqlite3ext.h"
21 SQLITE_EXTENSION_INIT1
22 #include <assert.h>
23 #include <string.h>
24 
25 /*
26 ** Functions:     zorder(X0,X1,....)
27 **
28 ** Convert integers X0, X1, ... into morton code.
29 **
30 ** The output is a signed 64-bit integer.  If any argument is too large,
31 ** an error is thrown.
32 */
zorderFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)33 static void zorderFunc(
34   sqlite3_context *context,
35   int argc,
36   sqlite3_value **argv
37 ){
38   sqlite3_int64 z, x[63];
39   int i, j;
40   z = 0;
41   for(i=0; i<argc; i++){
42     x[i] = sqlite3_value_int64(argv[i]);
43   }
44   if( argc>0 ){
45     for(i=0; i<63; i++){
46       j = i%argc;
47       z |= (x[j]&1)<<i;
48       x[j] >>= 1;
49     }
50   }
51   sqlite3_result_int64(context, z);
52   for(i=0; i<argc; i++){
53     if( x[i] ){
54       sqlite3_result_error(context, "parameter too large", -1);
55     }
56   }
57 }
58 
59 
60 /*
61 ** Functions:     unzorder(Z,N,I)
62 **
63 ** Assuming that Z is an N-dimensional Morton code, extract the I-th
64 ** dimension.
65 */
unzorderFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)66 static void unzorderFunc(
67   sqlite3_context *context,
68   int argc,
69   sqlite3_value **argv
70 ){
71   sqlite3_int64 z, n, i, x;
72   int j, k;
73   z = sqlite3_value_int64(argv[0]);
74   n = sqlite3_value_int64(argv[1]);
75   i = sqlite3_value_int64(argv[2]);
76   x = 0;
77   for(k=0, j=i; j<63; j+=n, k++){
78     x |= ((z>>j)&1)<<k;
79   }
80   sqlite3_result_int64(context, x);
81 }
82 
83 
84 #ifdef _WIN32
85 __declspec(dllexport)
86 #endif
sqlite3_zorder_init(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)87 int sqlite3_zorder_init(
88   sqlite3 *db,
89   char **pzErrMsg,
90   const sqlite3_api_routines *pApi
91 ){
92   int rc = SQLITE_OK;
93   SQLITE_EXTENSION_INIT2(pApi);
94   (void)pzErrMsg;  /* Unused parameter */
95   rc = sqlite3_create_function(db, "zorder", -1, SQLITE_UTF8, 0,
96                                zorderFunc, 0, 0);
97   if( rc==SQLITE_OK ){
98     rc = sqlite3_create_function(db, "unzorder", 3, SQLITE_UTF8, 0,
99                                unzorderFunc, 0, 0);
100   }
101   return rc;
102 }
103