Merge branch 'jb/restage/chop-fast' into jb/release/vere

This commit is contained in:
Joe Bryan 2022-11-18 17:43:46 -05:00
commit 1ec977aede
5 changed files with 700 additions and 411 deletions

View File

@ -363,11 +363,43 @@
u3r_bytes_all(c3_w* len_w,
u3_atom a);
/* u3r_chop_bits():
**
** XOR `wid_d` bits from`src_w` at `bif_g` to `dst_w` at `bif_g`
**
** NB: [dst_w] must have space for [bit_g + wid_d] bits
*/
void
u3r_chop_bits(c3_g bif_g,
c3_d wid_d,
c3_g bit_g,
c3_w* dst_w,
const c3_w* src_w);
/* u3r_chop_words():
**
** Into the bloq space of `met`, from position `fum` for a
** span of `wid`, to position `tou`, XOR from `src_w`
** into `dst_w`.
**
** NB: [dst_w] must have space for [tou_w + wid_w] bloqs
*/
void
u3r_chop_words(c3_g met_g,
c3_w fum_w,
c3_w wid_w,
c3_w tou_w,
c3_w* dst_w,
c3_w len_w,
const c3_w* src_w);
/* u3r_chop():
**
** Into the bloq space of `met`, from position `fum` for a
** span of `wid`, to position `tou`, XOR from atom `src`
** into ray `dst`.
** into `dst_w`.
**
** NB: [dst_w] must have space for [tou_w + wid_w] bloqs
*/
void
u3r_chop(c3_g met_g,

View File

@ -1453,11 +1453,174 @@ u3r_safe_chub(u3_noun dat, c3_d* out_d)
return c3y;
}
/* u3r_chop_bits():
**
** XOR `wid_d` bits from`src_w` at `bif_g` to `dst_w` at `bif_g`
**
** NB: [dst_w] must have space for [bit_g + wid_d] bits
*/
void
u3r_chop_bits(c3_g bif_g,
c3_d wid_d,
c3_g bit_g,
c3_w* dst_w,
const c3_w* src_w)
{
c3_y fib_y = 32 - bif_g;
c3_y tib_y = 32 - bit_g;
// we need to chop words
//
if ( wid_d >= tib_y ) {
// align *dst_w
//
if ( bit_g ) {
c3_w low_w = src_w[0] >> bif_g;
if ( bif_g > bit_g ) {
low_w ^= src_w[1] << fib_y;
}
*dst_w++ ^= low_w << bit_g;
wid_d -= tib_y;
bif_g += tib_y;
src_w += !!(bif_g >> 5);
bif_g &= 31;
fib_y = 32 - bif_g;
}
{
size_t i_i, byt_i = wid_d >> 5;
if ( !bif_g ) {
for ( i_i = 0; i_i < byt_i; i_i++ ) {
dst_w[i_i] ^= src_w[i_i];
}
}
else {
for ( i_i = 0; i_i < byt_i; i_i++ ) {
dst_w[i_i] ^= (src_w[i_i] >> bif_g) ^ (src_w[i_i + 1] << fib_y);
}
}
src_w += byt_i;
dst_w += byt_i;
wid_d &= 31;
bit_g = 0;
}
}
// we need to chop (more) bits
//
if ( wid_d ) {
c3_w hig_w = src_w[0] >> bif_g;
if ( wid_d > fib_y ) {
hig_w ^= src_w[1] << fib_y;
}
*dst_w ^= (hig_w & ((1 << wid_d) - 1)) << bit_g;
}
}
/* u3r_chop_words():
**
** Into the bloq space of `met`, from position `fum` for a
** span of `wid`, to position `tou`, XOR from `src_w`
** into `dst_w`.
**
** NB: [dst_w] must have space for [tou_w + wid_w] bloqs
*/
void
u3r_chop_words(c3_g met_g,
c3_w fum_w,
c3_w wid_w,
c3_w tou_w,
c3_w* dst_w,
c3_w len_w,
const c3_w* src_w)
{
// operate on words
//
if ( met_g >= 5 ) {
size_t i_i, wid_i;
{
c3_g hut_g = met_g - 5;
size_t fum_i = (size_t)fum_w << hut_g;
size_t tou_i = (size_t)tou_w << hut_g;
size_t tot_i;
wid_i = (size_t)wid_w << hut_g;
tot_i = fum_i + wid_i;
// since [dst_w] must have space for (tou_w + wid_w) bloqs,
// neither conversion can overflow
//
if ( (fum_i >> hut_g != fum_w) || (tot_i - wid_i != fum_i) ) {
u3m_bail(c3__fail);
return;
}
else if ( fum_i >= len_w ) {
return;
}
if ( tot_i > len_w ) {
wid_i -= tot_i - len_w;
}
src_w += fum_i;
dst_w += tou_i;
}
for ( i_i = 0; i_i < wid_i; i_i++ ) {
dst_w[i_i] ^= src_w[i_i];
}
}
// operate on bits
//
else {
c3_d wid_d = (c3_d)wid_w << met_g;
c3_g bif_g, bit_g;
{
c3_d len_d = (c3_d)len_w << 5;
c3_d fum_d = (c3_d)fum_w << met_g;
c3_d tou_d = (c3_d)tou_w << met_g;
c3_d tot_d = fum_d + wid_d;
// see above
//
if ( (fum_d >> met_g != fum_w) || (tot_d - wid_d != fum_d) ) {
u3m_bail(c3__fail);
return;
}
else if ( fum_d > len_d ) {
return;
}
if ( tot_d > len_d ) {
wid_d -= tot_d - len_d;
}
src_w += fum_d >> 5;
dst_w += tou_d >> 5;
bif_g = fum_d & 31;
bit_g = tou_d & 31;
}
u3r_chop_bits(bif_g, wid_d, bit_g, dst_w, src_w);
}
}
/* u3r_chop():
**
** Into the bloq space of `met`, from position `fum` for a
** span of `wid`, to position `tou`, XOR from atom `src`
** into `dst_w`.
**
** NB: [dst_w] must have space for [tou_w + wid_w] bloqs
*/
void
u3r_chop(c3_g met_g,
@ -1467,65 +1630,24 @@ u3r_chop(c3_g met_g,
c3_w* dst_w,
u3_atom src)
{
c3_w i_w;
c3_w* src_w;
c3_w len_w;
c3_w* buf_w;
c3_assert(u3_none != src);
c3_assert(_(u3a_is_atom(src)));
if ( _(u3a_is_cat(src)) ) {
len_w = src ? 1 : 0;
buf_w = &src;
src_w = &src;
}
else {
u3a_atom* src_u = u3a_to_ptr(src);
c3_assert(u3_none != src);
c3_assert(_(u3a_is_atom(src)));
len_w = src_u->len_w;
buf_w = src_u->buf_w;
src_w = src_u->buf_w;
}
if ( met_g < 5 ) {
c3_w san_w = (1 << met_g);
c3_w mek_w = ((1 << san_w) - 1);
c3_w baf_w = (fum_w << met_g);
c3_w bat_w = (tou_w << met_g);
// XX: efficiency: poor. Iterate by words.
//
for ( i_w = 0; i_w < wid_w; i_w++ ) {
c3_w waf_w = (baf_w >> 5);
c3_g raf_g = (baf_w & 31);
c3_w wat_w = (bat_w >> 5);
c3_g rat_g = (bat_w & 31);
c3_w hop_w;
hop_w = (waf_w >= len_w) ? 0 : buf_w[waf_w];
hop_w = (hop_w >> raf_g) & mek_w;
dst_w[wat_w] ^= (hop_w << rat_g);
baf_w += san_w;
bat_w += san_w;
}
}
else {
c3_g hut_g = (met_g - 5);
c3_w san_w = (1 << hut_g);
c3_w j_w;
for ( i_w = 0; i_w < wid_w; i_w++ ) {
c3_w wuf_w = (fum_w + i_w) << hut_g;
c3_w wut_w = (tou_w + i_w) << hut_g;
for ( j_w = 0; j_w < san_w; j_w++ ) {
dst_w[wut_w + j_w] ^=
((wuf_w + j_w) >= len_w)
? 0
: buf_w[wuf_w + j_w];
}
}
}
u3r_chop_words(met_g, fum_w, wid_w, tou_w, dst_w, len_w, src_w);
}
/* u3r_string(): `a` as malloced C string.

View File

@ -0,0 +1,68 @@
#include "all.h"
#include "ur/ur.h"
#include "vere/ivory.h"
#include "vere/vere.h"
/* _setup(): prepare for tests.
*/
static void
_setup(void)
{
c3_d len_d = u3_Ivory_pill_len;
c3_y* byt_y = u3_Ivory_pill;
u3_cue_xeno* sil_u;
u3_weak pil;
u3C.wag_w |= u3o_hashless;
u3m_boot_lite(1 << 26);
sil_u = u3s_cue_xeno_init_with(ur_fib27, ur_fib28);
if ( u3_none == (pil = u3s_cue_xeno_with(sil_u, len_d, byt_y)) ) {
printf("*** fail _setup 1\n");
exit(1);
}
u3s_cue_xeno_done(sil_u);
if ( c3n == u3v_boot_lite(pil) ) {
printf("*** fail _setup 2\n");
exit(1);
}
}
/* _test_lily(): test small noun parsing.
*/
static void
_test_lily()
{
c3_l lit_l;
c3_w big_w[] = {0, 0, 1};
u3_noun big = u3i_words(3, big_w);
u3_noun cod = u3dc("scot", c3__uv, big);
if ( c3y == u3v_lily(c3__uv, cod, &lit_l) ) {
printf("*** fail _test_lily-1\n");
exit(1);
}
cod = u3dc("scot", c3__ud, 0x7fffffff);
if ( (c3n == u3v_lily(c3__ud, cod, &lit_l)) ||
(0x7fffffff != lit_l) ) {
printf("*** fail _test_lily-2a\n");
exit(1);
}
cod = u3dc("scot", c3__ux, u3i_word(0x80000000));
if ( c3y == u3v_lily(c3__ux, cod, &lit_l) ) {
printf("*** fail _test_lily-2b\n");
exit(1);
}
}
/* main(): run all test cases.
*/
int
main(int argc, char* argv[])
{
_setup();
_test_lily();
fprintf(stderr, "test boot: ok\n");
return 0;
}

View File

@ -1,7 +1,4 @@
#include "all.h"
#include "ur/ur.h"
#include "vere/ivory.h"
#include "vere/vere.h"
#define TRUE 1
#define FALSE 0
@ -11,23 +8,358 @@
static void
_setup(void)
{
c3_d len_d = u3_Ivory_pill_len;
c3_y* byt_y = u3_Ivory_pill;
u3_cue_xeno* sil_u;
u3_weak pil;
u3m_init(1 << 20);
u3m_pave(c3y);
}
u3C.wag_w |= u3o_hashless;
u3m_boot_lite(u3a_bytes);
sil_u = u3s_cue_xeno_init_with(ur_fib27, ur_fib28);
if ( u3_none == (pil = u3s_cue_xeno_with(sil_u, len_d, byt_y)) ) {
printf("*** fail _setup 1\n");
exit(1);
/* _test_u3r_chop: "extract bit slices from atom"
*/
static c3_i
_test_u3r_chop()
{
c3_i ret_i = 1;
c3_w dst_w = 0;
u3_atom src = 0b11011;
// bloq 0
//
{
// read 1 bit from pos=0 (far right)
//
dst_w = 0;
u3r_chop(0, 0, 1, 0, &dst_w, src);
if ( 0x1 != dst_w ) {
fprintf(stderr, "test: u3r_chop: bloq 0, 0\r\n");
ret_i = 0;
}
u3s_cue_xeno_done(sil_u);
if ( c3n == u3v_boot_lite(pil) ) {
printf("*** fail _setup 2\n");
exit(1);
// read 1 bit from pos=1
//
dst_w = 0;
u3r_chop(0, 1, 1, 0, &dst_w, src);
if ( 0x1 != dst_w ) {
fprintf(stderr, "test: u3r_chop: bloq 0, 1\r\n");
ret_i = 0;
}
// read 1 bit from pos=2
//
dst_w = 0;
u3r_chop(0, 2, 1, 0, &dst_w, src);
if ( 0x0 != dst_w ) {
fprintf(stderr, "test: u3r_chop: bloq 0, 2\r\n");
ret_i = 0;
}
// read 4 x 1 bit bloq from pos=0
//
dst_w = 0;
u3r_chop(0, 0, 4, 0, &dst_w, src);
if ( 0b1011 != dst_w ) {
fprintf(stderr, "test: u3r_chop: bloq 0, 3\r\n");
ret_i = 0;
}
// read 4 x 1 bit bloq from pos=0 into offset 1
//
dst_w = 0;
u3r_chop(0, 0, 4, 1, &dst_w, src);
if ( 0b10110 != dst_w ) {
fprintf(stderr, "test: u3r_chop: bloq 0, 4\r\n");
ret_i = 0;
}
}
// bloq 1
//
{
// read 2 bit from pos=0 (far right)
//
dst_w = 0;
u3r_chop(1, 0, 1, 0, &dst_w, src);
if ( 0b11 != dst_w ) {
fprintf(stderr, "test: u3r_chop: bloq 1, 0\r\n");
ret_i = 0;
}
// read 2 bit from pos=1
//
dst_w = 0;
u3r_chop(1, 1, 1, 0, &dst_w, src);
if ( 0b10 != dst_w ) {
fprintf(stderr, "test: u3r_chop: bloq 1, 1\r\n");
ret_i = 0;
}
// read 2 bit from pos=2 (2 bloq over)
dst_w = 0;
u3r_chop(1, 2, 1, 0, &dst_w, src);
if ( 0b01 != dst_w ) {
fprintf(stderr, "test: u3r_chop: bloq 1, 2\r\n");
ret_i = 0;
}
}
// bloq 3
{
dst_w = 0;
u3r_chop(3, 0, 1, 0, &dst_w, src);
if ( 0b11011 != dst_w ) {
fprintf(stderr, "test: u3r_chop: bloq 3, 0\r\n");
ret_i = 0;
}
}
// read 1,8,16 bit bloqs from an indirect atom
//
{
src = u3i_string("abcdefghij");
// 1 bit pos=0 (far right)
//
dst_w = 0;
u3r_chop(0, 0, 1, 0, &dst_w, src);
if ( 0b1 != dst_w ) {
fprintf(stderr, "test: u3r_chop: indirect 0\r\n");
ret_i = 0;
}
// 8 bits pos=0
//
dst_w = 0;
u3r_chop(0, 0, 8, 0, &dst_w, src);
if ( 0b1100001 != dst_w ) {
fprintf(stderr, "test: u3r_chop: indirect 1\r\n");
ret_i = 0;
}
// 1 byte pos=0
//
dst_w = 0;
u3r_chop(3, 0, 1, 0, &dst_w, src);
if ( 0b1100001 != dst_w ) {
fprintf(stderr, "test: u3r_chop: indirect 2\r\n");
ret_i = 0;
}
// 1 short pos=0
//
dst_w = 0;
u3r_chop(4, 0, 1, 0, &dst_w, src);
if ( 0b0110001001100001 != dst_w ) {
fprintf(stderr, "test: u3r_chop: indirect 3\r\n");
ret_i = 0;
}
u3z(src);
}
// read lots of bits from a direct noun which holds 64 bits of data
// makes sure that we handle top 32 / bottom 32 correctly
{
c3_y inp_y[8] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 };
src = u3i_bytes(8, inp_y);
c3_w dst_w[2] = {0};
u3r_chop(0, 0, 63, 0, dst_w, src);
if ( (0x3020100 != dst_w[0]) || (0x7060504 != dst_w[1]) ) {
fprintf(stderr, "test: u3r_chop: indirect 4\r\n");
ret_i = 0;
}
u3z(src);
}
// as above (read lots of bits from a direct noun which holds 64 bits of data
// makes sure that we handle top 32 / bottom 32 correctly)
// but with a bit more nuance
{
c3_y inp_y[8] = { 0x0, 0x0, 0x0, 0xaa, 0xff, 0x0, 0x0, 0x0 };
src = u3i_bytes(8, (c3_y*)inp_y);
dst_w = 0;
u3r_chop(0, 24, 16, 0, &dst_w, src);
if ( 0b1111111110101010 != dst_w ) {
fprintf(stderr, "test: u3r_chop: indirect 5\r\n");
ret_i = 0;
}
u3z(src);
}
return ret_i;
}
/* _test_chop_slow(): "golden master" for chop tests (formerly u3r_chop())
*/
void
_test_chop_slow(c3_g met_g,
c3_w fum_w,
c3_w wid_w,
c3_w tou_w,
c3_w* dst_w,
c3_w len_w,
c3_w* buf_w)
{
c3_w i_w;
if ( met_g < 5 ) {
c3_w san_w = (1 << met_g);
c3_w mek_w = ((1 << san_w) - 1);
c3_w baf_w = (fum_w << met_g);
c3_w bat_w = (tou_w << met_g);
// XX: efficiency: poor. Iterate by words.
//
for ( i_w = 0; i_w < wid_w; i_w++ ) {
c3_w waf_w = (baf_w >> 5);
c3_g raf_g = (baf_w & 31);
c3_w wat_w = (bat_w >> 5);
c3_g rat_g = (bat_w & 31);
c3_w hop_w;
hop_w = (waf_w >= len_w) ? 0 : buf_w[waf_w];
hop_w = (hop_w >> raf_g) & mek_w;
dst_w[wat_w] ^= (hop_w << rat_g);
baf_w += san_w;
bat_w += san_w;
}
}
else {
c3_g hut_g = (met_g - 5);
c3_w san_w = (1 << hut_g);
c3_w j_w;
for ( i_w = 0; i_w < wid_w; i_w++ ) {
c3_w wuf_w = (fum_w + i_w) << hut_g;
c3_w wut_w = (tou_w + i_w) << hut_g;
for ( j_w = 0; j_w < san_w; j_w++ ) {
dst_w[wut_w + j_w] ^=
((wuf_w + j_w) >= len_w)
? 0
: buf_w[wuf_w + j_w];
}
}
}
}
/* _test_chop_smol(): test permuations of chop from bloq 0-4
*/
static c3_i
_test_chop_smol(c3_c* cap_c, c3_y val_y)
{
c3_i ret_i = 1;
c3_g met_g;
c3_w fum_w, wid_w, tou_w;
c3_w len_w = 34; // (rsh [0 5] (mul 2 (mul 34 (bex 4))))
c3_w src_w[len_w];
c3_w a_w[len_w];
c3_w b_w[len_w];
memset(src_w, val_y, len_w << 2);
for ( met_g = 0; met_g < 5; met_g++ ) {
for ( fum_w = 0; fum_w <= len_w; fum_w++ ) {
for ( wid_w = 0; wid_w <= len_w; wid_w++ ) {
for ( tou_w = 0; tou_w <= len_w; tou_w++ ) {
memset(a_w, 0, len_w << 2);
memset(b_w, 0, len_w << 2);
u3r_chop_words(met_g, fum_w, wid_w, tou_w, a_w, len_w, src_w);
_test_chop_slow(met_g, fum_w, wid_w, tou_w, b_w, len_w, src_w);
if ( 0 != memcmp(a_w, b_w, len_w << 2) ) {
c3_g sif_g = 5 - met_g;
c3_w mas_w = (1 << met_g) - 1;
c3_w out_w = tou_w >> sif_g;
c3_w max_w = out_w + !!(fum_w & mas_w)
+ (wid_w >> sif_g) + !!(wid_w & mas_w);
fprintf(stderr, "%s (0x%x): met_g=%u fum_w=%u wid_w=%u tou_w=%u\r\n",
cap_c, val_y,
met_g, fum_w, wid_w, tou_w);
fprintf(stderr, "%u-%u: ", out_w, max_w - 1);
for ( ; out_w < max_w; out_w++ ) {
fprintf(stderr, "[0x%x 0x%x] ", a_w[out_w], b_w[out_w]);
}
fprintf(stderr, "\r\n");
}
}
}
}
}
return ret_i;
}
/* _test_chop_huge(): test permuations of chop from bloq 5+
*/
static c3_i
_test_chop_huge(c3_c* cap_c, c3_y val_y)
{
c3_i ret_i = 1;
c3_g met_g;
c3_w fum_w, wid_w, tou_w;
c3_w len_w = 192; // (rsh [0 5] (mul 2 (mul 3 (bex 10))))
c3_w src_w[len_w];
c3_w a_w[len_w];
c3_w b_w[len_w];
memset(src_w, val_y, len_w << 2);
for ( met_g = 5; met_g <= 10; met_g++ ) {
for ( fum_w = 0; fum_w <= 3; fum_w++ ) {
for ( wid_w = 0; wid_w <= 2; wid_w++ ) {
for ( tou_w = 0; tou_w <= 1; tou_w++ ) {
memset(a_w, 0, len_w << 2);
memset(b_w, 0, len_w << 2);
u3r_chop_words(met_g, fum_w, wid_w, tou_w, a_w, len_w, src_w);
_test_chop_slow(met_g, fum_w, wid_w, tou_w, b_w, len_w, src_w);
if ( 0 != memcmp(a_w, b_w, len_w << 2) ) {
c3_g sif_g = met_g - 5;
c3_w mas_w = (1 << met_g) - 1;
c3_w out_w = tou_w << sif_g;
c3_w max_w = out_w + !!(fum_w & mas_w)
+ (wid_w << sif_g) + !!(wid_w & mas_w);
fprintf(stderr, "%s (0x%x): met_g=%u fum_w=%u wid_w=%u tou_w=%u\r\n",
cap_c, val_y,
met_g, fum_w, wid_w, tou_w);
fprintf(stderr, "%u-%u: ", out_w, max_w - 1);
for ( ; out_w < max_w; out_w++ ) {
fprintf(stderr, "[0x%x 0x%x] ", a_w[out_w], b_w[out_w]);
}
fprintf(stderr, "\r\n");
}
}
}
}
}
return ret_i;
}
/* _test_u3r_chop(): bit slice XOR
*/
static c3_i
_test_chop()
{
return _test_u3r_chop()
& _test_chop_smol("chop smol zeros", 0x0)
& _test_chop_smol("chop smol ones", 0xff)
& _test_chop_smol("chop smol alt 1", 0xaa)
& _test_chop_smol("chop smol alt 2", 0x55)
& _test_chop_huge("chop huge zeros", 0x0)
& _test_chop_huge("chop huge ones", 0xff)
& _test_chop_huge("chop huge alt 1", 0xaa)
& _test_chop_huge("chop huge alt 2", 0x55);
}
/* _util_rand_string(): dynamically allocated len_w random string
@ -1265,256 +1597,6 @@ _test_u3r_at()
if (bignum != ret) { printf("*** u3r_at \n"); }
}
/* _test_u3r_chop: "extract bit slices from atom"
*/
static void
_test_u3r_chop()
{
c3_w dst_w = 0;
// read 1 bit bloq
{
// read 1 bit from pos=0 (far right)
u3_atom src = 0b11011;
c3_g bloqsize_g = 0;
dst_w = 0;
u3r_chop(bloqsize_g, /// bloq size
0, // start index
1, // count of bloqs
0, // end index
& dst_w, // where bytes go to
src); // where bytes come from
if (0x1 != dst_w) { printf("*** test_u3r_chop \n"); }
// read 1 bit from pos=1
dst_w = 0;
u3r_chop(bloqsize_g, /// bloq size
1, // start index
1, // count of bloqs
0, // end index
& dst_w, // where bytes go to
src); // where bytes come from
if (0x1 != dst_w) { printf("*** test_u3r_chop 2\n"); }
// read 1 bit from pos=2
dst_w = 0;
u3r_chop(bloqsize_g, /// bloq size
2, // start index
1, // count of bloqs
0, // end index
& dst_w, // where bytes go to
src); // where bytes come from
if (0x0 != dst_w) { printf("*** test_u3r_chop 3\n"); }
// read 4 x 1 bit bloq from pos=0
dst_w = 0;
u3r_chop(bloqsize_g, /// bloq size
0, // start index
4, // count of bloqs
0, // end index
& dst_w, // where bytes go to
src); // where bytes come from
if (0b1011 != dst_w) { printf("*** test_u3r_chop 4\n"); }
// read 1 x 1 bit bloq from pos=0 into offset 1
dst_w = 0;
u3r_chop(bloqsize_g, /// bloq size
0, // start index
4, // count of bloqs
1, // end index
& dst_w, // where bytes go to
src); // where bytes come from
if (0b10110 != dst_w) { printf("*** test_u3r_chop 5\n"); }
}
// read 2 bit bloq
{
u3_atom src = 0b11011;
c3_g bloqsize_g = 1;
// read 2 bit from pos=0 (far right)
dst_w = 0;
u3r_chop(bloqsize_g, /// bloq size
0, // start index
1, // count of bloqs
0, // end index
& dst_w, // where bytes go to
src); // where bytes come from
if (0b11 != dst_w) { printf("*** test_u3r_chop 2.1\n"); }
// read 2 bit from pos=1 (1 bloq over )
dst_w = 0;
u3r_chop(bloqsize_g, /// bloq size
1, // start index
1, // count of bloqs
0, // end index
& dst_w, // where bytes go to
src); // where bytes come from
if (0b10 != dst_w) { printf("*** test_u3r_chop 2.2\n"); }
// read 2 bit from pos=2 (2 bloq over)
dst_w = 0;
u3r_chop(bloqsize_g, /// bloq size
2, // start index
1, // count of bloqs
0, // end index
& dst_w, // where bytes go to
src); // where bytes come from
if (0b01 != dst_w) { printf("*** test_u3r_chop 2.3\n"); }
}
// read 8 bit bloq
{
u3_atom src = 0b11011;
c3_g bloqsize_g = 3; // 2^3 = 8 bits
// pos=0 (far right)
dst_w = 0;
u3r_chop(bloqsize_g, /// bloq size
0, // start index
1, // count of bloqs
0, // end index
& dst_w, // where bytes go to
src); // where bytes come from
if (0b11011 != dst_w) { printf("*** test_u3r_chop 8.1\n"); }
}
// read 1,8,16 bit bloqs from an indirect atom
{
// build an indirect noun 'src'
c3_c* input_c = "abcdefghij";
u3_noun src = u3i_bytes(10, (c3_y*)input_c);
c3_g bloqsize_g = 0; // 2^0 = 1 bit
// 1 x 1 bit pos=0 (far right)
dst_w = 0;
u3r_chop(bloqsize_g, /// bloq size
0, // start index
1, // count of bloqs
0, // end index
& dst_w, // where bytes go to
src); // where bytes come from
if (0b1 != dst_w) {
printf("*** test_u3r_chop indirect.1\n");
}
// 8 x 1 bit pos=0 (far right)
dst_w = 0;
u3r_chop(bloqsize_g, /// bloq size
0, // start index
8, // count of bloqs
0, // end index
& dst_w, // where bytes go to
src); // where bytes come from
if (0b1100001 != dst_w) {
printf("*** test_u3r_chop indirect.2\n");
}
// 1 x 1 byte = 8 bit, pos=0 (far right)
bloqsize_g = 3; // 2^3 = 1 byte
dst_w = 0;
u3r_chop(bloqsize_g, /// bloq size
0, // start index
1, // count of bloqs
0, // end index
& dst_w, // where bytes go to
src); // where bytes come from
if (0b1100001 != dst_w) {
printf("*** test_u3r_chop indirect.3\n");
}
// 1 x 16 bit bloq, pos = 0
bloqsize_g = 4; // 2^4 = 2 bytes
dst_w = 0;
u3r_chop(bloqsize_g, /// bloq size
0, // start index
1, // count of bloqs
0, // end index
& dst_w, // where bytes go to
src); // where bytes come from
if (0b0110001001100001 != dst_w) {
printf("*** test_u3r_chop indirect.4\n");
}
}
// read lots of bits from a direct noun which holds 64 bits of data
// makes sure that we handle top 32 / bottom 32 correctly
{
// build an indirect noun 'src'
c3_c input_c[8] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 };
u3_noun src = u3i_bytes(8, (c3_y*)input_c);
c3_g bloqsize_g = 0; // 2^0 = 1 bit
c3_w dst_w[2];
memset(dst_w, 0, 2 * sizeof(c3_w));
u3r_chop(bloqsize_g, /// bloq size
0, // start index
63, // count of bloqs
0, // offset on out index
dst_w, // where bytes go to
src); // where bytes come from
}
// as above (read lots of bits from a direct noun which holds 64 bits of data
// makes sure that we handle top 32 / bottom 32 correctly)
// but with a bit more nuance
{
// least significant most
c3_c input_c[8] = { 0x0, 0x0, 0x0, 0xaa, 0xff, 0x0, 0x0, 0x0 };
u3_noun src = u3i_bytes(8, (c3_y*)input_c);
c3_g bloqsize_g = 0; // 2^0 = 1 bit
c3_w dst_w = 0;
u3r_chop(bloqsize_g, /// bloq size
24, // start index
16, // count of bloqs
0, // offset on out index
& dst_w, // where bytes go to
src); // where bytes come from
if (0b1111111110101010 != dst_w) {
printf("*** test_u3r_chop indirect. 6\n");
}
}
}
// XX disabled, static functions
//
#if 0
@ -1652,31 +1734,17 @@ _test_nvm_stack()
#endif
}
/* _test_lily(): test small noun parsing.
*/
static void
_test_lily()
static c3_i
_test_noun(void)
{
c3_l lit_l;
c3_w big_w[] = {0, 0, 1};
u3_noun big = u3i_words(3, big_w);
u3_noun cod = u3dc("scot", c3__uv, big);
c3_i ret_i = 1;
if ( c3y == u3v_lily(c3__uv, cod, &lit_l) ) {
printf("*** fail _test_lily-1\n");
exit(1);
}
cod = u3dc("scot", c3__ud, 0x7fffffff);
if ( (c3n == u3v_lily(c3__ud, cod, &lit_l)) ||
(0x7fffffff != lit_l) ) {
printf("*** fail _test_lily-2a\n");
exit(1);
}
cod = u3dc("scot", c3__ux, u3i_word(0x80000000));
if ( c3y == u3v_lily(c3__ux, cod, &lit_l) ) {
printf("*** fail _test_lily-2b\n");
exit(1);
if ( !_test_chop() ) {
fprintf(stderr, "test noun: chop failed\r\n");
ret_i = 0;
}
return ret_i;
}
/* main(): run all test cases.
@ -1686,9 +1754,20 @@ main(int argc, char* argv[])
{
_setup();
if ( !_test_noun() ) {
fprintf(stderr, "test noun: failed\r\n");
exit(1);
}
// GC
//
u3m_grab(u3_none);
// XX the following tests leak memory
// fix and move to _test_noun()
//
_test_noun_bits_set();
_test_noun_bits_read();
_test_u3r_chop();
_test_imprison();
_test_imprison_complex();
_test_sing();
@ -1698,7 +1777,6 @@ main(int argc, char* argv[])
_test_cells_complex();
_test_u3r_at();
_test_nvm_stack();
_test_lily();
fprintf(stderr, "test_noun: ok\n");

View File

@ -411,25 +411,21 @@ ur_bsr_bytes_any(ur_bsr_t *bsr, uint64_t len, uint8_t *out)
//
else {
uint8_t rest = 8 - off;
uint8_t mask = (1 << off) - 1;
uint8_t byt, l, m = *b >> off;
uint64_t last = left - 1;
uint64_t max = ur_min(last, len_byt);
uint8_t m, l;
// loop over all the bytes we need (or all that remain)
//
// [l] holds [off] bits
// [m] holds [rest] bits
//
{
uint64_t max = ur_min(last, len_byt);
uint64_t i;
for ( i = 0; i < max; i++ ) {
byt = *++b;
l = byt & mask;
out[i] = m ^ (l << rest);
m = byt >> off;
out[i] = (b[i] >> off) ^ (b[i + 1] << rest);
}
b += max;
m = *b >> off;
}
// we're reading into or beyond the last byte [bsr]
@ -441,13 +437,13 @@ ur_bsr_bytes_any(ur_bsr_t *bsr, uint64_t len, uint8_t *out)
uint8_t bits = len - (last << 3);
if ( bits < rest ) {
out[last] = m & ((1 << bits) - 1);
out[max] = m & ((1 << len_bit) - 1);
bsr->bytes = b;
left = 1;
off += len_bit;
}
else {
out[last] = m;
out[max] = m;
bsr->bytes = 0;
left = 0;
off = 0;
@ -465,11 +461,11 @@ ur_bsr_bytes_any(ur_bsr_t *bsr, uint64_t len, uint8_t *out)
if ( len_bit ) {
if ( len_bit <= rest ) {
out[len_byt] = m & ((1 << len_bit) - 1);
out[max] = m & ((1 << len_bit) - 1);
}
else {
l = *++b & ((1 << off) - 1);
out[len_byt] = m ^ (l << rest);
out[max] = (m ^ (l << rest)) & ((1 << len_bit) - 1);
}
}
}
@ -1035,67 +1031,60 @@ ur_bsw64(ur_bsw_t *bsw, uint8_t len, uint64_t val)
}
static inline void
_bsw_bytes_unsafe(ur_bsw_t *bsw, uint64_t len, uint8_t *byt)
_bsw_bytes_unsafe(ur_bsw_t *bsw, const uint64_t len, const uint8_t* src)
{
uint64_t len_byt = len >> 3;
uint8_t len_bit = ur_mask_3(len);
uint64_t fill = bsw->fill;
uint8_t off = bsw->off;
uint8_t *dst = bsw->bytes + fill;
if ( !off ) {
memcpy(bsw->bytes + fill, byt, len_byt);
fill += len_byt;
off = len_bit;
const uint64_t len_byt = len >> 3;
const uint8_t len_bit = ur_mask_3(len);
if ( off ) {
bsw->bytes[fill] = byt[len_byt] & ((1 << off) - 1);
memcpy(dst, src, len_byt);
bsw->fill = fill + len_byt;
if ( len_bit ) {
dst[len_byt] = src[len_byt] & ((1 << len_bit) - 1);
bsw->off = len_bit;
}
}
// the least-significant bits of the input become the
// most-significant bits of a byte in the output stream, and vice-versa
//
else {
uint8_t rest = 8 - off;
uint8_t mask = (1 << rest) - 1;
uint8_t l, m = bsw->bytes[fill];
uint64_t i;
const uint8_t rest = 8 - off;
for ( i = 0; i < len_byt; i++ ) {
l = byt[i] & mask;
bsw->bytes[fill++] = m ^ (l << off);
m = byt[i] >> rest;
if ( rest >= len ) {
uint16_t ful = off + len;
*dst ^= (*src & ((1 << len) - 1)) << off;
if ( ful >> 3 ) {
bsw->fill = fill + 1;
}
// no trailing bits; we need only write the rest of the last byte.
//
// NB: while semantically equivalent to the subsequent block,
// this case must be separate to avoid reading off the end of [byt]
//
if ( !len_bit ) {
bsw->bytes[fill] = m;
bsw->off = ur_mask_3(ful);
}
// trailing bits fit into the current output byte.
//
else if ( len_bit < rest ) {
l = byt[len_byt] & ((1 << len_bit) - 1);
bsw->bytes[fill] = m ^ (l << off);
off += len_bit;
}
// trailing bits extend into the next output byte.
//
else {
l = byt[len_byt] & mask;
bsw->bytes[fill++] = m ^ (l << off);
const uint64_t nel = len - rest;
const uint64_t len_byt = nel >> 3;
const uint8_t len_bit = ur_mask_3(nel);
m = byt[len_byt] >> rest;
*dst++ ^= *src << off;
off = len_bit - rest;
bsw->bytes[fill] = m & ((1 << off) - 1);
for ( uint64_t i = 0; i < len_byt; i++ ) {
dst[i] = (src[i] >> rest) ^ (src[i + 1] << off);
}
{
uint8_t tal = (src[len_byt] >> rest)
^ (( off > len_bit ) ? 0 : (src[len_byt + 1] << off));
dst[len_byt] = tal & ((1 << len_bit) - 1);
}
bsw->fill = fill + len_byt + 1;
bsw->off = len_bit;
}
}
bsw->off = off;
bsw->fill = fill;
bsw->bits += len;
}