#include <inttypes.h>
#include <math.h>
#include <pthread.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif
#define INTERPRETED
#define WITHOUT_MAIN
// Types
// --------
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int32_t i32;
typedef float f32;
typedef double f64;
typedef _Atomic(u8) a8;
typedef _Atomic(u16) a16;
typedef _Atomic(u32) a32;
typedef _Atomic(u64) a64;
// Configuration
// -------------
// Threads per CPU
#ifndef TPC_L2
#define TPC_L2 0
#endif
#define TPC (1ul << TPC_L2)
// Types
// -----
// Local Types
typedef u8 Tag; // Tag ::= 3-bit (rounded up to u8)
typedef u32 Val; // Val ::= 29-bit (rounded up to u32)
typedef u32 Port; // Port ::= Tag + Val (fits a u32)
typedef u64 Pair; // Pair ::= Port + Port (fits a u64)
typedef a32 APort; // atomic Port
typedef a64 APair; // atomic Pair
// Rules
typedef u8 Rule; // Rule ::= 3-bit (rounded up to 8)
// Numbs
typedef u32 Numb; // Numb ::= 29-bit (rounded up to u32)
// Tags
#define VAR 0x0 // variable
#define REF 0x1 // reference
#define ERA 0x2 // eraser
#define NUM 0x3 // number
#define CON 0x4 // constructor
#define DUP 0x5 // duplicator
#define OPR 0x6 // operator
#define SWI 0x7 // switch
// Interaction Rule Values
#define LINK 0x0
#define CALL 0x1
#define VOID 0x2
#define ERAS 0x3
#define ANNI 0x4
#define COMM 0x5
#define OPER 0x6
#define SWIT 0x7
// Numbers
static const f32 U24_MAX = (f32) (1 << 24) - 1;
static const f32 U24_MIN = 0.0;
static const f32 I24_MAX = (f32) (1 << 23) - 1;
static const f32 I24_MIN = (f32) (i32) ((-1u) << 23);
#define TY_SYM 0x00
#define TY_U24 0x01
#define TY_I24 0x02
#define TY_F24 0x03
#define OP_ADD 0x04
#define OP_SUB 0x05
#define FP_SUB 0x06
#define OP_MUL 0x07
#define OP_DIV 0x08
#define FP_DIV 0x09
#define OP_REM 0x0A
#define FP_REM 0x0B
#define OP_EQ 0x0C
#define OP_NEQ 0x0D
#define OP_LT 0x0E
#define OP_GT 0x0F
#define OP_AND 0x10
#define OP_OR 0x11
#define OP_XOR 0x12
#define OP_SHL 0x13
#define FP_SHL 0x14
#define OP_SHR 0x15
#define FP_SHR 0x16
// Constants
#define FREE 0x00000000
#define ROOT 0xFFFFFFF8
#define NONE 0xFFFFFFFF
// Cache Padding
#define CACHE_PAD 64
// Global Net
#define HLEN (1ul << 16) // max 16k high-priority redexes
#define RLEN (1ul << 24) // max 16m low-priority redexes
#define G_NODE_LEN (1ul << 29) // max 536m nodes
#define G_VARS_LEN (1ul << 29) // max 536m vars
#define G_RBAG_LEN (TPC * RLEN)
typedef struct Net {
APair node_buf[G_NODE_LEN]; // global node buffer
APort vars_buf[G_VARS_LEN]; // global vars buffer
APair rbag_buf[G_RBAG_LEN]; // global rbag buffer
a64 itrs; // interaction count
a32 idle; // idle thread counter
} Net;
#define DEF_RBAG_LEN 0xFFF
#define DEF_NODE_LEN 0xFFF
// Top-Level Definition
typedef struct Def {
char name[256];
bool safe;
u32 rbag_len;
u32 node_len;
u32 vars_len;
Port root;
Pair node_buf[DEF_NODE_LEN];
Pair rbag_buf[DEF_RBAG_LEN];
} Def;
typedef struct Book Book;
// A Foreign Function
typedef struct {
char name[256];
Port (*func)(Net*, Book*, Port);
} FFn;
// Book of Definitions
typedef struct Book {
u32 defs_len;
Def defs_buf[0x4000];
u32 ffns_len;
FFn ffns_buf[0x4000];
} Book;
// Local Thread Memory
typedef struct TM {
u32 tid; // thread id
u32 itrs; // interaction count
u32 nput; // next node allocation attempt index
u32 vput; // next vars allocation attempt index
u32 hput; // next hbag push index
u32 rput; // next rbag push index
u32 sidx; // steal index
u32 nloc[0xFFF]; // global node allocation indices
u32 vloc[0xFFF]; // global vars allocation indices
Pair hbag_buf[HLEN]; // high-priority redexes
} TM;
// Debugger
// --------
typedef struct {
char x[13];
} Show;
void put_u16(char* B, u16 val);
Show show_port(Port port);
Show show_rule(Rule rule);
void print_net(Net* net);
void pretty_print_numb(Numb word);
void pretty_print_port(Net* net, Book* book, Port port);
// Port: Constructor and Getters
// -----------------------------
static inline Port new_port(Tag tag, Val val) {
return (val << 3) | tag;
}
static inline Tag get_tag(Port port) {
return port & 7;
}
static inline Val get_val(Port port) {
return port >> 3;
}
// Pair: Constructor and Getters
// -----------------------------
static inline const Pair new_pair(Port fst, Port snd) {
return ((u64)snd << 32) | fst;
}
static inline Port get_fst(Pair pair) {
return pair & 0xFFFFFFFF;
}
static inline Port get_snd(Pair pair) {
return pair >> 32;
}
Pair set_par_flag(Pair pair) {
Port p1 = get_fst(pair);
Port p2 = get_snd(pair);
if (get_tag(p1) == REF) {
return new_pair(new_port(get_tag(p1), get_val(p1) | 0x10000000), p2);
} else {
return pair;
}
}
Pair clr_par_flag(Pair pair) {
Port p1 = get_fst(pair);
Port p2 = get_snd(pair);
if (get_tag(p1) == REF) {
return new_pair(new_port(get_tag(p1), get_val(p1) & 0xFFFFFFF), p2);
} else {
return pair;
}
}
bool get_par_flag(Pair pair) {
Port p1 = get_fst(pair);
if (get_tag(p1) == REF) {
return (get_val(p1) >> 28) == 1;
} else {
return false;
}
}
// Utils
// -----
// Swaps two ports.
static inline void swap(Port *a, Port *b) {
Port x = *a; *a = *b; *b = x;
}
static inline u32 min(u32 a, u32 b) {
return (a < b) ? a : b;
}
static inline f32 clamp(f32 x, f32 min, f32 max) {
const f32 t = x < min ? min : x;
return (t > max) ? max : t;
}
// A simple spin-wait barrier using atomic operations
a64 a_reached = 0; // number of threads that reached the current barrier
a64 a_barrier = 0; // number of barriers passed during this program
void sync_threads() {
u64 barrier_old = atomic_load_explicit(&a_barrier, memory_order_relaxed);
if (atomic_fetch_add_explicit(&a_reached, 1, memory_order_relaxed) == (TPC - 1)) {
// Last thread to reach the barrier resets the counter and advances the barrier
atomic_store_explicit(&a_reached, 0, memory_order_relaxed);
atomic_store_explicit(&a_barrier, barrier_old + 1, memory_order_release);
} else {
u32 tries = 0;
while (atomic_load_explicit(&a_barrier, memory_order_acquire) == barrier_old) {
sched_yield();
}
}
}
// Global sum function
static a32 GLOBAL_SUM = 0;
u32 global_sum(u32 x) {
atomic_fetch_add_explicit(&GLOBAL_SUM, x, memory_order_relaxed);
sync_threads();
u32 sum = atomic_load_explicit(&GLOBAL_SUM, memory_order_relaxed);
sync_threads();
atomic_store_explicit(&GLOBAL_SUM, 0, memory_order_relaxed);
return sum;
}
// TODO: write a time64() function that returns the time as fast as possible as a u64
static inline u64 time64() {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (u64)ts.tv_sec * 1000000000ULL + (u64)ts.tv_nsec;
}
// Ports / Pairs / Rules
// ---------------------
// True if this port has a pointer to a node.
static inline bool is_nod(Port a) {
return get_tag(a) >= CON;
}
// True if this port is a variable.
static inline bool is_var(Port a) {
return get_tag(a) == VAR;
}
// Given two tags, gets their interaction rule.
static inline Rule get_rule(Port a, Port b) {
const u8 table[8][8] = {
//VAR REF ERA NUM CON DUP OPR SWI
{LINK,LINK,LINK,LINK,LINK,LINK,LINK,LINK}, // VAR
{LINK,VOID,VOID,VOID,CALL,CALL,CALL,CALL}, // REF
{LINK,VOID,VOID,VOID,ERAS,ERAS,ERAS,ERAS}, // ERA
{LINK,VOID,VOID,VOID,ERAS,ERAS,OPER,SWIT}, // NUM
{LINK,CALL,ERAS,ERAS,ANNI,COMM,COMM,COMM}, // CON
{LINK,CALL,ERAS,ERAS,COMM,ANNI,COMM,COMM}, // DUP
{LINK,CALL,ERAS,OPER,COMM,COMM,ANNI,COMM}, // OPR
{LINK,CALL,ERAS,SWIT,COMM,COMM,COMM,ANNI}, // SWI
};
return table[get_tag(a)][get_tag(b)];
}
// Same as above, but receiving a pair.
static inline Rule get_pair_rule(Pair AB) {
return get_rule(get_fst(AB), get_snd(AB));
}
// Should we swap ports A and B before reducing this rule?
static inline bool should_swap(Port A, Port B) {
return get_tag(B) < get_tag(A);
}
// Gets a rule's priority
static inline bool is_high_priority(Rule rule) {
// TODO: this needs to be more readable
return (bool)((0b00011101 >> rule) & 1);
}
// Adjusts a newly allocated port.
static inline Port adjust_port(Net* net, TM* tm, Port port) {
Tag tag = get_tag(port);
Val val = get_val(port);
if (is_nod(port)) return new_port(tag, tm->nloc[val]);
if (is_var(port)) return new_port(tag, tm->vloc[val]);
return new_port(tag, val);
}
// Adjusts a newly allocated pair.
static inline Pair adjust_pair(Net* net, TM* tm, Pair pair) {
Port p1 = adjust_port(net, tm, get_fst(pair));
Port p2 = adjust_port(net, tm, get_snd(pair));
return new_pair(p1, p2);
}
// Numbs
// -----
// Constructor and getters for SYM (operation selector)
static inline Numb new_sym(u32 val) {
return (val << 5) | TY_SYM;
}
static inline u32 get_sym(Numb word) {
return (word >> 5);
}
// Constructor and getters for U24 (unsigned 24-bit integer)
static inline Numb new_u24(u32 val) {
return (val << 5) | TY_U24;
}
static inline u32 get_u24(Numb word) {
return word >> 5;
}
// Constructor and getters for I24 (signed 24-bit integer)
static inline Numb new_i24(i32 val) {
return ((u32)val << 5) | TY_I24;
}
static inline i32 get_i24(Numb word) {
return ((i32)word) << 3 >> 8;
}
// Constructor and getters for F24 (24-bit float)
static inline Numb new_f24(float val) {
u32 bits = *(u32*)&val;
u32 shifted_bits = bits >> 8;
u32 lost_bits = bits & 0xFF;
// round ties to even
shifted_bits += (!isnan(val)) & ((lost_bits - ((lost_bits >> 7) & !shifted_bits)) >> 7);
// ensure NaNs don't become infinities
shifted_bits |= isnan(val);
return (shifted_bits << 5) | TY_F24;
}
static inline float get_f24(Numb word) {
u32 bits = (word << 3) & 0xFFFFFF00;
return *(float*)&bits;
}
// Flip flag
static inline Tag get_typ(Numb word) {
return word & 0x1F;
}
static inline bool is_num(Numb word) {
return get_typ(word) >= TY_U24 && get_typ(word) <= TY_F24;
}
static inline bool is_cast(Numb word) {
return get_typ(word) == TY_SYM && get_sym(word) >= TY_U24 && get_sym(word) <= TY_F24;
}
// Partial application
static inline Numb partial(Numb a, Numb b) {
return (b & ~0x1F) | get_sym(a);
}
// Cast a number to another type.
// The semantics are meant to spiritually resemble rust's numeric casts:
// - i24 <-> u24: is just reinterpretation of bits
// - f24 -> i24,
// f24 -> u24: casts to the "closest" integer representing this float,
// saturating if out of range and 0 if NaN
// - i24 -> f24,
// u24 -> f24: casts to the "closest" float representing this integer.
static inline Numb cast(Numb a, Numb b) {
if (get_sym(a) == TY_U24 && get_typ(b) == TY_U24) return b;
if (get_sym(a) == TY_U24 && get_typ(b) == TY_I24) {
// reinterpret bits
i32 val = get_i24(b);
return new_u24(*(u32*) &val);
}
if (get_sym(a) == TY_U24 && get_typ(b) == TY_F24) {
f32 val = get_f24(b);
if (isnan(val)) {
return new_u24(0);
}
return new_u24((u32) clamp(val, U24_MIN, U24_MAX));
}
if (get_sym(a) == TY_I24 && get_typ(b) == TY_U24) {
// reinterpret bits
u32 val = get_u24(b);
return new_i24(*(i32*) &val);
}
if (get_sym(a) == TY_I24 && get_typ(b) == TY_I24) return b;
if (get_sym(a) == TY_I24 && get_typ(b) == TY_F24) {
f32 val = get_f24(b);
if (isnan(val)) {
return new_i24(0);
}
return new_i24((i32) clamp(val, I24_MIN, I24_MAX));
}
if (get_sym(a) == TY_F24 && get_typ(b) == TY_U24) return new_f24((f32) get_u24(b));
if (get_sym(a) == TY_F24 && get_typ(b) == TY_I24) return new_f24((f32) get_i24(b));
if (get_sym(a) == TY_F24 && get_typ(b) == TY_F24) return b;
return new_u24(0);
}
// Operate function
static inline Numb operate(Numb a, Numb b) {
Tag at = get_typ(a);
Tag bt = get_typ(b);
if (at == TY_SYM && bt == TY_SYM) {
return new_u24(0);
}
if (is_cast(a) && is_num(b)) {
return cast(a, b);
}
if (is_cast(b) && is_num(a)) {
return cast(b, a);
}
if (at == TY_SYM && bt != TY_SYM) {
return partial(a, b);
}
if (at != TY_SYM && bt == TY_SYM) {
return partial(b, a);
}
if (at >= OP_ADD && bt >= OP_ADD) {
return new_u24(0);
}
if (at < OP_ADD && bt < OP_ADD) {
return new_u24(0);
}
Tag op, ty;
Numb swp;
if (at >= OP_ADD) {
op = at; ty = bt;
} else {
op = bt; ty = at; swp = a; a = b; b = swp;
}
switch (ty) {
case TY_U24: {
u32 av = get_u24(a);
u32 bv = get_u24(b);
switch (op) {
case OP_ADD: return new_u24(av + bv);
case OP_SUB: return new_u24(av - bv);
case FP_SUB: return new_u24(bv - av);
case OP_MUL: return new_u24(av * bv);
case OP_DIV: return new_u24(av / bv);
case FP_DIV: return new_u24(bv / av);
case OP_REM: return new_u24(av % bv);
case FP_REM: return new_u24(bv % av);
case OP_EQ: return new_u24(av == bv);
case OP_NEQ: return new_u24(av != bv);
case OP_LT: return new_u24(av < bv);
case OP_GT: return new_u24(av > bv);
case OP_AND: return new_u24(av & bv);
case OP_OR: return new_u24(av | bv);
case OP_XOR: return new_u24(av ^ bv);
case OP_SHL: return new_u24(av << (bv & 31));
case FP_SHL: return new_u24(bv << (av & 31));
case OP_SHR: return new_u24(av >> (bv & 31));
case FP_SHR: return new_u24(bv >> (av & 31));
default: return new_u24(0);
}
}
case TY_I24: {
i32 av = get_i24(a);
i32 bv = get_i24(b);
switch (op) {
case OP_ADD: return new_i24(av + bv);
case OP_SUB: return new_i24(av - bv);
case FP_SUB: return new_i24(bv - av);
case OP_MUL: return new_i24(av * bv);
case OP_DIV: return new_i24(av / bv);
case FP_DIV: return new_i24(bv / av);
case OP_REM: return new_i24(av % bv);
case FP_REM: return new_i24(bv % av);
case OP_EQ: return new_u24(av == bv);
case OP_NEQ: return new_u24(av != bv);
case OP_LT: return new_u24(av < bv);
case OP_GT: return new_u24(av > bv);
case OP_AND: return new_i24(av & bv);
case OP_OR: return new_i24(av | bv);
case OP_XOR: return new_i24(av ^ bv);
default: return new_i24(0);
}
}
case TY_F24: {
float av = get_f24(a);
float bv = get_f24(b);
switch (op) {
case OP_ADD: return new_f24(av + bv);
case OP_SUB: return new_f24(av - bv);
case FP_SUB: return new_f24(bv - av);
case OP_MUL: return new_f24(av * bv);
case OP_DIV: return new_f24(av / bv);
case FP_DIV: return new_f24(bv / av);
case OP_REM: return new_f24(fmodf(av, bv));
case FP_REM: return new_f24(fmodf(bv, av));
case OP_EQ: return new_u24(av == bv);
case OP_NEQ: return new_u24(av != bv);
case OP_LT: return new_u24(av < bv);
case OP_GT: return new_u24(av > bv);
case OP_AND: return new_f24(atan2f(av, bv));
case OP_OR: return new_f24(logf(bv) / logf(av));
case OP_XOR: return new_f24(powf(av, bv));
case OP_SHL: return new_f24(sin(av + bv));
case OP_SHR: return new_f24(tan(av + bv));
default: return new_f24(0);
}
}
default: return new_u24(0);
}
}
// RBag
// ----
// FIXME: what about some bound checks?
static inline void push_redex(Net* net, TM* tm, Pair redex) {
#ifdef DEBUG
bool free_local = tm->hput < HLEN;
bool free_global = tm->rput < RLEN;
if (!free_global || !free_local) {
debug("push_redex: limited resources, maybe corrupting memory\n");
}
#endif
if (is_high_priority(get_pair_rule(redex))) {
tm->hbag_buf[tm->hput++] = redex;
} else {
atomic_store_explicit(&net->rbag_buf[tm->tid*(G_RBAG_LEN/TPC) + (tm->rput++)], redex, memory_order_relaxed);
}
}
static inline Pair pop_redex(Net* net, TM* tm) {
if (tm->hput > 0) {
return tm->hbag_buf[--tm->hput];
} else if (tm->rput > 0) {
return atomic_exchange_explicit(&net->rbag_buf[tm->tid*(G_RBAG_LEN/TPC) + (--tm->rput)], 0, memory_order_relaxed);
} else {
return 0;
}
}
static inline u32 rbag_len(Net* net, TM* tm) {
return tm->rput + tm->hput;
}
// TM
// --
static TM* tm[TPC];
TM* tm_new(u32 tid) {
TM* tm = malloc(sizeof(TM));
tm->tid = tid;
tm->itrs = 0;
tm->nput = 1;
tm->vput = 1;
tm->rput = 0;
tm->hput = 0;
tm->sidx = 0;
return tm;
}
void alloc_static_tms() {
for (u32 t = 0; t < TPC; ++t) {
tm[t] = tm_new(t);
}
}
void free_static_tms() {
for (u32 t = 0; t < TPC; ++t) {
free(tm[t]);
}
}
// Net
// ----
// Stores a new node on global.
static inline void node_create(Net* net, u32 loc, Pair val) {
atomic_store_explicit(&net->node_buf[loc], val, memory_order_relaxed);
}
// Stores a var on global.
static inline void vars_create(Net* net, u32 var, Port val) {
atomic_store_explicit(&net->vars_buf[var], val, memory_order_relaxed);
}
// Reads a node from global.
static inline Pair node_load(Net* net, u32 loc) {
return atomic_load_explicit(&net->node_buf[loc], memory_order_relaxed);
}
// Reads a var from global.
static inline Port vars_load(Net* net, u32 var) {
return atomic_load_explicit(&net->vars_buf[var], memory_order_relaxed);
}
// Stores a node on global.
static inline void node_store(Net* net, u32 loc, Pair val) {
atomic_store_explicit(&net->node_buf[loc], val, memory_order_relaxed);
}
// Exchanges a node on global by a value. Returns old.
static inline Pair node_exchange(Net* net, u32 loc, Pair val) {
return atomic_exchange_explicit(&net->node_buf[loc], val, memory_order_relaxed);
}
// Exchanges a var on global by a value. Returns old.
static inline Port vars_exchange(Net* net, u32 var, Port val) {
return atomic_exchange_explicit(&net->vars_buf[var], val, memory_order_relaxed);
}
// Takes a node.
static inline Pair node_take(Net* net, u32 loc) {
return node_exchange(net, loc, 0);
}
// Takes a var.
static inline Port vars_take(Net* net, u32 var) {
return vars_exchange(net, var, 0);
}
// Net
// ---
// Initializes a net.
static inline Net* net_new() {
Net* net = calloc(1, sizeof(Net));
atomic_store(&net->itrs, 0);
atomic_store(&net->idle, 0);
return net;
}
// Allocator
// ---------
u32 node_alloc_1(Net* net, TM* tm, u32* lps) {
while (true) {
u32 lc = tm->tid*(G_NODE_LEN/TPC) + (tm->nput%(G_NODE_LEN/TPC));
Pair elem = net->node_buf[lc];
tm->nput += 1;
if (lc > 0 && elem == 0) {
return lc;
}
// FIXME: check this decently
if (++(*lps) >= G_NODE_LEN/TPC) printf("OOM\n");
}
}
u32 vars_alloc_1(Net* net, TM* tm, u32* lps) {
while (true) {
u32 lc = tm->tid*(G_NODE_LEN/TPC) + (tm->vput%(G_NODE_LEN/TPC));
Port elem = net->vars_buf[lc];
tm->vput += 1;
if (lc > 0 && elem == 0) {
return lc;
}
// FIXME: check this decently
if (++(*lps) >= G_NODE_LEN/TPC) printf("OOM\n");
}
}
u32 node_alloc(Net* net, TM* tm, u32 num) {
u32 got = 0;
u32 lps = 0;
while (got < num) {
u32 lc = tm->tid*(G_NODE_LEN/TPC) + (tm->nput%(G_NODE_LEN/TPC));
Pair elem = net->node_buf[lc];
tm->nput += 1;
if (lc > 0 && elem == 0) {
tm->nloc[got++] = lc;
}
// FIXME: check this decently
if (++lps >= G_NODE_LEN/TPC) printf("OOM\n");
}
return got;
}
u32 vars_alloc(Net* net, TM* tm, u32 num) {
u32 got = 0;
u32 lps = 0;
while (got < num) {
u32 lc = tm->tid*(G_NODE_LEN/TPC) + (tm->vput%(G_NODE_LEN/TPC));
Port elem = net->vars_buf[lc];
tm->vput += 1;
if (lc > 0 && elem == 0) {
tm->vloc[got++] = lc;
}
// FIXME: check this decently
if (++lps >= G_NODE_LEN/TPC) printf("OOM\n");
}
return got;
}
// Gets the necessary resources for an interaction. Returns success.
static inline bool get_resources(Net* net, TM* tm, u32 need_rbag, u32 need_node, u32 need_vars) {
u32 got_rbag = min(RLEN - tm->rput, HLEN - tm->hput);
u32 got_node = node_alloc(net, tm, need_node);
u32 got_vars = vars_alloc(net, tm, need_vars);
return got_rbag >= need_rbag && got_node >= need_node && got_vars >= need_vars;
}
// Linking
// -------
// Peeks a variable's final target without modifying it.
static inline Port peek(Net* net, Port var) {
while (get_tag(var) == VAR) {
Port val = vars_load(net, get_val(var));
if (val == NONE) break;
if (val == 0) break;
var = val;
}
return var;
}
// Finds a variable's value.
static inline Port enter(Net* net, Port var) {
// While `B` is VAR: extend it (as an optimization)
while (get_tag(var) == VAR) {
// Takes the current `var` substitution as `val`
Port val = vars_exchange(net, get_val(var), NONE);
// If there was no `val`, stop, as there is no extension
if (val == NONE || val == 0) {
break;
}
// Otherwise, delete `B` (we own both) and continue
vars_take(net, get_val(var));
var = val;
}
return var;
}
// Atomically Links `A ~ B`.
static inline void link(Net* net, TM* tm, Port A, Port B) {
// Attempts to directionally point `A ~> B`
while (true) {
// If `A` is NODE: swap `A` and `B`, and continue
if (get_tag(A) != VAR && get_tag(B) == VAR) {
Port X = A; A = B; B = X;
}
// If `A` is NODE: create the `A ~ B` redex
if (get_tag(A) != VAR) {
push_redex(net, tm, new_pair(A, B)); // TODO: move global ports to local
break;
}
// Extends B (as an optimization)
B = enter(net, B);
// Since `A` is VAR: point `A ~> B`.
// Stores `A -> B`, taking the current `A` subst as `A'`
Port A_ = vars_exchange(net, get_val(A), B);
// If there was no `A'`, stop, as we lost B's ownership
if (A_ == NONE) {
break;
}
//if (A_ == 0) { ? } // FIXME: must handle on the move-to-global algo
// Otherwise, delete `A` (we own both) and link `A' ~ B`
vars_take(net, get_val(A));
A = A_;
}
}
// Links `A ~ B` (as a pair).
static inline void link_pair(Net* net, TM* tm, Pair AB) {
link(net, tm, get_fst(AB), get_snd(AB));
}
// Interactions
// ------------
// The Link Interaction.
static inline bool interact_link(Net* net, TM* tm, Port a, Port b) {
// Allocates needed nodes and vars.
if (!get_resources(net, tm, 1, 0, 0)) {
debug("interact_link: get_resources failed\n");
return false;
}
// Links.
link_pair(net, tm, new_pair(a, b));
return true;
}
// Declared here for use in call interactions.
static inline bool interact_eras(Net* net, TM* tm, Port a, Port b);
// The Call Interaction.
#ifdef COMPILED
///COMPILED_INTERACT_CALL///
#else
static inline bool interact_call(Net* net, TM* tm, Port a, Port b, Book* book) {
// Loads Definition.
u32 fid = get_val(a) & 0xFFFFFFF;
Def* def = &book->defs_buf[fid];
// Copy Optimization.
if (def->safe && get_tag(b) == DUP) {
return interact_eras(net, tm, a, b);
}
// Allocates needed nodes and vars.
if (!get_resources(net, tm, def->rbag_len + 1, def->node_len, def->vars_len)) {
debug("interact_call: get_resources failed\n");
return false;
}
// Stores new vars.
for (u32 i = 0; i < def->vars_len; ++i) {
vars_create(net, tm->vloc[i], NONE);
}
// Stores new nodes.
for (u32 i = 0; i < def->node_len; ++i) {
node_create(net, tm->nloc[i], adjust_pair(net, tm, def->node_buf[i]));
}
// Links.
for (u32 i = 0; i < def->rbag_len; ++i) {
link_pair(net, tm, adjust_pair(net, tm, def->rbag_buf[i]));
}
link_pair(net, tm, new_pair(adjust_port(net, tm, def->root), b));
return true;
}
#endif
// The Void Interaction.
static inline bool interact_void(Net* net, TM* tm, Port a, Port b) {
return true;
}
// The Eras Interaction.
static inline bool interact_eras(Net* net, TM* tm, Port a, Port b) {
// Allocates needed nodes and vars.
if (!get_resources(net, tm, 2, 0, 0)) {
debug("interact_eras: get_resources failed\n");
return false;
}
// Checks availability
if (node_load(net, get_val(b)) == 0) {
return false;
}
// Loads ports.
Pair B = node_exchange(net, get_val(b), 0);
Port B1 = get_fst(B);
Port B2 = get_snd(B);
// Links.
link_pair(net, tm, new_pair(a, B1));
link_pair(net, tm, new_pair(a, B2));
return true;
}
// The Anni Interaction.
static inline bool interact_anni(Net* net, TM* tm, Port a, Port b) {
// Allocates needed nodes and vars.
if (!get_resources(net, tm, 2, 0, 0)) {
debug("interact_anni: get_resources failed\n");
return false;
}
// Checks availability
if (node_load(net, get_val(a)) == 0 || node_load(net, get_val(b)) == 0) {
return false;
}
// Loads ports.
Pair A = node_take(net, get_val(a));
Port A1 = get_fst(A);
Port A2 = get_snd(A);
Pair B = node_take(net, get_val(b));
Port B1 = get_fst(B);
Port B2 = get_snd(B);
// Links.
link_pair(net, tm, new_pair(A1, B1));
link_pair(net, tm, new_pair(A2, B2));
return true;
}
// The Comm Interaction.
static inline bool interact_comm(Net* net, TM* tm, Port a, Port b) {
// Allocates needed nodes and vars.
if (!get_resources(net, tm, 4, 4, 4)) {
debug("interact_comm: get_resources failed\n");
return false;
}
// Checks availability
if (node_load(net, get_val(a)) == 0 || node_load(net, get_val(b)) == 0) {
return false;
}
// Loads ports.
Pair A = node_take(net, get_val(a));
Port A1 = get_fst(A);
Port A2 = get_snd(A);
Pair B = node_take(net, get_val(b));
Port B1 = get_fst(B);
Port B2 = get_snd(B);
// Stores new vars.
vars_create(net, tm->vloc[0], NONE);
vars_create(net, tm->vloc[1], NONE);
vars_create(net, tm->vloc[2], NONE);
vars_create(net, tm->vloc[3], NONE);
// Stores new nodes.
node_create(net, tm->nloc[0], new_pair(new_port(VAR, tm->vloc[0]), new_port(VAR, tm->vloc[1])));
node_create(net, tm->nloc[1], new_pair(new_port(VAR, tm->vloc[2]), new_port(VAR, tm->vloc[3])));
node_create(net, tm->nloc[2], new_pair(new_port(VAR, tm->vloc[0]), new_port(VAR, tm->vloc[2])));
node_create(net, tm->nloc[3], new_pair(new_port(VAR, tm->vloc[1]), new_port(VAR, tm->vloc[3])));
// Links.
link_pair(net, tm, new_pair(new_port(get_tag(b), tm->nloc[0]), A1));
link_pair(net, tm, new_pair(new_port(get_tag(b), tm->nloc[1]), A2));
link_pair(net, tm, new_pair(new_port(get_tag(a), tm->nloc[2]), B1));
link_pair(net, tm, new_pair(new_port(get_tag(a), tm->nloc[3]), B2));
return true;
}
// The Oper Interaction.
static inline bool interact_oper(Net* net, TM* tm, Port a, Port b) {
// Allocates needed nodes and vars.
if (!get_resources(net, tm, 1, 1, 0)) {
debug("interact_oper: get_resources failed\n");
return false;
}
// Checks availability
if (node_load(net, get_val(b)) == 0) {
return false;
}
// Loads ports.
Val av = get_val(a);
Pair B = node_take(net, get_val(b));
Port B1 = get_fst(B);
Port B2 = enter(net, get_snd(B));
// Performs operation.
if (get_tag(B1) == NUM) {
Val bv = get_val(B1);
Numb cv = operate(av, bv);
link_pair(net, tm, new_pair(new_port(NUM, cv), B2));
} else {
node_create(net, tm->nloc[0], new_pair(a, B2));
link_pair(net, tm, new_pair(B1, new_port(OPR, tm->nloc[0])));
}
return true;
}
// The Swit Interaction.
static inline bool interact_swit(Net* net, TM* tm, Port a, Port b) {
// Allocates needed nodes and vars.
if (!get_resources(net, tm, 1, 2, 0)) {
debug("interact_swit: get_resources failed\n");
return false;
}
// Checks availability
if (node_load(net, get_val(b)) == 0) {
return false;
}
// Loads ports.
u32 av = get_u24(get_val(a));
Pair B = node_take(net, get_val(b));
Port B1 = get_fst(B);
Port B2 = get_snd(B);
// Stores new nodes.
if (av == 0) {
node_create(net, tm->nloc[0], new_pair(B2, new_port(ERA,0)));
link_pair(net, tm, new_pair(new_port(CON, tm->nloc[0]), B1));
} else {
node_create(net, tm->nloc[0], new_pair(new_port(ERA,0), new_port(CON, tm->nloc[1])));
node_create(net, tm->nloc[1], new_pair(new_port(NUM, new_u24(av-1)), B2));
link_pair(net, tm, new_pair(new_port(CON, tm->nloc[0]), B1));
}
return true;
}
// Pops a local redex and performs a single interaction.
static inline bool interact(Net* net, TM* tm, Book* book) {
// Pops a redex.
Pair redex = pop_redex(net, tm);
// If there is no redex, stop.
if (redex != 0) {
// Gets redex ports A and B.
Port a = get_fst(redex);
Port b = get_snd(redex);
// Gets the rule type.
Rule rule = get_rule(a, b);
// Used for root redex.
if (get_tag(a) == REF && b == ROOT) {
rule = CALL;
// Swaps ports if necessary.
} else if (should_swap(a,b)) {
swap(&a, &b);
}
// Dispatches interaction rule.
bool success;
switch (rule) {
case LINK: success = interact_link(net, tm, a, b); break;
#ifdef COMPILED
case CALL: success = interact_call(net, tm, a, b); break;
#else
case CALL: success = interact_call(net, tm, a, b, book); break;
#endif
case VOID: success = interact_void(net, tm, a, b); break;
case ERAS: success = interact_eras(net, tm, a, b); break;
case ANNI: success = interact_anni(net, tm, a, b); break;
case COMM: success = interact_comm(net, tm, a, b); break;
case OPER: success = interact_oper(net, tm, a, b); break;
case SWIT: success = interact_swit(net, tm, a, b); break;
}
// If error, pushes redex back.
if (!success) {
push_redex(net, tm, redex);
return false;
// Else, increments the interaction count.
} else if (rule != LINK) {
tm->itrs += 1;
}
}
return true;
}
// Evaluator
// ---------
void evaluator(Net* net, TM* tm, Book* book) {
// Initializes the global idle counter
atomic_store_explicit(&net->idle, TPC - 1, memory_order_relaxed);
sync_threads();
// Performs some interactions
u32 tick = 0;
bool busy = tm->tid == 0;
while (true) {
tick += 1;
// If we have redexes...
if (rbag_len(net, tm) > 0) {
// Update global idle counter
if (!busy) atomic_fetch_sub_explicit(&net->idle, 1, memory_order_relaxed);
busy = true;
// Perform an interaction
#ifdef DEBUG
if (!interact(net, tm, book)) debug("interaction failed\n");
#else
interact(net, tm, book);
#endif
// If we have no redexes...
} else {
// Update global idle counter
if (busy) atomic_fetch_add_explicit(&net->idle, 1, memory_order_relaxed);
busy = false;
//// Peeks a redex from target
u32 sid = (tm->tid - 1) % TPC;
u32 idx = sid*(G_RBAG_LEN/TPC) + (tm->sidx++);
// Stealing Everything: this will steal all redexes
Pair got = atomic_exchange_explicit(&net->rbag_buf[idx], 0, memory_order_relaxed);
if (got != 0) {
push_redex(net, tm, got);
continue;
} else {
tm->sidx = 0;
}
// Chill...
sched_yield();
// Halt if all threads are idle
if (tick % 256 == 0) {
if (atomic_load_explicit(&net->idle, memory_order_relaxed) == TPC) {
break;
}
}
}
}
sync_threads();
atomic_fetch_add(&net->itrs, tm->itrs);
tm->itrs = 0;
}
// Normalizer
// ----------
// Thread data
typedef struct {
Net* net;
TM* tm;
Book* book;
} ThreadArg;
void* thread_func(void* arg) {
ThreadArg* data = (ThreadArg*)arg;
evaluator(data->net, data->tm, data->book);
return NULL;
}
// Sets the initial redex.
void boot_redex(Net* net, Pair redex) {
net->vars_buf[get_val(ROOT)] = NONE;
net->rbag_buf[0] = redex;
}
// Evaluates all redexes.
// TODO: cache threads to avoid spawning overhead
void normalize(Net* net, Book* book) {
// Inits thread_arg objects
ThreadArg thread_arg[TPC];
for (u32 t = 0; t < TPC; ++t) {
thread_arg[t].net = net;
thread_arg[t].tm = tm[t];
thread_arg[t].book = book;
}
// Spawns the evaluation threads
pthread_t threads[TPC];
for (u32 t = 0; t < TPC; ++t) {
pthread_create(&threads[t], NULL, thread_func, &thread_arg[t]);
}
// Wait for the threads to finish
for (u32 t = 0; t < TPC; ++t) {
pthread_join(threads[t], NULL);
}
}
// Util: expands a REF Port.
Port expand(Net* net, Book* book, Port port) {
Port old = vars_load(net, get_val(ROOT));
Port got = peek(net, port);
while (get_tag(got) == REF) {
boot_redex(net, new_pair(got, ROOT));
normalize(net, book);
got = peek(net, vars_load(net, get_val(ROOT)));
}
vars_create(net, get_val(ROOT), old);
return got;
}
// Reads back an image.
// Encoding: (<tree>,<tree>) | #RRGGBB
void read_img(Net* net, Port port, u32 width, u32 height, u32* buffer) {
//pretty_print_port(net, port);
//printf("\n");
typedef struct {
Port port; u32 lv;
u32 x0; u32 x1;
u32 y0; u32 y1;
} Rect;
Rect stk[24];
u32 pos = 0;
stk[pos++] = (Rect){port, 0, 0, width, 0, height};
while (pos > 0) {
Rect rect = stk[--pos];
Port port = enter(net, rect.port);
u32 lv = rect.lv;
u32 x0 = rect.x0;
u32 x1 = rect.x1;
u32 y0 = rect.y0;
u32 y1 = rect.y1;
if (get_tag(port) == CON) {
Pair nd = node_load(net, get_val(port));
Port p1 = get_fst(nd);
Port p2 = get_snd(nd);
u32 xm = (x0 + x1) / 2;
u32 ym = (y0 + y1) / 2;
if (lv % 2 == 0) {
stk[pos++] = (Rect){p2, lv+1, xm, x1, y0, y1};
stk[pos++] = (Rect){p1, lv+1, x0, xm, y0, y1};
} else {
stk[pos++] = (Rect){p2, lv+1, x0, x1, ym, y1};
stk[pos++] = (Rect){p1, lv+1, x0, x1, y0, ym};
}
continue;
}
if (get_tag(port) == NUM) {
u32 color = get_u24(get_val(port));
printf("COL=%08x x0=%04u x1=%04u y0=%04u y1=%04u | %s\n", color, x0, x1, y0, y1, show_port(port).x);
for (u32 y = y0; y < y1; y++) {
for (u32 x = x0; x < x1; x++) {
buffer[y*width + x] = 0xFF000000 | color;
}
}
continue;
}
break;
}
}
//#ifdef IO_DRAWIMAGE
//// Global variables for the window and renderer
//static SDL_Window *window = NULL;
//static SDL_Renderer *renderer = NULL;
//static SDL_Texture *texture = NULL;
//// Function to close the SDL window and clean up resources
//void close_sdl(void) {
//if (texture != NULL) {
//SDL_DestroyTexture(texture);
//texture = NULL;
//}
//if (renderer != NULL) {
//SDL_DestroyRenderer(renderer);
//renderer = NULL;
//}
//if (window != NULL) {
//SDL_DestroyWindow(window);
//window = NULL;
//}
//SDL_Quit();
//}
//// Function to render an image to the SDL window
//void render(uint32_t width, uint32_t height, uint32_t *buffer) {
//// Initialize SDL if it hasn't been initialized
//if (SDL_WasInit(SDL_INIT_VIDEO) == 0) {
//if (SDL_Init(SDL_INIT_VIDEO) < 0) {
//fprintf(stderr, "SDL could not initialize! SDL Error: %s\n", SDL_GetError());
//return;
//}
//}
//// Create window and renderer if they don't exist
//if (window == NULL) {
//window = SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN);
//if (window == NULL) {
//fprintf(stderr, "Window could not be created! SDL Error: %s\n", SDL_GetError());
//return;
//}
//renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
//if (renderer == NULL) {
//SDL_DestroyWindow(window);
//window = NULL;
//fprintf(stderr, "Renderer could not be created! SDL Error: %s\n", SDL_GetError());
//return;
//}
//}
//// Create or recreate the texture if necessary
//if (texture == NULL) {
//texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);
//if (texture == NULL) {
//fprintf(stderr, "Texture could not be created! SDL Error: %s\n", SDL_GetError());
//return;
//}
//}
//// Update the texture with the new buffer
//if (SDL_UpdateTexture(texture, NULL, buffer, width * sizeof(uint32_t)) < 0) {
//fprintf(stderr, "Texture could not be updated! SDL Error: %s\n", SDL_GetError());
//return;
//}
//// Clear the renderer
//SDL_RenderClear(renderer);
//// Copy the texture to the renderer
//SDL_RenderCopy(renderer, texture, NULL, NULL);
//// Update the screen
//SDL_RenderPresent(renderer);
//// Process events to prevent the OS from thinking the application is unresponsive
//SDL_Event e;
//while (SDL_PollEvent(&e)) {
//if (e.type == SDL_QUIT) {
//close_sdl();
//exit(0);
//}
//}
//}
//// IO: DrawImage
//Port io_put_image(Net* net, Book* book, u32 argc, Port* argv) {
//u32 width = 256;
//u32 height = 256;
//// Create a buffer
//uint32_t *buffer = (uint32_t *)malloc(width * height * sizeof(uint32_t));
//if (buffer == NULL) {
//fprintf(stderr, "Failed to allocate memory for buffer\n");
//return 1;
//}
//// Initialize buffer to a dark blue background
//for (int i = 0; i < width * height; ++i) {
//buffer[i] = 0xFF000030; // Dark blue background
//}
//// Converts a HVM2 tuple-encoded quadtree to a color buffer
//read_img(net, argv[0], width, height, buffer);
//// Render the buffer to the screen
//render(width, height, buffer);
//// Wait some time
//SDL_Delay(2000);
//// Free the buffer
//free(buffer);
//return new_port(ERA, 0);
//}
//#else
//// IO: DrawImage
//Port io_put_image(Net* net, Book* book, u32 argc, Port* argv) {
//printf("DRAWIMAGE: disabled.\n");
//printf("Image rendering is a WIP. For now, to enable it, you must:\n");
//printf("1. Generate a C file, with `hvm gen-c your_file.hvm`.\n");
//printf("2. Manually un-comment the '#define IO_DRAWIMAGE' line on it.\n");
//printf("3. Have SDL installed and compile it with '-lSDL2'.\n");
//return new_port(ERA, 0);
//}
//#endif
// Book Loader
// -----------
bool book_load(Book* book, u32* buf) {
// Reads defs_len
book->defs_len = *buf++;
// Parses each def
for (u32 i = 0; i < book->defs_len; ++i) {
// Reads fid
u32 fid = *buf++;
// Gets def
Def* def = &book->defs_buf[fid];
// Reads name
memcpy(def->name, buf, 256);
buf += 64;
// Reads safe flag
def->safe = *buf++;
// Reads lengths
def->rbag_len = *buf++;
def->node_len = *buf++;
def->vars_len = *buf++;
if (def->rbag_len > DEF_RBAG_LEN) {
fprintf(stderr, "def '%s' has too many redexes: %u\n", def->name, def->rbag_len);
return false;
}
if (def->node_len > DEF_NODE_LEN) {
fprintf(stderr, "def '%s' has too many nodes: %u\n", def->name, def->node_len);
return false;
}
// Reads root
def->root = *buf++;
// Reads rbag_buf
memcpy(def->rbag_buf, buf, 8*def->rbag_len);
buf += def->rbag_len * 2;
// Reads node_buf
memcpy(def->node_buf, buf, 8*def->node_len);
buf += def->node_len * 2;
}
return true;
}
// Debug Printing
// --------------
void put_u32(char* B, u32 val) {
for (int i = 0; i < 8; i++, val >>= 4) {
B[8-i-1] = "0123456789ABCDEF"[val & 0xF];
}
}
Show show_port(Port port) {
// NOTE: this is done like that because sprintf seems not to be working
Show s;
switch (get_tag(port)) {
case VAR: memcpy(s.x, "VAR:", 4); put_u32(s.x+4, get_val(port)); break;
case REF: memcpy(s.x, "REF:", 4); put_u32(s.x+4, get_val(port)); break;
case ERA: memcpy(s.x, "ERA:________", 12); break;
case NUM: memcpy(s.x, "NUM:", 4); put_u32(s.x+4, get_val(port)); break;
case CON: memcpy(s.x, "CON:", 4); put_u32(s.x+4, get_val(port)); break;
case DUP: memcpy(s.x, "DUP:", 4); put_u32(s.x+4, get_val(port)); break;
case OPR: memcpy(s.x, "OPR:", 4); put_u32(s.x+4, get_val(port)); break;
case SWI: memcpy(s.x, "SWI:", 4); put_u32(s.x+4, get_val(port)); break;
}
s.x[12] = '\0';
return s;
}
Show show_rule(Rule rule) {
Show s;
switch (rule) {
case LINK: memcpy(s.x, "LINK", 4); break;
case VOID: memcpy(s.x, "VOID", 4); break;
case ERAS: memcpy(s.x, "ERAS", 4); break;
case ANNI: memcpy(s.x, "ANNI", 4); break;
case COMM: memcpy(s.x, "COMM", 4); break;
case OPER: memcpy(s.x, "OPER", 4); break;
case SWIT: memcpy(s.x, "SWIT", 4); break;
case CALL: memcpy(s.x, "CALL", 4); break;
default : memcpy(s.x, "????", 4); break;
}
s.x[4] = '\0';
return s;
}
//void print_rbag(RBag* rbag) {
//printf("RBAG | FST-TREE | SND-TREE \n");
//printf("---- | ------------ | ------------\n");
//for (u32 i = rbag->lo_ini; i < rbag->lo_end; ++i) {
//Pair redex = rbag->lo_buf[i%RLEN];
//printf("%04X | %s | %s\n", i, show_port(get_fst(redex)).x, show_port(get_snd(redex)).x);
//}
//for (u32 i = 0; i > rbag->hi_end; ++i) {
//Pair redex = rbag->hi_buf[i];
//printf("%04X | %s | %s\n", i, show_port(get_fst(redex)).x, show_port(get_snd(redex)).x);
//}
//printf("==== | ============ | ============\n");
//}
void print_net(Net* net) {
printf("NODE | PORT-1 | PORT-2 \n");
printf("---- | ------------ | ------------\n");
for (u32 i = 0; i < G_NODE_LEN; ++i) {
Pair node = node_load(net, i);
if (node != 0) {
printf("%04X | %s | %s\n", i, show_port(get_fst(node)).x, show_port(get_snd(node)).x);
}
}
printf("==== | ============ |\n");
printf("VARS | VALUE |\n");
printf("---- | ------------ |\n");
for (u32 i = 0; i < G_VARS_LEN; ++i) {
Port var = vars_load(net,i);
if (var != 0) {
printf("%04X | %s |\n", i, show_port(vars_load(net,i)).x);
}
}
printf("==== | ============ |\n");
}
void pretty_print_numb(Numb word) {
switch (get_typ(word)) {
case TY_SYM: {
switch (get_sym(word)) {
// types
case TY_U24: printf("[u24]"); break;
case TY_I24: printf("[i24]"); break;
case TY_F24: printf("[f24]"); break;
// operations
case OP_ADD: printf("[+]"); break;
case OP_SUB: printf("[-]"); break;
case FP_SUB: printf("[:-]"); break;
case OP_MUL: printf("[*]"); break;
case OP_DIV: printf("[/]"); break;
case FP_DIV: printf("[:/]"); break;
case OP_REM: printf("[%%]"); break;
case FP_REM: printf("[:%%]"); break;
case OP_EQ: printf("[=]"); break;
case OP_NEQ: printf("[!]"); break;
case OP_LT: printf("[<]"); break;
case OP_GT: printf("[>]"); break;
case OP_AND: printf("[&]"); break;
case OP_OR: printf("[|]"); break;
case OP_XOR: printf("[^]"); break;
case OP_SHL: printf("[<<]"); break;
case FP_SHL: printf("[:<<]"); break;
case OP_SHR: printf("[>>]"); break;
case FP_SHR: printf("[:>>]"); break;
default: printf("[?]"); break;
}
break;
}
case TY_U24: {
printf("%u", get_u24(word));
break;
}
case TY_I24: {
printf("%+d", get_i24(word));
break;
}
case TY_F24: {
if (isinf(get_f24(word))) {
if (signbit(get_f24(word))) {
printf("-inf");
} else {
printf("+inf");
}
} else if (isnan(get_f24(word))) {
printf("+NaN");
} else {
printf("%.7e", get_f24(word));
}
break;
}
default: {
switch (get_typ(word)) {
case OP_ADD: printf("[+0x%07X]", get_u24(word)); break;
case OP_SUB: printf("[-0x%07X]", get_u24(word)); break;
case FP_SUB: printf("[:-0x%07X]", get_u24(word)); break;
case OP_MUL: printf("[*0x%07X]", get_u24(word)); break;
case OP_DIV: printf("[/0x%07X]", get_u24(word)); break;
case FP_DIV: printf("[:/0x%07X]", get_u24(word)); break;
case OP_REM: printf("[%%0x%07X]", get_u24(word)); break;
case FP_REM: printf("[:%%0x%07X]", get_u24(word)); break;
case OP_EQ: printf("[=0x%07X]", get_u24(word)); break;
case OP_NEQ: printf("[!0x%07X]", get_u24(word)); break;
case OP_LT: printf("[<0x%07X]", get_u24(word)); break;
case OP_GT: printf("[>0x%07X]", get_u24(word)); break;
case OP_AND: printf("[&0x%07X]", get_u24(word)); break;
case OP_OR: printf("[|0x%07X]", get_u24(word)); break;
case OP_XOR: printf("[^0x%07X]", get_u24(word)); break;
case OP_SHL: printf("[<<0x%07X]", get_u24(word)); break;
case FP_SHL: printf("[:<<0x%07X]", get_u24(word)); break;
case OP_SHR: printf("[>>0x%07X]", get_u24(word)); break;
case FP_SHR: printf("[:>>0x%07X]", get_u24(word)); break;
default: printf("[?0x%07X]", get_u24(word)); break;
}
break;
}
}
}
void pretty_print_port(Net* net, Book* book, Port port) {
Port stack[4096];
stack[0] = port;
u32 len = 1;
u32 num = 0;
while (len > 0) {
Port cur = stack[--len];
switch (get_tag(cur)) {
case CON: {
Pair node = node_load(net,get_val(cur));
Port p2 = get_snd(node);
Port p1 = get_fst(node);
printf("(");
stack[len++] = new_port(ERA, (u32)(')'));
stack[len++] = p2;
stack[len++] = new_port(ERA, (u32)(' '));
stack[len++] = p1;
break;
}
case ERA: {
if (get_val(cur) != 0) {
printf("%c", (char)get_val(cur));
} else {
printf("*");
}
break;
}
case VAR: {
Port got = vars_load(net, get_val(cur));
if (got != NONE) {
stack[len++] = got;
} else {
printf("x%x", get_val(cur));
}
break;
}
case NUM: {
pretty_print_numb(get_val(cur));
break;
}
case DUP: {
Pair node = node_load(net,get_val(cur));
Port p2 = get_snd(node);
Port p1 = get_fst(node);
printf("{");
stack[len++] = new_port(ERA, (u32)('}'));
stack[len++] = p2;
stack[len++] = new_port(ERA, (u32)(' '));
stack[len++] = p1;
break;
}
case OPR: {
Pair node = node_load(net,get_val(cur));
Port p2 = get_snd(node);
Port p1 = get_fst(node);
printf("$(");
stack[len++] = new_port(ERA, (u32)(')'));
stack[len++] = p2;
stack[len++] = new_port(ERA, (u32)(' '));
stack[len++] = p1;
break;
}
case SWI: {
Pair node = node_load(net,get_val(cur));
Port p2 = get_snd(node);
Port p1 = get_fst(node);
printf("?(");
stack[len++] = new_port(ERA, (u32)(')'));
stack[len++] = p2;
stack[len++] = new_port(ERA, (u32)(' '));
stack[len++] = p1;
break;
}
case REF: {
u32 fid = get_val(cur) & 0xFFFFFFF;
Def* def = &book->defs_buf[fid];
printf("@%s", def->name);
break;
}
}
}
}
//void pretty_print_rbag(Net* net, RBag* rbag) {
//for (u32 i = rbag->lo_ini; i < rbag->lo_end; ++i) {
//Pair redex = rbag->lo_buf[i];
//if (redex != 0) {
//pretty_print_port(net, get_fst(redex));
//printf(" ~ ");
//pretty_print_port(net, get_snd(redex));
//printf("\n");
//}
//}
//for (u32 i = 0; i > rbag->hi_end; ++i) {
//Pair redex = rbag->hi_buf[i];
//if (redex != 0) {
//pretty_print_port(net, get_fst(redex));
//printf(" ~ ");
//pretty_print_port(net, get_snd(redex));
//printf("\n");
//}
//}
//}
// Demos
// -----
// stress_test 2^10 x 65536
//static const u8 BOOK_BUF[] = {6, 0, 0, 0, 0, 0, 0, 0, 109, 97, 105, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 4, 0, 0, 0, 11, 10, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 102, 117, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 25, 0, 0, 0, 2, 0, 0, 0, 102, 117, 110, 95, 95, 67, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 4, 0, 0, 0, 11, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 0, 102, 117, 110, 95, 95, 67, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 9, 0, 0, 128, 20, 0, 0, 0, 9, 0, 0, 128, 44, 0, 0, 0, 13, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 3, 4, 0, 0, 38, 0, 0, 0, 24, 0, 0, 0, 16, 0, 0, 0, 8, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 108, 111, 111, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 41, 0, 0, 0, 5, 0, 0, 0, 108, 111, 111, 112, 95, 95, 67, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0};
// stress_test 2^18 x 65536
//static const u8 BOOK_BUF[] = {6, 0, 0, 0, 0, 0, 0, 0, 109, 97, 105, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 4, 0, 0, 0, 11, 18, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 102, 117, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 25, 0, 0, 0, 2, 0, 0, 0, 102, 117, 110, 95, 95, 67, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 4, 0, 0, 0, 11, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 0, 102, 117, 110, 95, 95, 67, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 9, 0, 0, 128, 20, 0, 0, 0, 9, 0, 0, 128, 44, 0, 0, 0, 13, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 3, 4, 0, 0, 38, 0, 0, 0, 24, 0, 0, 0, 16, 0, 0, 0, 8, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 108, 111, 111, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 41, 0, 0, 0, 5, 0, 0, 0, 108, 111, 111, 112, 95, 95, 67, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0};
// bitonic_sort 2^20
//static const u8 BOOK_BUF[] = {19, 0, 0, 0, 0, 0, 0, 0, 109, 97, 105, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 4, 0, 0, 0, 11, 18, 0, 0, 12, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 100, 111, 119, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 60, 0, 0, 0, 20, 0, 0, 0, 44, 0, 0, 0, 28, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 52, 0, 0, 0, 16, 0, 0, 0, 24, 0, 0, 0, 16, 0, 0, 0, 68, 0, 0, 0, 8, 0, 0, 0, 24, 0, 0, 0, 2, 0, 0, 0, 100, 111, 119, 110, 95, 95, 67, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 13, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 25, 0, 0, 128, 60, 0, 0, 0, 25, 0, 0, 128, 84, 0, 0, 0, 13, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 28, 0, 0, 0, 36, 0, 0, 0, 16, 0, 0, 0, 24, 0, 0, 0, 45, 0, 0, 0, 52, 0, 0, 0, 32, 0, 0, 0, 40, 0, 0, 0, 48, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 32, 0, 0, 0, 76, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 8, 0, 0, 0, 92, 0, 0, 0, 40, 0, 0, 0, 100, 0, 0, 0, 24, 0, 0, 0, 56, 0, 0, 0, 3, 0, 0, 0, 102, 108, 111, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 60, 0, 0, 0, 20, 0, 0, 0, 44, 0, 0, 0, 28, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 52, 0, 0, 0, 16, 0, 0, 0, 24, 0, 0, 0, 16, 0, 0, 0, 68, 0, 0, 0, 8, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 102, 108, 111, 119, 95, 95, 67, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 14, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 9, 0, 0, 0, 60, 0, 0, 0, 129, 0, 0, 0, 84, 0, 0, 0, 13, 0, 0, 0, 28, 0, 0, 0, 22, 0, 0, 0, 8, 0, 0, 0, 35, 1, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 44, 0, 0, 0, 16, 0, 0, 0, 24, 0, 0, 0, 53, 0, 0, 0, 48, 0, 0, 0, 32, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 32, 0, 0, 0, 76, 0, 0, 0, 56, 0, 0, 0, 48, 0, 0, 0, 8, 0, 0, 0, 92, 0, 0, 0, 40, 0, 0, 0, 100, 0, 0, 0, 16, 0, 0, 0, 108, 0, 0, 0, 24, 0, 0, 0, 56, 0, 0, 0, 5, 0, 0, 0, 103, 101, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 8, 0, 0, 0, 20, 0, 0, 0, 8, 0, 0, 0, 28, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 103, 101, 110, 95, 95, 67, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 12, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 41, 0, 0, 128, 68, 0, 0, 0, 41, 0, 0, 128, 84, 0, 0, 0, 13, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 29, 0, 0, 0, 60, 0, 0, 0, 38, 0, 0, 0, 54, 0, 0, 0, 59, 2, 0, 0, 46, 0, 0, 0, 35, 1, 0, 0, 16, 0, 0, 0, 59, 2, 0, 0, 24, 0, 0, 0, 32, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 16, 0, 0, 0, 32, 0, 0, 0, 8, 0, 0, 0, 92, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 7, 0, 0, 0, 109, 97, 105, 110, 95, 95, 67, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 4, 0, 0, 0, 11, 18, 0, 0, 12, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 109, 97, 105, 110, 95, 95, 67, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 4, 0, 0, 0, 11, 18, 0, 0, 12, 0, 0, 0, 11, 0, 0, 0, 20, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 115, 111, 114, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 60, 0, 0, 0, 20, 0, 0, 0, 44, 0, 0, 0, 28, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 52, 0, 0, 0, 16, 0, 0, 0, 24, 0, 0, 0, 16, 0, 0, 0, 68, 0, 0, 0, 8, 0, 0, 0, 24, 0, 0, 0, 10, 0, 0, 0, 115, 111, 114, 116, 95, 95, 67, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 17, 0, 0, 0, 9, 0, 0, 0, 4, 0, 0, 0, 25, 0, 0, 0, 60, 0, 0, 0, 73, 0, 0, 128, 92, 0, 0, 0, 73, 0, 0, 128, 116, 0, 0, 0, 13, 0, 0, 0, 36, 0, 0, 0, 22, 0, 0, 0, 29, 0, 0, 0, 35, 1, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 16, 0, 0, 0, 44, 0, 0, 0, 52, 0, 0, 0, 24, 0, 0, 0, 32, 0, 0, 0, 40, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 40, 0, 0, 0, 76, 0, 0, 0, 84, 0, 0, 0, 48, 0, 0, 0, 56, 0, 0, 0, 64, 0, 0, 0, 8, 0, 0, 0, 100, 0, 0, 0, 11, 0, 0, 0, 108, 0, 0, 0, 24, 0, 0, 0, 56, 0, 0, 0, 16, 0, 0, 0, 124, 0, 0, 0, 11, 1, 0, 0, 132, 0, 0, 0, 32, 0, 0, 0, 64, 0, 0, 0, 11, 0, 0, 0, 115, 117, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 8, 0, 0, 0, 20, 0, 0, 0, 8, 0, 0, 0, 28, 0, 0, 0, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 115, 117, 109, 95, 95, 67, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 89, 0, 0, 128, 36, 0, 0, 0, 89, 0, 0, 128, 68, 0, 0, 0, 13, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 16, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 16, 0, 0, 0, 54, 0, 0, 0, 3, 4, 0, 0, 62, 0, 0, 0, 40, 0, 0, 0, 32, 0, 0, 0, 8, 0, 0, 0, 76, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 13, 0, 0, 0, 115, 119, 97, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 44, 0, 0, 0, 20, 0, 0, 0, 28, 0, 0, 0, 113, 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 8, 0, 0, 0, 16, 0, 0, 0, 8, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 14, 0, 0, 0, 115, 119, 97, 112, 95, 95, 67, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 8, 0, 0, 0, 20, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 115, 119, 97, 112, 95, 95, 67, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 8, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 16, 0, 0, 0, 119, 97, 114, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 52, 0, 0, 0, 20, 0, 0, 0, 28, 0, 0, 0, 137, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 8, 0, 0, 0, 44, 0, 0, 0, 16, 0, 0, 0, 24, 0, 0, 0, 16, 0, 0, 0, 60, 0, 0, 0, 8, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 17, 0, 0, 0, 119, 97, 114, 112, 95, 95, 67, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 105, 0, 0, 0, 76, 0, 0, 0, 13, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 29, 0, 0, 0, 52, 0, 0, 0, 38, 0, 0, 0, 24, 0, 0, 0, 3, 15, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 62, 0, 0, 0, 40, 0, 0, 0, 3, 18, 0, 0, 70, 0, 0, 0, 16, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 84, 0, 0, 0, 24, 0, 0, 0, 92, 0, 0, 0, 8, 0, 0, 0, 40, 0, 0, 0, 18, 0, 0, 0, 119, 97, 114, 112, 95, 95, 67, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 21, 0, 0, 0, 12, 0, 0, 0, 4, 0, 0, 0, 129, 0, 0, 128, 92, 0, 0, 0, 129, 0, 0, 128, 132, 0, 0, 0, 13, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 28, 0, 0, 0, 36, 0, 0, 0, 16, 0, 0, 0, 24, 0, 0, 0, 44, 0, 0, 0, 52, 0, 0, 0, 32, 0, 0, 0, 40, 0, 0, 0, 61, 0, 0, 0, 68, 0, 0, 0, 48, 0, 0, 0, 56, 0, 0, 0, 76, 0, 0, 0, 84, 0, 0, 0, 64, 0, 0, 0, 72, 0, 0, 0, 80, 0, 0, 0, 88, 0, 0, 0, 8, 0, 0, 0, 100, 0, 0, 0, 56, 0, 0, 0, 108, 0, 0, 0, 40, 0, 0, 0, 116, 0, 0, 0, 24, 0, 0, 0, 124, 0, 0, 0, 72, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 48, 0, 0, 0, 148, 0, 0, 0, 32, 0, 0, 0, 156, 0, 0, 0, 16, 0, 0, 0, 164, 0, 0, 0, 64, 0, 0, 0, 80, 0, 0, 0};
//COMPILED_BOOK_BUF//
#ifdef IO
void do_run_io(Net* net, Book* book, Port port);
#endif
// Main
// ----
void hvm_c(u32* book_buffer) {
// Creates static TMs
alloc_static_tms();
// Loads the Book
Book* book = NULL;
if (book_buffer) {
book = (Book*)malloc(sizeof(Book));
if (!book_load(book, book_buffer)) {
fprintf(stderr, "failed to load book\n");
return;
}
}
// GMem
Net *net = net_new();
// Starts the timer
u64 start = time64();
// Creates an initial redex that calls main
boot_redex(net, new_pair(new_port(REF, 0), ROOT));
#ifdef IO
do_run_io(net, book, ROOT);
#else
normalize(net, book);
#endif
// Prints the result
printf("Result: ");
pretty_print_port(net, book, enter(net, ROOT));
printf("\n");
// Stops the timer
double duration = (time64() - start) / 1000000000.0; // seconds
// Prints interactions and time
u64 itrs = atomic_load(&net->itrs);
printf("- ITRS: %" PRIu64 "\n", itrs);
printf("- TIME: %.2fs\n", duration);
printf("- MIPS: %.2f\n", (double)itrs / duration / 1000000.0);
// Frees everything
free_static_tms();
free(net);
free(book);
}
#ifdef WITH_MAIN
int main() {
hvm_c((u32*)BOOK_BUF);
return 0;
}
#endif