decompiled_code:
unsigned int *__fastcall fst_compose(__int64 a1, __int64 a2, unsigned int *a3)
{
__int64 v4; // rbp
__int64 v5; // rbx
__int64 v6; // r15
unsigned int v7; // eax
__int64 v8; // r15
unsigned int v9; // eax
__int64 v11; // [rsp+0h] [rbp-B8h]
unsigned int v12; // [rsp+8h] [rbp-B0h]
__int64 v13; // [rsp+8h] [rbp-B0h]
__int64 v14; // [rsp+10h] [rbp-A8h]
unsigned int v15; // [rsp+10h] [rbp-A8h]
unsigned int v16; // [rsp+1Ch] [rbp-9Ch]
unsigned int v17; // [rsp+28h] [rbp-90h] BYREF
unsigned int v18; // [rsp+2Ch] [rbp-8Ch] BYREF
int v19[10]; // [rsp+30h] [rbp-88h] BYREF
int v20; // [rsp+58h] [rbp-60h] BYREF
unsigned int v21; // [rsp+5Ch] [rbp-5Ch]
char v22[8]; // [rsp+60h] [rbp-58h] BYREF
void (__fastcall *v23)(float, float); // [rsp+68h] [rbp-50h]
float v24; // [rsp+74h] [rbp-44h]

sr_get(v22, *(unsigned __int8 *)(a1 + 12));
v11 = queue_create(8LL);
v4 = queue_create(32LL);
v5 = hash_create(hash_pair, cmp_pair, 8LL, 4LL, 1000LL);
v20 = *(_DWORD *)a1;
v21 = *(_DWORD *)a2;
queue_enque(v11, &v20);
while ( queue_deque(v11, &v20) )
{
v6 = *(_QWORD *)(a1 + 16);
v12 = v20;
v14 = *(_QWORD *)(a2 + 16);
v16 = v21;
if ( !hash_get(v5, &v20, &v18) )
{
v7 = fst_add_state(a3);
v18 = v7;
if ( *(_DWORD *)(v6 + 24LL * v12 + 12) && *(_DWORD *)(v14 + 24LL * v16 + 12) )
fst_set_final(a3, v7, v24);
if ( v20 == *(_DWORD *)a1 && v21 == *(_DWORD *)a2 )
*a3 = v18;
hash_add(v5, &v20, &v18);
}
match_arcs(a1, a2, (unsigned int *)&v20, (__int64)v22, v4);
while ( queue_deque(v4, v19) )
{
v20 = v19[0];
v21 = v19[4];
if ( !hash_get(v5, &v20, &v17) )
{
v8 = *(_QWORD *)(a1 + 16) + 24LL * (unsigned int)v20;
v13 = *(_QWORD *)(a2 + 16);
v15 = v21;
v9 = fst_add_state(a3);
v17 = v9;
if ( *(_DWORD *)(v8 + 12) )
{
if ( *(_DWORD *)(v13 + 24LL * v15 + 12) )
fst_set_final(a3, v9, v24);
}
queue_enque(v11, &v20);
hash_add(v5, &v20, &v17);
}
v23(*(float *)&v19[1], *(float *)&v19[5]);
fst_add_arc(a3, v18, v17, (unsigned int)v19[2], (unsigned int)v19[7]);
}
}
queue_remove(v11);
queue_remove(v4);
hash_remove(v5);
return a3;
}

canonical_decompiled_code:
unsigned int *__fastcall func3(__int64 a1, __int64 a2, unsigned int *a3)
{
__int64 v4; // rbp
__int64 v5; // rbx
__int64 v6; // r15
unsigned int v7; // eax
__int64 v8; // r15
unsigned int v9; // eax
__int64 v11; // [rsp+0h] [rbp-B8h]
unsigned int v12; // [rsp+8h] [rbp-B0h]
__int64 v13; // [rsp+8h] [rbp-B0h]
__int64 v14; // [rsp+10h] [rbp-A8h]
unsigned int v15; // [rsp+10h] [rbp-A8h]
unsigned int v16; // [rsp+1Ch] [rbp-9Ch]
unsigned int v17; // [rsp+28h] [rbp-90h] BYREF
unsigned int v18; // [rsp+2Ch] [rbp-8Ch] BYREF
int v19[10]; // [rsp+30h] [rbp-88h] BYREF
int v20; // [rsp+58h] [rbp-60h] BYREF
unsigned int v21; // [rsp+5Ch] [rbp-5Ch]
char v22[8]; // [rsp+60h] [rbp-58h] BYREF
void (__fastcall *v23)(float, float); // [rsp+68h] [rbp-50h]
float v24; // [rsp+74h] [rbp-44h]

sr_get(v22, *(unsigned __int8 *)(a1 + 12));
v11 = queue_create(8LL);
v4 = queue_create(32LL);
v5 = hash_create(hash_pair, cmp_pair, 8LL, 4LL, 1000LL);
v20 = *(_DWORD *)a1;
v21 = *(_DWORD *)a2;
queue_enque(v11, &v20);
while ( queue_deque(v11, &v20) )
{
v6 = *(_QWORD *)(a1 + 16);
v12 = v20;
v14 = *(_QWORD *)(a2 + 16);
v16 = v21;
if ( !hash_get(v5, &v20, &v18) )
{
v7 = fst_add_state(a3);
v18 = v7;
if ( *(_DWORD *)(v6 + 24LL * v12 + 12) && *(_DWORD *)(v14 + 24LL * v16 + 12) )
fst_set_final(a3, v7, v24);
if ( v20 == *(_DWORD *)a1 && v21 == *(_DWORD *)a2 )
*a3 = v18;
hash_add(v5, &v20, &v18);
}
func2(a1, a2, (unsigned int *)&v20, (__int64)v22, v4);
while ( queue_deque(v4, v19) )
{
v20 = v19[0];
v21 = v19[4];
if ( !hash_get(v5, &v20, &v17) )
{
v8 = *(_QWORD *)(a1 + 16) + 24LL * (unsigned int)v20;
v13 = *(_QWORD *)(a2 + 16);
v15 = v21;
v9 = fst_add_state(a3);
v17 = v9;
if ( *(_DWORD *)(v8 + 12) )
{
if ( *(_DWORD *)(v13 + 24LL * v15 + 12) )
fst_set_final(a3, v9, v24);
}
queue_enque(v11, &v20);
hash_add(v5, &v20, &v17);
}
v23(*(float *)&v19[1], *(float *)&v19[5]);
fst_add_arc(a3, v18, v17, (unsigned int)v19[2], (unsigned int)v19[7]);
}
}
queue_remove(v11);
queue_remove(v4);
hash_remove(v5);
return a3;
}

original_code:
struct _fst * fst_compose(
    const struct _fst * fst_a,
    const struct _fst * fst_b,
    struct _fst * fst_c )
{
    struct _sr sr = sr_get(fst_a->sr_type);
    struct _queue * q = queue_create(sizeof(struct _spair));
    struct _queue * mq = queue_create(sizeof(struct _arc_pair));
    struct _hash * marked = hash_create(
                    hash_pair,
                    cmp_pair,
                    sizeof(struct _spair),
                    sizeof(uint32_t),
                    1000 );
    struct _spair pair;
    struct _arc_pair mi;
    uint32_t sc, dst_sc;
    struct _state * state_a, * state_b;
    struct _state * dst_state_a, * dst_state_b;
    struct _arc * arc_a, * arc_b;
    pair.a = fst_a->start;
    pair.b = fst_b->start;
    queue_enque(q, &pair);
    while( (queue_deque(q, &pair)) != ((void *)0) ) {
        state_a = &fst_a->states[pair.a];
        state_b = &fst_b->states[pair.b];
        if (hash_get(marked, &pair, &sc) == ((void *)0)) {
            sc = fst_add_state(fst_c);
            if (state_a->final && state_b->final)
                fst_set_final(fst_c, sc, sr.one);
            if (pair.a == fst_a->start && pair.b == fst_b->start)
                fst_c->start = sc;
            hash_add(marked, &pair, &sc);
        }
        match_arcs( fst_a, fst_b,
                        &pair,
                        &sr,
                        mq );
        while ( queue_deque(mq, &mi) != ((void *)0) ) {
            arc_a = &mi.a;
            arc_b = &mi.b;
            pair.a = arc_a->state;
            pair.b = arc_b->state;
            if (hash_get(marked, &pair, &dst_sc) == ((void *)0)) {
                dst_state_a = &fst_a->states[pair.a];
                dst_state_b = &fst_b->states[pair.b];
                dst_sc = fst_add_state(fst_c);
                if (dst_state_a->final && dst_state_b->final) {
                    fst_set_final(fst_c, dst_sc, sr.one);
                }
                queue_enque(q, &pair);
                hash_add(marked, &pair, &dst_sc);
            }
            fst_add_arc(
                fst_c,
                sc,
                dst_sc,
                arc_a->ilabel,
                arc_b->olabel,
                sr.prod(arc_a->weight, arc_b->weight));
        }
    }
    queue_remove(q);
    queue_remove(mq);
    hash_remove(marked);
    return fst_c;
}

canonical_original_code:
struct _fst *fst_compose(struct _fst *fst_a, struct _fst *fst_b, struct _fst *fst_c)
{
    struct _sr sr = sr_get(fst_a->sr_type);
    struct _queue *q = queue_create(sizeof(struct _spair));
    struct _queue *mq = queue_create(sizeof(struct _arc_pair));
    struct _hash *marked = hash_create(
                    hash_pair,
                    cmp_pair,
                    sizeof(struct _spair),
                    sizeof(uint32_t),
                    1000 );
    struct _spair pair;
    struct _arc_pair mi;
    unsigned int sc; unsigned int dst_sc;
    struct _state *state_a; struct _state *state_b;
    struct _state *dst_state_a; struct _state *dst_state_b;
    struct _arc *arc_a; struct _arc *arc_b;
    pair.a = fst_a->start;
    pair.b = fst_b->start;
    queue_enque(q, &pair);
    while( (queue_deque(q, &pair)) != ((void *)0) ) {
        state_a = &fst_a->states[pair.a];
        state_b = &fst_b->states[pair.b];
        if (hash_get(marked, &pair, &sc) == ((void *)0)) {
            sc = fst_add_state(fst_c);
            if (state_a->final && state_b->final)
                fst_set_final(fst_c, sc, sr.one);
            if (pair.a == fst_a->start && pair.b == fst_b->start)
                fst_c->start = sc;
            hash_add(marked, &pair, &sc);
        }
        match_arcs( fst_a, fst_b,
                        &pair,
                        &sr,
                        mq );
        while ( queue_deque(mq, &mi) != ((void *)0) ) {
            arc_a = &mi.a;
            arc_b = &mi.b;
            pair.a = arc_a->state;
            pair.b = arc_b->state;
            if (hash_get(marked, &pair, &dst_sc) == ((void *)0)) {
                dst_state_a = &fst_a->states[pair.a];
                dst_state_b = &fst_b->states[pair.b];
                dst_sc = fst_add_state(fst_c);
                if (dst_state_a->final && dst_state_b->final) {
                    fst_set_final(fst_c, dst_sc, sr.one);
                }
                queue_enque(q, &pair);
                hash_add(marked, &pair, &dst_sc);
            }
            fst_add_arc(
                fst_c,
                sc,
                dst_sc,
                arc_a->ilabel,
                arc_b->olabel,
                sr.prod(arc_a->weight, arc_b->weight));
        }
    }
    queue_remove(q);
    queue_remove(mq);
    hash_remove(marked);
    return fst_c;
}

variable_types: struct _sr { float (*sum)(float a, float b); float (*prod)(float a, float b); float zero; float one; }

variable_types: struct _hash { struct _bucket { struct _bitem { void *key; void *value; struct _bitem *next; } *head; struct _bitem *tail; } *buckets; unsigned long item_size; unsigned long key_size; unsigned long size; unsigned long n_items; unsigned long (*hash_f)(void *key); int (*cmp_f)(void *key_a, void *key_b); } *

variable_types: struct _spair { unsigned int a; unsigned int b; }

variable_types: struct _arc_pair { struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } a; struct _arc b; }

variable_types:
sc
unsigned int

return_type: struct _fst { unsigned int start; unsigned int n_states; unsigned int n_max; unsigned char sr_type; unsigned char flags; struct _state { unsigned int n_arcs; unsigned int n_max; float weight; int final; struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } *arcs; } *states; } *

user_defined_types: struct _arc_pair { struct _arc a; struct _arc b; }

user_defined_types: struct _qnode { struct _qnode *next; char item[1]; }


repo: lightcaster/fslib

original_code:
void match_unsorted(
                struct _arc * a,
                struct _arc * b,
                uint32_t M,
                uint32_t N,
                struct _queue * q)
{
    struct _match_item mi;
    for (uint32_t i = 0; i < M; ++i)
        for (uint32_t j = 0; j < N; ++j)
            if ( a[i].olabel == b[j].ilabel && _match(a, b, i, j)) {
                mi.a = a[i];
                mi.b = b[j];
                queue_enque(q, &mi);
            }
}

canonical_original_code:
void match_unsorted(struct _arc *a, struct _arc *b, unsigned int M, unsigned int N, struct _queue *q)
{
    struct _match_item mi;
    for (unsigned int i = 0; i < M; ++i)
        for (unsigned int j = 0; j < N; ++j)
            if ( a[i].olabel == b[j].ilabel && _match(a, b, i, j)) {
                mi.a = a[i];
                mi.b = b[j];
                queue_enque(q, &mi);
            }
}

variable_types: struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } *

variable_types:
b
struct _arc *

variable_types:
M
unsigned int

variable_types:
N
unsigned int

variable_types: struct _queue { struct _qnode { struct _qnode *next; char item[1]; } *head; struct _qnode *tail; unsigned long item_size; unsigned long n_items; } *

variable_types: struct _match_item { struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } a; struct _arc b; }

variable_types:
i
unsigned int

variable_types:
j
unsigned int

return_type: void

user_defined_types: struct _match_item { struct _arc a; struct _arc b; }

user_defined_types: struct _queue { struct _qnode *head; struct _qnode *tail; unsigned long item_size; unsigned long n_items; }


original_code:
void match_half_sorted(
                struct _arc * a,
                struct _arc * b,
                uint32_t M,
                uint32_t N,
                struct _queue * q)
{
    uint32_t l, h, ll, hh;
    uint32_t i,m;
    struct _match_item mi;
    for (i=0; i < M; ++i) {
        l = 0;
        h = N-1;
        while ( l <= h ) {
            m = (l + h) >> 1;
            if (a[i].olabel > b[m].ilabel) l = m + 1;
            else
                if (a[i].olabel < b[m].ilabel) {
                    if (m == 0) break;
                    h = m - 1;
                }
                else {
                    ll = hh = m;
                    while ((ll > l) && (a[i].olabel == b[ll-1].ilabel)) --ll;
                    while ((hh < h) && (a[i].olabel == b[hh+1].ilabel)) ++hh;
                    while (ll <= hh ) {
                        mi.a = a[i];
                        mi.b = b[ll];
                        if (_match(a, b, i, ll))
                            queue_enque(q, &mi);
                        ++ll;
                    }
                    break;
                }
        }
    }
}

