FORM  4.2
index.c
Go to the documentation of this file.
1 
8 /* #[ License : */
9 /*
10  * Copyright (C) 1984-2017 J.A.M. Vermaseren
11  * When using this file you are requested to refer to the publication
12  * J.A.M.Vermaseren "New features of FORM" math-ph/0010025
13  * This is considered a matter of courtesy as the development was paid
14  * for by FOM the Dutch physics granting agency and we would like to
15  * be able to track its scientific use to convince FOM of its value
16  * for the community.
17  *
18  * This file is part of FORM.
19  *
20  * FORM is free software: you can redistribute it and/or modify it under the
21  * terms of the GNU General Public License as published by the Free Software
22  * Foundation, either version 3 of the License, or (at your option) any later
23  * version.
24  *
25  * FORM is distributed in the hope that it will be useful, but WITHOUT ANY
26  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
27  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
28  * details.
29  *
30  * You should have received a copy of the GNU General Public License along
31  * with FORM. If not, see <http://www.gnu.org/licenses/>.
32  */
33 /* #] License : */
34 
35 /*
36  #[ Includes : index.c
37 */
38 
39 #include "form3.h"
40 
41 /*
42  #] Includes :
43  #[ syntax and use :
44 
45  The indexing of brackets is not automatic! It should only be used
46  when one intends to use the contents of individual brackets.
47  This is done with the addition of a + sign to the bracket statement:
48  B+ a,b,c; or AB+ a,b,c;
49  It does require resources! The index is kept in memory and is removed
50  once the expression is treated and passed on to the output with different
51  or no brackets.
52  The index is limited to a given amount of space. Hence if there are too
53  many brackets we will skip some in the index. Skipping goes by space
54  occupied by the contents. We take the two adjacent bracket(s) with the
55  least space together and represent them by the first one only. This gives
56  a new spot.
57  The expression struct has two pointers:
58  bracketinfo for using.
59  newbracketinfo for making new index.
60 
61  #] syntax and use :
62  #[ FindBracket :
63 */
64 
65 POSITION *FindBracket(WORD nexp, WORD *bracket)
66 {
67  GETIDENTITY
68  BRACKETINDEX *bi;
69  BRACKETINFO *bracketinfo;
70  EXPRESSIONS e = &(Expressions[nexp]);
71  LONG hi, low, med;
72  int i;
73  WORD oldsorttype = AR.SortType, *t1, *t2, j, bsize, *term, *p, *pstop, *pp;
74  WORD *tstop, *cp, a[4], *bracketh;
75  FILEHANDLE *fi;
76  POSITION auxpos, toppos;
77  switch ( e->status ) {
78  case UNHIDELEXPRESSION:
79  case UNHIDEGEXPRESSION:
80  case DROPHLEXPRESSION:
81  case DROPHGEXPRESSION:
82  case HIDDENLEXPRESSION:
83  case HIDDENGEXPRESSION:
84  fi = AR.hidefile;
85  break;
86  default:
87  fi = AR.infile;
88  break;
89  }
90  if ( AT.bracketinfo ) bracketinfo = AT.bracketinfo;
91  else bracketinfo = e->bracketinfo;
92  hi = bracketinfo->indexfill; low = 0;
93  if ( hi <= 0 ) return(0);
94 /*
95  The next code is needed for a problem with sorting when there are
96  only functions outside the bracket. This gives ordinarily the wrong
97  sorting. We solve that by taking HAAKJE along with the outside while
98  running the Compare. But this means that we need to copy bracket.
99 */
100  bracketh = TermMalloc("FindBracket");
101  i = *bracket; p = bracket; pp = bracketh; NCOPY(pp,p,i)
102  pp -= 3; *pp++ = HAAKJE; *pp++ = 3; *pp++ = 0; *pp++ = 1; *pp++ = 1; *pp++ = 3;
103  *bracketh += 3;
104 
105  AT.fromindex = 1;
106  AR.SortType = bracketinfo->SortType;
107  bi = bracketinfo->indexbuffer + hi - 1;
108  if ( *bracketh == 7 ) {
109  if ( bracketinfo->bracketbuffer[bi->bracket] == 7 ) i = 0;
110  else i = -1;
111  }
112  else if ( bracketinfo->bracketbuffer[bi->bracket] == 7 ) i = 1;
113  else i = CompareTerms(BHEAD bracketh,bracketinfo->bracketbuffer+bi->bracket,0);
114  if ( i < 0 ) {
115  AR.SortType = oldsorttype;
116  AT.fromindex = 0;
117  TermFree(bracketh,"FindBracket");
118  return(0);
119  }
120  else if ( i == 0 ) med = hi-1;
121  else {
122  for (;;) {
123  med = (hi+low)/2;
124  bi = bracketinfo->indexbuffer + med;
125  if ( *bracketh == 7 ) {
126  if ( bracketinfo->bracketbuffer[bi->bracket] == 7 ) i = 0;
127  else i = -1;
128  }
129  else if ( bracketinfo->bracketbuffer[bi->bracket] == 7 ) i = 1;
130  else i = CompareTerms(BHEAD bracketh,bracketinfo->bracketbuffer+bi->bracket,0);
131  if ( i == 0 ) { break; }
132  if ( i > 0 ) {
133  if ( low == med ) { /* no occurrence */
134  AR.SortType = oldsorttype;
135  AT.fromindex = 0;
136  TermFree(bracketh,"FindBracket");
137  return(0);
138  }
139  hi = med;
140  }
141  else if ( i < 0 ) {
142  if ( low == med ) break;
143  low = med;
144  }
145  }}
146 /*
147  The bracket is now either bi itself or between bi and the next one
148  or it is not present at all.
149 */
150  AN.theposition = AS.OldOnFile[nexp];
151  ADD2POS(AN.theposition,bi->start);
152 /*
153  The seek will have to move closer to the actual read so that we
154  can place a lock around the two.
155  if ( fi->handle >= 0 ) SeekFile(fi->handle,&AN.theposition,SEEK_SET);
156  else SetScratch(fi,&AN.theposition);
157 */
158 /*
159  Put the bracket in the compress buffer as if it were the last term read.
160  Have a look at AR.CompressPointer. (set it right)
161 */
162  term = AT.WorkPointer;
163  t1 = bracketinfo->bracketbuffer+bi->bracket;
164  j = *t1;
165 /*
166  Note that in the bracketbuffer, the bracket sits with HAAKJE.
167 
168  The next is (hopefully) a bug fix. Originally the code read bsize = j
169  but that overcounts one. We have the part outside the bracket and the
170  coefficient which is 1,1,3. But we also have the length indicator.
171  Where we use the variable bsize we do not include the length indicator,
172  and we have the part outside plus 7,3,0 which is also three words.
173 */
174  bsize = j-1;
175  t2 = AR.CompressPointer;
176  NCOPY(t2,t1,j)
177  if ( i == 0 ) { /* We found the proper bracket already */
178  AR.SortType = oldsorttype;
179  AT.fromindex = 0;
180  TermFree(bracketh,"FindBracket");
181  return(&AN.theposition);
182  }
183 /*
184  Here we have to skip to the bracket if it exists (!)
185  Let us first look whether the expression is in memory.
186  If not we have to make a buffer to increase speed..
187 */
188  if ( fi->handle < 0 ) {
189  p = (WORD *)((UBYTE *)(fi->PObuffer)
190  + BASEPOSITION(AS.OldOnFile[nexp])
191  + BASEPOSITION(bi->start));
192  pstop = (WORD *)((UBYTE *)(fi->PObuffer)
193  + BASEPOSITION(AS.OldOnFile[nexp])
194  + BASEPOSITION(bi->next));
195  while ( p < pstop ) {
196 /*
197  Check now: if size or part from previous term < size of bracket
198  we have to setup the bracket again and test.
199  Otherwise, skip immediately to the next term.
200 */
201  if ( *p <= -bsize ) { /* no change of bracket */
202  p++; p += *p + 1;
203  }
204  else if ( *p < 0 ) { /* changes bracket */
205  pp = p;
206  t2 = AR.CompressPointer;
207  t1 = t2 - *p++ + 1;
208  j = *p++;
209  NCOPY(t1,p,j)
210  t2++; while ( *t2 != HAAKJE ) t2 += t2[1];
211  t2 += t2[1];
212  a[1] = t2[0]; a[2] = t2[1]; a[3] = t2[2];
213  *t2++ = 1; *t2++ = 1; *t2++ = 3;
214  *AR.CompressPointer = t2 - AR.CompressPointer;
215  bsize = *AR.CompressPointer - 1;
216  if ( *bracketh == 7 ) {
217  if ( AR.CompressPointer[0] == 7 ) i = 0;
218  else i = -1;
219  }
220  else if ( AR.CompressPointer[0] == 7 ) i = 1;
221  else i = CompareTerms(BHEAD bracketh,AR.CompressPointer,0);
222  t2[-3] = a[1]; t2[-2] = a[2]; t2[-1] = a[3];
223  if ( i == 0 ) {
224  SETBASEPOSITION(AN.theposition,(pp-fi->PObuffer)*sizeof(WORD));
225  fi->POfill = pp;
226  goto found;
227  }
228  if ( i > 0 ) break; /* passed what was possible */
229  }
230  else { /* no compression. We have to check! */
231  WORD *oldworkpointer = AT.WorkPointer, *t3, *t4;
232  t2 = p + 1; while ( *t2 != HAAKJE ) t2 += t2[1];
233  t2 += t2[1];
234 /*
235  Here we need to copy the term. Modifying has proven to
236  be NOT threadsafe.
237 */
238  t3 = oldworkpointer; t4 = p;
239  while ( t4 < t2 ) *t3++ = *t4++;
240  *t3++ = 1; *t3++ = 1; *t3++ = 3;
241  *oldworkpointer = t3 - oldworkpointer;
242  bsize = *oldworkpointer - 1;
243  AT.WorkPointer = t3;
244  t3 = oldworkpointer;
245  if ( *bracketh == 7 ) {
246  if ( t3[0] == 7 ) i = 0;
247  else i = -1;
248  }
249  else if ( t3[0] == 7 ) i = 1;
250  else {
251  i = CompareTerms(BHEAD bracketh,t3,0);
252  }
253  AT.WorkPointer = oldworkpointer;
254  if ( i == 0 ) {
255  SETBASEPOSITION(AN.theposition,(p-fi->PObuffer)*sizeof(WORD));
256  fi->POfill = p;
257  goto found;
258  }
259  if ( i > 0 ) break; /* passed what was possible */
260  p += *p;
261  }
262  }
263  AR.SortType = oldsorttype;
264  AT.fromindex = 0;
265  TermFree(bracketh,"FindBracket");
266  return(0); /* Bracket does not exist */
267  }
268  else {
269 /*
270  In this case we can work with the old representation without HAAKJE.
271  We stop searching when we reach toppos and we do not call Compare.
272 */
273  toppos = AS.OldOnFile[nexp];
274  ADD2POS(toppos,bi->next);
275  cp = AR.CompressPointer;
276  for(;;) {
277  auxpos = AN.theposition;
278  GetOneTerm(BHEAD term,fi,&auxpos,0);
279  if ( *term == 0 ) {
280  AR.SortType = oldsorttype;
281  AT.fromindex = 0;
282  return(0); /* Bracket does not exist */
283  }
284  tstop = term + *term;
285  tstop -= ABS(tstop[-1]);
286  t1 = term + 1;
287  while ( *t1 != HAAKJE && t1 < tstop ) t1 += t1[1];
288  i = *bracket-4;
289  if ( t1-term == *bracket-3 ) {
290  t1 = term + 1; t2 = bracket+1;
291  while ( i > 0 && *t1 == *t2 ) { t1++; t2++; i--; }
292  if ( i <= 0 ) {
293  AR.CompressPointer = cp;
294  goto found;
295  }
296  }
297  AR.CompressPointer = cp;
298  AN.theposition = auxpos;
299 /*
300  Now check whether we passed the 'point'
301 */
302  if ( ISGEPOS(AN.theposition,toppos) ) {
303  AR.SortType = oldsorttype;
304  AR.CompressPointer = cp;
305  AT.fromindex = 0;
306  TermFree(bracketh,"FindBracket");
307  return(0); /* Bracket does not exist */
308  }
309  }
310  }
311 found:
312  AR.SortType = oldsorttype;
313  AT.fromindex = 0;
314  TermFree(bracketh,"FindBracket");
315  return(&AN.theposition);
316 }
317 
318 /*
319  #] FindBracket :
320  #[ PutBracketInIndex :
321 
322  Call via
323  if ( AR.BracketOn ) PutBracketInIndex(BHEAD term);
324 
325  This means that there should be a bracket somewhere
326  Note that the brackets come in in proper order.
327 
328  DON'T forget AR.SortType to be put into e->bracketinfo->SortType
329 */
330 
331 VOID PutBracketInIndex(PHEAD WORD *term, POSITION *newpos)
332 {
333  GETBIDENTITY
334  BRACKETINDEX *bi, *b1, *b2, *b3;
335  BRACKETINFO *b;
336  POSITION thepos;
337  EXPRESSIONS e = Expressions + AR.CurExpr;
338  LONG hi, i, average;
339  WORD *t, *tstop, *t1, *t2, *oldt, oldsize, a[4];
340  if ( ( b = e->newbracketinfo ) == 0 ) return;
341  DIFPOS(thepos,*newpos,e->onfile);
342  tstop = term + *term;
343  tstop -= ABS(tstop[-1]);
344  t = term+1;
345  while ( *t != HAAKJE && t < tstop ) t += t[1];
346  if ( t >= tstop ) return; /* no ticket, no laundry */
347  t += t[1]; /* include HAAKJE for the sorting */
348  a[0] = t[0]; a[1] = t[1]; a[2] = t[2];
349  oldt = t; oldsize = *term; *t++ = 1; *t++ = 1; *t++ = 3;
350  *term = t - term;
351  AT.fromindex = 1;
352 /*
353  Check now with the last bracket in the buffer.
354  If it is the same we can abort.
355 */
356  hi = b->indexfill;
357  if ( hi > 0 ) {
358  bi = b->indexbuffer + hi - 1;
359  bi->next = thepos;
360  if ( *term == 7 ) {
361  if ( b->bracketbuffer[bi->bracket] == 7 ) i = 0;
362  else i = -1;
363  }
364  else if ( b->bracketbuffer[bi->bracket] == 7 ) i = 1;
365  else i = CompareTerms(BHEAD term,b->bracketbuffer+bi->bracket,0);
366  if ( i == 0 ) { /* still the same bracket */
367  bi->termsinbracket++;
368  goto bracketdone;
369  }
370  if ( i > 0 ) { /* We have a problem */
371 /*
372  There is a special case in which we have only functions and
373  term is contained completely in the bracket
374 */
375 /*
376  t = term + 1;
377  tstop = term + *term - 3;
378  while ( t < tstop && *t > HAAKJE ) t += t[1];
379  if ( t < tstop ) goto problems;
380 */
381  for ( i = 1; i < *term - 3; i++ ) {
382  if ( term[i] != b->bracketbuffer[bi->bracket+i] ) break;
383  }
384  if ( i < *term - 3 ) {
385 /*
386 problems:;
387 */
388  *term = oldsize; oldt[0] = a[0]; oldt[1] = a[1]; oldt[2] = a[2];
389  MLOCK(ErrorMessageLock);
390  MesPrint("Error!!!! Illegal bracket sequence detected in PutBracketInIndex");
391 #ifdef WITHPTHREADS
392  MesPrint("Worker = %w");
393 #endif
394  PrintTerm(term,"term into index");
395  PrintTerm(b->bracketbuffer+bi->bracket,"Last in index");
396  MUNLOCK(ErrorMessageLock);
397  AT.fromindex = 0;
398  Terminate(-1);
399  }
400  i = -1;
401  }
402  }
403 /*
404  If there is room for more brackets, we add this one.
405 */
406  if ( b->bracketfill+*term >= b->bracketbuffersize
407  && ( b->bracketbuffersize < AM.MaxBracketBufferSize
408  || ( e->vflags & ISFACTORIZED ) != 0 ) ) {
409 /*
410  Enlarge bracket buffer
411 */
412  WORD *oldbracketbuffer = b->bracketbuffer;
413  i = MaX(b->bracketbuffersize * 2, b->bracketfill+*term+1);
414  if ( i > AM.MaxBracketBufferSize && ( e->vflags & ISFACTORIZED ) == 0 )
415  i = AM.MaxBracketBufferSize;
416  if ( i > b->bracketfill+*term ) {
417  b->bracketbuffersize = i;
418  b->bracketbuffer = (WORD *)Malloc1(b->bracketbuffersize*sizeof(WORD),
419  "new bracket buffer");
420  t1 = b->bracketbuffer; t2 = oldbracketbuffer;
421  i = b->bracketfill;
422  NCOPY(t1,t2,i)
423  if ( oldbracketbuffer ) M_free(oldbracketbuffer,"old bracket buffer");
424  }
425  }
426  if ( b->bracketfill+*term < b->bracketbuffersize ) {
427  if ( b->indexfill >= b->indexbuffersize ) {
428 /*
429  Enlarge index
430 */
431  BRACKETINDEX *oldindexbuffer = b->indexbuffer;
432  b->indexbuffersize *= 2;
433  b->indexbuffer = (BRACKETINDEX *)
434  Malloc1(b->indexbuffersize*sizeof(BRACKETINDEX),"new bracket index");
435  b1 = b->indexbuffer; b2 = oldindexbuffer;
436  i = b->indexfill;
437  NCOPY(b1,b2,i)
438  if ( oldindexbuffer ) M_free(oldindexbuffer,"old bracket index");
439  }
440  }
441  else {
442 /*
443  We have too many brackets in the buffer. Try to improve.
444  This is the interesting algorithm. We try to eliminate about 1/4 to
445  1/2 of the brackets from the index. This should be done by size of
446  the bracket contents to make the searching as fast as possible.
447  But! Do not touch the last bracket.
448  Note that we are always filling from the back.
449  Algorithm: Throw away every second bracket, unless b1+b2 is much longer
450  than average. How much is something we can tune.
451 */
452  average = DIVPOS(thepos,b->indexfill+1);
453  if ( average <= 0 ) {
454  MLOCK(ErrorMessageLock);
455  MesPrint("Problems with bracket buffer. Increase MaxBracketBufferSize in form.set");
456  MesPrint("Current size is %l",AM.MaxBracketBufferSize*sizeof(WORD));
457  MUNLOCK(ErrorMessageLock);
458  Terminate(-1);
459  }
460  average *= 4; /* 2*2: one 2 for much longer, one 2 because we have pairs */
461  t2 = b->bracketbuffer;
462  b3 = b1 = b->indexbuffer;
463  bi = b->indexbuffer + b->indexfill;
464  b2 = b1+1;
465  while ( b2+2 < bi ) {
466  if ( DIFBASE(b2->next,b1->start) > average ) {
467  t1 = b->bracketbuffer + b1->bracket;
468  b1->bracket = t2 - b->bracketbuffer;
469  i = *t1; NCOPY(t2,t1,i)
470  *b3++ = *b1;
471  t1 = b->bracketbuffer + b2->bracket;
472  b2->bracket = t2 - b->bracketbuffer;
473  i = *t1; NCOPY(t2,t1,i)
474  *b3++ = *b2;
475  if ( b3 <= b1 ) {
476  PUTZERO(b1->start);
477  PUTZERO(b1->next);
478  b1->bracket = 0;
479  b1->termsinbracket = 0;
480  }
481  if ( b3 <= b2 ) {
482  PUTZERO(b2->start);
483  PUTZERO(b2->next);
484  b2->bracket = 0;
485  b2->termsinbracket = 0;
486  }
487  }
488  else {
489  t1 = b->bracketbuffer + b1->bracket;
490  b1->bracket = t2 - b->bracketbuffer;
491  i = *t1; NCOPY(t2,t1,i)
492  b1->next = b2->next;
493  b1->termsinbracket += b2->termsinbracket;
494  *b3++ = *b1;
495  if ( b3 <= b1 ) {
496  PUTZERO(b1->start);
497  PUTZERO(b1->next);
498  b1->bracket = 0;
499  b1->termsinbracket = 0;
500  }
501  PUTZERO(b2->start);
502  PUTZERO(b2->next);
503  b2->bracket = 0;
504  b2->termsinbracket = 0;
505  }
506  b1 += 2; b2 += 2;
507  }
508  while ( b1 < bi ) {
509  t1 = b->bracketbuffer + b1->bracket;
510  b1->bracket = t2 - b->bracketbuffer;
511  i = *t1; NCOPY(t2,t1,i)
512  *b3++ = *b1;
513  if ( b3 <= b1 ) {
514  PUTZERO(b1->start);
515  PUTZERO(b1->next);
516  b1->bracket = 0;
517  b1->termsinbracket = 0;
518  }
519  b1++;
520  }
521  b->indexfill = b3 - b->indexbuffer;
522  b->bracketfill = t2 - b->bracketbuffer;
523  }
524  bi = b->indexbuffer + b->indexfill;
525  b->indexfill++;
526  bi->bracket = b->bracketfill;
527  bi->start = thepos;
528  bi->next = thepos;
529  bi->termsinbracket = 1;
530 /*
531  Copy the bracket into the buffer
532 */
533  t1 = term; t2 = b->bracketbuffer + bi->bracket; i = *t1;
534  b->bracketfill += i;
535  NCOPY(t2,t1,i)
536 bracketdone:
537  *term = oldsize; oldt[0] = a[0]; oldt[1] = a[1]; oldt[2] = a[2];
538  AT.fromindex = 0;
539 }
540 
541 /*
542  #] PutBracketInIndex :
543  #[ ClearBracketIndex :
544 */
545 
546 void ClearBracketIndex(WORD numexp)
547 {
548  BRACKETINFO *b;
549  if ( numexp >= 0 ) {
550  b = Expressions[numexp].bracketinfo;
551  Expressions[numexp].bracketinfo = 0;
552  }
553  else if ( numexp == -1 ) {
554  GETIDENTITY
555  b = AT.bracketinfo;
556  AT.bracketinfo = 0;
557  }
558  else {
559  numexp = -numexp-2;
560  b = Expressions[numexp].newbracketinfo;
561  Expressions[numexp].newbracketinfo = 0;
562  }
563  if ( b == 0 ) return;
564  b->indexfill = b->indexbuffersize = 0;
565  b->bracketfill = b->bracketbuffersize = 0;
566  M_free(b->bracketbuffer,"ClearBracketBuffer");
567  M_free(b->indexbuffer,"ClearIndexBuffer");
568  M_free(b,"BracketInfo");
569 }
570 
571 /*
572  #] ClearBracketIndex :
573  #[ OpenBracketIndex :
574 
575  Note: This routine is thread-safe
576 */
577 
578 VOID OpenBracketIndex(WORD nexpr)
579 {
580  EXPRESSIONS e = Expressions + nexpr;
581  BRACKETINFO *bi;
582  LONG i;
583  bi = (BRACKETINFO *)Malloc1(sizeof(BRACKETINFO),"BracketInfo");
584  e->newbracketinfo = bi;
585 /*
586  i = 20*AM.MaxTer/sizeof(WORD);
587  if ( i < 1000 ) i = 1000;
588 */
589  i = 2000;
590  bi->bracketbuffer = (WORD *)Malloc1(i*sizeof(WORD),"Bracket Buffer");
591  bi->bracketbuffersize = i;
592  bi->bracketfill = 0;
593  i = 50;
594  bi->indexbuffer = (BRACKETINDEX *)Malloc1(i*sizeof(BRACKETINDEX),"Bracket Index");
595  bi->indexbuffersize = i;
596  bi->indexfill = 0;
597  bi->SortType = AC.SortType;
598 }
599 
600 /*
601  #] OpenBracketIndex :
602  #[ PutInside :
603 
604  Puts a term, or a bracket determined part of a term inside a function.
605 
606  AT.WorkPointer points at term+*term
607 */
608 
609 int PutInside(PHEAD WORD *term, WORD *code)
610 {
611  WORD *from, *to, *oldbuf, *tStop, *t, *tt, oldon, oldact, inc, argsize, *termout;
612  int i, ii, error;
613 
614  if ( code[1] == 4 && ( code[2] == 0 || code[2] == 1 ) ) {
615 /*
616  Put all inside. Move the term by 1+FUNHEAD+ARGHEAD
617 */
618  from = term+*term; to = from+1+ARGHEAD+FUNHEAD; i = ii = *term;
619  to[0] = 1; to[1] = 1; to[2] = 3;
620  while ( --i >= 0 ) *--to = *--from;
621  to = term;
622  *to++ = term[0]+4+ARGHEAD+FUNHEAD;
623  *to++ = code[3];
624  *to++ = ii+FUNHEAD+ARGHEAD;
625  *to++ = 1; /* set dirty flags, because there could be a fast notation */
626  FILLFUN3(to)
627  *to++ = ii+ARGHEAD;
628  *to++ = 1;
629  FILLARG(to)
630  return(0);
631  }
632 /*
633  First we save the old bracket variables. Then we set variables to
634  influence the PutBracket routine and call it.
635  After that we set the values back and sort out the results by placing the
636  inside of the bracket inside the function.
637 */
638  termout = AT.WorkPointer;
639  oldbuf = AT.BrackBuf;
640  oldon = AR.BracketOn;
641  oldact = AT.PolyAct;
642  AR.BracketOn = -code[2];
643  AT.BrackBuf = code+4;
644  AT.PolyAct = 0;
645  error = PutBracket(BHEAD term);
646  AT.PolyAct = oldact;
647  AT.BrackBuf = oldbuf;
648  AR.BracketOn = oldon;
649  if ( error ) return(error);
650  i = *termout; from = termout; to = term;
651  NCOPY(to,from,i);
652  tStop = term +*term; tStop -= tStop[-1];
653  t = term+1;
654  while ( t < tStop && *t != HAAKJE ) t += t[1];
655  from = term + *term;
656  inc = FUNHEAD+ARGHEAD-t[1]+1;
657  tt = t + t[1];
658  argsize = from-tt+1;
659  to = from + inc;
660  to[0] = 1;
661  to[1] = 1;
662  to[2] = 3;
663  while ( from > tt ) *--to = *--from;
664  *--to = argsize;
665  *t++ = code[3];
666  *t++ = argsize+FUNHEAD+ARGHEAD;
667  *t++ = 1;
668  FILLFUN3(t);
669  *t++ = argsize+ARGHEAD;
670  *t++ = 1;
671  FILLARG(t);
672  *term += inc+3;
673  AT.WorkPointer = term+*term;
674  if ( Normalize(BHEAD term) ) error = 1;
675  return(error);
676 }
677 
678 /*
679  #] PutInside :
680 */
681 
682 /*
683  The next routines are for indexing the local output files in a parallel
684  sort. This indexing is needed to get a fast determination of the
685  splitting terms needed to divide the terms evenly over the processors.
686  Actually this method works well for ParFORM, but may not work well
687  for TFORM.
688 
689  #[ PutTermInIndex :
690 
691  Puts a term in the term index.
692  Action:
693  if the index hasn't reached its full size
694  if there is room, put the term
695  if there is no room: extend the buffer, put the term
696  else
697  check if the last term has a number of the type skip*m+1
698  if no, overwrite the last term
699  if yes, check whether there is room for one more term
700  yes: add the term
701  no: drop all even terms, compress the list,
702  multiply skip by 2, and add this term.
703 
704 int PutTermInIndex(WORD *term,POSITION *position)
705 {
706  return(0);
707 }
708 
709  #] PutTermInIndex :
710 */
WORD * bracketbuffer
Definition: structs.h:318
Definition: structs.h:620
#define PHEAD
Definition: ftypes.h:56
WORD SortType
Definition: structs.h:323
BRACKETINDEX * indexbuffer
Definition: structs.h:317
int handle
Definition: structs.h:648