#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <stdio.h>
#include "ppport.h"
typedef
unsigned
short
AM_SHORT;
typedef
unsigned
long
AM_LONG;
typedef
AM_LONG AM_BIG_INT[8];
#define high_bits(x) x >> 16
#define low_bits(x) x & 0xffff
#define carry(var, ind) \
var[ind + 1] += high_bits(var[ind]); \
var[ind] = low_bits(var[ind])
#define carry_pointer(p) \
*(p + 1) += high_bits(*(p + 1)); \
*(p) = low_bits(*(p))
#define carry_replace(var, ind) \
var[ind + 1] = high_bits(var[ind]); \
var[ind] = low_bits(var[ind])
typedef
struct
AM_supra {
AM_SHORT *data;
AM_SHORT count;
AM_SHORT next;
unsigned
char
touched;
} AM_SUPRA;
typedef
struct
AM_guts {
AM_SHORT *lptr[4];
AM_SUPRA *sptr[4];
SV **activeVar;
SV **outcome;
SV **itemcontextchain;
HV *itemcontextchainhead;
HV *subtooutcome;
HV *contextsize;
HV *pointers;
HV *gang;
SV **sum;
IV numoutcomes;
} AM_GUTS;
static
int
AMguts_mgFree(pTHX_ SV *sv, MAGIC *mg) {
int
i;
AM_GUTS *guts = (AM_GUTS *) SvPVX(mg->mg_obj);
for
(i = 0; i < 4; ++i) {
Safefree(guts->lptr[i]);
Safefree(guts->sptr[i][0].data);
Safefree(guts->sptr[i]);
}
return
0;
}
MGVTBL AMguts_vtab = {
NULL,
NULL,
NULL,
NULL,
AMguts_mgFree
};
AM_LONG tens[16];
AM_LONG ones[16];
normalize(SV *s) {
AM_LONG dspace[10];
AM_LONG qspace[10];
char
outspace[55];
AM_LONG *dividend, *quotient, *dptr, *qptr;
char
*outptr;
unsigned
int
outlength = 0;
AM_LONG *p = (AM_LONG *) SvPVX(s);
STRLEN length = SvCUR(s) /
sizeof
(AM_LONG);
long
double
nn = 0;
int
j;
for
(j = 8; j; --j){
nn = 65536.0 * nn + (
double
) *(p + j - 1);
}
dividend = &dspace[0];
quotient = &qspace[0];
Copy(p, dividend, length,
sizeof
(AM_LONG));
outptr = outspace + 54;
while
(1) {
AM_LONG *temp, carry = 0;
while
(length && (*(dividend + length - 1) == 0)) --length;
if
(length == 0) {
sv_setpvn(s, outptr, outlength);
break
;
}
dptr = dividend + length - 1;
qptr = quotient + length - 1;
while
(dptr >= dividend) {
unsigned
int
i;
*dptr += carry << 16;
*qptr = 0;
for
(i = 16; i; ) {
--i;
if
(tens[i] <= *dptr) {
*dptr -= tens[i];
*qptr += ones[i];
}
}
carry = *dptr;
--dptr;
--qptr;
}
--outptr;
*outptr = (
char
) (0x30 + *dividend) & 0x00ff;
++outlength;
temp = dividend;
dividend = quotient;
quotient = temp;
}
SvNVX(s) = nn;
SvNOK_on(s);
}
normalize_debug(SV *s) {
AM_LONG dspace[10];
AM_LONG qspace[10];
char
outspace[55];
AM_LONG *dividend, *quotient, *dptr, *qptr;
char
*outptr;
unsigned
int
outlength = 0;
AM_LONG *p = (AM_LONG *) SvPVX(s);
STRLEN length = SvCUR(s) /
sizeof
(AM_LONG);
long
double
nn = 0;
int
j;
fprintf
(stderr,
"--------\n"
);
for
(j = 8; j; --j){
nn = 65536.0 * nn + (
double
) *(p + j - 1);
fprintf
(stderr,
"%lu\n"
, *(p + j - 1));
}
dividend = &dspace[0];
quotient = &qspace[0];
Copy(p, dividend, length,
sizeof
(AM_LONG));
outptr = outspace + 54;
while
(1) {
AM_LONG *temp, carry = 0;
while
(length && (*(dividend + length - 1) == 0)) --length;
if
(length == 0) {
sv_setpvn(s, outptr, outlength);
break
;
}
dptr = dividend + length - 1;
qptr = quotient + length - 1;
while
(dptr >= dividend) {
unsigned
int
i;
*dptr += carry << 16;
*qptr = 0;
for
(i = 16; i; ) {
--i;
if
(tens[i] <= *dptr) {
*dptr -= tens[i];
*qptr += ones[i];
}
}
carry = *dptr;
--dptr;
--qptr;
}
--outptr;
*outptr = (
char
) (0x30 + *dividend) & 0x00ff;
++outlength;
temp = dividend;
dividend = quotient;
quotient = temp;
}
SvNVX(s) = nn;
SvNOK_on(s);
}
MODULE = Algorithm::AM PACKAGE = Algorithm::AM
BOOT:
{
AM_LONG ten = 10;
AM_LONG one = 1;
AM_LONG *tensptr = &tens[0];
AM_LONG *onesptr = &ones[0];
unsigned
int
i;
for
(i = 16; i; i--) {
*tensptr = ten;
*onesptr = one;
++tensptr;
++onesptr;
ten <<= 1;
one <<= 1;
}
}
void
_initialize(...)
PREINIT:
HV *project;
AM_GUTS guts;
SV *svguts;
MAGIC *mg;
int
i;
PPCODE:
project = (HV *) SvRV(ST(0));
guts.activeVar = AvARRAY((AV *) SvRV(ST(1)));
guts.outcome = AvARRAY((AV *) SvRV(ST(2)));
guts.itemcontextchain = AvARRAY((AV *) SvRV(ST(3)));
guts.itemcontextchainhead = (HV *) SvRV(ST(4));
guts.subtooutcome = (HV *) SvRV(ST(5));
guts.contextsize = (HV *) SvRV(ST(6));
guts.pointers = (HV *) SvRV(ST(7));
guts.gang = (HV *) SvRV(ST(8));
guts.sum = AvARRAY((AV *) SvRV(ST(9)));
guts.numoutcomes = av_len((AV *) SvRV(ST(9)));
for
(i = 0; i < 4; ++i) {
UV v = SvUVX(guts.activeVar[i]);
Newz(0, guts.lptr[i], 1 << v, AM_SHORT);
Newz(0, guts.sptr[i], 1 << (v + 1), AM_SUPRA);
Newz(0, guts.sptr[i][0].data, 2, AM_SHORT);
}
svguts = newSVpv((
char
*) &guts,
sizeof
(AM_GUTS));
sv_magic((SV *) project, svguts, PERL_MAGIC_ext, NULL, 0);
SvRMAGICAL_off((SV *) project);
mg = mg_find((SV *) project, PERL_MAGIC_ext);
mg->mg_virtual = &AMguts_vtab;
mg_magical((SV *) project);
void
_fillandcount(...)
PREINIT:
HV *project;
AM_GUTS *guts;
MAGIC *mg;
AM_SHORT activeVar[4];
AM_SHORT **lptr;
AM_SUPRA **sptr;
AM_SHORT nptr[4];
AM_SHORT subcontextnumber;
AM_SHORT *subcontext;
AM_SHORT *suboutcome;
SV **outcome, **itemcontextchain, **sum;
HV *itemcontextchainhead, *subtooutcome, *contextsize, *pointers, *gang;
IV numoutcomes;
HE *he;
AM_BIG_INT grandtotal = {0, 0, 0, 0, 0, 0, 0, 0};
SV *tempsv;
int
chunk, i;
AM_SHORT gaps[16];
AM_SHORT *intersect, *intersectlist;
AM_SHORT *intersectlist2, *intersectlist3, *ilist2top, *ilist3top;
PPCODE:
project = (HV *) SvRV(ST(0));
mg = mg_find((SV *) project, PERL_MAGIC_ext);
guts = (AM_GUTS *) SvPVX(mg->mg_obj);
lptr = guts->lptr;
sptr = guts->sptr;
for
(chunk = 0; chunk < 4; ++chunk) {
activeVar[chunk] = (AM_SHORT) SvUVX(guts->activeVar[chunk]);
Zero(lptr[chunk], 1 << activeVar[chunk], AM_SHORT);
sptr[chunk][0].next = 0;
nptr[chunk] = 1;
for
(i = 1; i < 1 << (activeVar[chunk] + 1); ++i)
sptr[chunk][i].next = (AM_SHORT) i + 1;
}
subtooutcome = guts->subtooutcome;
subcontextnumber = (AM_SHORT) HvUSEDKEYS(subtooutcome);
Newz(0, subcontext, 4 * (subcontextnumber + 1), AM_SHORT);
subcontext += 4 * subcontextnumber;
Newz(0, suboutcome, subcontextnumber + 1, AM_SHORT);
suboutcome += subcontextnumber;
Newz(0, intersectlist, subcontextnumber + 1, AM_SHORT);
Newz(0, intersectlist2, subcontextnumber + 1, AM_SHORT);
ilist2top = intersectlist2 + subcontextnumber;
Newz(0, intersectlist3, subcontextnumber + 1, AM_SHORT);
ilist3top = intersectlist3 + subcontextnumber;
hv_iterinit(subtooutcome);
while
(he = hv_iternext(subtooutcome)) {
AM_SHORT *contextptr = (AM_SHORT *) HeKEY(he);
AM_SHORT outcome = (AM_SHORT) SvUVX(HeVAL(he));
for
(chunk = 0; chunk < 4; ++chunk, ++contextptr) {
AM_SHORT active = activeVar[chunk];
AM_SHORT *lattice = lptr[chunk];
AM_SUPRA *supralist = sptr[chunk];
AM_SHORT nextsupra = nptr[chunk];
AM_SHORT context = *contextptr;
AM_SUPRA *p, *c;
AM_SHORT pi, ci;
AM_SHORT d, t, tt, numgaps = 0;
subcontext[chunk] = context;
if
(context == 0) {
for
(p = supralist + supralist->next;
p != supralist; p = supralist + p->next) {
AM_SHORT *data;
Newz(0, data, p->data[0] + 3, AM_SHORT);
Copy(p->data + 2, data + 3, p->data[0], AM_SHORT);
data[2] = subcontextnumber;
data[0] = p->data[0] + 1;
Safefree(p->data);
p->data = data;
}
if
(lattice[context] == 0) {
AM_SHORT count = 0;
ci = nptr[chunk];
nptr[chunk] = supralist[ci].next;
c = supralist + ci;
c->next = supralist->next;
supralist->next = ci;
Newz(0, c->data, 3, AM_SHORT);
c->data[2] = subcontextnumber;
c->data[0] = 1;
for
(i = 0; i < (1 << active); ++i) {
if
(lattice[i] == 0) {
lattice[i] = ci;
++count;
}
}
c->count = count;
}
continue
;
}
d = context;
for
(i = 1 << (active - 1); i; i >>= 1)
if
(!(i & context))
gaps[numgaps++] = i;
t = 1 << numgaps;
p = supralist + (pi = lattice[context]);
if
(pi) --(p->count);
ci = nextsupra;
nextsupra = supralist[ci].next;
p->touched = 1;
c = supralist + ci;
c->touched = 0;
c->next = p->next;
p->next = ci;
c->count = 1;
Newz(0, c->data, p->data[0] + 3, AM_SHORT);
Copy(p->data + 2, c->data + 3, p->data[0], AM_SHORT);
c->data[2] = subcontextnumber;
c->data[0] = p->data[0] + 1;
lattice[context] = ci;
while
(--t) {
for
(i = 0, tt = ~t & (t - 1); tt; tt >>= 1, ++i);
d ^= gaps[i];
p = supralist + (pi = lattice[d]);
if
(pi) --(p->count);
switch
(p->touched) {
case
1:
++supralist[lattice[d] = p->next].count;
break
;
case
0:
ci = nextsupra;
nextsupra = supralist[ci].next;
p->touched = 1;
c = supralist + ci;
c->touched = 0;
c->next = p->next;
p->next = ci;
c->count = 1;
Newz(0, c->data, p->data[0] + 3, AM_SHORT);
Copy(p->data + 2, c->data + 3, p->data[0], AM_SHORT);
c->data[2] = subcontextnumber;
c->data[0] = p->data[0] + 1;
lattice[d] = ci;
}
}
p = supralist;
p->touched = 0;
do
{
if
(supralist[i = p->next].count == 0) {
Safefree(supralist[i].data);
p->next = supralist[i].next;
supralist[i].next = nextsupra;
nextsupra = (AM_SHORT) i;
}
else
{
p = supralist + p->next;
p->touched = 0;
}
}
while
(p->next);
nptr[chunk] = nextsupra;
}
subcontext -= 4;
*suboutcome = outcome;
--suboutcome;
--subcontextnumber;
}
contextsize = guts->contextsize;
pointers = guts->pointers;
if
(SvUVX(ST(1))) {
AM_SUPRA *p0, *p1, *p2, *p3;
AM_SHORT outcome;
AM_SHORT length;
unsigned
short
*temp, *i, *j, *k;
for
(p0 = sptr[0] + sptr[0]->next; p0 != sptr[0]; p0 = sptr[0] + p0->next) {
for
(p1 = sptr[1] + sptr[1]->next; p1 != sptr[1]; p1 = sptr[1] + p1->next) {
i = p0->data + p0->data[0] + 1;
j = p1->data + p1->data[0] + 1;
k = ilist2top;
while
(1) {
while
(*i > *j) --i;
if
(*i == 0)
break
;
if
(*i < *j) {
temp = i;
i = j;
j = temp;
continue
;
}
*k = *i;
--i;
--j;
--k;
}
if
(k == ilist2top)
continue
;
*k = 0;
for
(p2 = sptr[2] + sptr[2]->next; p2 != sptr[2]; p2 = sptr[2] + p2->next) {
i = ilist2top;
j = p2->data + p2->data[0] + 1;
k = ilist3top;
while
(1) {
while
(*i > *j) --i;
if
(*i == 0)
break
;
if
(*i < *j) {
temp = i;
i = j;
j = temp;
continue
;
}
*k = *i;
--i;
--j;
--k;
}
if
(k == ilist3top)
continue
;
*k = 0;
for
(p3 = sptr[3] + sptr[3]->next; p3 != sptr[3]; p3 = sptr[3] + p3->next) {
outcome = 0;
length = 0;
intersect = intersectlist;
i = ilist3top;
j = p3->data + p3->data[0] + 1;
while
(1) {
while
(*i > *j) --i;
if
(*i == 0)
break
;
if
(*i < *j) {
temp = i;
i = j;
j = temp;
continue
;
}
*intersect = *i;
++intersect;
++length;
if
(outcome == 0) {
if
(length > 1) {
length = 0;
break
;
}
else
{
outcome = suboutcome[*i];
}
}
else
{
if
(outcome != suboutcome[*i]) {
length = 0;
break
;
}
}
--i;
--j;
}
if
(length) {
AM_SHORT i;
AM_LONG pointercount = 0;
AM_BIG_INT count = {0, 0, 0, 0, 0, 0, 0, 0};
AM_LONG mask = 0xffff;
count[0] = p0->count;
count[0] *= p1->count;
carry(count, 0);
count[0] *= p2->count;
count[1] *= p2->count;
carry(count, 0);
carry(count, 1);
count[0] *= p3->count;
count[1] *= p3->count;
count[2] *= p3->count;
carry(count, 0);
carry(count, 1);
carry(count, 2);
for
(i = 0; i < length; ++i)
pointercount += (AM_LONG)
SvUV(*hv_fetch(contextsize,
(
char
*) (subcontext + (4 * intersectlist[i])),
8, 0));
if
(pointercount & 0xffff0000) {
AM_SHORT pchi = (AM_SHORT) (high_bits(pointercount));
AM_SHORT pclo = (AM_SHORT) (low_bits(pointercount));
AM_LONG hiprod[6];
hiprod[1] = pchi * count[0];
hiprod[2] = pchi * count[1];
hiprod[3] = pchi * count[2];
hiprod[4] = pchi * count[3];
count[0] *= pclo;
count[1] *= pclo;
count[2] *= pclo;
count[3] *= pclo;
carry(count, 0);
carry(count, 1);
carry(count, 2);
carry(count, 3);
count[1] += hiprod[1];
count[2] += hiprod[2];
count[3] += hiprod[3];
count[4] += hiprod[4];
carry(count, 1);
carry(count, 2);
carry(count, 3);
carry(count, 4);
}
else
{
count[0] *= pointercount;
count[1] *= pointercount;
count[2] *= pointercount;
count[3] *= pointercount;
carry(count, 0);
carry(count, 1);
carry(count, 2);
carry(count, 3);
}
for
(i = 0; i < length; ++i) {
int
j;
SV *tempsv;
AM_LONG *p;
tempsv = *hv_fetch(pointers,
(
char
*) (subcontext + (4 * intersectlist[i])),
8, 1);
if
(!SvPOK(tempsv)) {
SvUPGRADE(tempsv, SVt_PVNV);
SvGROW(tempsv, 8 *
sizeof
(AM_LONG) + 1);
Zero(SvPVX(tempsv), 8, AM_LONG);
SvCUR_set(tempsv, 8 *
sizeof
(AM_LONG));
SvPOK_on(tempsv);
}
p = (AM_LONG *) SvPVX(tempsv);
for
(j = 0; j < 7; ++j) {
*(p + j) += count[j];
carry_pointer(p + j);
}
}
}
}
}
}
}
for
(p0 = sptr[0] + sptr[0]->next; p0 != sptr[0]; p0 = sptr[0] + p0->next)
Safefree(p0->data);
for
(p1 = sptr[1] + sptr[1]->next; p1 != sptr[1]; p1 = sptr[1] + p1->next)
Safefree(p1->data);
for
(p2 = sptr[2] + sptr[2]->next; p2 != sptr[2]; p2 = sptr[2] + p2->next)
Safefree(p2->data);
for
(p3 = sptr[3] + sptr[3]->next; p3 != sptr[3]; p3 = sptr[3] + p3->next)
Safefree(p3->data);
}
else
{
AM_SUPRA *p0, *p1, *p2, *p3;
AM_SHORT outcome;
AM_SHORT length;
unsigned
short
*temp, *i, *j, *k;
for
(p0 = sptr[0] + sptr[0]->next; p0 != sptr[0]; p0 = sptr[0] + p0->next) {
for
(p1 = sptr[1] + sptr[1]->next; p1 != sptr[1]; p1 = sptr[1] + p1->next) {
i = p0->data + p0->data[0] + 1;
j = p1->data + p1->data[0] + 1;
k = ilist2top;
while
(1) {
while
(*i > *j) --i;
if
(*i == 0)
break
;
if
(*i < *j) {
temp = i;
i = j;
j = temp;
continue
;
}
*k = *i;
--i;
--j;
--k;
}
if
(k == ilist2top)
continue
;
*k = 0;
for
(p2 = sptr[2] + sptr[2]->next; p2 != sptr[2]; p2 = sptr[2] + p2->next) {
i = ilist2top;
j = p2->data + p2->data[0] + 1;
k = ilist3top;
while
(1) {
while
(*i > *j) --i;
if
(*i == 0)
break
;
if
(*i < *j) {
temp = i;
i = j;
j = temp;
continue
;
}
*k = *i;
--i;
--j;
--k;
}
if
(k == ilist3top)
continue
;
*k = 0;
for
(p3 = sptr[3] + sptr[3]->next; p3 != sptr[3]; p3 = sptr[3] + p3->next) {
outcome = 0;
length = 0;
intersect = intersectlist;
i = ilist3top;
j = p3->data + p3->data[0] + 1;
while
(1) {
while
(*i > *j) --i;
if
(*i == 0)
break
;
if
(*i < *j) {
temp = i;
i = j;
j = temp;
continue
;
}
*intersect = *i;
++intersect;
++length;
if
(outcome == 0) {
if
(length > 1) {
length = 0;
break
;
}
else
{
outcome = suboutcome[*i];
}
}
else
{
if
(outcome != suboutcome[*i]) {
length = 0;
break
;
}
}
--i;
--j;
}
if
(length) {
AM_SHORT i;
AM_BIG_INT count = {0, 0, 0, 0, 0, 0, 0, 0};
AM_LONG mask = 0xffff;
count[0] = p0->count;
count[0] *= p1->count;
carry(count, 0);
count[0] *= p2->count;
count[1] *= p2->count;
carry(count, 0);
carry(count, 1);
count[0] *= p3->count;
count[1] *= p3->count;
count[2] *= p3->count;
carry(count, 0);
carry(count, 1);
carry(count, 2);
for
(i = 0; i < length; ++i) {
int
j;
SV *tempsv;
AM_LONG *p;
tempsv = *hv_fetch(pointers,
(
char
*) (subcontext + (4 * intersectlist[i])),
8, 1);
if
(!SvPOK(tempsv)) {
SvUPGRADE(tempsv, SVt_PVNV);
SvGROW(tempsv, 8 *
sizeof
(AM_LONG) + 1);
Zero(SvPVX(tempsv), 8, AM_LONG);
SvCUR_set(tempsv, 8 *
sizeof
(AM_LONG));
SvPOK_on(tempsv);
}
p = (AM_LONG *) SvPVX(tempsv);
for
(j = 0; j < 7; ++j) {
*(p + j) += count[j];
carry_pointer(p + j);
}
}
}
}
}
}
}
for
(p0 = sptr[0] + sptr[0]->next; p0 != sptr[0]; p0 = sptr[0] + p0->next)
Safefree(p0->data);
for
(p1 = sptr[1] + sptr[1]->next; p1 != sptr[1]; p1 = sptr[1] + p1->next)
Safefree(p1->data);
for
(p2 = sptr[2] + sptr[2]->next; p2 != sptr[2]; p2 = sptr[2] + p2->next)
Safefree(p2->data);
for
(p3 = sptr[3] + sptr[3]->next; p3 != sptr[3]; p3 = sptr[3] + p3->next)
Safefree(p3->data);
}
gang = guts->gang;
outcome = guts->outcome;
itemcontextchain = guts->itemcontextchain;
itemcontextchainhead = guts->itemcontextchainhead;
sum = guts->sum;
numoutcomes = guts->numoutcomes;
hv_iterinit(pointers);
while
(he = hv_iternext(pointers)) {
AM_LONG count;
AM_SHORT counthi, countlo;
AM_BIG_INT p;
AM_BIG_INT gangcount;
AM_SHORT thisoutcome;
SV *dataitem;
Copy(SvPVX(HeVAL(he)), p, 8, AM_LONG);
fprintf
(stderr,
"value of p for %s:\n"
, HeKEY(he));
for
(i = 0; i < 8; i++)
fprintf
(stderr,
"%lu\n"
, p[i]);
tempsv = *hv_fetch(contextsize, HeKEY(he), 4 *
sizeof
(AM_SHORT), 0);
count = (AM_LONG) SvUVX(tempsv);
counthi = (AM_SHORT) (high_bits(count));
countlo = (AM_SHORT) (low_bits(count));
fprintf
(stderr,
"countlo: %hu\n"
, countlo);
fprintf
(stderr,
"counthi: %hu\n"
, counthi);
fprintf
(stderr,
"gangcount 1:\n--------\n"
);
gangcount[0] = 0;
for
(i = 0; i < 6; ++i) {
fprintf
(stderr,
"before: %lu\n"
, gangcount[i]);
gangcount[i] += countlo * p[i];
carry_replace(gangcount, i);
fprintf
(stderr,
"after: %lu\n"
, gangcount[i]);
}
fprintf
(stderr,
"gangcount 2:\n--------\n"
);
if
(counthi) {
for
(i = 0; i < 6; ++i) {
fprintf
(stderr,
"before: %lu\n"
, gangcount[i]);
gangcount[i + 1] += counthi * p[i];
carry(gangcount, i + 1);
fprintf
(stderr,
"after: %lu\n"
, gangcount[i]);
}
}
fprintf
(stderr,
"grandtotal 3:\n--------\n"
);
for
(i = 0; i < 7; ++i) {
fprintf
(stderr,
"before: %lu\n"
, grandtotal[i]);
grandtotal[i] += gangcount[i];
carry(grandtotal, i);
fprintf
(stderr,
"after: %lu\n"
, grandtotal[i]);
}
fprintf
(stderr,
"before: %lu\n"
, grandtotal[i]);
grandtotal[7] += gangcount[7];
fprintf
(stderr,
"after: %lu\n"
, grandtotal[i]);
tempsv = *hv_fetch(gang, HeKEY(he), 4 *
sizeof
(AM_SHORT), 1);
SvUPGRADE(tempsv, SVt_PVNV);
sv_setpvn(tempsv, (
char
*) gangcount, 8 *
sizeof
(AM_LONG));
normalize(tempsv);
normalize(HeVAL(he));
tempsv = *hv_fetch(subtooutcome, HeKEY(he), 4 *
sizeof
(AM_SHORT), 0);
thisoutcome = (AM_SHORT) SvUVX(tempsv);
if
(thisoutcome) {
AM_LONG *s = (AM_LONG *) SvPVX(sum[thisoutcome]);
for
(i = 0; i < 7; ++i) {
*(s + i) += gangcount[i];
carry_pointer(s + i);
}
}
else
{
dataitem = *hv_fetch(itemcontextchainhead, HeKEY(he), 4 *
sizeof
(AM_SHORT), 0);
while
(SvIOK(dataitem)) {
IV datanum = SvIVX(dataitem);
IV ocnum = SvIVX(outcome[datanum]);
AM_LONG *s = (AM_LONG *) SvPVX(sum[ocnum]);
for
(i = 0; i < 7; ++i) {
*(s + i) += p[i];
carry_pointer(s + i);
dataitem = itemcontextchain[datanum];
}
}
}
}
for
(i = 1; i <= numoutcomes; ++i) normalize(sum[i]);
tempsv = *hv_fetch(pointers,
"grandtotal"
, 10, 1);
SvUPGRADE(tempsv, SVt_PVNV);
sv_setpvn(tempsv, (
char
*) grandtotal, 8 *
sizeof
(AM_LONG));
fprintf
(stderr,
"normalizing grandtotal\n"
);
normalize_debug(tempsv);
Safefree(subcontext);
Safefree(suboutcome);
Safefree(intersectlist);
Safefree(intersectlist2);
Safefree(intersectlist3);