canonical_original_code:
void match_half_sorted(struct _arc *a, struct _arc *b, unsigned int M, unsigned int N, struct _queue *q)
{
    unsigned int l; unsigned int h; unsigned int ll; unsigned int hh;
    unsigned int i; unsigned int m;
    struct _match_item mi;
    for (i=0; i < M; ++i) {
        l = 0;
        h = N-1;
        while ( l <= h ) {
            m = (l + h) >> 1;
            if (a[i].olabel > b[m].ilabel) l = m + 1;
            else
                if (a[i].olabel < b[m].ilabel) {
                    if (m == 0) break;
                    h = m - 1;
                }
                else {
                    ll = hh = m;
                    while ((ll > l) && (a[i].olabel == b[ll-1].ilabel)) --ll;
                    while ((hh < h) && (a[i].olabel == b[hh+1].ilabel)) ++hh;
                    while (ll <= hh ) {
                        mi.a = a[i];
                        mi.b = b[ll];
                        if (_match(a, b, i, ll))
                            queue_enque(q, &mi);
                        ++ll;
                    }
                    break;
                }
        }
    }
}

variable_types:
l
unsigned int

variable_types:
h
unsigned int

variable_types:
ll
unsigned int

variable_types:
hh
unsigned int

variable_types:
m
unsigned int

user_defined_types: struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; }


original_code:
void match_half_sorted_rev(
                struct _arc * a,
                struct _arc * b,
                uint32_t M,
                uint32_t N,
                struct _queue * q)
{
    uint32_t l, h, ll, hh;
    uint32_t i,m;
    struct _match_item mi;
    for (i=0; i < N; ++i) {
        l = 0;
        h = M-1;
        while ( l <= h ) {
            m = (l + h) >> 1;
            if (b[i].ilabel > a[m].olabel) l = m + 1;
            else
                if (b[i].ilabel < a[m].olabel) {
                    if (m == 0) break;
                    h = m - 1;
                }
                else {
                    ll = hh = m;
                    while ((ll > l) && (b[i].ilabel == a[ll-1].olabel)) --ll;
                    while ((hh < h) && (b[i].ilabel == a[hh+1].olabel)) ++hh;
                    while (ll <= hh ) {
                        mi.a = a[ll];
                        mi.b = b[i];
                        if (_match(a, b, ll, i))
                            queue_enque(q, &mi);
                        ++ll;
                    }
                    break;
                }
        }
    }
}

canonical_original_code:
void match_half_sorted_rev(struct _arc *a, struct _arc *b, unsigned int M, unsigned int N, struct _queue *q)
{
    unsigned int l; unsigned int h; unsigned int ll; unsigned int hh;
    unsigned int i; unsigned int m;
    struct _match_item mi;
    for (i=0; i < N; ++i) {
        l = 0;
        h = M-1;
        while ( l <= h ) {
            m = (l + h) >> 1;
            if (b[i].ilabel > a[m].olabel) l = m + 1;
            else
                if (b[i].ilabel < a[m].olabel) {
                    if (m == 0) break;
                    h = m - 1;
                }
                else {
                    ll = hh = m;
                    while ((ll > l) && (b[i].ilabel == a[ll-1].olabel)) --ll;
                    while ((hh < h) && (b[i].ilabel == a[hh+1].olabel)) ++hh;
                    while (ll <= hh ) {
                        mi.a = a[ll];
                        mi.b = b[i];
                        if (_match(a, b, ll, i))
                            queue_enque(q, &mi);
                        ++ll;
                    }
                    break;
                }
        }
    }
}


original_code:
void match_full_sorted(
                struct _arc * a,
                struct _arc * b,
                uint32_t M,
                uint32_t N,
                struct _queue * q)
{
    uint32_t i = 0;
    uint32_t j = 0;
    uint32_t t;
    struct _match_item mi;
    while (i < M && j < N) {
        if ( a[i].olabel < b[j].ilabel ) ++i;
        else
            if ( a[i].olabel > b[j].ilabel ) ++j;
            else {
                for (t=j; a[i].olabel == b[t].ilabel; ++t ) {
                    mi.a = a[i];
                    mi.b = b[t];
                    if (_match(a, b, i, t))
                        queue_enque(q, &mi);
                }
                ++i;
            }
    }
}

canonical_original_code:
void match_full_sorted(struct _arc *a, struct _arc *b, unsigned int M, unsigned int N, struct _queue *q)
{
    unsigned int i = 0;
    unsigned int j = 0;
    unsigned int t;
    struct _match_item mi;
    while (i < M && j < N) {
        if ( a[i].olabel < b[j].ilabel ) ++i;
        else
            if ( a[i].olabel > b[j].ilabel ) ++j;
            else {
                for (t=j; a[i].olabel == b[t].ilabel; ++t ) {
                    mi.a = a[i];
                    mi.b = b[t];
                    if (_match(a, b, i, t))
                        queue_enque(q, &mi);
                }
                ++i;
            }
    }
}

variable_types:
t
unsigned int


decompiled_code:
_BYTE *fst_create()
{
_BYTE *result; // rax

result = malloc(0x18uLL);
result[12] = 0;
*((_DWORD *)result + 1) = 0;
*((_DWORD *)result + 2) = 0;
*(_DWORD *)result = 0;
result[13] = 0;
*((_QWORD *)result + 2) = 0LL;
return result;
}

canonical_decompiled_code:
_BYTE *func0()
{
_BYTE *result; // rax

result = malloc(0x18uLL);
result[12] = 0;
*((_DWORD *)result + 1) = 0;
*((_DWORD *)result + 2) = 0;
*(_DWORD *)result = 0;
result[13] = 0;
*((_QWORD *)result + 2) = 0LL;
return result;
}

original_code:
struct _fst * fst_create() {
    struct _fst * fst;
    fst = malloc(sizeof(struct _fst));
    fst->sr_type = 0;
    fst->n_states = 0;
    fst->n_max = 0;
    fst->start = 0;
    fst->flags = 0;
    fst->states = ((void *)0);
    return fst;
}

canonical_original_code:
struct _fst *fst_create() {
    struct _fst *fst;
    fst = malloc(sizeof(struct _fst));
    fst->sr_type = 0;
    fst->n_states = 0;
    fst->n_max = 0;
    fst->start = 0;
    fst->flags = 0;
    fst->states = ((void *)0);
    return fst;
}

variable_types: struct _fst { unsigned int start; unsigned int n_states; unsigned int n_max; unsigned char sr_type; unsigned char flags; struct _state { unsigned int n_arcs; unsigned int n_max; float weight; int final; struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } *arcs; } *states; } *

user_defined_types: struct _fst { unsigned int start; unsigned int n_states; unsigned int n_max; unsigned char sr_type; unsigned char flags; struct _state *states; }

user_defined_types: struct _state { unsigned int n_arcs; unsigned int n_max; float weight; int final; struct _arc *arcs; }


original_code:
uint32_t fst_add_state(struct _fst * fst) {
    struct _state * state;
    ++fst->n_states;
    if (fst->n_states > fst->n_max) {
        fst->n_max = fst->n_states * 2;
        fst->states = realloc(fst->states,
            sizeof(struct _state) * fst->n_max);
    }
    state = &fst->states[fst->n_states - 1];
    state->n_arcs = 0;
    state->n_max = 0;
    state->final = 0;
    state->weight = 0;
    state->arcs = ((void *)0);
    return fst->n_states - 1;
}

canonical_original_code:
unsigned int fst_add_state(struct _fst *fst) {
    struct _state *state;
    ++fst->n_states;
    if (fst->n_states > fst->n_max) {
        fst->n_max = fst->n_states * 2;
        fst->states = realloc(fst->states,
            sizeof(struct _state) * fst->n_max);
    }
    state = &fst->states[fst->n_states - 1];
    state->n_arcs = 0;
    state->n_max = 0;
    state->final = 0;
    state->weight = 0;
    state->arcs = ((void *)0);
    return fst->n_states - 1;
}

variable_types: struct _state { unsigned int n_arcs; unsigned int n_max; float weight; int final; struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } *arcs; } *

return_type: unsigned int


original_code:
uint32_t fst_add_arc(
            struct _fst * fst,
            uint32_t src,
            uint32_t dst,
            uint32_t il,
            uint32_t ol,
            float weight)
{
    struct _arc * arc;
    struct _state * state = &fst->states[src];
    ++state->n_arcs;
    if (state->n_arcs > state->n_max) {
        state->n_max = state->n_arcs * 2;
        state->arcs = realloc(state->arcs,
            sizeof(struct _arc) * state->n_max);
    }
    arc = &state->arcs[state->n_arcs - 1];
    arc->state = dst;
    arc->ilabel = il;
    arc->olabel = ol;
    arc->weight = weight;
    return state->n_arcs - 1;
}

canonical_original_code:
unsigned int fst_add_arc(struct _fst *fst, unsigned int src, unsigned int dst, unsigned int il, unsigned int ol, float weight)
{
    struct _arc *arc;
    struct _state *state = &fst->states[src];
    ++state->n_arcs;
    if (state->n_arcs > state->n_max) {
        state->n_max = state->n_arcs * 2;
        state->arcs = realloc(state->arcs,
            sizeof(struct _arc) * state->n_max);
    }
    arc = &state->arcs[state->n_arcs - 1];
    arc->state = dst;
    arc->ilabel = il;
    arc->olabel = ol;
    arc->weight = weight;
    return state->n_arcs - 1;
}

variable_types:
src
unsigned int

variable_types:
dst
unsigned int

variable_types:
il
unsigned int

variable_types:
ol
unsigned int

variable_types: weight float


original_code:
void fst_empty(struct _fst * fst) {
    struct _state * state;
    for(uint32_t s=0; s < fst->n_states; ++s) {
        state = fst->states + s;
        if (state->arcs != ((void *)0))
            free(state->arcs);
    }
    if ( fst->states != ((void *)0) )
        free(fst->states);
    fst->n_states = 0;
    fst->n_max = 0;
    fst->states = ((void *)0);
    fst->start = 0;
}

canonical_original_code:
void fst_empty(struct _fst *fst) {
    struct _state *state;
    for(unsigned int s = 0; s < fst->n_states; ++s) {
        state = fst->states + s;
        if (state->arcs != ((void *)0))
            free(state->arcs);
    }
    if ( fst->states != ((void *)0) )
        free(fst->states);
    fst->n_states = 0;
    fst->n_max = 0;
    fst->states = ((void *)0);
    fst->start = 0;
}

variable_types:
s
unsigned int


decompiled_code:
void __fastcall fst_remove(void *ptr)
{
fst_empty((__int64)ptr);
free(ptr);
}

canonical_decompiled_code:
void __fastcall func4(void *ptr)
{
func3((__int64)ptr);
free(ptr);
}

original_code:
void fst_remove(struct _fst * fst) {
    fst_empty(fst);
    free(fst);
}

canonical_original_code:
void fst_remove(struct _fst *fst) {
    fst_empty(fst);
    free(fst);
}


decompiled_code:
__int64 __fastcall fst_set_final(__int64 a1, unsigned int a2, float a3)
{
__int64 result; // rax

result = 24LL * a2;
*(_DWORD *)(*(_QWORD *)(a1 + 16) + result + 12) = 1;
*(float *)(*(_QWORD *)(a1 + 16) + result + 8) = a3;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func5(__int64 a1, unsigned int a2, float a3)
{
__int64 result; // rax

result = 24LL * a2;
*(_DWORD *)(*(_QWORD *)(a1 + 16) + result + 12) = 1;
*(float *)(*(_QWORD *)(a1 + 16) + result + 8) = a3;
return result;
}

original_code:
void fst_set_final(struct _fst * fst, uint32_t s, float w) {
    (&fst->states[s])->final = 1;
    (&fst->states[s])->weight = w;
}

canonical_original_code:
void fst_set_final(struct _fst *fst, unsigned int s, float w) {
    (&fst->states[s])->final = 1;
    (&fst->states[s])->weight = w;
}

variable_types: w float


original_code:
uint32_t fst_get_n_arcs(const struct _fst * fst) {
    uint32_t n = 0;
    for (uint32_t s = 0; s < fst->n_states; ++s) {
        n += fst->states[s].n_arcs;
    }
    return n;
}

canonical_original_code:
unsigned int fst_get_n_arcs(struct _fst *fst) {
    unsigned int n = 0;
    for (unsigned int s = 0; s < fst->n_states; ++s) {
        n += fst->states[s].n_arcs;
    }
    return n;
}

variable_types:
n
unsigned int


original_code:
void fst_copy(const struct _fst * orig, struct _fst * copy) {
    struct _state * so, * sc;
    memcpy(copy, orig, sizeof(struct _fst));
    copy->states = malloc(sizeof(struct _state) * orig->n_max);
    memcpy(copy->states, orig->states, sizeof(struct _state) * orig->n_states);
    for(uint32_t s=0; s < copy->n_states; ++s) {
        sc = &copy->states[s];
        so = &orig->states[s];
        sc->arcs = malloc(sizeof(struct _arc) * sc->n_max);
        memcpy(sc->arcs, so->arcs, sizeof(struct _arc) * sc->n_arcs);
    }
}

canonical_original_code:
void fst_copy(struct _fst *orig, struct _fst *copy) {
    struct _state *so; struct _state *sc;
    memcpy(copy, orig, sizeof(struct _fst));
    copy->states = malloc(sizeof(struct _state) * orig->n_max);
    memcpy(copy->states, orig->states, sizeof(struct _state) * orig->n_states);
    for(unsigned int s = 0; s < copy->n_states; ++s) {
        sc = &copy->states[s];
        so = &orig->states[s];
        sc->arcs = malloc(sizeof(struct _arc) * sc->n_max);
        memcpy(sc->arcs, so->arcs, sizeof(struct _arc) * sc->n_arcs);
    }
}

variable_types:
copy
struct _fst *


original_code:
void fst_relabel(struct _fst * fst, uint32_t old, uint32_t new, int dir) {
    struct _state * state;
    struct _arc * arc;
    for (uint32_t s = 0; s < fst->n_states; ++s) {
        state = &fst->states[s];
        for (uint32_t a = 0; a < state->n_arcs; ++a) {
            arc = &state->arcs[a];
            if (dir == 0) {
                if (arc->ilabel == old) arc->ilabel = new;
            } else {
                if (arc->olabel == old) arc->olabel = new;
            }
        }
    }
}

canonical_original_code:
void fst_relabel(struct _fst *fst, unsigned int old, unsigned int new, int dir) {
    struct _state *state;
    struct _arc *arc;
    for (unsigned int s = 0; s < fst->n_states; ++s) {
        state = &fst->states[s];
        for (unsigned int a = 0; a < state->n_arcs; ++a) {
            arc = &state->arcs[a];
            if (dir == 0) {
                if (arc->ilabel == old) arc->ilabel = new;
            } else {
                if (arc->olabel == old) arc->olabel = new;
            }
        }
    }
}

variable_types:
old
unsigned int

variable_types:
new
unsigned int

variable_types: dir int

variable_types: struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } *

