mirror of
https://github.com/pgpointcloud/pointcloud.git
synced 2025-12-08 20:36:04 +00:00
Tests in place for patchlevel filtering
much optimization left to do
This commit is contained in:
parent
fdc27ea55d
commit
668d2413b2
@ -9,6 +9,7 @@ EXE = cu_tester
|
||||
# ADD YOUR NEW TEST FILE HERE (1/1)
|
||||
OBJS = \
|
||||
cu_tester.o \
|
||||
cu_pc_bytes.o \
|
||||
cu_pc_schema.o \
|
||||
cu_pc_point.o \
|
||||
cu_pc_patch.o \
|
||||
|
||||
474
lib/cunit/cu_pc_bytes.c
Normal file
474
lib/cunit/cu_pc_bytes.c
Normal file
@ -0,0 +1,474 @@
|
||||
/***********************************************************************
|
||||
* cu_pc_schema.c
|
||||
*
|
||||
* Testing for the schema API functions
|
||||
*
|
||||
* Portions Copyright (c) 2012, OpenGeo
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#include "CUnit/Basic.h"
|
||||
#include "cu_tester.h"
|
||||
|
||||
/* GLOBALS ************************************************************/
|
||||
|
||||
static PCSCHEMA *schema = NULL;
|
||||
static const char *xmlfile = "data/pdal-schema.xml";
|
||||
|
||||
/* Setup/teardown for this suite */
|
||||
static int
|
||||
init_suite(void)
|
||||
{
|
||||
char *xmlstr = file_to_str(xmlfile);
|
||||
int rv = pc_schema_from_xml(xmlstr, &schema);
|
||||
pcfree(xmlstr);
|
||||
if ( rv == PC_FAILURE ) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
clean_suite(void)
|
||||
{
|
||||
pc_schema_free(schema);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* TESTS **************************************************************/
|
||||
|
||||
|
||||
static PCBYTES initbytes(uint8_t *bytes, size_t size, uint32_t interp)
|
||||
{
|
||||
PCBYTES pcb;
|
||||
pcb.bytes = bytes;
|
||||
pcb.size = size;
|
||||
pcb.interpretation = interp;
|
||||
pcb.npoints = pcb.size / pc_interpretation_size(pcb.interpretation);
|
||||
pcb.compression = PC_DIM_NONE;
|
||||
pcb.readonly = PC_TRUE;
|
||||
return pcb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Run-length encode a byte stream by word.
|
||||
* Lots of identical words means great
|
||||
* compression ratios.
|
||||
*/
|
||||
static void
|
||||
test_run_length_encoding()
|
||||
{
|
||||
char *bytes, *bytes_rle, *bytes_de_rle;
|
||||
int nr;
|
||||
uint32_t bytes_nelems;
|
||||
size_t bytes_rle_size;
|
||||
size_t size;
|
||||
uint8_t interp;
|
||||
size_t interp_size;
|
||||
PCBYTES pcb, epcb, pcb2;
|
||||
|
||||
/*
|
||||
typedef struct
|
||||
{
|
||||
size_t size;
|
||||
uint32_t npoints;
|
||||
uint32_t interpretation;
|
||||
uint32_t compression;
|
||||
uint8_t *bytes;
|
||||
} PCBYTES;
|
||||
*/
|
||||
|
||||
bytes = "aaaabbbbccdde";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
nr = pc_bytes_run_count(&pcb);
|
||||
CU_ASSERT_EQUAL(nr, 5);
|
||||
|
||||
bytes = "a";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
nr = pc_bytes_run_count(&pcb);
|
||||
CU_ASSERT_EQUAL(nr, 1);
|
||||
|
||||
bytes = "aa";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
nr = pc_bytes_run_count(&pcb);
|
||||
CU_ASSERT_EQUAL(nr, 1);
|
||||
|
||||
bytes = "ab";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
nr = pc_bytes_run_count(&pcb);
|
||||
CU_ASSERT_EQUAL(nr, 2);
|
||||
|
||||
bytes = "abcdefg";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
nr = pc_bytes_run_count(&pcb);
|
||||
CU_ASSERT_EQUAL(nr, 7);
|
||||
|
||||
bytes = "aabcdefg";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
nr = pc_bytes_run_count(&pcb);
|
||||
CU_ASSERT_EQUAL(nr, 7);
|
||||
|
||||
bytes = "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
nr = pc_bytes_run_count(&pcb);
|
||||
CU_ASSERT_EQUAL(nr, 1);
|
||||
|
||||
epcb = pc_bytes_run_length_encode(pcb);
|
||||
pcb2 = pc_bytes_run_length_decode(epcb);
|
||||
|
||||
CU_ASSERT_EQUAL(memcmp(pcb.bytes, pcb2.bytes, pcb.size), 0);
|
||||
CU_ASSERT_EQUAL(pcb.size, pcb2.size);
|
||||
CU_ASSERT_EQUAL(pcb.npoints, pcb2.npoints);
|
||||
pc_bytes_free(epcb);
|
||||
pc_bytes_free(pcb2);
|
||||
|
||||
bytes = "aabcdefg";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
epcb = pc_bytes_run_length_encode(pcb);
|
||||
pcb2 = pc_bytes_run_length_decode(epcb);
|
||||
CU_ASSERT_EQUAL(memcmp(pcb.bytes, pcb2.bytes, pcb.size), 0);
|
||||
CU_ASSERT_EQUAL(pcb.size, pcb2.size);
|
||||
CU_ASSERT_EQUAL(pcb.npoints, pcb2.npoints);
|
||||
pc_bytes_free(epcb);
|
||||
pc_bytes_free(pcb2);
|
||||
|
||||
bytes = (uint8_t*)((uint32_t[]){ 10, 10, 10, 20, 20, 30, 20, 20 });
|
||||
pcb = initbytes(bytes, 8, PC_UINT32);
|
||||
epcb = pc_bytes_run_length_encode(pcb);
|
||||
pcb2 = pc_bytes_run_length_decode(epcb);
|
||||
CU_ASSERT_EQUAL(memcmp(pcb.bytes, pcb2.bytes, pcb.size), 0);
|
||||
CU_ASSERT_EQUAL(pcb.size, pcb2.size);
|
||||
CU_ASSERT_EQUAL(pcb.npoints, pcb2.npoints);
|
||||
pc_bytes_free(epcb);
|
||||
pc_bytes_free(pcb2);
|
||||
|
||||
bytes = (uint8_t*)((uint16_t[]){ 10, 10, 10, 20, 20, 30, 20, 20 });
|
||||
pcb = initbytes(bytes, 8, PC_UINT16);
|
||||
epcb = pc_bytes_run_length_encode(pcb);
|
||||
pcb2 = pc_bytes_run_length_decode(epcb);
|
||||
CU_ASSERT_EQUAL(memcmp(pcb.bytes, pcb2.bytes, pcb.size), 0);
|
||||
CU_ASSERT_EQUAL(pcb.size, pcb2.size);
|
||||
CU_ASSERT_EQUAL(pcb.npoints, pcb2.npoints);
|
||||
pc_bytes_free(epcb);
|
||||
pc_bytes_free(pcb2);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Strip the common bits off a stream and pack the
|
||||
* remaining bits in behind. Test bit counting and
|
||||
* round-trip encode/decode paths.
|
||||
*/
|
||||
static void
|
||||
test_sigbits_encoding()
|
||||
{
|
||||
int i;
|
||||
uint8_t *bytes, *ebytes;
|
||||
uint16_t *bytes16, *ebytes16;
|
||||
uint32_t *bytes32, *ebytes32;
|
||||
size_t ebytes_size;
|
||||
|
||||
uint32_t count, nelems;
|
||||
uint8_t common8;
|
||||
uint16_t common16;
|
||||
uint32_t common32;
|
||||
PCBYTES pcb, epcb, pcb2;
|
||||
|
||||
/*
|
||||
01100001 a
|
||||
01100010 b
|
||||
01100011 c
|
||||
01100000 `
|
||||
*/
|
||||
bytes = "abc";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
common8 = pc_bytes_sigbits_count_8(&pcb, &count);
|
||||
CU_ASSERT_EQUAL(count, 6);
|
||||
CU_ASSERT_EQUAL(common8, '`');
|
||||
|
||||
bytes = "abcdef";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
common8 = pc_bytes_sigbits_count_8(&pcb, &count);
|
||||
CU_ASSERT_EQUAL(count, 5);
|
||||
CU_ASSERT_EQUAL(common8, '`');
|
||||
|
||||
/*
|
||||
0110000101100001 aa
|
||||
0110001001100010 bb
|
||||
0110001101100011 cc
|
||||
0110000000000000 24576
|
||||
*/
|
||||
bytes = "aabbcc";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT16);
|
||||
count = pc_bytes_sigbits_count(&pcb);
|
||||
CU_ASSERT_EQUAL(count, 6);
|
||||
|
||||
/*
|
||||
"abca" encoded:
|
||||
base a b c a
|
||||
01100000 01 10 11 01
|
||||
*/
|
||||
bytes = "abcaabcaabcbabcc";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_INT8);
|
||||
epcb = pc_bytes_sigbits_encode(pcb);
|
||||
CU_ASSERT_EQUAL(epcb.bytes[0], 2); /* unique bit count */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[1], 96); /* common bits */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[2], 109); /* packed byte */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[3], 109); /* packed byte */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[4], 110); /* packed byte */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[5], 111); /* packed byte */
|
||||
pc_bytes_free(epcb);
|
||||
|
||||
/*
|
||||
"abca" encoded:
|
||||
base a b c d a b
|
||||
01100000 001 010 011 100 001 010
|
||||
*/
|
||||
bytes = "abcdab";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_INT8);
|
||||
epcb = pc_bytes_sigbits_encode(pcb);
|
||||
CU_ASSERT_EQUAL(epcb.bytes[0], 3); /* unique bit count */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[1], 96); /* common bits */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[2], 41); /* packed byte */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[3], 194); /* packed byte */
|
||||
|
||||
pcb2 = pc_bytes_sigbits_decode(epcb);
|
||||
CU_ASSERT_EQUAL(pcb2.bytes[0], 'a');
|
||||
CU_ASSERT_EQUAL(pcb2.bytes[1], 'b');
|
||||
CU_ASSERT_EQUAL(pcb2.bytes[2], 'c');
|
||||
CU_ASSERT_EQUAL(pcb2.bytes[3], 'd');
|
||||
CU_ASSERT_EQUAL(pcb2.bytes[4], 'a');
|
||||
CU_ASSERT_EQUAL(pcb2.bytes[5], 'b');
|
||||
pc_bytes_free(pcb2);
|
||||
pc_bytes_free(epcb);
|
||||
|
||||
/* Test the 16 bit implementation path */
|
||||
nelems = 6;
|
||||
bytes16 = (uint16_t[]){
|
||||
24929, /* 0110000101100001 */
|
||||
24930, /* 0110000101100010 */
|
||||
24931, /* 0110000101100011 */
|
||||
24932, /* 0110000101100100 */
|
||||
24933, /* 0110000101100101 */
|
||||
24934 /* 0110000101100110 */
|
||||
};
|
||||
/* encoded 0110000101100 001 010 011 100 101 110 */
|
||||
bytes = (uint8_t*)bytes16;
|
||||
pcb = initbytes(bytes, nelems*2, PC_INT16);
|
||||
|
||||
/* Test the 16 bit implementation path */
|
||||
common16 = pc_bytes_sigbits_count_16(&pcb, &count);
|
||||
CU_ASSERT_EQUAL(common16, 24928);
|
||||
CU_ASSERT_EQUAL(count, 13);
|
||||
epcb = pc_bytes_sigbits_encode(pcb);
|
||||
ebytes16 = (uint16_t*)(epcb.bytes);
|
||||
// printf("commonbits %d\n", commonbits);
|
||||
CU_ASSERT_EQUAL(ebytes16[0], 3); /* unique bit count */
|
||||
CU_ASSERT_EQUAL(ebytes16[1], 24928); /* common bits */
|
||||
CU_ASSERT_EQUAL(ebytes16[2], 10699); /* packed uint16 one */
|
||||
|
||||
/* uint8_t* pc_bytes_sigbits_decode(const uint8_t *bytes, uint32_t interpretation, uint32_t nelems) */
|
||||
pcb2 = pc_bytes_sigbits_decode(epcb);
|
||||
pc_bytes_free(epcb);
|
||||
bytes16 = (uint16_t*)(pcb2.bytes);
|
||||
CU_ASSERT_EQUAL(bytes16[0], 24929);
|
||||
CU_ASSERT_EQUAL(bytes16[1], 24930);
|
||||
CU_ASSERT_EQUAL(bytes16[2], 24931);
|
||||
CU_ASSERT_EQUAL(bytes16[3], 24932);
|
||||
CU_ASSERT_EQUAL(bytes16[4], 24933);
|
||||
CU_ASSERT_EQUAL(bytes16[5], 24934);
|
||||
pc_bytes_free(pcb2);
|
||||
|
||||
/* Test the 32 bit implementation path */
|
||||
nelems = 6;
|
||||
|
||||
bytes32 = (uint32_t[]){
|
||||
103241, /* 0000000000000001 1001 0011 0100 1001 */
|
||||
103251, /* 0000000000000001 1001 0011 0101 0011 */
|
||||
103261, /* 0000000000000001 1001 0011 0101 1101 */
|
||||
103271, /* 0000000000000001 1001 0011 0110 0111 */
|
||||
103281, /* 0000000000000001 1001 0011 0111 0001 */
|
||||
103291 /* 0000000000000001 1001 0011 0111 1011 */
|
||||
};
|
||||
bytes = (uint8_t*)bytes32;
|
||||
pcb = initbytes(bytes, nelems*4, PC_INT32);
|
||||
|
||||
common32 = pc_bytes_sigbits_count_32(&pcb, &count);
|
||||
CU_ASSERT_EQUAL(count, 26); /* unique bit count */
|
||||
CU_ASSERT_EQUAL(common32, 103232);
|
||||
|
||||
epcb = pc_bytes_sigbits_encode(pcb);
|
||||
ebytes32 = (uint32_t*)(epcb.bytes);
|
||||
CU_ASSERT_EQUAL(ebytes32[0], 6); /* unique bit count */
|
||||
CU_ASSERT_EQUAL(ebytes32[1], 103232); /* common bits */
|
||||
CU_ASSERT_EQUAL(ebytes32[2], 624388039); /* packed uint32 */
|
||||
|
||||
pcb2 = pc_bytes_sigbits_decode(epcb);
|
||||
pc_bytes_free(epcb);
|
||||
bytes32 = (uint32_t*)(pcb2.bytes);
|
||||
CU_ASSERT_EQUAL(bytes32[0], 103241);
|
||||
CU_ASSERT_EQUAL(bytes32[1], 103251);
|
||||
CU_ASSERT_EQUAL(bytes32[2], 103261);
|
||||
CU_ASSERT_EQUAL(bytes32[3], 103271);
|
||||
CU_ASSERT_EQUAL(bytes32[4], 103281);
|
||||
CU_ASSERT_EQUAL(bytes32[5], 103291);
|
||||
pc_bytes_free(pcb2);
|
||||
|
||||
/* What if all the words are the same? */
|
||||
nelems = 6;
|
||||
bytes16 = (uint16_t[]){
|
||||
24929, /* 0000000000000001 1001 0011 0100 1001 */
|
||||
24929, /* 0000000000000001 1001 0011 0101 0011 */
|
||||
24929, /* 0000000000000001 1001 0011 0101 1101 */
|
||||
24929, /* 0000000000000001 1001 0011 0110 0111 */
|
||||
24929, /* 0000000000000001 1001 0011 0111 0001 */
|
||||
24929 /* 0000000000000001 1001 0011 0111 1011 */
|
||||
};
|
||||
bytes = (uint8_t*)bytes16;
|
||||
pcb = initbytes(bytes, nelems*2, PC_INT16);
|
||||
epcb = pc_bytes_sigbits_encode(pcb);
|
||||
pcb2 = pc_bytes_sigbits_decode(epcb);
|
||||
pc_bytes_free(epcb);
|
||||
pc_bytes_free(pcb2);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode and decode a byte stream. Data matches?
|
||||
*/
|
||||
static void
|
||||
test_zlib_encoding()
|
||||
{
|
||||
uint8_t *bytes, *ebytes;
|
||||
uint32_t i;
|
||||
PCBYTES pcb, epcb, pcb2;
|
||||
/*
|
||||
uint8_t *
|
||||
pc_bytes_zlib_encode(const uint8_t *bytes, uint32_t interpretation, uint32_t nelems)
|
||||
uint8_t *
|
||||
pc_bytes_zlib_decode(const uint8_t *bytes, uint32_t interpretation)
|
||||
*/
|
||||
bytes = "abcaabcaabcbabcc";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_INT8);
|
||||
epcb = pc_bytes_zlib_encode(pcb);
|
||||
pcb2 = pc_bytes_zlib_decode(epcb);
|
||||
CU_ASSERT_EQUAL(memcmp(pcb.bytes, pcb2.bytes, pcb.size), 0);
|
||||
pc_bytes_free(epcb);
|
||||
pc_bytes_free(pcb2);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_rle_filter()
|
||||
{
|
||||
char *bytes;
|
||||
PCBYTES pcb, epcb, fpcb;
|
||||
PCBITMAP *map1, *map2;
|
||||
|
||||
/*
|
||||
typedef struct
|
||||
{
|
||||
size_t size;
|
||||
uint32_t npoints;
|
||||
uint32_t interpretation;
|
||||
uint32_t compression;
|
||||
uint8_t *bytes;
|
||||
} PCBYTES;
|
||||
*/
|
||||
|
||||
bytes = "aaaabbbbccdd";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
epcb = pc_bytes_run_length_encode(pcb);
|
||||
CU_ASSERT_EQUAL(epcb.bytes[0], 4);
|
||||
|
||||
map1 = pc_bytes_bitmap(&epcb, PC_GT, 'b', 'b');
|
||||
CU_ASSERT_EQUAL(map1->nset, 4);
|
||||
map2 = pc_bytes_bitmap(&epcb, PC_GT, 'a', 'a');
|
||||
CU_ASSERT_EQUAL(map2->nset, 8);
|
||||
|
||||
fpcb = pc_bytes_filter(&epcb, map1);
|
||||
CU_ASSERT_EQUAL(fpcb.bytes[0], 2);
|
||||
CU_ASSERT_EQUAL(fpcb.bytes[1], 'c');
|
||||
CU_ASSERT_EQUAL(fpcb.bytes[2], 2);
|
||||
CU_ASSERT_EQUAL(fpcb.bytes[3], 'd');
|
||||
CU_ASSERT_EQUAL(fpcb.size, 4);
|
||||
CU_ASSERT_EQUAL(fpcb.npoints, 4);
|
||||
pc_bytes_free(fpcb);
|
||||
pc_bitmap_free(map1);
|
||||
|
||||
fpcb = pc_bytes_filter(&epcb, map2);
|
||||
CU_ASSERT_EQUAL(fpcb.bytes[0], 4);
|
||||
CU_ASSERT_EQUAL(fpcb.bytes[1], 'b');
|
||||
CU_ASSERT_EQUAL(fpcb.bytes[2], 2);
|
||||
CU_ASSERT_EQUAL(fpcb.bytes[3], 'c');
|
||||
CU_ASSERT_EQUAL(fpcb.size, 6);
|
||||
CU_ASSERT_EQUAL(fpcb.npoints, 8);
|
||||
pc_bytes_free(fpcb);
|
||||
pc_bitmap_free(map2);
|
||||
pc_bytes_free(epcb);
|
||||
|
||||
bytes = (uint8_t*)((uint32_t[]){ 10, 10, 10, 20, 20, 30, 20, 20 });
|
||||
pcb = initbytes(bytes, 32, PC_UINT32);
|
||||
epcb = pc_bytes_run_length_encode(pcb);
|
||||
map1 = pc_bytes_bitmap(&epcb, PC_LT, 25, 25);
|
||||
CU_ASSERT_EQUAL(map1->nset, 7);
|
||||
fpcb = pc_bytes_filter(&epcb, map1);
|
||||
CU_ASSERT_EQUAL(fpcb.size, 15);
|
||||
CU_ASSERT_EQUAL(fpcb.npoints, 7);
|
||||
|
||||
pc_bytes_free(fpcb);
|
||||
|
||||
pc_bytes_free(epcb);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
test_uncompressed_filter()
|
||||
{
|
||||
char *bytes;
|
||||
PCBYTES pcb, epcb, fpcb;
|
||||
PCBITMAP *map1, *map2;
|
||||
|
||||
/*
|
||||
typedef struct
|
||||
{
|
||||
size_t size;
|
||||
uint32_t npoints;
|
||||
uint32_t interpretation;
|
||||
uint32_t compression;
|
||||
uint8_t *bytes;
|
||||
} PCBYTES;
|
||||
*/
|
||||
|
||||
bytes = "aaaabbbbccdd";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
CU_ASSERT_EQUAL(pcb.bytes[0], 'a');
|
||||
CU_ASSERT_EQUAL(pcb.npoints, 12);
|
||||
|
||||
map1 = pc_bytes_bitmap(&pcb, PC_GT, 'b', 'b');
|
||||
CU_ASSERT_EQUAL(map1->nset, 4);
|
||||
|
||||
fpcb = pc_bytes_filter(&pcb, map1);
|
||||
CU_ASSERT_EQUAL(fpcb.bytes[0], 'c');
|
||||
CU_ASSERT_EQUAL(fpcb.size, 4);
|
||||
CU_ASSERT_EQUAL(fpcb.npoints, 4);
|
||||
pc_bytes_free(fpcb);
|
||||
|
||||
// pc_bytes_free(epcb);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* REGISTER ***********************************************************/
|
||||
|
||||
CU_TestInfo bytes_tests[] = {
|
||||
PC_TEST(test_run_length_encoding),
|
||||
PC_TEST(test_sigbits_encoding),
|
||||
PC_TEST(test_zlib_encoding),
|
||||
PC_TEST(test_rle_filter),
|
||||
PC_TEST(test_uncompressed_filter),
|
||||
CU_TEST_INFO_NULL
|
||||
};
|
||||
|
||||
CU_SuiteInfo bytes_suite = {"bytes", init_suite, clean_suite, bytes_tests};
|
||||
@ -222,323 +222,7 @@ test_schema_xy()
|
||||
|
||||
}
|
||||
|
||||
static PCBYTES initbytes(uint8_t *bytes, size_t size, uint32_t interp)
|
||||
{
|
||||
PCBYTES pcb;
|
||||
pcb.bytes = bytes;
|
||||
pcb.size = size;
|
||||
pcb.interpretation = interp;
|
||||
pcb.npoints = pcb.size / pc_interpretation_size(pcb.interpretation);
|
||||
pcb.compression = PC_DIM_NONE;
|
||||
return pcb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Run-length encode a byte stream by word.
|
||||
* Lots of identical words means great
|
||||
* compression ratios.
|
||||
*/
|
||||
static void
|
||||
test_run_length_encoding()
|
||||
{
|
||||
char *bytes, *bytes_rle, *bytes_de_rle;
|
||||
int nr;
|
||||
uint32_t bytes_nelems;
|
||||
size_t bytes_rle_size;
|
||||
size_t size;
|
||||
uint8_t interp;
|
||||
size_t interp_size;
|
||||
PCBYTES pcb, epcb, pcb2;
|
||||
|
||||
/*
|
||||
typedef struct
|
||||
{
|
||||
size_t size;
|
||||
uint32_t npoints;
|
||||
uint32_t interpretation;
|
||||
uint32_t compression;
|
||||
uint8_t *bytes;
|
||||
} PCBYTES;
|
||||
*/
|
||||
|
||||
bytes = "aaaabbbbccdde";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
nr = pc_bytes_run_count(&pcb);
|
||||
CU_ASSERT_EQUAL(nr, 5);
|
||||
|
||||
bytes = "a";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
nr = pc_bytes_run_count(&pcb);
|
||||
CU_ASSERT_EQUAL(nr, 1);
|
||||
|
||||
bytes = "aa";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
nr = pc_bytes_run_count(&pcb);
|
||||
CU_ASSERT_EQUAL(nr, 1);
|
||||
|
||||
bytes = "ab";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
nr = pc_bytes_run_count(&pcb);
|
||||
CU_ASSERT_EQUAL(nr, 2);
|
||||
|
||||
bytes = "abcdefg";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
nr = pc_bytes_run_count(&pcb);
|
||||
CU_ASSERT_EQUAL(nr, 7);
|
||||
|
||||
bytes = "aabcdefg";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
nr = pc_bytes_run_count(&pcb);
|
||||
CU_ASSERT_EQUAL(nr, 7);
|
||||
|
||||
bytes = "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
nr = pc_bytes_run_count(&pcb);
|
||||
CU_ASSERT_EQUAL(nr, 1);
|
||||
|
||||
epcb = pc_bytes_run_length_encode(pcb);
|
||||
pcb2 = pc_bytes_run_length_decode(epcb);
|
||||
|
||||
CU_ASSERT_EQUAL(memcmp(pcb.bytes, pcb2.bytes, pcb.size), 0);
|
||||
CU_ASSERT_EQUAL(pcb.size, pcb2.size);
|
||||
CU_ASSERT_EQUAL(pcb.npoints, pcb2.npoints);
|
||||
pc_bytes_free(epcb);
|
||||
pc_bytes_free(pcb2);
|
||||
|
||||
bytes = "aabcdefg";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
epcb = pc_bytes_run_length_encode(pcb);
|
||||
pcb2 = pc_bytes_run_length_decode(epcb);
|
||||
CU_ASSERT_EQUAL(memcmp(pcb.bytes, pcb2.bytes, pcb.size), 0);
|
||||
CU_ASSERT_EQUAL(pcb.size, pcb2.size);
|
||||
CU_ASSERT_EQUAL(pcb.npoints, pcb2.npoints);
|
||||
pc_bytes_free(epcb);
|
||||
pc_bytes_free(pcb2);
|
||||
|
||||
bytes = (uint8_t*)((uint32_t[]){ 10, 10, 10, 20, 20, 30, 20, 20 });
|
||||
pcb = initbytes(bytes, 8, PC_UINT32);
|
||||
epcb = pc_bytes_run_length_encode(pcb);
|
||||
pcb2 = pc_bytes_run_length_decode(epcb);
|
||||
CU_ASSERT_EQUAL(memcmp(pcb.bytes, pcb2.bytes, pcb.size), 0);
|
||||
CU_ASSERT_EQUAL(pcb.size, pcb2.size);
|
||||
CU_ASSERT_EQUAL(pcb.npoints, pcb2.npoints);
|
||||
pc_bytes_free(epcb);
|
||||
pc_bytes_free(pcb2);
|
||||
|
||||
bytes = (uint8_t*)((uint16_t[]){ 10, 10, 10, 20, 20, 30, 20, 20 });
|
||||
pcb = initbytes(bytes, 8, PC_UINT16);
|
||||
epcb = pc_bytes_run_length_encode(pcb);
|
||||
pcb2 = pc_bytes_run_length_decode(epcb);
|
||||
CU_ASSERT_EQUAL(memcmp(pcb.bytes, pcb2.bytes, pcb.size), 0);
|
||||
CU_ASSERT_EQUAL(pcb.size, pcb2.size);
|
||||
CU_ASSERT_EQUAL(pcb.npoints, pcb2.npoints);
|
||||
pc_bytes_free(epcb);
|
||||
pc_bytes_free(pcb2);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Strip the common bits off a stream and pack the
|
||||
* remaining bits in behind. Test bit counting and
|
||||
* round-trip encode/decode paths.
|
||||
*/
|
||||
static void
|
||||
test_sigbits_encoding()
|
||||
{
|
||||
int i;
|
||||
uint8_t *bytes, *ebytes;
|
||||
uint16_t *bytes16, *ebytes16;
|
||||
uint32_t *bytes32, *ebytes32;
|
||||
size_t ebytes_size;
|
||||
|
||||
uint32_t count, nelems;
|
||||
uint8_t common8;
|
||||
uint16_t common16;
|
||||
uint32_t common32;
|
||||
PCBYTES pcb, epcb, pcb2;
|
||||
|
||||
/*
|
||||
01100001 a
|
||||
01100010 b
|
||||
01100011 c
|
||||
01100000 `
|
||||
*/
|
||||
bytes = "abc";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
common8 = pc_bytes_sigbits_count_8(&pcb, &count);
|
||||
CU_ASSERT_EQUAL(count, 6);
|
||||
CU_ASSERT_EQUAL(common8, '`');
|
||||
|
||||
bytes = "abcdef";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT8);
|
||||
common8 = pc_bytes_sigbits_count_8(&pcb, &count);
|
||||
CU_ASSERT_EQUAL(count, 5);
|
||||
CU_ASSERT_EQUAL(common8, '`');
|
||||
|
||||
/*
|
||||
0110000101100001 aa
|
||||
0110001001100010 bb
|
||||
0110001101100011 cc
|
||||
0110000000000000 24576
|
||||
*/
|
||||
bytes = "aabbcc";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_UINT16);
|
||||
count = pc_bytes_sigbits_count(&pcb);
|
||||
CU_ASSERT_EQUAL(count, 6);
|
||||
|
||||
/*
|
||||
"abca" encoded:
|
||||
base a b c a
|
||||
01100000 01 10 11 01
|
||||
*/
|
||||
bytes = "abcaabcaabcbabcc";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_INT8);
|
||||
epcb = pc_bytes_sigbits_encode(pcb);
|
||||
CU_ASSERT_EQUAL(epcb.bytes[0], 2); /* unique bit count */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[1], 96); /* common bits */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[2], 109); /* packed byte */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[3], 109); /* packed byte */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[4], 110); /* packed byte */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[5], 111); /* packed byte */
|
||||
pc_bytes_free(epcb);
|
||||
|
||||
/*
|
||||
"abca" encoded:
|
||||
base a b c d a b
|
||||
01100000 001 010 011 100 001 010
|
||||
*/
|
||||
bytes = "abcdab";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_INT8);
|
||||
epcb = pc_bytes_sigbits_encode(pcb);
|
||||
CU_ASSERT_EQUAL(epcb.bytes[0], 3); /* unique bit count */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[1], 96); /* common bits */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[2], 41); /* packed byte */
|
||||
CU_ASSERT_EQUAL(epcb.bytes[3], 194); /* packed byte */
|
||||
|
||||
pcb2 = pc_bytes_sigbits_decode(epcb);
|
||||
CU_ASSERT_EQUAL(pcb2.bytes[0], 'a');
|
||||
CU_ASSERT_EQUAL(pcb2.bytes[1], 'b');
|
||||
CU_ASSERT_EQUAL(pcb2.bytes[2], 'c');
|
||||
CU_ASSERT_EQUAL(pcb2.bytes[3], 'd');
|
||||
CU_ASSERT_EQUAL(pcb2.bytes[4], 'a');
|
||||
CU_ASSERT_EQUAL(pcb2.bytes[5], 'b');
|
||||
pc_bytes_free(pcb2);
|
||||
pc_bytes_free(epcb);
|
||||
|
||||
/* Test the 16 bit implementation path */
|
||||
nelems = 6;
|
||||
bytes16 = (uint16_t[]){
|
||||
24929, /* 0110000101100001 */
|
||||
24930, /* 0110000101100010 */
|
||||
24931, /* 0110000101100011 */
|
||||
24932, /* 0110000101100100 */
|
||||
24933, /* 0110000101100101 */
|
||||
24934 /* 0110000101100110 */
|
||||
};
|
||||
/* encoded 0110000101100 001 010 011 100 101 110 */
|
||||
bytes = (uint8_t*)bytes16;
|
||||
pcb = initbytes(bytes, nelems*2, PC_INT16);
|
||||
|
||||
/* Test the 16 bit implementation path */
|
||||
common16 = pc_bytes_sigbits_count_16(&pcb, &count);
|
||||
CU_ASSERT_EQUAL(common16, 24928);
|
||||
CU_ASSERT_EQUAL(count, 13);
|
||||
epcb = pc_bytes_sigbits_encode(pcb);
|
||||
ebytes16 = (uint16_t*)(epcb.bytes);
|
||||
// printf("commonbits %d\n", commonbits);
|
||||
CU_ASSERT_EQUAL(ebytes16[0], 3); /* unique bit count */
|
||||
CU_ASSERT_EQUAL(ebytes16[1], 24928); /* common bits */
|
||||
CU_ASSERT_EQUAL(ebytes16[2], 10699); /* packed uint16 one */
|
||||
|
||||
/* uint8_t* pc_bytes_sigbits_decode(const uint8_t *bytes, uint32_t interpretation, uint32_t nelems) */
|
||||
pcb2 = pc_bytes_sigbits_decode(epcb);
|
||||
pc_bytes_free(epcb);
|
||||
bytes16 = (uint16_t*)(pcb2.bytes);
|
||||
CU_ASSERT_EQUAL(bytes16[0], 24929);
|
||||
CU_ASSERT_EQUAL(bytes16[1], 24930);
|
||||
CU_ASSERT_EQUAL(bytes16[2], 24931);
|
||||
CU_ASSERT_EQUAL(bytes16[3], 24932);
|
||||
CU_ASSERT_EQUAL(bytes16[4], 24933);
|
||||
CU_ASSERT_EQUAL(bytes16[5], 24934);
|
||||
pc_bytes_free(pcb2);
|
||||
|
||||
/* Test the 32 bit implementation path */
|
||||
nelems = 6;
|
||||
|
||||
bytes32 = (uint32_t[]){
|
||||
103241, /* 0000000000000001 1001 0011 0100 1001 */
|
||||
103251, /* 0000000000000001 1001 0011 0101 0011 */
|
||||
103261, /* 0000000000000001 1001 0011 0101 1101 */
|
||||
103271, /* 0000000000000001 1001 0011 0110 0111 */
|
||||
103281, /* 0000000000000001 1001 0011 0111 0001 */
|
||||
103291 /* 0000000000000001 1001 0011 0111 1011 */
|
||||
};
|
||||
bytes = (uint8_t*)bytes32;
|
||||
pcb = initbytes(bytes, nelems*4, PC_INT32);
|
||||
|
||||
common32 = pc_bytes_sigbits_count_32(&pcb, &count);
|
||||
CU_ASSERT_EQUAL(count, 26); /* unique bit count */
|
||||
CU_ASSERT_EQUAL(common32, 103232);
|
||||
|
||||
epcb = pc_bytes_sigbits_encode(pcb);
|
||||
ebytes32 = (uint32_t*)(epcb.bytes);
|
||||
CU_ASSERT_EQUAL(ebytes32[0], 6); /* unique bit count */
|
||||
CU_ASSERT_EQUAL(ebytes32[1], 103232); /* common bits */
|
||||
CU_ASSERT_EQUAL(ebytes32[2], 624388039); /* packed uint32 */
|
||||
|
||||
pcb2 = pc_bytes_sigbits_decode(epcb);
|
||||
pc_bytes_free(epcb);
|
||||
bytes32 = (uint32_t*)(pcb2.bytes);
|
||||
CU_ASSERT_EQUAL(bytes32[0], 103241);
|
||||
CU_ASSERT_EQUAL(bytes32[1], 103251);
|
||||
CU_ASSERT_EQUAL(bytes32[2], 103261);
|
||||
CU_ASSERT_EQUAL(bytes32[3], 103271);
|
||||
CU_ASSERT_EQUAL(bytes32[4], 103281);
|
||||
CU_ASSERT_EQUAL(bytes32[5], 103291);
|
||||
pc_bytes_free(pcb2);
|
||||
|
||||
/* What if all the words are the same? */
|
||||
nelems = 6;
|
||||
bytes16 = (uint16_t[]){
|
||||
24929, /* 0000000000000001 1001 0011 0100 1001 */
|
||||
24929, /* 0000000000000001 1001 0011 0101 0011 */
|
||||
24929, /* 0000000000000001 1001 0011 0101 1101 */
|
||||
24929, /* 0000000000000001 1001 0011 0110 0111 */
|
||||
24929, /* 0000000000000001 1001 0011 0111 0001 */
|
||||
24929 /* 0000000000000001 1001 0011 0111 1011 */
|
||||
};
|
||||
bytes = (uint8_t*)bytes16;
|
||||
pcb = initbytes(bytes, nelems*2, PC_INT16);
|
||||
epcb = pc_bytes_sigbits_encode(pcb);
|
||||
pcb2 = pc_bytes_sigbits_decode(epcb);
|
||||
pc_bytes_free(epcb);
|
||||
pc_bytes_free(pcb2);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode and decode a byte stream. Data matches?
|
||||
*/
|
||||
static void
|
||||
test_zlib_encoding()
|
||||
{
|
||||
uint8_t *bytes, *ebytes;
|
||||
uint32_t i;
|
||||
PCBYTES pcb, epcb, pcb2;
|
||||
/*
|
||||
uint8_t *
|
||||
pc_bytes_zlib_encode(const uint8_t *bytes, uint32_t interpretation, uint32_t nelems)
|
||||
uint8_t *
|
||||
pc_bytes_zlib_decode(const uint8_t *bytes, uint32_t interpretation)
|
||||
*/
|
||||
bytes = "abcaabcaabcbabcc";
|
||||
pcb = initbytes(bytes, strlen(bytes), PC_INT8);
|
||||
epcb = pc_bytes_zlib_encode(pcb);
|
||||
pcb2 = pc_bytes_zlib_decode(epcb);
|
||||
CU_ASSERT_EQUAL(memcmp(pcb.bytes, pcb2.bytes, pcb.size), 0);
|
||||
pc_bytes_free(epcb);
|
||||
pc_bytes_free(pcb2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pivot a pointlist into a dimlist and back.
|
||||
@ -832,9 +516,6 @@ CU_TestInfo patch_tests[] = {
|
||||
PC_TEST(test_patch_hex_in),
|
||||
PC_TEST(test_patch_hex_out),
|
||||
PC_TEST(test_schema_xy),
|
||||
PC_TEST(test_run_length_encoding),
|
||||
PC_TEST(test_sigbits_encoding),
|
||||
PC_TEST(test_zlib_encoding),
|
||||
PC_TEST(test_patch_dimensional),
|
||||
PC_TEST(test_patch_dimensional_compression),
|
||||
PC_TEST(test_patch_union),
|
||||
|
||||
@ -82,11 +82,66 @@ test_point_hex_inout()
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
test_point_access()
|
||||
{
|
||||
PCPOINT *pt;
|
||||
int rv;
|
||||
double a1, a2, a3, a4, b1, b2, b3, b4;
|
||||
int idx = 0;
|
||||
|
||||
pt = pc_point_make(schema);
|
||||
CU_ASSERT( pt != NULL );
|
||||
|
||||
/* One at a time */
|
||||
idx = 0;
|
||||
a1 = 1.5;
|
||||
rv = pc_point_set_double_by_index(pt, idx, a1);
|
||||
rv = pc_point_get_double_by_index(pt, idx, &b1);
|
||||
// printf("d1=%g, d2=%g\n", a1, b1);
|
||||
CU_ASSERT_DOUBLE_EQUAL(a1, b1, 0.0000001);
|
||||
|
||||
idx = 2;
|
||||
a2 = 1501500.12;
|
||||
rv = pc_point_set_double_by_index(pt, idx, a2);
|
||||
rv = pc_point_get_double_by_index(pt, idx, &b2);
|
||||
CU_ASSERT_DOUBLE_EQUAL(a2, b2, 0.0000001);
|
||||
|
||||
a3 = 91;
|
||||
rv = pc_point_set_double_by_name(pt, "Intensity", a3);
|
||||
rv = pc_point_get_double_by_name(pt, "Intensity", &b3);
|
||||
CU_ASSERT_DOUBLE_EQUAL(a3, b3, 0.0000001);
|
||||
|
||||
pc_point_free(pt);
|
||||
|
||||
/* All at once */
|
||||
pt = pc_point_make(schema);
|
||||
a1 = 1.5;
|
||||
a2 = 1501500.12;
|
||||
a3 = 91;
|
||||
a4 = 200;
|
||||
rv = pc_point_set_double_by_index(pt, 0, a1);
|
||||
rv = pc_point_set_double_by_index(pt, 1, a2);
|
||||
rv = pc_point_set_double_by_name(pt, "Intensity", a3);
|
||||
rv = pc_point_set_double_by_name(pt, "Z", a4);
|
||||
rv = pc_point_get_double_by_index(pt, 0, &b1);
|
||||
rv = pc_point_get_double_by_index(pt, 1, &b2);
|
||||
rv = pc_point_get_double_by_name(pt, "Intensity", &b3);
|
||||
rv = pc_point_get_double_by_name(pt, "Z", &b4);
|
||||
CU_ASSERT_DOUBLE_EQUAL(a1, b1, 0.0000001);
|
||||
CU_ASSERT_DOUBLE_EQUAL(a2, b2, 0.0000001);
|
||||
CU_ASSERT_DOUBLE_EQUAL(a3, b3, 0.0000001);
|
||||
CU_ASSERT_DOUBLE_EQUAL(a4, b4, 0.0000001);
|
||||
|
||||
pc_point_free(pt);
|
||||
|
||||
}
|
||||
|
||||
/* REGISTER ***********************************************************/
|
||||
|
||||
CU_TestInfo point_tests[] = {
|
||||
PC_TEST(test_point_hex_inout),
|
||||
PC_TEST(test_point_access),
|
||||
CU_TEST_INFO_NULL
|
||||
};
|
||||
|
||||
|
||||
@ -115,60 +115,7 @@ test_dimension_byteoffsets()
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
test_point_access()
|
||||
{
|
||||
PCPOINT *pt;
|
||||
int rv;
|
||||
double a1, a2, a3, a4, b1, b2, b3, b4;
|
||||
int idx = 0;
|
||||
|
||||
pt = pc_point_make(schema);
|
||||
CU_ASSERT( pt != NULL );
|
||||
|
||||
/* One at a time */
|
||||
idx = 0;
|
||||
a1 = 1.5;
|
||||
rv = pc_point_set_double_by_index(pt, idx, a1);
|
||||
rv = pc_point_get_double_by_index(pt, idx, &b1);
|
||||
// printf("d1=%g, d2=%g\n", a1, b1);
|
||||
CU_ASSERT_DOUBLE_EQUAL(a1, b1, 0.0000001);
|
||||
|
||||
idx = 2;
|
||||
a2 = 1501500.12;
|
||||
rv = pc_point_set_double_by_index(pt, idx, a2);
|
||||
rv = pc_point_get_double_by_index(pt, idx, &b2);
|
||||
CU_ASSERT_DOUBLE_EQUAL(a2, b2, 0.0000001);
|
||||
|
||||
a3 = 91;
|
||||
rv = pc_point_set_double_by_name(pt, "NumberOfReturns", a3);
|
||||
rv = pc_point_get_double_by_name(pt, "NumberOfReturns", &b3);
|
||||
CU_ASSERT_DOUBLE_EQUAL(a3, b3, 0.0000001);
|
||||
|
||||
pc_point_free(pt);
|
||||
|
||||
/* All at once */
|
||||
pt = pc_point_make(schema);
|
||||
a1 = 1.5;
|
||||
a2 = 1501500.12;
|
||||
a3 = 91;
|
||||
a4 = 200;
|
||||
rv = pc_point_set_double_by_index(pt, 0, a1);
|
||||
rv = pc_point_set_double_by_index(pt, 2, a2);
|
||||
rv = pc_point_set_double_by_name(pt, "NumberOfReturns", a3);
|
||||
rv = pc_point_set_double_by_name(pt, "UserData", a4);
|
||||
rv = pc_point_get_double_by_index(pt, 0, &b1);
|
||||
rv = pc_point_get_double_by_index(pt, 2, &b2);
|
||||
rv = pc_point_get_double_by_name(pt, "NumberOfReturns", &b3);
|
||||
rv = pc_point_get_double_by_name(pt, "UserData", &b4);
|
||||
CU_ASSERT_DOUBLE_EQUAL(a1, b1, 0.0000001);
|
||||
CU_ASSERT_DOUBLE_EQUAL(a2, b2, 0.0000001);
|
||||
CU_ASSERT_DOUBLE_EQUAL(a3, b3, 0.0000001);
|
||||
CU_ASSERT_DOUBLE_EQUAL(a4, b4, 0.0000001);
|
||||
|
||||
pc_point_free(pt);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
test_schema_compression(void)
|
||||
@ -184,7 +131,6 @@ CU_TestInfo schema_tests[] = {
|
||||
PC_TEST(test_schema_size),
|
||||
PC_TEST(test_dimension_get),
|
||||
PC_TEST(test_dimension_byteoffsets),
|
||||
PC_TEST(test_point_access),
|
||||
PC_TEST(test_schema_compression),
|
||||
CU_TEST_INFO_NULL
|
||||
};
|
||||
|
||||
@ -17,6 +17,7 @@ extern CU_SuiteInfo schema_suite;
|
||||
extern CU_SuiteInfo patch_suite;
|
||||
extern CU_SuiteInfo point_suite;
|
||||
extern CU_SuiteInfo ght_suite;
|
||||
extern CU_SuiteInfo bytes_suite;
|
||||
|
||||
/*
|
||||
** The main() function for setting up and running the tests.
|
||||
@ -32,6 +33,7 @@ int main(int argc, char *argv[])
|
||||
patch_suite,
|
||||
point_suite,
|
||||
ght_suite,
|
||||
bytes_suite,
|
||||
CU_SUITE_INFO_NULL
|
||||
};
|
||||
|
||||
|
||||
15
lib/pc_api.h
15
lib/pc_api.h
@ -372,7 +372,7 @@ uint8_t* pc_patch_to_wkb(const PCPATCH *patch, size_t *wkbsize);
|
||||
/** Returns text form of patch */
|
||||
char* pc_patch_to_string(const PCPATCH *patch);
|
||||
|
||||
/** */
|
||||
/** Return byte buffer size of serialization */
|
||||
size_t pc_patch_dimensional_serialized_size(const PCPATCH_DIMENSIONAL *patch);
|
||||
|
||||
/** How big will the serialization be? */
|
||||
@ -402,8 +402,17 @@ int pc_patch_compute_extent(PCPATCH *patch);
|
||||
/** True/false if bounds intersect */
|
||||
int pc_bounds_intersects(const PCBOUNDS *b1, const PCBOUNDS *b2);
|
||||
|
||||
/** Returns newly allocated patch that only contains the points fitting the filter condition */
|
||||
PCPATCH* pc_patch_filter(const PCPATCH *pa, uint32_t dimnum, PC_FILTERTYPE filter, double val1, double val2);
|
||||
/** Subset batch based on less-than condition on dimension */
|
||||
PCPATCH* pc_patch_filter_lt_by_name(const PCPATCH *pa, const char *name, double val);
|
||||
|
||||
/** Subset batch based on greater-than condition on dimension */
|
||||
PCPATCH* pc_patch_filter_gt_by_name(const PCPATCH *pa, const char *name, double val);
|
||||
|
||||
/** Subset batch based on equality condition on dimension */
|
||||
PCPATCH* pc_patch_filter_equal_by_name(const PCPATCH *pa, const char *name, double val);
|
||||
|
||||
/** Subset batch based on range condition on dimension */
|
||||
PCPATCH* pc_patch_filter_between_by_name(const PCPATCH *pa, const char *name, double val1, double val2);
|
||||
|
||||
|
||||
#endif /* _PC_API_H */
|
||||
|
||||
@ -149,6 +149,9 @@ char* pc_dimstats_to_string(const PCDIMSTATS *pds);
|
||||
* PATCHES
|
||||
*/
|
||||
|
||||
/** Returns newly allocated patch that only contains the points fitting the filter condition */
|
||||
PCPATCH* pc_patch_filter(const PCPATCH *pa, uint32_t dimnum, PC_FILTERTYPE filter, double val1, double val2);
|
||||
|
||||
/* DIMENSIONAL PATCHES */
|
||||
char* pc_patch_dimensional_to_string(const PCPATCH_DIMENSIONAL *pa);
|
||||
PCPATCH_DIMENSIONAL* pc_patch_dimensional_from_uncompressed(const PCPATCH_UNCOMPRESSED *pa);
|
||||
|
||||
@ -31,6 +31,11 @@ pc_bytes_free(PCBYTES pcb)
|
||||
pcfree(pcb.bytes);
|
||||
}
|
||||
|
||||
int pc_bytes_empty(const PCBYTES *pcb)
|
||||
{
|
||||
return pcb->npoints == 0 || pcb->bytes == NULL || pcb->size == 0;
|
||||
}
|
||||
|
||||
PCBYTES
|
||||
pc_bytes_make(const PCDIMENSION *dim, uint32_t npoints)
|
||||
{
|
||||
@ -48,8 +53,11 @@ static PCBYTES
|
||||
pc_bytes_clone(PCBYTES pcb)
|
||||
{
|
||||
PCBYTES pcbnew = pcb;
|
||||
pcbnew.bytes = pcalloc(pcb.size);
|
||||
memcpy(pcbnew.bytes, pcb.bytes, pcb.size);
|
||||
if ( ! pc_bytes_empty(&pcb) )
|
||||
{
|
||||
pcbnew.bytes = pcalloc(pcb.size);
|
||||
memcpy(pcbnew.bytes, pcb.bytes, pcb.size);
|
||||
}
|
||||
pcbnew.readonly = PC_FALSE;
|
||||
return pcbnew;
|
||||
}
|
||||
@ -552,6 +560,7 @@ pc_bytes_sigbits_encode_8(const PCBYTES pcb, uint8_t commonvalue, uint8_t common
|
||||
pcbout.size = size_out;
|
||||
pcbout.bytes = bytes_out;
|
||||
pcbout.compression = PC_DIM_SIGBITS;
|
||||
pcbout.readonly = PC_FALSE;
|
||||
return pcbout;
|
||||
}
|
||||
|
||||
@ -643,6 +652,7 @@ pc_bytes_sigbits_encode_16(const PCBYTES pcb, uint16_t commonvalue, uint8_t comm
|
||||
pcbout.size = size_out;
|
||||
pcbout.bytes = bytes_out;
|
||||
pcbout.compression = PC_DIM_SIGBITS;
|
||||
pcbout.readonly = PC_FALSE;
|
||||
return pcbout;
|
||||
}
|
||||
|
||||
@ -733,6 +743,7 @@ pc_bytes_sigbits_encode_32(const PCBYTES pcb, uint32_t commonvalue, uint8_t comm
|
||||
pcbout.size = size_out;
|
||||
pcbout.bytes = bytes_out;
|
||||
pcbout.compression = PC_DIM_SIGBITS;
|
||||
pcbout.readonly = PC_FALSE;
|
||||
return pcbout;
|
||||
}
|
||||
|
||||
@ -866,6 +877,7 @@ pc_bytes_sigbits_decode_8(const PCBYTES pcb)
|
||||
pcbout.size = outbytes_size;
|
||||
pcbout.compression = PC_DIM_SIGBITS;
|
||||
pcbout.bytes = outbytes;
|
||||
pcbout.readonly = PC_FALSE;
|
||||
return pcbout;
|
||||
}
|
||||
|
||||
@ -922,6 +934,7 @@ pc_bytes_sigbits_decode_16(const PCBYTES pcb)
|
||||
pcbout.size = outbytes_size;
|
||||
pcbout.compression = PC_DIM_SIGBITS;
|
||||
pcbout.bytes = outbytes;
|
||||
pcbout.readonly = PC_FALSE;
|
||||
return pcbout;
|
||||
}
|
||||
|
||||
@ -979,6 +992,7 @@ pc_bytes_sigbits_decode_32(const PCBYTES pcb)
|
||||
pcbout.size = outbytes_size;
|
||||
pcbout.compression = PC_DIM_SIGBITS;
|
||||
pcbout.bytes = outbytes;
|
||||
pcbout.readonly = PC_FALSE;
|
||||
return pcbout;
|
||||
}
|
||||
|
||||
@ -1059,6 +1073,7 @@ pc_bytes_zlib_encode(const PCBYTES pcb)
|
||||
pcbout.size = have;
|
||||
pcbout.bytes = pcalloc(pcbout.size);
|
||||
pcbout.compression = PC_DIM_ZLIB;
|
||||
pcbout.readonly = PC_FALSE;
|
||||
memcpy(pcbout.bytes, buf, have);
|
||||
pcfree(buf);
|
||||
deflateEnd(&strm);
|
||||
@ -1082,6 +1097,7 @@ pc_bytes_zlib_decode(const PCBYTES pcb)
|
||||
|
||||
/* Set up output memory */
|
||||
pcbout.bytes = pcalloc(pcbout.size);
|
||||
pcbout.readonly = PC_FALSE;
|
||||
|
||||
/* Use our own allocators */
|
||||
strm.zalloc = pc_zlib_alloc;
|
||||
@ -1336,6 +1352,7 @@ pc_bytes_filter(const PCBYTES *pcb, const PCBITMAP *map)
|
||||
case PC_DIM_NONE:
|
||||
return pc_bytes_uncompressed_filter(pcb, map);
|
||||
|
||||
case PC_DIM_RLE:
|
||||
case PC_DIM_SIGBITS:
|
||||
case PC_DIM_ZLIB:
|
||||
{
|
||||
@ -1347,9 +1364,6 @@ pc_bytes_filter(const PCBYTES *pcb, const PCBITMAP *map)
|
||||
return efpcb;
|
||||
}
|
||||
|
||||
case PC_DIM_RLE:
|
||||
return pc_bytes_run_length_filter(pcb, map);
|
||||
|
||||
default:
|
||||
pcerror("%s: unknown compression", __func__);
|
||||
}
|
||||
|
||||
@ -159,7 +159,6 @@ pc_patch_dimensional_filter(const PCPATCH_DIMENSIONAL *pdl, const PCBITMAP *map)
|
||||
return fpdl;
|
||||
}
|
||||
|
||||
|
||||
PCPATCH *
|
||||
pc_patch_filter(const PCPATCH *pa, uint32_t dimnum, PC_FILTERTYPE filter, double val1, double val2)
|
||||
{
|
||||
@ -171,7 +170,13 @@ pc_patch_filter(const PCPATCH *pa, uint32_t dimnum, PC_FILTERTYPE filter, double
|
||||
case PC_NONE:
|
||||
{
|
||||
PCBITMAP *map = pc_patch_uncompressed_bitmap((PCPATCH_UNCOMPRESSED*)pa, dimnum, filter, val1, val2);
|
||||
PCPATCH_UNCOMPRESSED *pu = pc_patch_uncompressed_filter((PCPATCH_UNCOMPRESSED*)pa, map);
|
||||
PCPATCH_UNCOMPRESSED *pu;
|
||||
if ( map->nset == 0 )
|
||||
{
|
||||
pc_bitmap_free(map);
|
||||
return (PCPATCH*)pc_patch_uncompressed_make(pa->schema, 0);
|
||||
}
|
||||
pu = pc_patch_uncompressed_filter((PCPATCH_UNCOMPRESSED*)pa, map);
|
||||
pc_bitmap_free(map);
|
||||
paout = (PCPATCH*)pu;
|
||||
break;
|
||||
@ -180,8 +185,15 @@ pc_patch_filter(const PCPATCH *pa, uint32_t dimnum, PC_FILTERTYPE filter, double
|
||||
{
|
||||
PCPATCH_UNCOMPRESSED *pu = pc_patch_uncompressed_from_ght((PCPATCH_GHT*)pa);
|
||||
PCBITMAP *map = pc_patch_uncompressed_bitmap(pu, dimnum, filter, val1, val2);
|
||||
PCPATCH_UNCOMPRESSED *pu2 = pc_patch_uncompressed_filter(pu, map);
|
||||
PCPATCH_GHT *pgh = pc_patch_ght_from_uncompressed(pu2);
|
||||
PCPATCH_UNCOMPRESSED *pu2;
|
||||
PCPATCH_GHT *pgh;
|
||||
if ( map->nset == 0 )
|
||||
{
|
||||
pc_bitmap_free(map);
|
||||
return (PCPATCH*)pc_patch_uncompressed_make(pa->schema, 0);
|
||||
}
|
||||
pu2 = pc_patch_uncompressed_filter(pu, map);
|
||||
pgh = pc_patch_ght_from_uncompressed(pu2);
|
||||
pc_patch_free((PCPATCH*)pu);
|
||||
pc_patch_free((PCPATCH*)pu2);
|
||||
paout = (PCPATCH*)pgh;
|
||||
@ -190,7 +202,13 @@ pc_patch_filter(const PCPATCH *pa, uint32_t dimnum, PC_FILTERTYPE filter, double
|
||||
case PC_DIMENSIONAL:
|
||||
{
|
||||
PCBITMAP *map = pc_patch_dimensional_bitmap((PCPATCH_DIMENSIONAL*)pa, dimnum, filter, val1, val2);
|
||||
PCPATCH_DIMENSIONAL *pdl = pc_patch_dimensional_filter((PCPATCH_DIMENSIONAL*)pa, map);
|
||||
PCPATCH_DIMENSIONAL *pdl;
|
||||
if ( map->nset == 0 )
|
||||
{
|
||||
pc_bitmap_free(map);
|
||||
return (PCPATCH*)pc_patch_uncompressed_make(pa->schema, 0);
|
||||
}
|
||||
pdl = pc_patch_dimensional_filter((PCPATCH_DIMENSIONAL*)pa, map);
|
||||
pc_bitmap_free(map);
|
||||
paout = (PCPATCH*)pdl;
|
||||
break;
|
||||
@ -207,3 +225,52 @@ pc_patch_filter(const PCPATCH *pa, uint32_t dimnum, PC_FILTERTYPE filter, double
|
||||
|
||||
return paout;
|
||||
}
|
||||
|
||||
PCPATCH *
|
||||
pc_patch_filter_lt_by_name(const PCPATCH *pa, const char *name, double val)
|
||||
{
|
||||
/* Error out if we can't find the name */
|
||||
PCDIMENSION *d = pc_schema_get_dimension_by_name(pa->schema, name);
|
||||
if ( ! d ) return NULL;
|
||||
|
||||
return pc_patch_filter(pa, d->position, PC_LT, val, val);
|
||||
}
|
||||
|
||||
PCPATCH *
|
||||
pc_patch_filter_gt_by_name(const PCPATCH *pa, const char *name, double val)
|
||||
{
|
||||
/* Error out if we can't find the name */
|
||||
PCDIMENSION *d = pc_schema_get_dimension_by_name(pa->schema, name);
|
||||
if ( ! d ) return NULL;
|
||||
|
||||
return pc_patch_filter(pa, d->position, PC_GT, val, val);
|
||||
}
|
||||
|
||||
PCPATCH *
|
||||
pc_patch_filter_equal_by_name(const PCPATCH *pa, const char *name, double val)
|
||||
{
|
||||
/* Error out if we can't find the name */
|
||||
PCDIMENSION *d = pc_schema_get_dimension_by_name(pa->schema, name);
|
||||
if ( ! d ) return NULL;
|
||||
|
||||
return pc_patch_filter(pa, d->position, PC_EQUAL, val, val);
|
||||
}
|
||||
|
||||
PCPATCH *
|
||||
pc_patch_filter_between_by_name(const PCPATCH *pa, const char *name, double val1, double val2)
|
||||
{
|
||||
/* Ensure val1 < val2 always */
|
||||
if ( val1 > val2 )
|
||||
{
|
||||
double tmp = val1;
|
||||
val1 = val2;
|
||||
val2 = tmp;
|
||||
}
|
||||
/* Error out if we can't find the name */
|
||||
PCDIMENSION *d = pc_schema_get_dimension_by_name(pa->schema, name);
|
||||
if ( ! d ) return NULL;
|
||||
|
||||
return pc_patch_filter(pa, d->position, PC_BETWEEN, val1, val2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -124,7 +124,9 @@ void pc_set_handlers(pc_allocator allocator, pc_reallocator reallocator,
|
||||
void *
|
||||
pcalloc(size_t size)
|
||||
{
|
||||
void *mem = pc_context.alloc(size);
|
||||
void *mem;
|
||||
if ( ! size ) return NULL;
|
||||
mem = pc_context.alloc(size);
|
||||
memset(mem, 0, size); /* Always clean memory */
|
||||
return mem;
|
||||
}
|
||||
|
||||
@ -203,7 +203,7 @@ pc_patch_uncompressed_compute_extent(PCPATCH_UNCOMPRESSED *patch)
|
||||
void
|
||||
pc_patch_uncompressed_free(PCPATCH_UNCOMPRESSED *patch)
|
||||
{
|
||||
if ( ! patch->readonly )
|
||||
if ( patch->data && ! patch->readonly )
|
||||
{
|
||||
pcfree(patch->data);
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ Datum pcpatch_numpoints(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_compression(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_intersects(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_get_stat(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_filter(PG_FUNCTION_ARGS);
|
||||
Datum pcpatch_size(PG_FUNCTION_ARGS);
|
||||
Datum pcpoint_size(PG_FUNCTION_ARGS);
|
||||
Datum pc_version(PG_FUNCTION_ARGS);
|
||||
@ -633,3 +634,72 @@ Datum pcpatch_get_stat(PG_FUNCTION_ARGS)
|
||||
pfree(dim_str);
|
||||
PG_RETURN_DATUM(DirectFunctionCall1(float8_numeric, Float8GetDatum(double_result)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* PC_FilterLessThan(patch pcpatch, dimname text, value) returns PcPatch
|
||||
* PC_FilterGreaterThan(patch pcpatch, dimname text, value) returns PcPatch
|
||||
* PC_FilterEqual(patch pcpatch, dimname text, value) returns PcPatch
|
||||
* PC_FilterBetween(patch pcpatch, dimname text, value1, value2) returns PcPatch
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(pcpatch_filter);
|
||||
Datum pcpatch_filter(PG_FUNCTION_ARGS)
|
||||
{
|
||||
SERIALIZED_PATCH *serpatch = PG_GETARG_SERPATCH_P(0);
|
||||
PCSCHEMA *schema = pc_schema_from_pcid(serpatch->pcid, fcinfo);
|
||||
char *dim_name = text_to_cstring(PG_GETARG_TEXT_P(1));
|
||||
float8 value1 = PG_GETARG_FLOAT8(2);
|
||||
float8 value2 = PG_GETARG_FLOAT8(3);
|
||||
int32 mode = PG_GETARG_INT32(4);
|
||||
PCPATCH *patch;
|
||||
PCPATCH *patch_filtered;
|
||||
SERIALIZED_PATCH *serpatch_filtered;
|
||||
|
||||
patch = pc_patch_deserialize(serpatch, schema);
|
||||
if ( ! patch )
|
||||
{
|
||||
elog(ERROR, "failed to deserialize patch");
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
|
||||
switch ( mode )
|
||||
{
|
||||
case 0:
|
||||
patch_filtered = pc_patch_filter_lt_by_name(patch, dim_name, value1);
|
||||
break;
|
||||
case 1:
|
||||
patch_filtered = pc_patch_filter_gt_by_name(patch, dim_name, value1);
|
||||
break;
|
||||
case 2:
|
||||
patch_filtered = pc_patch_filter_equal_by_name(patch, dim_name, value1);
|
||||
break;
|
||||
case 3:
|
||||
patch_filtered = pc_patch_filter_between_by_name(patch, dim_name, value1, value2);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "unknown mode \"%d\"", mode);
|
||||
}
|
||||
|
||||
pc_patch_free(patch);
|
||||
PG_FREE_IF_COPY(serpatch, 0);
|
||||
|
||||
if ( ! patch_filtered )
|
||||
{
|
||||
elog(ERROR, "dimension \"%s\" does not exist", dim_name);
|
||||
}
|
||||
pfree(dim_name);
|
||||
|
||||
if ( patch_filtered->npoints <= 0 )
|
||||
{
|
||||
pc_patch_free(patch_filtered);
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
|
||||
serpatch_filtered = pc_patch_serialize(patch_filtered, NULL);
|
||||
pc_patch_free(patch_filtered);
|
||||
|
||||
PG_RETURN_POINTER(serpatch_filtered);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -163,6 +163,22 @@ CREATE OR REPLACE FUNCTION PC_PatchAvg(p pcpatch, attr text, stat text default '
|
||||
RETURNS numeric AS 'MODULE_PATHNAME', 'pcpatch_get_stat'
|
||||
LANGUAGE 'c' IMMUTABLE STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION PC_FilterLessThan(p pcpatch, attr text, v1 float8 default 0.0, v2 float8 default 0.0, mode int4 default 0)
|
||||
RETURNS pcpatch AS 'MODULE_PATHNAME', 'pcpatch_filter'
|
||||
LANGUAGE 'c' IMMUTABLE STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION PC_FilterGreaterThan(p pcpatch, attr text, v1 float8 default 0.0, v2 float8 default 0.0, mode int4 default 1)
|
||||
RETURNS pcpatch AS 'MODULE_PATHNAME', 'pcpatch_filter'
|
||||
LANGUAGE 'c' IMMUTABLE STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION PC_FilterEquals(p pcpatch, attr text, v1 float8 default 0.0, v2 float8 default 0.0, mode int4 default 2)
|
||||
RETURNS pcpatch AS 'MODULE_PATHNAME', 'pcpatch_filter'
|
||||
LANGUAGE 'c' IMMUTABLE STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION PC_FilterBetween(p pcpatch, attr text, v1 float8 default 0.0, v2 float8 default 0.0, mode int4 default 3)
|
||||
RETURNS pcpatch AS 'MODULE_PATHNAME', 'pcpatch_filter'
|
||||
LANGUAGE 'c' IMMUTABLE STRICT;
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- POINTCLOUD_COLUMNS
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user