FORM 4.3
index.c
Go to the documentation of this file.
1
8/* #[ License : */
9/*
10 * Copyright (C) 1984-2022 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
65POSITION *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(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(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(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(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 }
311found:
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
331VOID 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(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/*
386problems:;
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;
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)
536bracketdone:
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
546void 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
578VOID 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
609int 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
704int PutTermInIndex(WORD *term,POSITION *position)
705{
706 return(0);
707}
708
709 #] PutTermInIndex :
710*/
BRACKETINDEX * indexbuffer
Definition: structs.h:329
WORD * bracketbuffer
Definition: structs.h:330
WORD SortType
Definition: structs.h:335
Definition: structs.h:633
int handle
Definition: structs.h:661