variable_types:
a
unsigned int


decompiled_code:
__int64 __fastcall fst_print(__int64 a1)
{
__int64 v1; // r12
unsigned int v2; // eax
unsigned int *v3; // rax
__int64 v4; // rdx
unsigned int v5; // er14
__int64 v6; // rcx
unsigned int *v7; // rbx
__int64 v8; // r13
int v10[11]; // [rsp+Ch] [rbp-2Ch] BYREF

v1 = queue_create(4LL);
v10[0] = 0;
if ( *(_DWORD *)(a1 + 4) )
{
v2 = 0;
do
{
v3 = (unsigned int *)(*(_QWORD *)(a1 + 16) + 24LL * v2);
v4 = *v3;
v5 = v3[3];
v6 = *((_QWORD *)v3 + 2);
if ( (_DWORD)v4 )
{
v7 = (unsigned int *)*((_QWORD *)v3 + 2);
v8 = v6 + 16LL * (unsigned int)(v4 - 1) + 16;
do
{
printf("%u\t%u\t%u\t%u\t%.5f\n", (unsigned int)v10[0], *v7, v7[2], v7[3], *((float *)v7 + 1));
v7 += 4;
}
while ( v7 != (unsigned int *)v8 );
}
if ( v5 == 1 )
queue_enque(v1, v10, v4, v6);
v2 = v10[0] + 1;
v10[0] = v2;
}
while ( v2 < *(_DWORD *)(a1 + 4) );
}
while ( queue_deque(v1, v10) )
printf("%u\t%f\n", (unsigned int)v10[0], *(float *)(*(_QWORD *)(a1 + 16) + 24LL * (unsigned int)v10[0] + 8));
return queue_remove(v1);
}

canonical_decompiled_code:
__int64 __fastcall func2(__int64 a1)
{
__int64 v1; // r12
unsigned int v2; // eax
unsigned int *v3; // rax
__int64 v4; // rdx
unsigned int v5; // er14
__int64 v6; // rcx
unsigned int *v7; // rbx
__int64 v8; // r13
int v10[11]; // [rsp+Ch] [rbp-2Ch] BYREF

v1 = queue_create(4LL);
v10[0] = 0;
if ( *(_DWORD *)(a1 + 4) )
{
v2 = 0;
do
{
v3 = (unsigned int *)(*(_QWORD *)(a1 + 16) + 24LL * v2);
v4 = *v3;
v5 = v3[3];
v6 = *((_QWORD *)v3 + 2);
if ( (_DWORD)v4 )
{
v7 = (unsigned int *)*((_QWORD *)v3 + 2);
v8 = v6 + 16LL * (unsigned int)(v4 - 1) + 16;
do
{
printf("%u\t%u\t%u\t%u\t%.5f\n", (unsigned int)v10[0], *v7, v7[2], v7[3], *((float *)v7 + 1));
v7 += 4;
}
while ( v7 != (unsigned int *)v8 );
}
if ( v5 == 1 )
queue_enque(v1, v10, v4, v6);
v2 = v10[0] + 1;
v10[0] = v2;
}
while ( v2 < *(_DWORD *)(a1 + 4) );
}
while ( queue_deque(v1, v10) )
printf("%u\t%f\n", (unsigned int)v10[0], *(float *)(*(_QWORD *)(a1 + 16) + 24LL * (unsigned int)v10[0] + 8));
return queue_remove(v1);
}

original_code:
void fst_print(const struct _fst * fst) {
    struct _state state;
    struct _arc arc;
    uint32_t s;
    uint32_t a;
    struct _queue *finals = queue_create(sizeof(uint32_t));
    for(s=0; s < fst->n_states; ++s) {
        state = fst->states[s];
        for(a=0; a < state.n_arcs; ++a) {
            arc = state.arcs[a];
            printf("%""u""\t%""u""\t%""u""\t%""u""\t%.5f\n",
                s,
                arc.state,
                arc.ilabel,
                arc.olabel,
                arc.weight);
        }
        if(state.final == 1) {
            queue_enque(finals, &s);
        }
    }
    while(queue_deque(finals, &s) != ((void *)0)) {
        state = fst->states[s];
        printf("%""u""\t%f\n", s, state.weight);
    }
    queue_remove(finals);
}

canonical_original_code:
void fst_print(struct _fst *fst) {
    struct _state state;
    struct _arc arc;
    unsigned int s;
    unsigned int a;
    struct _queue *finals = queue_create(sizeof(uint32_t));
    for(s=0; s < fst->n_states; ++s) {
        state = fst->states[s];
        for(a=0; a < state.n_arcs; ++a) {
            arc = state.arcs[a];
            printf("%""u""\t%""u""\t%""u""\t%""u""\t%.5f\n",
                s,
                arc.state,
                arc.ilabel,
                arc.olabel,
                arc.weight);
        }
        if(state.final == 1) {
            queue_enque(finals, &s);
        }
    }
    while(queue_deque(finals, &s) != ((void *)0)) {
        state = fst->states[s];
        printf("%""u""\t%f\n", s, state.weight);
    }
    queue_remove(finals);
}

variable_types: struct _state { unsigned int n_arcs; unsigned int n_max; float weight; int final; struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } *arcs; }

variable_types: struct _queue { struct _qnode { struct _qnode *next; char item[1]; } *head; struct _qnode *tail; unsigned long item_size; unsigned long n_items; } *


original_code:
void fst_print_sym(
                    const struct _fst * fst,
                    struct _symt * ist,
                    struct _symt * ost,
                    struct _symt * sst)
{
    struct _state state;
    struct _arc arc;
    token_t sa, sb, li, lo;
    rtrans_f strans, itrans, otrans;
    uint32_t s;
    uint32_t a;
    itrans = (ist == ((void *)0) ? trn:trt);
    otrans = (ost == ((void *)0) ? trn:trt);
    strans = (sst == ((void *)0) ? trn:trt);
    struct _queue *finals = queue_create(sizeof(uint32_t));
    for(s=0; s < fst->n_states; ++s) {
        state = fst->states[s];
        for(a=0; a < state.n_arcs; ++a) {
            arc = state.arcs[a];
            strans(sst, s, sa);
            strans(sst, arc.state, sb);
            itrans(ist, arc.ilabel, li);
            otrans(ost, arc.olabel, lo);
            if (sa == ((void *)0) || sb == ((void *)0) || li == ((void *)0) || lo == ((void *)0)) {
                fprintf(stderr, "Invalid symbol\n");
                exit(1);
            }
            printf("%s\t%s\t%s\t%s\t%.5f\n",
                sa,
                sb,
                li,
                lo,
                arc.weight);
        }
        if(state.final == 1) {
            queue_enque(finals, &s);
        }
    }
    while(queue_deque(finals, &s) != ((void *)0)) {
        state = fst->states[s];
        strans(sst, s, sa);
        if (sa == ((void *)0)) {
            fprintf(stderr, "Invalid symbol\n");
            exit(1);
        }
        printf("%s\t%f\n", sa, state.weight);
    }
    queue_remove(finals);
}

canonical_original_code:
void fst_print_sym(struct _fst *fst, struct _symt *ist, struct _symt *ost, struct _symt *sst)
{
    struct _state state;
    struct _arc arc;
    char sa[1024]; char sb[1024]; char li[1024]; char lo[1024];
    char *(*strans)(struct _symt *st, unsigned long id, char *token); char *(*itrans)(struct _symt *st, unsigned long id, char *token); char *(*otrans)(struct _symt *st, unsigned long id, char *token);
    unsigned int s;
    unsigned int a;
    itrans = (ist == ((void *)0) ? trn:trt);
    otrans = (ost == ((void *)0) ? trn:trt);
    strans = (sst == ((void *)0) ? trn:trt);
    struct _queue *finals = queue_create(sizeof(uint32_t));
    for(s=0; s < fst->n_states; ++s) {
        state = fst->states[s];
        for(a=0; a < state.n_arcs; ++a) {
            arc = state.arcs[a];
            strans(sst, s, sa);
            strans(sst, arc.state, sb);
            itrans(ist, arc.ilabel, li);
            otrans(ost, arc.olabel, lo);
            if (sa == ((void *)0) || sb == ((void *)0) || li == ((void *)0) || lo == ((void *)0)) {
                fprintf(stderr, "Invalid symbol\n");
                exit(1);
            }
            printf("%s\t%s\t%s\t%s\t%.5f\n",
                sa,
                sb,
                li,
                lo,
                arc.weight);
        }
        if(state.final == 1) {
            queue_enque(finals, &s);
        }
    }
    while(queue_deque(finals, &s) != ((void *)0)) {
        state = fst->states[s];
        strans(sst, s, sa);
        if (sa == ((void *)0)) {
            fprintf(stderr, "Invalid symbol\n");
            exit(1);
        }
        printf("%s\t%f\n", sa, state.weight);
    }
    queue_remove(finals);
}

variable_types: struct _fst { unsigned int start; unsigned int n_states; unsigned int n_max; unsigned char sr_type; unsigned char flags; struct _state { unsigned int n_arcs; unsigned int n_max; float weight; int final; struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } *arcs; } *states; } *

variable_types:
ost
struct _symt *

variable_types:
sst
struct _symt *

variable_types:
sa
char [1024]

variable_types:
sb
char [1024]

variable_types:
li
char [1024]

variable_types:
lo
char [1024]

variable_types: char *(*)(struct _symt { unsigned long n_items; unsigned long n_max; char **sym; struct _hash { struct _bucket { struct _bitem { void *key; void *value; struct _bitem *next; } *head; struct _bitem *tail; } *buckets; unsigned long item_size; unsigned long key_size; unsigned long size; unsigned long n_items; unsigned long (*hash_f)(void *key); int (*cmp_f)(void *key_a, void *key_b); } *rev; } *st, unsigned long id, char *token)

user_defined_types: struct _symt { unsigned long n_items; unsigned long n_max; char **sym; struct _hash *rev; }

user_defined_types: struct _hash { struct _bucket *buckets; unsigned long item_size; unsigned long key_size; unsigned long size; unsigned long n_items; unsigned long (*hash_f)(void *key); int (*cmp_f)(void *key_a, void *key_b); }

user_defined_types: struct _bucket { struct _bitem *head; struct _bitem *tail; }


trt

decompiled_code:
void *__fastcall trt(__int64 a1, __int64 a2, char *a3)
{
const char *v4; // rax
void *v5; // rbx

v4 = (const char *)symt_get();
v5 = (void *)v4;
if ( v4 )
{
strcpy(a3, v4);
v5 = a3;
}
else
{
fprintf(stderr, "Unknown token: %s\n", 0LL);
}
return v5;
}

canonical_decompiled_code:
void *__fastcall func0(__int64 a1, __int64 a2, char *a3)
{
const char *v4; // rax
void *v5; // rbx

v4 = (const char *)symt_get();
v5 = (void *)v4;
if ( v4 )
{
strcpy(a3, v4);
v5 = a3;
}
else
{
fprintf(stderr, "Unknown token: %s\n", 0LL);
}
return v5;
}

original_code:
static char * trt(struct _symt * st, size_t id, char * token) {
    char * t = symt_get(st, id);
    if (t == ((void *)0)) {
        token = ((void *)0);
        fprintf(stderr, "Unknown token: %s\n", token);
    } else {
        strcpy(token, t);
    }
    return token;
}

canonical_original_code:
static char *trt(struct _symt *st, unsigned long id, char *token) {
    char *t = symt_get(st, id);
    if (t == ((void *)0)) {
        token = ((void *)0);
        fprintf(stderr, "Unknown token: %s\n", token);
    } else {
        strcpy(token, t);
    }
    return token;
}

variable_types: struct _symt { unsigned long n_items; unsigned long n_max; char **sym; struct _hash { struct _bucket { struct _bitem { void *key; void *value; struct _bitem *next; } *head; struct _bitem *tail; } *buckets; unsigned long item_size; unsigned long key_size; unsigned long size; unsigned long n_items; unsigned long (*hash_f)(void *key); int (*cmp_f)(void *key_a, void *key_b); } *rev; } *

variable_types:
id
unsigned long

variable_types:
token
char *

variable_types:
t
char *

return_type: char *


trn

decompiled_code:
char *__fastcall trn(__int64 a1, __int64 a2, char *a3)
{
sprintf(a3, "%zu", a2);
return a3;
}

canonical_decompiled_code:
char *__fastcall func1(__int64 a1, __int64 a2, char *a3)
{
sprintf(a3, "%zu", a2);
return a3;
}

original_code:
static char * trn(struct _symt * st, size_t id, char * token) {
    sprintf(token, "%zu", id);
    return token;
}

canonical_original_code:
static char *trn(struct _symt *st, unsigned long id, char *token) {
    sprintf(token, "%zu", id);
    return token;
}

user_defined_types: struct _bitem { void *key; void *value; struct _bitem *next; }


bindex

decompiled_code:
__int64 __fastcall bindex(int a1)
{
return (unsigned int)(a1 / 32);
}

canonical_decompiled_code:
__int64 __fastcall func0(int a1)
{
return (unsigned int)(a1 / 32);
}

original_code: static inline int bindex(int b) { return b / WORD_SIZE; }

variable_types: b int

return_type: int


boffset

decompiled_code:
__int64 __fastcall boffset(int a1)
{
return (unsigned int)(a1 % 32);
}

canonical_decompiled_code:
__int64 __fastcall func1(int a1)
{
return (unsigned int)(a1 % 32);
}

original_code: static inline int boffset(int b) { return b % WORD_SIZE; }


decompiled_code:
void __fastcall bitset_remove(void *ptr)
{
free(*(void **)ptr);
free(ptr);
}

canonical_decompiled_code:
void __fastcall func2(void *ptr)
{
free(*(void **)ptr);
free(ptr);
}

original_code:
void bitset_remove(struct _bitset * bitset) {
    free(bitset->words);
    free(bitset);
}

canonical_original_code:
void bitset_remove(struct _bitset *bitset) {
    free(bitset->words);
    free(bitset);
}

variable_types: struct _bitset { unsigned int *words; int n_words; } *


