use relative seeks and hilbert curve

This commit is contained in:
Alain Zscheile 2023-01-02 09:33:51 +01:00
parent 4e5fd39cc9
commit 5f92902208
4 changed files with 93 additions and 26 deletions

42
hilbert.c Normal file
View 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;
}
}

View file

@ -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
View file

@ -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
View 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);