FORM v5.0.0-35-g6318119
sort.c
Go to the documentation of this file.
1
17/* #[ License : */
18/*
19 * Copyright (C) 1984-2026 J.A.M. Vermaseren
20 * When using this file you are requested to refer to the publication
21 * J.A.M.Vermaseren "New features of FORM" math-ph/0010025
22 * This is considered a matter of courtesy as the development was paid
23 * for by FOM the Dutch physics granting agency and we would like to
24 * be able to track its scientific use to convince FOM of its value
25 * for the community.
26 *
27 * This file is part of FORM.
28 *
29 * FORM is free software: you can redistribute it and/or modify it under the
30 * terms of the GNU General Public License as published by the Free Software
31 * Foundation, either version 3 of the License, or (at your option) any later
32 * version.
33 *
34 * FORM is distributed in the hope that it will be useful, but WITHOUT ANY
35 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
36 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
37 * details.
38 *
39 * You should have received a copy of the GNU General Public License along
40 * with FORM. If not, see <http://www.gnu.org/licenses/>.
41 */
42/* #] License : */
43/*
44 #[ Includes : sort.c
45
46 Sort routines according to new conventions (25-jun-1997).
47 This is more object oriented.
48 The active sort is indicated by AT.SS which should agree with
49 AN.FunSorts[AR.sLevel];
50
51#define GZIPDEBUG
52*/
53#define NEWSPLITMERGE
54/* Comment to turn off Timsort in SplitMerge for debugging: */
55#define NEWSPLITMERGETIMSORT
56/* During SplitMerge, print pointer array state on entry. Very spammy, for debugging. */
57/* #define SPLITMERGEDEBUG */
58/* Debug printing for GarbHand */
59/* #define TESTGARB */
60
61#include "form3.h"
62
63#ifdef WITHPTHREADS
64UBYTE THRbuf[100];
65#endif
66
67#ifdef WITHSTATS
68extern LONG numwrites;
69extern LONG numreads;
70extern LONG numseeks;
71extern LONG nummallocs;
72extern LONG numfrees;
73#endif
74
75/*
76 #] Includes :
77 #[ SortUtilities :
78 #[ WriteStats : void WriteStats(lspace,par,checkLogType)
79*/
80
81char *toterms[] = { " ", " >>", "-->" };
82
83#define HUMANSTRLEN 12
84#define HUMANSUFFLEN 4
85const char humanTermsSuffix[HUMANSUFFLEN][4] = {"K ","M ","B ","T "};
86const char humanBytesSuffix[HUMANSUFFLEN][4] = {"KiB","MiB","GiB","TiB"};
87void HumanString(char* string, float input, const char suffix[HUMANSUFFLEN][4]) {
88 int ind = -1;
89 while (ind < 0 || (input >= 1000.0f && ind < HUMANSUFFLEN) ) {
90 input /= 1000.0f;
91 ind++;
92 }
93 if ( input <= 0.5f ) {
94 snprintf(string, HUMANSTRLEN,
95 " ( <1 %s)", suffix[ind]);
96 }
97 else {
98 snprintf(string, HUMANSTRLEN,
99 " (%3.f %s)", input, suffix[ind]);
100 }
101}
102
103WORD DigitsIn(LONG x) {
104 if ( x < 0 ) x = -x;
105 WORD dig = 1;
106 while ( x > 9 ) {
107 dig++;
108 x /= 10;
109 }
110 return dig;
111}
112
129void WriteStats(POSITION *plspace, WORD par, WORD checkLogType)
130{
131 GETIDENTITY
132 char buf[120];
133 LONG millitime;
134 WORD timepart;
135 SORTING *S;
136 int use_wtime;
137
138 if ( AT.SS == AT.S0 && AC.StatsFlag ) {
139#ifdef WITHPTHREADS
140 if ( AC.ThreadStats == 0 && identity > 0 ) return;
141#elif defined(WITHMPI)
142 if ( AC.OldParallelStats ) return;
143 if ( ! AC.ProcessStats && PF.me != MASTER ) return;
144#endif
145 if ( Expressions == 0 ) return;
146
147 if ( par == STATSSPLITMERGE ) {
148 if ( AC.ShortStatsMax == 0 ) return;
149 AR.ShortSortCount++;
150 if ( AR.ShortSortCount < AC.ShortStatsMax ) return;
151 }
152 AR.ShortSortCount = 0;
153
154 S = AT.SS;
155
156 char humanGenTermsText[HUMANSTRLEN] = "";
157 char humanTermsLeftText[HUMANSTRLEN] = "";
158 char humanBytesText[HUMANSTRLEN] = "";
159 char humanUnsortedBytesText[HUMANSTRLEN] = "";
160 char humanComparisonsText[HUMANSTRLEN] = "";
161 if ( AC.HumanStatsFlag ) {
162 HumanString(humanGenTermsText, (float)(S->GenTerms), humanTermsSuffix);
163 HumanString(humanTermsLeftText, (float)(S->TermsLeft), humanTermsSuffix);
164 HumanString(humanBytesText, (float)(BASEPOSITION(*plspace)), humanBytesSuffix);
165 HumanString(humanUnsortedBytesText, (float)(S->verbUnsortedSize), humanBytesSuffix);
166 HumanString(humanComparisonsText, (float)(S->verbComparisons), humanTermsSuffix);
167 }
168
169 MLOCK(ErrorMessageLock);
170
171 /* If the statistics should not go to the log file, temporarily hide the
172 * LogHandle. This must be done within the ErrorMessageLock region to
173 * avoid a data race between threads. */
174 const WORD oldLogHandle = AC.LogHandle;
175 if ( checkLogType && AM.LogType ) {
176 AC.LogHandle = -1;
177 }
178
179 if ( AC.ShortStats ) {}
180 else {
181#ifdef WITHPTHREADS
182 if ( identity > 0 ) {
183 MesPrint(" Thread %d reporting",identity);
184 }
185 else {
186 MesPrint("");
187 }
188#elif defined(WITHMPI)
189 if ( PF.me != MASTER ) {
190 MesPrint(" Process %d reporting",PF.me);
191 }
192 else {
193 MesPrint("");
194 }
195#else
196 MesPrint("");
197#endif
198 }
199 /*
200 * We define WTimeStatsFlag as a flag to print the wall-clock time on
201 * the *master*, not in workers. This can be confusing in thread
202 * statistics when short statistics is used. Technically,
203 * TimeWallClock() is not thread-safe in TFORM.
204 */
205 use_wtime = AC.WTimeStatsFlag;
206#if defined(WITHPTHREADS)
207 if ( use_wtime && identity > 0 ) use_wtime = 0;
208#elif defined(WITHMPI)
209 if ( use_wtime && PF.me != MASTER ) use_wtime = 0;
210#endif
211 char *wpref = use_wtime ? "W" : "";
212 char *wspac = use_wtime ? "" : " ";
213 millitime = use_wtime ? TimeWallClock(1) * 10 : TimeCPU(1);
214 timepart = (WORD)(millitime%1000);
215 millitime /= 1000;
216 timepart /= 10;
217
218 if ( AC.ShortStats ) {
219#if defined(WITHPTHREADS) || defined(WITHMPI)
220#ifdef WITHPTHREADS
221 if ( identity > 0 ) {
222#else
223 if ( PF.me != MASTER ) {
224 const int identity = PF.me;
225#endif
226 if ( par == STATSSPLITMERGE || par == STATSPOSTSORT ) {
227 snprintf(buf, sizeof(buf),
228 "%d: %7ld.%02us %8ld>%10ld%3s%10ld:%10ld %s %s",identity,
229 millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
230 S->TermsLeft,BASEPOSITION(*plspace),EXPRNAME(AR.CurExpr),
231 AC.Commercial);
232 MesPrint("%s", buf);
233 }
234 else if ( par == STATSMERGETOFILE ) {
235 snprintf(buf, sizeof(buf),
236 "%d: %7ld.%02us %10ld:%10ld",identity,millitime,timepart,
237 S->TermsLeft,BASEPOSITION(*plspace));
238 MesPrint("%s", buf);
239 }
240 }
241 else
242#endif
243 {
244 if ( par == STATSSPLITMERGE || par == STATSPOSTSORT ) {
245 snprintf(buf, sizeof(buf),
246 "%7ld.%02us %8ld>%10ld%3s%10ld:%10ld %s %s",
247 millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
248 S->TermsLeft,BASEPOSITION(*plspace),EXPRNAME(AR.CurExpr),
249 AC.Commercial);
250 MesPrint("%s", buf);
251 }
252 else if ( par == STATSMERGETOFILE ) {
253 snprintf(buf, sizeof(buf),
254 "%7ld.%02us %10ld:%10ld",millitime,timepart,
255 S->TermsLeft,BASEPOSITION(*plspace));
256 MesPrint("%s", buf);
257 }
258 }
259 }
260 else {
261 if ( par == STATSMERGETOFILE ) {
262 snprintf(buf, sizeof(buf),
263 "%sTime = %7ld.%02u sec",wpref,millitime,timepart);
264 MesPrint("%s", buf);
265 }
266 else {
267 snprintf(buf, sizeof(buf),
268 "%sTime = %7ld.%02u sec %sGenerated terms = %10ld%s",
269 wpref,millitime,timepart,wspac,S->GenTerms,humanGenTermsText);
270 MesPrint("%s", buf);
271 }
272
273 if ( par == STATSSPLITMERGE ) {
274 snprintf(buf, sizeof(buf),
275 "%16s%8ld Terms %s = %10ld%s",
276 EXPRNAME(AR.CurExpr),AN.ninterms,FG.swmes[par],S->TermsLeft,
277 humanTermsLeftText);
278 MesPrint("%s", buf);
279 }
280 else {
281#ifdef WITHPTHREADS
282 if ( identity > 0 && par == STATSPOSTSORT ) {
283 snprintf(buf, sizeof(buf),
284 "%16s Terms in thread = %10ld%s",
285 EXPRNAME(AR.CurExpr),S->TermsLeft,humanTermsLeftText);
286 MesPrint("%s", buf);
287 }
288 else
289#elif defined(WITHMPI)
290 if ( PF.me != MASTER && par == STATSPOSTSORT ) {
291 snprintf(buf, sizeof(buf),
292 "%16s Terms in process= %10ld%s",
293 EXPRNAME(AR.CurExpr),S->TermsLeft,humanTermsLeftText);
294 MesPrint("%s", buf);
295 }
296 else
297#endif
298 {
299 snprintf(buf, sizeof(buf),
300 "%16s Terms %s = %10ld%s",
301 EXPRNAME(AR.CurExpr),FG.swmes[par],S->TermsLeft,
302 humanTermsLeftText);
303 MesPrint("%s", buf);
304 }
305 }
306
307 const WORD dig = DigitsIn(BASEPOSITION(*plspace));
308 snprintf(buf, sizeof(buf), "%24s Bytes used%*s=%11ld%s",
309 AC.Commercial,MiN(6,17-dig),"",BASEPOSITION(*plspace),
310 humanBytesText);
311 MesPrint("%s", buf);
312 }
313
314 if ( par == STATSPOSTSORT ) {
315 if ( AC.SortVerbose ) {
316 snprintf(buf, sizeof(buf), "%24s Unsorted bytes =%11ld%s",
317 "",S->verbUnsortedSize,humanUnsortedBytesText);
318 MesPrint("%s", buf);
319 snprintf(buf, sizeof(buf), "%24s Small Buffer =%5ld,%5ld",
320 "",S->verbSBsortTerms,S->verbSBsortCap);
321 MesPrint("%s", buf);
322 snprintf(buf, sizeof(buf), "%24s Large Buffer =%5ld,%5ld",
323 "",S->verbLBsortPatches,S->verbLBsortCap);
324 MesPrint("%s", buf);
325 snprintf(buf, sizeof(buf), "%24s Comparisons =%11ld%s",
326 "",S->verbComparisons,humanComparisonsText);
327 MesPrint("%s", buf);
328 }
329 }
330
331#ifdef WITHSTATS
332 MesPrint("Total number of writes: %l, reads: %l, seeks, %l"
333 ,numwrites,numreads,numseeks);
334 MesPrint("Total number of mallocs: %l, frees: %l"
335 ,nummallocs,numfrees);
336#endif
337 /* Put back the original LogHandle, it was changed if the statistics were
338 * not printed in the log file. */
339 AC.LogHandle = oldLogHandle;
340
341 MUNLOCK(ErrorMessageLock);
342 }
343}
344
345/*
346 #] WriteStats :
347 #[ NewSort : WORD NewSort()
348*/
359int NewSort(PHEAD0)
360{
361 GETBIDENTITY
362 SORTING *S, **newFS;
363 int i, newsize;
364 if ( AN.SoScratC == 0 )
365 AN.SoScratC = (UWORD *)Malloc1(2*(AM.MaxTal+2)*sizeof(UWORD),"NewSort");
366 AR.sLevel++;
367 if ( AR.sLevel >= AN.NumFunSorts ) {
368 if ( AN.NumFunSorts == 0 ) newsize = 100;
369 else newsize = 2*AN.NumFunSorts;
370 newFS = (SORTING **)Malloc1((newsize+1)*sizeof(SORTING *),"FunSort pointers");
371 for ( i = 0; i < AN.NumFunSorts; i++ ) newFS[i] = AN.FunSorts[i];
372 for ( ; i <= newsize; i++ ) newFS[i] = 0;
373 if ( AN.FunSorts ) M_free(AN.FunSorts,"FunSort pointers");
374 AN.FunSorts = newFS; AN.NumFunSorts = newsize;
375 }
376 if ( AR.sLevel == 0 ) {
377
378 AN.FunSorts[0] = AT.S0;
379 if ( AR.PolyFun == 0 ) { AT.S0->PolyFlag = 0; }
380 else if ( AR.PolyFunType == 1 ) { AT.S0->PolyFlag = 1; }
381 else if ( AR.PolyFunType == 2 ) {
382 if ( AR.PolyFunExp == 2
383 || AR.PolyFunExp == 3 ) AT.S0->PolyFlag = 1;
384 else AT.S0->PolyFlag = 2;
385 }
386 AR.ShortSortCount = 0;
387 }
388 else {
389 if ( AN.FunSorts[AR.sLevel] == 0 ) {
390 AN.FunSorts[AR.sLevel] = AllocSort(
391 AM.SLargeSize,AM.SSmallSize,AM.SSmallEsize,AM.STermsInSmall
392 ,AM.SMaxPatches,AM.SMaxFpatches,AM.SIOsize,1);
393 }
394 AN.FunSorts[AR.sLevel]->PolyFlag = 0;
395 }
396 AT.SS = S = AN.FunSorts[AR.sLevel];
397 S->sFill = S->sBuffer;
398 S->lFill = S->lBuffer;
399 S->lPatch = 0;
400 S->fPatchN = 0;
401 S->GenTerms = S->TermsLeft = S->GenSpace = S->SpaceLeft = 0;
402 S->PoinFill = S->sPointer;
403 *S->PoinFill = S->sFill;
404 if ( AR.sLevel > 0 ) { S->PolyWise = 0; }
405 PUTZERO(S->SizeInFile[0]); PUTZERO(S->SizeInFile[1]); PUTZERO(S->SizeInFile[2]);
406 S->sTerms = 0;
407 PUTZERO(S->file.POposition);
408 S->stage4 = 0;
409 if ( AR.sLevel > AN.MaxFunSorts ) AN.MaxFunSorts = AR.sLevel;
410/*
411 The next variable is for the staged sort only.
412 It should be treated differently
413
414 PUTZERO(AN.OldPosOut);
415*/
416 // Zero the SortVerbose counters:
417 S->verbComparisons = 0;
418 S->verbSBsortTerms = 0;
419 S->verbSBsortCap = 0;
420 S->verbLBsortPatches = 0;
421 S->verbLBsortCap = 0;
422 S->verbUnsortedSize = 0;
423 return(0);
424}
425
426/*
427 #] NewSort :
428 #[ EndSort : WORD EndSort(PHEAD buffer,par)
429*/
454LONG EndSort(PHEAD WORD *buffer, int par)
455{
456 GETBIDENTITY
457 SORTING *S = AT.SS;
458 WORD j, **ss, *to, *t;
459 LONG sSpace, over, tover, spare, retval = 0;
460 POSITION position, pp;
461 off_t lSpace;
462 FILEHANDLE *fout = 0, *oldoutfile = 0, *newout = 0;
463
464 if ( AM.exitflag && AR.sLevel == 0 ) return(0);
465#ifdef WITHMPI
466 if( (retval = PF_EndSort()) > 0){
467 oldoutfile = AR.outfile;
468 retval = 0;
469 goto RetRetval;
470 }
471 else if(retval < 0){
472 retval = -1;
473 goto RetRetval;
474 }
475 /* PF_EndSort returned 0: for S != AM.S0 and slaves still do the regular sort */
476#endif /* WITHMPI */
477 oldoutfile = AR.outfile;
478/* PolyFlag repair action
479 if ( S == AT.S0 ) {
480 if ( AR.PolyFun == 0 ) { S->PolyFlag = 0; }
481 else if ( AR.PolyFunType == 1 ) { S->PolyFlag = 1; }
482 else if ( AR.PolyFunType == 2 ) {
483 if ( AR.PolyFunExp == 2
484 || AR.PolyFunExp == 3 ) S->PolyFlag = 1;
485 else S->PolyFlag = 2;
486 }
487 S->PolyWise = 0;
488 }
489 else {
490 S->PolyFlag = S->PolyWise = 0;
491 }
492*/
493 S->PolyWise = 0;
494 *(S->PoinFill) = 0;
495#ifdef SPLITTIME
496 PrintTime((UBYTE *)"EndSort, before SplitMerge");
497#endif
498 S->sPointer[SplitMerge(BHEAD S->sPointer,S->sTerms)] = 0;
499#ifdef SPLITTIME
500 PrintTime((UBYTE *)"Endsort, after SplitMerge");
501#endif
502 sSpace = 0;
503 tover = over = S->sTerms;
504 ss = S->sPointer;
505 if ( over >= 0 ) {
506 if ( S->lPatch > 0 || S->file.handle >= 0 ) {
507 ss[over] = 0;
508 sSpace = ComPress(ss,&spare);
509 S->TermsLeft -= over - spare;
510 if ( par == 1 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
511 }
512 else if ( S != AT.S0 ) {
513 ss[over] = 0;
514 if ( par == 2 ) {
515 sSpace = 3;
516 while ( ( t = *ss++ ) != 0 ) { sSpace += *t; }
517 if ( AN.tryterm > 0 && ( (sSpace+1)*sizeof(WORD) < (size_t)(AM.MaxTer) ) ) {
518 to = TermMalloc("$-sort space");
519 }
520 else {
521 LONG allocsp = sSpace+1;
522 if ( allocsp < MINALLOC ) allocsp = MINALLOC;
523 allocsp = ((allocsp+7)/8)*8;
524 to = (WORD *)Malloc1(allocsp*sizeof(WORD),"$-sort space");
525 if ( AN.tryterm > 0 ) AN.tryterm = 0;
526 }
527 *((WORD **)buffer) = to;
528 ss = S->sPointer;
529 while ( ( t = *ss++ ) != 0 ) {
530 j = *t; while ( --j >= 0 ) *to++ = *t++;
531 }
532 *to = 0;
533 retval = sSpace + 1;
534 }
535 else {
536 to = buffer;
537 sSpace = 0;
538 while ( ( t = *ss++ ) != 0 ) {
539 j = *t;
540 if ( ( sSpace += j ) > AM.MaxTer/((LONG)sizeof(WORD)) ) {
541 /* Too big! Get the total size for useful error message */
542 while ( ( t = *ss++ ) != 0 ) {
543 sSpace += *t;
544 }
545 MLOCK(ErrorMessageLock);
546 MesPrint("Sorted function argument too long (%d words). Increase MaxTermSize (%l words).", sSpace, AM.MaxTer/((LONG)sizeof(WORD)));
547 MUNLOCK(ErrorMessageLock);
548 retval = -1; goto RetRetval;
549 }
550 while ( --j >= 0 ) *to++ = *t++;
551 }
552 *to = 0;
553 retval = to - buffer;
554 }
555 goto RetRetval;
556 }
557 else {
558 POSITION oldpos;
559 if ( S == AT.S0 ) {
560 fout = AR.outfile;
561 *AR.CompressPointer = 0;
562 SeekScratch(AR.outfile,&position);
563 }
564 else {
565 fout = &(S->file);
566 PUTZERO(position);
567 }
568 oldpos = position;
569 S->TermsLeft = 0;
570/*
571 Here we can go directly to the output.
572*/
573#ifdef WITHZLIB
574 { int oldgzipCompress = AR.gzipCompress;
575 AR.gzipCompress = 0;
576#endif
577 if ( tover > 0 ) {
578 ss = S->sPointer;
579 while ( ( t = *ss++ ) != 0 ) {
580 if ( *t ) S->TermsLeft++;
581#ifdef WITHPTHREADS
582 if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD t); }
583 else
584#endif
585 if ( PutOut(BHEAD t,&position,fout,1) < 0 ) {
586 retval = -1; goto RetRetval;
587 }
588 }
589 }
590#ifdef WITHPTHREADS
591 if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD 0); }
592 else
593#endif
594 if ( FlushOut(&position,fout,1) ) {
595 retval = -1; goto RetRetval;
596 }
597#ifdef WITHZLIB
598 AR.gzipCompress = oldgzipCompress;
599 }
600#endif
601#ifdef WITHPTHREADS
602 if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
603#endif
604#ifdef WITHMPI
605 if ( PF.me != MASTER && PF.exprtodo < 0 ) goto RetRetval;
606#endif
607 DIFPOS(oldpos,position,oldpos);
608 S->SpaceLeft = BASEPOSITION(oldpos);
609 WriteStats(&oldpos,STATSPOSTSORT,NOCHECKLOGTYPE);
610 pp = oldpos;
611 goto RetRetval;
612 }
613 }
614 else if ( par == 1 && newout == 0 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
615 sSpace++;
616 lSpace = sSpace + (S->lFill - S->lBuffer) - (LONG)S->lPatch*(AM.MaxTer/sizeof(WORD));
617/* Note wrt MaxTer and lPatch: each patch starts with space for decompression */
618/* Not needed if only large buffer, but needed when using files (?) */
619 SETBASEPOSITION(pp,lSpace);
620 MULPOS(pp,sizeof(WORD));
621 if ( S->file.handle >= 0 ) {
622 ADD2POS(pp,S->fPatches[S->fPatchN]);
623 }
624 if ( S == AT.S0 ) {
625 if ( S->lPatch > 0 || S->file.handle >= 0 ) {
626 WriteStats(&pp,STATSSPLITMERGE,CHECKLOGTYPE);
627 }
628 }
629 if ( par == 2 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
630 if ( S->lPatch > 0 ) {
631 if ( ( S->lPatch >= S->MaxPatches ) ||
632 ( ( (WORD *)(((UBYTE *)(S->lFill + sSpace)) + 2*AM.MaxTer) ) >= S->lTop ) ) {
633/*
634 The large buffer is too full. Merge and write it
635*/
636 // Update SortVerbose counters
637 if ( S->lPatch >= S->MaxPatches ) S->verbLBsortPatches++;
638 else S->verbLBsortCap++;
639
640#ifdef GZIPDEBUG
641 MLOCK(ErrorMessageLock);
642 MesPrint("%w EndSort: lPatch = %d, MaxPatches = %d,lFill = %x, sSpace = %ld, MaxTer = %d, lTop = %x"
643 ,S->lPatch,S->MaxPatches,S->lFill,sSpace,AM.MaxTer/sizeof(WORD),S->lTop);
644 MUNLOCK(ErrorMessageLock);
645#endif
646
647 if ( MergePatches(1) ) {
648 MLOCK(ErrorMessageLock);
649 MesCall("EndSort");
650 MUNLOCK(ErrorMessageLock);
651 retval = -1; goto RetRetval;
652 }
653 S->lPatch = 0;
654 pp = S->SizeInFile[1];
655 MULPOS(pp,sizeof(WORD));
656#ifndef WITHPTHREADS
657 if ( S == AT.S0 )
658#endif
659 {
660 POSITION pppp;
661 SETBASEPOSITION(pppp,0);
662 SeekFile(S->file.handle,&pppp,SEEK_CUR);
663 SeekFile(S->file.handle,&pp,SEEK_END);
664 SeekFile(S->file.handle,&pppp,SEEK_SET);
665 WriteStats(&pp,STATSMERGETOFILE,CHECKLOGTYPE);
666 UpdateMaxSize();
667 }
668 }
669 else {
670 S->Patches[S->lPatch++] = S->lFill;
671 to = (WORD *)(((UBYTE *)(S->lFill)) + AM.MaxTer);
672 if ( tover > 0 ) {
673 ss = S->sPointer;
674 while ( ( t = *ss++ ) != 0 ) {
675 j = *t;
676 if ( j < 0 ) j = t[1] + 2;
677 while ( --j >= 0 ) *to++ = *t++;
678 }
679 }
680 *to++ = 0;
681 S->lFill = to;
682 if ( S->file.handle < 0 ) {
683 if ( MergePatches(2) ) {
684 MLOCK(ErrorMessageLock);
685 MesCall("EndSort");
686 MUNLOCK(ErrorMessageLock);
687 retval = -1; goto RetRetval;
688 }
689 if ( S == AT.S0 ) {
690 pp = S->SizeInFile[2];
691 MULPOS(pp,sizeof(WORD));
692#ifdef WITHPTHREADS
693 if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
694#endif
695 WriteStats(&pp,STATSPOSTSORT,NOCHECKLOGTYPE);
696 UpdateMaxSize();
697 }
698 else {
699 if ( par == 2 && newout->handle >= 0 ) {
700 POSITION zeropos;
701 PUTZERO(zeropos);
702#ifdef ALLLOCK
703 LOCK(newout->pthreadslock);
704#endif
705 SeekFile(newout->handle,&zeropos,SEEK_SET);
706 to = (WORD *)Malloc1(BASEPOSITION(newout->filesize)+sizeof(WORD)*2
707 ,"$-buffer reading");
708 if ( AN.tryterm > 0 ) AN.tryterm = 0;
709 if ( ( retval = ReadFile(newout->handle,(UBYTE *)to,BASEPOSITION(newout->filesize)) ) !=
710 BASEPOSITION(newout->filesize) ) {
711 MLOCK(ErrorMessageLock);
712 MesPrint("Error reading information for $ variable");
713 MUNLOCK(ErrorMessageLock);
714 M_free(to,"$-buffer reading");
715 retval = -1;
716 }
717 else {
718 *((WORD **)buffer) = to;
719 retval /= sizeof(WORD);
720 }
721#ifdef ALLLOCK
722 UNLOCK(newout->pthreadslock);
723#endif
724 }
725 else if ( newout->handle >= 0 ) {
726/*
727 We land here if par == 1 (function arg sort) and PutOut has created a file.
728 This means that the term is larger than SIOsize, which we ensure is at least
729 as large as MaxTermSize in setfile.c. Thus we know already that the term won't fit.
730*/
731TooLarge:
732 MLOCK(ErrorMessageLock);
733 MesPrint("(1)Output should fit inside a single term. Increase MaxTermSize?");
734 MesCall("EndSort");
735 MUNLOCK(ErrorMessageLock);
736 retval = -1; goto RetRetval;
737 }
738 else {
739 t = newout->PObuffer;
740 // We deal with the par == 2 case after RetRetval.
741 if ( par != 2 ) {
742 j = newout->POfill - t;
743 to = buffer;
744 if ( to >= AT.WorkSpace && to < AT.WorkTop && to+j > AT.WorkTop )
745 goto WorkSpaceError;
746 if ( j > AM.MaxTer ) {
747 MLOCK(ErrorMessageLock);
748 MesPrint("Encountered term of size: %d words.", j/(LONG)sizeof(WORD) );
749 MUNLOCK(ErrorMessageLock);
750 goto TooLarge;
751 }
752 NCOPY(to,t,j);
753 retval = to - buffer - 1;
754 }
755 }
756 }
757 goto RetRetval;
758 }
759 if ( MergePatches(1) ) { /* --> SortFile */
760 MLOCK(ErrorMessageLock);
761 MesCall("EndSort");
762 MUNLOCK(ErrorMessageLock);
763 retval = -1; goto RetRetval;
764 }
765 UpdateMaxSize();
766 pp = S->SizeInFile[1];
767 MULPOS(pp,sizeof(WORD));
768#ifndef WITHPTHREADS
769 if ( S == AT.S0 )
770#endif
771 {
772 POSITION pppp;
773 SETBASEPOSITION(pppp,0);
774 SeekFile(S->file.handle,&pppp,SEEK_CUR);
775 SeekFile(S->file.handle,&pp,SEEK_END);
776 SeekFile(S->file.handle,&pppp,SEEK_SET);
777 WriteStats(&pp,STATSMERGETOFILE,CHECKLOGTYPE);
778 }
779#ifdef WITHERRORXXX
780 if ( S != AT.S0 ) {
781/*
782 This is wrong! We have sorted to the sort file.
783 Things are not sitting in the output yet.
784*/
785 if ( newout->handle >= 0 ) goto TooLarge;
786 t = newout->PObuffer;
787 j = newout->POfill - t;
788 to = buffer;
789 if ( to >= AT.WorkSpace && to < AT.WorkTop && to+j > AT.WorkTop )
790 goto WorkSpaceError;
791 if ( j > AM.MaxTer ) goto TooLarge;
792 NCOPY(to,t,j);
793 goto RetRetval;
794 }
795#endif
796 }
797 }
798 if ( S->file.handle >= 0 ) {
799#ifdef GZIPDEBUG
800 MLOCK(ErrorMessageLock);
801 MesPrint("%w EndSort: fPatchN = %d, lPatch = %d, position = %12p"
802 ,S->fPatchN,S->lPatch,&(S->fPatches[S->fPatchN]));
803 MUNLOCK(ErrorMessageLock);
804#endif
805 if ( S->lPatch <= 0 ) {
806 StageSort(&(S->file));
807 position = S->fPatches[S->fPatchN];
808 ss = S->sPointer;
809 if ( *ss ) {
810 *AR.CompressPointer = 0;
811#ifdef WITHZLIB
812 if ( S == AT.S0 && AR.NoCompress == 0 && AR.gzipCompress > 0 )
813 S->fpcompressed[S->fPatchN] = 1;
814 else
815 S->fpcompressed[S->fPatchN] = 0;
816 SetupOutputGZIP(&(S->file));
817#endif
818 while ( ( t = *ss++ ) != 0 ) {
819 if ( PutOut(BHEAD t,&position,&(S->file),1) < 0 ) {
820 retval = -1; goto RetRetval;
821 }
822 }
823 if ( FlushOut(&position,&(S->file),1) ) {
824 retval = -1; goto RetRetval;
825 }
826 ++(S->fPatchN);
827 S->fPatches[S->fPatchN] = position;
828 UpdateMaxSize();
829#ifdef GZIPDEBUG
830 MLOCK(ErrorMessageLock);
831 MesPrint("%w EndSort+: fPatchN = %d, lPatch = %d, position = %12p"
832 ,S->fPatchN,S->lPatch,&(S->fPatches[S->fPatchN]));
833 MUNLOCK(ErrorMessageLock);
834#endif
835 }
836 }
837 AR.Stage4Name = 0;
838#ifdef WITHPTHREADS
839 if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
840 if ( S->file.handle >= 0 ) {
841 SynchFile(S->file.handle);
842 }
843 }
844#endif
845 UpdateMaxSize();
846 if ( MergePatches(0) ) {
847 MLOCK(ErrorMessageLock);
848 MesCall("EndSort");
849 MUNLOCK(ErrorMessageLock);
850 retval = -1; goto RetRetval;
851 }
852 S->stage4 = 0;
853#ifdef WITHPTHREADS
854 if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
855#endif
856 pp = S->SizeInFile[0];
857 MULPOS(pp,sizeof(WORD));
858 WriteStats(&pp,STATSPOSTSORT,NOCHECKLOGTYPE);
859 UpdateMaxSize();
860 }
861RetRetval:
862
863#ifdef WITHMPI
864 /* NOTE: PF_EndSort has been changed such that it sets S->TermsLeft. (TU 30 Jun 2011) */
865 if ( AR.sLevel == 0 && (PF.me == MASTER || PF.exprtodo >= 0) ) {
866 Expressions[AR.CurExpr].counter = S->TermsLeft;
867 Expressions[AR.CurExpr].size = pp;
868 }
869#else
870 if ( AR.sLevel == 0 ) {
871 Expressions[AR.CurExpr].counter = S->TermsLeft;
872 Expressions[AR.CurExpr].size = pp;
873 }/*if ( AR.sLevel == 0 )*/
874#endif
875/*:[25nov2003 mt]*/
876 if ( S->file.handle >= 0 && ( par != 1 ) && ( par != 2 ) ) {
877 /* sortfile is still open */
878 UpdateMaxSize();
879#ifdef WITHZLIB
880 ClearSortGZIP(&(S->file));
881#endif
882 CloseFile(S->file.handle);
883 S->file.handle = -1;
884 remove(S->file.name);
885#ifdef GZIPDEBUG
886 MLOCK(ErrorMessageLock);
887 MesPrint("%wEndSort: sortfile %s removed",S->file.name);
888 MUNLOCK(ErrorMessageLock);
889#endif
890 }
891 AR.outfile = oldoutfile;
892 AR.sLevel--;
893 if ( AR.sLevel >= 0 ) AT.SS = AN.FunSorts[AR.sLevel];
894 if ( par == 1 ) {
895 if ( retval < 0 ) {
896 UpdateMaxSize();
897 if ( newout ) {
898 DeAllocFileHandle(newout);
899 newout = 0;
900 }
901 }
902 else if ( newout ) {
903 if ( newout->handle >= 0 ) {
904 MLOCK(ErrorMessageLock);
905 MesPrint("(2)Output should fit inside a single term. Increase MaxTermSize?");
906 MesCall("EndSort");
907 MUNLOCK(ErrorMessageLock);
908 Terminate(-1);
909 }
910 else if ( newout->POfill > newout->PObuffer ) {
911/*
912 Here we have to copy the contents of the 'file' into
913 the buffer. We assume that this buffer lies in the WorkSpace.
914 Hence
915*/
916 j = newout->POfill-newout->PObuffer;
917 if ( buffer >= AT.WorkSpace && buffer < AT.WorkTop && buffer+j > AT.WorkTop )
918 goto WorkSpaceError;
919 else {
920 to = buffer; t = newout->PObuffer;
921 while ( j-- > 0 ) *to++ = *t++;
922 }
923 UpdateMaxSize();
924 }
925 DeAllocFileHandle(newout);
926 newout = 0;
927 }
928 }
929 else if ( par == 2 ) {
930 if ( newout ) {
931 if ( retval == 0 ) {
932 if ( newout->handle >= 0 ) {
933/*
934 output resides at the moment in a file
935 Find the size, make a buffer, copy into the buffer and clean up.
936*/
937 POSITION zeropos;
938 PUTZERO(position);
939#ifdef ALLLOCK
940 LOCK(newout->pthreadslock);
941#endif
942 SeekFile(newout->handle,&position,SEEK_END);
943 PUTZERO(zeropos);
944 SeekFile(newout->handle,&zeropos,SEEK_SET);
945 to = (WORD *)Malloc1(BASEPOSITION(position)+sizeof(WORD)*3
946 ,"$-buffer reading");
947 if ( AN.tryterm > 0 ) AN.tryterm = 0;
948 if ( ( retval = ReadFile(newout->handle,(UBYTE *)to,BASEPOSITION(position)) ) !=
949 BASEPOSITION(position) ) {
950 MLOCK(ErrorMessageLock);
951 MesPrint("Error reading information for $ variable");
952 MUNLOCK(ErrorMessageLock);
953 M_free(to,"$-buffer reading");
954 retval = -1;
955 }
956 else {
957 *((WORD **)buffer) = to;
958 retval /= sizeof(WORD);
959 }
960#ifdef ALLLOCK
961 UNLOCK(newout->pthreadslock);
962#endif
963 }
964 else {
965/*
966 output resides in the cache buffer and the file was never opened
967*/
968 LONG wsiz = newout->POfill - newout->PObuffer;
969 if ( AN.tryterm > 0 && ( (wsiz+2)*sizeof(WORD) < (size_t)(AM.MaxTer) ) ) {
970 to = TermMalloc("$-sort space");
971 }
972 else {
973 LONG allocsp = wsiz+2;
974 if ( allocsp < MINALLOC ) allocsp = MINALLOC;
975 allocsp = ((allocsp+7)/8)*8;
976 to = (WORD *)Malloc1(allocsp*sizeof(WORD),"$-buffer reading");
977 if ( AN.tryterm > 0 ) AN.tryterm = 0;
978 }
979 *((WORD **)buffer) = to; t = newout->PObuffer;
980 retval = wsiz;
981 NCOPY(to,t,wsiz);
982 }
983 }
984 UpdateMaxSize();
985 DeAllocFileHandle(newout);
986 newout = 0;
987 }
988 }
989 else {
990 if ( newout ) {
991 DeAllocFileHandle(newout);
992 newout = 0;
993 }
994 }
995
996 return(retval);
997WorkSpaceError:
998 MLOCK(ErrorMessageLock);
999 MesWork();
1000 MesCall("EndSort");
1001 MUNLOCK(ErrorMessageLock);
1002 Terminate(-1);
1003 return(-1);
1004}
1005
1006/*
1007 #] EndSort :
1008 #[ PutIn : LONG PutIn(handle,position,buffer,take,npat)
1009*/
1025LONG PutIn(FILEHANDLE *file, POSITION *position, WORD *buffer, WORD **take, int npat)
1026{
1027 LONG i, RetCode;
1028 WORD *from, *to;
1029#ifndef WITHZLIB
1030 DUMMYUSE(npat);
1031#endif
1032 from = buffer + ( file->POsize * sizeof(UBYTE) )/sizeof(WORD);
1033 i = from - *take;
1034 if ( i*((LONG)(sizeof(WORD))) > AM.MaxTer ) {
1035 MLOCK(ErrorMessageLock);
1036 MesPrint("Problems in PutIn");
1037 MUNLOCK(ErrorMessageLock);
1038 Terminate(-1);
1039 }
1040 to = buffer;
1041 while ( --i >= 0 ) *--to = *--from;
1042 *take = to;
1043#ifdef WITHZLIB
1044 if ( ( RetCode = FillInputGZIP(file,position,(UBYTE *)buffer
1045 ,file->POsize,npat) ) < 0 ) {
1046 MLOCK(ErrorMessageLock);
1047 MesPrint("PutIn: We have RetCode = %x while reading %x bytes",
1048 RetCode,file->POsize);
1049 MUNLOCK(ErrorMessageLock);
1050 Terminate(-1);
1051 }
1052#else
1053#ifdef ALLLOCK
1054 LOCK(file->pthreadslock);
1055#endif
1056 SeekFile(file->handle,position,SEEK_SET);
1057 if ( ( RetCode = ReadFile(file->handle,(UBYTE *)buffer,file->POsize) ) < 0 ) {
1058#ifdef ALLLOCK
1059 UNLOCK(file->pthreadslock);
1060#endif
1061 MLOCK(ErrorMessageLock);
1062 MesPrint("PutIn: We have RetCode = %x while reading %x bytes",
1063 RetCode,file->POsize);
1064 MUNLOCK(ErrorMessageLock);
1065 Terminate(-1);
1066 }
1067#ifdef ALLLOCK
1068 UNLOCK(file->pthreadslock);
1069#endif
1070#endif
1071 return(RetCode);
1072}
1073
1074/*
1075 #] PutIn :
1076 #[ Sflush : WORD Sflush(file)
1077*/
1086{
1087 LONG size, RetCode;
1088#ifdef WITHZLIB
1089 GETIDENTITY
1090 int dobracketindex = 0;
1091 if ( AR.sLevel <= 0 && Expressions[AR.CurExpr].newbracketinfo
1092 && ( fi == AR.outfile || fi == AR.hidefile ) ) dobracketindex = 1;
1093#endif
1094 if ( fi->handle < 0 ) {
1095 if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
1096#ifdef GZIPDEBUG
1097 MLOCK(ErrorMessageLock);
1098 MesPrint("%w Sflush created scratch file %s",fi->name);
1099 MUNLOCK(ErrorMessageLock);
1100#endif
1101 fi->handle = (WORD)RetCode;
1102 PUTZERO(fi->filesize);
1103 PUTZERO(fi->POposition);
1104 }
1105 else {
1106 MLOCK(ErrorMessageLock);
1107 MesPrint("Cannot create scratch file %s",fi->name);
1108 MUNLOCK(ErrorMessageLock);
1109 return(-1);
1110 }
1111 }
1112#ifdef WITHZLIB
1113 if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
1114 && dobracketindex == 0 ) {
1115 if ( FlushOutputGZIP(fi) ) return(-1);
1116 fi->POfill = fi->PObuffer;
1117 }
1118 else
1119#endif
1120 {
1121#ifdef ALLLOCK
1122 LOCK(fi->pthreadslock);
1123#endif
1124 size = (fi->POfill-fi->PObuffer)*sizeof(WORD);
1125 SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
1126 if ( WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),size) != size ) {
1127#ifdef ALLLOCK
1128 UNLOCK(fi->pthreadslock);
1129#endif
1130 MLOCK(ErrorMessageLock);
1131 MesPrint("Write error while finishing sort. Disk full?");
1132 MUNLOCK(ErrorMessageLock);
1133 return(-1);
1134 }
1135 ADDPOS(fi->filesize,size);
1136 ADDPOS(fi->POposition,size);
1137 fi->POfill = fi->PObuffer;
1138#ifdef ALLLOCK
1139 UNLOCK(fi->pthreadslock);
1140#endif
1141 }
1142 return(0);
1143}
1144
1145/*
1146 #] Sflush :
1147 #[ PutOut : WORD PutOut(term,position,file,ncomp)
1148*/
1171WORD PutOut(PHEAD WORD *term, POSITION *position, FILEHANDLE *fi, WORD ncomp)
1172{
1173 GETBIDENTITY
1174 WORD i, *p, ret, *r, *rr, j, k, first;
1175 int dobracketindex = 0;
1176 LONG RetCode;
1177
1178 if ( AT.SS != AT.S0 ) {
1179/*
1180 For this case no compression should be used
1181*/
1182 if ( ( i = *term ) <= 0 ) return(0);
1183 ret = i;
1184 ADDPOS(*position,i*sizeof(WORD));
1185 p = fi->POfill;
1186 do {
1187 if ( p >= fi->POstop ) {
1188 if ( fi->handle < 0 ) {
1189 if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
1190#ifdef GZIPDEBUG
1191 MLOCK(ErrorMessageLock);
1192 MesPrint("%w PutOut created sortfile %s",fi->name);
1193 MUNLOCK(ErrorMessageLock);
1194#endif
1195 fi->handle = (WORD)RetCode;
1196 PUTZERO(fi->filesize);
1197 PUTZERO(fi->POposition);
1198/*
1199 Should not be here anymore?
1200#ifdef WITHZLIB
1201 fi->ziobuffer = 0;
1202#endif
1203*/
1204 }
1205 else {
1206 MLOCK(ErrorMessageLock);
1207 MesPrint("Cannot create scratch file %s",fi->name);
1208 MUNLOCK(ErrorMessageLock);
1209 return(-1);
1210 }
1211 }
1212#ifdef ALLLOCK
1213 LOCK(fi->pthreadslock);
1214#endif
1215 if ( fi == AR.hidefile ) {
1216 LOCK(AS.inputslock);
1217 }
1218 SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
1219 if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize) ) != fi->POsize ) {
1220 if ( fi == AR.hidefile ) {
1221 UNLOCK(AS.inputslock);
1222 }
1223#ifdef ALLLOCK
1224 UNLOCK(fi->pthreadslock);
1225#endif
1226 MLOCK(ErrorMessageLock);
1227 MesPrint("Write error during sort. Disk full?");
1228 MesPrint("Attempt to write %l bytes on file %d at position %15p",
1229 fi->POsize,fi->handle,&(fi->POposition));
1230 MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
1231 MUNLOCK(ErrorMessageLock);
1232 return(-1);
1233 }
1234 ADDPOS(fi->filesize,fi->POsize);
1235 p = fi->PObuffer;
1236 ADDPOS(fi->POposition,fi->POsize);
1237 if ( fi == AR.hidefile ) {
1238 UNLOCK(AS.inputslock);
1239 }
1240#ifdef ALLLOCK
1241 UNLOCK(fi->pthreadslock);
1242#endif
1243#ifdef WITHPTHREADS
1244 if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
1245 if ( fi->handle >= 0 ) SynchFile(fi->handle);
1246 }
1247#endif
1248 }
1249 *p++ = *term++;
1250 } while ( --i > 0 );
1251 fi->POfull = fi->POfill = p;
1252 return(ret);
1253 }
1254 if ( ( AP.PreDebug & DUMPOUTTERMS ) == DUMPOUTTERMS ) {
1255 MLOCK(ErrorMessageLock);
1256#ifdef WITHPTHREADS
1257 snprintf((char *)(THRbuf),100,"PutOut(%d)",AT.identity);
1258 PrintTerm(term,(char *)(THRbuf));
1259#else
1260 PrintTerm(term,"PutOut");
1261#endif
1262 MesPrint("ncomp = %d, AR.NoCompress = %d, AR.sLevel = %d",ncomp,AR.NoCompress,AR.sLevel);
1263 MesPrint("File %s, position %p",fi->name,position);
1264 MUNLOCK(ErrorMessageLock);
1265 }
1266
1267 if ( AR.sLevel <= 0 && Expressions[AR.CurExpr].newbracketinfo
1268 && ( fi == AR.outfile || fi == AR.hidefile ) ) dobracketindex = 1;
1269 r = rr = AR.CompressPointer;
1270 first = j = k = ret = 0;
1271 if ( ( i = *term ) != 0 ) {
1272 if ( i < 0 ) { /* Compressed term */
1273 i = term[1] + 2;
1274 if ( fi == AR.outfile || fi == AR.hidefile ) {
1275 MLOCK(ErrorMessageLock);
1276 MesPrint("Ran into precompressed term");
1277 MUNLOCK(ErrorMessageLock);
1278 Terminate(-1);
1279 return(-1);
1280 }
1281 }
1282 else if ( !AR.NoCompress && ( ncomp > 0 ) && AR.sLevel <= 0 ) { /* Must compress */
1283 if ( dobracketindex ) {
1284 PutBracketInIndex(BHEAD term,position);
1285 }
1286 j = *r++ - 1;
1287 p = term + 1;
1288 i--;
1289 if ( AR.PolyFun ) {
1290 WORD *polystop, *sa;
1291 sa = p + i;
1292 sa -= ABS(sa[-1]);
1293 polystop = p;
1294 while ( polystop < sa && *polystop != AR.PolyFun ) {
1295 polystop += polystop[1];
1296 }
1297 if ( polystop < sa ) {
1298 if ( AR.PolyFunType == 2 ) polystop[2] &= ~MUSTCLEANPRF;
1299 while ( i > 0 && j > 0 && *p == *r && p < polystop ) {
1300 i--; j--; k--; p++; r++;
1301 }
1302 }
1303 else {
1304 while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
1305 }
1306 }
1307#ifdef WITHFLOAT
1308 else if ( AT.aux_ != 0 ) {
1309 WORD *floatstop, *sa;
1310 sa = p + i;
1311 sa -= ABS(sa[-1]);
1312 floatstop = p;
1313 while ( floatstop < sa && *floatstop != FLOATFUN ) {
1314 floatstop += floatstop[1];
1315 }
1316 if ( floatstop < sa ) {
1317 while ( i > 0 && j > 0 && *p == *r && p < floatstop ) {
1318 i--; j--; k--; p++; r++;
1319 }
1320 }
1321 else {
1322 while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
1323 }
1324 }
1325#endif
1326 else {
1327 WORD *sa;
1328 sa = p + i;
1329 sa -= ABS(sa[-1]);
1330 while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
1331 }
1332 if ( k > -2 ) {
1333nocompress:
1334 j = i = *term;
1335 k = 0;
1336 p = term;
1337 r = rr;
1338 NCOPY(r,p,j);
1339 }
1340 else {
1341 *rr = *term;
1342 term = p;
1343 j = i;
1344 NCOPY(r,p,j);
1345 j = i;
1346 i += 2;
1347 first = 2;
1348 }
1349/* Sabotage getting into the coefficient next time */
1350 r[-(ABS(r[-1]))] = 0;
1351 if ( r >= AR.ComprTop ) {
1352 MLOCK(ErrorMessageLock);
1353 MesPrint("CompressSize of %10l is insufficient",AM.CompressSize);
1354 MUNLOCK(ErrorMessageLock);
1355 Terminate(-1);
1356 return(-1);
1357 }
1358 }
1359 else if ( !AR.NoCompress && ( ncomp < 0 ) && AR.sLevel <= 0 ) {
1360 /* No compress but put in compress buffer anyway */
1361 if ( dobracketindex ) {
1362 PutBracketInIndex(BHEAD term,position);
1363 }
1364 j = *r++ - 1;
1365 p = term + 1;
1366 i--;
1367 if ( AR.PolyFun ) {
1368 WORD *polystop, *sa;
1369 sa = p + i;
1370 sa -= ABS(sa[-1]);
1371 polystop = p;
1372 while ( polystop < sa && *polystop != AR.PolyFun ) {
1373 polystop += polystop[1];
1374 }
1375 if ( polystop < sa ) {
1376 if ( AR.PolyFunType == 2 ) polystop[2] &= ~MUSTCLEANPRF;
1377 while ( i > 0 && j > 0 && *p == *r && p < polystop ) {
1378 i--; j--; k--; p++; r++;
1379 }
1380 }
1381 else {
1382 while ( i > 0 && j > 0 && *p == *r ) { i--; j--; k--; p++; r++; }
1383 }
1384 }
1385 else {
1386 while ( i > 0 && j > 0 && *p == *r ) { i--; j--; k--; p++; r++; }
1387 }
1388 goto nocompress;
1389 }
1390 else {
1391 if ( AR.PolyFunType == 2 ) {
1392 WORD *t, *tstop;
1393 tstop = term + *term;
1394 tstop -= ABS(tstop[-1]);
1395 t = term+1;
1396 while ( t < tstop ) {
1397 if ( *t == AR.PolyFun ) {
1398 t[2] &= ~MUSTCLEANPRF;
1399 }
1400 t += t[1];
1401 }
1402 }
1403 if ( dobracketindex ) {
1404 PutBracketInIndex(BHEAD term,position);
1405 }
1406 }
1407 ret = i;
1408 ADDPOS(*position,i*sizeof(WORD));
1409 p = fi->POfill;
1410 do {
1411 if ( p >= fi->POstop ) {
1412#ifdef WITHMPI /* [16mar1998 ar] */
1413 if ( PF.me != MASTER && AR.sLevel <= 0 && (fi == AR.outfile || fi == AR.hidefile) && PF.parallel && PF.exprtodo < 0 ) {
1414 PF_BUFFER *sbuf = PF.sbuf;
1415 sbuf->fill[sbuf->active] = fi->POstop;
1416 PF_ISendSbuf(MASTER,PF_BUFFER_MSGTAG);
1417 p = fi->PObuffer = fi->POfill = fi->POfull =
1418 sbuf->buff[sbuf->active];
1419 fi->POstop = sbuf->stop[sbuf->active];
1420 }
1421 else
1422#endif /* WITHMPI [16mar1998 ar] */
1423 {
1424 if ( fi->handle < 0 ) {
1425 if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
1426#ifdef GZIPDEBUG
1427 MLOCK(ErrorMessageLock);
1428 MesPrint("%w PutOut created sortfile %s",fi->name);
1429 MUNLOCK(ErrorMessageLock);
1430#endif
1431 fi->handle = (WORD)RetCode;
1432 PUTZERO(fi->filesize);
1433 PUTZERO(fi->POposition);
1434/*
1435 Should not be here?
1436#ifdef WITHZLIB
1437 fi->ziobuffer = 0;
1438#endif
1439*/
1440 }
1441 else {
1442 MLOCK(ErrorMessageLock);
1443 MesPrint("Cannot create scratch file %s",fi->name);
1444 MUNLOCK(ErrorMessageLock);
1445 return(-1);
1446 }
1447 }
1448#ifdef WITHZLIB
1449 if ( !AR.NoCompress && ncomp > 0 && AR.gzipCompress > 0
1450 && dobracketindex == 0 && fi->zsp != 0 ) {
1451 fi->POfill = p;
1452 if ( PutOutputGZIP(fi) ) return(-1);
1453 p = fi->PObuffer;
1454 }
1455 else
1456#endif
1457 {
1458#ifdef ALLLOCK
1459 LOCK(fi->pthreadslock);
1460#endif
1461 if ( fi == AR.hidefile ) {
1462 LOCK(AS.inputslock);
1463 }
1464 SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
1465 if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize) ) != fi->POsize ) {
1466 if ( fi == AR.hidefile ) {
1467 UNLOCK(AS.inputslock);
1468 }
1469#ifdef ALLLOCK
1470 UNLOCK(fi->pthreadslock);
1471#endif
1472 MLOCK(ErrorMessageLock);
1473 MesPrint("Write error during sort. Disk full?");
1474 MesPrint("Attempt to write %l bytes on file %d at position %15p",
1475 fi->POsize,fi->handle,&(fi->POposition));
1476 MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
1477 MUNLOCK(ErrorMessageLock);
1478 return(-1);
1479 }
1480 ADDPOS(fi->filesize,fi->POsize);
1481 p = fi->PObuffer;
1482 ADDPOS(fi->POposition,fi->POsize);
1483 if ( fi == AR.hidefile ) {
1484 UNLOCK(AS.inputslock);
1485 }
1486#ifdef ALLLOCK
1487 UNLOCK(fi->pthreadslock);
1488#endif
1489#ifdef WITHPTHREADS
1490 if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
1491 if ( fi->handle >= 0 ) SynchFile(fi->handle);
1492 }
1493#endif
1494 }
1495 }
1496 }
1497 if ( first ) {
1498 if ( first == 2 ) *p++ = k;
1499 else *p++ = j;
1500 first--;
1501 }
1502 else *p++ = *term++;
1503/*
1504 if ( AP.DebugFlag ) {
1505 TalToLine((UWORD)(p[-1])); TokenToLine((UBYTE *)" ");
1506 }
1507*/
1508 } while ( --i > 0 );
1509 fi->POfull = fi->POfill = p;
1510 }
1511/*
1512 if ( AP.DebugFlag ) {
1513 AO.OutSkip = 0;
1514 FiniLine();
1515 }
1516*/
1517 return(ret);
1518}
1519
1520/*
1521 #] PutOut :
1522 #[ FlushOut : WORD FlushOut(position,file,compr)
1523*/
1533int FlushOut(POSITION *position, FILEHANDLE *fi, int compr)
1534{
1535 GETIDENTITY
1536 LONG size, RetCode;
1537 int dobracketindex = 0;
1538#ifndef WITHZLIB
1539 DUMMYUSE(compr);
1540#endif
1541 if ( AR.sLevel <= 0 && Expressions[AR.CurExpr].newbracketinfo
1542 && ( fi == AR.outfile || fi == AR.hidefile ) ) dobracketindex = 1;
1543#ifdef WITHMPI /* [16mar1998 ar] */
1544 if ( PF.me != MASTER && AR.sLevel <= 0 && (fi == AR.outfile || fi == AR.hidefile) && PF.parallel && PF.exprtodo < 0 ) {
1545 PF_BUFFER *sbuf = PF.sbuf;
1546 if ( fi->POfill >= fi->POstop ){
1547 sbuf->fill[sbuf->active] = fi->POstop;
1548 PF_ISendSbuf(MASTER,PF_BUFFER_MSGTAG);
1549 fi->POfull = fi->POfill = fi->PObuffer = sbuf->buff[sbuf->active];
1550 fi->POstop = sbuf->stop[sbuf->active];
1551 }
1552 *(fi->POfill)++ = 0;
1553 sbuf->fill[sbuf->active] = fi->POfill;
1554 PF_ISendSbuf(MASTER,PF_ENDBUFFER_MSGTAG);
1555 fi->PObuffer = fi->POfill = fi->POfull = sbuf->buff[sbuf->active];
1556 fi->POstop = sbuf->stop[sbuf->active];
1557 return(0);
1558 }
1559#endif /* WITHMPI [16mar1998 ar] */
1560 if ( fi->POfill >= fi->POstop ) {
1561 if ( fi->handle < 0 ) {
1562 if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
1563#ifdef GZIPDEBUG
1564 MLOCK(ErrorMessageLock);
1565 MesPrint("%w FlushOut created scratch file %s",fi->name);
1566 MUNLOCK(ErrorMessageLock);
1567#endif
1568 PUTZERO(fi->filesize);
1569 PUTZERO(fi->POposition);
1570 fi->handle = (WORD)RetCode;
1571/*
1572 Should not be here?
1573#ifdef WITHZLIB
1574 fi->ziobuffer = 0;
1575#endif
1576*/
1577 }
1578 else {
1579 MLOCK(ErrorMessageLock);
1580 MesPrint("Cannot create scratch file %s",fi->name);
1581 MUNLOCK(ErrorMessageLock);
1582 return(-1);
1583 }
1584 }
1585#ifdef WITHZLIB
1586 if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
1587 && dobracketindex == 0 && ( compr > 0 ) && fi->zsp != 0 ) {
1588 if ( PutOutputGZIP(fi) ) return(-1);
1589 fi->POfill = fi->PObuffer;
1590 }
1591 else
1592#endif
1593 {
1594#ifdef ALLLOCK
1595 LOCK(fi->pthreadslock);
1596#endif
1597 if ( fi == AR.hidefile ) {
1598 LOCK(AS.inputslock);
1599 }
1600 SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
1601 if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize) ) != fi->POsize ) {
1602#ifdef ALLLOCK
1603 UNLOCK(fi->pthreadslock);
1604#endif
1605 if ( fi == AR.hidefile ) {
1606 UNLOCK(AS.inputslock);
1607 }
1608 MLOCK(ErrorMessageLock);
1609 MesPrint("Write error while sorting. Disk full?");
1610 MesPrint("Attempt to write %l bytes on file %d at position %15p",
1611 fi->POsize,fi->handle,&(fi->POposition));
1612 MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
1613 MUNLOCK(ErrorMessageLock);
1614 return(-1);
1615 }
1616 ADDPOS(fi->filesize,fi->POsize);
1617 fi->POfill = fi->PObuffer;
1618 ADDPOS(fi->POposition,fi->POsize);
1619 if ( fi == AR.hidefile ) {
1620 UNLOCK(AS.inputslock);
1621 }
1622#ifdef ALLLOCK
1623 UNLOCK(fi->pthreadslock);
1624#endif
1625#ifdef WITHPTHREADS
1626 if ( AS.MasterSort && AC.ThreadSortFileSynch && fi != AR.hidefile ) {
1627 if ( fi->handle >= 0 ) SynchFile(fi->handle);
1628 }
1629#endif
1630 }
1631 }
1632 *(fi->POfill)++ = 0;
1633 fi->POfull = fi->POfill;
1634/*
1635 {
1636 UBYTE OutBuf[140];
1637 if ( AP.DebugFlag ) {
1638 AO.OutFill = AO.OutputLine = OutBuf;
1639 AO.OutSkip = 3;
1640 FiniLine();
1641 TokenToLine((UBYTE *)"End of expression written");
1642 FiniLine();
1643 }
1644 }
1645*/
1646 size = (fi->POfill-fi->PObuffer)*sizeof(WORD);
1647 if ( fi->handle >= 0 ) {
1648#ifdef WITHZLIB
1649 if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
1650 && dobracketindex == 0 && ( compr > 0 ) && fi->zsp != 0 ) {
1651 if ( FlushOutputGZIP(fi) ) return(-1);
1652 fi->POfill = fi->PObuffer;
1653 }
1654 else
1655#endif
1656 {
1657#ifdef ALLLOCK
1658 LOCK(fi->pthreadslock);
1659#endif
1660 if ( fi == AR.hidefile ) {
1661 LOCK(AS.inputslock);
1662 }
1663 SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
1664/*
1665 MesPrint("FlushOut: writing %l bytes to position %12p",size,&(fi->POposition));
1666*/
1667 if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),size) ) != size ) {
1668#ifdef ALLLOCK
1669 UNLOCK(fi->pthreadslock);
1670#endif
1671 if ( fi == AR.hidefile ) {
1672 UNLOCK(AS.inputslock);
1673 }
1674 MLOCK(ErrorMessageLock);
1675 MesPrint("Write error while finishing sorting. Disk full?");
1676 MesPrint("Attempt to write %l bytes on file %d at position %15p",
1677 size,fi->handle,&(fi->POposition));
1678 MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
1679 MUNLOCK(ErrorMessageLock);
1680 return(-1);
1681 }
1682 ADDPOS(fi->filesize,size);
1683 ADDPOS(fi->POposition,size);
1684 fi->POfill = fi->PObuffer;
1685 if ( fi == AR.hidefile ) {
1686 UNLOCK(AS.inputslock);
1687 }
1688#ifdef ALLLOCK
1689 UNLOCK(fi->pthreadslock);
1690#endif
1691#ifdef WITHPTHREADS
1692 if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
1693 if ( fi->handle >= 0 ) SynchFile(fi->handle);
1694 }
1695#endif
1696 }
1697 }
1698 if ( dobracketindex ) {
1699 BRACKETINFO *b = Expressions[AR.CurExpr].newbracketinfo;
1700 if ( b->indexfill > 0 ) {
1701 DIFPOS(b->indexbuffer[b->indexfill-1].next,*position,Expressions[AR.CurExpr].onfile);
1702 }
1703 }
1704#ifdef WITHZLIB
1705 if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
1706 && dobracketindex == 0 && ( compr > 0 ) && fi->zsp != 0 ) {
1707 PUTZERO(*position);
1708 if ( fi->handle >= 0 ) {
1709#ifdef ALLLOCK
1710 LOCK(fi->pthreadslock);
1711#endif
1712 SeekFile(fi->handle,position,SEEK_END);
1713#ifdef ALLLOCK
1714 UNLOCK(fi->pthreadslock);
1715#endif
1716 }
1717 else {
1718 ADDPOS(*position,((UBYTE *)fi->POfill-(UBYTE *)fi->PObuffer));
1719 }
1720 }
1721 else
1722#endif
1723 {
1724 ADDPOS(*position,sizeof(WORD));
1725 }
1726 return(0);
1727}
1728
1729/*
1730 #] FlushOut :
1731 #[ AddCoef : WORD AddCoef(pterm1,pterm2)
1732*/
1747int AddCoef(PHEAD WORD **ps1, WORD **ps2)
1748{
1749 GETBIDENTITY
1750 SORTING *S = AT.SS;
1751 WORD *s1, *s2;
1752 WORD l1, l2, i;
1753 WORD OutLen, *t, j;
1754 UWORD *OutCoef;
1755#ifdef WITHFLOAT
1756 if ( AT.SortFloatMode ) return(AddWithFloat(BHEAD ps1,ps2));
1757#endif
1758 OutCoef = AN.SoScratC;
1759 s1 = *ps1; s2 = *ps2;
1760 GETCOEF(s1,l1);
1761 GETCOEF(s2,l2);
1762 if ( AddRat(BHEAD (UWORD *)s1,l1,(UWORD *)s2,l2,OutCoef,&OutLen) ) {
1763 MLOCK(ErrorMessageLock);
1764 MesCall("AddCoef");
1765 MUNLOCK(ErrorMessageLock);
1766 Terminate(-1);
1767 }
1768 if ( AN.ncmod != 0 ) {
1769 if ( ( AC.modmode & POSNEG ) != 0 ) {
1770 NormalModulus(OutCoef,&OutLen);
1771/*
1772 We had forgotten that this can also become smaller but the
1773 denominator isn't there. Correct in the other case
1774 17-may-2009 [JV]
1775*/
1776 j = ABS(OutLen); OutCoef[j] = 1;
1777 for ( i = 1; i < j; i++ ) OutCoef[j+i] = 0;
1778 }
1779 else if ( BigLong(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod)) >= 0 ) {
1780 SubPLon(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod),OutCoef,&OutLen);
1781 OutCoef[OutLen] = 1;
1782 for ( i = 1; i < OutLen; i++ ) OutCoef[OutLen+i] = 0;
1783 }
1784 }
1785 if ( !OutLen ) { *ps1 = *ps2 = 0; return(0); }
1786 OutLen *= 2;
1787 if ( OutLen < 0 ) i = - ( --OutLen );
1788 else i = ++OutLen;
1789 if ( l1 < 0 ) l1 = -l1;
1790 l1 *= 2; l1++;
1791 if ( i <= l1 ) { /* Fits in 1 */
1792 l1 -= i;
1793 **ps1 -= l1;
1794 s2 = (WORD *)OutCoef;
1795 while ( --i > 0 ) *s1++ = *s2++;
1796 *s1++ = OutLen;
1797 while ( --l1 >= 0 ) *s1++ = 0;
1798 goto RegEnd;
1799 }
1800 if ( l2 < 0 ) l2 = -l2;
1801 l2 *= 2; l2++;
1802 if ( i <= l2 ) { /* Fits in 2 */
1803 l2 -= i;
1804 **ps2 -= l2;
1805 s1 = (WORD *)OutCoef;
1806 while ( --i > 0 ) *s2++ = *s1++;
1807 *s2++ = OutLen;
1808 while ( --l2 >= 0 ) *s2++ = 0;
1809 *ps1 = *ps2;
1810 goto RegEnd;
1811 }
1812
1813 /* Doesn't fit. Make a new term. */
1814
1815 t = s1;
1816 s1 = *ps1;
1817 j = *s1++ + i - l1; /* Space needed */
1818 if ( (S->sFill + j) >= S->sTop2 ) {
1819 GarbHand();
1820 s1 = *ps1;
1821 t = s1 + *s1 - 1;
1822 j = *s1++ + i - l1; /* Space needed */
1823 l1 = *t;
1824 if ( l1 < 0 ) l1 = - l1;
1825 t -= l1-1;
1826 }
1827 s2 = S->sFill;
1828 *s2++ = j;
1829 while ( s1 < t ) *s2++ = *s1++;
1830 s1 = (WORD *)OutCoef;
1831 while ( --i > 0 ) *s2++ = *s1++;
1832 *s2++ = OutLen;
1833 *ps1 = S->sFill;
1834 S->sFill = s2;
1835RegEnd:
1836 *ps2 = 0;
1837 if ( **ps1 > AM.MaxTer/((LONG)(sizeof(WORD))) ) {
1838 MLOCK(ErrorMessageLock);
1839 MesPrint("Term too complex after addition in sort. MaxTermSize = %10l",
1840 AM.MaxTer/sizeof(WORD));
1841 MUNLOCK(ErrorMessageLock);
1842 Terminate(-1);
1843 }
1844 return(1);
1845}
1846
1847/*
1848 #] AddCoef :
1849 #[ AddPoly : WORD AddPoly(pterm1,pterm2)
1850*/
1876int AddPoly(PHEAD WORD **ps1, WORD **ps2)
1877{
1878 GETBIDENTITY
1879 SORTING *S = AT.SS;
1880 WORD i;
1881 WORD *s1, *s2, *m, *w, *t, oldpw = S->PolyWise;
1882 s1 = *ps1 + S->PolyWise;
1883 s2 = *ps2 + S->PolyWise;
1884 w = AT.WorkPointer;
1885/*
1886 Add here the two arguments. Is a straight merge.
1887*/
1888 if ( S->PolyFlag == 2 && AR.PolyFunExp != 2 && AR.PolyFunExp != 3 ) {
1889 WORD **oldSplitScratch = AN.SplitScratch;
1890 LONG oldSplitScratchSize = AN.SplitScratchSize;
1891 LONG oldInScratch = AN.InScratch;
1892 WORD oldtype = AR.SortType;
1893 if ( (WORD *)((UBYTE *)w + AM.MaxTer) >= AT.WorkTop ) {
1894 MLOCK(ErrorMessageLock);
1895 MesPrint("Program was adding polyratfun arguments");
1896 MesWork();
1897 MUNLOCK(ErrorMessageLock);
1898 }
1899 AR.SortType = SORTHIGHFIRST;
1900 S->PolyWise = 0;
1901 AN.SplitScratch = AN.SplitScratch1;
1902 AN.SplitScratchSize = AN.SplitScratchSize1;
1903 AN.InScratch = AN.InScratch1;
1904 poly_ratfun_add(BHEAD s1,s2);
1905 S->PolyWise = oldpw;
1906 AN.SplitScratch1 = AN.SplitScratch;
1907 AN.SplitScratchSize1 = AN.SplitScratchSize;
1908 AN.InScratch1 = AN.InScratch;
1909 AN.SplitScratch = oldSplitScratch;
1910 AN.SplitScratchSize = oldSplitScratchSize;
1911 AN.InScratch = oldInScratch;
1912 AT.WorkPointer = w;
1913 AR.SortType = oldtype;
1914 if ( w[1] <= FUNHEAD ||
1915 ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) ) {
1916 *ps1 = *ps2 = 0; return(0);
1917 }
1918 }
1919 else {
1920 if ( w + s1[1] + s2[1] + 12 + ARGHEAD >= AT.WorkTop ) {
1921 MLOCK(ErrorMessageLock);
1922 MesPrint("Program was adding polyfun arguments");
1923 MesWork();
1924 MUNLOCK(ErrorMessageLock);
1925 }
1926 AddArgs(BHEAD s1,s2,w);
1927 }
1928/*
1929 Now we need to store the result in a convenient place.
1930*/
1931 if ( w[1] <= FUNHEAD ) { *ps1 = *ps2 = 0; return(0); }
1932 if ( w[1] <= s1[1] || w[1] <= s2[1] ) { /* Fits in place. */
1933 if ( w[1] > s1[1] ) {
1934 *ps1 = *ps2;
1935 s1 = s2;
1936 }
1937 t = s1 + s1[1];
1938 m = *ps1 + **ps1;
1939 i = w[1];
1940 NCOPY(s1,w,i);
1941 if ( s1 != t ) {
1942 while ( t < m ) *s1++ = *t++;
1943 **ps1 = WORDDIF(s1,(*ps1));
1944 }
1945 *ps2 = 0;
1946 }
1947 else { /* Make new term */
1948#ifdef TESTGARB
1949 s2 = *ps2;
1950#endif
1951 *ps2 = 0;
1952 if ( (S->sFill + (**ps1 + w[1] - s1[1])) >= S->sTop2 ) {
1953#ifdef TESTGARB
1954 MesPrint("------Garbage collection-------");
1955#endif
1956 AT.WorkPointer += w[1];
1957 GarbHand();
1958 AT.WorkPointer = w;
1959 s1 = *ps1;
1960 if ( (S->sFill + (**ps1 + w[1] - s1[1])) >= S->sTop2 ) {
1961#ifdef TESTGARB
1962 UBYTE OutBuf[140];
1963 MLOCK(ErrorMessageLock);
1964 AO.OutFill = AO.OutputLine = OutBuf;
1965 AO.OutSkip = 3;
1966 FiniLine();
1967 i = *s2;
1968 while ( --i >= 0 ) {
1969 TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)" ");
1970 }
1971 FiniLine();
1972 AO.OutFill = AO.OutputLine = OutBuf;
1973 AO.OutSkip = 3;
1974 FiniLine();
1975 s2 = *ps1;
1976 i = *s2;
1977 while ( --i >= 0 ) {
1978 TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)" ");
1979 }
1980 FiniLine();
1981 AO.OutFill = AO.OutputLine = OutBuf;
1982 AO.OutSkip = 3;
1983 FiniLine();
1984 s2 = w;
1985 i = w[1];
1986 while ( --i >= 0 ) {
1987 TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)" ");
1988 }
1989 FiniLine();
1990 if ( AR.sLevel > 0 ) {
1991 MesPrint("Please increase SubSmallExtension setup parameter.");
1992 }
1993 else {
1994 MesPrint("Please increase SmallExtension setup parameter.");
1995 }
1996 MUNLOCK(ErrorMessageLock);
1997#else
1998 MLOCK(ErrorMessageLock);
1999 if ( AR.sLevel > 0 ) {
2000 MesPrint("Please increase SubSmallExtension setup parameter.");
2001 }
2002 else {
2003 MesPrint("Please increase SmallExtension setup parameter.");
2004 }
2005 MUNLOCK(ErrorMessageLock);
2006#endif
2007 Terminate(-1);
2008 }
2009 }
2010 t = *ps1;
2011 s2 = S->sFill;
2012 m = s2;
2013 i = S->PolyWise;
2014 NCOPY(s2,t,i);
2015 i = w[1];
2016 NCOPY(s2,w,i);
2017 t = t + t[1];
2018 w = *ps1 + **ps1;
2019 while ( t < w ) *s2++ = *t++;
2020 *m = WORDDIF(s2,m);
2021 *ps1 = m;
2022 S->sFill = s2;
2023 if ( *m > AM.MaxTer/((LONG)sizeof(WORD)) ) {
2024 MLOCK(ErrorMessageLock);
2025 MesPrint("Term too complex after polynomial addition. MaxTermSize = %10l",
2026 AM.MaxTer/sizeof(WORD));
2027 MUNLOCK(ErrorMessageLock);
2028 Terminate(-1);
2029 }
2030 }
2031 return(1);
2032}
2033
2034/*
2035 #] AddPoly :
2036 #[ AddArgs : void AddArgs(arg1,arg2,to)
2037*/
2038
2039#define INSLENGTH(x) w[1] = FUNHEAD+ARGHEAD+x; w[FUNHEAD] = ARGHEAD+x;
2040
2048void AddArgs(PHEAD WORD *s1, WORD *s2, WORD *m)
2049{
2050 GETBIDENTITY
2051 WORD i1, i2;
2052 WORD *w = m, *mm, *t, *t1, *t2, *tstop1, *tstop2;
2053 WORD tempterm[8+FUNHEAD];
2054
2055 *m++ = AR.PolyFun; *m++ = 0; FILLFUN(m)
2056 *m++ = 0; *m++ = 0; FILLARG(m)
2057 if ( s1[FUNHEAD] < 0 || s2[FUNHEAD] < 0 ) {
2058 if ( s1[FUNHEAD] < 0 ) {
2059 if ( s2[FUNHEAD] < 0 ) { /* Both are special */
2060 if ( s1[FUNHEAD] <= -FUNCTION ) {
2061 if ( s2[FUNHEAD] == s1[FUNHEAD] ) {
2062 *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
2063 FILLFUN(m)
2064 *m++ = 2; *m++ = 1; *m++ = 3;
2065 INSLENGTH(4+FUNHEAD)
2066 }
2067 else if ( s2[FUNHEAD] <= -FUNCTION ) {
2068 i1 = functions[-FUNCTION-s1[FUNHEAD]].commute != 0;
2069 i2 = functions[-FUNCTION-s2[FUNHEAD]].commute != 0;
2070 if ( ( !i1 && i2 ) || ( i1 == i2 && i1 > i2 ) ) {
2071 i1 = s2[FUNHEAD];
2072 s2[FUNHEAD] = s1[FUNHEAD];
2073 s1[FUNHEAD] = i1;
2074 }
2075 *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
2076 FILLFUN(m)
2077 *m++ = 1; *m++ = 1; *m++ = 3;
2078 *m++ = 4+FUNHEAD; *m++ = -s2[FUNHEAD]; *m++ = FUNHEAD;
2079 FILLFUN(m)
2080 *m++ = 1; *m++ = 1; *m++ = 3;
2081 INSLENGTH(8+2*FUNHEAD)
2082 }
2083 else if ( s2[FUNHEAD] == -SYMBOL ) {
2084 *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s2[FUNHEAD+1]; *m++ = 1;
2085 *m++ = 1; *m++ = 1; *m++ = 3;
2086 *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
2087 FILLFUN(m)
2088 *m++ = 1; *m++ = 1; *m++ = 3;
2089 INSLENGTH(12+FUNHEAD)
2090 }
2091 else { /* number */
2092 *m++ = 4;
2093 *m++ = ABS(s2[FUNHEAD+1]); *m++ = 1; *m++ = s2[FUNHEAD+1] < 0 ? -3: 3;
2094 *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
2095 FILLFUN(m)
2096 *m++ = 1; *m++ = 1; *m++ = 3;
2097 INSLENGTH(8+FUNHEAD)
2098 }
2099 }
2100 else if ( s1[FUNHEAD] == -SYMBOL ) {
2101 if ( s2[FUNHEAD] == s1[FUNHEAD] ) {
2102 if ( s1[FUNHEAD+1] == s2[FUNHEAD+1] ) {
2103 *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s1[FUNHEAD+1];
2104 *m++ = 1; *m++ = 2; *m++ = 1; *m++ = 3;
2105 INSLENGTH(8)
2106 }
2107 else {
2108 if ( s1[FUNHEAD+1] > s2[FUNHEAD+1] )
2109 { i1 = s2[FUNHEAD+1]; i2 = s1[FUNHEAD+1]; }
2110 else { i1 = s1[FUNHEAD+1]; i2 = s2[FUNHEAD+1]; }
2111 *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = i1;
2112 *m++ = 1; *m++ = 1; *m++ = 1; *m++ = 3;
2113 *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = i2;
2114 *m++ = 1; *m++ = 1; *m++ = 1; *m++ = 3;
2115 INSLENGTH(16)
2116 }
2117 }
2118 else if ( s2[FUNHEAD] <= -FUNCTION ) {
2119 *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s1[FUNHEAD+1]; *m++ = 1;
2120 *m++ = 1; *m++ = 1; *m++ = 3;
2121 *m++ = 4+FUNHEAD; *m++ = -s2[FUNHEAD]; *m++ = FUNHEAD;
2122 FILLFUN(m)
2123 *m++ = 1; *m++ = 1; *m++ = 3;
2124 INSLENGTH(12+FUNHEAD)
2125 }
2126 else {
2127 *m++ = 4;
2128 *m++ = ABS(s2[FUNHEAD+1]); *m++ = 1; *m++ = s2[FUNHEAD+1] < 0 ? -3: 3;
2129 *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s1[FUNHEAD+1]; *m++ = 1;
2130 *m++ = 1; *m++ = 1; *m++ = 3;
2131 INSLENGTH(12)
2132 }
2133 }
2134 else { /* Must be -SNUMBER! */
2135 if ( s2[FUNHEAD] <= -FUNCTION ) {
2136 *m++ = 4;
2137 *m++ = ABS(s1[FUNHEAD+1]); *m++ = 1; *m++ = s1[FUNHEAD+1] < 0 ? -3: 3;
2138 *m++ = 4+FUNHEAD; *m++ = -s2[FUNHEAD]; *m++ = FUNHEAD;
2139 FILLFUN(m)
2140 *m++ = 1; *m++ = 1; *m++ = 3;
2141 INSLENGTH(8+FUNHEAD)
2142 }
2143 else if ( s2[FUNHEAD] == -SYMBOL ) {
2144 *m++ = 4;
2145 *m++ = ABS(s1[FUNHEAD+1]); *m++ = 1; *m++ = s1[FUNHEAD+1] < 0 ? -3: 3;
2146 *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s2[FUNHEAD+1]; *m++ = 1;
2147 *m++ = 1; *m++ = 1; *m++ = 3;
2148 INSLENGTH(12)
2149 }
2150 else { /* Both are numbers. add. */
2151 LONG x1;
2152 x1 = (LONG)s1[FUNHEAD+1] + (LONG)s2[FUNHEAD+1];
2153 if ( x1 < 0 ) { i1 = (WORD)(-x1); i2 = -3; }
2154 else { i1 = (WORD)x1; i2 = 3; }
2155 if ( x1 && AN.ncmod != 0 ) {
2156 m[0] = 4;
2157 m[1] = i1;
2158 m[2] = 1;
2159 m[3] = i2;
2160 if ( Modulus(m) ) Terminate(-1);
2161 if ( *m == 0 ) w[1] = 0;
2162 else {
2163 if ( *m == 4 && ( m[1] & MAXPOSITIVE ) == m[1]
2164 && m[3] == 3 ) {
2165 i1 = m[1];
2166 m -= ARGHEAD;
2167 *m++ = -SNUMBER;
2168 *m++ = i1;
2169 INSLENGTH(4)
2170 }
2171 else {
2172 INSLENGTH(*m)
2173 m += *m;
2174 }
2175 }
2176 }
2177 else {
2178 if ( x1 == 0 ) {
2179 w[1] = FUNHEAD;
2180 }
2181 else if ( ( i1 & MAXPOSITIVE ) == i1 ) {
2182 m -= ARGHEAD;
2183 *m++ = -SNUMBER;
2184 *m++ = (WORD)x1;
2185 w[1] = FUNHEAD+2;
2186 }
2187 else {
2188 *m++ = 4; *m++ = i1; *m++ = 1; *m++ = i2;
2189 INSLENGTH(4)
2190 }
2191 }
2192 }
2193 }
2194 }
2195 else { /* Only s1 is special */
2196s1only:
2197/*
2198 Compose a term in `tempterm'
2199*/
2200 t = tempterm;
2201 if ( s1[FUNHEAD] <= -FUNCTION ) {
2202 *t++ = 4+FUNHEAD; *t++ = -s1[FUNHEAD]; *t++ = FUNHEAD;
2203 FILLFUN(t)
2204 *t++ = 1; *t++ = 1; *t++ = 3;
2205 }
2206 else if ( s1[FUNHEAD] == -SYMBOL ) {
2207 *t++ = 8; *t++ = SYMBOL; *t++ = 4;
2208 *t++ = s1[FUNHEAD+1]; *t++ = 1;
2209 *t++ = 1; *t++ = 1; *t++ = 3;
2210 }
2211 else {
2212 *t++ = 4; *t++ = ABS(s1[FUNHEAD+1]);
2213 *t++ = 1; *t++ = s1[FUNHEAD+1] < 0 ? -3: 3;
2214 }
2215 tstop1 = t;
2216 s1 = tempterm;
2217 goto twogen;
2218 }
2219 }
2220 else { /* Only s2 is special */
2221 t = s1;
2222 s1 = s2;
2223 s2 = t;
2224 goto s1only;
2225 }
2226 }
2227 else {
2228 int oldPolyFlag;
2229 tstop1 = s1 + s1[1];
2230 s1 += FUNHEAD+ARGHEAD;
2231twogen:
2232 tstop2 = s2 + s2[1];
2233 s2 += FUNHEAD+ARGHEAD;
2234/*
2235 Now we should merge the expressions in s1 and s2 into m.
2236*/
2237 oldPolyFlag = AT.SS->PolyFlag;
2238 AT.SS->PolyFlag = 0;
2239 while ( s1 < tstop1 && s2 < tstop2 ) {
2240 i1 = CompareTerms(BHEAD s1,s2,(WORD)(-1));
2241 if ( i1 > 0 ) {
2242 i2 = *s1;
2243 NCOPY(m,s1,i2);
2244 }
2245 else if ( i1 < 0 ) {
2246 i2 = *s2;
2247 NCOPY(m,s2,i2);
2248 }
2249 else { /* Coefficients should be added. */
2250 WORD i;
2251 t = s1+*s1;
2252 i1 = t[-1];
2253 i2 = *s1 - ABS(i1);
2254 t2 = s2 + i2;
2255 s2 += *s2;
2256 mm = m;
2257 NCOPY(m,s1,i2);
2258 t1 = s1;
2259 s1 = t;
2260 i2 = s2[-1];
2261/*
2262 t1,i1 is the first coefficient
2263 t2,i2 is the second coefficient
2264 It should be placed at m,i1
2265*/
2266 i1 = REDLENG(i1);
2267 i2 = REDLENG(i2);
2268 if ( AddRat(BHEAD (UWORD *)t1,i1,(UWORD *)t2,i2,(UWORD *)m,&i) ) {
2269 MLOCK(ErrorMessageLock);
2270 MesPrint("Addition of coefficients of PolyFun");
2271 MUNLOCK(ErrorMessageLock);
2272 Terminate(-1);
2273 }
2274 if ( i == 0 ) {
2275 m = mm;
2276 }
2277 else {
2278 i1 = INCLENG(i);
2279 m += ABS(i1);
2280 m[-1] = i1;
2281 *mm = WORDDIF(m,mm);
2282 if ( AN.ncmod != 0 ) {
2283 if ( Modulus(mm) ) Terminate(-1);
2284 if ( !*mm ) m = mm;
2285 else m = mm + *mm;
2286 }
2287 }
2288 }
2289 }
2290 while ( s1 < tstop1 ) *m++ = *s1++;
2291 while ( s2 < tstop2 ) *m++ = *s2++;
2292 w[1] = WORDDIF(m,w);
2293 w[FUNHEAD] = w[1] - FUNHEAD;
2294 if ( ToFast(w+FUNHEAD,w+FUNHEAD) ) {
2295 if ( w[FUNHEAD] <= -FUNCTION ) w[1] = FUNHEAD+1;
2296 else w[1] = FUNHEAD+2;
2297 if ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) w[1] = FUNHEAD;
2298 }
2299/* AT.SS->PolyFlag = AR.PolyFunType;*/
2300 AT.SS->PolyFlag = oldPolyFlag;
2301 }
2302}
2303
2304/*
2305 #] AddArgs :
2306 #[ Compare1 : WORD Compare1(term1,term2,level)
2307*/
2341WORD Compare1(PHEAD WORD *term1, WORD *term2, WORD level)
2342{
2343 SORTING *S = AT.SS;
2344 WORD *stopper1, *stopper2, *t2;
2345 WORD *s1, *s2, *t1;
2346 WORD *stopex1, *stopex2;
2347 WORD c1, c2;
2348 WORD prevorder;
2349 WORD count = -1, localPoly, polyhit = -1;
2350
2351 // Update SortVerbose counter
2352 S->verbComparisons++;
2353
2354 if ( S->PolyFlag ) {
2355/*
2356 if ( S->PolyWise != 0 ) {
2357 MLOCK(ErrorMessageLock);
2358 MesPrint("S->PolyWise is not zero!!!!!");
2359 MUNLOCK(ErrorMessageLock);
2360 }
2361*/
2362 count = 0; localPoly = 1; S->PolyWise = polyhit = 0;
2363 S->PolyFlag = AR.PolyFunType;
2364 if ( AR.PolyFunType == 2 &&
2365 ( AR.PolyFunExp == 2 || AR.PolyFunExp == 3 ) ) S->PolyFlag = 1;
2366 }
2367 else { localPoly = 0; }
2368#ifdef WITHFLOAT
2369 AT.SortFloatMode = 0;
2370#endif
2371 prevorder = 0;
2372 GETSTOP(term1,s1);
2373 stopper1 = s1;
2374 GETSTOP(term2,stopper2);
2375 t1 = term1 + 1;
2376 t2 = term2 + 1;
2377 while ( t1 < stopper1 && t2 < stopper2 ) {
2378 if ( *t1 != *t2 ) {
2379 if ( *t1 == HAAKJE ) return(PREV(-1));
2380 if ( *t2 == HAAKJE ) return(PREV(1));
2381 if ( *t1 >= (FUNCTION-1) ) {
2382 if ( *t2 < (FUNCTION-1) ) return(PREV(-1));
2383 if ( *t1 < FUNCTION && *t2 < FUNCTION ) return(PREV(*t2-*t1));
2384 if ( *t1 < FUNCTION ) return(PREV(1));
2385 if ( *t2 < FUNCTION ) return(PREV(-1));
2386 c1 = functions[*t1-FUNCTION].commute;
2387 c2 = functions[*t2-FUNCTION].commute;
2388 if ( !c1 ) {
2389 if ( c2 ) return(PREV(1));
2390 else return(PREV(*t2-*t1));
2391 }
2392 else {
2393 if ( !c2 ) return(PREV(-1));
2394 else return(PREV(*t2-*t1));
2395 }
2396 }
2397 else return(PREV(*t2-*t1));
2398 }
2399 s1 = t1 + 2;
2400 s2 = t2 + 2;
2401 c1 = *t1;
2402 t1 += t1[1];
2403 t2 += t2[1];
2404 if ( localPoly && c1 < FUNCTION ) {
2405 polyhit = 1;
2406 }
2407 if ( c1 <= (FUNCTION-1)
2408 || ( c1 >= FUNCTION && functions[c1-FUNCTION].spec > 0 ) ) {
2409 if ( c1 == SYMBOL ) {
2410 if ( *s1 == FACTORSYMBOL && *s2 == FACTORSYMBOL
2411 && s1[-1] == 4 && s2[-1] == 4
2412 && ( ( t1 < stopper1 && *t1 == HAAKJE )
2413 || ( t1 == stopper1 && AT.fromindex ) ) ) {
2414/*
2415 We have to be very careful with the criteria here, because
2416 Compare1 is called both in the regular sorting and by the
2417 routine that makes the bracket index. In the last case
2418 there is no HAAKJE subterm.
2419*/
2420 if ( s1[1] != s2[1] ) return(s2[1]-s1[1]);
2421 s1 += 2; s2 += 2;
2422 }
2423 else if ( AR.SortType >= SORTPOWERFIRST ) {
2424 WORD i1 = 0, *r1;
2425 r1 = s1;
2426 while ( s1 < t1 ) { i1 += s1[1]; s1 += 2; }
2427 s1 = r1; r1 = s2;
2428 while ( s2 < t2 ) { i1 -= s2[1]; s2 += 2; }
2429 s2 = r1;
2430 if ( i1 ) {
2431 if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
2432 return(PREV(i1));
2433 }
2434 }
2435 while ( s1 < t1 ) {
2436 if ( s2 >= t2 ) {
2437/* return(PREV(1)); */
2438 if ( AR.SortType==SORTLOWFIRST ) {
2439 return(PREV((s1[1]>0?-1:1)));
2440 }
2441 else {
2442 return(PREV((s1[1]<0?-1:1)));
2443 }
2444 }
2445 if ( *s1 != *s2 ) {
2446/* return(PREV(*s2-*s1)); */
2447 if ( AR.SortType==SORTLOWFIRST ) {
2448 if ( *s1 < *s2 ) {
2449 return(PREV((s1[1]<0?1:-1)));
2450 }
2451 else {
2452 return(PREV((s2[1]<0?-1:1)));
2453 }
2454 }
2455 else {
2456 if ( *s1 < *s2 ) {
2457 return(PREV((s1[1]<0?-1:1)));
2458 }
2459 else {
2460 return(PREV((s2[1]<0?1:-1)));
2461 }
2462 }
2463 }
2464 s1++; s2++;
2465 if ( *s1 != *s2 ) return(
2466 PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
2467 s1++; s2++;
2468 }
2469 if ( s2 < t2 ) {
2470/* return(PREV(-1)); */
2471 if ( AR.SortType==SORTLOWFIRST ) {
2472 return(PREV((s2[1]<0?-1:1)));
2473 }
2474 else {
2475 return(PREV((s2[1]<0?1:-1)));
2476 }
2477 }
2478 }
2479 else if ( c1 == DOTPRODUCT ) {
2480 if ( AR.SortType >= SORTPOWERFIRST ) {
2481 WORD i1 = 0, *r1;
2482 r1 = s1;
2483 while ( s1 < t1 ) { i1 += s1[2]; s1 += 3; }
2484 s1 = r1; r1 = s2;
2485 while ( s2 < t2 ) { i1 -= s2[2]; s2 += 3; }
2486 s2 = r1;
2487 if ( i1 ) {
2488 if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
2489 return(PREV(i1));
2490 }
2491 }
2492 while ( s1 < t1 ) {
2493 if ( s2 >= t2 ) return(PREV(1));
2494 if ( *s1 != *s2 ) return(PREV(*s2-*s1));
2495 s1++; s2++;
2496 if ( *s1 != *s2 ) return(PREV(*s2-*s1));
2497 s1++; s2++;
2498 if ( *s1 != *s2 ) return(
2499 PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
2500 s1++; s2++;
2501 }
2502 if ( s2 < t2 ) return(PREV(-1));
2503 }
2504 else {
2505 while ( s1 < t1 ) {
2506 if ( s2 >= t2 ) return(PREV(1));
2507 if ( *s1 != *s2 ) return(PREV(*s2-*s1));
2508 s1++; s2++;
2509 }
2510 if ( s2 < t2 ) return(PREV(-1));
2511 }
2512 }
2513 else {
2514#if FUNHEAD != 2
2515 s1 += FUNHEAD-2;
2516 s2 += FUNHEAD-2;
2517#endif
2518 if ( localPoly && c1 == AR.PolyFun ) {
2519 if ( count == 0 ) {
2520 if ( S->PolyFlag == 1 ) {
2521 WORD i1, i2;
2522 if ( *s1 > 0 ) i1 = *s1;
2523 else if ( *s1 <= -FUNCTION ) i1 = 1;
2524 else i1 = 2;
2525 if ( *s2 > 0 ) i2 = *s2;
2526 else if ( *s2 <= -FUNCTION ) i2 = 1;
2527 else i2 = 2;
2528 if ( s1+i1 == t1 && s2+i2 == t2 ) { /* This is the stuff */
2529/*
2530 Test for scalar nature
2531*/
2532 if ( !polyhit ) {
2533 WORD *u1, *u2, *ustop;
2534 if ( *s1 < 0 ) {
2535 if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
2536 goto NoPoly;
2537 }
2538 else {
2539 u1 = s1 + ARGHEAD;
2540 while ( u1 < t1 ) {
2541 u2 = u1 + *u1;
2542 ustop = u2 - ABS(u2[-1]);
2543 u1++;
2544 while ( u1 < ustop ) {
2545 if ( *u1 == INDEX ) goto NoPoly;
2546 u1 += u1[1];
2547 }
2548 u1 = u2;
2549 }
2550 }
2551 if ( *s2 < 0 ) {
2552 if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
2553 goto NoPoly;
2554 }
2555 else {
2556 u1 = s2 + ARGHEAD;
2557 while ( u1 < t2 ) {
2558 u2 = u1 + *u1;
2559 ustop = u2 - ABS(u2[-1]);
2560 u1++;
2561 while ( u1 < ustop ) {
2562 if ( *u1 == INDEX ) goto NoPoly;
2563 u1 += u1[1];
2564 }
2565 u1 = u2;
2566 }
2567 }
2568 }
2569 S->PolyWise = WORDDIF(s1,term1);
2570 S->PolyWise -= FUNHEAD;
2571 count = 1;
2572 continue;
2573 }
2574 else {
2575NoPoly:
2576 S->PolyWise = localPoly = 0;
2577 }
2578 }
2579 else if ( AR.PolyFunType == 2 ) {
2580 WORD i1, i2, i1a, i2a;
2581 if ( *s1 > 0 ) i1 = *s1;
2582 else if ( *s1 <= -FUNCTION ) i1 = 1;
2583 else i1 = 2;
2584 if ( *s2 > 0 ) i2 = *s2;
2585 else if ( *s2 <= -FUNCTION ) i2 = 1;
2586 else i2 = 2;
2587 if ( s1[i1] > 0 ) i1a = s1[i1];
2588 else if ( s1[i1] <= -FUNCTION ) i1a = 1;
2589 else i1a = 2;
2590 if ( s2[i2] > 0 ) i2a = s2[i2];
2591 else if ( s2[i2] <= -FUNCTION ) i2a = 1;
2592 else i2a = 2;
2593 if ( s1+i1+i1a == t1 && s2+i2+i2a == t2 ) { /* This is the stuff */
2594/*
2595 Test for scalar nature
2596*/
2597 if ( !polyhit ) {
2598 WORD *u1, *u2, *ustop;
2599 if ( *s1 < 0 ) {
2600 if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
2601 goto NoPoly;
2602 }
2603 else {
2604 u1 = s1 + ARGHEAD;
2605 while ( u1 < s1+i1 ) {
2606 u2 = u1 + *u1;
2607 ustop = u2 - ABS(u2[-1]);
2608 u1++;
2609 while ( u1 < ustop ) {
2610 if ( *u1 == INDEX ) goto NoPoly;
2611 u1 += u1[1];
2612 }
2613 u1 = u2;
2614 }
2615 }
2616 if ( s1[i1] < 0 ) {
2617 if ( s1[i1] != -SNUMBER && s1[i1] != -SYMBOL && s1[i1] > -FUNCTION )
2618 goto NoPoly;
2619 }
2620 else {
2621 u1 = s1 +i1 + ARGHEAD;
2622 while ( u1 < t1 ) {
2623 u2 = u1 + *u1;
2624 ustop = u2 - ABS(u2[-1]);
2625 u1++;
2626 while ( u1 < ustop ) {
2627 if ( *u1 == INDEX ) goto NoPoly;
2628 u1 += u1[1];
2629 }
2630 u1 = u2;
2631 }
2632 }
2633 if ( *s2 < 0 ) {
2634 if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
2635 goto NoPoly;
2636 }
2637 else {
2638 u1 = s2 + ARGHEAD;
2639 while ( u1 < s2+i2 ) {
2640 u2 = u1 + *u1;
2641 ustop = u2 - ABS(u2[-1]);
2642 u1++;
2643 while ( u1 < ustop ) {
2644 if ( *u1 == INDEX ) goto NoPoly;
2645 u1 += u1[1];
2646 }
2647 u1 = u2;
2648 }
2649 }
2650 if ( s2[i2] < 0 ) {
2651 if ( s2[i2] != -SNUMBER && s2[i2] != -SYMBOL && s2[i2] > -FUNCTION )
2652 goto NoPoly;
2653 }
2654 else {
2655 u1 = s2 + i2 + ARGHEAD;
2656 while ( u1 < t2 ) {
2657 u2 = u1 + *u1;
2658 ustop = u2 - ABS(u2[-1]);
2659 u1++;
2660 while ( u1 < ustop ) {
2661 if ( *u1 == INDEX ) goto NoPoly;
2662 u1 += u1[1];
2663 }
2664 u1 = u2;
2665 }
2666 }
2667 }
2668 S->PolyWise = WORDDIF(s1,term1);
2669 S->PolyWise -= FUNHEAD;
2670 count = 1;
2671 continue;
2672 }
2673 else {
2674 S->PolyWise = localPoly = 0;
2675 }
2676 }
2677 else {
2678 S->PolyWise = localPoly = 0;
2679 }
2680 }
2681 else {
2682 t1 = term1 + S->PolyWise;
2683 t2 = term2 + S->PolyWise;
2684 S->PolyWise = 0;
2685 localPoly = 0;
2686 continue;
2687 }
2688 }
2689#ifdef WITHFLOAT
2690 if ( level == 0 && c1 == FLOATFUN && t1 == stopper1 && t2 == stopper2 && AT.aux_ != 0 ) {
2691/*
2692 We have two FLOATFUN's. Test whether they are 'legal'
2693*/
2694 if ( TestFloat(s1-FUNHEAD) ) {
2695 if ( TestFloat(s2-FUNHEAD) ) { AT.SortFloatMode = 3; return(0); }
2696 else { return(1); }
2697 }
2698 else if ( TestFloat(s2-FUNHEAD) ) { return(-1); }
2699 }
2700#endif
2701 while ( s1 < t1 ) {
2702/*
2703 The next statement was added 9-nov-2001. It repaired a bad error
2704*/
2705 if ( s2 >= t2 ) return(PREV(-1));
2706/*
2707 There is a little problem here with fast arguments
2708 We don't want to sacrifice speed, but we like to
2709 keep a rational ordering. This last one suffers in
2710 the solution that has been chosen here.
2711*/
2712 if ( AC.properorderflag ) {
2713 WORD oldpolyflag;
2714 oldpolyflag = S->PolyFlag;
2715 S->PolyFlag = 0;
2716 if ( ( c2 = -CompArg(s1,s2) ) != 0 ) {
2717 S->PolyFlag = oldpolyflag; return(PREV(c2));
2718 }
2719 S->PolyFlag = oldpolyflag;
2720 NEXTARG(s1)
2721 NEXTARG(s2)
2722 }
2723 else {
2724 if ( *s1 > 0 ) {
2725 if ( *s2 > 0 ) {
2726 WORD oldpolyflag;
2727 stopex1 = s1 + *s1;
2728 if ( s2 >= t2 ) return(PREV(-1));
2729 stopex2 = s2 + *s2;
2730 s1 += ARGHEAD; s2 += ARGHEAD;
2731 oldpolyflag = S->PolyFlag;
2732 S->PolyFlag = 0;
2733 while ( s1 < stopex1 ) {
2734 if ( s2 >= stopex2 ) {
2735 S->PolyFlag = oldpolyflag; return(PREV(-1));
2736 }
2737 if ( ( c2 = CompareTerms(BHEAD s1,s2,(WORD)1) ) != 0 ) {
2738 S->PolyFlag = oldpolyflag; return(PREV(c2));
2739 }
2740 s1 += *s1;
2741 s2 += *s2;
2742 }
2743 S->PolyFlag = oldpolyflag;
2744 if ( s2 < stopex2 ) return(PREV(1));
2745 }
2746 else return(PREV(1));
2747 }
2748 else {
2749 if ( *s2 > 0 ) return(PREV(-1));
2750 if ( *s1 != *s2 ) { return(PREV(*s1-*s2)); }
2751 if ( *s1 > -FUNCTION ) {
2752 if ( *++s1 != *++s2 ) { return(PREV(*s2-*s1)); }
2753 }
2754 s1++; s2++;
2755 }
2756 }
2757 }
2758 if ( s2 < t2 ) return(PREV(1));
2759 }
2760 }
2761#ifdef WITHFLOAT
2762 if ( level == 0 && t1 < stopper1 && *t1 == FLOATFUN && t1+t1[1] == stopper1
2763 && TestFloat(t1) && AT.aux_ != 0 ) {
2764 AT.SortFloatMode = 1; return(0);
2765 }
2766 else if ( level == 0 && t2 < stopper2 && *t2 == FLOATFUN && t2+t2[1] == stopper2
2767 && TestFloat(t2) && AT.aux_ != 0 ) {
2768 AT.SortFloatMode = 2; return(0);
2769 }
2770#endif
2771 {
2772 if ( AR.SortType != SORTLOWFIRST ) {
2773 if ( t1 < stopper1 ) return(PREV(1));
2774 if ( t2 < stopper2 ) return(PREV(-1));
2775 }
2776 else {
2777 if ( t1 < stopper1 ) return(PREV(-1));
2778 if ( t2 < stopper2 ) return(PREV(1));
2779 }
2780 }
2781 if ( level == 3 ) return(CompCoef(term1,term2));
2782 if ( level >= 1 )
2783 return(CompCoef(term2,term1));
2784 return(0);
2785}
2786
2787/*
2788 #] Compare1 :
2789 #[ CompareSymbols : WORD CompareSymbols(term1,term2,par)
2790*/
2804WORD CompareSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
2805{
2806 int sum1, sum2;
2807 WORD *t1, *t2, *tt1, *tt2;
2808 int low, high;
2809 DUMMYUSE(par);
2810 if ( AR.SortType == SORTLOWFIRST ) { low = 1; high = -1; }
2811 else { low = -1; high = 1; }
2812 t1 = term1 + 1; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); t1 += 2;
2813 t2 = term2 + 1; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); t2 += 2;
2814 if ( AN.polysortflag > 0 ) {
2815 sum1 = 0; sum2 = 0;
2816 while ( t1 < tt1 ) { sum1 += t1[1]; t1 += 2; }
2817 while ( t2 < tt2 ) { sum2 += t2[1]; t2 += 2; }
2818 if ( sum1 < sum2 ) return(low);
2819 if ( sum1 > sum2 ) return(high);
2820 t1 = term1+3; t2 = term2 + 3;
2821 }
2822 while ( t1 < tt1 && t2 < tt2 ) {
2823 if ( *t1 > *t2 ) return(low);
2824 if ( *t1 < *t2 ) return(high);
2825 if ( t1[1] < t2[1] ) return(low);
2826 if ( t1[1] > t2[1] ) return(high);
2827 t1 += 2; t2 += 2;
2828 }
2829 if ( t1 < tt1 ) return(high);
2830 if ( t2 < tt2 ) return(low);
2831 return(0);
2832}
2833
2834/*
2835 #] CompareSymbols :
2836 #[ CompareHSymbols : WORD CompareHSymbols(term1,term2,par)
2837*/
2847WORD CompareHSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
2848{
2849 WORD *t1, *t2, *tt1, *tt2, *ttt1, *ttt2;
2850 DUMMYUSE(par);
2851 DUMMYUSE(AT.WorkPointer);
2852 t1 = term1 + 1; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); t1 += 2;
2853 t2 = term2 + 1; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); t2 += 2;
2854 while ( t1 < tt1 && t2 < tt2 ) {
2855 if ( *t1 != *t2 ) {
2856 if ( t1[0] < t2[0] ) return(-1);
2857 return(1);
2858 }
2859 else if ( *t1 == HAAKJE ) {
2860 t1 += 3; t2 += 3; continue;
2861 }
2862 ttt1 = t1+t1[1]; ttt2 = t2+t2[1];
2863 while ( t1 < ttt1 && t2 < ttt2 ) {
2864 if ( *t1 > *t2 ) return(-1);
2865 if ( *t1 < *t2 ) return(1);
2866 if ( t1[1] < t2[1] ) return(-1);
2867 if ( t1[1] > t2[1] ) return(1);
2868 t1 += 2; t2 += 2;
2869 }
2870 if ( t1 < ttt1 ) return(1);
2871 if ( t2 < ttt2 ) return(-1);
2872 }
2873 if ( t1 < tt1 ) return(1);
2874 if ( t2 < tt2 ) return(-1);
2875 return(0);
2876}
2877
2878/*
2879 #] CompareHSymbols :
2880 #[ ComPress : LONG ComPress(ss,n)
2881*/
2900LONG ComPress(WORD **ss, LONG *n)
2901{
2902 GETIDENTITY
2903 WORD *t, *s, j, k;
2904 LONG size = 0;
2905 int newsize, i;
2906/*
2907 #[ debug :
2908
2909 WORD **sss = ss;
2910
2911 if ( AP.DebugFlag ) {
2912 UBYTE OutBuf[140];
2913 MLOCK(ErrorMessageLock);
2914 MesPrint("ComPress:");
2915 AO.OutFill = AO.OutputLine = OutBuf;
2916 AO.OutSkip = 3;
2917 FiniLine();
2918 ss = sss;
2919 while ( *ss ) {
2920 s = *ss++;
2921 j = *s;
2922 if ( j < 0 ) {
2923 j = s[1] + 2;
2924 }
2925 while ( --j >= 0 ) {
2926 TalToLine((UWORD)(*s++)); TokenToLine((UBYTE *)" ");
2927 }
2928 FiniLine();
2929 }
2930 AO.OutSkip = 0;
2931 FiniLine();
2932 MUNLOCK(ErrorMessageLock);
2933 ss = sss;
2934 }
2935
2936 #] debug :
2937*/
2938 *n = 0;
2939 if ( AT.SS == AT.S0 && !AR.NoCompress ) {
2940 if ( AN.compressSize == 0 ) {
2941 if ( *ss ) { AN.compressSize = **ss + 64; }
2942 else { AN.compressSize = AM.MaxTer/sizeof(WORD) + 2; }
2943 AN.compressSpace = (WORD *)Malloc1(AN.compressSize*sizeof(WORD),"Compression");
2944 }
2945 AN.compressSpace[0] = 0;
2946 while ( *ss ) {
2947 k = 0;
2948 s = *ss;
2949 j = *s++;
2950 if ( j > AN.compressSize ) {
2951 newsize = j + 64;
2952 t = (WORD *)Malloc1(newsize*sizeof(WORD),"Compression");
2953 t[0] = 0;
2954 if ( AN.compressSpace ) {
2955 for ( i = 0; i < *AN.compressSpace; i++ ) t[i] = AN.compressSpace[i];
2956 M_free(AN.compressSpace,"Compression");
2957 }
2958 AN.compressSpace = t;
2959 AN.compressSize = newsize;
2960 }
2961 t = AN.compressSpace;
2962 i = *t - 1;
2963 *t++ = j; j--;
2964 if ( AR.PolyFun ) {
2965 WORD *polystop, *sa;
2966 sa = s + j;
2967 sa -= ABS(sa[-1]);
2968 polystop = s;
2969 while ( polystop < sa && *polystop != AR.PolyFun ) {
2970 polystop += polystop[1];
2971 }
2972 while ( i > 0 && j > 0 && *s == *t && s < polystop ) {
2973 i--; j--; s++; t++; k--;
2974 }
2975 }
2976 else {
2977 WORD *sa;
2978 sa = s + j;
2979 sa -= ABS(sa[-1]);
2980 while ( i > 0 && j > 0 && *s == *t && s < sa ) { i--; j--; s++; t++; k--; }
2981 }
2982 if ( k < -1 ) {
2983 s[-1] = j;
2984 s[-2] = k;
2985 *ss = s-2;
2986 size += j + 2;
2987 }
2988 else {
2989 size += *AN.compressSpace;
2990 if ( k == -1 ) { t--; s--; j++; }
2991 }
2992 while ( --j >= 0 ) *t++ = *s++;
2993/* Sabotage getting into the coefficient next time */
2994 t = AN.compressSpace + *AN.compressSpace;
2995 t[-(ABS(t[-1]))] = 0;
2996 ss++;
2997 (*n)++;
2998 }
2999 }
3000 else {
3001 while ( *ss ) {
3002 size += *(*ss++);
3003 (*n)++;
3004 }
3005 }
3006/*
3007 #[ debug :
3008
3009 if ( AP.DebugFlag ) {
3010 UBYTE OutBuf[140];
3011 AO.OutFill = AO.OutputLine = OutBuf;
3012 AO.OutSkip = 3;
3013 FiniLine();
3014 ss = sss;
3015 while ( *ss ) {
3016 s = *ss++;
3017 j = *s;
3018 if ( j < 0 ) {
3019 j = s[1] + 2;
3020 }
3021 while ( --j >= 0 ) {
3022 TalToLine((UWORD)(*s++)); TokenToLine((UBYTE *)" ");
3023 }
3024 FiniLine();
3025 }
3026 AO.OutSkip = 0;
3027 FiniLine();
3028 }
3029
3030 #] debug :
3031*/
3032 return(size);
3033}
3034
3035/*
3036 #] ComPress :
3037 #[ SplitMerge : void SplitMerge(Point,number)
3038*/
3064#ifdef NEWSPLITMERGE
3065
3066LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
3067{
3068 GETBIDENTITY
3069 SORTING *S = AT.SS;
3070 WORD **pp3, **pp1, **pp2, **pptop;
3071 LONG i, newleft, newright, split;
3072
3073#ifdef SPLITMERGEDEBUG
3074 /* Print current array state on entry. */
3075 printf("%4ld: ", number);
3076 for (int ii = 0; ii < S->sTerms; ii++) {
3077 if ( (S->sPointer)[ii] ) {
3078 printf("%4d ", (unsigned)(S->sPointer[ii]-S->sBuffer));
3079 }
3080 else {
3081 printf(".... ");
3082 }
3083 }
3084 printf("\n");
3085 fflush(stdout);
3086#endif
3087
3088 if ( number < 2 ) return(number);
3089 if ( number == 2 ) {
3090 pp1 = Pointer; pp2 = pp1 + 1;
3091 if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
3092 pp3 = (WORD **)(*pp1); *pp1 = *pp2; *pp2 = (WORD *)pp3;
3093 }
3094 else if ( i == 0 ) {
3095 number--;
3096 if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) == 0 ) number = 0; }
3097 else { if ( AddCoef(BHEAD pp1,pp2) == 0 ) number = 0; }
3098 }
3099 return(number);
3100 }
3101 pptop = Pointer + number;
3102 split = number/2;
3103 newleft = SplitMerge(BHEAD Pointer,split);
3104 newright = SplitMerge(BHEAD Pointer+split,number-split);
3105 if ( newright == 0 ) return(newleft);
3106/*
3107 We compare the last of the left with the first of the right
3108 If they are already in order, we will be done quickly.
3109 We may have to compactify the buffer because the recursion may
3110 have created holes. Also this compare may result in equal terms.
3111 Addition of 23-jul-1999. It makes things a bit faster.
3112*/
3113 if ( newleft > 0 && newright > 0 &&
3114 ( i = CompareTerms(BHEAD Pointer[newleft-1],Pointer[split],(WORD)0) ) >= 0 ) {
3115 pp2 = Pointer+split; pp1 = Pointer+newleft-1;
3116 if ( i == 0 ) {
3117 if ( S->PolyWise ) {
3118 if ( AddPoly(BHEAD pp1,pp2) > 0 ) pp1++;
3119 else newleft--;
3120 }
3121 else {
3122 if ( AddCoef(BHEAD pp1,pp2) > 0 ) pp1++;
3123 else newleft--;
3124 }
3125 *pp2++ = 0; newright--;
3126 }
3127 else pp1++;
3128 newleft += newright;
3129 if ( pp1 < pp2 ) {
3130 while ( --newright >= 0 ) *pp1++ = *pp2++;
3131 while ( pp1 < pptop ) *pp1++ = 0;
3132 }
3133 return(newleft);
3134 }
3135
3136 if ( split >= AN.SplitScratchSize ) {
3137 AN.SplitScratchSize = (split*3)/2+100;
3138 if ( AN.SplitScratchSize > S->Terms2InSmall/2 )
3139 AN.SplitScratchSize = S->Terms2InSmall/2;
3140 if ( AN.SplitScratch ) M_free(AN.SplitScratch,"AN.SplitScratch");
3141 AN.SplitScratch = (WORD **)Malloc1(AN.SplitScratchSize*sizeof(WORD *),"AN.SplitScratch");
3142 }
3143
3144 pp3 = AN.SplitScratch; pp1 = Pointer;
3145 /* Move rather than copy, so GarbHand can't double-count. */
3146 for ( i = 0; i < newleft; i++ ) { *pp3++ = *pp1; *pp1++ = 0; }
3147 AN.InScratch = newleft;
3148 pp1 = AN.SplitScratch; pp2 = Pointer + split; pp3 = Pointer;
3149
3150#ifdef NEWSPLITMERGETIMSORT
3151/*
3152 An improvement in the style of Timsort
3153*/
3154 while ( newleft > 8 ) {
3155 /* Check the middle of the LHS terms */
3156 LONG nnleft = newleft/2;
3157 if ( ( i = CompareTerms(BHEAD pp1[nnleft],*pp2,(WORD)0) ) < 0 ) {
3158 /* The terms are not in order. Break out and continue as normal. */
3159 break;
3160 }
3161 /* The terms merge or are in order. Copy pointers up to this point. */
3162 /* In the copy, zero the skipped pointers so GarbHand can't double-count. */
3163 for (int iii = 0; iii < nnleft; iii++) {
3164 *pp3++ = *pp1;
3165 *pp1++ = 0;
3166 }
3167 newleft -= nnleft;
3168 if ( i == 0 ) {
3169 if ( S->PolyWise ) { i = AddPoly(BHEAD pp1,pp2); }
3170 else { i = AddCoef(BHEAD pp1,pp2); }
3171 if ( i == 0 ) {
3172 /* The terms cancelled. The next term goes in *pp3. Don't move. */
3173 }
3174 else {
3175 /* The terms added. Advance pp3. */
3176 *pp3++ = *pp1;
3177 }
3178 /* We have taken a LHS (copy) and RHS term. */
3179 *pp2++ = 0;
3180 newright--;
3181 *pp1++ = 0;
3182 newleft--;
3183 break;
3184 }
3185 }
3186#endif
3187
3188 while ( newleft > 0 && newright > 0 ) {
3189 if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
3190 *pp3++ = *pp2;
3191 *pp2++ = 0;
3192 newright--;
3193 }
3194 else if ( i > 0 ) {
3195 *pp3++ = *pp1;
3196 *pp1++ = 0;
3197 newleft--;
3198 }
3199 else {
3200 if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3201 else { if ( AddCoef(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3202 *pp1++ = 0; *pp2++ = 0; newleft--; newright--;
3203 }
3204 }
3205 for ( i = 0; i < newleft; i++ ) { *pp3++ = *pp1; *pp1++ = 0; }
3206 if ( pp3 == pp2 ) {
3207 pp3 += newright;
3208 } else {
3209 for ( i = 0; i < newright; i++ ) { *pp3++ = *pp2++; }
3210 }
3211 newleft = pp3 - Pointer;
3212 while ( pp3 < pptop ) *pp3++ = 0;
3213 AN.InScratch = 0;
3214 return(newleft);
3215}
3216
3217#else
3218
3219LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
3220{
3221 GETBIDENTITY
3222 SORTING *S = AT.SS;
3223 WORD **pp3, **pp1, **pp2;
3224 LONG nleft, nright, i, newleft, newright;
3225 WORD **pptop;
3226
3227#ifdef SPLITMERGEDEBUG
3228 /* Print current array state on entry. */
3229 printf("%4ld: ", number);
3230 for (int ii = 0; ii < S->sTerms; ii++) {
3231 if ( (S->sPointer)[ii] ) {
3232 printf("%4d ", (unsigned)(S->sPointer[ii]-S->sBuffer));
3233 }
3234 else {
3235 printf(".... ");
3236 }
3237 }
3238 printf("\n");
3239 fflush(stdout);
3240#endif
3241
3242 if ( number < 2 ) return(number);
3243 if ( number == 2 ) {
3244 pp1 = Pointer; pp2 = pp1 + 1;
3245 if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
3246 pp3 = (WORD **)(*pp1); *pp1 = *pp2; *pp2 = (WORD *)pp3;
3247 }
3248 else if ( i == 0 ) {
3249 number--;
3250 if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) == 0 ) { number = 0; } }
3251 else { if ( AddCoef(BHEAD pp1,pp2) == 0 ) { number = 0; } }
3252 }
3253 return(number);
3254 }
3255 pptop = Pointer + number;
3256 nleft = number >> 1; nright = number - nleft;
3257 newleft = SplitMerge(BHEAD Pointer,nleft);
3258 newright = SplitMerge(BHEAD Pointer+nleft,nright);
3259/*
3260 We compare the last of the left with the first of the right
3261 If they are already in order, we will be done quickly.
3262 We may have to compactify the buffer because the recursion may
3263 have created holes. Also this compare may result in equal terms.
3264 Addition of 23-jul-1999. It makes things a bit faster.
3265*/
3266 if ( newleft > 0 && newright > 0 &&
3267 ( i = CompareTerms(BHEAD Pointer[newleft-1],Pointer[nleft],(WORD)0) ) >= 0 ) {
3268 pp2 = Pointer+nleft; pp1 = Pointer+newleft-1;
3269 if ( i == 0 ) {
3270 if ( S->PolyWise ) {
3271 if ( AddPoly(BHEAD pp1,pp2) > 0 ) pp1++;
3272 else newleft--;
3273 }
3274 else {
3275 if ( AddCoef(BHEAD pp1,pp2) > 0 ) pp1++;
3276 else newleft--;
3277 }
3278 *pp2++ = 0; newright--;
3279 }
3280 else pp1++;
3281 newleft += newright;
3282 if ( pp1 < pp2 ) {
3283 while ( --newright >= 0 ) *pp1++ = *pp2++;
3284 while ( pp1 < pptop ) *pp1++ = 0;
3285 }
3286 return(newleft);
3287 }
3288 if ( nleft > AN.SplitScratchSize ) {
3289 AN.SplitScratchSize = (nleft*3)/2+100;
3290 if ( AN.SplitScratchSize > S->Terms2InSmall/2 )
3291 AN.SplitScratchSize = S->Terms2InSmall/2;
3292 if ( AN.SplitScratch ) M_free(AN.SplitScratch,"AN.SplitScratch");
3293 AN.SplitScratch = (WORD **)Malloc1(AN.SplitScratchSize*sizeof(WORD *),"AN.SplitScratch");
3294 }
3295 pp3 = AN.SplitScratch; pp1 = Pointer; i = nleft;
3296 do { *pp3++ = *pp1; *pp1++ = 0; } while ( *pp1 && --i > 0 );
3297 if ( i > 0 ) { *pp3 = 0; i--; }
3298 AN.InScratch = nleft - i;
3299 pp1 = AN.SplitScratch; pp2 = Pointer + nleft; pp3 = Pointer;
3300 while ( nleft > 0 && nright > 0 && *pp1 && *pp2 ) {
3301 if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
3302 *pp3++ = *pp2;
3303 *pp2++ = 0;
3304 nright--;
3305 }
3306 else if ( i > 0 ) {
3307 *pp3++ = *pp1;
3308 *pp1++ = 0;
3309 nleft--;
3310 }
3311 else {
3312 if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3313 else { if ( AddCoef(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3314 *pp1++ = 0; *pp2++ = 0; nleft--; nright--;
3315 }
3316 }
3317 while ( --nleft >= 0 && *pp1 ) { *pp3++ = *pp1; *pp1++ = 0; }
3318 while ( --nright >= 0 && *pp2 ) { *pp3++ = *pp2++; }
3319 nleft = pp3 - Pointer;
3320 while ( pp3 < pptop ) *pp3++ = 0;
3321 AN.InScratch = 0;
3322 return(nleft);
3323}
3324
3325#endif
3326
3327/*
3328 #] SplitMerge :
3329 #[ GarbHand : void GarbHand()
3330*/
3346void GarbHand(void)
3347{
3348 GETIDENTITY
3349 SORTING *S = AT.SS;
3350 WORD **Point, *s2, *t, *garbuf, i;
3351 LONG k, total = 0;
3352 int tobereturned = 0;
3353/*
3354 Compute the size needed. Put it in total.
3355*/
3356#ifdef TESTGARB
3357 MLOCK(ErrorMessageLock);
3358 MesPrint("in: S->sFill = %l, S->sTop2 = %l",S->sFill-S->sBuffer,S->sTop2-S->sBuffer);
3359#endif
3360 Point = S->sPointer;
3361 k = S->sTerms;
3362 while ( --k >= 0 ) {
3363 if ( ( s2 = *Point++ ) != 0 ) { total += *s2; }
3364 }
3365 Point = AN.SplitScratch;
3366 k = AN.InScratch;
3367 while ( --k >= 0 ) {
3368 if ( ( s2 = *Point++ ) != 0 ) { total += *s2; }
3369 }
3370#ifdef TESTGARB
3371 MesPrint("total = %l, nterms = %l",total,AN.InScratch);
3372 MUNLOCK(ErrorMessageLock);
3373#endif
3374/*
3375 Test now whether it fits. If so deal with the problem inside
3376 the memory at the tail of the large buffer.
3377*/
3378 if ( S->lBuffer != 0 && S->lFill + total <= S->lTop ) {
3379 garbuf = S->lFill;
3380 }
3381 else {
3382 garbuf = (WORD *)Malloc1(total*sizeof(WORD),"Garbage buffer");
3383 tobereturned = 1;
3384 }
3385 t = garbuf;
3386 Point = S->sPointer;
3387 k = S->sTerms;
3388 while ( --k >= 0 ) {
3389 if ( *Point ) {
3390 s2 = *Point++;
3391 i = *s2;
3392 NCOPY(t,s2,i);
3393 }
3394 else { Point++; }
3395 }
3396 Point = AN.SplitScratch;
3397 k = AN.InScratch;
3398 while ( --k >= 0 ) {
3399 if ( *Point ) {
3400 s2 = *Point++;
3401 i = *s2;
3402 NCOPY(t,s2,i);
3403 }
3404 else Point++;
3405 }
3406 s2 = S->sBuffer;
3407 t = garbuf;
3408 Point = S->sPointer;
3409 k = S->sTerms;
3410 while ( --k >= 0 ) {
3411 if ( *Point ) {
3412 *Point++ = s2;
3413 i = *t;
3414 NCOPY(s2,t,i);
3415 }
3416 else { Point++; }
3417 }
3418 Point = AN.SplitScratch;
3419 k = AN.InScratch;
3420 while ( --k >= 0 ) {
3421 if ( *Point ) {
3422 *Point++ = s2;
3423 i = *t;
3424 NCOPY(s2,t,i);
3425 }
3426 else Point++;
3427 }
3428 S->sFill = s2;
3429#ifdef TESTGARB
3430 MLOCK(ErrorMessageLock);
3431 MesPrint("out: S->sFill = %l, S->sTop2 = %l",S->sFill-S->sBuffer,S->sTop2-S->sBuffer);
3432 if ( S->sFill >= S->sTop2 ) {
3433 MesPrint("We are in deep trouble");
3434 }
3435 MUNLOCK(ErrorMessageLock);
3436#endif
3437 if ( tobereturned ) M_free(garbuf,"Garbage buffer");
3438 return;
3439}
3440
3441/*
3442 #] GarbHand :
3443 #[ MergePatches : WORD MergePatches(par)
3444*/
3461int MergePatches(WORD par)
3462{
3463 GETIDENTITY
3464 SORTING *S = AT.SS;
3465 WORD **poin, **poin2, ul, k, i, im, *m1;
3466 WORD *p, lpat, mpat, level, l1, l2, r1, r2, r3, c;
3467 WORD *m2, *m3, r31, r33, ki, *rr;
3468 UWORD *coef;
3469 POSITION position;
3470 FILEHANDLE *fin, *fout;
3471 int fhandle;
3472/*
3473 UBYTE *s;
3474*/
3475#ifdef WITHZLIB
3476 POSITION position2;
3477 int oldgzipCompress = AR.gzipCompress;
3478 if ( par == 2 ) {
3479 AR.gzipCompress = 0;
3480 }
3481#endif
3482 fin = &S->file;
3483 fout = &(AR.FoStage4[0]);
3484NewMerge:
3485 coef = AN.SoScratC;
3486 poin = S->poina; poin2 = S->poin2a;
3487 rr = AR.CompressPointer;
3488 *rr = 0;
3489/*
3490 #[ Setup :
3491*/
3492 if ( par == 1 ) {
3493 fout = &(S->file);
3494 if ( fout->handle < 0 ) {
3495FileMake:
3496 PUTZERO(AN.OldPosOut);
3497 if ( ( fhandle = CreateFile(fout->name) ) < 0 ) {
3498 MLOCK(ErrorMessageLock);
3499 MesPrint("Cannot create file %s",fout->name);
3500 MUNLOCK(ErrorMessageLock);
3501 goto ReturnError;
3502 }
3503#ifdef GZIPDEBUG
3504 MLOCK(ErrorMessageLock);
3505 MesPrint("%w MergePatches created output file %s",fout->name);
3506 MUNLOCK(ErrorMessageLock);
3507#endif
3508 fout->handle = fhandle;
3509 PUTZERO(fout->filesize);
3510 PUTZERO(fout->POposition);
3511/*
3512 Should not be here?
3513#ifdef WITHZLIB
3514 fout->ziobuffer = 0;
3515#endif
3516*/
3517#ifdef ALLLOCK
3518 LOCK(fout->pthreadslock);
3519#endif
3520 SeekFile(fout->handle,&(fout->filesize),SEEK_SET);
3521#ifdef ALLLOCK
3522 UNLOCK(fout->pthreadslock);
3523#endif
3524 S->fPatchN = 0;
3525 PUTZERO(S->fPatches[0]);
3526 fout->POfill = fout->PObuffer;
3527 PUTZERO(fout->POposition);
3528 }
3529ConMer:
3530 StageSort(fout);
3531#ifdef WITHZLIB
3532 if ( S == AT.S0 && AR.NoCompress == 0 && AR.gzipCompress > 0 )
3533 S->fpcompressed[S->fPatchN] = 1;
3534 else
3535 S->fpcompressed[S->fPatchN] = 0;
3536 SetupOutputGZIP(fout);
3537#endif
3538 }
3539 else if ( par == 0 && S->stage4 > 0 ) {
3540/*
3541 We will have to do our job more than once.
3542 Input is from S->file and output will go to AR.FoStage4.
3543 The file corresponding to this last one must be made now.
3544*/
3545 AR.Stage4Name ^= 1;
3546/*
3547 s = (UBYTE *)(fout->name); while ( *s ) s++;
3548 if ( AR.Stage4Name ) s[-1] += 1;
3549 else s[-1] -= 1;
3550*/
3551 S->iPatches = S->fPatches;
3552 S->fPatches = S->inPatches;
3553 S->inPatches = S->iPatches;
3554 (S->inNum) = S->fPatchN;
3555 AN.OldPosIn = AN.OldPosOut;
3556#ifdef WITHZLIB
3557 m1 = S->fpincompressed;
3558 S->fpincompressed = S->fpcompressed;
3559 S->fpcompressed = m1;
3560 for ( i = 0; i < S->inNum; i++ ) {
3561 S->fPatchesStop[i] = S->iPatches[i+1];
3562#ifdef GZIPDEBUG
3563 MLOCK(ErrorMessageLock);
3564 MesPrint("%w fPatchesStop[%d] = %10p",i,&(S->fPatchesStop[i]));
3565 MUNLOCK(ErrorMessageLock);
3566#endif
3567 }
3568#endif
3569 S->stage4 = 0;
3570 goto FileMake;
3571 }
3572 else {
3573#ifdef WITHZLIB
3574/*
3575 The next statement is just for now
3576*/
3577 AR.gzipCompress = 0;
3578#endif
3579 if ( par == 0 ) {
3580 S->iPatches = S->fPatches;
3581 S->inNum = S->fPatchN;
3582#ifdef WITHZLIB
3583 m1 = S->fpincompressed;
3584 S->fpincompressed = S->fpcompressed;
3585 S->fpcompressed = m1;
3586 for ( i = 0; i < S->inNum; i++ ) {
3587 S->fPatchesStop[i] = S->fPatches[i+1];
3588#ifdef GZIPDEBUG
3589 MLOCK(ErrorMessageLock);
3590 MesPrint("%w fPatchesStop[%d] = %10p",i,&(S->fPatchesStop[i]));
3591 MUNLOCK(ErrorMessageLock);
3592#endif
3593 }
3594#endif
3595 }
3596 fout = AR.outfile;
3597 }
3598 if ( par ) { /* Mark end of patches */
3599 S->Patches[S->lPatch] = S->lFill;
3600 for ( i = 0; i < S->lPatch; i++ ) {
3601 S->pStop[i] = S->Patches[i+1]-1;
3602 S->Patches[i] = (WORD *)(((UBYTE *)(S->Patches[i])) + AM.MaxTer);
3603 }
3604 }
3605 else { /* Load the patches */
3606 S->lPatch = (S->inNum);
3607#ifdef WITHMPI
3608 if ( S->lPatch > 1 || ( (PF.exprtodo <0) && (fout == AR.outfile || fout == AR.hidefile ) ) ) {
3609#else
3610 if ( S->lPatch > 1 ) {
3611#endif
3612#ifdef WITHZLIB
3613 SetupAllInputGZIP(S);
3614#endif
3615 p = S->lBuffer;
3616 for ( i = 0; i < S->lPatch; i++ ) {
3617 p = (WORD *)(((UBYTE *)p)+2*AM.MaxTer+COMPINC*sizeof(WORD));
3618 S->Patches[i] = p;
3619 p = (WORD *)(((UBYTE *)p) + fin->POsize);
3620 S->pStop[i] = m2 = p;
3621#ifdef WITHZLIB
3622 PutIn(fin,&(S->iPatches[i]),S->Patches[i],&m2,i);
3623#else
3624 ADDPOS(S->iPatches[i],PutIn(fin,&(S->iPatches[i]),S->Patches[i],&m2,i));
3625#endif
3626 }
3627 }
3628 }
3629 if ( fout->handle >= 0 ) {
3630 PUTZERO(position);
3631#ifdef ALLLOCK
3632 LOCK(fout->pthreadslock);
3633#endif
3634 SeekFile(fout->handle,&position,SEEK_END);
3635 ADDPOS(position,((fout->POfill-fout->PObuffer)*sizeof(WORD)));
3636#ifdef ALLLOCK
3637 UNLOCK(fout->pthreadslock);
3638#endif
3639 }
3640 else {
3641 SETBASEPOSITION(position,(fout->POfill-fout->PObuffer)*sizeof(WORD));
3642 }
3643/*
3644 #] Setup :
3645
3646 The old code had to be replaced because all output needs to go
3647 through PutOut. For this we have to go term by term and keep
3648 track of the compression.
3649*/
3650 if ( S->lPatch == 1 ) { /* Single patch --> direct copy. Very rare. */
3651 LONG length;
3652
3653 if ( fout->handle < 0 ) if ( Sflush(fout) ) goto PatCall;
3654 if ( par ) { /* Memory to file */
3655#ifdef WITHZLIB
3656/*
3657 We fix here the problem that the thing needs to go through PutOut
3658*/
3659 m2 = m1 = *S->Patches; /* The m2 is to keep the compiler from complaining */
3660 while ( *m1 ) {
3661 if ( *m1 < 0 ) { /* Need to uncompress */
3662 i = -(*m1++); m2 += i; im = *m1+i+1;
3663 while ( i > 0 ) { *m1-- = *m2--; i--; }
3664 *m1 = im;
3665 }
3666#ifdef WITHPTHREADS
3667 /* Check here (and in the following) that we are at ground level
3668 (so S == AT.S0) to use PutToMaster. Control can reach here,
3669 with AS.MasterSort, but with S != AT.S0, when the SortBots are
3670 adding PolyRatFun and the sorting of their arguments requires
3671 large buffer patches to be merged. In this case, terms escape
3672 the PolyRatFun argument and end up at ground level, if we use
3673 PutToMaster. */
3674 if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
3675 im = PutToMaster(BHEAD m1);
3676 }
3677 else
3678#endif
3679 if ( ( im = PutOut(BHEAD m1,&position,fout,1) ) < 0 ) goto ReturnError;
3680 ADDPOS(S->SizeInFile[par],im);
3681 m2 = m1;
3682 m1 += *m1;
3683 }
3684#ifdef WITHPTHREADS
3685 if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
3686 PutToMaster(BHEAD 0);
3687 }
3688 else
3689#endif
3690 if ( FlushOut(&position,fout,1) ) goto ReturnError;
3691 ADDPOS(S->SizeInFile[par],1);
3692#else
3693/* old code */
3694 length = (LONG)(*S->pStop)-(LONG)(*S->Patches)+sizeof(WORD);
3695 if ( WriteFile(fout->handle,(UBYTE *)(*S->Patches),length) != length )
3696 goto PatwCall;
3697 ADDPOS(position,length);
3698 ADDPOS(fout->POposition,length);
3699 ADDPOS(fout->filesize,length);
3700 ADDPOS(S->SizeInFile[par],length/sizeof(WORD));
3701#endif
3702 }
3703 else { /* File to file */
3704#ifdef WITHZLIB
3705/*
3706 Note: if we change FRONTSIZE we need to make the minimum value
3707 of SmallEsize in AllocSort correspondingly larger or smaller.
3708 Theoretically we could get close to 2*AM.MaxTer!
3709*/
3710 #define FRONTSIZE (2*AM.MaxTer)
3711 WORD *copybuf = (WORD *)(((UBYTE *)(S->sBuffer)) + FRONTSIZE);
3712 WORD *copytop;
3713 SetupAllInputGZIP(S);
3714 m1 = m2 = copybuf;
3715 position2 = S->iPatches[0];
3716 while ( ( length = FillInputGZIP(fin,&position2,
3717 (UBYTE *)copybuf,
3718 (S->SmallEsize*sizeof(WORD)-FRONTSIZE),0) ) > 0 ) {
3719 copytop = (WORD *)(((UBYTE *)copybuf)+length);
3720 while ( *m1 && ( ( *m1 > 0 && m1+*m1 < copytop ) ||
3721 ( *m1 < 0 && ( m1+1 < copytop ) && ( m1+m1[1]+1 < copytop ) ) ) )
3722/*
3723 22-jun-2013 JV Extremely nasty bug that has been around for a while.
3724 What if the end is in the remaining part? We will loose terms!
3725 while ( *m1 && ( (WORD *)(((UBYTE *)(m1)) + AM.MaxTer ) < S->sTop2 ) )
3726*/
3727 {
3728 if ( *m1 < 0 ) { /* Need to uncompress */
3729 i = -(*m1++); m2 += i; im = *m1+i+1;
3730 while ( i > 0 ) { *m1-- = *m2--; i--; }
3731 *m1 = im;
3732 }
3733#ifdef WITHPTHREADS
3734 if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
3735 im = PutToMaster(BHEAD m1);
3736 }
3737 else
3738#endif
3739 if ( ( im = PutOut(BHEAD m1,&position,fout,1) ) < 0 ) goto ReturnError;
3740 ADDPOS(S->SizeInFile[par],im);
3741 m2 = m1;
3742 m1 += *m1;
3743 }
3744 if ( m1 < copytop && *m1 == 0 ) break;
3745/*
3746 Now move the remaining part 'back'
3747*/
3748 m3 = copybuf;
3749 m1 = copytop;
3750 while ( m1 > m2 ) *--m3 = *--m1;
3751 m2 = m3;
3752 m1 = m2 + *m2;
3753 }
3754 if ( length < 0 ) {
3755 MLOCK(ErrorMessageLock);
3756 MesPrint("Readerror");
3757 goto PatCall2;
3758 }
3759#ifdef WITHPTHREADS
3760 if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
3761 PutToMaster(BHEAD 0);
3762 }
3763 else
3764#endif
3765 if ( FlushOut(&position,fout,1) ) goto ReturnError;
3766 ADDPOS(S->SizeInFile[par],1);
3767#else
3768/* old code */
3769 SeekFile(fin->handle,&(S->iPatches[0]),SEEK_SET); /* needed for stage4 */
3770 while ( ( length = ReadFile(fin->handle,
3771 (UBYTE *)(S->sBuffer),S->SmallEsize*sizeof(WORD)) ) > 0 ) {
3772 if ( WriteFile(fout->handle,(UBYTE *)(S->sBuffer),length) != length )
3773 goto PatwCall;
3774 ADDPOS(position,length);
3775 ADDPOS(fout->POposition,length);
3776 ADDPOS(fout->filesize,length);
3777 ADDPOS(S->SizeInFile[par],length/sizeof(WORD));
3778 }
3779 if ( length < 0 ) {
3780 MLOCK(ErrorMessageLock);
3781 MesPrint("Readerror");
3782 goto PatCall2;
3783 }
3784#endif
3785 }
3786 goto EndOfAll;
3787 }
3788 else if ( S->lPatch > 0 ) {
3789
3790 /* More than one patch. Construct the tree. */
3791
3792 lpat = 1;
3793 do { lpat *= 2; } while ( lpat < S->lPatch );
3794 mpat = ( lpat >> 1 ) - 1;
3795 k = lpat - S->lPatch;
3796
3797 /* k is the number of empty places in the tree. they will
3798 be at the even positions from 2 to 2*k */
3799
3800 for ( i = 1; i < lpat; i++ ) {
3801 S->tree[i] = -1;
3802 }
3803 for ( i = 1; i <= k; i++ ) {
3804 im = ( i * 2 ) - 1;
3805 poin[im] = S->Patches[i-1];
3806 poin2[im] = poin[im] + *(poin[im]);
3807 S->used[i] = im;
3808 S->ktoi[im] = i-1;
3809 S->tree[mpat+i] = 0;
3810 poin[im-1] = poin2[im-1] = 0;
3811 }
3812 for ( i = (k*2)+1; i <= lpat; i++ ) {
3813 S->used[i-k] = i;
3814 S->ktoi[i] = i-k-1;
3815 poin[i] = S->Patches[i-k-1];
3816 poin2[i] = poin[i] + *(poin[i]);
3817 }
3818/*
3819 the array poin tells the position of the i-th element of the S->tree
3820 'S->used' is a stack with the S->tree elements that need to be entered
3821 into the S->tree. at the beginning this is S->lPatch. during the
3822 sort there will be only very few elements.
3823 poin2 is the next value of poin. it has to be determined
3824 before the comparisons as the position or the size of the
3825 term indicated by poin may change.
3826 S->ktoi translates a S->tree element back to its stream number.
3827
3828 start the sort
3829*/
3830 level = S->lPatch;
3831
3832 /* introduce one term */
3833OneTerm:
3834 k = S->used[level];
3835 i = k + lpat - 1;
3836 if ( !*(poin[k]) ) {
3837 do { if ( !( i >>= 1 ) ) goto EndOfMerge; } while ( !S->tree[i] );
3838 if ( S->tree[i] == -1 ) {
3839 S->tree[i] = 0;
3840 level--;
3841 goto OneTerm;
3842 }
3843 k = S->tree[i];
3844 S->used[level] = k;
3845 S->tree[i] = 0;
3846 }
3847/*
3848 move terms down the tree
3849*/
3850 while ( i >>= 1 ) {
3851 if ( S->tree[i] > 0 ) {
3852 if ( ( c = CompareTerms(BHEAD poin[S->tree[i]],poin[k],(WORD)0) ) > 0 ) {
3853/*
3854 S->tree[i] is the smaller. Exchange and go on.
3855*/
3856 S->used[level] = S->tree[i];
3857 S->tree[i] = k;
3858 k = S->used[level];
3859 }
3860 else if ( !c ) { /* Terms are equal */
3861 S->TermsLeft--;
3862/*
3863 Here the terms are equal and their coefficients
3864 have to be added.
3865*/
3866 l1 = *( m1 = poin[S->tree[i]] );
3867 l2 = *( m2 = poin[k] );
3868 if ( S->PolyWise ) { /* Here we work with PolyFun */
3869 WORD *tt1, *w;
3870 tt1 = m1;
3871 m1 += S->PolyWise;
3872 m2 += S->PolyWise;
3873 if ( S->PolyFlag == 2 ) {
3874 w = poly_ratfun_add(BHEAD m1,m2);
3875 if ( *tt1 + w[1] - m1[1] > AM.MaxTer/((LONG)sizeof(WORD)) ) {
3876 MLOCK(ErrorMessageLock);
3877 MesPrint("Term too complex in PolyRatFun addition. MaxTermSize of %10l is too small",AM.MaxTer);
3878 MUNLOCK(ErrorMessageLock);
3879 Terminate(-1);
3880 }
3881 AT.WorkPointer = w;
3882 }
3883 else {
3884 w = AT.WorkPointer;
3885 if ( w + m1[1] + m2[1] > AT.WorkTop ) {
3886 MLOCK(ErrorMessageLock);
3887 MesPrint("A WorkSpace of %10l is too small",AM.WorkSize);
3888 MUNLOCK(ErrorMessageLock);
3889 Terminate(-1);
3890 }
3891 AddArgs(BHEAD m1,m2,w);
3892 }
3893 r1 = w[1];
3894 if ( r1 <= FUNHEAD
3895 || ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) )
3896 { goto cancelled; }
3897 if ( r1 == m1[1] ) {
3898 NCOPY(m1,w,r1);
3899 }
3900 else if ( r1 < m1[1] ) {
3901 r2 = m1[1] - r1;
3902 m2 = w + r1;
3903 m1 += m1[1];
3904 while ( --r1 >= 0 ) *--m1 = *--m2;
3905 m2 = m1 - r2;
3906 r1 = S->PolyWise;
3907 while ( --r1 >= 0 ) *--m1 = *--m2;
3908 *m1 -= r2;
3909 poin[S->tree[i]] = m1;
3910 }
3911 else {
3912 r2 = r1 - m1[1];
3913 m2 = tt1 - r2;
3914 r1 = S->PolyWise;
3915 m1 = tt1;
3916 *m1 += r2;
3917 poin[S->tree[i]] = m2;
3918 NCOPY(m2,m1,r1);
3919 r1 = w[1];
3920 NCOPY(m2,w,r1);
3921 }
3922 }
3923#ifdef WITHFLOAT
3924 else if ( AT.SortFloatMode ) {
3925 WORD *term1, *term2;
3926 term1 = poin[S->tree[i]];
3927 term2 = poin[k];
3928 if ( MergeWithFloat(BHEAD &term1,&term2) == 0 )
3929 goto cancelled;
3930 poin[S->tree[i]] = term1;
3931 }
3932#endif
3933 else {
3934 r1 = *( m1 += l1 - 1 );
3935 m1 -= ABS(r1) - 1;
3936 r1 = ( ( r1 > 0 ) ? (r1-1) : (r1+1) ) >> 1;
3937 r2 = *( m2 += l2 - 1 );
3938 m2 -= ABS(r2) - 1;
3939 r2 = ( ( r2 > 0 ) ? (r2-1) : (r2+1) ) >> 1;
3940
3941 if ( AddRat(BHEAD (UWORD *)m1,r1,(UWORD *)m2,r2,coef,&r3) ) {
3942 MLOCK(ErrorMessageLock);
3943 MesCall("MergePatches");
3944 MUNLOCK(ErrorMessageLock);
3945 SETERROR(-1)
3946 }
3947
3948 if ( AN.ncmod != 0 ) {
3949 if ( ( AC.modmode & POSNEG ) != 0 ) {
3950 NormalModulus(coef,&r3);
3951 }
3952 else if ( BigLong(coef,r3,(UWORD *)AC.cmod,ABS(AN.ncmod)) >= 0 ) {
3953 WORD ii;
3954 SubPLon(coef,r3,(UWORD *)AC.cmod,ABS(AN.ncmod),coef,&r3);
3955 coef[r3] = 1;
3956 for ( ii = 1; ii < r3; ii++ ) coef[r3+ii] = 0;
3957 }
3958 }
3959 r3 *= 2;
3960 r33 = ( r3 > 0 ) ? ( r3 + 1 ) : ( r3 - 1 );
3961 if ( r3 < 0 ) r3 = -r3;
3962 if ( r1 < 0 ) r1 = -r1;
3963 r1 *= 2;
3964 r31 = r3 - r1;
3965 if ( !r3 ) { /* Terms cancel */
3966cancelled:
3967 ul = S->used[level] = S->tree[i];
3968 S->tree[i] = -1;
3969/*
3970 We skip to the next term in stream ul
3971*/
3972 im = *poin2[ul];
3973 if ( im < 0 ) {
3974 r1 = poin2[ul][1] - im + 1;
3975 m1 = poin2[ul] + 2;
3976 m2 = poin[ul] - im + 1;
3977 while ( ++im <= 0 ) *--m1 = *--m2;
3978 *--m1 = r1;
3979 poin2[ul] = m1;
3980 im = r1;
3981 }
3982 poin[ul] = poin2[ul];
3983 ki = S->ktoi[ul];
3984 if ( !par && (poin[ul] + im + COMPINC) >= S->pStop[ki]
3985 && im > 0 ) {
3986#ifdef WITHZLIB
3987 PutIn(fin,&(S->iPatches[ki]),S->Patches[ki],&(poin[ul]),ki);
3988#else
3989 ADDPOS(S->iPatches[ki],PutIn(fin,&(S->iPatches[ki]),
3990 S->Patches[ki],&(poin[ul]),ki));
3991#endif
3992 poin2[ul] = poin[ul] + im;
3993 }
3994 else {
3995 poin2[ul] += im;
3996 }
3997 S->used[++level] = k;
3998 S->TermsLeft--;
3999 }
4000 else if ( !r31 ) { /* copy coef into term1 */
4001 goto CopCof2;
4002 }
4003 else if ( r31 < 0 ) { /* copy coef into term1
4004 and adjust the length of term1 */
4005 goto CopCoef;
4006 }
4007 else {
4008/*
4009 this is the dreaded calamity.
4010 is there enough space?
4011*/
4012 if( (poin[S->tree[i]]+l1+r31) >= poin2[S->tree[i]] ) {
4013/*
4014 no space! now the special trick for which
4015 we left 2*maxlng spaces open at the beginning
4016 of each patch.
4017*/
4018 if ( (l1 + r31) > AM.MaxTer/((LONG)sizeof(WORD)) ) {
4019 MLOCK(ErrorMessageLock);
4020 MesPrint("Coefficient overflow during sort");
4021 MUNLOCK(ErrorMessageLock);
4022 goto ReturnError;
4023 }
4024 m2 = poin[S->tree[i]];
4025 m3 = ( poin[S->tree[i]] -= r31 );
4026 do { *m3++ = *m2++; } while ( m2 < m1 );
4027 m1 = m3;
4028 }
4029CopCoef:
4030 *(poin[S->tree[i]]) += r31;
4031CopCof2:
4032 m2 = (WORD *)coef; im = r3;
4033 NCOPY(m1,m2,im);
4034 *m1 = r33;
4035 }
4036 }
4037/*
4038 Now skip to the next term in stream k.
4039*/
4040NextTerm:
4041 im = poin2[k][0];
4042 if ( im < 0 ) {
4043 r1 = poin2[k][1] - im + 1;
4044 m1 = poin2[k] + 2;
4045 m2 = poin[k] - im + 1;
4046 while ( ++im <= 0 ) *--m1 = *--m2;
4047 *--m1 = r1;
4048 poin2[k] = m1;
4049 im = r1;
4050 }
4051 poin[k] = poin2[k];
4052 ki = S->ktoi[k];
4053 if ( !par && ( (poin[k] + im + COMPINC) >= S->pStop[ki] )
4054 && im > 0 ) {
4055#ifdef WITHZLIB
4056 PutIn(fin,&(S->iPatches[ki]),S->Patches[ki],&(poin[k]),ki);
4057#else
4058 ADDPOS(S->iPatches[ki],PutIn(fin,&(S->iPatches[ki]),
4059 S->Patches[ki],&(poin[k]),ki));
4060#endif
4061 poin2[k] = poin[k] + im;
4062 }
4063 else {
4064 poin2[k] += im;
4065 }
4066 goto OneTerm;
4067 }
4068 }
4069 else if ( S->tree[i] < 0 ) {
4070 S->tree[i] = k;
4071 level--;
4072 goto OneTerm;
4073 }
4074 }
4075/*
4076 found the smallest in the set. indicated by k.
4077 write to its destination.
4078*/
4079#ifdef WITHPTHREADS
4080 if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
4081 im = PutToMaster(BHEAD poin[k]);
4082 }
4083 else
4084#endif
4085 if ( ( im = PutOut(BHEAD poin[k],&position,fout,1) ) < 0 ) {
4086 MLOCK(ErrorMessageLock);
4087 MesPrint("Called from MergePatches with k = %d (stream %d)",k,S->ktoi[k]);
4088 MUNLOCK(ErrorMessageLock);
4089 goto ReturnError;
4090 }
4091 ADDPOS(S->SizeInFile[par],im);
4092 goto NextTerm;
4093 }
4094 else {
4095 goto NormalReturn;
4096 }
4097EndOfMerge:
4098#ifdef WITHPTHREADS
4099 if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
4100 PutToMaster(BHEAD 0);
4101 }
4102 else
4103#endif
4104 if ( FlushOut(&position,fout,1) ) goto ReturnError;
4105 ADDPOS(S->SizeInFile[par],1);
4106EndOfAll:
4107 if ( par == 1 ) { /* Set the fpatch pointers */
4108#ifdef WITHZLIB
4109 SeekFile(fout->handle,&position,SEEK_CUR);
4110#endif
4111 (S->fPatchN)++;
4112 S->fPatches[S->fPatchN] = position;
4113 }
4114 if ( par == 0 && fout != AR.outfile ) {
4115/*
4116 Output went to sortfile. We have two possibilities:
4117 1: We are not finished with the current in-out cycle
4118 In that case we should pop to the next set of patches
4119 2: We finished a cycle and should clean up the in file
4120 Then we restart the sort.
4121*/
4122 (S->fPatchN)++;
4123 S->fPatches[S->fPatchN] = position;
4124 if ( ISNOTZEROPOS(AN.OldPosIn) ) { /* We are not done */
4125
4126 SeekFile(fin->handle,&(AN.OldPosIn),SEEK_SET);
4127/*
4128 We don't need extra provisions for the zlib compression here.
4129 If part of an expression has been sorted, the whole has been so.
4130 This means that S->fpincompressed[] will remain the same
4131*/
4132 if ( (ULONG)ReadFile(fin->handle,(UBYTE *)(&(S->inNum)),(LONG)sizeof(WORD)) !=
4133 sizeof(WORD)
4134 || (ULONG)ReadFile(fin->handle,(UBYTE *)(&AN.OldPosIn),(LONG)sizeof(POSITION)) !=
4135 sizeof(POSITION)
4136 || (ULONG)ReadFile(fin->handle,(UBYTE *)S->iPatches,(LONG)((S->inNum)+1)
4137 *sizeof(POSITION)) != ((S->inNum)+1)*sizeof(POSITION) ) {
4138 MLOCK(ErrorMessageLock);
4139 MesPrint("Read error fourth stage sorting");
4140 MUNLOCK(ErrorMessageLock);
4141 goto ReturnError;
4142 }
4143 *rr = 0;
4144#ifdef WITHZLIB
4145 for ( i = 0; i < S->inNum; i++ ) {
4146 S->fPatchesStop[i] = S->iPatches[i+1];
4147#ifdef GZIPDEBUG
4148 MLOCK(ErrorMessageLock);
4149 MesPrint("%w fPatchesStop[%d] = %10p",i,&(S->fPatchesStop[i]));
4150 MUNLOCK(ErrorMessageLock);
4151#endif
4152 }
4153#endif
4154 goto ConMer;
4155 }
4156 else {
4157/*
4158 if ( fin == &(AR.FoStage4[0]) ) {
4159 s = (UBYTE *)(fin->name); while ( *s ) s++;
4160 if ( AR.Stage4Name == 1 ) s[-1] -= 1;
4161 else s[-1] += 1;
4162 }
4163*/
4164/* TruncateFile(fin->handle); */
4165 UpdateMaxSize();
4166#ifdef WITHZLIB
4167 ClearSortGZIP(fin);
4168#endif
4169 CloseFile(fin->handle);
4170 remove(fin->name); /* Gives diskspace free again. */
4171#ifdef GZIPDEBUG
4172 MLOCK(ErrorMessageLock);
4173 MesPrint("%w MergePatches removed in file %s",fin->name);
4174 MUNLOCK(ErrorMessageLock);
4175#endif
4176/*
4177 if ( fin == &(AR.FoStage4[0]) ) {
4178 s = (UBYTE *)(fin->name); while ( *s ) s++;
4179 if ( AR.Stage4Name == 1 ) s[-1] += 1;
4180 else s[-1] -= 1;
4181 }
4182*/
4183 fin->handle = -1;
4184 { FILEHANDLE *ff = fin; fin = fout; fout = ff; }
4185 PUTZERO(S->SizeInFile[0]);
4186 goto NewMerge;
4187 }
4188 }
4189 if ( par == 0 ) {
4190/* TruncateFile(fin->handle); */
4191 UpdateMaxSize();
4192#ifdef WITHZLIB
4193 ClearSortGZIP(fin);
4194#endif
4195 CloseFile(fin->handle);
4196 remove(fin->name);
4197 fin->handle = -1;
4198#ifdef GZIPDEBUG
4199 MLOCK(ErrorMessageLock);
4200 MesPrint("%w MergePatches removed in file %s",fin->name);
4201 MUNLOCK(ErrorMessageLock);
4202#endif
4203 }
4204NormalReturn:
4205#ifdef WITHZLIB
4206 AR.gzipCompress = oldgzipCompress;
4207#endif
4208 return(0);
4209ReturnError:
4210#ifdef WITHZLIB
4211 AR.gzipCompress = oldgzipCompress;
4212#endif
4213 return(-1);
4214#ifndef WITHZLIB
4215PatwCall:
4216 MLOCK(ErrorMessageLock);
4217 MesPrint("Error while writing to file.");
4218 goto PatCall2;
4219#endif
4220PatCall:;
4221 MLOCK(ErrorMessageLock);
4222PatCall2:;
4223 MesCall("MergePatches");
4224 MUNLOCK(ErrorMessageLock);
4225#ifdef WITHZLIB
4226 AR.gzipCompress = oldgzipCompress;
4227#endif
4228 SETERROR(-1)
4229}
4230
4231/*
4232 #] MergePatches :
4233 #[ StoreTerm : WORD StoreTerm(term)
4234*/
4244int StoreTerm(PHEAD WORD *term)
4245{
4246 GETBIDENTITY
4247 SORTING *S = AT.SS;
4248 WORD **ss, *lfill, j, *t;
4249 POSITION pp;
4250 LONG lSpace, sSpace, RetCode, over, tover;
4251
4252 // Update SortVerbose counters
4253 S->verbUnsortedSize += *term * sizeof(*term);
4254
4255 if ( ( ( AP.PreDebug & DUMPTOSORT ) == DUMPTOSORT ) && AR.sLevel == 0 ) {
4256#ifdef WITHPTHREADS
4257 snprintf((char *)(THRbuf),100,"StoreTerm(%d)",AT.identity);
4258 PrintTerm(term,(char *)(THRbuf));
4259#else
4260 PrintTerm(term,"StoreTerm");
4261#endif
4262 }
4263 if ( AM.exitflag && AR.sLevel == 0 ) return(0);
4264 S->sFill = *(S->PoinFill);
4265 if ( S->sTerms >= S->TermsInSmall || ( S->sFill + *term ) >= S->sTop ) {
4266/*
4267 The small buffer is full. It has to be sorted and written.
4268*/
4269 // Update SortVerbose counters
4270 if ( S->sTerms >= S->TermsInSmall ) S->verbSBsortTerms++;
4271 else S->verbSBsortCap++;
4272
4273 tover = over = S->sTerms;
4274 ss = S->sPointer;
4275 ss[over] = 0;
4276#ifdef SPLITTIME
4277 PrintTime((UBYTE *)"Before SplitMerge");
4278#endif
4279 ss[SplitMerge(BHEAD ss,over)] = 0;
4280#ifdef SPLITTIME
4281 PrintTime((UBYTE *)"After SplitMerge");
4282#endif
4283 sSpace = 0;
4284 if ( over > 0 ) {
4285 sSpace = ComPress(ss,&RetCode);
4286 S->TermsLeft -= over - RetCode;
4287 }
4288 sSpace++;
4289
4290 lSpace = sSpace + (S->lFill - S->lBuffer)
4291 - (AM.MaxTer/sizeof(WORD))*((LONG)S->lPatch);
4292 SETBASEPOSITION(pp,lSpace);
4293 MULPOS(pp,sizeof(WORD));
4294 if ( S->file.handle >= 0 ) {
4295 ADD2POS(pp,S->fPatches[S->fPatchN]);
4296 }
4297 if ( S == AT.S0 ) { /* Only statistics at ground level */
4298 WriteStats(&pp,STATSSPLITMERGE,CHECKLOGTYPE);
4299 }
4300 if ( ( S->lPatch >= S->MaxPatches ) ||
4301 ( ( (WORD *)(((UBYTE *)(S->lFill + sSpace)) + 2*AM.MaxTer ) ) >= S->lTop ) ) {
4302/*
4303 The large buffer is too full. Merge and write it
4304*/
4305 // Update SortVerbose counters
4306 if ( S->lPatch >= S->MaxPatches ) S->verbLBsortPatches++;
4307 else S->verbLBsortCap++;
4308
4309 if ( MergePatches(1) ) goto StoreCall;
4310/*
4311 pp = S->SizeInFile[1];
4312 ADDPOS(pp,sSpace);
4313 MULPOS(pp,sizeof(WORD));
4314*/
4315 SETBASEPOSITION(pp,sSpace);
4316 MULPOS(pp,sizeof(WORD));
4317 ADD2POS(pp,S->fPatches[S->fPatchN]);
4318
4319 if ( S == AT.S0 ) { /* Only statistics at ground level */
4320 WriteStats(&pp,STATSMERGETOFILE,CHECKLOGTYPE);
4321 }
4322 S->lPatch = 0;
4323 S->lFill = S->lBuffer;
4324 }
4325 S->Patches[S->lPatch++] = S->lFill;
4326 lfill = (WORD *)(((UBYTE *)(S->lFill)) + AM.MaxTer);
4327 if ( tover > 0 ) {
4328 ss = S->sPointer;
4329 while ( ( t = *ss++ ) != 0 ) {
4330 j = *t;
4331 if ( j < 0 ) j = t[1] + 2;
4332 while ( --j >= 0 ){
4333 *lfill++ = *t++;
4334 }
4335 }
4336 }
4337 *lfill++ = 0;
4338 S->lFill = lfill;
4339 S->sTerms = 0;
4340 S->PoinFill = S->sPointer;
4341 *(S->PoinFill) = S->sFill = S->sBuffer;
4342 }
4343 j = *term;
4344 while ( --j >= 0 ) *S->sFill++ = *term++;
4345 S->sTerms++;
4346 S->GenTerms++;
4347 S->TermsLeft++;
4348 *++S->PoinFill = S->sFill;
4349
4350 return(0);
4351
4352StoreCall:
4353 MLOCK(ErrorMessageLock);
4354 MesCall("StoreTerm");
4355 MUNLOCK(ErrorMessageLock);
4356 SETERROR(-1)
4357}
4358
4359/*
4360 #] StoreTerm :
4361 #[ StageSort : void StageSort(FILEHANDLE *fout)
4362*/
4370{
4371 GETIDENTITY
4372 SORTING *S = AT.SS;
4373 if ( S->fPatchN >= S->MaxFpatches ) {
4374 POSITION position;
4375 if ( S != AT.S0 ) {
4376/*
4377 There are no proper provisions for stage 4 or higher sorts
4378 for function arguments and $ variables. The reason:
4379 The current code maps out the patches, based on the size of
4380 the buffers in the FoStage4 structs, while they are used
4381 inside the S->file struct that may have far smaller buffers.
4382 By itself that might still be repairable, but it goes completely
4383 wrong when during the sort polyRatFuns have to be added and they
4384 would go into stage4 (very rare but possible).
4385 The only really correct solution would be to put FoStage4 structs
4386 in all sort levels. Messy. (JV 8-oct-2018).
4387*/
4388 MLOCK(ErrorMessageLock);
4389 MesPrint("Currently Stage 4 sorts are not allowed for function arguments or $ variables.");
4390 MesPrint("Please increase correspondingsorting parameters (sub-) in the setup.");
4391 MUNLOCK(ErrorMessageLock);
4392 Terminate(-1);
4393 }
4394 PUTZERO(position);
4395 MLOCK(ErrorMessageLock);
4396#ifdef WITHPTHREADS
4397 MesPrint("StageSort in thread %d",identity);
4398#elif defined(WITHMPI)
4399 MesPrint("StageSort in process %d",PF.me);
4400#else
4401 MesPrint("StageSort");
4402#endif
4403 MUNLOCK(ErrorMessageLock);
4404 SeekFile(fout->handle,&position,SEEK_END);
4405/*
4406 No extra compression data has to be written.
4407 S->fpincompressed should remain valid.
4408*/
4409 if ( (ULONG)WriteFile(fout->handle,(UBYTE *)(&(S->fPatchN)),(LONG)sizeof(WORD)) !=
4410 sizeof(WORD)
4411 || (ULONG)WriteFile(fout->handle,(UBYTE *)(&(AN.OldPosOut)),(LONG)sizeof(POSITION)) !=
4412 sizeof(POSITION)
4413 || (ULONG)WriteFile(fout->handle,(UBYTE *)(S->fPatches),(LONG)(S->fPatchN+1)
4414 *sizeof(POSITION)) != (S->fPatchN+1)*sizeof(POSITION) ) {
4415 MLOCK(ErrorMessageLock);
4416 MesPrint("Write error while staging sort. Disk full?");
4417 MUNLOCK(ErrorMessageLock);
4418 Terminate(-1);
4419 }
4420 AN.OldPosOut = position;
4421 fout->filesize = position;
4422 ADDPOS(fout->filesize,(S->fPatchN+2)*sizeof(POSITION) + sizeof(WORD));
4423 fout->POposition = fout->filesize;
4424 S->fPatches[0] = fout->filesize;
4425 S->fPatchN = 0;
4426
4427 if ( AR.FoStage4[0].PObuffer == 0 ) {
4428 AR.FoStage4[0].PObuffer = (WORD *)Malloc1(AR.FoStage4[0].POsize*sizeof(WORD)
4429 ,"Stage 4 buffer");
4430 AR.FoStage4[0].POfill = AR.FoStage4[0].PObuffer;
4431 AR.FoStage4[0].POstop = AR.FoStage4[0].PObuffer
4432 + AR.FoStage4[0].POsize/sizeof(WORD);
4433#ifdef WITHPTHREADS
4434 AR.FoStage4[0].pthreadslock = dummylock;
4435#endif
4436 }
4437 if ( AR.FoStage4[1].PObuffer == 0 ) {
4438 AR.FoStage4[1].PObuffer = (WORD *)Malloc1(AR.FoStage4[1].POsize*sizeof(WORD)
4439 ,"Stage 4 buffer");
4440 AR.FoStage4[1].POfill = AR.FoStage4[1].PObuffer;
4441 AR.FoStage4[1].POstop = AR.FoStage4[1].PObuffer
4442 + AR.FoStage4[1].POsize/sizeof(WORD);
4443#ifdef WITHPTHREADS
4444 AR.FoStage4[1].pthreadslock = dummylock;
4445#endif
4446 }
4447 S->stage4 = 1;
4448 }
4449}
4450
4451/*
4452 #] StageSort :
4453 #[ SortWild : WORD SortWild(w,nw)
4454*/
4468int SortWild(WORD *w, WORD nw)
4469{
4470 GETIDENTITY
4471 WORD *v, *s, *m, k, i;
4472 WORD *pScrat, *stop, *sv;
4473 int error = 0;
4474 pScrat = AT.WorkPointer;
4475 if ( ( AT.WorkPointer + 8 * AM.MaxWildcards ) >= AT.WorkTop ) {
4476 MLOCK(ErrorMessageLock);
4477 MesWork();
4478 MUNLOCK(ErrorMessageLock);
4479 return(-1);
4480 }
4481 stop = w + nw;
4482 i = 0;
4483 while ( i < nw ) {
4484 m = w + i;
4485 v = m + m[1];
4486 while ( v < stop && (
4487 *v == FROMSET || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
4488 while ( v < stop ) {
4489 if ( *v >= 0 ) {
4490 if ( AM.Ordering[*v] < AM.Ordering[*m] ) {
4491 m = v;
4492 }
4493 else if ( *v == *m ) {
4494 if ( v[2] < m[2] ) {
4495 m = v;
4496 }
4497 else if ( v[2] == m[2] ) {
4498 s = m + m[1];
4499 sv = v + v[1];
4500 if ( s < stop && ( *s == FROMSET
4501 || *s == SETTONUM || *s == LOADDOLLAR ) ) {
4502 if ( sv < stop && ( *sv == FROMSET
4503 || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
4504 if ( s[2] != sv[2] ) {
4505 error = -1;
4506 MLOCK(ErrorMessageLock);
4507 MesPrint("&Wildcard set conflict");
4508 MUNLOCK(ErrorMessageLock);
4509 }
4510 }
4511 *v = -1;
4512 }
4513 else {
4514 if ( sv < stop && ( *sv == FROMSET
4515 || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
4516 *m = -1;
4517 m = v;
4518 }
4519 else {
4520 *v = -1;
4521 }
4522 }
4523 }
4524 }
4525 }
4526 v += v[1];
4527 while ( v < stop && ( *v == FROMSET
4528 || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
4529 }
4530 s = pScrat;
4531 v = m;
4532 k = m[1];
4533 NCOPY(s,m,k);
4534 while ( m < stop && ( *m == FROMSET
4535 || *m == SETTONUM || *m == LOADDOLLAR ) ) {
4536 k = m[1];
4537 NCOPY(s,m,k);
4538 }
4539 *v = -1;
4540 pScrat = s;
4541 i = 0;
4542 while ( i < nw && ( w[i] < 0 || w[i] == FROMSET
4543 || w[i] == SETTONUM || w[i] == LOADDOLLAR ) ) i += w[i+1];
4544 }
4545 AC.NwildC = k = WORDDIF(pScrat,AT.WorkPointer);
4546 s = AT.WorkPointer;
4547 m = w;
4548 NCOPY(m,s,k);
4549 AC.WildC = m;
4550 return(error);
4551}
4552
4553/*
4554 #] SortWild :
4555 #[ CleanUpSort : void CleanUpSort(num)
4556*/
4561void CleanUpSort(int num)
4562{
4563 GETIDENTITY
4564 SORTING *S;
4565 int minnum = num, i;
4566 if ( AN.FunSorts ) {
4567 if ( num == -1 ) {
4568 if ( AN.MaxFunSorts > 3 ) {
4569 minnum = (AN.MaxFunSorts+4)/2;
4570 }
4571 else minnum = 4;
4572 }
4573 else if ( minnum == 0 ) minnum = 1;
4574 for ( i = minnum; i < AN.NumFunSorts; i++ ) {
4575 S = AN.FunSorts[i];
4576 if ( S ) {
4577 if ( S->file.handle >= 0 ) {
4578/* TruncateFile(S->file.handle); */
4579 UpdateMaxSize();
4580#ifdef WITHZLIB
4581 ClearSortGZIP(&(S->file));
4582#endif
4583 CloseFile(S->file.handle);
4584 S->file.handle = -1;
4585 remove(S->file.name);
4586#ifdef GZIPDEBUG
4587 MLOCK(ErrorMessageLock);
4588 MesPrint("%w CleanUpSort removed file %s",S->file.name);
4589 MUNLOCK(ErrorMessageLock);
4590#endif
4591 }
4592 M_free(S->sPointer, "CleanUpSort: sPointer");
4593 M_free(S->Patches, "CleanUpSort: Patches");
4594 M_free(S->pStop, "CleanUpSort: pStop");
4595 M_free(S->poina, "CleanUpSort: poina");
4596 M_free(S->poin2a, "CleanUpSort: poin2a");
4597 M_free(S->fPatches, "CleanUpSort: fPatches");
4598 M_free(S->fPatchesStop, "CleanUpSort: fPatchesStop");
4599 M_free(S->inPatches, "CleanUpSort: inPatches");
4600 M_free(S->tree, "CleanUpSort: tree");
4601 M_free(S->used, "CleanUpSort: used");
4602#ifdef WITHZLIB
4603 M_free(S->fpcompressed, "CleanUpSort: fpcompressed");
4604 M_free(S->fpincompressed, "CleanUpSort: fpincompressed");
4605#endif
4606 M_free(S->ktoi, "CleanUpSort: ktoi");
4607 M_free(S->lBuffer, "CleanUpSort: lBuffer+sBuffer");
4608 M_free(S->file.PObuffer, "CleanUpSort: PObuffer");
4609 M_free(S, "CleanUpSort: sorting struct");
4610 }
4611 AN.FunSorts[i] = 0;
4612 }
4613 AN.MaxFunSorts = minnum;
4614 if ( num == 0 ) {
4615 S = AN.FunSorts[0];
4616 if ( S ) {
4617 if ( S->file.handle >= 0 ) {
4618/* TruncateFile(S->file.handle); */
4619 UpdateMaxSize();
4620#ifdef WITHZLIB
4621 ClearSortGZIP(&(S->file));
4622#endif
4623 CloseFile(S->file.handle);
4624 S->file.handle = -1;
4625 remove(S->file.name);
4626#ifdef GZIPDEBUG
4627 MLOCK(ErrorMessageLock);
4628 MesPrint("%w CleanUpSort removed file %s",S->file.name);
4629 MUNLOCK(ErrorMessageLock);
4630#endif
4631 }
4632 }
4633 }
4634 }
4635 for ( i = 0; i < 2; i++ ) {
4636 if ( AR.FoStage4[i].handle >= 0 ) {
4637 UpdateMaxSize();
4638#ifdef WITHZLIB
4639 ClearSortGZIP(&(AR.FoStage4[i]));
4640#endif
4641 CloseFile(AR.FoStage4[i].handle);
4642 remove(AR.FoStage4[i].name);
4643 AR.FoStage4[i].handle = -1;
4644#ifdef GZIPDEBUG
4645 MLOCK(ErrorMessageLock);
4646 MesPrint("%w CleanUpSort removed stage4 file %s",AR.FoStage4[i].name);
4647 MUNLOCK(ErrorMessageLock);
4648#endif
4649 }
4650 }
4651}
4652
4653/*
4654 #] CleanUpSort :
4655 #[ LowerSortLevel : void LowerSortLevel()
4656*/
4662{
4663 GETIDENTITY
4664 if ( AR.sLevel >= 0 ) {
4665 AR.sLevel--;
4666 if ( AR.sLevel >= 0 ) AT.SS = AN.FunSorts[AR.sLevel];
4667 }
4668}
4669
4670/*
4671 #] LowerSortLevel :
4672 #[ PolyRatFunSpecial :
4673
4674 Keeps only the most divergent term in AR.PolyFunVar
4675 We assume that the terms are already in that notation.
4676*/
4677
4678WORD *PolyRatFunSpecial(PHEAD WORD *t1, WORD *t2)
4679{
4680 WORD *oldworkpointer = AT.WorkPointer, *t, *r;
4681 WORD exp1, exp2;
4682 int i;
4683 t = t1+FUNHEAD;
4684 if ( *t == -SYMBOL ) {
4685 if ( t[1] != AR.PolyFunVar ) goto Illegal;
4686 exp1 = 1;
4687 if ( t[2] != -SNUMBER ) goto Illegal;
4688 t[3] = 1;
4689 }
4690 else if ( *t == -SNUMBER ) {
4691 t[1] = 1;
4692 t += 2;
4693 if ( *t == -SYMBOL ) {
4694 if ( t[1] != AR.PolyFunVar ) goto Illegal;
4695 exp1 = -1;
4696 }
4697 else if ( *t == -SNUMBER ) {
4698 t[1] = 1;
4699 exp1 = 0;
4700 }
4701 else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
4702 && t[ARGHEAD+3] == AR.PolyFunVar ) {
4703 t[ARGHEAD+5] = 1;
4704 t[ARGHEAD+6] = 1;
4705 t[ARGHEAD+7] = 3;
4706 exp1 = -t[ARGHEAD+4];
4707 }
4708 else goto Illegal;
4709 }
4710 else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
4711 && t[ARGHEAD+3] == AR.PolyFunVar ) {
4712 t[ARGHEAD+5] = 1;
4713 t[ARGHEAD+6] = 1;
4714 t[ARGHEAD+7] = 3;
4715 exp1 = t[ARGHEAD+4];
4716 t += *t;
4717 if ( *t != -SNUMBER ) goto Illegal;
4718 t[1] = 1;
4719 }
4720 else goto Illegal;
4721
4722 t = t2+FUNHEAD;
4723 if ( *t == -SYMBOL ) {
4724 if ( t[1] != AR.PolyFunVar ) goto Illegal;
4725 exp2 = 1;
4726 if ( t[2] != -SNUMBER ) goto Illegal;
4727 t[3] = 1;
4728 }
4729 else if ( *t == -SNUMBER ) {
4730 t[1] = 1;
4731 t += 2;
4732 if ( *t == -SYMBOL ) {
4733 if ( t[1] != AR.PolyFunVar ) goto Illegal;
4734 exp2 = -1;
4735 }
4736 else if ( *t == -SNUMBER ) {
4737 t[1] = 1;
4738 exp2 = 0;
4739 }
4740 else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
4741 && t[ARGHEAD+3] == AR.PolyFunVar ) {
4742 t[ARGHEAD+5] = 1;
4743 t[ARGHEAD+6] = 1;
4744 t[ARGHEAD+7] = 3;
4745 exp2 = -t[ARGHEAD+4];
4746 }
4747 else goto Illegal;
4748 }
4749 else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
4750 && t[ARGHEAD+3] == AR.PolyFunVar ) {
4751 t[ARGHEAD+5] = 1;
4752 t[ARGHEAD+6] = 1;
4753 t[ARGHEAD+7] = 3;
4754 exp2 = t[ARGHEAD+4];
4755 t += *t;
4756 if ( *t != -SNUMBER ) goto Illegal;
4757 t[1] = 1;
4758 }
4759 else goto Illegal;
4760
4761 if ( exp1 <= exp2 ) { i = t1[1]; r = t1; }
4762 else { i = t2[1]; r = t2; }
4763 t = oldworkpointer;
4764 NCOPY(t,r,i)
4765
4766 return(oldworkpointer);
4767Illegal:
4768 MesPrint("Illegal occurrence of PolyRatFun with divergent option");
4769 Terminate(-1);
4770 return(0);
4771}
4772
4773/*
4774 #] PolyRatFunSpecial :
4775 #[ SimpleSplitMerge :
4776
4777 Sorts an array of WORDs. No adding of equal objects.
4778*/
4779
4780void SimpleSplitMergeRec(WORD *array,WORD num,WORD *auxarray)
4781{
4782 WORD n1,n2,i,j,k,*t1,*t2;
4783 if ( num < 2 ) return;
4784 if ( num == 2 ) {
4785 if ( array[0] > array[1] ) {
4786 EXCH(array[0],array[1])
4787 }
4788 return;
4789 }
4790 n1 = num/2;
4791 n2 = num - n1;
4792 SimpleSplitMergeRec(array,n1,auxarray);
4793 SimpleSplitMergeRec(array+n1,n2,auxarray);
4794 if ( array[n1-1] <= array[n1] ) return;
4795
4796 t1 = array; t2 = auxarray; i = n1; NCOPY(t2,t1,i);
4797 i = 0; j = n1; k = 0;
4798 while ( i < n1 && j < num ) {
4799 if ( auxarray[i] <= array[j] ) { array[k++] = auxarray[i++]; }
4800 else { array[k++] = array[j++]; }
4801 }
4802 while ( i < n1 ) array[k++] = auxarray[i++];
4803/*
4804 Remember: remnants of j are still in place!
4805*/
4806}
4807
4808void SimpleSplitMerge(WORD *array,WORD num)
4809{
4810 WORD *auxarray = Malloc1(sizeof(WORD)*num/2,"SimpleSplitMerge");
4811 SimpleSplitMergeRec(array,num,auxarray);
4812 M_free(auxarray,"SimpleSplitMerge");
4813}
4814
4815/*
4816 #] SimpleSplitMerge :
4817 #[ BinarySearch :
4818
4819 Searches in the sorted array with length num for the object x.
4820 If x is in the list, it returns the number of the array element
4821 that matched. If it is not in the list, it returns -1.
4822 If there are identical objects in the list, which one will
4823 match is quasi random.
4824*/
4825
4826WORD BinarySearch(WORD *array,WORD num,WORD x)
4827{
4828 WORD i, bot, top, med;
4829 if ( num < 8 ) {
4830 for ( i = 0; i < num; i++ ) if ( array[i] == x ) return(i);
4831 return(-1);
4832 }
4833 if ( array[0] > x || array[num-1] < x ) return(-1);
4834 bot = 0; top = num-1; med = (top+bot)/2;
4835 do {
4836 if ( array[med] == x ) return(med);
4837 if ( array[med] < x ) { bot = med+1; }
4838 else { top = med-1; }
4839 med = (top+bot)/2;
4840 } while ( med >= bot && med <= top );
4841 return(-1);
4842}
4843
4844/*
4845 #] BinarySearch :
4846 #] SortUtilities :
4847*/
WORD * poly_ratfun_add(PHEAD WORD *, WORD *)
Definition polywrap.cc:633
WORD CompCoef(WORD *, WORD *)
Definition reken.c:3048
LONG TimeWallClock(WORD)
Definition tools.c:3413
int NormalModulus(UWORD *, WORD *)
Definition reken.c:1404
LONG TimeCPU(WORD)
Definition tools.c:3487
int PF_ISendSbuf(int to, int tag)
Definition mpi.c:266
int PF_EndSort(void)
Definition parallel.c:874
int FlushOut(POSITION *position, FILEHANDLE *fi, int compr)
Definition sort.c:1533
LONG PutIn(FILEHANDLE *file, POSITION *position, WORD *buffer, WORD **take, int npat)
Definition sort.c:1025
LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
Definition sort.c:3066
WORD Compare1(PHEAD WORD *term1, WORD *term2, WORD level)
Definition sort.c:2341
LONG EndSort(PHEAD WORD *buffer, int par)
Definition sort.c:454
void GarbHand(void)
Definition sort.c:3346
WORD CompareHSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
Definition sort.c:2847
void LowerSortLevel(void)
Definition sort.c:4661
LONG ComPress(WORD **ss, LONG *n)
Definition sort.c:2900
int AddCoef(PHEAD WORD **ps1, WORD **ps2)
Definition sort.c:1747
WORD PutOut(PHEAD WORD *term, POSITION *position, FILEHANDLE *fi, WORD ncomp)
Definition sort.c:1171
int StoreTerm(PHEAD WORD *term)
Definition sort.c:4244
int NewSort(PHEAD0)
Definition sort.c:359
int SortWild(WORD *w, WORD nw)
Definition sort.c:4468
void WriteStats(POSITION *plspace, WORD par, WORD checkLogType)
Definition sort.c:129
WORD CompareSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
Definition sort.c:2804
void AddArgs(PHEAD WORD *s1, WORD *s2, WORD *m)
Definition sort.c:2048
void CleanUpSort(int num)
Definition sort.c:4561
void StageSort(FILEHANDLE *fout)
Definition sort.c:4369
int MergePatches(WORD par)
Definition sort.c:3461
int AddPoly(PHEAD WORD **ps1, WORD **ps2)
Definition sort.c:1876
int Sflush(FILEHANDLE *fi)
Definition sort.c:1085
BRACKETINDEX * indexbuffer
Definition structs.h:323
int handle
Definition structs.h:709