decompiled_code:
__int64 __fastcall bitset_set(_QWORD *a1, int a2)
{
char v2; // bp
__int64 result; // rax

v2 = boffset(a2);
result = (int)bindex(a2);
*(_DWORD *)(*a1 + 4LL * (int)result) |= 1 << v2;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func3(_QWORD *a1, int a2)
{
char v2; // bp
__int64 result; // rax

v2 = func1(a2);
result = (int)func0(a2);
*(_DWORD *)(*a1 + 4LL * (int)result) |= 1 << v2;
return result;
}

original_code:
void bitset_set(struct _bitset * bitset, int b) {
    bitset->words[bindex(b)] |= 1 << (boffset(b));
}

canonical_original_code:
void bitset_set(struct _bitset *bitset, int b) {
    bitset->words[bindex(b)] |= 1 << (boffset(b));
}

user_defined_types: struct _bitset { unsigned int *words; int n_words; }


decompiled_code:
__int64 __fastcall bitset_clear(_QWORD *a1, int a2)
{
char v2; // bp
__int64 result; // rax

v2 = boffset(a2);
result = (int)bindex(a2);
*(_DWORD *)(*a1 + 4LL * (int)result) &= __ROL4__(-2, v2);
return result;
}

canonical_decompiled_code:
__int64 __fastcall func4(_QWORD *a1, int a2)
{
char v2; // bp
__int64 result; // rax

v2 = func1(a2);
result = (int)func0(a2);
*(_DWORD *)(*a1 + 4LL * (int)result) &= __ROL4__(-2, v2);
return result;
}

original_code:
void bitset_clear(struct _bitset * bitset, int b) {
    bitset->words[bindex(b)] &= ~(1 << (boffset(b)));
}

canonical_original_code:
void bitset_clear(struct _bitset *bitset, int b) {
    bitset->words[bindex(b)] &= ~(1 << (boffset(b)));
}


decompiled_code:
_BOOL8 __fastcall bitset_get(_QWORD *a1, int a2)
{
int v2; // ebx

v2 = bindex(a2);
return (*(_DWORD *)(*a1 + 4LL * v2) & (1 << boffset(a2))) != 0;
}

canonical_decompiled_code:
_BOOL8 __fastcall func5(_QWORD *a1, int a2)
{
int v2; // ebx

v2 = func0(a2);
return (*(_DWORD *)(*a1 + 4LL * v2) & (1 << func1(a2))) != 0;
}

original_code:
int bitset_get(struct _bitset * bitset, int b) {
    return bitset->words[bindex(b)] & (1 << (boffset(b))) ? 1 : 0;
}

canonical_original_code:
int bitset_get(struct _bitset *bitset, int b) {
    return bitset->words[bindex(b)] & (1 << (boffset(b))) ? 1 : 0;
}


original_code:
void bitset_clear_all(struct _bitset * bitset) {
    for(int i = 0; i < bitset->n_words; ++i)
        bitset->words[i] = 0;
}

canonical_original_code:
void bitset_clear_all(struct _bitset *bitset) {
    for(int i = 0; i < bitset->n_words; ++i)
        bitset->words[i] = 0;
}

variable_types: i int


original_code:
void bitset_set_all(struct _bitset * bitset) {
    for(int i = 0; i < bitset->n_words; ++i)
        bitset->words[i] = ~0;
}

canonical_original_code:
void bitset_set_all(struct _bitset *bitset) {
    for(int i = 0; i < bitset->n_words; ++i)
        bitset->words[i] = ~0;
}


decompiled_code:
__int64 __fastcall bitset_union(__int64 a1, __int64 a2)
{
int v2; // edx
__int64 result; // rax

v2 = *(_DWORD *)(a1 + 8);
if ( v2 != *(_DWORD *)(a2 + 8) )
_assert_fail("a->n_words == b->n_words", "src/bitset.c", 0x35u, "bitset_union");
result = 0LL;
if ( v2 > 0 )
{
do
{
*(_DWORD *)(*(_QWORD *)a1 + 4 * result) |= *(_DWORD *)(*(_QWORD *)a2 + 4 * result);
++result;
}
while ( *(_DWORD *)(a1 + 8) > (int)result );
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func9(__int64 a1, __int64 a2)
{
int v2; // edx
__int64 result; // rax

v2 = *(_DWORD *)(a1 + 8);
if ( v2 != *(_DWORD *)(a2 + 8) )
_assert_fail("a->n_words == b->n_words", "src/bitset.c", 0x35u, "bitset_union");
result = 0LL;
if ( v2 > 0 )
{
do
{
*(_DWORD *)(*(_QWORD *)a1 + 4 * result) |= *(_DWORD *)(*(_QWORD *)a2 + 4 * result);
++result;
}
while ( *(_DWORD *)(a1 + 8) > (int)result );
}
return result;
}

original_code:
void bitset_union(struct _bitset * a, const struct _bitset * b) {
    ((a->n_words == b->n_words) ? (void) (0) : __assert_fail ("a->n_words == b->n_words", "src/bitset.c", 53, __extension__ __PRETTY_FUNCTION__));
    for(int i = 0; i < a->n_words; ++i)
        a->words[i] |= b->words[i];
}

canonical_original_code:
void bitset_union(struct _bitset *a, struct _bitset *b) {
    ((a->n_words == b->n_words) ? (void) (0) : __assert_fail ("a->n_words == b->n_words", "src/bitset.c", 53, __extension__ __PRETTY_FUNCTION__));
    for(int i = 0; i < a->n_words; ++i)
        a->words[i] |= b->words[i];
}

variable_types:
b
struct _bitset *


decompiled_code:
__int64 __fastcall bitset_intersect(__int64 a1, __int64 a2)
{
int v2; // edx
__int64 result; // rax

v2 = *(_DWORD *)(a1 + 8);
if ( v2 != *(_DWORD *)(a2 + 8) )
_assert_fail("a->n_words == b->n_words", "src/bitset.c", 0x3Cu, "bitset_intersect");
result = 0LL;
if ( v2 > 0 )
{
do
{
*(_DWORD *)(*(_QWORD *)a1 + 4 * result) &= *(_DWORD *)(*(_QWORD *)a2 + 4 * result);
++result;
}
while ( *(_DWORD *)(a1 + 8) > (int)result );
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func10(__int64 a1, __int64 a2)
{
int v2; // edx
__int64 result; // rax

v2 = *(_DWORD *)(a1 + 8);
if ( v2 != *(_DWORD *)(a2 + 8) )
_assert_fail("a->n_words == b->n_words", "src/bitset.c", 0x3Cu, "bitset_intersect");
result = 0LL;
if ( v2 > 0 )
{
do
{
*(_DWORD *)(*(_QWORD *)a1 + 4 * result) &= *(_DWORD *)(*(_QWORD *)a2 + 4 * result);
++result;
}
while ( *(_DWORD *)(a1 + 8) > (int)result );
}
return result;
}

original_code:
void bitset_intersect(struct _bitset * a, const struct _bitset * b) {
    ((a->n_words == b->n_words) ? (void) (0) : __assert_fail ("a->n_words == b->n_words", "src/bitset.c", 60, __extension__ __PRETTY_FUNCTION__));
    for(int i = 0; i < a->n_words; ++i)
        a->words[i] &= b->words[i];
}

canonical_original_code:
void bitset_intersect(struct _bitset *a, struct _bitset *b) {
    ((a->n_words == b->n_words) ? (void) (0) : __assert_fail ("a->n_words == b->n_words", "src/bitset.c", 60, __extension__ __PRETTY_FUNCTION__));
    for(int i = 0; i < a->n_words; ++i)
        a->words[i] &= b->words[i];
}


decompiled_code:
float __fastcall real_sum(float a1, float a2)
{
return a1 + a2;
}

canonical_decompiled_code:
float __fastcall func0(float a1, float a2)
{
return a1 + a2;
}

original_code: float real_sum(const float a, const float b) { return a+b; }

canonical_original_code: float real_sum(float a, float b) { return a+b; }

variable_types: a float

variable_types: b float

return_type: float


decompiled_code:
float __fastcall real_product(float a1, float a2)
{
return a1 * a2;
}

canonical_decompiled_code:
float __fastcall func1(float a1, float a2)
{
return a1 * a2;
}

original_code: float real_product(const float a, const float b) { return a*b; }

canonical_original_code: float real_product(float a, float b) { return a*b; }


decompiled_code:
float __fastcall tropical_sum(float a1, float a2)
{
return fminf(a1, a2);
}

canonical_decompiled_code:
float __fastcall func2(float a1, float a2)
{
return fminf(a1, a2);
}

original_code: float tropical_sum(const float a, const float b) { return a < b ? a : b; }

canonical_original_code: float tropical_sum(float a, float b) { return a < b ? a : b; }


decompiled_code:
float __fastcall tropical_product(float a1, float a2)
{
return a1 + a2;
}

canonical_decompiled_code:
float __fastcall func3(float a1, float a2)
{
return a1 + a2;
}

original_code: float tropical_product(const float a, const float b) { return a + b; }

canonical_original_code: float tropical_product(float a, float b) { return a + b; }


decompiled_code:
void __fastcall fst_iter_remove(void *ptr)
{
bitset_remove(*((_QWORD *)ptr + 1));
queue_remove(*((_QWORD *)ptr + 2));
free(ptr);
}

canonical_decompiled_code:
void __fastcall func0(void *ptr)
{
bitset_remove(*((_QWORD *)ptr + 1));
queue_remove(*((_QWORD *)ptr + 2));
free(ptr);
}

original_code:
void fst_iter_remove(struct _fst_iter * iter) {
    bitset_remove(iter->marked);
    queue_remove(iter->queue);
    iter->fst = ((void *)0);
    free(iter);
}

canonical_original_code:
void fst_iter_remove(struct _fst_iter *iter) {
    bitset_remove(iter->marked);
    queue_remove(iter->queue);
    iter->fst = ((void *)0);
    free(iter);
}

variable_types: struct _fst_iter { struct _fst { unsigned int start; unsigned int n_states; unsigned int n_max; unsigned char sr_type; unsigned char flags; struct _state { unsigned int n_arcs; unsigned int n_max; float weight; int final; struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } *arcs; } *states; } *fst; struct _bitset { unsigned int *words; int n_words; } *marked; struct _queue { struct _qnode { struct _qnode *next; char item[1]; } *head; struct _qnode *tail; unsigned long item_size; unsigned long n_items; } *queue; unsigned int state; } *

user_defined_types: struct _fst_iter { struct _fst *fst; struct _bitset *marked; struct _queue *queue; unsigned int state; }


decompiled_code:
__int64 __fastcall fst_iter_next(__int64 a1)
{
unsigned int v1; // eax
__int64 v2; // r13
unsigned int v3; // ebp
unsigned int *v4; // rbx
unsigned int v6[11]; // [rsp+Ch] [rbp-2Ch] BYREF

if ( queue_deque(*(_QWORD *)(a1 + 16), v6) )
{
v1 = v6[0];
*(_DWORD *)(a1 + 24) = v6[0];
v2 = *(_QWORD *)(*(_QWORD *)a1 + 16LL) + 24LL * v1;
if ( *(_DWORD *)v2 )
{
v3 = 0;
do
{
v4 = (unsigned int *)(*(_QWORD *)(v2 + 16) + 16LL * v3);
if ( !(unsigned int)bitset_get(*(_QWORD *)(a1 + 8), *v4) )
{
queue_enque(*(_QWORD *)(a1 + 16), v4);
bitset_set(*(_QWORD *)(a1 + 8), *v4);
}
++v3;
}
while ( *(_DWORD *)v2 > v3 );
}
}
else
{
*(_DWORD *)(a1 + 24) = -1;
}
return *(unsigned int *)(a1 + 24);
}

canonical_decompiled_code:
__int64 __fastcall func1(__int64 a1)
{
unsigned int v1; // eax
__int64 v2; // r13
unsigned int v3; // ebp
unsigned int *v4; // rbx
unsigned int v6[11]; // [rsp+Ch] [rbp-2Ch] BYREF

if ( queue_deque(*(_QWORD *)(a1 + 16), v6) )
{
v1 = v6[0];
*(_DWORD *)(a1 + 24) = v6[0];
v2 = *(_QWORD *)(*(_QWORD *)a1 + 16LL) + 24LL * v1;
if ( *(_DWORD *)v2 )
{
v3 = 0;
do
{
v4 = (unsigned int *)(*(_QWORD *)(v2 + 16) + 16LL * v3);
if ( !(unsigned int)bitset_get(*(_QWORD *)(a1 + 8), *v4) )
{
queue_enque(*(_QWORD *)(a1 + 16), v4);
bitset_set(*(_QWORD *)(a1 + 8), *v4);
}
++v3;
}
while ( *(_DWORD *)v2 > v3 );
}
}
else
{
*(_DWORD *)(a1 + 24) = -1;
}
return *(unsigned int *)(a1 + 24);
}

original_code:
uint32_t fst_iter_next(struct _fst_iter * iter) {
    struct _arc * arc;
    struct _state * state;
    uint32_t s;
    uint32_t a;
    if((queue_deque(iter->queue, &s)) != ((void *)0)) {
        iter->state = s;
        state = &iter->fst->states[s];
        for(a=0; a < state->n_arcs; ++a) {
            arc = &state->arcs[a];
            if (bitset_get(iter->marked, arc->state) == 0) {
                queue_enque(iter->queue, &arc->state);
                bitset_set(iter->marked, arc->state);
            }
        }
    } else {
        iter->state = -1;
    }
    return iter->state;
}

canonical_original_code:
unsigned int fst_iter_next(struct _fst_iter *iter) {
    struct _arc *arc;
    struct _state *state;
    unsigned int s;
    unsigned int a;
    if((queue_deque(iter->queue, &s)) != ((void *)0)) {
        iter->state = s;
        state = &iter->fst->states[s];
        for(a=0; a < state->n_arcs; ++a) {
            arc = &state->arcs[a];
            if (bitset_get(iter->marked, arc->state) == 0) {
                queue_enque(iter->queue, &arc->state);
                bitset_set(iter->marked, arc->state);
            }
        }
    } else {
        iter->state = -1;
    }
    return iter->state;
}

variable_types: struct _state { unsigned int n_arcs; unsigned int n_max; float weight; int final; struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } *arcs; } *

variable_types:
s
unsigned int

variable_types:
a
unsigned int


decompiled_code:
__int64 __fastcall fst_iter_visited(__int64 a1, __int64 a2)
{
return bitset_get(*(_QWORD *)(a1 + 8), a2);
}

canonical_decompiled_code:
__int64 __fastcall func2(__int64 a1, __int64 a2)
{
return bitset_get(*(_QWORD *)(a1 + 8), a2);
}

original_code:
int fst_iter_visited(struct _fst_iter * iter, uint32_t s) {
    return bitset_get(iter->marked, s);
}

canonical_original_code:
int fst_iter_visited(struct _fst_iter *iter, unsigned int s) {
    return bitset_get(iter->marked, s);
}


decompiled_code:
void __fastcall empty_chain(void *ptr)
{
void **v1; // rbx
void **v2; // rbp

v1 = (void **)ptr;
if ( ptr )
{
do
{
v2 = v1;
v1 = (void **)v1[2];
if ( v2[1] )
{
free(*v2);
free(v2[1]);
}
free(v2);
}
while ( v1 );
}
}

canonical_decompiled_code:
void __fastcall func0(void *ptr)
{
void **v1; // rbx
void **v2; // rbp

v1 = (void **)ptr;
if ( ptr )
{
do
{
v2 = v1;
v1 = (void **)v1[2];
if ( v2[1] )
{
free(*v2);
free(v2[1]);
}
free(v2);
}
while ( v1 );
}
}

original_code:
void empty_chain(struct _bitem * bitem) {
    struct _bitem * t_bitem = ((void *)0);
    while(bitem != ((void *)0)) {
        t_bitem = bitem;
        bitem = bitem->next;
        if (t_bitem->value) {
            free(t_bitem->key);
            free(t_bitem->value);
        }
        free(t_bitem);
    }
}

canonical_original_code:
void empty_chain(struct _bitem *bitem) {
    struct _bitem *t_bitem = ((void *)0);
    while(bitem != ((void *)0)) {
        t_bitem = bitem;
        bitem = bitem->next;
        if (t_bitem->value) {
            free(t_bitem->key);
            free(t_bitem->value);
        }
        free(t_bitem);
    }
}

variable_types: struct _bitem { void *key; void *value; struct _bitem *next; } *


decompiled_code:
void __fastcall hash_remove(void *ptr)
{
unsigned __int64 v1; // rbx

if ( *((_QWORD *)ptr + 3) )
{
v1 = 0LL;
do
empty_chain(*(void **)(*(_QWORD *)ptr + 16 * v1++));
while ( *((_QWORD *)ptr + 3) > v1 );
}
free(*(void **)ptr);
free(ptr);
}

canonical_decompiled_code:
void __fastcall func1(void *ptr)
{
unsigned __int64 v1; // rbx

if ( *((_QWORD *)ptr + 3) )
{
v1 = 0LL;
do
func0(*(void **)(*(_QWORD *)ptr + 16 * v1++));
while ( *((_QWORD *)ptr + 3) > v1 );
}
free(*(void **)ptr);
free(ptr);
}

original_code:
void hash_remove(struct _hash * hash) {
    for (size_t i = 0; i < hash->size; ++i) {
        empty_chain(hash->buckets[i].head);
    }
    free(hash->buckets);
    free(hash);
}

canonical_original_code:
void hash_remove(struct _hash *hash) {
    for (unsigned long i = 0; i < hash->size; ++i) {
        empty_chain(hash->buckets[i].head);
    }
    free(hash->buckets);
    free(hash);
}

variable_types: struct _hash { struct _bucket { struct _bitem { void *key; void *value; struct _bitem *next; } *head; struct _bitem *tail; } *buckets; unsigned long item_size; unsigned long key_size; unsigned long size; unsigned long n_items; unsigned long (*hash_f)(void *key); int (*cmp_f)(void *key_a, void *key_b); } *

variable_types:
i
unsigned long


original_code:
void hash_add( struct _hash * hash,
                void * key,
                void * value)
{
    size_t bnum = hash->hash_f(key) % hash->size;
    struct _bucket * bucket = &hash->buckets[bnum];
    for (
                struct _bitem * bi = bucket->head;
                bi != ((void *)0);
                bi = bi->next
    ) {
        if ( hash->cmp_f(key, bi->key) ) {
            memcpy(bi->key, key, hash->key_size);
            memcpy(bi->value, value, hash->item_size);
            return;
        }
    }
    struct _bitem * bitem = malloc(sizeof(struct _bitem));
    bitem->key = key;
    bitem->value = value;
    bitem->next = ((void *)0);
    bitem->key = malloc(hash->key_size);
    memcpy(bitem->key, key, hash->key_size);
    bitem->value = malloc(hash->item_size);
    memcpy(bitem->value, value, hash->item_size);
    if ( bucket->tail == ((void *)0) ) {
        bucket->tail = bucket->head = bitem;
    } else {
        bucket->tail->next = bitem;
        bucket->tail = bitem;
    }
    ++hash->n_items;
    if ( ( ((float)hash->n_items) / hash->size) > 0.75) {
        hash_resize(hash);
    }
}

canonical_original_code:
void hash_add(struct _hash *hash, void *key, void *value)
{
    unsigned long bnum = hash->hash_f(key) % hash->size;
    struct _bucket *bucket = &hash->buckets[bnum];
    for (
                struct _bitem *bi = bucket->head;
                bi != ((void *)0);
                bi = bi->next
    ) {
        if ( hash->cmp_f(key, bi->key) ) {
            memcpy(bi->key, key, hash->key_size);
            memcpy(bi->value, value, hash->item_size);
            return;
        }
    }
    struct _bitem *bitem = malloc(sizeof(struct _bitem));
    bitem->key = key;
    bitem->value = value;
    bitem->next = ((void *)0);
    bitem->key = malloc(hash->key_size);
    memcpy(bitem->key, key, hash->key_size);
    bitem->value = malloc(hash->item_size);
    memcpy(bitem->value, value, hash->item_size);
    if ( bucket->tail == ((void *)0) ) {
        bucket->tail = bucket->head = bitem;
    } else {
        bucket->tail->next = bitem;
        bucket->tail = bitem;
    }
    ++hash->n_items;
    if ( ( ((float)hash->n_items) / hash->size) > 0.75) {
        hash_resize(hash);
    }
}

variable_types:
key
void *

variable_types:
value
void *

variable_types:
bnum
unsigned long

variable_types: struct _bucket { struct _bitem { void *key; void *value; struct _bitem *next; } *head; struct _bitem *tail; } *


original_code:
void hash_resize(struct _hash * hash) {
    size_t old_size = hash->size;
    struct _bucket * old_buckets = hash->buckets;
    hash->size *= 2;
    hash->n_items = 0;
    hash->buckets = (struct _bucket *)malloc(
                hash->size * sizeof(struct _bucket));
    for (size_t i = 0; i < hash->size; i++)
        hash->buckets[i].head = hash->buckets[i].tail = ((void *)0);
    for (size_t i = 0; i < old_size; i++) {
        for ( struct _bitem * bi = old_buckets[i].head;
                bi != ((void *)0);
                bi = bi->next
        ) {
            hash_add(hash, bi->key, bi->value);
        }
    }
    for (size_t i = 0; i < old_size; ++i)
        empty_chain(old_buckets[i].head);
    free(old_buckets);
}

canonical_original_code:
void hash_resize(struct _hash *hash) {
    unsigned long old_size = hash->size;
    struct _bucket *old_buckets = hash->buckets;
    hash->size *= 2;
    hash->n_items = 0;
    hash->buckets = (struct _bucket *)malloc(
                hash->size * sizeof(struct _bucket));
    for (unsigned long i = 0; i < hash->size; i++)
        hash->buckets[i].head = hash->buckets[i].tail = ((void *)0);
    for (unsigned long i = 0; i < old_size; i++) {
        for ( struct _bitem *bi = old_buckets[i].head;
                bi != ((void *)0);
                bi = bi->next
        ) {
            hash_add(hash, bi->key, bi->value);
        }
    }
    for (unsigned long i = 0; i < old_size; ++i)
        empty_chain(old_buckets[i].head);
    free(old_buckets);
}


original_code:
void * hash_get( struct _hash * hash,
                    void * key,
                    void * item)
{
    struct _bucket bucket = hash->buckets[hash->hash_f(key) % hash->size];
    for (
                struct _bitem * bi = bucket.head;
                bi != ((void *)0);
                bi = bi->next
    ) {
        if ( hash->cmp_f(key, bi->key) ) {
            memcpy(item, bi->value, hash->item_size);
            return bi->value;
        }
    }
    return ((void *)0);
}

canonical_original_code:
void *hash_get(struct _hash *hash, void *key, void *item)
{
    struct _bucket bucket = hash->buckets[hash->hash_f(key) % hash->size];
    for (
                struct _bitem *bi = bucket.head;
                bi != ((void *)0);
                bi = bi->next
    ) {
        if ( hash->cmp_f(key, bi->key) ) {
            memcpy(item, bi->value, hash->item_size);
            return bi->value;
        }
    }
    return ((void *)0);
}

variable_types:
item
void *

variable_types: struct _bucket { struct _bitem { void *key; void *value; struct _bitem *next; } *head; struct _bitem *tail; }

return_type: void *


decompiled_code:
float __fastcall assert_arc_equal(__int64 a1, __int64 a2)
{
float result; // xmm0_4

if ( *(_DWORD *)a1 != *(_DWORD *)a2 )
_assert_fail("arc_a->state == arc_b->state", "src/test.c", 7u, "assert_arc_equal");
if ( *(_DWORD *)(a1 + 8) != *(_DWORD *)(a2 + 8) )
_assert_fail("arc_a->ilabel == arc_b->ilabel", "src/test.c", 8u, "assert_arc_equal");
if ( *(_DWORD *)(a1 + 12) != *(_DWORD *)(a2 + 12) )
_assert_fail("arc_a->olabel == arc_b->olabel", "src/test.c", 9u, "assert_arc_equal");
result = *(float *)(a1 + 4);
if ( result != *(float *)(a2 + 4) )
_assert_fail("arc_a->weight == arc_b->weight", "src/test.c", 0xAu, "assert_arc_equal");
return result;
}

canonical_decompiled_code:
float __fastcall func0(__int64 a1, __int64 a2)
{
float result; // xmm0_4

if ( *(_DWORD *)a1 != *(_DWORD *)a2 )
_assert_fail("arc_a->state == arc_b->state", "src/test.c", 7u, "assert_arc_equal");
if ( *(_DWORD *)(a1 + 8) != *(_DWORD *)(a2 + 8) )
_assert_fail("arc_a->ilabel == arc_b->ilabel", "src/test.c", 8u, "assert_arc_equal");
if ( *(_DWORD *)(a1 + 12) != *(_DWORD *)(a2 + 12) )
_assert_fail("arc_a->olabel == arc_b->olabel", "src/test.c", 9u, "assert_arc_equal");
result = *(float *)(a1 + 4);
if ( result != *(float *)(a2 + 4) )
_assert_fail("arc_a->weight == arc_b->weight", "src/test.c", 0xAu, "assert_arc_equal");
return result;
}

original_code:
void assert_arc_equal(const struct _arc * arc_a, const struct _arc * arc_b) {
    ((arc_a->state == arc_b->state) ? (void) (0) : __assert_fail ("arc_a->state == arc_b->state", "src/test.c", 7, __extension__ __PRETTY_FUNCTION__));
    ((arc_a->ilabel == arc_b->ilabel) ? (void) (0) : __assert_fail ("arc_a->ilabel == arc_b->ilabel", "src/test.c", 8, __extension__ __PRETTY_FUNCTION__));
    ((arc_a->olabel == arc_b->olabel) ? (void) (0) : __assert_fail ("arc_a->olabel == arc_b->olabel", "src/test.c", 9, __extension__ __PRETTY_FUNCTION__));
    ((arc_a->weight == arc_b->weight) ? (void) (0) : __assert_fail ("arc_a->weight == arc_b->weight", "src/test.c", 10, __extension__ __PRETTY_FUNCTION__));
}

canonical_original_code:
void assert_arc_equal(struct _arc *arc_a, struct _arc *arc_b) {
    ((arc_a->state == arc_b->state) ? (void) (0) : __assert_fail ("arc_a->state == arc_b->state", "src/test.c", 7, __extension__ __PRETTY_FUNCTION__));
    ((arc_a->ilabel == arc_b->ilabel) ? (void) (0) : __assert_fail ("arc_a->ilabel == arc_b->ilabel", "src/test.c", 8, __extension__ __PRETTY_FUNCTION__));
    ((arc_a->olabel == arc_b->olabel) ? (void) (0) : __assert_fail ("arc_a->olabel == arc_b->olabel", "src/test.c", 9, __extension__ __PRETTY_FUNCTION__));
    ((arc_a->weight == arc_b->weight) ? (void) (0) : __assert_fail ("arc_a->weight == arc_b->weight", "src/test.c", 10, __extension__ __PRETTY_FUNCTION__));
}

variable_types: struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } *


decompiled_code:
__int64 __fastcall assert_state_equal(__int64 a1, __int64 a2)
{
__int64 result; // rax

result = *(unsigned int *)(a2 + 12);
if ( *(_DWORD *)(a1 + 12) != (_DWORD)result )
_assert_fail("state_a->final == state_b->final", "src/test.c", 0x10u, "assert_state_equal");
return result;
}

canonical_decompiled_code:
__int64 __fastcall func1(__int64 a1, __int64 a2)
{
__int64 result; // rax

result = *(unsigned int *)(a2 + 12);
if ( *(_DWORD *)(a1 + 12) != (_DWORD)result )
_assert_fail("state_a->final == state_b->final", "src/test.c", 0x10u, "assert_state_equal");
return result;
}

original_code:
void assert_state_equal(const struct _state * state_a, const struct _state * state_b) {
    ((state_a->final == state_b->final) ? (void) (0) : __assert_fail ("state_a->final == state_b->final", "src/test.c", 16, __extension__ __PRETTY_FUNCTION__));
}

canonical_original_code:
void assert_state_equal(struct _state *state_a, struct _state *state_b) {
    ((state_a->final == state_b->final) ? (void) (0) : __assert_fail ("state_a->final == state_b->final", "src/test.c", 16, __extension__ __PRETTY_FUNCTION__));
}


decompiled_code:
void __fastcall assert_fst_equal(__int64 a1, __int64 a2)
{
unsigned int v2; // er15
int v3; // eax
unsigned int i; // er14
__int64 v5; // rbx
__int64 v6; // r12
__int64 v7; // rbx
int v8; // er13
unsigned int v9; // ebp
__int64 v10; // r13
__int64 v11; // r12
unsigned int j; // ebx
__int64 v13; // [rsp+0h] [rbp-48h]
__int64 v14; // [rsp+8h] [rbp-40h]

if ( *(_DWORD *)a1 != *(_DWORD *)a2 )
_assert_fail("a->start == b->start", "src/test.c", 0x1Au, "assert_fst_equal");
if ( *(_BYTE *)(a1 + 12) != *(_BYTE *)(a2 + 12) )
_assert_fail("a->sr_type == b->sr_type", "src/test.c", 0x1Bu, "assert_fst_equal");
v2 = *(_DWORD *)(a1 + 4);
v3 = *(_DWORD *)(a2 + 4);
if ( v2 != v3 )
_assert_fail("a->n_states == b->n_states", "src/test.c", 0x1Cu, "assert_fst_equal");
if ( v3 && v2 )
{
v13 = *(_QWORD *)(a1 + 16);
v14 = *(_QWORD *)(a2 + 16);
for ( i = 0; i < v2; ++i )
{
v5 = 24LL * i;
v6 = v13 + v5;
v7 = v14 + v5;
v8 = *(_DWORD *)v6;
v9 = *(_DWORD *)v7;
if ( *(_DWORD *)v6 != *(_DWORD *)v7 )
_assert_fail("state_a->n_arcs == state_b->n_arcs", "src/test.c", 0x23u, "assert_fst_equal");
assert_state_equal(v6, v7);
if ( v9 && v8 )
{
v10 = *(_QWORD *)(v6 + 16);
v11 = *(_QWORD *)(v7 + 16);
for ( j = 0; j < v9; ++j )
assert_arc_equal(v10 + 16LL * j, v11 + 16LL * j);
}
}
}
}

canonical_decompiled_code:
void __fastcall func2(__int64 a1, __int64 a2)
{
unsigned int v2; // er15
int v3; // eax
unsigned int i; // er14
__int64 v5; // rbx
__int64 v6; // r12
__int64 v7; // rbx
int v8; // er13
unsigned int v9; // ebp
__int64 v10; // r13
__int64 v11; // r12
unsigned int j; // ebx
__int64 v13; // [rsp+0h] [rbp-48h]
__int64 v14; // [rsp+8h] [rbp-40h]

if ( *(_DWORD *)a1 != *(_DWORD *)a2 )
_assert_fail("a->start == b->start", "src/test.c", 0x1Au, "assert_fst_equal");
if ( *(_BYTE *)(a1 + 12) != *(_BYTE *)(a2 + 12) )
_assert_fail("a->sr_type == b->sr_type", "src/test.c", 0x1Bu, "assert_fst_equal");
v2 = *(_DWORD *)(a1 + 4);
v3 = *(_DWORD *)(a2 + 4);
if ( v2 != v3 )
_assert_fail("a->n_states == b->n_states", "src/test.c", 0x1Cu, "assert_fst_equal");
if ( v3 && v2 )
{
v13 = *(_QWORD *)(a1 + 16);
v14 = *(_QWORD *)(a2 + 16);
for ( i = 0; i < v2; ++i )
{
v5 = 24LL * i;
v6 = v13 + v5;
v7 = v14 + v5;
v8 = *(_DWORD *)v6;
v9 = *(_DWORD *)v7;
if ( *(_DWORD *)v6 != *(_DWORD *)v7 )
_assert_fail("state_a->n_arcs == state_b->n_arcs", "src/test.c", 0x23u, "assert_fst_equal");
func1(v6, v7);
if ( v9 && v8 )
{
v10 = *(_QWORD *)(v6 + 16);
v11 = *(_QWORD *)(v7 + 16);
for ( j = 0; j < v9; ++j )
func0(v10 + 16LL * j, v11 + 16LL * j);
}
}
}
}

original_code:
void assert_fst_equal(const struct _fst * a, const struct _fst * b) {
    struct _state * state_a;
    struct _state * state_b;
    struct _arc * arc_a;
    struct _arc * arc_b;
    ((a->start == b->start) ? (void) (0) : __assert_fail ("a->start == b->start", "src/test.c", 26, __extension__ __PRETTY_FUNCTION__));
    ((a->sr_type == b->sr_type) ? (void) (0) : __assert_fail ("a->sr_type == b->sr_type", "src/test.c", 27, __extension__ __PRETTY_FUNCTION__));
    ((a->n_states == b->n_states) ? (void) (0) : __assert_fail ("a->n_states == b->n_states", "src/test.c", 28, __extension__ __PRETTY_FUNCTION__));
    for (uint32_t st = 0; st < a->n_states && st < b->n_states; ++st) {
        state_a = &a->states[st];
        state_b = &b->states[st];
        ((state_a->n_arcs == state_b->n_arcs) ? (void) (0) : __assert_fail ("state_a->n_arcs == state_b->n_arcs", "src/test.c", 35, __extension__ __PRETTY_FUNCTION__));
        assert_state_equal( state_a, state_b );
        for (uint32_t arc = 0;
                    arc < state_a->n_arcs && arc < state_b->n_arcs;
                    ++arc) {
            arc_a = &state_a->arcs[arc];
            arc_b = &state_b->arcs[arc];
            assert_arc_equal( arc_a, arc_b );
        }
    }
}

canonical_original_code:
void assert_fst_equal(struct _fst *a, struct _fst *b) {
    struct _state *state_a;
    struct _state *state_b;
    struct _arc *arc_a;
    struct _arc *arc_b;
    ((a->start == b->start) ? (void) (0) : __assert_fail ("a->start == b->start", "src/test.c", 26, __extension__ __PRETTY_FUNCTION__));
    ((a->sr_type == b->sr_type) ? (void) (0) : __assert_fail ("a->sr_type == b->sr_type", "src/test.c", 27, __extension__ __PRETTY_FUNCTION__));
    ((a->n_states == b->n_states) ? (void) (0) : __assert_fail ("a->n_states == b->n_states", "src/test.c", 28, __extension__ __PRETTY_FUNCTION__));
    for (unsigned int st = 0; st < a->n_states && st < b->n_states; ++st) {
        state_a = &a->states[st];
        state_b = &b->states[st];
        ((state_a->n_arcs == state_b->n_arcs) ? (void) (0) : __assert_fail ("state_a->n_arcs == state_b->n_arcs", "src/test.c", 35, __extension__ __PRETTY_FUNCTION__));
        assert_state_equal( state_a, state_b );
        for (unsigned int arc = 0;
                    arc < state_a->n_arcs && arc < state_b->n_arcs;
                    ++arc) {
            arc_a = &state_a->arcs[arc];
            arc_b = &state_b->arcs[arc];
            assert_arc_equal( arc_a, arc_b );
        }
    }
}

variable_types: struct _fst { unsigned int start; unsigned int n_states; unsigned int n_max; unsigned char sr_type; unsigned char flags; struct _state { unsigned int n_arcs; unsigned int n_max; float weight; int final; struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } *arcs; } *states; } *

variable_types:
b
struct _fst *

variable_types:
st
unsigned int

variable_types:
arc
unsigned int


decompiled_code:
_BOOL8 __fastcall states_cmp(unsigned int *a1, unsigned int *a2)
{
float v2; // ebx

v2 = *((float *)W + *a1);
return v2 == sr(*(double *)_mm_cvtsi32_si128(LODWORD(v2)).m128i_i64, *((float *)W + *a2));
}

canonical_decompiled_code:
_BOOL8 __fastcall func0(unsigned int *a1, unsigned int *a2)
{
float v2; // ebx

v2 = *((float *)W + *a1);
return v2 == sr(*(double *)_mm_cvtsi32_si128(LODWORD(v2)).m128i_i64, *((float *)W + *a2));
}

original_code:
static int states_cmp(const void * a, const void * b) {
    return W[*(uint32_t*)a] == sr.sum(
                    W[*(uint32_t*)a],
                    W[*(uint32_t*)b]
    ) ? 1:0;
}

canonical_original_code:
static int states_cmp(void *a, void *b) {
    return W[*(unsigned int *)a] == sr.sum(
                    W[*(unsigned int *)a],
                    W[*(unsigned int *)b]
    ) ? 1:0;
}

variable_types:
a
void *

variable_types:
b
void *


decompiled_code:
__int64 __fastcall states_hash(int *a1)
{
return *a1;
}

canonical_decompiled_code:
__int64 __fastcall func1(int *a1)
{
return *a1;
}

original_code: static size_t states_hash(void * a) { return *(int*)a; }

canonical_original_code: static unsigned long states_hash(void *a) { return *(int *)a; }

return_type: unsigned long


decompiled_code:
_BOOL8 __fastcall states_key_eq(_DWORD *a1, _DWORD *a2)
{
return *a1 == *a2;
}

canonical_decompiled_code:
_BOOL8 __fastcall func2(_DWORD *a1, _DWORD *a2)
{
return *a1 == *a2;
}

original_code:
static int states_key_eq(void * a, void * b) {
    return *(uint32_t*)a == *(uint32_t*)b;
}

canonical_original_code:
static int states_key_eq(void *a, void *b) {
    return *(unsigned int *)a == *(unsigned int *)b;
}


backtrace

decompiled_code:
void *__fastcall backtrace(__int64 a1, unsigned int a2)
{
unsigned int v2; // ebp
unsigned int v3; // ebx
unsigned int v4; // er12
__int64 v5; // rbp
__int64 v6; // rdx
void *result; // rax

v2 = a2;
((void (*)(void))fst_add_state)();
if ( !a2 )
return (void *)fst_set_final(a1, 0LL, *((float *)&qword_3E0 + 1));
v3 = a2;
v4 = 0;
do
{
fst_add_state(a1);
v3 = *((_DWORD *)B + 4 * v3);
++v4;
}
while ( v3 );
fst_set_final(a1, v4, *((float *)&qword_3E0 + 1));
do
{
v5 = 16LL * v2;
v6 = v4--;
fst_add_arc(
a1,
v4,
v6,
*(unsigned int *)((char *)B + v5 + 8),
*(unsigned int *)((char *)B + v5 + 12),
*(float *)((char *)B + v5 + 4));
result = B;
v2 = *(_DWORD *)((char *)B + v5);
}
while ( v2 );
return result;
}

canonical_decompiled_code:
void *__fastcall func3(__int64 a1, unsigned int a2)
{
unsigned int v2; // ebp
unsigned int v3; // ebx
unsigned int v4; // er12
__int64 v5; // rbp
__int64 v6; // rdx
void *result; // rax

v2 = a2;
((void (*)(void))fst_add_state)();
if ( !a2 )
return (void *)fst_set_final(a1, 0LL, *((float *)&qword_3E0 + 1));
v3 = a2;
v4 = 0;
do
{
fst_add_state(a1);
v3 = *((_DWORD *)B + 4 * v3);
++v4;
}
while ( v3 );
fst_set_final(a1, v4, *((float *)&qword_3E0 + 1));
do
{
v5 = 16LL * v2;
v6 = v4--;
fst_add_arc(
a1,
v4,
v6,
*(unsigned int *)((char *)B + v5 + 8),
*(unsigned int *)((char *)B + v5 + 12),
*(float *)((char *)B + v5 + 4));
result = B;
v2 = *(_DWORD *)((char *)B + v5);
}
while ( v2 );
return result;
}

original_code:
static void backtrace(struct _fst * path, uint32_t f) {
    struct _arc arc;
    uint32_t s;
    uint32_t n=0;
    fst_add_state(path);
    for(s=f; s != 0; s=B[s].state, ++n)
        fst_add_state(path);
    fst_set_final(path, n, sr.one);
    for(s=f; s != 0; s=B[s].state, --n) {
        arc=B[s];
        fst_add_arc(path, n-1, n, arc.ilabel, arc.olabel, arc.weight);
    }
}

canonical_original_code:
static void backtrace(struct _fst *path, unsigned int f) {
    struct _arc arc;
    unsigned int s;
    unsigned int n = 0;
    fst_add_state(path);
    for(s=f; s != 0; s=B[s].state, ++n)
        fst_add_state(path);
    fst_set_final(path, n, sr.one);
    for(s=f; s != 0; s=B[s].state, --n) {
        arc=B[s];
        fst_add_arc(path, n-1, n, arc.ilabel, arc.olabel, arc.weight);
    }
}

variable_types:
f
unsigned int

variable_types: struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; }

