urbit/noun/retrieve.c

1796 lines
33 KiB
C
Raw Normal View History

2014-09-11 04:01:32 +04:00
/* g/r.c
2014-09-05 23:55:16 +04:00
**
*/
#include "all.h"
/* _frag_word(): fast fragment/branch prediction for top word.
*/
2014-09-06 00:13:24 +04:00
static u3_weak
_frag_word(c3_w a_w, u3_noun b)
2014-09-05 23:55:16 +04:00
{
c3_assert(0 != a_w);
{
2014-11-18 00:56:51 +03:00
c3_w dep_w = u3x_dep(a_w);
2014-09-05 23:55:16 +04:00
while ( dep_w ) {
2014-11-06 03:20:01 +03:00
if ( c3n == u3a_is_cell(b) ) {
2014-11-06 02:36:30 +03:00
return u3_none;
2014-09-05 23:55:16 +04:00
}
else {
2014-11-06 03:20:01 +03:00
u3a_cell* b_u = u3a_to_ptr(b);
2014-09-05 23:55:16 +04:00
2014-09-06 00:13:24 +04:00
b = *(((u3_noun*)&(b_u->hed)) + (1 & (a_w >> (dep_w - 1))));
2014-09-05 23:55:16 +04:00
dep_w--;
}
}
return b;
}
}
/* _frag_deep(): fast fragment/branch for deep words.
*/
2014-09-06 00:13:24 +04:00
static u3_weak
_frag_deep(c3_w a_w, u3_noun b)
2014-09-05 23:55:16 +04:00
{
c3_w dep_w = 32;
while ( dep_w ) {
2014-11-06 03:20:01 +03:00
if ( c3n == u3a_is_cell(b) ) {
2014-11-06 02:36:30 +03:00
return u3_none;
2014-09-05 23:55:16 +04:00
}
else {
2014-11-06 03:20:01 +03:00
u3a_cell* b_u = u3a_to_ptr(b);
2014-09-05 23:55:16 +04:00
2014-09-06 00:13:24 +04:00
b = *(((u3_noun*)&(b_u->hed)) + (1 & (a_w >> (dep_w - 1))));
2014-09-05 23:55:16 +04:00
dep_w--;
}
}
return b;
}
2014-11-06 03:20:01 +03:00
/* u3r_at():
2014-09-05 23:55:16 +04:00
**
2014-11-06 02:36:30 +03:00
** Return fragment (a) of (b), or u3_none if not applicable.
2014-09-05 23:55:16 +04:00
*/
2014-09-06 00:13:24 +04:00
u3_weak
2014-12-03 00:53:35 +03:00
u3r_at(u3_atom a, u3_noun b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 02:36:30 +03:00
c3_assert(u3_none != a);
c3_assert(u3_none != b);
2014-09-05 23:55:16 +04:00
2014-12-03 00:53:35 +03:00
u3t_on(far_o);
2014-09-05 23:55:16 +04:00
if ( 0 == a ) {
2014-12-03 00:53:35 +03:00
u3t_off(far_o);
2014-11-06 02:36:30 +03:00
return u3_none;
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
if ( _(u3a_is_cat(a)) ) {
2014-12-03 00:53:35 +03:00
u3t_off(far_o);
2014-09-05 23:55:16 +04:00
return _frag_word(a, b);
}
else {
2014-11-06 03:20:01 +03:00
if ( !_(u3a_is_pug(a)) ) {
2014-12-03 00:53:35 +03:00
u3t_off(far_o);
2014-11-06 02:36:30 +03:00
return u3_none;
2014-09-05 23:55:16 +04:00
}
else {
2014-11-06 03:20:01 +03:00
u3a_atom* a_u = u3a_to_ptr(a);
2014-09-05 23:55:16 +04:00
c3_w len_w = a_u->len_w;
b = _frag_word(a_u->buf_w[len_w - 1], b);
len_w -= 1;
while ( len_w ) {
2014-09-15 07:27:48 +04:00
b = _frag_deep(a_u->buf_w[len_w - 1], b);
2014-09-05 23:55:16 +04:00
2014-11-06 02:36:30 +03:00
if ( u3_none == b ) {
2014-12-03 00:53:35 +03:00
u3t_off(far_o);
2014-09-05 23:55:16 +04:00
return b;
} else {
len_w--;
}
}
2014-12-03 00:53:35 +03:00
u3t_off(far_o);
2014-09-05 23:55:16 +04:00
return b;
}
}
}
2014-11-06 03:20:01 +03:00
/* u3r_mean():
2014-09-05 23:55:16 +04:00
**
** Attempt to deconstruct `a` by axis, noun pairs; 0 terminates.
** Axes must be sorted in tree order.
*/
struct _mean_pair {
c3_w axe_w;
2014-09-06 00:13:24 +04:00
u3_noun* som;
2014-09-05 23:55:16 +04:00
};
static c3_w
_mean_cut(c3_w len_w,
struct _mean_pair* prs_m)
{
c3_w i_w, cut_t, cut_w;
2014-11-05 04:09:17 +03:00
cut_t = 0;
2014-09-05 23:55:16 +04:00
cut_w = 0;
for ( i_w = 0; i_w < len_w; i_w++ ) {
c3_w axe_w = prs_m[i_w].axe_w;
2014-11-18 00:56:51 +03:00
if ( (cut_t == 0) && (3 == u3x_cap(axe_w)) ) {
2014-11-05 04:09:17 +03:00
cut_t = 1;
2014-09-05 23:55:16 +04:00
cut_w = i_w;
}
2014-11-18 00:56:51 +03:00
prs_m[i_w].axe_w = u3x_mas(axe_w);
2014-09-05 23:55:16 +04:00
}
return cut_t ? cut_w : i_w;
}
2014-11-06 06:10:22 +03:00
static c3_o
2014-09-06 00:13:24 +04:00
_mean_extract(u3_noun som,
2014-09-05 23:55:16 +04:00
c3_w len_w,
struct _mean_pair* prs_m)
{
if ( len_w == 0 ) {
2014-11-05 04:18:47 +03:00
return c3y;
2014-09-05 23:55:16 +04:00
}
else if ( (len_w == 1) && (1 == prs_m[0].axe_w) ) {
*prs_m->som = som;
2014-11-05 04:18:47 +03:00
return c3y;
2014-09-05 23:55:16 +04:00
}
else {
2014-11-06 03:20:01 +03:00
if ( c3n == u3a_is_cell(som) ) {
2014-11-05 04:18:47 +03:00
return c3n;
2014-09-05 23:55:16 +04:00
} else {
c3_w cut_w = _mean_cut(len_w, prs_m);
2014-11-05 04:18:47 +03:00
return c3a
2014-11-06 03:20:01 +03:00
(_mean_extract(u3a_h(som), cut_w, prs_m),
_mean_extract(u3a_t(som), (len_w - cut_w), (prs_m + cut_w)));
2014-09-05 23:55:16 +04:00
}
}
}
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_mean(u3_noun som,
2014-09-05 23:55:16 +04:00
...)
{
va_list ap;
c3_w len_w;
struct _mean_pair* prs_m;
2014-11-06 02:36:30 +03:00
c3_assert(u3_none != som);
2014-09-05 23:55:16 +04:00
/* Count.
*/
len_w = 0;
{
va_start(ap, som);
while ( 1 ) {
if ( 0 == va_arg(ap, c3_w) ) {
break;
}
2014-09-06 00:13:24 +04:00
va_arg(ap, u3_noun*);
2014-09-05 23:55:16 +04:00
len_w++;
}
va_end(ap);
}
prs_m = alloca(len_w * sizeof(struct _mean_pair));
/* Install.
*/
{
c3_w i_w;
va_start(ap, som);
for ( i_w = 0; i_w < len_w; i_w++ ) {
prs_m[i_w].axe_w = va_arg(ap, c3_w);
2014-09-06 00:13:24 +04:00
prs_m[i_w].som = va_arg(ap, u3_noun*);
2014-09-05 23:55:16 +04:00
}
va_end(ap);
}
/* Extract.
*/
return _mean_extract(som, len_w, prs_m);
}
static __inline__ c3_w
_mug_fnv(c3_w has_w)
{
return (has_w * ((c3_w)16777619));
}
static __inline__ c3_w
_mug_out(c3_w has_w)
{
return (has_w >> 31) ^ (has_w & 0x7fffffff);
}
static __inline__ c3_w
_mug_both(c3_w lef_w, c3_w rit_w)
{
c3_w bot_w = _mug_fnv(lef_w ^ _mug_fnv(rit_w));
c3_w out_w = _mug_out(bot_w);
if ( 0 != out_w ) {
return out_w;
}
else {
return _mug_both(lef_w, ++rit_w);
}
}
2014-11-06 03:20:01 +03:00
/* u3r_mug_both():
2014-09-05 23:55:16 +04:00
**
** Join two mugs.
*/
c3_w
2014-11-06 03:20:01 +03:00
u3r_mug_both(c3_w lef_w, c3_w rit_w)
2014-09-05 23:55:16 +04:00
{
return _mug_both(lef_w, rit_w);
}
static __inline__ c3_w
2015-06-09 01:51:11 +03:00
_mug_bytes_in(c3_w off_w, c3_w nby_w, const c3_y* byt_y)
2014-09-05 23:55:16 +04:00
{
c3_w i_w;
for ( i_w = 0; i_w < nby_w; i_w++ ) {
off_w = _mug_fnv(off_w ^ byt_y[i_w]);
}
return off_w;
}
static c3_w
2015-06-09 01:51:11 +03:00
_mug_bytes(c3_w off_w, c3_w nby_w, const c3_y* byt_y)
2014-09-05 23:55:16 +04:00
{
c3_w has_w = _mug_bytes_in(off_w, nby_w, byt_y);
c3_w out_w = _mug_out(has_w);
if ( 0 != out_w ) {
return out_w;
}
else {
return _mug_bytes(++off_w, nby_w, byt_y);
}
}
static __inline__ c3_w
_mug_words_in(c3_w off_w, c3_w nwd_w, const c3_w* wod_w)
{
if ( 0 == nwd_w ) {
return off_w;
} else {
c3_w i_w, x_w;
for ( i_w = 0; i_w < (nwd_w - 1); i_w++ ) {
x_w = wod_w[i_w];
{
c3_y a_y = (x_w & 0xff);
c3_y b_y = ((x_w >> 8) & 0xff);
c3_y c_y = ((x_w >> 16) & 0xff);
c3_y d_y = ((x_w >> 24) & 0xff);
off_w = _mug_fnv(off_w ^ a_y);
off_w = _mug_fnv(off_w ^ b_y);
off_w = _mug_fnv(off_w ^ c_y);
off_w = _mug_fnv(off_w ^ d_y);
}
}
x_w = wod_w[nwd_w - 1];
if ( x_w ) {
off_w = _mug_fnv(off_w ^ (x_w & 0xff));
x_w >>= 8;
if ( x_w ) {
off_w = _mug_fnv(off_w ^ (x_w & 0xff));
x_w >>= 8;
if ( x_w ) {
off_w = _mug_fnv(off_w ^ (x_w & 0xff));
x_w >>= 8;
if ( x_w ) {
off_w = _mug_fnv(off_w ^ (x_w & 0xff));
}
}
}
}
}
return off_w;
}
static c3_w
_mug_words(c3_w off_w, c3_w nwd_w, const c3_w* wod_w)
{
c3_w has_w = _mug_words_in(off_w, nwd_w, wod_w);
c3_w out_w = _mug_out(has_w);
if ( 0 != out_w ) {
return out_w;
}
else {
return _mug_words(++off_w, nwd_w, wod_w);
}
}
2014-11-06 03:20:01 +03:00
/* u3r_mug():
2014-09-05 23:55:16 +04:00
**
** Compute and/or recall the mug (31-bit FNV1a hash) of (a).
*/
c3_w
2014-11-06 03:20:01 +03:00
u3r_mug(u3_noun veb)
2014-09-05 23:55:16 +04:00
{
2014-11-06 02:36:30 +03:00
c3_assert(u3_none != veb);
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( _(u3a_is_cat(veb)) ) {
2014-09-05 23:55:16 +04:00
c3_w x_w = veb;
2014-12-15 17:30:28 +03:00
return _mug_words(2166136261U, (veb ? 1 : 0), &x_w);
2014-09-05 23:55:16 +04:00
} else {
2014-11-06 03:20:01 +03:00
u3a_noun* veb_u = u3a_to_ptr(veb);
2014-09-05 23:55:16 +04:00
if ( veb_u->mug_w ) {
return veb_u->mug_w;
}
else {
2014-11-06 03:20:01 +03:00
if ( _(u3a_is_cell(veb)) ) {
u3a_cell* veb_u = u3a_to_ptr(veb);
2014-09-06 00:13:24 +04:00
u3_noun hed = veb_u->hed;
u3_noun tel = veb_u->tel;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
veb_u->mug_w = u3r_mug_cell(hed, tel);
2014-09-05 23:55:16 +04:00
return veb_u->mug_w;
}
else {
2014-11-06 03:20:01 +03:00
u3a_atom* veb_u = u3a_to_ptr(veb);
2014-09-05 23:55:16 +04:00
c3_w len_w = veb_u->len_w;
veb_u->mug_w = _mug_words(2166136261U, len_w, veb_u->buf_w);
2014-09-05 23:55:16 +04:00
return veb_u->mug_w;
}
}
}
}
2014-11-06 03:20:01 +03:00
/* u3r_mug_words():
2014-09-05 23:55:16 +04:00
**
** Compute the mug of `buf`, `len`, LSW first.
*/
c3_w
2014-11-06 03:20:01 +03:00
u3r_mug_words(const c3_w *buf_w,
2014-09-05 23:55:16 +04:00
c3_w len_w)
{
2014-12-19 22:41:57 +03:00
return _mug_words(2166136261U, len_w, buf_w);
2014-09-05 23:55:16 +04:00
}
2015-11-07 01:08:58 +03:00
/* u3r_mug_d():
**
** Compute the mug of `num`, LSW first.
*/
c3_w
u3r_mug_d(c3_d num_d)
{
c3_w buf_w[2];
buf_w[0] = (c3_w)(num_d & 0xffffffffULL);
buf_w[1] = (c3_w)(num_d >> 32ULL);
return u3r_mug_words(buf_w, 2);
}
2015-06-06 02:35:41 +03:00
/* u3r_mug_bytes():
**
** Compute the mug of `buf`, `len`, LSW first.
*/
c3_w
u3r_mug_bytes(const c3_y *buf_w,
c3_w len_w)
{
return _mug_bytes(2166136261U, len_w, buf_w);
}
2014-11-06 03:20:01 +03:00
/* u3r_mug_string():
2014-09-05 23:55:16 +04:00
**
** Compute the mug of `a`, LSB first.
*/
c3_w
2014-11-06 03:20:01 +03:00
u3r_mug_string(const c3_c *a_c)
2014-09-05 23:55:16 +04:00
{
2014-12-19 22:41:57 +03:00
return _mug_bytes(2166136261U, strlen(a_c), (c3_y *)a_c);
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_mug_cell():
2014-09-05 23:55:16 +04:00
**
** Compute the mug of the cell `[hed tel]`.
*/
c3_w
2014-11-06 03:20:01 +03:00
u3r_mug_cell(u3_noun hed,
2014-09-06 00:13:24 +04:00
u3_noun tel)
2014-09-05 23:55:16 +04:00
{
2014-11-06 03:20:01 +03:00
c3_w lus_w = u3r_mug(hed);
c3_w biq_w = u3r_mug(tel);
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
return u3r_mug_both(lus_w, biq_w);
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_mug_trel():
2014-09-05 23:55:16 +04:00
**
** Compute the mug of `[a b c]`.
*/
c3_w
2014-11-06 03:20:01 +03:00
u3r_mug_trel(u3_noun a,
2014-09-06 00:13:24 +04:00
u3_noun b,
u3_noun c)
2014-09-05 23:55:16 +04:00
{
2014-11-06 03:20:01 +03:00
return u3r_mug_both
(u3r_mug(a), u3r_mug_both(u3r_mug(b), u3r_mug(c)));
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_mug_qual():
2014-09-05 23:55:16 +04:00
**
** Compute the mug of `[a b c d]`.
*/
c3_w
2014-11-06 03:20:01 +03:00
u3r_mug_qual(u3_noun a,
2014-09-06 00:13:24 +04:00
u3_noun b,
u3_noun c,
u3_noun d)
2014-09-05 23:55:16 +04:00
{
2014-11-06 03:20:01 +03:00
return u3r_mug_both
(u3r_mug(a),
u3r_mug_both(u3r_mug(b),
u3r_mug_both(u3r_mug(c), u3r_mug(d))));
2014-09-05 23:55:16 +04:00
}
2015-06-08 22:48:35 +03:00
/* _sang_one(): unify but leak old.
*/
2015-06-08 22:48:35 +03:00
static void
_sang_one(u3_noun* a, u3_noun* b)
{
if ( *a == *b ) {
return;
}
else {
c3_o asr_o = u3a_is_senior(u3R, *a);
c3_o bsr_o = u3a_is_senior(u3R, *b);
if ( _(asr_o) && _(bsr_o) ) {
// You shouldn't have let this happen. We don't want to
// descend down to a lower road and free there, because
// synchronization - though this could be revisited under
// certain circumstances.
//
return;
}
if ( _(asr_o) && !_(bsr_o) ){
// u3z(*b);
*b = *a;
}
if ( _(bsr_o) && !_(asr_o) ) {
// u3z(*a);
*a = *b;
}
if ( u3a_is_north(u3R) ) {
if ( *a <= *b ) {
u3k(*a);
// u3z(*b);
*b = *a;
} else {
u3k(*b);
// u3z(*a);
*a = *b;
}
}
else {
if ( *a >= *b ) {
u3k(*a);
// u3z(*b);
*b = *a;
} else {
u3k(*b);
// u3z(*a);
*a = *b;
}
}
}
}
2018-01-24 04:22:27 +03:00
typedef struct {
u3_noun a;
u3_noun b;
c3_y sat_y;
2018-01-24 04:22:27 +03:00
} eqframe;
static inline eqframe*
_eq_peek()
{
return (eqframe*) u3a_peek(sizeof(eqframe));
}
static inline void
_eq_push(u3_noun a, u3_noun b)
2018-01-24 04:22:27 +03:00
{
eqframe* cur = (eqframe*) u3a_push(sizeof(eqframe));
cur->a = a;
cur->b = b;
cur->sat_y = 0;
2018-01-24 04:22:27 +03:00
}
static inline void
_eq_pop()
{
u3a_pop(sizeof(eqframe));
}
/* _sing_one(): do not pick a unified pointer for identical (a) and (b).
*/
static void
_sing_one(u3_noun* a, u3_noun* b)
{
// this space left intentionally blank
}
2014-10-09 02:16:24 +04:00
/* _sung_one(): pick a unified pointer for identical (a) and (b).
2017-05-11 13:57:18 +03:00
**
** Assumes exclusive access to noun memory.
*/
2014-10-09 02:16:24 +04:00
static void
_sung_one(u3_noun* a, u3_noun* b)
{
2017-05-11 13:57:18 +03:00
2014-10-09 02:16:24 +04:00
if ( *a == *b ) {
return;
2017-05-11 13:57:18 +03:00
} else {
u3_road* rod_u = u3R;
while ( 1 ) {
2014-10-09 02:16:24 +04:00
//
2017-05-11 13:57:18 +03:00
// we can't perform this kind of butchery on the home road,
// where asynchronous things can allocate.
//
if ( u3R == &u3H->rod_u ) {
break;
2014-10-09 02:16:24 +04:00
}
2017-05-11 13:57:18 +03:00
else {
c3_o asr_o = u3a_is_senior(u3R, *a);
c3_o bsr_o = u3a_is_senior(u3R, *b);
if ( _(asr_o) && _(bsr_o) ) {
//
// when unifying on a higher road, we can't free nouns,
// because we can't track junior nouns that point into
// that road.
//
// this is just an implementation issue -- we could set use
// counts to 0 without actually freeing. but the allocator
// would have to be actually designed for this.
//
// not freeing may generate spurious leaks, so we disable
// senior unification when debugging memory. this will
// cause a very slow boot process as the compiler compiles
// itself, constantly running into duplicates.
//
#ifdef U3_MEMORY_DEBUG
return;
#else
u3R = u3to(u3_road, u3R->par_p);
continue;
#endif
}
if ( _(asr_o) && !_(bsr_o) ){
if ( u3R == rod_u ) { u3z(*b); }
*b = *a;
}
if ( _(bsr_o) && !_(asr_o) ) {
if ( u3R == rod_u ) { u3z(*a); }
*a = *b;
}
if ( u3a_is_north(u3R) ) {
if ( *a <= *b ) {
u3k(*a);
if ( u3R == rod_u ) { u3z(*b); }
*b = *a;
} else {
u3k(*b);
if ( u3R == rod_u ) { u3z(*a); }
*a = *b;
}
}
else {
if ( *a >= *b ) {
u3k(*a);
if ( u3R == rod_u ) { u3z(*b); }
*b = *a;
} else {
u3k(*b);
if ( u3R == rod_u ) { u3z(*a); }
*a = *b;
}
}
break;
2014-10-09 02:16:24 +04:00
}
}
2017-05-11 13:57:18 +03:00
u3R = rod_u;
2014-10-09 02:16:24 +04:00
}
}
static inline c3_o
2018-01-29 21:52:47 +03:00
_song_atom(u3_atom a, u3_atom b)
{
u3a_atom* a_u = u3a_to_ptr(a);
if ( !_(u3a_is_atom(b)) ||
_(u3a_is_cat(a)) ||
_(u3a_is_cat(b)) )
{
return c3n;
}
else {
u3a_atom* b_u = u3a_to_ptr(b);
if ( a_u->mug_w &&
b_u->mug_w &&
(a_u->mug_w != b_u->mug_w) )
{
return c3n;
}
else {
c3_w w_rez = a_u->len_w;
c3_w w_mox = b_u->len_w;
if ( w_rez != w_mox ) {
return c3n;
}
else {
c3_w i_w;
for ( i_w = 0; i_w < w_rez; i_w++ ) {
if ( a_u->buf_w[i_w] != b_u->buf_w[i_w] ) {
return c3n;
}
}
}
}
}
return c3y;
}
/* knob: set lower to get more/earlier memoize-by-pointer,
* higher to avoid allocating the u3h as often */
#define EQ_WHISTLE 1024
/* _song_x(): yes if a and b are the same noun, use uni to unify
2014-09-05 23:55:16 +04:00
*/
2014-11-06 06:10:22 +03:00
static c3_o
_song_x(u3_noun a, u3_noun b, void (*uni)(u3_noun*, u3_noun*))
2014-09-05 23:55:16 +04:00
{
eqframe* fam;
u3p(eqframe) empty = u3R->cap_p;
c3_w wis_w = 0;
c3_o r_o = c3n;
u3p(u3h_root) har_p = 0;
_eq_push(a, b);
/* there's a while and a switch here. continues all mean "do the loop again"
** and breaks all mean "fall through this switch case". There are no breaks
** that early terminate the loop.
*/
2018-01-24 04:22:27 +03:00
while ( empty != u3R->cap_p ) {
fam = _eq_peek();
if ( (a = fam->a) == (b = fam->b) ) {
r_o = c3y;
2018-01-24 04:22:27 +03:00
}
else if ( c3y == u3a_is_atom(a) ) {
r_o = _song_atom(a, b);
2018-01-24 04:22:27 +03:00
}
else if ( c3y == u3a_is_atom(b) ) {
r_o = c3n;
}
else {
u3a_cell* a_u = u3a_to_ptr(a);
u3a_cell* b_u = u3a_to_ptr(b);
2014-09-05 23:55:16 +04:00
switch ( fam->sat_y ) {
case 2:
uni(&(a_u->tel), &(b_u->tel));
r_o = c3y;
break;
2014-09-05 23:55:16 +04:00
case 1:
uni(&(a_u->hed), &(b_u->hed));
_eq_push(a_u->tel, b_u->tel);
fam->sat_y = 2;
continue;
2018-01-24 04:22:27 +03:00
case 0: {
2018-01-24 04:22:27 +03:00
if ( a_u->mug_w &&
b_u->mug_w &&
(a_u->mug_w != b_u->mug_w) ) {
r_o = c3n;
break;
2014-09-05 23:55:16 +04:00
}
2018-01-24 04:22:27 +03:00
else {
if ( har_p != 0 ) {
u3_noun key = u3nc(u3a_to_off(a), u3a_to_off(b));
u3_noun got = u3h_get(har_p, key);
u3z(key);
if ( u3_none != got ) {
_eq_pop();
continue;
}
}
_eq_push(a_u->hed, b_u->hed);
fam->sat_y = 1;
continue;
2014-09-05 23:55:16 +04:00
}
}
default:
c3_assert(0);
2014-09-05 23:55:16 +04:00
}
}
if ( c3n == r_o ) {
if ( 0 != har_p ) {
u3h_free(har_p);
}
u3R->cap_p = empty;
return c3n;
}
else {
if ( 0 == har_p && (wis_w++ > EQ_WHISTLE) ) {
har_p = u3h_new();
}
if ( 0 != har_p ) {
u3_noun key = u3nc(u3a_to_off(a), u3a_to_off(b));
u3h_put(har_p, key, c3y);
u3z(key);
}
_eq_pop();
}
}
if ( 0 != har_p ) {
u3h_free(har_p);
2014-09-05 23:55:16 +04:00
}
return c3y;
2014-09-05 23:55:16 +04:00
}
2015-06-08 22:48:35 +03:00
/* u3r_sang(): yes iff (a) and (b) are the same noun, unifying equals.
*/
c3_o
u3r_sang(u3_noun a, u3_noun b)
{
return _song_x(a, b, &_sang_one);
2015-06-08 22:48:35 +03:00
}
2014-11-06 03:20:01 +03:00
/* u3r_sing():
2014-09-05 23:55:16 +04:00
**
** Yes iff (a) and (b) are the same noun.
*/
2014-11-06 06:10:22 +03:00
c3_o
2015-06-08 22:48:35 +03:00
u3r_sing(u3_noun a, u3_noun b)
2014-09-05 23:55:16 +04:00
{
2015-06-08 22:48:35 +03:00
#ifndef U3_MEMORY_DEBUG
if ( u3R->par_p ) {
c3_o ret_o;
u3t_on(euq_o);
ret_o = u3r_sang(a, b);
u3t_off(euq_o);
return ret_o;
2015-06-08 22:48:35 +03:00
}
#endif
{
c3_o ret_o;
2015-01-15 22:10:29 +03:00
2015-06-08 22:48:35 +03:00
u3t_on(euq_o);
ret_o = _song_x(a, b, &_sing_one);
2015-06-08 22:48:35 +03:00
u3t_off(euq_o);
2015-01-15 22:10:29 +03:00
2015-06-08 22:48:35 +03:00
return ret_o;
}
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_sung(): yes iff (a) and (b) are the same noun, unifying equals.
2014-10-09 02:16:24 +04:00
*/
2014-11-06 06:10:22 +03:00
c3_o
2015-06-08 22:48:35 +03:00
u3r_sung(u3_noun a, u3_noun b)
2014-10-09 02:16:24 +04:00
{
return _song_x(a, b, &_sung_one);
2014-10-09 02:16:24 +04:00
}
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_fing(u3_noun a,
2014-09-06 00:13:24 +04:00
u3_noun b)
2014-09-05 23:55:16 +04:00
{
2014-11-05 04:18:47 +03:00
return (a == b) ? c3y : c3n;
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_sing_cell():
2014-09-05 23:55:16 +04:00
**
** Yes iff `[p q]` and `b` are the same noun.
*/
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_sing_cell(u3_noun p,
2014-09-06 00:13:24 +04:00
u3_noun q,
u3_noun b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 03:20:01 +03:00
return c3a(_(u3a_is_cell(b)),
c3a(u3r_sing(p, u3a_h(b)),
u3r_sing(q, u3a_t(b))));
2014-09-05 23:55:16 +04:00
}
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_fing_cell(u3_noun p,
2014-09-06 00:13:24 +04:00
u3_noun q,
u3_noun b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 03:20:01 +03:00
return c3a(_(u3a_is_cell(b)),
c3a(u3r_fing(p, u3a_h(b)),
u3r_fing(q, u3a_t(b))));
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_sing_mixt():
2014-09-05 23:55:16 +04:00
**
** Yes iff `[p q]` and `b` are the same noun.
*/
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_sing_mixt(const c3_c* p_c,
2014-09-06 00:13:24 +04:00
u3_noun q,
u3_noun b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 03:20:01 +03:00
return c3a(_(u3a_is_cell(b)),
c3a(u3r_sing_c(p_c, u3a_h(b)),
u3r_sing(q, u3a_t(b))));
2014-09-05 23:55:16 +04:00
}
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_fing_mixt(const c3_c* p_c,
2014-09-06 00:13:24 +04:00
u3_noun q,
u3_noun b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 03:20:01 +03:00
return c3a(_(u3a_is_cell(b)),
c3a(u3r_sing_c(p_c, u3a_h(b)),
u3r_fing(q, u3a_t(b))));
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_sing_trel():
2014-09-05 23:55:16 +04:00
**
** Yes iff `[p q r]` and `b` are the same noun.
*/
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_sing_trel(u3_noun p,
2014-09-06 00:13:24 +04:00
u3_noun q,
u3_noun r,
u3_noun b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 03:20:01 +03:00
return c3a(_(u3a_is_cell(b)),
c3a(u3r_sing(p, u3a_h(b)),
u3r_sing_cell(q, r, u3a_t(b))));
2014-09-05 23:55:16 +04:00
}
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_fing_trel(u3_noun p,
2014-09-06 00:13:24 +04:00
u3_noun q,
u3_noun r,
u3_noun b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 03:20:01 +03:00
return c3a(_(u3a_is_cell(b)),
c3a(u3r_fing(p, u3a_h(b)),
u3r_fing_cell(q, r, u3a_t(b))));
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_sing_qual():
2014-09-05 23:55:16 +04:00
**
** Yes iff `[p q r]` and `b` are the same noun.
*/
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_sing_qual(u3_noun p,
2014-09-06 00:13:24 +04:00
u3_noun q,
u3_noun r,
u3_noun s,
u3_noun b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 03:20:01 +03:00
return c3a(_(u3a_is_cell(b)),
c3a(u3r_sing(p, u3a_h(b)),
u3r_sing_trel(q, r, s, u3a_t(b))));
2014-09-05 23:55:16 +04:00
}
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_fing_qual(u3_noun p,
2014-09-06 00:13:24 +04:00
u3_noun q,
u3_noun r,
u3_noun s,
u3_noun b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 03:20:01 +03:00
return c3a(_(u3a_is_cell(b)),
c3a(u3r_fing(p, u3a_h(b)),
u3r_fing_trel(q, r, s, u3a_t(b))));
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_nord():
2014-09-05 23:55:16 +04:00
**
** Return 0, 1 or 2 if `a` is below, equal to, or above `b`.
*/
2014-09-06 00:13:24 +04:00
u3_atom
2014-11-06 03:20:01 +03:00
u3r_nord(u3_noun a,
2014-09-06 00:13:24 +04:00
u3_noun b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 02:36:30 +03:00
c3_assert(u3_none != a);
c3_assert(u3_none != b);
2014-09-05 23:55:16 +04:00
if ( a == b ) {
return 1;
}
else {
2014-11-06 03:20:01 +03:00
if ( _(u3a_is_atom(a)) ) {
if ( !_(u3a_is_atom(b)) ) {
2014-09-05 23:55:16 +04:00
return 0;
} else {
2014-11-06 03:20:01 +03:00
if ( _(u3a_is_cat(a)) ) {
if ( _(u3a_is_cat(b)) ) {
2014-09-05 23:55:16 +04:00
return (a < b) ? 0 : 2;
}
else return 0;
}
2014-11-06 03:20:01 +03:00
else if ( _(u3a_is_cat(b)) ) {
2014-09-05 23:55:16 +04:00
return 2;
}
else {
2014-11-06 03:20:01 +03:00
u3a_atom* a_u = u3a_to_ptr(a);
u3a_atom* b_u = u3a_to_ptr(b);
2014-09-05 23:55:16 +04:00
c3_w w_rez = a_u->len_w;
c3_w w_mox = b_u->len_w;
if ( w_rez != w_mox ) {
return (w_rez < w_mox) ? 0 : 2;
}
else {
c3_w i_w;
for ( i_w = 0; i_w < w_rez; i_w++ ) {
c3_w ai_w = a_u->buf_w[i_w];
c3_w bi_w = b_u->buf_w[i_w];
if ( ai_w != bi_w ) {
return (ai_w < bi_w) ? 0 : 2;
}
}
return 1;
}
}
}
} else {
2014-11-06 03:20:01 +03:00
if ( _(u3a_is_atom(b)) ) {
2014-09-05 23:55:16 +04:00
return 2;
} else {
2014-11-06 03:20:01 +03:00
u3_atom c = u3r_nord(u3a_h(a), u3a_h(b));
2014-09-05 23:55:16 +04:00
if ( 1 == c ) {
2014-11-06 03:20:01 +03:00
return u3r_nord(u3a_t(a), u3a_t(b));
2014-09-05 23:55:16 +04:00
} else {
return c;
}
}
}
}
}
2014-11-06 03:20:01 +03:00
/* u3r_sing_c():
2014-09-05 23:55:16 +04:00
**
** Yes iff (b) is the same noun as the C string a_c.
*/
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_sing_c(const c3_c* a_c,
2014-10-24 04:35:26 +04:00
u3_noun b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 02:36:30 +03:00
c3_assert(u3_none != b);
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( !_(u3a_is_atom(b)) ) {
2014-11-05 04:18:47 +03:00
return c3n;
2014-09-05 23:55:16 +04:00
}
else {
c3_w w_sof = strlen(a_c);
c3_w i_w;
2014-11-06 03:20:01 +03:00
if ( w_sof != u3r_met(3, b) ) {
2014-11-05 04:18:47 +03:00
return c3n;
2014-10-24 04:35:26 +04:00
}
2014-09-05 23:55:16 +04:00
for ( i_w = 0; i_w < w_sof; i_w++ ) {
2014-11-06 03:20:01 +03:00
if ( u3r_byte(i_w, b) != a_c[i_w] ) {
2014-11-05 04:18:47 +03:00
return c3n;
2014-09-05 23:55:16 +04:00
}
}
2014-11-05 04:18:47 +03:00
return c3y;
2014-09-05 23:55:16 +04:00
}
}
2014-11-06 03:20:01 +03:00
/* u3r_bush():
2014-09-05 23:55:16 +04:00
**
** Factor [a] as a bush [b.[p q] c].
*/
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_bush(u3_noun a,
2014-09-06 00:13:24 +04:00
u3_noun* b,
u3_noun* c)
2014-09-05 23:55:16 +04:00
{
2014-11-06 02:36:30 +03:00
c3_assert(u3_none != a);
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( _(u3a_is_atom(a)) ) {
2014-11-05 04:18:47 +03:00
return c3n;
2014-09-05 23:55:16 +04:00
}
else {
2014-11-06 03:20:01 +03:00
*b = u3a_h(a);
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( _(u3a_is_atom(*b)) ) {
2014-11-05 04:18:47 +03:00
return c3n;
2014-09-05 23:55:16 +04:00
} else {
2014-11-06 03:20:01 +03:00
*c = u3a_t(a);
2014-11-05 04:18:47 +03:00
return c3y;
2014-09-05 23:55:16 +04:00
}
}
}
2014-11-06 03:20:01 +03:00
/* u3r_cell():
2014-09-05 23:55:16 +04:00
**
** Factor (a) as a cell (b c).
*/
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_cell(u3_noun a,
2014-09-06 00:13:24 +04:00
u3_noun* b,
u3_noun* c)
2014-09-05 23:55:16 +04:00
{
2014-11-06 02:36:30 +03:00
c3_assert(u3_none != a);
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( _(u3a_is_atom(a)) ) {
2014-11-05 04:18:47 +03:00
return c3n;
2014-09-05 23:55:16 +04:00
}
else {
2014-11-06 03:20:01 +03:00
if ( b ) *b = u3a_h(a);
if ( c ) *c = u3a_t(a);
2014-11-05 04:18:47 +03:00
return c3y;
2014-09-05 23:55:16 +04:00
}
}
2014-11-06 03:20:01 +03:00
/* u3r_p():
2014-09-05 23:55:16 +04:00
**
** & [0] if [a] is of the form [b *c].
*/
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_p(u3_noun a,
2014-09-06 00:13:24 +04:00
u3_noun b,
u3_noun* c)
2014-09-05 23:55:16 +04:00
{
2014-09-06 00:13:24 +04:00
u3_noun feg, nux;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( (c3y == u3r_cell(a, &feg, &nux)) &&
(c3y == u3r_sing(feg, b)) )
2014-09-05 23:55:16 +04:00
{
*c = nux;
2014-11-05 04:18:47 +03:00
return c3y;
2014-09-05 23:55:16 +04:00
}
2014-11-05 04:18:47 +03:00
else return c3n;
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_pq():
2014-09-05 23:55:16 +04:00
**
** & [0] if [a] is of the form [b *c d].
*/
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_pq(u3_noun a,
2014-09-06 00:13:24 +04:00
u3_noun b,
u3_noun* c,
u3_noun* d)
2014-09-05 23:55:16 +04:00
{
2014-09-06 00:13:24 +04:00
u3_noun nux;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( (c3y == u3r_p(a, b, &nux)) &&
(c3y == u3r_cell(nux, c, d)) )
2014-09-05 23:55:16 +04:00
{
2014-11-05 04:18:47 +03:00
return c3y;
2014-09-05 23:55:16 +04:00
}
2014-11-05 04:18:47 +03:00
else return c3n;
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_pqr():
2014-09-05 23:55:16 +04:00
**
** & [0] if [a] is of the form [b *c *d *e].
*/
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_pqr(u3_noun a,
2014-09-06 00:13:24 +04:00
u3_noun b,
u3_noun* c,
u3_noun* d,
u3_noun* e)
2014-09-05 23:55:16 +04:00
{
2014-09-06 00:13:24 +04:00
u3_noun nux;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( (c3y == u3r_p(a, b, &nux)) &&
(c3y == u3r_trel(nux, c, d, e)) )
2014-09-05 23:55:16 +04:00
{
2014-11-05 04:18:47 +03:00
return c3y;
2014-09-05 23:55:16 +04:00
}
2014-11-05 04:18:47 +03:00
else return c3n;
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_pqrs():
2014-09-05 23:55:16 +04:00
**
** & [0] if [a] is of the form [b *c *d *e *f].
*/
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_pqrs(u3_noun a,
2014-09-06 00:13:24 +04:00
u3_noun b,
u3_noun* c,
u3_noun* d,
u3_noun* e,
u3_noun* f)
2014-09-05 23:55:16 +04:00
{
2014-09-06 00:13:24 +04:00
u3_noun nux;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( (c3y == u3r_p(a, b, &nux)) &&
(c3y == u3r_qual(nux, c, d, e, f)) )
2014-09-05 23:55:16 +04:00
{
2014-11-05 04:18:47 +03:00
return c3y;
2014-09-05 23:55:16 +04:00
}
2014-11-05 04:18:47 +03:00
else return c3n;
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_trel():
2014-09-05 23:55:16 +04:00
**
** Factor (a) as a trel (b c d).
*/
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_trel(u3_noun a,
2014-09-06 00:13:24 +04:00
u3_noun *b,
u3_noun *c,
u3_noun *d)
2014-09-05 23:55:16 +04:00
{
2014-09-06 00:13:24 +04:00
u3_noun guf;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( (c3y == u3r_cell(a, b, &guf)) &&
(c3y == u3r_cell(guf, c, d)) ) {
2014-11-05 04:18:47 +03:00
return c3y;
2014-09-05 23:55:16 +04:00
}
else {
2014-11-05 04:18:47 +03:00
return c3n;
2014-09-05 23:55:16 +04:00
}
}
2014-11-06 03:20:01 +03:00
/* u3r_qual():
2014-09-05 23:55:16 +04:00
**
** Factor (a) as a qual (b c d e).
*/
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_qual(u3_noun a,
2014-09-06 00:13:24 +04:00
u3_noun* b,
u3_noun* c,
u3_noun* d,
u3_noun* e)
2014-09-05 23:55:16 +04:00
{
2014-09-06 00:13:24 +04:00
u3_noun guf;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( (c3y == u3r_cell(a, b, &guf)) &&
(c3y == u3r_trel(guf, c, d, e)) ) {
2014-11-05 04:18:47 +03:00
return c3y;
2014-09-05 23:55:16 +04:00
}
2014-11-05 04:18:47 +03:00
else return c3n;
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_quil():
2014-09-05 23:55:16 +04:00
**
** Factor (a) as a quil (b c d e f).
*/
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_quil(u3_noun a,
2014-09-06 00:13:24 +04:00
u3_noun* b,
u3_noun* c,
u3_noun* d,
u3_noun* e,
u3_noun* f)
2014-09-05 23:55:16 +04:00
{
2014-09-06 00:13:24 +04:00
u3_noun guf;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( (c3y == u3r_cell(a, b, &guf)) &&
(c3y == u3r_qual(guf, c, d, e, f)) ) {
2014-11-05 04:18:47 +03:00
return c3y;
2014-09-05 23:55:16 +04:00
}
2014-11-05 04:18:47 +03:00
else return c3n;
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_hext():
2014-09-05 23:55:16 +04:00
**
** Factor (a) as a hext (b c d e f g)
*/
2014-11-06 06:10:22 +03:00
c3_o
2014-11-06 03:20:01 +03:00
u3r_hext(u3_noun a,
2014-09-06 00:13:24 +04:00
u3_noun* b,
u3_noun* c,
u3_noun* d,
u3_noun* e,
u3_noun* f,
u3_noun* g)
2014-09-05 23:55:16 +04:00
{
2014-09-06 00:13:24 +04:00
u3_noun guf;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( (c3y == u3r_cell(a, b, &guf)) &&
(c3y == u3r_quil(guf, c, d, e, f, g)) ) {
2014-11-05 04:18:47 +03:00
return c3y;
2014-09-05 23:55:16 +04:00
}
2014-11-05 04:18:47 +03:00
else return c3n;
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3r_met():
2014-09-05 23:55:16 +04:00
**
** Return the size of (b) in bits, rounded up to
** (1 << a_y).
**
** For example, (a_y == 3) returns the size in bytes.
*/
c3_w
2014-11-06 03:20:01 +03:00
u3r_met(c3_y a_y,
2014-09-06 00:13:24 +04:00
u3_atom b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 02:36:30 +03:00
c3_assert(u3_none != b);
2014-11-06 03:20:01 +03:00
c3_assert(_(u3a_is_atom(b)));
2014-09-05 23:55:16 +04:00
if ( b == 0 ) {
return 0;
}
else {
/* gal_w: number of words besides (daz_w) in (b).
** daz_w: top word in (b).
*/
c3_w gal_w;
c3_w daz_w;
2014-11-06 03:20:01 +03:00
if ( _(u3a_is_cat(b)) ) {
2014-09-05 23:55:16 +04:00
gal_w = 0;
daz_w = b;
}
else {
2014-11-06 03:20:01 +03:00
u3a_atom* b_u = u3a_to_ptr(b);
2014-09-05 23:55:16 +04:00
gal_w = (b_u->len_w) - 1;
daz_w = b_u->buf_w[gal_w];
}
switch ( a_y ) {
case 0:
case 1:
case 2: {
/* col_w: number of bits in (daz_w)
** bif_w: number of bits in (b)
*/
c3_w bif_w, col_w;
col_w = c3_bits_word(daz_w);
bif_w = col_w + (gal_w << 5);
return (bif_w + ((1 << a_y) - 1)) >> a_y;
}
case 3: {
return (gal_w << 2)
+ ((daz_w >> 24) ? 4 : (daz_w >> 16) ? 3 : (daz_w >> 8) ? 2 : 1);
}
case 4: {
return (gal_w << 1)
+ ((daz_w >> 16) ? 2 : 1);
}
default: {
c3_y gow_y = (a_y - 5);
return ((gal_w + 1) + ((1 << gow_y) - 1)) >> gow_y;
}
}
}
}
2014-11-06 03:20:01 +03:00
/* u3r_bit():
2014-09-05 23:55:16 +04:00
**
** Return bit (a_w) of (b).
*/
c3_b
2014-11-06 03:20:01 +03:00
u3r_bit(c3_w a_w,
2014-09-06 00:13:24 +04:00
u3_atom b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 02:36:30 +03:00
c3_assert(u3_none != b);
2014-11-06 03:20:01 +03:00
c3_assert(_(u3a_is_atom(b)));
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( _(u3a_is_cat(b)) ) {
2014-09-05 23:55:16 +04:00
if ( a_w >= 31 ) {
return 0;
}
else return (1 & (b >> a_w));
}
else {
2014-11-06 03:20:01 +03:00
u3a_atom* b_u = u3a_to_ptr(b);
2014-09-05 23:55:16 +04:00
c3_y vut_y = (a_w & 31);
c3_w pix_w = (a_w >> 5);
if ( pix_w >= b_u->len_w ) {
return 0;
}
else {
c3_w nys_w = b_u->buf_w[pix_w];
return (1 & (nys_w >> vut_y));
}
}
}
2014-11-06 03:20:01 +03:00
/* u3r_byte():
2014-09-05 23:55:16 +04:00
**
** Return byte (a_w) of (b).
*/
c3_y
2014-11-06 03:20:01 +03:00
u3r_byte(c3_w a_w,
2014-09-06 00:13:24 +04:00
u3_atom b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 02:36:30 +03:00
c3_assert(u3_none != b);
2014-11-06 03:20:01 +03:00
c3_assert(_(u3a_is_atom(b)));
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( _(u3a_is_cat(b)) ) {
2014-09-05 23:55:16 +04:00
if ( a_w > 3 ) {
return 0;
}
else return (255 & (b >> (a_w << 3)));
}
else {
2014-11-06 03:20:01 +03:00
u3a_atom* b_u = u3a_to_ptr(b);
2015-07-29 23:43:55 +03:00
c3_y vut_y = (a_w & 3);
c3_w pix_w = (a_w >> 2);
2014-09-05 23:55:16 +04:00
if ( pix_w >= b_u->len_w ) {
return 0;
}
else {
c3_w nys_w = b_u->buf_w[pix_w];
return (255 & (nys_w >> (vut_y << 3)));
}
}
}
2014-11-06 03:20:01 +03:00
/* u3r_bytes():
2014-09-05 23:55:16 +04:00
**
** Copy bytes (a_w) through (a_w + b_w - 1) from (d) to (c).
*/
void
2014-11-06 03:20:01 +03:00
u3r_bytes(c3_w a_w,
2014-09-05 23:55:16 +04:00
c3_w b_w,
c3_y* c_y,
2014-09-06 00:13:24 +04:00
u3_atom d)
2014-09-05 23:55:16 +04:00
{
2014-11-06 02:36:30 +03:00
c3_assert(u3_none != d);
2015-07-29 23:43:55 +03:00
c3_assert(_(u3a_is_atom(d)));
if ( _(u3a_is_cat(d)) ) {
c3_w e_w = d >> (c3_min(a_w, 4) << 3);
c3_w m_w = c3_min(b_w, 4);
memcpy(c_y, (c3_y*)&e_w, m_w);
if ( b_w > 4 ) {
memset(c_y + 4, 0, b_w - 4);
}
}
else {
u3a_atom* d_u = u3a_to_ptr(d);
c3_w n_w = d_u->len_w << 2;
c3_y* x_y = (c3_y*)d_u->buf_w + a_w;
2014-09-05 23:55:16 +04:00
2015-07-29 23:43:55 +03:00
if ( a_w >= n_w ) {
memset(c_y, 0, b_w);
}
else {
c3_w z_w = c3_min(b_w, n_w - a_w);
memcpy(c_y, x_y, z_w);
if ( b_w > n_w - a_w ) {
memset(c_y + z_w, 0, b_w + a_w - n_w);
}
}
2014-09-05 23:55:16 +04:00
}
}
2014-11-06 03:20:01 +03:00
/* u3r_mp():
2014-09-05 23:55:16 +04:00
**
** Copy (b) into (a_mp).
*/
void
2014-11-06 03:20:01 +03:00
u3r_mp(mpz_t a_mp,
2014-09-06 00:13:24 +04:00
u3_atom b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 02:36:30 +03:00
c3_assert(u3_none != b);
2014-11-06 03:20:01 +03:00
c3_assert(_(u3a_is_atom(b)));
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( _(u3a_is_cat(b)) ) {
2014-09-05 23:55:16 +04:00
mpz_init_set_ui(a_mp, b);
}
else {
2014-11-06 03:20:01 +03:00
u3a_atom* b_u = u3a_to_ptr(b);
2014-09-05 23:55:16 +04:00
c3_w len_w = b_u->len_w;
/* Slight deficiency in the GMP API.
*/
c3_assert(!(len_w >> 27));
mpz_init2(a_mp, len_w << 5);
/* Efficiency: horrible.
*/
{
c3_w *buf_w = alloca(len_w << 2);
c3_w i_w;
for ( i_w=0; i_w < len_w; i_w++ ) {
buf_w[i_w] = b_u->buf_w[i_w];
}
mpz_import(a_mp, len_w, -1, 4, 0, 0, buf_w);
}
}
}
2014-11-06 03:20:01 +03:00
/* u3r_word():
2014-09-05 23:55:16 +04:00
**
** Return word (a_w) of (b).
*/
c3_w
2014-11-06 03:20:01 +03:00
u3r_word(c3_w a_w,
2014-09-06 00:13:24 +04:00
u3_atom b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 02:36:30 +03:00
c3_assert(u3_none != b);
2014-11-06 03:20:01 +03:00
c3_assert(_(u3a_is_atom(b)));
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( _(u3a_is_cat(b)) ) {
2014-09-05 23:55:16 +04:00
if ( a_w > 0 ) {
return 0;
}
else return b;
}
else {
2014-11-06 03:20:01 +03:00
u3a_atom* b_u = u3a_to_ptr(b);
2014-09-05 23:55:16 +04:00
if ( a_w >= b_u->len_w ) {
return 0;
}
else return b_u->buf_w[a_w];
}
}
2014-11-06 03:20:01 +03:00
/* u3r_chub():
2014-09-05 23:55:16 +04:00
**
** Return double-word (a_w) of (b).
*/
c3_d
2014-11-06 03:20:01 +03:00
u3r_chub(c3_w a_w,
2014-09-06 00:13:24 +04:00
u3_atom b)
2014-09-05 23:55:16 +04:00
{
2014-11-06 03:20:01 +03:00
c3_w wlo_w = u3r_word(a_w * 2, b);
c3_w whi_w = u3r_word(1 + (a_w * 2), b);
2014-09-05 23:55:16 +04:00
return (((uint64_t)whi_w) << 32ULL) | ((uint64_t)wlo_w);
}
2014-11-06 03:20:01 +03:00
/* u3r_words():
2014-09-05 23:55:16 +04:00
**
** Copy words (a_w) through (a_w + b_w - 1) from (d) to (c).
*/
void
2014-11-06 03:20:01 +03:00
u3r_words(c3_w a_w,
2014-09-05 23:55:16 +04:00
c3_w b_w,
c3_w* c_w,
2014-09-06 00:13:24 +04:00
u3_atom d)
2014-09-05 23:55:16 +04:00
{
2014-11-06 02:36:30 +03:00
c3_assert(u3_none != d);
2015-07-29 23:43:55 +03:00
c3_assert(_(u3a_is_atom(d)));
2014-09-05 23:55:16 +04:00
2015-07-29 23:43:55 +03:00
if ( b_w == 0 ) {
return;
}
if ( _(u3a_is_cat(d)) ) {
if ( a_w == 0 ) {
*c_w = d;
memset((c3_y*)(c_w + 1), 0, (b_w - 1) << 2);
}
else {
memset((c3_y*)c_w, 0, b_w << 2);
}
}
else {
u3a_atom* d_u = u3a_to_ptr(d);
if ( a_w >= d_u->len_w ) {
memset((c3_y*)c_w, 0, b_w << 2);
}
else {
c3_w z_w = c3_min(b_w, d_u->len_w - a_w);
c3_w* x_w = d_u->buf_w + a_w;
memcpy((c3_y*)c_w, (c3_y*)x_w, z_w << 2);
if ( b_w > d_u->len_w - a_w ) {
memset((c3_y*)(c_w + z_w), 0, (b_w + a_w - d_u->len_w) << 2);
}
}
2014-09-05 23:55:16 +04:00
}
}
2014-11-06 03:20:01 +03:00
/* u3r_chop():
2014-09-05 23:55:16 +04:00
**
** Into the bloq space of `met`, from position `fum` for a
** span of `wid`, to position `tou`, XOR from atom `src`
** into `dst_w`.
*/
void
2014-11-06 03:20:01 +03:00
u3r_chop(c3_g met_g,
2014-09-05 23:55:16 +04:00
c3_w fum_w,
c3_w wid_w,
c3_w tou_w,
c3_w* dst_w,
2014-09-06 00:13:24 +04:00
u3_atom src)
2014-09-05 23:55:16 +04:00
{
c3_w i_w;
c3_w len_w;
c3_w* buf_w;
2014-11-06 02:36:30 +03:00
c3_assert(u3_none != src);
2014-11-06 03:20:01 +03:00
c3_assert(_(u3a_is_atom(src)));
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( _(u3a_is_cat(src)) ) {
2014-09-05 23:55:16 +04:00
len_w = src ? 1 : 0;
buf_w = &src;
}
else {
2014-11-06 03:20:01 +03:00
u3a_atom* src_u = u3a_to_ptr(src);
2014-09-05 23:55:16 +04:00
len_w = src_u->len_w;
buf_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];
}
}
}
}
2014-11-06 03:20:01 +03:00
/* u3r_string(): `a` as malloced C string.
2014-09-05 23:55:16 +04:00
*/
c3_c*
2014-11-06 03:20:01 +03:00
u3r_string(u3_atom a)
2014-09-05 23:55:16 +04:00
{
2014-11-06 03:20:01 +03:00
c3_w met_w = u3r_met(3, a);
2014-09-05 23:55:16 +04:00
c3_c* str_c = c3_malloc(met_w + 1);
2014-11-06 03:20:01 +03:00
u3r_bytes(0, met_w, (c3_y*)str_c, a);
2014-09-05 23:55:16 +04:00
str_c[met_w] = 0;
return str_c;
}
2014-11-06 03:20:01 +03:00
/* u3r_tape(): `a`, a list of bytes, as malloced C string.
2014-09-05 23:55:16 +04:00
*/
c3_y*
2014-11-06 03:20:01 +03:00
u3r_tape(u3_noun a)
2014-09-05 23:55:16 +04:00
{
2014-09-06 00:13:24 +04:00
u3_noun b;
2014-09-05 23:55:16 +04:00
c3_w i_w;
c3_y *a_y;
2014-11-06 03:20:01 +03:00
for ( i_w = 0, b=a; c3y == u3a_is_cell(b); i_w++, b=u3a_t(b) )
2014-09-05 23:55:16 +04:00
;
a_y = c3_malloc(i_w + 1);
2014-11-06 03:20:01 +03:00
for ( i_w = 0, b=a; c3y == u3a_is_cell(b); i_w++, b=u3a_t(b) ) {
a_y[i_w] = u3a_h(b);
2014-09-05 23:55:16 +04:00
}
a_y[i_w] = 0;
return a_y;
}
2014-09-07 02:39:28 +04:00
#if 0
/* Finalization mix for better avalanching.
*/
static c3_w
_mur_fmix(c3_w h_w)
{
h_w ^= h_w >> 16;
h_w *= 0x85ebca6b;
h_w ^= h_w >> 13;
h_w *= 0xc2b2ae35;
h_w ^= h_w >> 16;
return h_w;
}
/* _mur_words(): raw MurmurHash3 on raw words.
*/
static c3_w
_mur_words(c3_w syd_w, const c3_w* key_w, c3_w len_w)
{
c3_w goc_w = syd_w;
c3_w lig_w = 0xcc9e2d51;
c3_w duf_w = 0x1b873593;
c3_w i_w;
for ( i_w = 0; i_w < len_w; i_w++ ) {
c3_w kop_w = key_w[i_w];
kop_w *= lig_w;
kop_w = c3_rotw(15, kop_w);
kop_w *= duf_w;
goc_w ^= kop_w;
goc_w = c3_rotw(13, goc_w);
goc_w = (goc_w * 5) + 0xe6546b64;
}
goc_w ^= len_w;
goc_w = _mur_fmix(goc_w);
return goc_w;
}
/* u3_mur_words(): 31-bit nonzero MurmurHash3 on raw words.
*/
c3_w
u3_mur_words(const c3_w* key_w, c3_w len_w)
{
c3_w syd_w = 0xcafebabe;
while ( 1 ) {
c3_w haz_w = _mur_words(syd_w, key_w, len_w);
c3_w ham_w = (haz_w >> 31) ^ (haz_w & 0x7fffffff);
if ( 0 != ham_w ) return ham_w;
else syd_w++;
}
}
/* u3_mur_both():
**
** Join two murs.
*/
c3_w
u3_mur_both(c3_w lef_w, c3_w rit_w)
{
c3_w ham_w = lef_w ^ (0x7fffffff ^ rit_w);
return u3_mur_words(&ham_w, (0 == ham_w) ? 0 : 1);
}
/* u3_mur(): MurmurHash3 on a noun.
*/
c3_w
u3_mur(u3_noun veb)
{
if ( u3_fly_is_cat(veb) ) {
return u3_mur_words(&veb, (0 == veb) ? 0 : 1);
}
else {
c3_w mur_w;
if ( (mur_w=*u3_at_dog_mur(veb)) ) {
return mur_w;
}
2014-11-06 06:10:22 +03:00
if ( u3dog_is_pom(veb) ) {
2014-09-07 02:39:28 +04:00
mur_w = u3_mur_both(u3_mur(u3h(veb)), u3_mur(u3t(veb)));
}
else {
c3_w len_w = u3_met(5, veb);
c3_w* buf_w = malloc(4 * len_w);
u3_words(0, len_w, buf_w, veb);
mur_w = u3_mur_words(buf_w, len_w);
free(buf_w);
}
*u3_at_dog_mur(veb) = mur_w;
return mur_w;
}
}
/* u3_mur_string():
**
** Compute the mur of `a`, LSB first.
*/
c3_w
u3_mur_string(const c3_c *a_c)
{
c3_w len_w = strlen(a_c);
c3_w wor_w = ((len_w + 3) >> 2);
c3_w* buf_w = alloca(4 * wor_w);
c3_w i_w;
for ( i_w = 0; i_w < wor_w; i_w++ ) { buf_w[i_w] = 0; }
for ( i_w = 0; i_w < len_w; i_w++ ) {
c3_w inx_w = (i_w >> 2);
c3_w byt_w = (i_w & 3);
buf_w[inx_w] |= (a_c[i_w] << (8 * byt_w));
}
return u3_mur_words(buf_w, wor_w);
}
/* u3_mur_cell():
**
** Compute the mur of the cell `[hed tel]`.
*/
c3_w
u3_mur_cell(u3_noun hed,
u3_noun tel)
{
c3_w lus_w = u3_mur(hed);
c3_w biq_w = u3_mur(tel);
return u3_mur_both(lus_w, biq_w);
}
/* u3_mur_trel():
**
** Compute the mur of `[a b c]`.
*/
c3_w
u3_mur_trel(u3_noun a,
u3_noun b,
u3_noun c)
{
return u3_mur_both(u3_mur(a), u3_mur_both(u3_mur(b), u3_mur(c)));
}
/* u3_mur_qual():
**
** Compute the mur of `[a b c d]`.
*/
c3_w
u3_mur_qual(u3_noun a,
u3_noun b,
u3_noun c,
u3_noun d)
{
return u3_mur_both(u3_mur(a),
u3_mur_both(u3_mur(b),
u3_mur_both(u3_mur(c), u3_mur(d))));
}
#endif