aboutsummaryrefslogtreecommitdiff
path: root/ext/misc/zorder.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/misc/zorder.c')
-rw-r--r--ext/misc/zorder.c60
1 files changed, 46 insertions, 14 deletions
diff --git a/ext/misc/zorder.c b/ext/misc/zorder.c
index c385d3c3c..c4c5fcdc7 100644
--- a/ext/misc/zorder.c
+++ b/ext/misc/zorder.c
@@ -16,6 +16,17 @@
**
** 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
@@ -25,43 +36,53 @@ SQLITE_EXTENSION_INIT1
/*
** Functions: zorder(X0,X1,....)
**
-** Convert integers X0, X1, ... into morton code.
+** 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,
-** an error is thrown.
+** 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[63];
+ 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]);
}
- if( argc>0 ){
- for(i=0; i<63; i++){
- j = i%argc;
- z |= (x[j]&1)<<i;
- x[j] >>= 1;
- }
+ 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] ){
- sqlite3_result_error(context, "parameter too large", -1);
+ 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;
}
}
}
/*
-** Functions: unzorder(Z,N,I)
+** Function: unzorder(Z,N,K)
**
-** Assuming that Z is an N-dimensional Morton code, extract the I-th
-** dimension.
+** 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,
@@ -72,7 +93,18 @@ static void unzorderFunc(
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;