~ubuntu-branches/ubuntu/quantal/psicode/quantal

« back to all changes in this revision

Viewing changes to src/lib/libint/emit_order.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Banck
  • Date: 2006-09-10 14:01:33 UTC
  • Revision ID: james.westby@ubuntu.com-20060910140133-ib2j86trekykfsfv
Tags: upstream-3.2.3
ImportĀ upstreamĀ versionĀ 3.2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*------------------------------------------------------------------------------------------------------
 
2
  Builds a library of functions-calls for applying HRR and VRR
 
3
 ------------------------------------------------------------------------------------------------------*/
 
4
 
 
5
#include <stdio.h>
 
6
#include <string.h>
 
7
#include "mem_man.h"
 
8
#include "build_libint.h"
 
9
#define MAXNODE 3000
 
10
#define NONODE -1000000
 
11
#define SSSSNODE -1111
 
12
 
 
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 */
 
15
 
 
16
extern FILE *outfile, *hrr_header, *init_code;
 
17
extern int libint_stack_size[MAX_AM/2+1];
 
18
extern LibintParams_t Params;
 
19
 
 
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 */
 
23
  int pointer;
 
24
  int children[2];        /* Up to 5 children of the class */
 
25
  int parents_counter;
 
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 */
 
32
  } hrr_class;
 
33
 
 
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 */
 
38
  int pointer;
 
39
  int children[5];        /* Up to 5 children of the class */
 
40
  int parents_counter;
 
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 */
 
45
  int marked;
 
46
  int target;
 
47
  } vrr_class;
 
48
 
 
49
 
 
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) */
 
54
 
 
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];
 
57
 
 
58
void emit_order()
 
59
{
 
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;
 
67
 
 
68
  int i, j, k, l;
 
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 */
 
75
  int target_data;
 
76
  int done;
 
77
  int max_stack_size = 0;
 
78
  int num_vrr_targets;
 
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};
 
89
 
 
90
  for(la=0;la<=new_am;la++) {
 
91
    lb_max = la/2;
 
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++) {
 
96
      ld_max = lc/2;
 
97
      ld_min = (lc <= new_am/2) ? 0 : lc - new_am/2;
 
98
      for(ld=ld_min;ld<=ld_max;ld++) {
 
99
 
 
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;
 
106
 
 
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);
 
119
      else
 
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");
 
131
 
 
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");
 
138
      if (to_inline_hrr) {
 
139
        fprintf(hrr_code,"#define INLINE_HRR_WORKER\n");
 
140
        fprintf(hrr_code,"#include \"%s\"\n",inline_hrr_list_name);
 
141
      }
 
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);
 
145
      else
 
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");
 
154
      
 
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);
 
160
 
 
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");
 
166
      if (to_inline_vrr) {
 
167
        fprintf(vrr_code,"#define INLINE_VRR_WORKER\n");
 
168
        fprintf(vrr_code,"#include \"%s\"\n",inline_vrr_list_name);
 
169
      }
 
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);
 
176
 
 
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));
 
185
        }
 
186
 
 
187
      
 
188
      
 
189
      /* (a b|c d) */
 
190
      hrr_nodes[0].A = la-lb;
 
191
      hrr_nodes[0].B = lb;
 
192
      hrr_nodes[0].C = lc-ld;
 
193
      hrr_nodes[0].D = ld;
 
194
      hrr_nodes[0].llink = -1;
 
195
      hrr_nodes[0].rlink = -1;
 
196
      first_hrr_to_compute = 0;
 
197
      last_hrr_node = 0;
 
198
      mk_hrr_node(hrr_nodes[0], hrr_nodes, 0);
 
199
      hrr_nodes[0].target = 1;
 
200
 
 
201
      /*-------------------------------------------
 
202
        Traverse the graph starting at each target
 
203
       -------------------------------------------*/
 
204
      for(k=0; k<2; k++)
 
205
        if(hrr_nodes[0].children[k]>0)
 
206
          mark_hrr_parents(hrr_nodes[0].children[k], hrr_nodes, 0);
 
207
 
 
208
      /*-----------------------------------------------------------------
 
209
        Empirical rule as with what heap size to start memory allocation
 
210
       -----------------------------------------------------------------*/
 
211
      init_mem(1);
 
212
      
 
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);
 
222
        }
 
223
      }
 
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);
 
227
      
 
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");
 
239
      
 
240
      j = first_hrr_to_compute;
 
