diff options
Diffstat (limited to 'ext/misc/zorder.c')
-rw-r--r-- | ext/misc/zorder.c | 60 |
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; |