variable_types:
s
unsigned int

variable_types:
n
unsigned int


decompiled_code:
void __fastcall queue_empty(__int64 a1)
{
void *v1; // rbp

v1 = malloc(*(_QWORD *)(a1 + 16));
while ( queue_deque(a1, v1) )
;
*(_QWORD *)(a1 + 24) = 0LL;
free(v1);
}

canonical_decompiled_code:
void __fastcall func0(__int64 a1)
{
void *v1; // rbp

v1 = malloc(*(_QWORD *)(a1 + 16));
while ( queue_deque(a1, v1) )
;
*(_QWORD *)(a1 + 24) = 0LL;
free(v1);
}

original_code:
void queue_empty(struct _queue * q) {
    void * item = malloc(q->item_size);
    while( queue_deque(q, item) != ((void *)0) );
    q->n_items = 0;
    free (item);
}

canonical_original_code:
void queue_empty(struct _queue *q) {
    void *item = malloc(q->item_size);
    while( queue_deque(q, item) != ((void *)0) );
    q->n_items = 0;
    free (item);
}

variable_types: struct _queue { struct _qnode { struct _qnode *next; char item[1]; } *head; struct _qnode *tail; unsigned long item_size; unsigned long n_items; } *


decompiled_code:
void __fastcall queue_remove(void *ptr)
{
queue_empty((__int64)ptr);
free(ptr);
}