241
      do {
 
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]);
 
255
        }
 
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]);
 
266
        }
 
267
        j = hrr_nodes[j].rlink;
 
268
      } while (j != -1);
 
269
      fprintf(hrr_code," return int_stack+%d;}\n",target_data);
 
270
      fclose(hrr_code);
 
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;
 
276
      }
 
277
 
 
278
 
 
279
      /*------------------------------------------------------------------
 
280
        Now generate the VRR graph using the (e0|f0) type classes present
 
281
        in the HRR graph as "potential" targets
 
282
       ------------------------------------------------------------------*/
 
283
      
 
284
      last_vrr_node = 0;
 
285
      num_vrr_targets = 0;
 
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;
 
299
            }
 
300
            else {
 
301
              vrr_nodes[last_vrr_node].rlink = -1;
 
302
              vrr_nodes[last_vrr_node].llink = -1;
 
303
            }
 
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;
 
307
            num_vrr_targets++;
 
308
          }
 
309
          else
 
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");
 
313
        }
 
314
 
 
315
      /* Traverse the graph starting at each target */
 
316
      for(i=0;i<num_vrr_targets;i++) {
 
317
        j = target_vrr_nodes[i];
 
318
        for(k=0; k<5; k++){
 
319
          if(vrr_nodes[j].children[k]>0){
 
320
            mark_vrr_parents(vrr_nodes[j].children[k], vrr_nodes, j);
 
321
          }
 
322
        }
 
323
      }
 
324
 
 
325
      /*-----------------------------------------------------------------
 
326
        Empirical rule as with what size heap to start memory allocation
 
327
       -----------------------------------------------------------------*/
 
328
      init_mem(1);
 
329
 
 
330
 
 
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");
 
338
      
 
339
      j = first_vrr_to_compute;
 
340
      do {
 
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]);
 
347
        }
 
348
        else {
 
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,");
 
351
        }
 
352
        fprintf(vrr_code, "vrr_stack+%d", vrr_nodes[j].pointer);
 
353
        for(k=0; k<5; k++){
 
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");
 
358
          else
 
359
            fprintf(vrr_code, ", Data->F+%d", (-1)*vrr_nodes[j].children[k]);
 
360
        }
 
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");
 
367
        }
 
368
        j = vrr_nodes[j].rlink;
 
369
      } while (j != -1);
 
370
      fprintf(vrr_code, "\n}\n\n");
 
371
      fclose(vrr_code);
 
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;
 
377
      }
 
378
      
 
379
      
 
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;
 
384
 
 
385
      max_stack_size = 0;
 
386
 
 
387
      }
 
388
    }
 
389
    }
 
390
  }
 
391
  return;
 
392
}
 
393
 
 
394
 
 
395
/* Recursive function that build the HRR subgraph given the parent */
 
396
 
 
397
int mk_hrr_node(hrr_class node, hrr_class *allnodes, int new)
 
398
{
 
399
 
 
400
  int i, j, k, l;
 
401
  hrr_class O[2];
 
402
  int subnodes = 0;
 
403
  int thisnode;
 
404
  int rlink, llink;
 
405
  int made = 0;
 
406
  static int io[] = {1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210};
 
407
 
 
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;
 
414
    thisnode = i;
 
415
    made = 1;
 
416
  }
 
417
 
 
418
  /* it's not computed, add it, and make it the first to compute! */
 
419
  if(!made){
 
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 ..*/
 
435
    last_hrr_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");
 
439
      exit(1);
 
440
    }
 
441
  }
 
442
 
 
443
  /* If the parent class wasn't on stack already (!new) - increase the parent counter */
 
444
  if(!new){
 
445
    allnodes[thisnode].num_parents++;
 
446
    allnodes[thisnode].parents_counter++;
 
447
    }
 
448
 
 
449
 
 
450
  /* now make all child nodes */
 
