Optimize: u3a_malt takes care of trailing zeros.
(x==0) ? 0 : \
1 + ((x - 1) / y);
-/*
- TODO Don't do the double flop.
-*/
u3_noun u3qc_repn(u3_atom bits, u3_noun blox) {
if ( !_(u3a_is_cat(bits) || bits==0 || bits>31) ) {
return u3m_bail(c3__fail);
}
- blox = u3kb_flop(blox);
-
- //
- // We need to enforce the invariant that the result does not contain
- // leading (? TODO). Since each input block must be smaller than
- // a word, simply stripping off leading zero blocks is enough to
- // ensure this.
- //
- // We also verify that each input block is a direct atom.
- //
- while (1) {
- if (blox == 0) {
- return 0;
- }
-
- u3_noun blok_n = u3h(blox);
-
- if (!_(u3a_is_cat(blok_n)))
- return u3m_bail(c3__fail);
-
- if (blok_n != 0) break;
-
- blox = u3t(blox);
- }
-
- blox = u3kb_flop(blox);
-
//
// Calculate input and output size.
//
@@ -77,16 +47,15 @@ u3_noun u3qc_repn(u3_atom bits, u3_noun blox) {
// once full.
//
// acc register
- // idx where the register will be flushed to
// use number of register bits filled (used)
+ // cur next buffer word to flush into.
//
- c3_w acc=0, idx=0, use=0;
+ c3_w acc=0, use=0, *cur=buf;
void flush() {
- buf[idx++] = acc;
- acc = 0;
- use = 0;
+ *cur++ = acc;
+ acc = use = 0;
}
c3_w slice(c3_w sz, c3_w off, c3_w val) {
@@ -94,9 +63,14 @@ u3_noun u3qc_repn(u3_atom bits, u3_noun blox) {
}
for (c3_w i=0; i<num_blox; i++) {
- c3_w blok = u3a_h(blox);
+ u3_noun blok_n = u3h(blox);
blox = u3t(blox);
+ if (!_(u3a_is_cat(blok_n)))
+ return u3m_bail(c3__fail);
+
+ c3_w blok = blok_n;
+
for (c3_w rem_in_blok=bits; rem_in_blok;) {
c3_w rem_in_acc = 32 - use;
if (rem_in_blok == rem_in_acc) { // EQ
@@ -114,7 +88,6 @@ u3_noun u3qc_repn(u3_atom bits, u3_noun blox) {
flush();
}
}
-
}
//