canonical_decompiled_code:
void __fastcall func1(void *ptr)
{
func0((__int64)ptr);
free(ptr);
}

original_code:
void queue_remove(struct _queue * q) {
    queue_empty(q);
    free (q);
}

canonical_original_code:
void queue_remove(struct _queue *q) {
    queue_empty(q);
    free (q);
}


decompiled_code:
void __fastcall fst_get_finals(__int64 a1, __int64 a2)
{
unsigned int v2; // eax
unsigned int v3[7]; // [rsp+Ch] [rbp-1Ch] BYREF

v3[0] = 0;
if ( *(_DWORD *)(a1 + 4) )
{
v2 = 0;
do
{
if ( *(_DWORD *)(*(_QWORD *)(a1 + 16) + 24LL * v2 + 12) )
queue_enque(a2, v3);
v2 = v3[0] + 1;
v3[0] = v2;
}
while ( v2 < *(_DWORD *)(a1 + 4) );
}
}

original_code:
static void fst_get_finals(struct _fst * fst, struct _queue * finals) {
    struct _state * state;
    for (uint32_t s=0; s < fst->n_states; ++s) {
        state = fst->states + s;
        if (state->final)
            queue_enque(finals, &s);
    }
}

canonical_original_code:
static void fst_get_finals(struct _fst *fst, struct _queue *finals) {
    struct _state *state;
    for (unsigned int s = 0; s < fst->n_states; ++s) {
        state = fst->states + s;
        if (state->final)
            queue_enque(finals, &s);
    }
}

variable_types: struct _state { unsigned int n_arcs; unsigned int n_max; float weight; int final; struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } *arcs; } *