451
  if (!made) {
 
452
  if(node.B){
 
453
    O[0].A = node.A+1;
 
454
    O[0].B = node.B-1;
 
455
    O[0].C = node.C;
 
456
    O[0].D = node.D;
 
457
    allnodes[thisnode].children[0] = 
 
458
            mk_hrr_node(O[0], allnodes, made);
 
459
    O[1].A = node.A;
 
460
    O[1].B = node.B-1;
 
461
    O[1].C = node.C;
 
462
    O[1].D = node.D;
 
463
    allnodes[thisnode].children[1] =
 
464
            mk_hrr_node(O[1], allnodes, made);
 
465
  }
 
466
  else if(node.D){
 
467
    O[0].A = node.A;
 
468
    O[0].B = node.B;
 
469
    O[0].C = node.C+1;
 
470
    O[0].D = node.D-1;
 
471
    allnodes[thisnode].children[0] = 
 
472
            mk_hrr_node(O[0], allnodes, made);
 
473
    O[1].A = node.A;
 
474
    O[1].B = node.B;
 
475
    O[1].C = node.C;
 
476
    O[1].D = node.D-1;
 
477
    allnodes[thisnode].children[1] = 
 
478
            mk_hrr_node(O[1], allnodes, made);
 
479
  }
 
480
  }
 
481
 
 
482
  return thisnode;
 
483
 
 
484
}
 
485
 
 
486
 
 
487
/* Recursive function that build the VRR subgraph given the parent */
 
488
 
 
489
int mk_vrr_node(vrr_class node, vrr_class *allnodes, int new)
 
490
{
 
491
 
 
492
  int i, j, k, l;
 
493
  vrr_class O[5];
 
494
  int subnodes = 0;
 
495
  int thisnode;
 
496
  int rlink, llink;
 
497
  int made = 0;
 
498
  static int io[] = {1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210};
 
499
 
 
500
  /* Are there any children? */
 
501
  if(node.A+node.C == 0) return (-1)*node.m;
 
502
 
 
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;
 
509
    thisnode = i;
 
510
    made = 1;
 
511
  }
 
512
 
 
513
  /* it's not computed, add it, and make it the first to compute! */
 
514
  if(!made){
 
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 ..*/
 
532
    last_vrr_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");
 
536
      exit(1);
 
537
    }
 
538
  }
 
539
 
 
540
  /* If the parent class wasn't on stack already (!new) - increase the parent counter */
 
541
  if(!new){
 
542
    allnodes[thisnode].num_parents++;
 
543
    allnodes[thisnode].parents_counter++;
 
544
    }
 
545
 
 
546
 
 
547
  /* now make all child nodes */
 
548
  if (!made) {
 
549
  if(node.A){
 
550
    O[0].A = node.A-1;
 
551
    O[0].C = node.C;
 
552
    O[0].m = node.m;
 
553
    allnodes[thisnode].children[0] = 
 
554
            mk_vrr_node(O[0], allnodes, made);
 
555
    O[1].A = node.A-1;
 
556
    O[1].C = node.C;
 
557
    O[1].m = node.m+1;
 
558
    allnodes[thisnode].children[1] = 
 
559
            mk_vrr_node(O[1], allnodes, made);
 
560
    if(node.A>1){
 
561
      O[2].A = node.A-2;
 
562
      O[2].C = node.C;
 
563
      O[2].m = node.m;
 
564
      allnodes[thisnode].children[2] = 
 
565
            mk_vrr_node(O[2], allnodes, made);
 
566
      O[3].A = node.A-2;
 
567
      O[3].C = node.C;
 
568
      O[3].m = node.m+1;
 
569
      allnodes[thisnode].children[3] = 
 
570
            mk_vrr_node(O[3], allnodes, made);
 
571
      }
 
572
    if(node.C){
 
573
      O[4].A = node.A-1;
 
574
      O[4].C = node.C-1;
 
575
      O[4].m = node.m+1;
 
576
      allnodes[thisnode].children[4] = 
 
577
            mk_vrr_node(O[4], allnodes, made);
 
578
      }
 
579
    }
 
580
  else if(node.C){
 
581
    O[0].A = node.A;
 
582
    O[0].C = node.C-1;
 
583
    O[0].m = node.m;
 
584
    allnodes[thisnode].children[0] = 
 
585
            mk_vrr_node(O[0], allnodes, made);
 
586
    O[1].A = node.A;
 
587
    O[1].C = node.C-1;
 
588
    O[1].m = node.m+1;
 
589
    allnodes[thisnode].children[1] = 
 
590
            mk_vrr_node(O[1], allnodes, made);
 
591
    if(node.C>1){
 
592
      O[2].A = node.A;
 
593
      O[2].C = node.C-2;
 
594
      O[2].m = node.m;
 
595
      allnodes[thisnode].children[2] = 
 
596
            mk_vrr_node(O[2], allnodes, made);
 
597
      O[3].A = node.A;
 
598
      O[3].C = node.C-2;
 
599
      O[3].m = node.m+1;
 
600
      allnodes[thisnode].children[3] = 
 
601
            mk_vrr_node(O[3], allnodes, made);
 
602
      }
 
603
    }
 
604
  }
 
