From 2811a7f70acd99e0f76f8133665069837bbe219f Mon Sep 17 00:00:00 2001 From: benjamin-tlon <42358674+benjamin-tlon@users.noreply.github.com> Date: Mon, 25 Feb 2019 14:17:26 -0800 Subject: [PATCH] ripn jet (#1210) --- include/jets/w.h | 1 + jets/c/rip.c | 154 +++++++++++++++++++++++------------------------ jets/c/ripn.c | 98 ++++++++++++++++++++++++++++++ jets/tree.c | 21 ++++++- meson.build | 1 + 5 files changed, 194 insertions(+), 81 deletions(-) create mode 100644 jets/c/ripn.c diff --git a/include/jets/w.h b/include/jets/w.h index 2ecb90c533..5ff3ab2cf9 100644 --- a/include/jets/w.h +++ b/include/jets/w.h @@ -66,6 +66,7 @@ u3_noun u3wc_rep(u3_noun); u3_noun u3wc_rev(u3_noun); u3_noun u3wc_rip(u3_noun); + u3_noun u3wc_ripn(u3_noun); u3_noun u3wc_rsh(u3_noun); u3_noun u3wc_swp(u3_noun); u3_noun u3wc_sqt(u3_noun); diff --git a/jets/c/rip.c b/jets/c/rip.c index 30cee3dd6a..3f05c01eb0 100644 --- a/jets/c/rip.c +++ b/jets/c/rip.c @@ -1,92 +1,86 @@ -/* j/3/rip.c -** -*/ #include "all.h" +u3_noun u3qc_rip(u3_atom bloq, u3_atom b) { + if ( !_(u3a_is_cat(bloq)) || (bloq >= 32) ) { + return u3m_bail(c3__fail); + } -/* functions -*/ - u3_noun - u3qc_rip(u3_atom a, - u3_atom b) - { - if ( !_(u3a_is_cat(a)) || (a >= 32) ) { + c3_g bloq_g = bloq; + + /* + This is a fast-path for the case where all the resulting blocks will + fit in 31-bit direct atoms. + */ + if ( bloq_g < 5 ) { // produce direct atoms + u3_noun acc = u3_nul; + + c3_w met_w = u3r_met(bloq_g, b); // num blocks in atom + c3_w nbits_w = 1 << bloq_g; // block size in bits + c3_w bmask_w = (1 << nbits_w) - 1; // result mask + + for ( c3_w i_w = 0; i_w < met_w; i_w++ ) { // `i_w` is block index + c3_w nex_w = i_w + 1; // next block + c3_w pat_w = met_w - nex_w; // blks left after this + c3_w bit_w = pat_w << bloq_g; // bits left after this + c3_w wor_w = bit_w >> 5; // wrds left after this + c3_w sif_w = bit_w & 31; // bits left in word + c3_w src_w = u3r_word(wor_w, b); // find word by index + c3_w rip_w = (src_w >> sif_w) & bmask_w; // get item from word + + acc = u3nc(rip_w, acc); + } + + return acc; + } + + u3_noun acc = u3_nul; + c3_w met_w = u3r_met(bloq_g, b); + c3_w len_w = u3r_met(5, b); + c3_g san_g = (bloq_g - 5); + c3_w san_w = 1 << san_g; + c3_w dif_w = (met_w << san_g) - len_w; + c3_w tub_w = ((dif_w == 0) ? san_w : (san_w - dif_w)); + + for ( c3_w i_w = 0; i_w < met_w; i_w++ ) { + c3_w pat_w = (met_w - (i_w + 1)); + c3_w wut_w = (pat_w << san_g); + c3_w sap_w = ((0 == i_w) ? tub_w : san_w); + c3_w* sal_w = u3a_slab(sap_w); + + if ( 0 == sal_w ) { return u3m_bail(c3__fail); } - else { - u3_noun pir = u3_nul; - c3_g a_g = a; - c3_w i_w; - if ( a_g < 5 ) { - c3_w met_w = u3r_met(a_g, b); - c3_w mek_w = ((1 << (1 << a_g)) - 1); + c3_w j_w; + u3_atom rip; - for ( i_w = 0; i_w < met_w; i_w++ ) { - c3_w pat_w = (met_w - (i_w + 1)); - c3_w bit_w = (pat_w << a_g); - c3_w wor_w = (bit_w >> 5); - c3_w sif_w = (bit_w & 31); - c3_w src_w = u3r_word(wor_w, b); - c3_w rip_w = ((src_w >> sif_w) & mek_w); - - pir = u3nc(rip_w, pir); - } - return pir; - } - else { - c3_w met_w = u3r_met(a_g, b); - c3_w len_w = u3r_met(5, b); - c3_g san_g = (a_g - 5); - c3_w san_w = 1 << san_g; - c3_w dif_w = (met_w << san_g) - len_w; - c3_w tub_w = ((dif_w == 0) ? san_w : (san_w - dif_w)); - - for ( i_w = 0; i_w < met_w; i_w++ ) { - c3_w pat_w = (met_w - (i_w + 1)); - c3_w wut_w = (pat_w << san_g); - c3_w sap_w = ((0 == i_w) ? tub_w : san_w); - c3_w* sal_w = u3a_slab(sap_w); - - if ( 0 == sal_w ) { - return u3m_bail(c3__fail); - } else { - c3_w j_w; - u3_atom rip; - - for ( j_w = 0; j_w < sap_w; j_w++ ) { - sal_w[j_w] = u3r_word(wut_w + j_w, b); - } - - rip = u3a_malt(sal_w); - pir = u3nc(rip, pir); - } - len_w -= san_w; - } - } - return pir; + for ( j_w = 0; j_w < sap_w; j_w++ ) { + sal_w[j_w] = u3r_word(wut_w + j_w, b); } - } - u3_noun - u3wc_rip(u3_noun cor) - { - u3_noun a, b; - if ( (c3n == u3r_mean(cor, u3x_sam_2, &a, u3x_sam_3, &b, 0)) || - (c3n == u3ud(a)) || - (c3n == u3ud(b)) ) - { - return u3m_bail(c3__exit); - } else { - return u3qc_rip(a, b); - } + rip = u3a_malt(sal_w); + acc = u3nc(rip, acc); + len_w -= san_w; } - u3_noun - u3kc_rip(u3_atom a, - u3_atom b) - { - u3_noun res = u3qc_rip(a, b); - u3z(a); u3z(b); - return res; + return acc; +} + +u3_noun u3wc_rip(u3_noun cor) { + u3_noun a, b; + + if ( (c3n == u3r_mean(cor, u3x_sam_2, &a, u3x_sam_3, &b, 0)) || + (c3n == u3ud(a)) || + (c3n == u3ud(b)) + ) { + return u3m_bail(c3__exit); } + + return u3qc_rip(a, b); +} + +u3_noun u3kc_rip(u3_atom a, u3_atom b) { + u3_noun res = u3qc_rip(a, b); + u3z(a); u3z(b); + return res; +} diff --git a/jets/c/ripn.c b/jets/c/ripn.c new file mode 100644 index 0000000000..eea18e9a83 --- /dev/null +++ b/jets/c/ripn.c @@ -0,0 +1,98 @@ +#include "all.h" + +/* + Get the lowest `n` bits of a word `w` using a bitmask. +*/ +#define TAKEBITS(n,w) \ + ((n)==32) ? (w) : \ + ((n)==0) ? 0 : \ + ((w) & ((1 << (n)) - 1)) + +/* + Divide, rounding up. +*/ +#define DIVCEIL(x,y) 1 + ((x - 1) / y); + +/* + `ripn` breaks `atom` into a list of blocks, of bit-width `bits`. The + resulting list will be least-significant block first. + + XX TODO This only handles cases where the bit-width is <= 32. + + For each block we produce, we need to grab the relevant words inside + `atom`, so we first compute their indicies. + + `ins_idx` is the word-index of the least-significant word we + care about, and `sig_idx` is the word after that. + + Next we grab those words (`ins_word` and `sig_word`) from the atom + using `u3r_word`. Note that `sig_idx` might be out-of-bounds for the + underlying array of `atom`, but `u3r_word` returns 0 in that case, + which is exatly what we want. + + Now, we need to grab the relevant bits out of both words, and combine + them. `bits_rem_in_ins_word` is the number of remaining (insignificant) + bits in `ins_word`, `nbits_ins` is the number of bits we want from the + less-significant word, and `nbits_sig` from the more-significant one. + + Take the least significant `nbits_sig` bits from `sig_word`, and take + the slice we care about from `ins_word`. In order to take that slice, + we drop `bits_rem_in_ins_word` insignificant bits, and then take the + `nbits_sig` most-significant bits. + + Last, we slice out those bits from the two words, combine them into + one word, and cons them onto the front of the result. +*/ +u3_noun u3qc_ripn(u3_atom bits, u3_atom atom) { + if ( !_(u3a_is_cat(bits) || bits==0 || bits>31) ) { + return u3m_bail(c3__fail); + } + + c3_w bit_width = u3r_met(0, atom); + c3_w num_blocks = DIVCEIL(bit_width, bits); + + u3_noun res = u3_nul; + + for ( c3_w blk = 0; blk < num_blocks; blk++ ) { + c3_w next_blk = blk + 1; + c3_w blks_rem = num_blocks - next_blk; + c3_w bits_rem = blks_rem * bits; + c3_w ins_idx = bits_rem / 32; + c3_w sig_idx = ins_idx + 1; + + c3_w bits_rem_in_ins_word = bits_rem % 32; + + c3_w ins_word = u3r_word(ins_idx, atom); + c3_w sig_word = u3r_word(sig_idx, atom); + c3_w nbits_ins = c3_min(bits, 32 - bits_rem_in_ins_word); + c3_w nbits_sig = bits - nbits_ins; + + c3_w ins_word_bits = TAKEBITS(nbits_ins, ins_word >> bits_rem_in_ins_word); + c3_w sig_word_bits = TAKEBITS(nbits_sig, sig_word); + + c3_w item = ins_word_bits | (sig_word_bits << nbits_ins); + + res = u3nc(item, res); + } + + return res; +} + +u3_noun u3wc_ripn(u3_noun cor) { + u3_noun bits, atom; + + if ( (c3n == u3r_mean(cor, u3x_sam_2, &bits, u3x_sam_3, &atom, 0)) || + (c3n == u3ud(bits)) || + (c3n == u3ud(atom)) ) + { + return u3m_bail(c3__exit); + } + + return u3qc_ripn(bits, atom); +} + +u3_noun u3kc_ripn(u3_atom bits, u3_atom atom) { + u3_noun res = u3qc_ripn(bits, atom); + u3z(bits), u3z(atom); + return res; +} diff --git a/jets/tree.c b/jets/tree.c index b09505e8da..64f2d41986 100644 --- a/jets/tree.c +++ b/jets/tree.c @@ -1,5 +1,18 @@ -/* j/tree.c +/* + To generate the hashes, take the sha256 of the jammed battery. For example: + + ``` + > `@ux`(shax (jam -:ripn)) + 0x2759.a693.1e9e.f9a5.2c8e.ee43.1088.43d9.4d39.32a6.b04f.86cb.6ba1.5553.4329.3a28 + ``` + + Becomes: + + ``` + 2759a6931e9ef9a52c8eee43108843d94d3932a6b04f86cb6ba1555343293a28 + ``` */ + #include "all.h" static u3j_harm _141_hex_aes_ecba_en_a[] = {{".2", u3wea_ecba_en}, {}}; @@ -1473,6 +1486,11 @@ static c3_c* _141_two_rip_ha[] = { "e8e0b834aded0d2738bcf38a93bf373d412a51e0cee7f274277a6393e634a65e", 0 }; +static u3j_harm _141_two_ripn_a[] = {{".2", u3wc_ripn, c3y}, {}}; +static c3_c* _141_two_ripn_ha[] = { + "2759a6931e9ef9a52c8eee43108843d94d3932a6b04f86cb6ba1555343293a28", + 0 +}; static u3j_harm _141_two_rsh_a[] = {{".2", u3wc_rsh, c3y}, {}}; static c3_c* _141_two_rsh_ha[] = { "a401145b4c11ec8d17a729fe30f06c295865ffed1b970b0a788f0fec1ed0a703", @@ -1710,6 +1728,7 @@ static u3j_core _141_two_d[] = { "rep", 7, _141_two_rep_a, 0, _141_two_rep_ha }, { "rev", 7, _141_two_rev_a, 0, _141_two_rev_ha }, { "rip", 7, _141_two_rip_a, 0, _141_two_rip_ha }, + { "ripn", 7, _141_two_ripn_a, 0, _141_two_ripn_ha }, { "rsh", 7, _141_two_rsh_a, 0, _141_two_rsh_ha }, { "swp", 7, _141_two_swp_a, 0, _141_two_swp_ha }, { "rub", 7, _141_two_rub_a, 0, _141_two_rub_ha }, diff --git a/meson.build b/meson.build index cdf12cd7b6..5cec95b129 100644 --- a/meson.build +++ b/meson.build @@ -73,6 +73,7 @@ jets_c_src = [ 'jets/c/rep.c', 'jets/c/rev.c', 'jets/c/rip.c', +'jets/c/ripn.c', 'jets/c/rsh.c', 'jets/c/swp.c', 'jets/c/sqt.c'