decompiled_code:
void __fastcall fst_close(__int64 a1, __int64 a2)
{
__int64 v3; // r12
__int64 v4; // rsi
__int64 v5; // rax
unsigned int v6; // [rsp+0h] [rbp-3Ch] BYREF
char v7[20]; // [rsp+4h] [rbp-38h] BYREF
float v8; // [rsp+18h] [rbp-24h]

if ( *(_QWORD *)(a2 + 24) > 1uLL )
{
sr_get(v7, *(unsigned __int8 *)(a1 + 12));
v3 = (unsigned int)fst_add_state(a1);
fst_set_final(a1, v3, v8);
while ( queue_deque(a2, &v6) )
{
v4 = v6;
v5 = *(_QWORD *)(a1 + 16) + 24LL * v6;
*(_DWORD *)(v5 + 12) = 0;
fst_add_arc(a1, v4, (unsigned int)v3, 0LL, 0LL, *(float *)(v5 + 8));
}
}
}

canonical_decompiled_code:
void __fastcall func1(__int64 a1, __int64 a2)
{
__int64 v3; // r12
__int64 v4; // rsi
__int64 v5; // rax
unsigned int v6; // [rsp+0h] [rbp-3Ch] BYREF
char v7[20]; // [rsp+4h] [rbp-38h] BYREF
float v8; // [rsp+18h] [rbp-24h]

if ( *(_QWORD *)(a2 + 24) > 1uLL )
{
sr_get(v7, *(unsigned __int8 *)(a1 + 12));
v3 = (unsigned int)fst_add_state(a1);
fst_set_final(a1, v3, v8);
while ( queue_deque(a2, &v6) )
{
v4 = v6;
v5 = *(_QWORD *)(a1 + 16) + 24LL * v6;
*(_DWORD *)(v5 + 12) = 0;
fst_add_arc(a1, v4, (unsigned int)v3, 0LL, 0LL, *(float *)(v5 + 8));
}
}
}

original_code:
void fst_close(struct _fst * fst, struct _queue * finals) {
    if ( finals->n_items < 2)
        return;
    struct _state * state;
    struct _sr sr = sr_get(fst->sr_type);
    uint32_t final;
    uint32_t s;
    final = fst_add_state(fst);
    fst_set_final(fst, final, sr.one);
    while(queue_deque(finals, &s) != ((void *)0)) {
        state = &fst->states[s];
        state->final = 0;
        fst_add_arc( fst,
                        s,
                        final,
                        0,
                        0,
                        state->weight);
    }
}

canonical_original_code:
void fst_close(struct _fst *fst, struct _queue *finals) {
    if ( finals->n_items < 2)
        return;
    struct _state *state;
    struct _sr sr = sr_get(fst->sr_type);
    unsigned int final;
    unsigned int s;
    final = fst_add_state(fst);
    fst_set_final(fst, final, sr.one);
    while(queue_deque(finals, &s) != ((void *)0)) {
        state = &fst->states[s];
        state->final = 0;
        fst_add_arc( fst,
                        s,
                        final,
                        0,
                        0,
                        state->weight);
    }
}

variable_types: struct _sr { float (*sum)(float a, float b); float (*prod)(float a, float b); float zero; float one; }

variable_types:
final
unsigned int


decompiled_code:
__int64 __fastcall fst_reverse(unsigned int *a1)
{
__int64 v1; // r14
unsigned int v2; // ebx
unsigned int v3; // eax
_DWORD *v4; // rdx
unsigned int v5; // er12
__int64 v6; // rbp
unsigned int v7; // ebx
float *v8; // rax
float v10[18]; // [rsp+0h] [rbp-48h] BYREF

sr_get(v10, *((unsigned __int8 *)a1 + 12));
v1 = fst_create();
v2 = *a1;
fst_copy(a1, v1);
if ( a1[1] )
{
v3 = 0;
do
{
v4 = (_DWORD *)(*((_QWORD *)a1 + 2) + 24LL * v3);
*v4 = 0;
if ( v4[3] )
{
*a1 = v3;
v4[3] = 0;
}
++v3;
}
while ( a1[1] > v3 );
}
fst_set_final(a1, v2, v10[5]);
if ( *(_DWORD *)(v1 + 4) )
{
v5 = 0;
do
{
v6 = *(_QWORD *)(v1 + 16) + 24LL * v5;
if ( *(_DWORD *)v6 )
{
v7 = 0;
do
{
v8 = (float *)(*(_QWORD *)(v6 + 16) + 16LL * v7);
fst_add_arc(a1, *(unsigned int *)v8, v5, *((unsigned int *)v8 + 2), *((unsigned int *)v8 + 3), v8[1]);
++v7;
}
while ( *(_DWORD *)v6 > v7 );
}
++v5;
}
while ( *(_DWORD *)(v1 + 4) > v5 );
}
return fst_remove(v1);
}

original_code:
void fst_reverse(struct _fst * fst) {
    struct _sr sr = sr_get(fst->sr_type);
    struct _state * state;
    struct _arc * arc;
    struct _fst * orig = fst_create();
    uint32_t s;
    uint32_t start_s = fst->start;
    fst_copy(fst, orig);
    for(s=0; s < fst->n_states; ++s ) {
        state = &fst->states[s];
        state->n_arcs = 0;
        if (state->final) {
            fst->start = s;
            state->final = 0;
        }
    }
    fst_set_final(fst, start_s, sr.one);
    for(s=0; s < orig->n_states; ++s) {
        state = &orig->states[s];
        for(uint32_t a=0; a < state->n_arcs; ++a) {
            arc = &state->arcs[a];
            fst_add_arc( fst,
                            arc->state,
                            s,
                            arc->ilabel,
                            arc->olabel,
                            arc->weight);
        }
    }
    fst_remove(orig);
}

canonical_original_code:
void fst_reverse(struct _fst *fst) {
    struct _sr sr = sr_get(fst->sr_type);
    struct _state *state;
    struct _arc *arc;
    struct _fst *orig = fst_create();
    unsigned int s;
    unsigned int start_s = fst->start;
    fst_copy(fst, orig);
    for(s=0; s < fst->n_states; ++s ) {
        state = &fst->states[s];
        state->n_arcs = 0;
        if (state->final) {
            fst->start = s;
            state->final = 0;
        }
    }
    fst_set_final(fst, start_s, sr.one);
    for(s=0; s < orig->n_states; ++s) {
        state = &orig->states[s];
        for(unsigned int a = 0; a < state->n_arcs; ++a) {
            arc = &state->arcs[a];
            fst_add_arc( fst,
                            arc->state,
                            s,
                            arc->ilabel,
                            arc->olabel,
                            arc->weight);
        }
    }
    fst_remove(orig);
}

variable_types:
a
unsigned int

user_defined_types: struct _sr { float (*sum)(float a, float b); float (*prod)(float a, float b); float zero; float one; }


original_code:
struct _fst * fst_rm_states(struct _fst * fst, struct _bitset * mask) {
    struct _state * state;
    struct _arc * arc;
    uint32_t idx[sizeof(uint32_t) * fst->n_states];
    uint32_t shift = 0;
    for(uint32_t s=0; s < fst->n_states; ++s) {
        if (bitset_get(mask, s) ) {
            ++shift;
        }
        else {
            idx[s] = shift;
            fst->states[s - shift] = fst->states[s];
        }
    }
    fst->n_states -= shift;
    for(uint32_t s=0; s < fst->n_states; ++s) {
        state = &fst->states[s];
        uint32_t sh = 0;
        for(uint32_t a=0; a < state->n_arcs; ++a) {
            arc = &state->arcs[a];
            arc->state -= idx[arc->state];
            if (arc->state >= fst->n_states) {
                ++sh;
            } else {
                state->arcs[a - sh] = state->arcs[a];
            }
        }
        state->n_arcs -= sh;
    }
    return fst;
}

canonical_original_code:
struct _fst *fst_rm_states(struct _fst *fst, struct _bitset *mask) {
    struct _state *state;
    struct _arc *arc;
    unsigned int idx[-1];
    unsigned int shift = 0;
    for(unsigned int s = 0; s < fst->n_states; ++s) {
        if (bitset_get(mask, s) ) {
            ++shift;
        }
        else {
            idx[s] = shift;
            fst->states[s - shift] = fst->states[s];
        }
    }
    fst->n_states -= shift;
    for(unsigned int s = 0; s < fst->n_states; ++s) {
        state = &fst->states[s];
        unsigned int sh = 0;
        for(unsigned int a = 0; a < state->n_arcs; ++a) {
            arc = &state->arcs[a];
            arc->state -= idx[arc->state];
            if (arc->state >= fst->n_states) {
                ++sh;
            } else {
                state->arcs[a - sh] = state->arcs[a];
            }
        }
        state->n_arcs -= sh;
    }
    return fst;
}

variable_types:
fst
struct _fst *

variable_types: struct _bitset { unsigned int *words; int n_words; } *

variable_types:
idx
unsigned int [-1]

variable_types:
shift
unsigned int

variable_types:
sh
unsigned int


decompiled_code:
unsigned int *__fastcall fst_trim(unsigned int *a1)
{
__int64 v1; // r13
unsigned __int64 v2; // rax
__int64 v3; // rbx
__int64 v4; // rbp

v1 = queue_create(4LL);
fst_get_finals((__int64)a1, v1);
v2 = *(_QWORD *)(v1 + 24);
if ( v2 )
{
if ( v2 > 1 )
fst_close((__int64)a1, v1);
v3 = fst_iter_create(a1);
while ( (unsigned int)fst_iter_next(v3) != -1 )
;
fst_reverse(a1);
v4 = fst_iter_create(a1);
while ( (unsigned int)fst_iter_next(v4) != -1 )
;
fst_reverse(a1);
bitset_intersect(*(_QWORD *)(v3 + 8), *(_QWORD *)(v4 + 8));
bitset_toggle_all(*(_QWORD *)(v3 + 8));
fst_rm_states((__int64)a1, *(_QWORD *)(v3 + 8));
fst_iter_remove(v4);
fst_iter_remove(v3);
}
else
{
fst_empty(a1);
}
queue_remove(v1);
return a1;
}

canonical_decompiled_code:
unsigned int *__fastcall func4(unsigned int *a1)
{
__int64 v1; // r13
unsigned __int64 v2; // rax
__int64 v3; // rbx
__int64 v4; // rbp

v1 = queue_create(4LL);
func0((__int64)a1, v1);
v2 = *(_QWORD *)(v1 + 24);
if ( v2 )
{
if ( v2 > 1 )
func1((__int64)a1, v1);
v3 = fst_iter_create(a1);
while ( (unsigned int)fst_iter_next(v3) != -1 )
;
func2(a1);
v4 = fst_iter_create(a1);
while ( (unsigned int)fst_iter_next(v4) != -1 )
;
func2(a1);
bitset_intersect(*(_QWORD *)(v3 + 8), *(_QWORD *)(v4 + 8));
bitset_toggle_all(*(_QWORD *)(v3 + 8));
func3((__int64)a1, *(_QWORD *)(v3 + 8));
fst_iter_remove(v4);
fst_iter_remove(v3);
}
else
{
fst_empty(a1);
}
queue_remove(v1);
return a1;
}

original_code:
struct _fst * fst_trim(struct _fst * fst) {
    struct _queue * finals = queue_create(sizeof(uint32_t));
    fst_get_finals(fst, finals);
    if (finals->n_items == 0) {
        fst_empty(fst);
    } else {
        if (finals->n_items > 1) {
            fst_close(fst, finals);
        }
        struct _fst_iter * iter = fst_iter_create(fst);
        while ( fst_iter_next(iter) != -1 )
            ;
        fst_reverse(fst);
        struct _fst_iter * iter_rev = fst_iter_create(fst);
        while ( fst_iter_next(iter_rev) != -1 )
            ;
        fst_reverse(fst);
        bitset_intersect(iter->marked, iter_rev->marked);
        bitset_toggle_all(iter->marked);
        fst_rm_states(fst, iter->marked);
        fst_iter_remove(iter_rev);
        fst_iter_remove(iter);
    }
    queue_remove(finals);
    return fst;
}

canonical_original_code:
struct _fst *fst_trim(struct _fst *fst) {
    struct _queue *finals = queue_create(sizeof(uint32_t));
    fst_get_finals(fst, finals);
    if (finals->n_items == 0) {
        fst_empty(fst);
    } else {
        if (finals->n_items > 1) {
            fst_close(fst, finals);
        }
        struct _fst_iter *iter = fst_iter_create(fst);
        while ( fst_iter_next(iter) != -1 )
            ;
        fst_reverse(fst);
        struct _fst_iter *iter_rev = fst_iter_create(fst);
        while ( fst_iter_next(iter_rev) != -1 )
            ;
        fst_reverse(fst);
        bitset_intersect(iter->marked, iter_rev->marked);
        bitset_toggle_all(iter->marked);
        fst_rm_states(fst, iter->marked);
        fst_iter_remove(iter_rev);
        fst_iter_remove(iter);
    }
    queue_remove(finals);
    return fst;
}

variable_types: struct _fst_iter { struct _fst { unsigned int start; unsigned int n_states; unsigned int n_max; unsigned char sr_type; unsigned char flags; struct _state { unsigned int n_arcs; unsigned int n_max; float weight; int final; struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } *arcs; } *states; } *fst; struct _bitset { unsigned int *words; int n_words; } *marked; struct _queue { struct _qnode { struct _qnode *next; char item[1]; } *head; struct _qnode *tail; unsigned long item_size; unsigned long n_items; } *queue; unsigned int state; } *


icomp

decompiled_code:
__int64 __fastcall icomp(const void *a1, const void *a2)
{
return (unsigned int)(*((_DWORD *)a1 + 2) - *((_DWORD *)a2 + 2));
}

canonical_decompiled_code:
__int64 __fastcall func0(const void *a1, const void *a2)
{
return (unsigned int)(*((_DWORD *)a1 + 2) - *((_DWORD *)a2 + 2));
}

original_code:
static int icomp(const void *a, const void *b)
{
  return (int) ( ((struct _arc *)a)->ilabel - ((struct _arc *)b)->ilabel );
}

canonical_original_code:
static int icomp(void *a, void *b)
{
  return (int) ( ((struct _arc *)a)->ilabel - ((struct _arc *)b)->ilabel );
}

variable_types:
a
void *


ocomp

decompiled_code:
__int64 __fastcall ocomp(__int64 a1, __int64 a2)
{
return (unsigned int)(*(_DWORD *)(a1 + 12) - *(_DWORD *)(a2 + 12));
}

canonical_decompiled_code:
__int64 __fastcall func1(__int64 a1, __int64 a2)
{
return (unsigned int)(*(_DWORD *)(a1 + 12) - *(_DWORD *)(a2 + 12));
}

original_code:
static int ocomp(const void *a, const void *b)
{
  return (int) ( ((struct _arc *)a)->olabel - ((struct _arc *)b)->olabel );
}

canonical_original_code:
static int ocomp(void *a, void *b)
{
  return (int) ( ((struct _arc *)a)->olabel - ((struct _arc *)b)->olabel );
}

variable_types:
b
void *