605
 
 
606
  return thisnode;
 
607
 
 
608
}
 
609
 
 
610
 
 
611
/* Make hrr_nodes[rent] a parent of hrr_nodes[n] and proceed recursively */
 
612
 
 
613
int mark_hrr_parents(int n, hrr_class *allnodes, int rent)
 
614
{
 
615
  int i;
 
616
  int *tmp;
 
617
 
 
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;
 
621
 
 
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;
 
631
 
 
632
    for(i=0; i<2; i++)
 
633
      if(allnodes[n].children[i]>0)
 
634
        mark_hrr_parents(allnodes[n].children[i], allnodes, n);
 
635
  }
 
636
  return;
 
637
}
 
638
 
 
639
 
 
640
/* Make vrr_nodes[rent] a parent of vrr_nodes[n] and proceed recursively */
 
641
 
 
642
int mark_vrr_parents(int n, vrr_class *allnodes, int rent)
 
643
{
 
644
  int i;
 
645
  int *tmp;
 
646
 
 
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;
 
650
 
 
651
 
 
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 */
 
656
  if (i == 0) {
 
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;
 
661
 
 
662
    for(i=0; i<5; i++)
 
663
      if(allnodes[n].children[i]>0)
 
664
        mark_vrr_parents(allnodes[n].children[i], allnodes, n);
 
665
 
 
666
  }
 
667
  return;
 
668
}
 
669
 
 
670
 
 
671
 
 
672
/* This functions controls memory placement of computed classes on the CINTS stack */
 
673
 
 
674
int alloc_mem_hrr(hrr_class *nodes)
 
675
{
 
676
  int i, j, k, l;
 
677
  int size;
 
678
  int child;
 
679
  int free_it;
 
680
  static int io[] = {1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210};
 
681
 
 
682
  j = first_hrr_to_compute;
 
683
  do{
 
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 */
 
688
    }
 
689
      
 
690
    /* Figure out which children can be freed,
 
691
       i.e. which children are not targets and have all parents marked */
 
692
    for(k=0; k<2; k++){
 
693
      child = nodes[j].children[k];
 
694
      if(child>0)
 
695
        if (nodes[child].target == 0) {
 
696
          free_it = 1;
 
697
          for(l=0; l<nodes[child].num_parents; l++)
 
698
            if(!nodes[nodes[child].parents[l]].marked)
 
699
              free_it = 0;
 
700
          if(free_it)
 
701
            free_mem(nodes[child].pointer, nodes[child].size);
 
702
        }
 
703
    }
 
704
    j = nodes[j].rlink;
 
705
  } while (j != -1);
 
706
  
 
707
  return nodes[0].pointer;
 
708
}
 
709
 
 
710
 
 
711
 
 
712
/* This functions controls memory placement of computed classes on the CINTS stack */
 
713
 
 
714
int alloc_mem_vrr(vrr_class *nodes)
 
715
{
 
716
  int i, j, k, l;
 
717
  int size;
 
718
  int child;
 
719
  int free_it;
 
720
  static int io[] = {1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210};
 
721
 
 
722
  /* Mark all nodes as not computed */
 
723
  for(i=0; i<last_vrr_node; i++)
 
724
    nodes[i].marked = 0;
 
725
 
 
726
  j = first_vrr_to_compute;
 
727
  do{
 
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 */
 
731
 
 
732
    /* Figure out which children can be freed,
 
733
       i.e. which children have all parents marked */
 
734
    for(k=0; k<5; k++){
 
735
      child = nodes[j].children[k];
 
736
      if(child>0){
 
737
        free_it = 1;
 
738
        for(l=0; l<nodes[child].num_parents; l++){
 
739
          if(!nodes[nodes[child].parents[l]].marked) {
 
740
            free_it = 0;
 
741
          }
 
742
        }
 
743
        if(free_it){
 
744
          free_mem(nodes[child].pointer, nodes[child].size);
 
745
        }
 
746
      }
 
747
    }
 
748
    j = nodes[j].rlink;
 
749
  } while (j != -1);
 
750
  
 
751
  return nodes[0].pointer;
 
752
}