FORM v5.0.1-33-gdf7fc94
notation.c
Go to the documentation of this file.
1
6/* #[ License : */
7/*
8 * Copyright (C) 1984-2026 J.A.M. Vermaseren
9 * When using this file you are requested to refer to the publication
10 * J.A.M.Vermaseren "New features of FORM" math-ph/0010025
11 * This is considered a matter of courtesy as the development was paid
12 * for by FOM the Dutch physics granting agency and we would like to
13 * be able to track its scientific use to convince FOM of its value
14 * for the community.
15 *
16 * This file is part of FORM.
17 *
18 * FORM is free software: you can redistribute it and/or modify it under the
19 * terms of the GNU General Public License as published by the Free Software
20 * Foundation, either version 3 of the License, or (at your option) any later
21 * version.
22 *
23 * FORM is distributed in the hope that it will be useful, but WITHOUT ANY
24 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
25 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
26 * details.
27 *
28 * You should have received a copy of the GNU General Public License along
29 * with FORM. If not, see <http://www.gnu.org/licenses/>.
30 */
31/* #] License : */
32/*
33 #[ Includes :
34*/
35
36#include "form3.h"
37
38/*
39 #] Includes :
40 #[ NormPolyTerm :
41
42 Brings a term to normal form.
43
44 This routine knows objects of the following types:
45 SYMBOL
46 HAAKJE
47 SNUMBER
48 LNUMBER
49 The SNUMBER and LNUMBER are worked into the coefficient.
50 One of the essences here is that everything can be done in place.
51*/
52
53int NormPolyTerm(PHEAD WORD *term)
54{
55 WORD *tcoef, ncoef, *tstop, *tfill, *t, *tt;
56 int equal, i;
57 WORD *r1, *r2, *r3, *r4, *r5, *rfirst, rv;
58 WORD *lnum, nnum; /* Scratch, originally for factorials */
59/*
60 One: find the coefficient
61*/
62 tcoef = term+*term;
63 ncoef = tcoef[-1];
64 tstop = tcoef - ABS(tcoef[-1]);
65 tfill = t = term + 1;
66 rfirst = 0;
67 if ( t >= tstop ) { return(*term); }
68 while ( t < tstop ) {
69 switch ( *t ) {
70 case SYMBOL:
71 if ( rfirst == 0 ) {
72/*
73 Here we only need to sort
74 1: assume no equals. Bubble.
75*/
76 rfirst = t;
77 r2 = rfirst+4; tt = r3 = t + t[1]; equal = 0;
78 while ( r2 < r3 ) {
79 r1 = r2 - 2;
80 if ( *r2 > *r1 ) { r2 += 2; continue; }
81 if ( *r2 == *r1 ) { r2 += 2; equal = 1; continue; }
82 rv = *r1; *r1 = *r2; *r2 = rv;
83 r1 -= 2; r2 -= 2; r4 = r2 + 2;
84 while ( r1 > t ) {
85 if ( *r2 >= *r1 ) { r2 = r4; break; }
86 rv = *r1; *r1 = *r2; *r2 = rv;
87 r1 -= 2; r2 -= 2;
88 }
89 }
90/*
91 2: hunt down the equal objects
92 postpone eliminating zero powers.
93*/
94 if ( equal ) {
95 r1 = t+2; r2 = r1+2;
96 while ( r2 < r3 ) {
97 if ( *r1 == *r2 ) {
98 r1[1] += r2[1];
99 r4 = r2+2;
100 while ( r4 < r3 ) *r2++ = *r4++;
101 t[1] -= 2;
102 r2 = r1 + 2; r3 -= 2;
103 }
104 }
105 }
106 }
107 else {
108/*
109 Here we only need to insert
110*/
111 r1 = t + 2; tt = r3 = t + t[1];
112 while ( r1 < r3 ) {
113 r2 = rfirst+2; r4 = rfirst + rfirst[1];
114 while ( r2 < r4 ) {
115 if ( *r1 == *r2 ) {
116 r2[1] += r1[1];
117 break;
118 }
119 else if ( *r2 > *r1 ) {
120 r5 = r4;
121 while ( r5 > r2 ) { r5[1] = r5[-1]; r5[0] = r5[-2]; r5 -= 2; }
122 rfirst[1] += 2;
123 *r2 = *r1; r2[1] = r1[1];
124 break;
125 }
126 r2 += 2;
127 }
128 if ( r2 == r4 ) {
129 rfirst[1] += 2;
130 *r2++ = *r1++; *r2++ = *r1++;
131 }
132 else r1 += 2;
133 }
134 }
135 t = tt;
136 break;
137 case HAAKJE: /* Here we skip brackets */
138 t += t[1];
139 break;
140 case SNUMBER:
141 if ( t[2] < 0 ) {
142 t[2] = -t[2];
143 if ( t[3] & 1 ) ncoef = -ncoef;
144 }
145 else if ( t[2] == 0 ) {
146 if ( t[3] < 0 ) goto NormInf;
147 goto NormZero;
148 }
149 lnum = TermMalloc("lnum");
150 lnum[0] = t[2];
151 nnum = 1;
152 if ( t[3] && RaisPow(BHEAD (UWORD *)lnum,&nnum,(UWORD)(ABS(t[3]))) ) goto FromNorm;
153 ncoef = REDLENG(ncoef);
154 if ( t[3] < 0 ) {
155 if ( Divvy(BHEAD (UWORD *)tstop,&ncoef,(UWORD *)lnum,nnum) )
156 goto FromNorm;
157 }
158 else if ( t[3] > 0 ) {
159 if ( Mully(BHEAD (UWORD *)tstop,&ncoef,(UWORD *)lnum,nnum) )
160 goto FromNorm;
161 }
162 ncoef = INCLENG(ncoef);
163 t += t[1];
164 TermFree(lnum,"lnum");
165 break;
166 case LNUMBER:
167 ncoef = REDLENG(ncoef);
168 if ( Mully(BHEAD (UWORD *)tstop,&ncoef,(UWORD *)(t+3),t[2]) ) goto FromNorm;
169 ncoef = INCLENG(ncoef);
170 t += t[1];
171 break;
172 default:
173/* INTERNAL_ERROR_EXCL_START */
174 MLOCK(ErrorMessageLock);
175 MesPrint("!>Illegal code in NormPolyTerm");
176 MUNLOCK(ErrorMessageLock);
177 Terminate(-1);
178 break;
179/* INTERNAL_ERROR_EXCL_STOP */
180 }
181 }
182/*
183 Now we try to eliminate objects to the power zero.
184*/
185 if ( rfirst ) {
186 r2 = rfirst+2;
187 r3 = rfirst + rfirst[1];
188 while ( r2 < r3 ) {
189 if ( r2[1] == 0 ) {
190 r1 = r2 + 2;
191 while ( r1 < r3 ) { r1[-2] = r1[0]; r1[-1] = r1[1]; r1 += 2; }
192 r3 -= 2;
193 rfirst[1] -= 2;
194 }
195 else { r2 += 2; }
196 }
197 if ( rfirst[1] < 4 ) rfirst = 0;
198 }
199/*
200 Finally we put the term together
201*/
202 if ( rfirst ) {
203 i = rfirst[1];
204 NCOPY(tfill,rfirst,i)
205 }
206 i = ABS(ncoef)-1;
207 NCOPY(tfill,tstop,i)
208 *tfill++ = ncoef;
209 *term = tfill - term;
210 return(*term);
211NormZero:
212 *term = 0;
213 return(0);
214NormInf:
215 MLOCK(ErrorMessageLock);
216 MesPrint("0^0 in NormPolyTerm");
217 MUNLOCK(ErrorMessageLock);
218 Terminate(-1);
219 return(-1);
220FromNorm:
221 MLOCK(ErrorMessageLock);
222 MesCall("NormPolyTerm");
223 MUNLOCK(ErrorMessageLock);
224 Terminate(-1);
225 return(-1);
226}
227
228/*
229 #] NormPolyTerm :
230 #[ ComparePoly :
231*/
253#ifdef WITHCOMPAREPOLY
254
255WORD ComparePoly(WORD *term1, WORD *term2, WORD level)
256{
257 WORD *t1, *t2, *t3, *t4, *tstop1, *tstop2;
258 tstop1 = term1 + *term1;
259 tstop1 -= ABS(tstop1[-1]);
260 tstop2 = term2 + *term2;
261 tstop2 -= ABS(tstop2[-1]);
262 t1 = term1+1;
263 t2 = term2+1;
264 while ( t1 < tstop1 && t2 < tstop2 ) {
265 if ( *t1 == *t2 ) {
266 if ( *t1 == HAAKJE ) {
267 if ( t1[2] != t2[2] ) return(t2[2]-t1[2]);
268 t1 += t1[1]; t2 += t2[1];
269 }
270 else { /* must be type SYMBOL */
271 t3 = t1 + t1[1]; t4 = t2 + t2[1];
272 t1 += 2; t2 += 2;
273 while ( t1 < t3 && t2 < t4 ) {
274 if ( *t1 != *t2 ) return(*t2-*t1);
275 if ( t1[1] != t2[1] ) return(t2[1]-t1[1]);
276 t1 += 2; t2 += 2;
277 }
278 if ( t1 < t3 ) return(-1);
279 if ( t2 < t4 ) return(1);
280 }
281 }
282 else return(*t2-*t1);
283 }
284 if ( t1 < tstop1 ) return(-1);
285 if ( t2 < tstop2 ) return(1);
286 return(0);
287}
288
289#endif
290
291/*
292 #] ComparePoly :
293 #[ ConvertToPoly :
294*/
307static int FirstWarnConvertToPoly = 1;
308
309int ConvertToPoly(PHEAD WORD *term, WORD *outterm, WORD *comlist, WORD par)
310{
311 WORD *tout, *tstop, ncoef, *t, *r, *tt, *ttwo = 0;
312 int i, action = 0;
313 tt = term + *term;
314 ncoef = ABS(tt[-1]);
315 tstop = tt - ncoef;
316 tout = outterm+1;
317 t = term + 1;
318 if ( comlist[2] == DOALL ) {
319 while ( t < tstop ) {
320 if ( *t == SYMBOL ) {
321 r = t+2;
322 t += t[1];
323 while ( r < t ) {
324 if ( r[1] > 0 ) {
325 *tout++ = SYMBOL;
326 *tout++ = 4;
327 *tout++ = r[0];
328 *tout++ = r[1];
329 }
330 else {
331 tout[1] = SYMBOL;
332 tout[2] = 4;
333 tout[3] = r[0];
334 tout[4] = -1;
335 i = FindSubterm(tout+1);
336 *tout++ = SYMBOL;
337 *tout++ = 4;
338 *tout++ = MAXVARIABLES-i;
339 *tout++ = -r[1];
340 action = 1;
341 }
342 r += 2;
343 }
344 }
345 else if ( *t == DOTPRODUCT ) {
346 r = t + 2;
347 t += t[1];
348 while ( r < t ) {
349 tout[1] = DOTPRODUCT;
350 tout[2] = 5;
351 tout[3] = r[0];
352 tout[4] = r[1];
353 if ( r[2] < 0 ) {
354 tout[5] = -1;
355 }
356 else {
357 tout[5] = 1;
358 }
359 i = FindSubterm(tout+1);
360 *tout++ = SYMBOL;
361 *tout++ = 4;
362 *tout++ = MAXVARIABLES-i;
363 *tout++ = ABS(r[2]);
364 r += 3;
365 action = 1;
366 }
367 }
368 else if ( *t == VECTOR ) {
369 r = t + 2;
370 t += t[1];
371 while ( r < t ) {
372 tout[1] = VECTOR;
373 tout[2] = 4;
374 tout[3] = r[0];
375 tout[4] = r[1];
376 i = FindSubterm(tout+1);
377 *tout++ = SYMBOL;
378 *tout++ = 4;
379 *tout++ = MAXVARIABLES-i;
380 *tout++ = 1;
381 r += 2;
382 action = 1;
383 }
384 }
385 else if ( *t == INDEX ) {
386 r = t + 2;
387 t += t[1];
388 while ( r < t ) {
389 tout[1] = INDEX;
390 tout[2] = 3;
391 tout[3] = r[0];
392 i = FindSubterm(tout+1);
393 *tout++ = SYMBOL;
394 *tout++ = 4;
395 *tout++ = MAXVARIABLES-i;
396 *tout++ = 1;
397 r++;
398 action = 1;
399 }
400 }
401 else if ( *t == HAAKJE) {
402 if ( par ) {
403 tout[0] = 1; tout[1] = 1; tout[2] = 3;
404 *outterm = (tout+3)-outterm;
405 if ( NormPolyTerm(BHEAD outterm) < 0 ) return(-1);
406 tout = outterm + *outterm;
407 tout -= 3;
408 i = t[1]; NCOPY(tout,t,i);
409 ttwo = tout-1;
410 }
411 else { t += t[1]; }
412 }
413 else if ( *t >= FUNCTION ) {
414 i = FindSubterm(t);
415 t += t[1];
416 *tout++ = SYMBOL;
417 *tout++ = 4;
418 *tout++ = MAXVARIABLES-i;
419 *tout++ = 1;
420 action = 1;
421 }
422 else {
423 if ( FirstWarnConvertToPoly ) {
424 MLOCK(ErrorMessageLock);
425 MesPrint("Illegal object in conversion to polynomial notation");
426 MUNLOCK(ErrorMessageLock);
427 FirstWarnConvertToPoly = 0;
428 }
429 return(-1);
430 }
431 }
432 NCOPY(tout,tstop,ncoef)
433 if ( ttwo ) {
434 WORD hh = *ttwo;
435 *ttwo = tout-ttwo;
436 if ( ( i = NormPolyTerm(BHEAD ttwo) ) >= 0 ) i = action;
437 tout = ttwo + *ttwo;
438 *ttwo = hh;
439 *outterm = tout - outterm;
440 }
441 else {
442 *outterm = tout-outterm;
443 if ( ( i = NormPolyTerm(BHEAD outterm) ) >= 0 ) i = action;
444 }
445 }
446 else if ( comlist[2] == ONLYFUNCTIONS ) {
447 while ( t < tstop ) {
448 if ( *t >= FUNCTION ) {
449 if ( comlist[1] == 3 ) {
450 i = FindSubterm(t);
451 t += t[1];
452 *tout++ = SYMBOL;
453 *tout++ = 4;
454 *tout++ = MAXVARIABLES-i;
455 *tout++ = 1;
456 action = 1;
457 }
458 else {
459 for ( i = 3; i < comlist[1]; i++ ) {
460 if ( *t == comlist[i] ) break;
461 }
462 if ( i < comlist[1] ) {
463 i = FindSubterm(t);
464 t += t[1];
465 *tout++ = SYMBOL;
466 *tout++ = 4;
467 *tout++ = MAXVARIABLES-i;
468 *tout++ = 1;
469 action = 1;
470 }
471 else {
472 i = t[1]; NCOPY(tout,t,i);
473 }
474 }
475 }
476 else {
477 i = t[1]; NCOPY(tout,t,i);
478 }
479 }
480 NCOPY(tout,tstop,ncoef)
481 *outterm = tout-outterm;
482 Normalize(BHEAD outterm);
483 i = action;
484 }
485 else {
486/* INTERNAL_ERROR_EXCL_START */
487 MLOCK(ErrorMessageLock);
488 MesPrint("!>Illegal internal code in conversion to polynomial notation");
489 MUNLOCK(ErrorMessageLock);
490 i = -1;
491/* INTERNAL_ERROR_EXCL_STOP */
492 }
493 return(i);
494}
495
496/*
497 #] ConvertToPoly :
498 #[ LocalConvertToPoly :
499*/
514int LocalConvertToPoly(PHEAD WORD *term, WORD *outterm, WORD startebuf, WORD par)
515{
516 WORD *tout, *tstop, ncoef, *t, *r, *tt, *ttwo = 0;
517 int i, action = 0;
518 tt = term + *term;
519 ncoef = ABS(tt[-1]);
520 tstop = tt - ncoef;
521 tout = outterm+1;
522 t = term + 1;
523 while ( t < tstop ) {
524 if ( *t == SYMBOL ) {
525 r = t+2;
526 t += t[1];
527 while ( r < t ) {
528 if ( r[1] > 0 ) {
529 *tout++ = SYMBOL;
530 *tout++ = 4;
531 *tout++ = r[0];
532 *tout++ = r[1];
533 }
534 else {
535 tout[1] = SYMBOL;
536 tout[2] = 4;
537 tout[3] = r[0];
538 tout[4] = -1;
539 i = FindLocalSubterm(BHEAD tout+1,startebuf);
540 *tout++ = SYMBOL;
541 *tout++ = 4;
542 *tout++ = MAXVARIABLES-i;
543 *tout++ = -r[1];
544 action = 1;
545 }
546 r += 2;
547 }
548 }
549 else if ( *t == DOTPRODUCT ) {
550 r = t + 2;
551 t += t[1];
552 while ( r < t ) {
553 tout[1] = DOTPRODUCT;
554 tout[2] = 5;
555 tout[3] = r[0];
556 tout[4] = r[1];
557 if ( r[2] < 0 ) {
558 tout[5] = -1;
559 }
560 else {
561 tout[5] = 1;
562 }
563 i = FindLocalSubterm(BHEAD tout+1,startebuf);
564 *tout++ = SYMBOL;
565 *tout++ = 4;
566 *tout++ = MAXVARIABLES-i;
567 *tout++ = ABS(r[2]);
568 r += 3;
569 action = 1;
570 }
571 }
572 else if ( *t == VECTOR ) {
573 r = t + 2;
574 t += t[1];
575 while ( r < t ) {
576 tout[1] = VECTOR;
577 tout[2] = 4;
578 tout[3] = r[0];
579 tout[4] = r[1];
580 i = FindLocalSubterm(BHEAD tout+1,startebuf);
581 *tout++ = SYMBOL;
582 *tout++ = 4;
583 *tout++ = MAXVARIABLES-i;
584 *tout++ = 1;
585 r += 2;
586 action = 1;
587 }
588 }
589 else if ( *t == INDEX ) {
590 r = t + 2;
591 t += t[1];
592 while ( r < t ) {
593 tout[1] = INDEX;
594 tout[2] = 3;
595 tout[3] = r[0];
596 i = FindLocalSubterm(BHEAD tout+1,startebuf);
597 *tout++ = SYMBOL;
598 *tout++ = 4;
599 *tout++ = MAXVARIABLES-i;
600 *tout++ = 1;
601 r++;
602 action = 1;
603 }
604 }
605 else if ( *t == HAAKJE) {
606 if ( par ) {
607 tout[0] = 1; tout[1] = 1; tout[2] = 3;
608 *outterm = (tout+3)-outterm;
609 if ( NormPolyTerm(BHEAD outterm) < 0 ) return(-1);
610 tout = outterm + *outterm;
611 tout -= 3;
612 i = t[1]; NCOPY(tout,t,i);
613 ttwo = tout-1;
614 }
615 else { t += t[1]; }
616 }
617 else if ( *t >= FUNCTION ) {
618 i = FindLocalSubterm(BHEAD t,startebuf);
619 t += t[1];
620 *tout++ = SYMBOL;
621 *tout++ = 4;
622 *tout++ = MAXVARIABLES-i;
623 *tout++ = 1;
624 action = 1;
625 }
626 else {
627 if ( FirstWarnConvertToPoly ) {
628 MLOCK(ErrorMessageLock);
629 MesPrint("Illegal object in conversion to polynomial notation");
630 MUNLOCK(ErrorMessageLock);
631 FirstWarnConvertToPoly = 0;
632 }
633 return(-1);
634 }
635 }
636 NCOPY(tout,tstop,ncoef)
637 if ( ttwo ) {
638 WORD hh = *ttwo;
639 *ttwo = tout-ttwo;
640 if ( ( i = NormPolyTerm(BHEAD ttwo) ) >= 0 ) i = action;
641 tout = ttwo + *ttwo;
642 *ttwo = hh;
643 *outterm = tout - outterm;
644 }
645 else {
646 *outterm = tout-outterm;
647 if ( ( i = NormPolyTerm(BHEAD outterm) ) >= 0 ) i = action;
648 }
649 return(i);
650}
651
652/*
653 #] LocalConvertToPoly :
654 #[ ConvertFromPoly :
655
656 Converts a generic term from polynomial notation to the original
657 in which the extra symbols have been replaced by their values.
658 The output is in outterm.
659 We only deal with the extra symbols in the range from < i <= to
660 The output has to be sent to TestSub because it may contain
661 subexpressions when extra symbols have been replaced.
662*/
663
664int ConvertFromPoly(PHEAD WORD *term, WORD *outterm, WORD from, WORD to, WORD offset, WORD par)
665{
666 WORD *tout, *tstop, *tstop1, ncoef, *t, *r, *tt;
667 int i;
668/* first = 1; */
669 tt = term + *term;
670 tout = outterm+1;
671 ncoef = ABS(tt[-1]);
672 tstop = tt - ncoef;
673/*
674 r = t = term + 1;
675 while ( t < tstop ) {
676 if ( *t == SYMBOL ) {
677 tstop1 = t + t[1];
678 tt = t + 2;
679 while ( tt < tstop1 ) {
680 if ( ( *tt < MAXVARIABLES - to )
681 || ( *tt >= MAXVARIABLES - from ) ) {
682 tt += 2;
683 }
684 else break;
685 }
686 if ( tt >= tstop1 ) { t = tstop1; continue; }
687 while ( r < t ) *tout++ = *r++;
688 t += 2;
689 first = 0;
690 while ( t < tstop1 ) {
691 if ( ( *t < MAXVARIABLES - to )
692 || ( *t >= MAXVARIABLES - from ) ) {
693 *tout++ = SYMBOL;
694 *tout++ = 4;
695 *tout++ = *t++;
696 *tout++ = *t++;
697 }
698 else {
699 *tout++ = SUBEXPRESSION;
700 *tout++ = SUBEXPSIZE;
701 *tout++ = MAXVARIABLES - *t++ + offset;
702 *tout++ = *t++;
703 if ( par ) *tout++ = AT.ebufnum;
704 else *tout++ = AM.sbufnum;
705 FILLSUB(tout)
706 }
707 }
708 r = t;
709 }
710 else {
711 t += t[1];
712 }
713 }
714 if ( first ) {
715 i = *term; t = term;
716 NCOPY(outterm,t,i);
717 return(*term);
718 }
719 while ( r < t ) *tout++ = *r++;
720 NCOPY(tout,tstop,ncoef)
721 *outterm = tout-outterm;
722*/
723 t = term + 1;
724 while ( t < tstop ) {
725 if ( *t == SYMBOL ) {
726 tstop1 = t + t[1];
727 tt = t + 2;
728 while ( tt < tstop1 ) {
729 if ( ( *tt < MAXVARIABLES - to )
730 || ( *tt >= MAXVARIABLES - from ) ) {
731 tt += 2;
732 }
733 else {
734 *tout++ = SUBEXPRESSION;
735 *tout++ = SUBEXPSIZE;
736 *tout++ = MAXVARIABLES - *tt++ + offset;
737 *tout++ = *tt++;
738 if ( par ) *tout++ = AT.ebufnum;
739 else *tout++ = AM.sbufnum;
740 FILLSUB(tout)
741 }
742 }
743 r = tout; t += 2;
744 *tout++ = SYMBOL; *tout++ = 0;
745 while ( t < tstop1 ) {
746 if ( ( *t < MAXVARIABLES - to )
747 || ( *t >= MAXVARIABLES - from ) ) {
748 *tout++ = *t++;
749 *tout++ = *t++;
750 }
751 else { t += 2; }
752 }
753 r[1] = tout - r;
754 if ( r[1] <= 2 ) tout = r;
755 }
756 else {
757 i = t[1]; NCOPY(tout,t,i)
758 }
759 }
760 NCOPY(tout,tstop,ncoef)
761 *outterm = tout-outterm;
762 return(*outterm);
763}
764
765/*
766 #] ConvertFromPoly :
767 #[ FindSubterm :
768
769 In this routine we look up a variable.
770 If we don't find it we will enter it in the subterm compiler buffer
771 Searching is by tree structure.
772 Adding changes the tree.
773
774 Notice that in TFORM we should be in sequential mode.
775*/
776
777int FindSubterm(WORD *subterm)
778{
779 WORD old[5], *ss, *term;
780 int number;
781 CBUF *C = cbuf + AM.sbufnum;
782 LONG oldCpointer;
783 term = subterm-1;
784 ss = subterm+subterm[1];
785/*
786 Convert to proper term
787*/
788 old[0] = *term; old[1] = ss[0]; old[2] = ss[1]; old[3] = ss[2]; old[4] = ss[3];
789 ss[0] = 1; ss[1] = 1; ss[2] = 3; ss[3] = 0; *term = subterm[1]+4;
790/*
791 We may have to add the term to the compiler
792 buffer and then to the tree. This cannot be done in parallel and
793 hence we have to set a lock.
794*/
795 LOCK(AM.sbuflock);
796
797 oldCpointer = C->Pointer-C->Buffer; /* Offset of course !!!!!*/
798 AddRHS(AM.sbufnum,1);
799 AddNtoC(AM.sbufnum,*term,term,8);
800 AddToCB(C,0)
801/*
802 See whether we have this one already. If not, insert it in the tree.
803*/
804 number = InsTree(AM.sbufnum,C->numrhs);
805/*
806 Restore old values and return what is needed.
807*/
808 if ( number < (C->numrhs) ) { /* It existed already */
809 C->Pointer = oldCpointer + C->Buffer;
810 C->numrhs--;
811 }
812 else {
813 GETIDENTITY
814 WORD dim = DimensionSubterm(subterm);
815
816 if ( dim == -MAXPOSITIVE ) { /* Give error message but continue */
817 WORD *old = AN.currentTerm;
818 AN.currentTerm = term;
819 MLOCK(ErrorMessageLock);
820 MesPrint("Dimension out of range in %t");
821 MUNLOCK(ErrorMessageLock);
822 AN.currentTerm = old;
823 }
824/*
825 Store the dimension
826*/
827 C->dimension[number] = dim;
828 }
829 UNLOCK(AM.sbuflock);
830
831 *term = old[0]; ss[0] = old[1]; ss[1] = old[2]; ss[2] = old[3]; ss[3] = old[4];
832 return(number);
833}
834
835/*
836 #] FindSubterm :
837 #[ FindLocalSubterm :
838
839 In this routine we look up a variable.
840 If we don't find it we will enter it in the subterm compiler buffer
841 Searching is by tree structure.
842 Adding changes the tree.
843
844 Notice that in TFORM we should be in sequential mode.
845*/
846
847int FindLocalSubterm(PHEAD WORD *subterm, WORD startebuf)
848{
849 WORD old[5], *ss, *term, i, j, *t1, *t2;
850 int number;
851 CBUF *C = cbuf + AT.ebufnum;
852 term = subterm-1;
853 ss = subterm+subterm[1];
854/*
855 Convert to proper term
856*/
857 old[0] = *term; old[1] = ss[0]; old[2] = ss[1]; old[3] = ss[2]; old[4] = ss[3];
858 ss[0] = 1; ss[1] = 1; ss[2] = 3; ss[3] = 0; *term = subterm[1]+4;
859/*
860 First see whether we have this one already in the global buffer.
861*/
862 number = FindTree(AM.sbufnum,term);
863 if ( number > 0 ) goto wearehappy;
864/*
865 Now look whether it is in the ebufnum between startebuf and numrhs
866 Note however that we need an offset of (numxsymbol-startebuf)
867*/
868 for ( i = startebuf+1; i <= C->numrhs; i++ ) {
869 t1 = C->rhs[i]; t2 = term;
870 if ( *t1 == *t2 ) {
871 j = *t1;
872 while ( *t1 == *t2 && j > 0 ) { t1++; t2++; j--; }
873 if ( j <= 0 ) {
874 number = i-startebuf+numxsymbol;
875 goto wearehappy;
876 }
877 }
878 }
879/*
880 Now we have to add it to cbuf[AT.ebufnum]
881*/
882 AddRHS(AT.ebufnum,1);
883 AddNtoC(AT.ebufnum,*term,term,9);
884 AddToCB(C,0)
885 number = C->numrhs-startebuf+numxsymbol;
886wearehappy:
887 *term = old[0]; ss[0] = old[1]; ss[1] = old[2]; ss[2] = old[3]; ss[3] = old[4];
888 return(number);
889}
890
891/*
892 #] FindLocalSubterm :
893 #[ PrintSubtermList :
894
895 Prints all the expressions in the subterm compiler buffer.
896 The format is such that they give definitions of the temporary
897 variables of which the contents are stored in this buffer.
898 These variables have the names Z_123 etc.
899*/
900
901void PrintSubtermList(int from,int to)
902{
903 UBYTE buffer[80], *out, outbuffer[300];
904 int first, i, ii, inc = 1;
905 WORD *term;
906 CBUF *C = cbuf + AM.sbufnum;
907/*
908 if ( to < from ) inc = -1;
909 if ( to == from ) inc = 0;
910*/
911 if ( from <= to ) {
912 inc = 1; to += inc;
913 }
914 else {
915 inc = -1; to += inc;
916 }
917 AO.OutFill = AO.OutputLine = outbuffer;
918 AO.OutStop = AO.OutputLine+AC.LineLength;
919 AO.IsBracket = 0;
920 AO.OutSkip = 3;
921
922 if ( AC.OutputMode == FORTRANMODE || AC.OutputMode == PFORTRANMODE ) {
923 TokenToLine((UBYTE *)" ");
924 AO.OutSkip = 7;
925 }
926 else if ( ( AO.Optimize.debugflags & 1 ) == 1 ) {}
927 else if ( AO.OutSkip > 0 ) {
928 for ( i = 0; i < AO.OutSkip; i++ ) TokenToLine((UBYTE *)" ");
929 }
930 i = from;
931 do {
932 if ( ( AO.Optimize.debugflags & 1 ) == 1 ) {
933 TokenToLine((UBYTE *)"id ");
934 for ( ii = 3; ii < AO.OutSkip; ii++ ) TokenToLine((UBYTE *)" ");
935 }
936/*
937 if ( AC.OutputMode == NORMALFORMAT ) {
938 TokenToLine((UBYTE *)"id ");
939 }
940*/
941 else if ( AC.OutputMode == FORTRANMODE || AC.OutputMode == PFORTRANMODE ) {}
942 else { TokenToLine((UBYTE *)" "); }
943
944 out = StrCopy((UBYTE *)AC.extrasym,buffer);
945 if ( AC.extrasymbols == 0 ) {
946 out = NumCopy(i,out);
947 out = StrCopy((UBYTE *)"_",out);
948 }
949 else if ( AC.extrasymbols == 1 ) {
950 out = AddArrayIndex(i,out);
951 }
952 out = StrCopy((UBYTE *)"=",out);
953 TokenToLine(buffer);
954 term = C->rhs[i];
955 first = 1;
956 if ( *term == 0 ) {
957 out = StrCopy((UBYTE *)"0",buffer);
958 if ( AC.OutputMode != FORTRANMODE && AC.OutputMode != PFORTRANMODE ) {
959 out = StrCopy((UBYTE *)";",out);
960 }
961 TokenToLine(buffer);
962 }
963 else {
964 while ( *term ) {
965 if ( WriteInnerTerm(term,first) ) Terminate(-1);
966 term += *term;
967 first = 0;
968 }
969 if ( AC.OutputMode != FORTRANMODE && AC.OutputMode != PFORTRANMODE ) {
970 out = StrCopy((UBYTE *)";",buffer);
971 TokenToLine(buffer);
972 }
973 }
974/*
975 There is a problem with FiniLine because it prepares for a
976 continuation line in fortran mode.
977 But the next statement should start on a blank line.
978*/
979/*
980 FiniLine();
981 if ( AC.OutputMode == FORTRANMODE || AC.OutputMode == PFORTRANMODE ) {
982 AO.OutFill = AO.OutputLine;
983 TokenToLine((UBYTE *)" ");
984 AO.OutSkip = 7;
985 }
986*/
987 if ( AC.OutputMode == FORTRANMODE || AC.OutputMode == PFORTRANMODE ) {
988 AO.OutSkip = 6;
989 FiniLine();
990 AO.OutSkip = 7;
991 }
992 else {
993 FiniLine();
994 }
995 i += inc;
996 } while ( i != to );
997}
998
999/*
1000 #] PrintSubtermList :
1001 #[ PrintExtraSymbol :
1002
1003 Prints the definition of extra symbol num as the contents
1004 of the expression in terms.
1005 The parameter par has three options:
1006 EXTRASYMBOL num is interpreted as the number of an extra symbol
1007 REGULARSYMBOL num is interpreted as the number of a symbol.
1008 It could still be an extra symbol.
1009 EXPRESSIONNUMBER num is the number of an expression.
1010 terms contains the rhs expression.
1011*/
1012
1013void PrintExtraSymbol(int num, WORD *terms,int par)
1014{
1015 UBYTE buffer[80], *out, outbuffer[300];
1016 int first, i;
1017 WORD *term;
1018
1019 AO.OutFill = AO.OutputLine = outbuffer;
1020 AO.OutStop = AO.OutputLine+AC.LineLength;
1021 AO.IsBracket = 0;
1022
1023 if ( AC.OutputMode == FORTRANMODE || AC.OutputMode == PFORTRANMODE ) {
1024 TokenToLine((UBYTE *)" ");
1025 AO.OutSkip = 7;
1026 }
1027 else if ( ( AO.Optimize.debugflags & 1 ) == 1 ) {
1028 TokenToLine((UBYTE *)"id ");
1029 for ( i = 3; i < AO.OutSkip; i++ ) TokenToLine((UBYTE *)" ");
1030 }
1031 else if ( AO.OutSkip > 0 ) {
1032 for ( i = 0; i < AO.OutSkip; i++ ) TokenToLine((UBYTE *)" ");
1033 }
1034 out = buffer;
1035 switch ( par ) {
1036 case REGULARSYMBOL:
1037 if ( num >= MAXVARIABLES-cbuf[AM.sbufnum].numrhs ) {
1038 num = MAXVARIABLES-num;
1039 }
1040 else {
1041 out = StrCopy(FindSymbol(num),out);
1042/* out = StrCopy(VARNAME(symbols,num),out); */
1043 break;
1044 }
1045 /* fall through */
1046 case EXTRASYMBOL:
1047 out = StrCopy(FindExtraSymbol(num),out);
1048/*
1049 out = StrCopy((UBYTE *)AC.extrasym,out);
1050 if ( AC.extrasymbols == 0 ) {
1051 out = NumCopy(num,out);
1052 out = StrCopy((UBYTE *)"_",out);
1053 }
1054 else if ( AC.extrasymbols == 1 ) {
1055 out = AddArrayIndex(num,out);
1056 }
1057*/
1058 break;
1059 case EXPRESSIONNUMBER:
1060 out = StrCopy(EXPRNAME(num),out);
1061 break;
1062 default:
1063 MesPrint("Illegal option in PrintExtraSymbol");
1064 Terminate(-1);
1065 }
1066 out = StrCopy((UBYTE *)"=",out);
1067 TokenToLine(buffer);
1068 term = terms;
1069 first = 1;
1070 if ( *term == 0 ) {
1071 out = StrCopy((UBYTE *)"0",buffer);
1072 TokenToLine(buffer);
1073 }
1074 else {
1075 while ( *term ) {
1076 if ( WriteInnerTerm(term,first) ) Terminate(-1);
1077 term += *term;
1078 first = 0;
1079 }
1080 }
1081 if ( AC.OutputMode != FORTRANMODE && AC.OutputMode != PFORTRANMODE ) {
1082 out = StrCopy((UBYTE *)";",buffer);
1083 TokenToLine(buffer);
1084 }
1085 FiniLine();
1086}
1087
1088/*
1089 #] PrintExtraSymbol :
1090 #[ FindSubexpression :
1091
1092 In this routine we look up a subexpression.
1093 If we don't find it we will enter it in the subterm compiler buffer
1094 Searching is by tree structure.
1095 Adding changes the tree.
1096
1097 Notice that in TFORM we should be in sequential mode.
1098*/
1099
1100int FindSubexpression(WORD *subexpr)
1101{
1102 WORD *term;
1103 int number;
1104 CBUF *C = cbuf + AM.sbufnum;
1105 LONG oldCpointer;
1106
1107 term = subexpr;
1108 while ( *term ) term += *term;
1109 number = term - subexpr;
1110/*
1111 We may have to add the subexpression to the tree.
1112 This requires a lock.
1113*/
1114 LOCK(AM.sbuflock);
1115
1116 oldCpointer = C->Pointer-C->Buffer; /* Offset of course !!!!!*/
1117 AddRHS(AM.sbufnum,1);
1118/*
1119 Add the terms to the compiler buffer. Paste on a zero.
1120*/
1121 AddNtoC(AM.sbufnum,number,subexpr,10);
1122 AddToCB(C,0)
1123/*
1124 See whether we have this one already. If not, insert it in the tree.
1125*/
1126 number = InsTree(AM.sbufnum,C->numrhs);
1127/*
1128 Restore old values and return what is needed.
1129*/
1130 if ( number < (C->numrhs) ) { /* It existed already */
1131 C->Pointer = oldCpointer + C->Buffer;
1132 C->numrhs--;
1133 }
1134 else {
1135 GETIDENTITY
1136 WORD dim = DimensionExpression(BHEAD subexpr);
1137/*
1138 Store the dimension
1139*/
1140 C->dimension[number] = dim;
1141 }
1142
1143 UNLOCK(AM.sbuflock);
1144
1145 return(number);
1146}
1147
1148/*
1149 #] FindSubexpression :
1150 #[ ExtraSymFun :
1151*/
1152
1153int ExtraSymFun(PHEAD WORD *term,WORD level)
1154{
1155 WORD *oldworkpointer = AT.WorkPointer;
1156 WORD *termout, *t1, *t2, *t3, *tstop, *tend, i;
1157 int retval = 0;
1158 tend = termout = term + *term;
1159 tstop = tend - ABS(tend[-1]);
1160 t3 = t1 = term+1; t2 = termout+1;
1161/*
1162 First refind the function(s). There is at least one.
1163*/
1164 while ( t1 < tstop ) {
1165 if ( *t1 == EXTRASYMFUN && t1[1] == FUNHEAD+2 ) {
1166 if ( t1[FUNHEAD] == -SNUMBER && t1[FUNHEAD+1] <= numxsymbol
1167 && t1[FUNHEAD+1] > 0 ) {
1168 i = t1[FUNHEAD+1];
1169 }
1170 else if ( t1[FUNHEAD] == -SYMBOL && t1[FUNHEAD+1] < MAXVARIABLES
1171 && t1[FUNHEAD+1] >= MAXVARIABLES-numxsymbol ) {
1172 i = MAXVARIABLES - t1[FUNHEAD+1];
1173 }
1174 else goto nocase;
1175 while ( t3 < t1 ) *t2++ = *t3++;
1176/*
1177 Now inset the rhs pointer
1178*/
1179 *t2++ = SUBEXPRESSION;
1180 *t2++ = SUBEXPSIZE;
1181 *t2++ = i;
1182 *t2++ = 1;
1183 *t2++ = AM.sbufnum;
1184 FILLSUB(t2)
1185 t3 = t1 = t1 + t1[1];
1186 }
1187 else if ( *t1 == EXTRASYMFUN && t1[1] == FUNHEAD ) {
1188 while ( t3 < t1 ) *t2++ = *t3++;
1189 t3 = t1 = t1 + t1[1];
1190 }
1191 else {
1192nocase:;
1193 t1 = t1 + t1[1];
1194 }
1195 }
1196 while ( t3 < tend ) *t2++ = *t3++;
1197 *termout = t2 - termout;
1198 AT.WorkPointer = t2;
1199 if ( AT.WorkPointer >= AT.WorkTop ) {
1200 MLOCK(ErrorMessageLock);
1201 MesWork();
1202 MUNLOCK(ErrorMessageLock);
1203 AT.WorkPointer = oldworkpointer;
1204 return(-1);
1205 }
1206 retval = Generator(BHEAD termout,level);
1207 AT.WorkPointer = oldworkpointer;
1208 if ( retval < 0 ) {
1209 MLOCK(ErrorMessageLock);
1210 MesCall("ExtraSymFun");
1211 MUNLOCK(ErrorMessageLock);
1212 }
1213 return(retval);
1214}
1215
1216/*
1217 #] ExtraSymFun :
1218 #[ PruneExtraSymbols :
1219*/
1220
1221int PruneExtraSymbols(WORD downto)
1222{
1223 CBUF *C = cbuf + AM.sbufnum;
1224 if ( downto < C->numrhs && downto >= 0 ) { /* !!!!! */
1225 ClearTree(AM.sbufnum);
1226 C->numrhs = downto;
1227 if ( downto == 0 ) {
1228 C->Pointer = C->Buffer;
1229 }
1230 else {
1231 WORD *w = C->rhs[downto], i;
1232 while ( *w ) w += *w;
1233 C->Pointer = w+1;
1234 for ( i = 1; i <= downto; i++ ) {
1235 InsTree(AM.sbufnum,i);
1236 }
1237 }
1238 }
1239 return(0);
1240}
1241
1242/*
1243 #] PruneExtraSymbols :
1244*/
WORD * AddRHS(int num, int type)
Definition comtool.c:210
int AddNtoC(int bufnum, int n, WORD *array, int par)
Definition comtool.c:313
int Generator(PHEAD WORD *, WORD)
Definition proces.c:3275
int LocalConvertToPoly(PHEAD WORD *term, WORD *outterm, WORD startebuf, WORD par)
Definition notation.c:514
WORD * dimension
Definition structs.h:979
WORD ** rhs
Definition structs.h:975
WORD * Buffer
Definition structs.h:971
WORD * Pointer
Definition structs.h:973