decompiled_code:
void __fastcall fst_arc_sort(__int64 a1, int a2)
{
char v2; // al
int (*v3)(const void *, const void *); // r12
unsigned int v4; // ebx
void **v5; // rax

if ( a2 )
{
v2 = *(_BYTE *)(a1 + 13) | 2;
v3 = (int (*)(const void *, const void *))ocomp;
}
else
{
v2 = *(_BYTE *)(a1 + 13) | 1;
v3 = (int (*)(const void *, const void *))icomp;
}
*(_BYTE *)(a1 + 13) = v2;
if ( *(_DWORD *)(a1 + 4) )
{
v4 = 0;
do
{
v5 = (void **)(*(_QWORD *)(a1 + 16) + 24LL * v4);
qsort(v5[2], *(unsigned int *)v5, 0x10uLL, v3);
++v4;
}
while ( *(_DWORD *)(a1 + 4) > v4 );
}
}

canonical_decompiled_code:
void __fastcall func2(__int64 a1, int a2)
{
char v2; // al
int (*v3)(const void *, const void *); // r12
unsigned int v4; // ebx
void **v5; // rax

if ( a2 )
{
v2 = *(_BYTE *)(a1 + 13) | 2;
v3 = (int (*)(const void *, const void *))ocomp;
}
else
{
v2 = *(_BYTE *)(a1 + 13) | 1;
v3 = (int (*)(const void *, const void *))icomp;
}
*(_BYTE *)(a1 + 13) = v2;
if ( *(_DWORD *)(a1 + 4) )
{
v4 = 0;
do
{
v5 = (void **)(*(_QWORD *)(a1 + 16) + 24LL * v4);
qsort(v5[2], *(unsigned int *)v5, 0x10uLL, v3);
++v4;
}
while ( *(_DWORD *)(a1 + 4) > v4 );
}
}

original_code:
void fst_arc_sort(struct _fst * fst, int sort_outer) {
    struct _state * state;
    int (*comp)(const void *, const void *);
    if (sort_outer == 0) {
        comp=icomp;
        fst->flags |= 0x01;
    } else {
        comp=ocomp;
        fst->flags |= 0x02;
    }
    for(uint32_t s = 0; s < fst->n_states; ++s) {
        state = &fst->states[s];
        qsort( state->arcs,
                state->n_arcs,
                sizeof(struct _arc),
                comp );
    }
}

canonical_original_code:
void fst_arc_sort(struct _fst *fst, int sort_outer) {
    struct _state *state;
    int (*comp)(void *, void *);
    if (sort_outer == 0) {
        comp=icomp;
        fst->flags |= 0x01;
    } else {
        comp=ocomp;
        fst->flags |= 0x02;
    }
    for(unsigned int s = 0; s < fst->n_states; ++s) {
        state = &fst->states[s];
        qsort( state->arcs,
                state->n_arcs,
                sizeof(struct _arc),
                comp );
    }
}

variable_types: struct _fst { unsigned int start; unsigned int n_states; unsigned int n_max; unsigned char sr_type; unsigned char flags; struct _state { unsigned int n_arcs; unsigned int n_max; float weight; int final; struct _arc { unsigned int state; float weight; unsigned int ilabel; unsigned int olabel; } *arcs; } *states; } *

variable_types:
comp
int (*)(void *, void *)


original_code:
static void heap_items_swap(struct _heap * heap, size_t i, size_t j) {
    char * items = heap->items;
    size_t s = heap->item_size;
    char * tmp = malloc(s);
    memcpy(tmp, items + i*s, s);
    memcpy(items + i*s, items + j*s, s);
    memcpy(items + j*s, tmp, s);
    if (heap->ht != ((void *)0)) {
        hash_add(heap->ht, items + i*s, &i);
        hash_add(heap->ht, items + j*s, &j);
    }
    free(tmp);
}

canonical_original_code:
static void heap_items_swap(struct _heap *heap, unsigned long i, unsigned long j) {
    char *items = heap->items;
    unsigned long s = heap->item_size;
    char *tmp = malloc(s);
    memcpy(tmp, items + i*s, s);
    memcpy(items + i*s, items + j*s, s);
    memcpy(items + j*s, tmp, s);
    if (heap->ht != ((void *)0)) {
        hash_add(heap->ht, items + i*s, &i);
        hash_add(heap->ht, items + j*s, &j);
    }
    free(tmp);
}

variable_types: struct _heap { unsigned long n_items; unsigned long n_max; unsigned long item_size; unsigned long limit; int (*cmp)(void *a, void *b); struct _hash { struct _bucket { struct _bitem { void *key; void *value; struct _bitem *next; } *head; struct _bitem *tail; } *buckets; unsigned long item_size; unsigned long key_size; unsigned long size; unsigned long n_items; unsigned long (*hash_f)(void *key); int (*cmp_f)(void *key_a, void *key_b); } *ht; char *items; } *

variable_types:
i
unsigned long

variable_types:
j
unsigned long

variable_types:
items
char *

variable_types:
s
unsigned long

variable_types:
tmp
char *

user_defined_types: struct _heap { unsigned long n_items; unsigned long n_max; unsigned long item_size; unsigned long limit; int (*cmp)(void *a, void *b); struct _hash *ht; char *items; }


original_code:
struct _hash * heap_index(struct _heap * heap, hash_func hsh, cmp_func hcmp) {
    if (heap->ht != ((void *)0))
        hash_remove(heap->ht);
    heap->ht = hash_create( hsh,
                            hcmp,
                            heap->item_size,
                            sizeof(size_t),
                            heap->n_max
                        );
    for (size_t i = 0; i < heap->n_items; ++i)
        hash_add(heap->ht, heap->items + i*heap->item_size, &i);
    return heap->ht;
}

canonical_original_code:
struct _hash *heap_index(struct _heap *heap, unsigned long (*hsh)(void *key), int (*hcmp)(void *key_a, void *key_b)) {
    if (heap->ht != ((void *)0))
        hash_remove(heap->ht);
    heap->ht = hash_create( hsh,
                            hcmp,
                            heap->item_size,
                            sizeof(unsigned long),
                            heap->n_max
                        );
    for (unsigned long i = 0; i < heap->n_items; ++i)
        hash_add(heap->ht, heap->items + i*heap->item_size, &i);
    return heap->ht;
}

variable_types: struct _heap { unsigned long n_items; unsigned long n_max; unsigned long item_size; unsigned long limit; int (*cmp)(void *a, void *b); struct _hash *ht; char *items; } *

variable_types:
hsh
unsigned long (*)(void *key)

variable_types:
hcmp
int (*)(void *key_a, void *key_b)

return_type: struct _hash { struct _bucket { struct _bitem { void *key; void *value; struct _bitem *next; } *head; struct _bitem *tail; } *buckets; unsigned long item_size; unsigned long key_size; unsigned long size; unsigned long n_items; unsigned long (*hash_f)(void *key); int (*cmp_f)(void *key_a, void *key_b); } *


decompiled_code:
void __fastcall heap_remove(void *ptr)
{
if ( !ptr )
_assert_fail("heap != NULL", "src/heap.c", 0x5Fu, "heap_remove");
if ( !*((_QWORD *)ptr + 6) )
_assert_fail("heap->items != NULL", "src/heap.c", 0x60u, "heap_remove");
if ( *((_QWORD *)ptr + 5) )
hash_remove();
free(*((void **)ptr + 6));
free(ptr);
}

canonical_decompiled_code:
void __fastcall func2(void *ptr)
{
if ( !ptr )
_assert_fail("heap != NULL", "src/heap.c", 0x5Fu, "heap_remove");
if ( !*((_QWORD *)ptr + 6) )
_assert_fail("heap->items != NULL", "src/heap.c", 0x60u, "heap_remove");
if ( *((_QWORD *)ptr + 5) )
hash_remove();
free(*((void **)ptr + 6));
free(ptr);
}

original_code:
void heap_remove(struct _heap * heap) {
    ((heap != ((void *)0)) ? (void) (0) : __assert_fail ("heap != NULL", "src/heap.c", 95, __extension__ __PRETTY_FUNCTION__));
    ((heap->items != ((void *)0)) ? (void) (0) : __assert_fail ("heap->items != NULL", "src/heap.c", 96, __extension__ __PRETTY_FUNCTION__));
    if (heap->ht != ((void *)0)) {
        hash_remove(heap->ht);
    }
    free(heap->items);
    free(heap);
}

canonical_original_code:
void heap_remove(struct _heap *heap) {
    ((heap != ((void *)0)) ? (void) (0) : __assert_fail ("heap != NULL", "src/heap.c", 95, __extension__ __PRETTY_FUNCTION__));
    ((heap->items != ((void *)0)) ? (void) (0) : __assert_fail ("heap->items != NULL", "src/heap.c", 96, __extension__ __PRETTY_FUNCTION__));
    if (heap->ht != ((void *)0)) {
        hash_remove(heap->ht);
    }
    free(heap->items);
    free(heap);
}


decompiled_code:
void __fastcall heap_heapify(__int64 a1, unsigned __int64 a2)
{
__int64 v2; // rbp
__int64 v3; // r15
__int64 v4; // r14
unsigned __int64 v5; // r13
unsigned __int64 v6; // rbx

v2 = a2;
v3 = *(_QWORD *)(a1 + 48);
v4 = *(_QWORD *)(a1 + 16);
if ( *(_QWORD *)a1 <= a2 )
_assert_fail("i < heap->n_items", "src/heap.c", 0x97u, "heap_heapify");
while ( 1 )
{
v5 = 2 * v2 + 2;
v6 = 2 * v2 + 1;
if ( *(_QWORD *)a1 <= v6
|| !(*(unsigned int (__fastcall **)(unsigned __int64, __int64))(a1 + 32))(v3 + v6 * v4, v3 + v4 * v2) )
{
break;
}
if ( v5 < *(_QWORD *)a1
&& (*(unsigned int (__fastcall **)(unsigned __int64, unsigned __int64))(a1 + 32))(v3 + v4 * v5, v3 + v6 * v4) )
{
goto LABEL_10;
}
LABEL_5:
if ( v2 == v6 )
return;
heap_items_swap((_QWORD *)a1, v2, v6);
v2 = v6;
}
if ( v5 < *(_QWORD *)a1
&& (*(unsigned int (__fastcall **)(unsigned __int64, __int64))(a1 + 32))(v3 + v4 * v5, v3 + v4 * v2) )
{
LABEL_10:
v6 = 2 * v2 + 2;
goto LABEL_5;
}
}

canonical_decompiled_code:
void __fastcall func3(__int64 a1, unsigned __int64 a2)
{
__int64 v2; // rbp
__int64 v3; // r15
__int64 v4; // r14
unsigned __int64 v5; // r13
unsigned __int64 v6; // rbx

v2 = a2;
v3 = *(_QWORD *)(a1 + 48);
v4 = *(_QWORD *)(a1 + 16);
if ( *(_QWORD *)a1 <= a2 )
_assert_fail("i < heap->n_items", "src/heap.c", 0x97u, "heap_heapify");
while ( 1 )
{
v5 = 2 * v2 + 2;
v6 = 2 * v2 + 1;
if ( *(_QWORD *)a1 <= v6
|| !(*(unsigned int (__fastcall **)(unsigned __int64, __int64))(a1 + 32))(v3 + v6 * v4, v3 + v4 * v2) )
{
break;
}
if ( v5 < *(_QWORD *)a1
&& (*(unsigned int (__fastcall **)(unsigned __int64, unsigned __int64))(a1 + 32))(v3 + v4 * v5, v3 + v6 * v4) )
{
goto LABEL_10;
}
LABEL_5:
if ( v2 == v6 )
return;
func0((_QWORD *)a1, v2, v6);
v2 = v6;
}
if ( v5 < *(_QWORD *)a1
&& (*(unsigned int (__fastcall **)(unsigned __int64, __int64))(a1 + 32))(v3 + v4 * v5, v3 + v4 * v2) )
{
LABEL_10:
v6 = 2 * v2 + 2;
goto LABEL_5;
}
}

original_code:
void heap_heapify(struct _heap * heap, size_t i) {
    char * items = heap->items;
    size_t s = heap->item_size;
    size_t l, r, mx;
    int done = 0;
    ((i < heap->n_items) ? (void) (0) : __assert_fail ("i < heap->n_items", "src/heap.c", 151, __extension__ __PRETTY_FUNCTION__));
    while (!done) {
        l = (((i + 1) << 1) - 1);
        r = ((i + 1) << 1);
        mx = ( l < heap->n_items && heap->cmp(items + l*s, items + i*s))
            ? l : i;
        mx = ( r < heap->n_items && heap->cmp(items + r*s, items + mx*s))
            ? r : mx;
        if (mx != i) {
            heap_items_swap(heap, i, mx);
            i = mx;
        } else {
            done=1;
        }
    }
}

canonical_original_code:
void heap_heapify(struct _heap *heap, unsigned long i) {
    char *items = heap->items;
    unsigned long s = heap->item_size;
    unsigned long l; unsigned long r; unsigned long mx;
    int done = 0;
    ((i < heap->n_items) ? (void) (0) : __assert_fail ("i < heap->n_items", "src/heap.c", 151, __extension__ __PRETTY_FUNCTION__));
    while (!done) {
        l = (((i + 1) << 1) - 1);
        r = ((i + 1) << 1);
        mx = ( l < heap->n_items && heap->cmp(items + l*s, items + i*s))
            ? l : i;
        mx = ( r < heap->n_items && heap->cmp(items + r*s, items + mx*s))
            ? r : mx;
        if (mx != i) {
            heap_items_swap(heap, i, mx);
            i = mx;
        } else {
            done=1;
        }
    }
}

variable_types:
l
unsigned long

variable_types:
r
unsigned long

variable_types:
mx
unsigned long

variable_types: done int


original_code:
void * heap_pop(struct _heap * heap, void * item) {
    char * items = heap->items;
    size_t s = heap->item_size;
    if (heap->n_items == 0)
        return ((void *)0);
    memcpy(item, items, s);
    --heap->n_items;
    if (heap->n_items > 0) {
        memcpy(items, items + heap->n_items * s, s);
        size_t i=0;
        if (heap->ht != ((void *)0))
            hash_add(heap->ht, items, &i);
    }
    if (heap->n_items > 1)
        heap_heapify(heap, 0);
    return item;
}

canonical_original_code:
void *heap_pop(struct _heap *heap, void *item) {
    char *items = heap->items;
    unsigned long s = heap->item_size;
    if (heap->n_items == 0)
        return ((void *)0);
    memcpy(item, items, s);
    --heap->n_items;
    if (heap->n_items > 0) {
        memcpy(items, items + heap->n_items * s, s);
        unsigned long i = 0;
        if (heap->ht != ((void *)0))
            hash_add(heap->ht, items, &i);
    }
    if (heap->n_items > 1)
        heap_heapify(heap, 0);
    return item;
}

variable_types:
item
void *