1
/*------------------------------------------------------------------------------------------------------
2
Builds a library of functions-calls for applying HRR and VRR
3
------------------------------------------------------------------------------------------------------*/
8
#include "build_libint.h"
10
#define NONODE -1000000
11
#define SSSSNODE -1111
13
static int last_hrr_node = 0; /* Global pointer to the last node on the HRR stack */
14
static int last_vrr_node = 0; /* Global pointer to the last node on the VRR stack */
16
extern FILE *outfile, *hrr_header, *init_code;
17
extern int libint_stack_size[MAX_AM/2+1];
18
extern LibintParams_t Params;
20
typedef struct hrr_node{
21
int A, B, C, D; /* Angular momenta on centers A and C */
22
int size; /* Class size in double words */
24
int children[2]; /* Up to 5 children of the class */
26
int num_parents; /* Number of parents */
27
int parents[5]; /* Pointers to parents */
28
int llink; /* Pointer to a class computed right before computing this one */
29
int rlink; /* Pointer to a class to be computed after this one is */
30
int marked; /* Flag indicating that this node has been computed */
31
int target; /* Flag indicating that this node is among targets */
34
typedef struct vrr_node{
35
int A, C; /* Angular momenta on centers A and C */
36
int m; /* Auxiliary index */
37
int size; /* Class size in double words */
39
int children[5]; /* Up to 5 children of the class */
41
int num_parents; /* Number of parents */
42
int parents[9]; /* Pointers to parents */
43
int llink; /* Pointer to a class computed right before computing this one */
44
int rlink; /* Pointer to a class to be computed after this one is */
50
static int first_hrr_to_compute = 0; /* Number of the first class to be computed
51
(pointer to the beginning of the linked list) */
52
static int first_vrr_to_compute = 0; /* Number of the first class to be computed
53
(pointer to the beginning of the linked list) */
55
static int hrr_hash_table[MAX_AM+1][MAX_AM+1][MAX_AM+1][MAX_AM+1];
56
static int vrr_hash_table[MAX_AM+1][MAX_AM+1][2*MAX_AM+1];
60
int old_am = Params.old_am;
61
int new_am = Params.new_am;
62
int opt_am = Params.opt_am;
63
int am_to_inline_into_hrr = Params.max_am_to_inline_vrr_manager;
64
int am_to_inline_vrr = Params.max_am_manager_to_inline_vrr_worker;
65
int am_to_inline_hrr = Params.max_am_manager_to_inline_hrr_worker;
66
int to_inline_into_hrr, to_inline_vrr, to_inline_hrr;
69
int la, lc, lc_min, ld, ld_max, ld_min;
70
int lb, lb_min, lb_max;
71
int current_highest_am, max_node_am;
72
int base_mem, hrr_mem, vrr_mem;
73
hrr_class hrr_nodes[MAXNODE]; /* Stack of HRR nodes */
74
vrr_class vrr_nodes[MAXNODE]; /* Stack of VRR nodes */
77
int max_stack_size = 0;
79
int target_vrr_nodes[MAX_AM*MAX_AM];
80
const char am_letter[] = "0pdfghiklmnoqrtuvwxyz";
81
char hrr_code_name[] = "hrr_order_0000.cc";
82
char hrr_function_name[] = "hrr_order_0000";
83
char vrr_code_name[] = "vrr_order_0000.cc";
84
char vrr_function_name[] = "vrr_order_0000";
85
char inline_vrr_list_name[] = "inline_vrr_order_0000.h";
86
char inline_hrr_list_name[] = "inline_hrr_order_0000.h";
87
FILE *hrr_code, *vrr_code, *inline_vrr_list, *inline_hrr_list;
88
static int io[] = {1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210};
90
for(la=0;la<=new_am;la++) {
92
lb_min = (la <= new_am/2) ? 0 : la - new_am/2;
93
lc_min = (la == 0) ? 1 : la;
94
for(lb=lb_min;lb<=lb_max;lb++) {
95
for(lc=lc_min;lc<=new_am;lc++) {
97
ld_min = (lc <= new_am/2) ? 0 : lc - new_am/2;
98
for(ld=ld_min;ld<=ld_max;ld++) {
100
current_highest_am = (la-lb > lb) ? la-lb : lb;
101
current_highest_am = (current_highest_am > lc-ld) ? current_highest_am : lc-ld;
102
current_highest_am = (current_highest_am > ld) ? current_highest_am : ld;
103
to_inline_into_hrr = (current_highest_am <= am_to_inline_into_hrr) ? 1 : 0;
104
to_inline_vrr = (current_highest_am <= am_to_inline_vrr) ? 1 : 0;
105
to_inline_hrr = (current_highest_am <= am_to_inline_hrr) ? 1 : 0;
107
/*---------------------------------------------------------------
108
Form code and function names for HRR and VRR ordering routines
109
---------------------------------------------------------------*/
110
sprintf(hrr_function_name,"hrr_order_%c%c%c%c",
111
am_letter[la-lb],am_letter[lb],
112
am_letter[lc-ld],am_letter[ld]);
113
sprintf(vrr_function_name,"vrr_order_%c%c%c%c",
114
am_letter[la-lb],am_letter[lb],
115
am_letter[lc-ld],am_letter[ld]);
116
sprintf(hrr_code_name,"%s.cc",hrr_function_name);
117
if (to_inline_into_hrr)
118
sprintf(vrr_code_name,"%s.h",vrr_function_name);
120
sprintf(vrr_code_name,"%s.cc",vrr_function_name);
121
sprintf(inline_vrr_list_name,"inline_vrr_order_%c%c%c%c.h",
122
am_letter[la-lb],am_letter[lb],
123
am_letter[lc-ld],am_letter[ld]);
124
sprintf(inline_hrr_list_name,"inline_hrr_order_%c%c%c%c.h",
125
am_letter[la-lb],am_letter[lb],
126
am_letter[lc-ld],am_letter[ld]);
127
hrr_code = fopen(hrr_code_name,"w");
128
vrr_code = fopen(vrr_code_name,"w");
129
inline_vrr_list = fopen(inline_vrr_list_name,"w");
130
inline_hrr_list = fopen(inline_hrr_list_name,"w");
132
/*-----------------------------------
133
Write the overhead to the HRR code
134
-----------------------------------*/
135
fprintf(hrr_code,"#include <stdio.h>\n");
136
fprintf(hrr_code,"#include <string.h>\n");
137
fprintf(hrr_code,"#include \"libint.h\"\n");
139
fprintf(hrr_code,"#define INLINE_HRR_WORKER\n");
140
fprintf(hrr_code,"#include \"%s\"\n",inline_hrr_list_name);
142
fprintf(hrr_code,"#include \"hrr_header.h\"\n\n");
143
if (to_inline_into_hrr)
144
fprintf(hrr_code,"#include \"%s\"\n",vrr_code_name);
146
fprintf(hrr_code,"extern void vrr_order_%c%c%c%c(Libint_t*, prim_data*);\n\n",
147
am_letter[la-lb],am_letter[lb],am_letter[lc-ld],am_letter[ld]);
148
fprintf(hrr_code," /* Computes quartets of (%c%c|%c%c) integrals */\n\n",
149
am_letter[la-lb],am_letter[lb],am_letter[lc-ld],am_letter[ld]);
150
fprintf(hrr_code,"REALTYPE *%s(Libint_t *Libint, int num_prim_comb)\n{\n",hrr_function_name);
151
fprintf(hrr_code," prim_data *Data = Libint->PrimQuartet;\n");
152
fprintf(hrr_code," REALTYPE *int_stack = Libint->int_stack;\n");
153
fprintf(hrr_code," int i;\n\n");
155
/*-------------------------------------------------------------
156
Include the function into the hrr_header.h and init_libint.c
157
-------------------------------------------------------------*/
158
fprintf(hrr_header,"REALTYPE *%s(Libint_t *, int);\n",hrr_function_name);
159
fprintf(init_code," build_eri[%d][%d][%d][%d] = %s;\n",la-lb,lb,lc-ld,ld,hrr_function_name);
161
/*-----------------------------------
162
Write the overhead to the VRR code
163
-----------------------------------*/
164
fprintf(vrr_code,"#include <stdio.h>\n");
165
fprintf(vrr_code,"#include \"libint.h\"\n");
167
fprintf(vrr_code,"#define INLINE_VRR_WORKER\n");
168
fprintf(vrr_code,"#include \"%s\"\n",inline_vrr_list_name);
170
fprintf(vrr_code,"#include \"vrr_header.h\"\n\n");
171
fprintf(vrr_code," /* Computes quartets necessary to compute (%c%c|%c%c) integrals */\n\n",
172
am_letter[la-lb],am_letter[lb],am_letter[lc-ld],am_letter[ld]);
173
if (to_inline_into_hrr)
174
fprintf(vrr_code,"inline ");
175
fprintf(vrr_code,"void %s(Libint_t * Libint, prim_data *Data)\n{\n",vrr_function_name);
177
/*----------------------------
178
Zero out the hashing tables
179
----------------------------*/
180
for(i=0;i<=MAX_AM;i++)
181
for(j=0;j<=MAX_AM;j++) {
182
memset(vrr_hash_table[i][j],0,(2*MAX_AM+1)*sizeof(int));
183
for(k=0;k<=MAX_AM;k++)
184
memset(hrr_hash_table[i][j][k],0,(MAX_AM+1)*sizeof(int));
190
hrr_nodes[0].A = la-lb;
192
hrr_nodes[0].C = lc-ld;
194
hrr_nodes[0].llink = -1;
195
hrr_nodes[0].rlink = -1;
196
first_hrr_to_compute = 0;
198
mk_hrr_node(hrr_nodes[0], hrr_nodes, 0);
199
hrr_nodes[0].target = 1;
201
/*-------------------------------------------
202
Traverse the graph starting at each target
203
-------------------------------------------*/
205
if(hrr_nodes[0].children[k]>0)
206
mark_hrr_parents(hrr_nodes[0].children[k], hrr_nodes, 0);
208
/*-----------------------------------------------------------------
209
Empirical rule as with what heap size to start memory allocation
210
-----------------------------------------------------------------*/
213
/*---------------------------------------------------------------
214
Allocate and zero out space for classes to be generated by VRR
215
---------------------------------------------------------------*/
216
for(i=last_hrr_node-1;i>=0;i--) {
217
if (hrr_nodes[i].B == 0 && hrr_nodes[i].D == 0) {
218
hrr_nodes[i].marked = 1;
219
hrr_nodes[i].pointer = get_mem(hrr_nodes[i].size);
220
fprintf(hrr_code," Libint->vrr_classes[%d][%d] = int_stack + %d;\n",
221
hrr_nodes[i].A,hrr_nodes[i].C,hrr_nodes[i].pointer);
224
base_mem = get_total_memory();
225
fprintf(hrr_code," memset(int_stack,0,%d*sizeof(REALTYPE));\n\n",base_mem);
226
fprintf(hrr_code," Libint->vrr_stack = int_stack + %d;\n",base_mem);
228
/*----------------------------
229
Build the HRR call sequence
230
----------------------------*/
231
target_data = alloc_mem_hrr(hrr_nodes);
232
hrr_mem = get_total_memory();
233
if (max_stack_size < hrr_mem)
234
max_stack_size = hrr_mem;
235
fprintf(hrr_code," for(i=0;i<num_prim_comb;i++) {\n");
236
fprintf(hrr_code," vrr_order_%c%c%c%c(Libint, Data);\n",
237
am_letter[la-lb],am_letter[lb],am_letter[lc-ld],am_letter[ld]);
238
fprintf(hrr_code," Data++;\n }\n");
240
j = first_hrr_to_compute;
242
fprintf(hrr_code, " /*--- compute (%c%c|%c%c) ---*/\n",
243
am_letter[hrr_nodes[j].A],am_letter[hrr_nodes[j].B],
244
am_letter[hrr_nodes[j].C],am_letter[hrr_nodes[j].D]);
245
if (hrr_nodes[j].B == 0 && hrr_nodes[j].D != 0) {
246
fprintf(hrr_code, " hrr3_build_%c%c(Libint->CD,int_stack+%d,int_stack+%d,",
247
am_letter[hrr_nodes[j].C], am_letter[hrr_nodes[j].D], hrr_nodes[j].pointer,
248
hrr_nodes[hrr_nodes[j].children[0]].pointer);
249
fprintf(hrr_code, "int_stack+%d,%d);\n", hrr_nodes[hrr_nodes[j].children[1]].pointer,
250
io[hrr_nodes[j].A]*io[hrr_nodes[j].B]);
251
/* Add this function to the list of inlined functions if necessary */
252
max_node_am = (hrr_nodes[j].C > hrr_nodes[j].D) ? hrr_nodes[j].C : hrr_nodes[j].D;
253
if (to_inline_hrr && max_node_am <= Params.max_am_to_inline_hrr_worker)
254
fprintf(inline_hrr_list,"#include \"hrr3_build_%c%c.h\"\n", am_letter[hrr_nodes[j].C], am_letter[hrr_nodes[j].D]);
256
else if (hrr_nodes[j].B != 0) {
257
fprintf(hrr_code, " hrr1_build_%c%c(Libint->AB,int_stack+%d,int_stack+%d,",
258
am_letter[hrr_nodes[j].A], am_letter[hrr_nodes[j].B], hrr_nodes[j].pointer,
259
hrr_nodes[hrr_nodes[j].children[0]].pointer);
260
fprintf(hrr_code, "int_stack+%d,%d);\n", hrr_nodes[hrr_nodes[j].children[1]].pointer,
261
io[hrr_nodes[j].C]*io[hrr_nodes[j].D]);
262
/* Add this function to the list of inlined functions if necessary */
263
max_node_am = (hrr_nodes[j].A > hrr_nodes[j].B) ? hrr_nodes[j].A : hrr_nodes[j].B;
264
if (to_inline_hrr && max_node_am <= Params.max_am_to_inline_hrr_worker)
265
fprintf(inline_hrr_list,"#include \"hrr1_build_%c%c.h\"\n", am_letter[hrr_nodes[j].A], am_letter[hrr_nodes[j].B]);
267
j = hrr_nodes[j].rlink;
269
fprintf(hrr_code," return int_stack+%d;}\n",target_data);
271
fclose(inline_hrr_list);
272
printf("Done with %s\n",hrr_code_name);
273
for(i=0;i<last_hrr_node;i++) {
274
hrr_nodes[i].llink = 0;
275
hrr_nodes[i].rlink = 0;
279
/*------------------------------------------------------------------
280
Now generate the VRR graph using the (e0|f0) type classes present
281
in the HRR graph as "potential" targets
282
------------------------------------------------------------------*/
286
for(i=0;i<last_hrr_node;i++)
287
if (hrr_nodes[i].B == 0 && hrr_nodes[i].D == 0) {
288
if ((j = vrr_hash_table[hrr_nodes[i].A][hrr_nodes[i].C][0]) == 0) {
289
target_vrr_nodes[num_vrr_targets] = last_vrr_node;
290
vrr_nodes[last_vrr_node].A = hrr_nodes[i].A;
291
vrr_nodes[last_vrr_node].C = hrr_nodes[i].C;
292
vrr_nodes[last_vrr_node].m = 0;
293
vrr_nodes[last_vrr_node].llink = -1;
294
vrr_nodes[last_vrr_node].rlink = -1;
295
if (num_vrr_targets) {
296
vrr_nodes[target_vrr_nodes[num_vrr_targets-1]].llink = last_vrr_node;
297
vrr_nodes[last_vrr_node].rlink = target_vrr_nodes[num_vrr_targets-1];
298
vrr_nodes[last_vrr_node].llink = -1;
301
vrr_nodes[last_vrr_node].rlink = -1;
302
vrr_nodes[last_vrr_node].llink = -1;
304
first_vrr_to_compute = last_vrr_node;
305
mk_vrr_node(vrr_nodes[last_vrr_node], vrr_nodes, 0);
306
vrr_nodes[first_vrr_to_compute].target = 1;
310
vrr_nodes[j-1].target = 1;
311
if (first_vrr_to_compute == last_vrr_node && i == last_hrr_node-1)
312
punt("Edward, you fucked up\n");
315
/* Traverse the graph starting at each target */
316
for(i=0;i<num_vrr_targets;i++) {
317
j = target_vrr_nodes[i];
319
if(vrr_nodes[j].children[k]>0){
320
mark_vrr_parents(vrr_nodes[j].children[k], vrr_nodes, j);
325
/*-----------------------------------------------------------------
326
Empirical rule as with what size heap to start memory allocation
327
-----------------------------------------------------------------*/
331
/* Build the call sequence */
332
target_data = alloc_mem_vrr(vrr_nodes);
333
vrr_mem = base_mem + get_total_memory();
334
if (max_stack_size < vrr_mem)
335
max_stack_size = vrr_mem;
336
fprintf(vrr_code," REALTYPE *vrr_stack = Libint->vrr_stack;\n");
337
fprintf(vrr_code," REALTYPE *tmp, *target_ptr;\n int i, am[2];\n");
339
j = first_vrr_to_compute;
341
if (vrr_nodes[j].A <= opt_am && vrr_nodes[j].C <= opt_am) {
342
fprintf(vrr_code, " _BUILD_%c0%c0(Data,", am_letter[vrr_nodes[j].A], am_letter[vrr_nodes[j].C]);
343
/* Add this function to the list of inlined functions if necessary */
344
max_node_am = (vrr_nodes[j].A > vrr_nodes[j].C) ? vrr_nodes[j].A : vrr_nodes[j].C;
345
if (to_inline_vrr && max_node_am <= Params.max_am_to_inline_vrr_worker)
346
fprintf(inline_vrr_list,"#include \"build_%c0%c0.h\"\n", am_letter[vrr_nodes[j].A], am_letter[vrr_nodes[j].C]);
349
fprintf(vrr_code, " am[0] = %d; am[1] = %d;\n", vrr_nodes[j].A, vrr_nodes[j].C);
350
fprintf(vrr_code, " vrr_build_xxxx(am,Data,");
352
fprintf(vrr_code, "vrr_stack+%d", vrr_nodes[j].pointer);
354
if(vrr_nodes[j].children[k] > 0)
355
fprintf(vrr_code, ", vrr_stack+%d", vrr_nodes[vrr_nodes[j].children[k]].pointer);
356
else if (vrr_nodes[j].children[k] == NONODE)
357
fprintf(vrr_code, ", NULL");
359
fprintf(vrr_code, ", Data->F+%d", (-1)*vrr_nodes[j].children[k]);
361
fprintf(vrr_code, ");\n");
362
if (vrr_nodes[j].target == 1) {
363
fprintf(vrr_code, " tmp = vrr_stack + %d;\n", vrr_nodes[j].pointer);
364
fprintf(vrr_code, " target_ptr = Libint->vrr_classes[%d][%d];\n",vrr_nodes[j].A,vrr_nodes[j].C);
365
fprintf(vrr_code, " for(i=0;i<%d;i++)\n",(vrr_nodes[j].A+1)*(vrr_nodes[j].A+2)*(vrr_nodes[j].C+1)*(vrr_nodes[j].C+2)/4);
366
fprintf(vrr_code, " target_ptr[i] += tmp[i];\n");
368
j = vrr_nodes[j].rlink;
370
fprintf(vrr_code, "\n}\n\n");
372
fclose(inline_vrr_list);
373
printf("Done with %s\n",vrr_code_name);
374
for(i=0;i<last_vrr_node;i++) {
375
vrr_nodes[i].llink = 0;
376
vrr_nodes[i].rlink = 0;
380
/* compare this max_stack_size to the libint_stack_size for
381
this angular momentum and reset it */
382
if (libint_stack_size[current_highest_am] < max_stack_size)
383
libint_stack_size[current_highest_am] = max_stack_size;
395
/* Recursive function that build the HRR subgraph given the parent */
397
int mk_hrr_node(hrr_class node, hrr_class *allnodes, int new)
406
static int io[] = {1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210};
408
/* Search for the parent node on stack
409
If it's not there - we'll add it to the end of the stack */
410
thisnode = last_hrr_node;
411
/* it's already placed on the stack allnodes - make sure children don't get created again (made = 1) */
412
if (hrr_hash_table[node.A][node.B][node.C][node.D]) {
413
i = hrr_hash_table[node.A][node.B][node.C][node.D] - 1;
418
/* it's not computed, add it, and make it the first to compute! */
420
allnodes[thisnode].A = node.A;
421
allnodes[thisnode].B = node.B;
422
allnodes[thisnode].C = node.C;
423
allnodes[thisnode].D = node.D;
424
hrr_hash_table[node.A][node.B][node.C][node.D] = thisnode + 1;
425
allnodes[thisnode].num_parents = 0;
426
allnodes[thisnode].parents_counter = 0;
427
allnodes[thisnode].marked = 0;
428
allnodes[thisnode].pointer = 0;
429
memset(allnodes[thisnode].parents,0,5*sizeof(int));
430
allnodes[thisnode].children[0] = NONODE;
431
allnodes[thisnode].children[1] = NONODE;
432
allnodes[thisnode].size = io[node.A]*io[node.B]*io[node.C]*io[node.D];
433
allnodes[thisnode].target = 0;
434
/* We just added a node ..*/
436
/* If stack is overfull - exit */
437
if(last_hrr_node==MAXNODE) {
438
printf(" Maximum stack size is reached. Change MAXNODE and recompile.\n\n");
443
/* If the parent class wasn't on stack already (!new) - increase the parent counter */
445
allnodes[thisnode].num_parents++;
446
allnodes[thisnode].parents_counter++;
450
/* now make all child nodes */
457
allnodes[thisnode].children[0] =
458
mk_hrr_node(O[0], allnodes, made);
463
allnodes[thisnode].children[1] =
464
mk_hrr_node(O[1], allnodes, made);
471
allnodes[thisnode].children[0] =
472
mk_hrr_node(O[0], allnodes, made);
477
allnodes[thisnode].children[1] =
478
mk_hrr_node(O[1], allnodes, made);
487
/* Recursive function that build the VRR subgraph given the parent */
489
int mk_vrr_node(vrr_class node, vrr_class *allnodes, int new)
498
static int io[] = {1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210};
500
/* Are there any children? */
501
if(node.A+node.C == 0) return (-1)*node.m;
503
/* Search for the parent node on stack
504
If it's not there - we'll add it to the end of the stack */
505
thisnode = last_vrr_node;
506
/* it's already placed on the stack allnodes - make sure children don't get created again (made = 1) */
507
if (vrr_hash_table[node.A][node.C][node.m]) {
508
i = vrr_hash_table[node.A][node.C][node.m] - 1;
513
/* it's not computed, add it, and make it the first to compute! */
515
allnodes[thisnode].A = node.A;
516
allnodes[thisnode].C = node.C;
517
allnodes[thisnode].m = node.m;
518
vrr_hash_table[node.A][node.C][node.m] = thisnode + 1;
519
allnodes[thisnode].num_parents = 0;
520
allnodes[thisnode].parents_counter = 0;
521
allnodes[thisnode].marked = 0;
522
allnodes[thisnode].target = 0;
523
allnodes[thisnode].pointer = 0;
524
memset(allnodes[thisnode].parents,0,10*sizeof(int));
525
allnodes[thisnode].children[0] = NONODE;
526
allnodes[thisnode].children[1] = NONODE;
527
allnodes[thisnode].children[2] = NONODE;
528
allnodes[thisnode].children[3] = NONODE;
529
allnodes[thisnode].children[4] = NONODE;
530
allnodes[thisnode].size = io[node.A]*io[node.C];
531
/* We just added a node ..*/
533
/* If stack is overfull - exit */
534
if(last_vrr_node==MAXNODE) {
535
printf(" Maximum stack size is reached. Change MAXNODE and recompile.\n\n");
540
/* If the parent class wasn't on stack already (!new) - increase the parent counter */
542
allnodes[thisnode].num_parents++;
543
allnodes[thisnode].parents_counter++;
547
/* now make all child nodes */
553
allnodes[thisnode].children[0] =
554
mk_vrr_node(O[0], allnodes, made);
558
allnodes[thisnode].children[1] =
559
mk_vrr_node(O[1], allnodes, made);
564
allnodes[thisnode].children[2] =
565
mk_vrr_node(O[2], allnodes, made);
569
allnodes[thisnode].children[3] =
570
mk_vrr_node(O[3], allnodes, made);
576
allnodes[thisnode].children[4] =
577
mk_vrr_node(O[4], allnodes, made);
584
allnodes[thisnode].children[0] =
585
mk_vrr_node(O[0], allnodes, made);
589
allnodes[thisnode].children[1] =
590
mk_vrr_node(O[1], allnodes, made);
595
allnodes[thisnode].children[2] =
596
mk_vrr_node(O[2], allnodes, made);
600
allnodes[thisnode].children[3] =
601
mk_vrr_node(O[3], allnodes, made);
611
/* Make hrr_nodes[rent] a parent of hrr_nodes[n] and proceed recursively */
613
int mark_hrr_parents(int n, hrr_class *allnodes, int rent)
618
/* handle case where it's in the parent list already */
619
for(i=allnodes[n].num_parents-1; i>=allnodes[n].parents_counter; i--)
620
if(rent==allnodes[n].parents[i]) return;
622
/* if the parent rent is not in the list - add it to the list! */
623
i = --allnodes[n].parents_counter;
624
allnodes[n].parents[i] = rent;
625
/* hits from all of the parents has been received - schedule it for computation and mark all of its children */
626
if (i == 0 && (allnodes[n].B != 0 || allnodes[n].D != 0)) {
627
allnodes[n].llink = -1;
628
allnodes[n].rlink = first_hrr_to_compute;
629
allnodes[first_hrr_to_compute].llink = n;
630
first_hrr_to_compute = n;
633
if(allnodes[n].children[i]>0)
634
mark_hrr_parents(allnodes[n].children[i], allnodes, n);
640
/* Make vrr_nodes[rent] a parent of vrr_nodes[n] and proceed recursively */
642
int mark_vrr_parents(int n, vrr_class *allnodes, int rent)
647
/* handle case where it's in there already */
648
for(i=allnodes[n].num_parents-1; i>=allnodes[n].parents_counter; i--)
649
if(rent==allnodes[n].parents[i]) return;
652
/* if the parent rent is not in the list - add it to the list! */
653
i = --allnodes[n].parents_counter;
654
allnodes[n].parents[i] = rent;
655
/* hits from all of the parents has been received - schedule it for computation and mark all of its children */
657
allnodes[n].llink = -1;
658
allnodes[n].rlink = first_vrr_to_compute;
659
allnodes[first_vrr_to_compute].llink = n;
660
first_vrr_to_compute = n;
663
if(allnodes[n].children[i]>0)
664
mark_vrr_parents(allnodes[n].children[i], allnodes, n);
672
/* This functions controls memory placement of computed classes on the CINTS stack */
674
int alloc_mem_hrr(hrr_class *nodes)
680
static int io[] = {1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210};
682
j = first_hrr_to_compute;
684
/* Node to compute */
685
if (nodes[j].marked == 0) {
686
nodes[j].marked = 1; /* sign that it has been passed */
687
nodes[j].pointer = get_mem(nodes[j].size); /* Allocate memory for it on a CINTS-provided stack */
690
/* Figure out which children can be freed,
691
i.e. which children are not targets and have all parents marked */
693
child = nodes[j].children[k];
695
if (nodes[child].target == 0) {
697
for(l=0; l<nodes[child].num_parents; l++)
698
if(!nodes[nodes[child].parents[l]].marked)
701
free_mem(nodes[child].pointer, nodes[child].size);
707
return nodes[0].pointer;
712
/* This functions controls memory placement of computed classes on the CINTS stack */
714
int alloc_mem_vrr(vrr_class *nodes)
720
static int io[] = {1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210};
722
/* Mark all nodes as not computed */
723
for(i=0; i<last_vrr_node; i++)
726
j = first_vrr_to_compute;
728
/* Node to compute */
729
nodes[j].marked = 1; /* sign that it has been passed */
730
nodes[j].pointer = get_mem(nodes[j].size); /* Allocate memory for it on a CINTS-provided stack */
732
/* Figure out which children can be freed,
733
i.e. which children have all parents marked */
735
child = nodes[j].children[k];
738
for(l=0; l<nodes[child].num_parents; l++){
739
if(!nodes[nodes[child].parents[l]].marked) {
744
free_mem(nodes[child].pointer, nodes[child].size);
751
return nodes[0].pointer;