File: zorder.c

package info (click to toggle)
sqlcipher 4.14.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 119,596 kB
  • sloc: ansic: 290,487; tcl: 24,958; javascript: 13,486; java: 8,153; sh: 7,784; makefile: 2,251; yacc: 1,727; cs: 307; sql: 73
file content (134 lines) | stat: -rw-r--r-- 3,451 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
** 2018-02-09
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** SQL functions for z-order (Morton code) transformations.
**
**      zorder(X0,X0,..,xN)      Generate an N+1 dimension Morton code
**
**      unzorder(Z,N,I)          Extract the I-th dimension from N-dimensional
**                               Morton code Z.
**
** Compiling:
**
**   (linux)    gcc -fPIC -shared zorder.c -o zorder.so
**   (mac)      clang -fPIC -dynamiclib zorder.c -o zorder.dylib
**   (windows)  cl zorder.c -link -dll -out:zorder.dll
**
** Usage example:
**
**     .load ./zorder
**     SELECT zorder(1,2,3,4);
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>

/*
** Functions:     zorder(X0,X1,....)
**
** Convert integers X0, X1, ... into morton code.  There must be at least
** two arguments.  There may be no more than 24 arguments.
**
** The output is a signed 64-bit integer.  If any argument is too large
** to be successfully encoded into a morton code, an error is raised.
*/
static void zorderFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  sqlite3_int64 z, x[24];
  int i, j;
  z = 0;
  if( argc<2 || argc>24 ){
    sqlite3_result_error(context,
       "zorder() needs between 2 and 24 arguments4", -1);
    return;
  }
  for(i=0; i<argc; i++){
    x[i] = sqlite3_value_int64(argv[i]);
  }
  for(i=0; i<63; i++){
    j = i%argc;
    z |= (x[j]&1)<<i;
    x[j] >>= 1;
  }
  sqlite3_result_int64(context, z);
  for(i=0; i<argc; i++){
    if( x[i] ){
      char *z = sqlite3_mprintf(
        "the %r argument to zorder() (%lld) is too large "
        "for a 64-bit %d-dimensional Morton code",
        i+1, sqlite3_value_int64(argv[i]), argc);
      sqlite3_result_error(context, z, -1);
      sqlite3_free(z);
      break;
    }
  }
}


/*
** Function:     unzorder(Z,N,K)
**
** Assuming that Z is an N-dimensional Morton code, extract the K-th
** dimension.  K is between 0 and N-1.  N must be between 2 and 24.
*/
static void unzorderFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  sqlite3_int64 z, n, i, x;
  int j, k;
  z = sqlite3_value_int64(argv[0]);
  n = sqlite3_value_int64(argv[1]);
  if( n<2 || n>24 ){
    sqlite3_result_error(context,
      "N argument to unzorder(Z,N,K) should be between 2 and 24",
      -1);
    return;
  }
  i = sqlite3_value_int64(argv[2]);
  if( i<0 || i>=n ){
    sqlite3_result_error(context,
      "K argument to unzorder(Z,N,K) should be between 0 and N-1", -1);
    return;
  }
  x = 0;
  for(k=0, j=i; j<63; j+=n, k++){
    x |= ((z>>j)&1)<<k;
  }
  sqlite3_result_int64(context, x);
}


#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_zorder_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "zorder", -1, SQLITE_UTF8, 0,
                               zorderFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "unzorder", 3, SQLITE_UTF8, 0,
                               unzorderFunc, 0, 0);
  }
  return rc;
}