use relative seeks and hilbert curve
This commit is contained in:
parent
4e5fd39cc9
commit
5f92902208
42
hilbert.c
Normal file
42
hilbert.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
#include "y16t_hilbert.h"
|
||||
|
||||
// rotate/flip a quadrant appropriately
|
||||
static void y16t_hilbert_rot(uint32_t n, uint32_t *x, uint32_t *y, uint32_t rx, uint32_t ry) {
|
||||
if (ry == 0) {
|
||||
if (rx == 1) {
|
||||
*x = n-1 - *x;
|
||||
*y = n-1 - *y;
|
||||
}
|
||||
|
||||
//Swap x and y
|
||||
uint32_t t = *x;
|
||||
*x = *y;
|
||||
*y = t;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((pure))
|
||||
uint32_t y16t_hilbert_xy2d(uint32_t n, uint32_t x, uint32_t y) {
|
||||
uint32_t rx, ry, s, d=0;
|
||||
for (s=n/2; s>0; s/=2) {
|
||||
rx = (x & s) > 0;
|
||||
ry = (y & s) > 0;
|
||||
d += s * s * ((3 * rx) ^ ry);
|
||||
y16t_hilbert_rot(n, &x, &y, rx, ry);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
void y16t_hilbert_d2xy(uint32_t n, uint32_t d, uint32_t *x, uint32_t *y) {
|
||||
uint32_t rx, ry, s, t=d;
|
||||
*x = *y = 0;
|
||||
for (s=1; s<n; s*=2) {
|
||||
rx = 1 & (t/2);
|
||||
ry = 1 & (t ^ rx);
|
||||
y16t_hilbert_rot(s, x, y, rx, ry);
|
||||
*x += s * rx;
|
||||
*y += s * ry;
|
||||
t /= 4;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
project('y16t 16-field quad tree library', 'c',
|
||||
project('y16t 16bit-field quad tree library', 'c',
|
||||
default_options : ['c_std=c17'],
|
||||
version : '0.0.0',
|
||||
license : 'Apache-2.0',
|
||||
|
@ -7,7 +7,7 @@ project('y16t 16-field quad tree library', 'c',
|
|||
install_headers('y16t.h')
|
||||
|
||||
liby16t = shared_library('y16t',
|
||||
files('y16t.c'),
|
||||
files('hilbert.c', 'y16t.c'),
|
||||
version : '0.0.0',
|
||||
c_args : ['-fno-plt', '-fno-unwind-tables', '-fno-exceptions', '-Werror=return-type'],
|
||||
include_directories : include_directories('.'),
|
||||
|
@ -27,4 +27,4 @@ pkg_mod.generate(
|
|||
version : meson.project_version(),
|
||||
name : 'liby16t',
|
||||
filebase : 'y16t',
|
||||
description : 'y16t 16-field quad tree library')
|
||||
description : 'y16t 16bit-field quad tree library')
|
||||
|
|
61
y16t.c
61
y16t.c
|
@ -1,23 +1,13 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
#include "y16t.h"
|
||||
#include "y16t_hilbert.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
|
||||
// conversion to ις-points interleaved coordinates
|
||||
static __attribute__((pure))
|
||||
uint16_t y16t_interleave2(const uint8_t x, const uint8_t y)
|
||||
{
|
||||
return
|
||||
((uint16_t)((x & 0x55) | (y & 0xaa)) << 8)
|
||||
|
|
||||
(uint16_t)((x & 0xaa) | (y & 0x55))
|
||||
;
|
||||
}
|
||||
|
||||
static __attribute__((pure))
|
||||
uint32_t y16t_table_at(const uint8_t x, const uint8_t y)
|
||||
{
|
||||
return ((uint32_t)y16t_interleave2(x, y)) << 2;
|
||||
return y16t_hilbert_xy2d(1 << 16, x, y) << 2;
|
||||
}
|
||||
|
||||
int y16t_idx_lookup(
|
||||
|
@ -26,12 +16,14 @@ int y16t_idx_lookup(
|
|||
uint8_t y,
|
||||
uint32_t *result
|
||||
) {
|
||||
const uint32_t key = y16t_table_at(x, y);
|
||||
const long key = y16t_table_at(x, y);
|
||||
|
||||
if(fseek(fh, (long)key, SEEK_SET) == -1)
|
||||
if(key && fseek(fh, key, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
if(fread(result, 4, 1, fh) != 1)
|
||||
return -EIO;
|
||||
if(key && fseek(fh, -key, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -42,13 +34,14 @@ int y16t_idx_update(
|
|||
const uint8_t y,
|
||||
const uint32_t newval
|
||||
) {
|
||||
const uint32_t key = y16t_table_at(x, y);
|
||||
const long key = y16t_table_at(x, y);
|
||||
|
||||
if(fseek(fh, (long)key, SEEK_SET) == -1)
|
||||
if(key && fseek(fh, key, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
|
||||
if(fwrite(&newval, 4, 1, fh) != 1)
|
||||
return -EIO;
|
||||
if(key && fseek(fh, -key, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -59,13 +52,24 @@ int y16t_idx_foreach_x(
|
|||
int (*callback)(uint32_t, void*),
|
||||
void *context
|
||||
) {
|
||||
long offset = 0;
|
||||
|
||||
for (uint16_t x = 0; x < 0xff; ++x) {
|
||||
uint32_t value = 0;
|
||||
int tmp = y16t_idx_lookup(fh, x, y, &value);
|
||||
if(tmp != 0) return tmp;
|
||||
tmp = callback(value, context);
|
||||
const uint32_t key = y16t_table_at(x, y);
|
||||
const long delta = ((long)key) - offset;
|
||||
if(delta && fseek(fh, delta, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
offset = key;
|
||||
if(fread(&value, 4, 1, fh) != 1)
|
||||
return -EIO;
|
||||
int tmp = callback(value, context);
|
||||
if(tmp != 0) return tmp;
|
||||
}
|
||||
|
||||
if(offset && fseek(fh, -offset, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -75,12 +79,23 @@ int y16t_idx_foreach_y(
|
|||
int (*callback)(uint32_t, void*),
|
||||
void *context
|
||||
) {
|
||||
long offset = 0;
|
||||
|
||||
for (uint16_t y = 0; y < 0xff; ++y) {
|
||||
uint32_t value = 0;
|
||||
int tmp = y16t_idx_lookup(fh, x, y, &value);
|
||||
if(tmp != 0) return tmp;
|
||||
tmp = callback(value, context);
|
||||
const uint32_t key = y16t_table_at(x, y);
|
||||
const long delta = ((long)key) - offset;
|
||||
if(delta && fseek(fh, delta, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
offset = key;
|
||||
if(fread(&value, 4, 1, fh) != 1)
|
||||
return -EIO;
|
||||
int tmp = callback(value, context);
|
||||
if(tmp != 0) return tmp;
|
||||
}
|
||||
|
||||
if(offset && fseek(fh, -offset, SEEK_CUR) == -1)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
10
y16t_hilbert.h
Normal file
10
y16t_hilbert.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
#pragma once
|
||||
#include <inttypes.h>
|
||||
|
||||
// conversion between hilbert curve distance and x,y values
|
||||
|
||||
__attribute__((pure))
|
||||
uint32_t y16t_hilbert_xy2d(uint32_t n, uint32_t x, uint32_t y);
|
||||
|
||||
void y16t_hilbert_d2xy(uint32_t n, uint32_t d, uint32_t *x, uint32_t *y);
|
Loading…
Reference in a new issue