FORM  4.1
sort.c
Go to the documentation of this file.
1 
17 /* #[ License : */
18 /*
19  * Copyright (C) 1984-2013 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 
55 #include "form3.h"
56 
57 #ifdef WITHPTHREADS
58 UBYTE THRbuf[100];
59 #endif
60 
61 #ifdef WITHSTATS
62 extern LONG numwrites;
63 extern LONG numreads;
64 extern LONG numseeks;
65 extern LONG nummallocs;
66 extern LONG numfrees;
67 #endif
68 
69 /*
70  #] Includes :
71  #[ SortUtilities :
72  #[ WriteStats : VOID WriteStats(lspace,par)
73 */
74 
75 char *toterms[] = { " ", " >>", "-->" };
76 
91 VOID WriteStats(POSITION *plspace, WORD par)
92 {
93  GETIDENTITY
94  LONG millitime, y = 0x7FFFFFFFL >> 1;
95  WORD timepart;
96  SORTING *S;
97  POSITION pp;
98  if ( AT.SS == AT.S0 && AC.StatsFlag ) {
99 #ifdef WITHPTHREADS
100  if ( AC.ThreadStats == 0 && identity > 0 ) return;
101 #elif defined(WITHMPI)
102  if ( AC.OldParallelStats ) return;
103  if ( ! AC.ProcessStats && PF.me != MASTER ) return;
104 #endif
105  if ( Expressions == 0 ) return;
106 
107  if ( par == 0 ) {
108  AR.ShortSortCount++;
109  if ( AR.ShortSortCount < AC.ShortStatsMax ) return;
110  }
111  AR.ShortSortCount = 0;
112 
113  S = AT.SS;
114  MLOCK(ErrorMessageLock);
115  if ( AC.ShortStats ) {}
116  else {
117 #ifdef WITHPTHREADS
118  if ( identity > 0 ) {
119  MesPrint(" Thread %d reporting",identity);
120  }
121  else {
122  MesPrint("");
123  }
124 #elif defined(WITHMPI)
125  if ( PF.me != MASTER ) {
126  MesPrint(" Process %d reporting",PF.me);
127  }
128  else {
129  MesPrint("");
130  }
131 #else
132  MesPrint("");
133 #endif
134  }
135  millitime = TimeCPU(1);
136  timepart = (WORD)(millitime%1000);
137  millitime /= 1000;
138  timepart /= 10;
139  if ( AC.ShortStats ) {
140 #if defined(WITHPTHREADS) || defined(WITHMPI)
141 #ifdef WITHPTHREADS
142  if ( identity > 0 ) {
143 #else
144  if ( PF.me != MASTER ) {
145  const int identity = PF.me;
146 #endif
147  if ( par == 0 || par == 2 ) {
148  SETBASEPOSITION(pp,y);
149  if ( ISLESSPOS(*plspace,pp) ) {
150  MesPrint("%d: %7l.%2is %8l>%10l%3s%10l:%10p %s %s",identity,
151  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
152  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
153 /*
154  MesPrint("%d: %14s %17s %7l.%2is %8l>%10l%3s%10l:%10p",identity,
155  EXPRNAME(AR.CurExpr),AC.Commercial,millitime,timepart,
156  AN.ninterms,S->GenTerms,toterms[par],S->TermsLeft,plspace);
157 */
158  }
159  else {
160  y = 1000000000L;
161  SETBASEPOSITION(pp,y);
162  MULPOS(pp,100);
163  if ( ISLESSPOS(*plspace,pp) ) {
164  MesPrint("%d: %7l.%2is %8l>%10l%3s%10l:%11p %s %s",identity,
165  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
166  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
167  }
168  else {
169  MULPOS(pp,10);
170  if ( ISLESSPOS(*plspace,pp) ) {
171  MesPrint("%d: %7l.%2is %8l>%10l%3s%10l:%12p %s %s",identity,
172  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
173  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
174  }
175  else {
176  MULPOS(pp,10);
177  if ( ISLESSPOS(*plspace,pp) ) {
178  MesPrint("%d: %7l.%2is %8l>%10l%3s%10l:%13p %s %s",identity,
179  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
180  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
181  }
182  else {
183  MULPOS(pp,10);
184  if ( ISLESSPOS(*plspace,pp) ) {
185  MesPrint("%d: %7l.%2is %8l>%10l%3s%10l:%14p %s %s",identity,
186  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
187  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
188  }
189  else {
190  MULPOS(pp,10);
191  if ( ISLESSPOS(*plspace,pp) ) {
192  MesPrint("%d: %7l.%2is %8l>%10l%3s%10l:%15p %s %s",identity,
193  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
194  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
195  }
196  else {
197  MULPOS(pp,10);
198  if ( ISLESSPOS(*plspace,pp) ) {
199  MesPrint("%d: %7l.%2is %8l>%10l%3s%10l:%16p %s %s",identity,
200  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
201  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
202  }
203  else {
204  MULPOS(pp,10);
205  if ( ISLESSPOS(*plspace,pp) ) {
206  MesPrint("%d: %7l.%2is %8l>%10l%3s%10l:%17p %s %s",identity,
207  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
208  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
209  }
210  } } } } }
211  }
212  }
213  }
214  else if ( par == 1 ) {
215  SETBASEPOSITION(pp,y);
216  if ( ISLESSPOS(*plspace,pp) ) {
217  MesPrint("%d: %7l.%2is %10l:%10p",identity,millitime,timepart,
218  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
219  }
220  else {
221  y = 1000000000L;
222  SETBASEPOSITION(pp,y);
223  MULPOS(pp,100);
224  if ( ISLESSPOS(*plspace,pp) ) {
225  MesPrint("%d: %7l.%2is %10l:%11p",identity,millitime,timepart,
226  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
227  }
228  else {
229  MULPOS(pp,10);
230  if ( ISLESSPOS(*plspace,pp) ) {
231  MesPrint("%d: %7l.%2is %10l:%12p",identity,millitime,timepart,
232  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
233  }
234  else {
235  MULPOS(pp,10);
236  if ( ISLESSPOS(*plspace,pp) ) {
237  MesPrint("%d: %7l.%2is %10l:%13p",identity,millitime,timepart,
238  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
239  }
240  else {
241  MULPOS(pp,10);
242  if ( ISLESSPOS(*plspace,pp) ) {
243  MesPrint("%d: %7l.%2is %10l:%14p",identity,millitime,timepart,
244  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
245  }
246  else {
247  MULPOS(pp,10);
248  if ( ISLESSPOS(*plspace,pp) ) {
249  MesPrint("%d: %7l.%2is %10l:%15p",identity,millitime,timepart,
250  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
251  }
252  else {
253  MULPOS(pp,10);
254  if ( ISLESSPOS(*plspace,pp) ) {
255  MesPrint("%d: %7l.%2is %10l:%16p",identity,millitime,timepart,
256  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
257  }
258  else {
259  MULPOS(pp,10);
260  if ( ISLESSPOS(*plspace,pp) ) {
261  MesPrint("%d: %7l.%2is %10l:%17p",identity,millitime,timepart,
262  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
263  }
264  } } } } }
265  }
266  }
267  } } else
268 #endif
269  {
270  if ( par == 0 || par == 2 ) {
271  SETBASEPOSITION(pp,y);
272  if ( ISLESSPOS(*plspace,pp) ) {
273  MesPrint("%7l.%2is %8l>%10l%3s%10l:%10p %s %s",
274  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
275  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
276 /*
277  MesPrint("%14s %17s %7l.%2is %8l>%10l%3s%10l:%10p",
278  EXPRNAME(AR.CurExpr),AC.Commercial,millitime,timepart,
279  AN.ninterms,S->GenTerms,toterms[par],S->TermsLeft,plspace);
280 */
281  }
282  else {
283  y = 1000000000L;
284  SETBASEPOSITION(pp,y);
285  MULPOS(pp,100);
286  if ( ISLESSPOS(*plspace,pp) ) {
287  MesPrint("%7l.%2is %8l>%10l%3s%10l:%11p %s %s",
288  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
289  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
290  }
291  else {
292  MULPOS(pp,10);
293  if ( ISLESSPOS(*plspace,pp) ) {
294  MesPrint("%7l.%2is %8l>%10l%3s%10l:%12p %s %s",
295  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
296  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
297  }
298  else {
299  MULPOS(pp,10);
300  if ( ISLESSPOS(*plspace,pp) ) {
301  MesPrint("%7l.%2is %8l>%10l%3s%10l:%13p %s %s",
302  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
303  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
304  }
305  else {
306  MULPOS(pp,10);
307  if ( ISLESSPOS(*plspace,pp) ) {
308  MesPrint("%7l.%2is %8l>%10l%3s%10l:%14p %s %s",
309  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
310  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
311  }
312  else {
313  MULPOS(pp,10);
314  if ( ISLESSPOS(*plspace,pp) ) {
315  MesPrint("%7l.%2is %8l>%10l%3s%10l:%15p %s %s",
316  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
317  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
318  }
319  else {
320  MULPOS(pp,10);
321  if ( ISLESSPOS(*plspace,pp) ) {
322  MesPrint("%7l.%2is %8l>%10l%3s%10l:%16p %s %s",
323  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
324  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
325  }
326  else {
327  MULPOS(pp,10);
328  if ( ISLESSPOS(*plspace,pp) ) {
329  MesPrint("%7l.%2is %8l>%10l%3s%10l:%17p %s %s",
330  millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
331  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
332  }
333  } } } } }
334  }
335  }
336  }
337  else if ( par == 1 ) {
338  SETBASEPOSITION(pp,y);
339  if ( ISLESSPOS(*plspace,pp) ) {
340  MesPrint("%7l.%2is %10l:%10p",millitime,timepart,
341  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
342  }
343  else {
344  y = 1000000000L;
345  SETBASEPOSITION(pp,y);
346  MULPOS(pp,100);
347  if ( ISLESSPOS(*plspace,pp) ) {
348  MesPrint("%7l.%2is %10l:%11p",millitime,timepart,
349  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
350  }
351  else {
352  MULPOS(pp,10);
353  if ( ISLESSPOS(*plspace,pp) ) {
354  MesPrint("%7l.%2is %10l:%12p",millitime,timepart,
355  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
356  }
357  else {
358  MULPOS(pp,10);
359  if ( ISLESSPOS(*plspace,pp) ) {
360  MesPrint("%7l.%2is %10l:%13p",millitime,timepart,
361  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
362  }
363  else {
364  MULPOS(pp,10);
365  if ( ISLESSPOS(*plspace,pp) ) {
366  MesPrint("%7l.%2is %10l:%14p",millitime,timepart,
367  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
368  }
369  else {
370  MULPOS(pp,10);
371  if ( ISLESSPOS(*plspace,pp) ) {
372  MesPrint("%7l.%2is %10l:%15p",millitime,timepart,
373  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
374  }
375  else {
376  MULPOS(pp,10);
377  if ( ISLESSPOS(*plspace,pp) ) {
378  MesPrint("%7l.%2is %10l:%16p",millitime,timepart,
379  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
380  }
381  else {
382  MULPOS(pp,10);
383  if ( ISLESSPOS(*plspace,pp) ) {
384  MesPrint("%7l.%2is %10l:%17p",millitime,timepart,
385  S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
386  }
387  } } } } }
388  }
389  }
390  }
391  } }
392  else {
393  if ( par == 1 ) {
394  MesPrint("Time = %7l.%2i sec",millitime,timepart);
395  }
396  else {
397 #if ( BITSINLONG > 32 )
398  if ( S->GenTerms >= 10000000000L ) {
399  MesPrint("Time = %7l.%2i sec Generated terms = %16l",
400  millitime,timepart,S->GenTerms);
401  }
402  else {
403  MesPrint("Time = %7l.%2i sec Generated terms = %10l",
404  millitime,timepart,S->GenTerms);
405  }
406 #else
407  MesPrint("Time = %7l.%2i sec Generated terms = %10l",
408  millitime,timepart,S->GenTerms);
409 #endif
410  }
411 #if ( BITSINLONG > 32 )
412  if ( par == 0 )
413  if ( S->TermsLeft >= 10000000000L ) {
414  MesPrint("%16s%8l Terms %s = %16l",EXPRNAME(AR.CurExpr),
415  AN.ninterms,FG.swmes[par],S->TermsLeft);
416  }
417  else {
418  MesPrint("%16s%8l Terms %s = %10l",EXPRNAME(AR.CurExpr),
419  AN.ninterms,FG.swmes[par],S->TermsLeft);
420  }
421  else {
422  if ( S->TermsLeft >= 10000000000L ) {
423 #ifdef WITHPTHREADS
424  if ( identity > 0 && par == 2 ) {
425  MesPrint("%16s Terms in thread = %16l",
426  EXPRNAME(AR.CurExpr),S->TermsLeft);
427  }
428  else
429 #elif defined(WITHMPI)
430  if ( PF.me != MASTER && par == 2 ) {
431  MesPrint("%16s Terms in process= %16l",
432  EXPRNAME(AR.CurExpr),S->TermsLeft);
433  }
434  else
435 #endif
436  {
437  MesPrint("%16s Terms %s = %16l",
438  EXPRNAME(AR.CurExpr),FG.swmes[par],S->TermsLeft);
439  }
440  }
441  else {
442 #ifdef WITHPTHREADS
443  if ( identity > 0 && par == 2 ) {
444  MesPrint("%16s Terms in thread = %10l",
445  EXPRNAME(AR.CurExpr),S->TermsLeft);
446  }
447  else
448 #elif defined(WITHMPI)
449  if ( PF.me != MASTER && par == 2 ) {
450  MesPrint("%16s Terms in process= %10l",
451  EXPRNAME(AR.CurExpr),S->TermsLeft);
452  }
453  else
454 #endif
455  {
456  MesPrint("%16s Terms %s = %10l",
457  EXPRNAME(AR.CurExpr),FG.swmes[par],S->TermsLeft);
458  }
459  }
460  }
461 #else
462  if ( par == 0 )
463  MesPrint("%16s%8l Terms %s = %10l",EXPRNAME(AR.CurExpr),
464  AN.ninterms,FG.swmes[par],S->TermsLeft);
465  else {
466 #ifdef WITHPTHREADS
467  if ( identity > 0 && par == 2 ) {
468  MesPrint("%16s Terms in thread = %10l",
469  EXPRNAME(AR.CurExpr),S->TermsLeft);
470  }
471  else
472 #elif defined(WITHMPI)
473  if ( PF.me != MASTER && par == 2 ) {
474  MesPrint("%16s Terms in process= %10l",
475  EXPRNAME(AR.CurExpr),S->TermsLeft);
476  }
477  else
478 #endif
479  {
480  MesPrint("%16s Terms %s = %10l",
481  EXPRNAME(AR.CurExpr),FG.swmes[par],S->TermsLeft);
482  }
483  }
484 #endif
485  SETBASEPOSITION(pp,y);
486  if ( ISLESSPOS(*plspace,pp) ) {
487  MesPrint("%24s Bytes used = %10p",AC.Commercial,plspace);
488  }
489  else {
490  y = 1000000000L;
491  SETBASEPOSITION(pp,y);
492  MULPOS(pp,100);
493  if ( ISLESSPOS(*plspace,pp) ) {
494  MesPrint("%24s Bytes used =%11p",AC.Commercial,plspace);
495  }
496  else {
497  MULPOS(pp,10);
498  if ( ISLESSPOS(*plspace,pp) ) {
499  MesPrint("%24s Bytes used =%12p",AC.Commercial,plspace);
500  }
501  else {
502  MULPOS(pp,10);
503  if ( ISLESSPOS(*plspace,pp) ) {
504  MesPrint("%24s Bytes used =%13p",AC.Commercial,plspace);
505  }
506  else {
507  MULPOS(pp,10);
508  if ( ISLESSPOS(*plspace,pp) ) {
509  MesPrint("%24s Bytes used =%14p",AC.Commercial,plspace);
510  }
511  else {
512  MULPOS(pp,10);
513  if ( ISLESSPOS(*plspace,pp) ) {
514  MesPrint("%24s Bytes used =%15p",AC.Commercial,plspace);
515  }
516  else {
517  MULPOS(pp,10);
518  if ( ISLESSPOS(*plspace,pp) ) {
519  MesPrint("%24s Bytes used =%16p",AC.Commercial,plspace);
520  }
521  else {
522  MULPOS(pp,10);
523  if ( ISLESSPOS(*plspace,pp) ) {
524  MesPrint("%24s Bytes used=%17p",AC.Commercial,plspace);
525  }
526  } } } } }
527  }
528  } }
529 #ifdef WITHSTATS
530  MesPrint("Total number of writes: %l, reads: %l, seeks, %l"
531  ,numwrites,numreads,numseeks);
532  MesPrint("Total number of mallocs: %l, frees: %l"
533  ,nummallocs,numfrees);
534 #endif
535  MUNLOCK(ErrorMessageLock);
536  }
537 }
538 
539 /*
540  #] WriteStats :
541  #[ NewSort : WORD NewSort()
542 */
553 WORD NewSort(PHEAD0)
554 {
555  GETBIDENTITY
556  SORTING *S, **newFS;
557  int i, newsize;
558  if ( AN.SoScratC == 0 )
559  AN.SoScratC = (UWORD *)Malloc1(2*(AM.MaxTal+2)*sizeof(UWORD),"NewSort");
560  AR.sLevel++;
561  if ( AR.sLevel >= AN.NumFunSorts ) {
562  if ( AN.NumFunSorts == 0 ) newsize = 100;
563  else newsize = 2*AN.NumFunSorts;
564  newFS = (SORTING **)Malloc1((newsize+1)*sizeof(SORTING *),"FunSort pointers");
565  for ( i = 0; i < AN.NumFunSorts; i++ ) newFS[i] = AN.FunSorts[i];
566  for ( ; i <= newsize; i++ ) newFS[i] = 0;
567  if ( AN.FunSorts ) M_free(AN.FunSorts,"FunSort pointers");
568  AN.FunSorts = newFS; AN.NumFunSorts = newsize;
569  }
570  if ( AR.sLevel == 0 ) {
571  AN.FunSorts[0] = AT.S0;
572  AT.S0->PolyFlag = ( AR.PolyFun != 0 ) ? AR.PolyFunType: 0;
573  AR.ShortSortCount = 0;
574  }
575  else {
576  if ( AN.FunSorts[AR.sLevel] == 0 ) {
577  AN.FunSorts[AR.sLevel] = AllocSort(
578  AM.SLargeSize,AM.SSmallSize,AM.SSmallEsize,AM.STermsInSmall
579  ,AM.SMaxPatches,AM.SMaxFpatches,AM.SIOsize);
580  }
581  }
582  AT.SS = S = AN.FunSorts[AR.sLevel];
583  S->sFill = S->sBuffer;
584  S->lFill = S->lBuffer;
585  S->lPatch = 0;
586  S->fPatchN = 0;
587  S->GenTerms = S->TermsLeft = S->GenSpace = S->SpaceLeft = 0;
588  S->PoinFill = S->sPointer;
589  *S->PoinFill = S->sFill;
590  PUTZERO(S->SizeInFile[0]); PUTZERO(S->SizeInFile[1]); PUTZERO(S->SizeInFile[2]);
591  S->sTerms = 0;
592  PUTZERO(S->file.POposition);
593  S->stage4 = 0;
594  if ( AR.sLevel > AN.MaxFunSorts ) AN.MaxFunSorts = AR.sLevel;
595 /*
596  The next variable is for the staged sort only.
597  It should be treated differently
598 
599  PUTZERO(AN.OldPosOut);
600 */
601  return(0);
602 }
603 
604 /*
605  #] NewSort :
606  #[ EndSort : WORD EndSort(PHEAD buffer,par)
607 */
632 LONG EndSort(PHEAD WORD *buffer, int par)
633 {
634  GETBIDENTITY
635  SORTING *S = AT.SS;
636  WORD j, **ss, *to, *t;
637  LONG sSpace, over, tover, spare, retval = 0, jj;
638  POSITION position, pp;
639  off_t lSpace;
640  FILEHANDLE *fout = 0, *oldoutfile = 0, *newout = 0;
641 
642  if ( AM.exitflag && AR.sLevel == 0 ) return(0);
643 #ifdef WITHMPI
644  if( (retval = PF_EndSort()) > 0){
645  oldoutfile = AR.outfile;
646  retval = 0;
647  goto RetRetval;
648  }
649  else if(retval < 0){
650  retval = -1;
651  goto RetRetval;
652  }
653  /* PF_EndSort returned 0: for S != AM.S0 and slaves still do the regular sort */
654 #endif /* WITHMPI */
655  oldoutfile = AR.outfile;
656  if ( S == AT.S0 ) {
657  S->PolyFlag = ( AR.PolyFun != 0 ) ? AR.PolyFunType: 0;
658  S->PolyWise = 0;
659  }
660  else {
661  S->PolyFlag = S->PolyWise = 0;
662  }
663  *(S->PoinFill) = 0;
664 
665  SplitMerge(BHEAD S->sPointer,S->sTerms);
666 
667  sSpace = 0;
668  tover = over = S->sTerms;
669  ss = S->sPointer;
670  if ( over >= 0 ) {
671  if ( S->lPatch > 0 || S->file.handle >= 0 ) {
672  ss[over] = 0;
673  sSpace = ComPress(ss,&spare);
674  S->TermsLeft -= over - spare;
675  if ( par == 1 ) { AR.outfile = newout = AllocFileHandle(); }
676  }
677  else if ( S != AT.S0 ) {
678  ss[over] = 0;
679  if ( par == 2 ) {
680  sSpace = 1;
681  while ( ( t = *ss++ ) != 0 ) { sSpace += *t; }
682  to = (WORD *)Malloc1(sSpace*sizeof(WORD),"$-sort space");
683  *((WORD **)buffer) = to;
684  ss = S->sPointer;
685  while ( ( t = *ss++ ) != 0 ) {
686  j = *t; while ( --j >= 0 ) *to++ = *t++;
687  }
688  *to = 0;
689  retval = sSpace + 1;
690  }
691  else {
692  to = buffer;
693  sSpace = 0;
694  while ( ( t = *ss++ ) != 0 ) {
695  j = *t;
696  if ( ( sSpace += j ) > AM.MaxTer/((LONG)sizeof(WORD)) ) {
697  MLOCK(ErrorMessageLock);
698  MesPrint("Sorted function argument too long.");
699  MUNLOCK(ErrorMessageLock);
700  retval = -1; goto RetRetval;
701  }
702  while ( --j >= 0 ) *to++ = *t++;
703  }
704  *to = 0;
705  }
706  goto RetRetval;
707  }
708  else {
709  POSITION oldpos;
710  if ( S == AT.S0 ) {
711  fout = AR.outfile;
712  *AR.CompressPointer = 0;
713  SeekScratch(AR.outfile,&position);
714  }
715  else {
716  fout = &(S->file);
717  PUTZERO(position);
718  }
719  oldpos = position;
720  S->TermsLeft = 0;
721 /*
722  Here we can go directly to the output.
723 */
724 #ifdef WITHZLIB
725  { int oldgzipCompress = AR.gzipCompress;
726  AR.gzipCompress = 0;
727  /* SetupOutputGZIP(fout); */
728 #endif
729  if ( tover > 0 ) {
730  ss = S->sPointer;
731  while ( ( t = *ss++ ) != 0 ) {
732  if ( *t ) S->TermsLeft++;
733 #ifdef WITHPTHREADS
734  if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD t); }
735  else
736 #endif
737  if ( PutOut(BHEAD t,&position,fout,1) < 0 ) {
738  retval = -1; goto RetRetval;
739  }
740  }
741  }
742 #ifdef WITHPTHREADS
743  if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD 0); }
744  else
745 #endif
746  if ( FlushOut(&position,fout,1) ) {
747  retval = -1; goto RetRetval;
748  }
749 #ifdef WITHZLIB
750  AR.gzipCompress = oldgzipCompress;
751  }
752 #endif
753 #ifdef WITHPTHREADS
754  if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
755 #endif
756 #ifdef WITHMPI
757  if ( PF.me != MASTER && PF.exprtodo < 0 ) goto RetRetval;
758 #endif
759  DIFPOS(oldpos,position,oldpos);
760  S->SpaceLeft = BASEPOSITION(oldpos);
761  WriteStats(&oldpos,(WORD)2);
762  goto RetRetval;
763  }
764  }
765  else if ( par == 1 && newout == 0 ) { AR.outfile = newout = AllocFileHandle(); }
766  sSpace++;
767  lSpace = sSpace + (S->lFill - S->lBuffer) - (LONG)S->lPatch*(AM.MaxTer/sizeof(WORD));
768 /* Note wrt MaxTer and lPatch: each patch starts with space for decompression */
769 /* Not needed if only large buffer, but needed when using files (?) */
770  SETBASEPOSITION(pp,lSpace);
771  MULPOS(pp,sizeof(WORD));
772  if ( S->file.handle >= 0 ) {
773  ADD2POS(pp,S->fPatches[S->fPatchN]);
774  }
775  if ( S == AT.S0 ) {
776  WORD oldLogHandle = AC.LogHandle;
777  if ( AC.LogHandle >= 0 && AM.LogType && ( ( S->lPatch > 0 )
778  || S->file.handle >= 0 ) ) AC.LogHandle = -1;
779  if ( S->lPatch > 0 || S->file.handle >= 0 ) { WriteStats(&pp,0); }
780  AC.LogHandle = oldLogHandle;
781  }
782  if ( par == 2 ) { AR.outfile = newout = AllocFileHandle(); }
783  if ( S->lPatch > 0 ) {
784  if ( ( S->lPatch >= S->MaxPatches ) ||
785  ( ( (WORD *)(((UBYTE *)(S->lFill + sSpace)) + 2*AM.MaxTer) ) >= S->lTop ) ) {
786 /*
787  The large buffer is too full. Merge and write it
788 */
789 #ifdef GZIPDEBUG
790  MLOCK(ErrorMessageLock);
791  MesPrint("%w EndSort: lPatch = %d, MaxPatches = %d,lFill = %x, sSpace = %ld, MaxTer = %d, lTop = %x"
792  ,S->lPatch,S->MaxPatches,S->lFill,sSpace,AM.MaxTer/sizeof(WORD),S->lTop);
793  MUNLOCK(ErrorMessageLock);
794 #endif
795  if ( MergePatches(1) ) {
796  MLOCK(ErrorMessageLock);
797  MesCall("EndSort");
798  MUNLOCK(ErrorMessageLock);
799  retval = -1; goto RetRetval;
800  }
801  S->lPatch = 0;
802  pp = S->SizeInFile[1];
803  MULPOS(pp,sizeof(WORD));
804 #ifndef WITHPTHREADS
805  if ( S == AT.S0 )
806 #endif
807  {
808  WORD oldLogHandle = AC.LogHandle;
809  POSITION pppp;
810  SETBASEPOSITION(pppp,0);
811  SeekFile(S->file.handle,&pppp,SEEK_CUR);
812  SeekFile(S->file.handle,&pp,SEEK_END);
813  SeekFile(S->file.handle,&pppp,SEEK_SET);
814  if ( AC.LogHandle >= 0 && AM.LogType ) AC.LogHandle = -1;
815  WriteStats(&pp,(WORD)1);
816  AC.LogHandle = oldLogHandle;
817  UpdateMaxSize();
818  }
819  }
820  else {
821  S->Patches[S->lPatch++] = S->lFill;
822  to = (WORD *)(((UBYTE *)(S->lFill)) + AM.MaxTer);
823  if ( tover > 0 ) {
824  ss = S->sPointer;
825  while ( ( t = *ss++ ) != 0 ) {
826  j = *t;
827  if ( j < 0 ) j = t[1] + 2;
828  while ( --j >= 0 ) *to++ = *t++;
829  }
830  }
831  *to++ = 0;
832  S->lFill = to;
833  if ( S->file.handle < 0 ) {
834  if ( MergePatches(2) ) {
835  MLOCK(ErrorMessageLock);
836  MesCall("EndSort");
837  MUNLOCK(ErrorMessageLock);
838  retval = -1; goto RetRetval;
839  }
840  if ( S == AT.S0 ) {
841 #ifdef WITHPTHREADS
842  if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
843 #endif
844  pp = S->SizeInFile[2];
845  MULPOS(pp,sizeof(WORD));
846  WriteStats(&pp,2);
847  UpdateMaxSize();
848  }
849  else {
850  if ( par == 2 && newout->handle >= 0 ) {
851  POSITION zeropos;
852  PUTZERO(zeropos);
853 #ifdef ALLLOCK
854  LOCK(newout->pthreadslock);
855 #endif
856  SeekFile(newout->handle,&zeropos,SEEK_SET);
857  to = (WORD *)Malloc1(BASEPOSITION(newout->filesize)
858  ,"$-buffer reading");
859  if ( ( retval = ReadFile(newout->handle,(UBYTE *)to,BASEPOSITION(newout->filesize)) ) !=
860  BASEPOSITION(newout->filesize) ) {
861  MLOCK(ErrorMessageLock);
862  MesPrint("Error reading information for $ variable");
863  MUNLOCK(ErrorMessageLock);
864  M_free(to,"$-buffer reading");
865  retval = -1;
866  }
867  else {
868  *((WORD **)buffer) = to;
869  retval /= sizeof(WORD);
870  }
871 #ifdef ALLLOCK
872  UNLOCK(newout->pthreadslock);
873 #endif
874  }
875  else if ( newout->handle >= 0 ) { /* output too large */
876 TooLarge:
877  MLOCK(ErrorMessageLock);
878  MesPrint("Output should fit inside a single term. Increase MaxTermSize?");
879  MesCall("EndSort");
880  MUNLOCK(ErrorMessageLock);
881  retval = -1; goto RetRetval;
882  }
883  else {
884  t = newout->PObuffer;
885  if ( par == 2 ) {
886  jj = newout->POfill - t;
887  to = (WORD *)Malloc1(jj*sizeof(WORD),"$-sort space");
888  *((WORD **)buffer) = to;
889  NCOPY(to,t,jj);
890  }
891  else {
892  j = newout->POfill - t;
893  to = buffer;
894  if ( to >= AT.WorkSpace && to < AT.WorkTop && to+j > AT.WorkTop )
895  goto WorkSpaceError;
896  if ( j > AM.MaxTer ) goto TooLarge;
897  NCOPY(to,t,j);
898  }
899  }
900  }
901  goto RetRetval;
902  }
903  if ( MergePatches(1) ) { /* --> SortFile */
904  MLOCK(ErrorMessageLock);
905  MesCall("EndSort");
906  MUNLOCK(ErrorMessageLock);
907  retval = -1; goto RetRetval;
908  }
909  UpdateMaxSize();
910  pp = S->SizeInFile[1];
911  MULPOS(pp,sizeof(WORD));
912 #ifndef WITHPTHREADS
913  if ( S == AT.S0 )
914 #endif
915  {
916  WORD oldLogHandle = AC.LogHandle;
917  POSITION pppp;
918  SETBASEPOSITION(pppp,0);
919  SeekFile(S->file.handle,&pppp,SEEK_CUR);
920  SeekFile(S->file.handle,&pp,SEEK_END);
921  SeekFile(S->file.handle,&pppp,SEEK_SET);
922  if ( AC.LogHandle >= 0 && AM.LogType ) AC.LogHandle = -1;
923  WriteStats(&pp,(WORD)1);
924  AC.LogHandle = oldLogHandle;
925  }
926 #ifdef WITHERRORXXX
927  if ( S != AT.S0 ) {
928 /*
929  This is wrong! We have sorted to the sort file.
930  Things are not sitting in the output yet.
931 */
932  if ( newout->handle >= 0 ) goto TooLarge;
933  t = newout->PObuffer;
934  j = newout->POfill - t;
935  to = buffer;
936  if ( to >= AT.WorkSpace && to < AT.WorkTop && to+j > AT.WorkTop )
937  goto WorkSpaceError;
938  if ( j > AM.MaxTer ) goto TooLarge;
939  NCOPY(to,t,j);
940  goto RetRetval;
941  }
942 #endif
943  }
944  }
945  if ( S->file.handle >= 0 ) {
946 #ifdef GZIPDEBUG
947  MLOCK(ErrorMessageLock);
948  MesPrint("%w EndSort: fPatchN = %d, lPatch = %d, position = %12p"
949  ,S->fPatchN,S->lPatch,&(S->fPatches[S->fPatchN]));
950  MUNLOCK(ErrorMessageLock);
951 #endif
952  if ( S->lPatch <= 0 ) {
953  StageSort(&(S->file));
954  position = S->fPatches[S->fPatchN];
955  ss = S->sPointer;
956  if ( *ss ) {
957 #ifdef WITHZLIB
958  *AR.CompressPointer = 0;
959  if ( S == AT.S0 && AR.NoCompress == 0 && AR.gzipCompress > 0 )
960  S->fpcompressed[S->fPatchN] = 1;
961  else
962  S->fpcompressed[S->fPatchN] = 0;
963  SetupOutputGZIP(&(S->file));
964 #endif
965  while ( ( t = *ss++ ) != 0 ) {
966  if ( PutOut(BHEAD t,&position,&(S->file),1) < 0 ) {
967  retval = -1; goto RetRetval;
968  }
969  }
970  if ( FlushOut(&position,&(S->file),1) ) {
971  retval = -1; goto RetRetval;
972  }
973  ++(S->fPatchN);
974  S->fPatches[S->fPatchN] = position;
975  UpdateMaxSize();
976 #ifdef GZIPDEBUG
977  MLOCK(ErrorMessageLock);
978  MesPrint("%w EndSort+: fPatchN = %d, lPatch = %d, position = %12p"
979  ,S->fPatchN,S->lPatch,&(S->fPatches[S->fPatchN]));
980  MUNLOCK(ErrorMessageLock);
981 #endif
982  }
983  }
984  AR.Stage4Name = 0;
985 #ifdef WITHPTHREADS
986  if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
987  if ( S->file.handle >= 0 ) {
988  SynchFile(S->file.handle);
989  }
990  }
991 #endif
992  UpdateMaxSize();
993  if ( MergePatches(0) ) {
994  MLOCK(ErrorMessageLock);
995  MesCall("EndSort");
996  MUNLOCK(ErrorMessageLock);
997  retval = -1; goto RetRetval;
998  }
999  S->stage4 = 0;
1000 #ifdef WITHPTHREADS
1001  if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
1002 #endif
1003  pp = S->SizeInFile[0];
1004  MULPOS(pp,sizeof(WORD));
1005  WriteStats(&pp,2);
1006  UpdateMaxSize();
1007  }
1008 RetRetval:
1009 
1010 #ifdef WITHMPI
1011  /* NOTE: PF_EndSort has been changed such that it sets S->TermsLeft. (TU 30 Jun 2011) */
1012  if ( AR.sLevel == 0 && (PF.me == MASTER || PF.exprtodo >= 0) ) {
1013  Expressions[AR.CurExpr].counter = S->TermsLeft;
1014  }
1015 #else
1016  if ( AR.sLevel == 0 ) {
1017  Expressions[AR.CurExpr].counter = S->TermsLeft;
1018  }/*if ( AR.sLevel == 0 )*/
1019 #endif
1020 /*:[25nov2003 mt]*/
1021  if ( S->file.handle >= 0 && ( par != 1 ) && ( par != 2 ) ) {
1022  /* sortfile is still open */
1023  UpdateMaxSize();
1024  CloseFile(S->file.handle);
1025  S->file.handle = -1;
1026  remove(S->file.name);
1027 #ifdef GZIPDEBUG
1028  MLOCK(ErrorMessageLock);
1029  MesPrint("%wEndSort: sortfile %s removed",S->file.name);
1030  MUNLOCK(ErrorMessageLock);
1031 #endif
1032  }
1033  AR.outfile = oldoutfile;
1034  AR.sLevel--;
1035  if ( AR.sLevel >= 0 ) AT.SS = AN.FunSorts[AR.sLevel];
1036  if ( par == 1 ) {
1037  if ( retval < 0 ) {
1038  UpdateMaxSize();
1039  DeAllocFileHandle(newout);
1040  newout = 0;
1041  }
1042  else if ( newout ) {
1043  if ( newout->handle >= 0 ) {
1044  MLOCK(ErrorMessageLock);
1045  MesPrint("Output should fit inside a single term. Increase MaxTermSize?");
1046  MesCall("EndSort");
1047  MUNLOCK(ErrorMessageLock);
1048  Terminate(-1);
1049  }
1050  else if ( newout->POfill > newout->PObuffer ) {
1051 /*
1052  Here we have to copy the contents of the 'file' into
1053  the buffer. We assume that this buffer lies in the WorkSpace.
1054  Hence
1055 */
1056  j = newout->POfill-newout->PObuffer;
1057  if ( buffer >= AT.WorkSpace && buffer < AT.WorkTop && buffer+j > AT.WorkTop )
1058  goto WorkSpaceError;
1059  else {
1060  to = buffer; t = newout->PObuffer;
1061  while ( j-- > 0 ) *to++ = *t++;
1062  }
1063  UpdateMaxSize();
1064  }
1065  DeAllocFileHandle(newout);
1066  newout = 0;
1067  }
1068  }
1069  else if ( par == 2 ) {
1070  if ( newout ) {
1071  if ( retval == 0 ) {
1072  if ( newout->handle >= 0 ) {
1073 /*
1074  output resides at the moment in a file
1075  Find the size, make a buffer, copy into the buffer and clean up.
1076 */
1077  POSITION zeropos;
1078  PUTZERO(position);
1079 #ifdef ALLLOCK
1080  LOCK(newout->pthreadslock);
1081 #endif
1082  SeekFile(newout->handle,&position,SEEK_END);
1083  PUTZERO(zeropos);
1084  SeekFile(newout->handle,&zeropos,SEEK_SET);
1085  to = (WORD *)Malloc1(BASEPOSITION(position)+sizeof(WORD)
1086  ,"$-buffer reading");
1087  if ( ( retval = ReadFile(newout->handle,(UBYTE *)to,BASEPOSITION(position)) ) !=
1088  BASEPOSITION(position) ) {
1089  MLOCK(ErrorMessageLock);
1090  MesPrint("Error reading information for $ variable");
1091  MUNLOCK(ErrorMessageLock);
1092  M_free(to,"$-buffer reading");
1093  retval = -1;
1094  }
1095  else {
1096  *((WORD **)buffer) = to;
1097  retval /= sizeof(WORD);
1098  }
1099 #ifdef ALLLOCK
1100  UNLOCK(newout->pthreadslock);
1101 #endif
1102  }
1103  else {
1104 /*
1105  output resides in the cache buffer and the file was never opened
1106 */
1107  LONG wsiz = newout->POfill - newout->PObuffer;
1108  to = (WORD *)Malloc1(wsiz*sizeof(WORD),"$-buffer reading");
1109  *((WORD **)buffer) = to; t = newout->PObuffer;
1110  retval = wsiz;
1111  NCOPY(to,t,wsiz);
1112  }
1113  }
1114  UpdateMaxSize();
1115  DeAllocFileHandle(newout);
1116  newout = 0;
1117  }
1118  }
1119  else {
1120  if ( newout ) {
1121  DeAllocFileHandle(newout);
1122  newout = 0;
1123  }
1124  }
1125  return(retval);
1126 WorkSpaceError:
1127  MLOCK(ErrorMessageLock);
1128  MesWork();
1129  MesCall("EndSort");
1130  MUNLOCK(ErrorMessageLock);
1131  Terminate(-1);
1132  return(-1);
1133 }
1134 
1135 /*
1136  #] EndSort :
1137  #[ PutIn : LONG PutIn(handle,position,buffer,take,npat)
1138 */
1154 LONG PutIn(FILEHANDLE *file, POSITION *position, WORD *buffer, WORD **take, int npat)
1155 {
1156  LONG i, RetCode;
1157  WORD *from, *to;
1158 #ifndef WITHZLIB
1159  DUMMYUSE(npat);
1160 #endif
1161  from = buffer + ( file->POsize * sizeof(UBYTE) )/sizeof(WORD);
1162  i = from - *take;
1163  if ( i*((LONG)(sizeof(WORD))) > AM.MaxTer ) {
1164  MLOCK(ErrorMessageLock);
1165  MesPrint("Problems in PutIn");
1166  MUNLOCK(ErrorMessageLock);
1167  Terminate(-1);
1168  }
1169  to = buffer;
1170  while ( --i >= 0 ) *--to = *--from;
1171  *take = to;
1172 #ifdef WITHZLIB
1173  if ( ( RetCode = FillInputGZIP(file,position,(UBYTE *)buffer
1174  ,file->POsize,npat) ) < 0 ) {
1175  MLOCK(ErrorMessageLock);
1176  MesPrint("PutIn: We have RetCode = %x while reading %x bytes",
1177  RetCode,file->POsize);
1178  MUNLOCK(ErrorMessageLock);
1179  Terminate(-1);
1180  }
1181 #else
1182 #ifdef ALLLOCK
1183  LOCK(file->pthreadslock);
1184 #endif
1185  SeekFile(file->handle,position,SEEK_SET);
1186  if ( ( RetCode = ReadFile(file->handle,(UBYTE *)buffer,file->POsize) ) < 0 ) {
1187 #ifdef ALLLOCK
1188  UNLOCK(file->pthreadslock);
1189 #endif
1190  MLOCK(ErrorMessageLock);
1191  MesPrint("PutIn: We have RetCode = %x while reading %x bytes",
1192  RetCode,file->POsize);
1193  MUNLOCK(ErrorMessageLock);
1194  Terminate(-1);
1195  }
1196 #ifdef ALLLOCK
1197  UNLOCK(file->pthreadslock);
1198 #endif
1199 #endif
1200  return(RetCode);
1201 }
1202 
1203 /*
1204  #] PutIn :
1205  #[ Sflush : WORD Sflush(file)
1206 */
1215 {
1216  LONG size, RetCode;
1217 #ifdef WITHZLIB
1218  GETIDENTITY
1219  int dobracketindex = 0;
1220  if ( AR.sLevel <= 0 && Expressions[AR.CurExpr].newbracketinfo
1221  && ( fi == AR.outfile || fi == AR.hidefile ) ) dobracketindex = 1;
1222 #endif
1223  if ( fi->handle < 0 ) {
1224  if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
1225 #ifdef GZIPDEBUG
1226  MLOCK(ErrorMessageLock);
1227  MesPrint("%w Sflush created scratch file %s",fi->name);
1228  MUNLOCK(ErrorMessageLock);
1229 #endif
1230  fi->handle = (WORD)RetCode;
1231  PUTZERO(fi->filesize);
1232  PUTZERO(fi->POposition);
1233  }
1234  else {
1235  MLOCK(ErrorMessageLock);
1236  MesPrint("Cannot create scratch file %s",fi->name);
1237  MUNLOCK(ErrorMessageLock);
1238  return(-1);
1239  }
1240  }
1241 #ifdef WITHZLIB
1242  if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
1243  && dobracketindex == 0 ) {
1244  if ( FlushOutputGZIP(fi) ) return(-1);
1245  fi->POfill = fi->PObuffer;
1246  }
1247  else
1248 #endif
1249  {
1250 #ifdef ALLLOCK
1251  LOCK(fi->pthreadslock);
1252 #endif
1253  size = (fi->POfill-fi->PObuffer)*sizeof(WORD);
1254  SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
1255  if ( WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),size) != size ) {
1256 #ifdef ALLLOCK
1257  UNLOCK(fi->pthreadslock);
1258 #endif
1259  MLOCK(ErrorMessageLock);
1260  MesPrint("Write error while finishing sort. Disk full?");
1261  MUNLOCK(ErrorMessageLock);
1262  return(-1);
1263  }
1264  ADDPOS(fi->filesize,size);
1265  ADDPOS(fi->POposition,size);
1266  fi->POfill = fi->PObuffer;
1267 #ifdef ALLLOCK
1268  UNLOCK(fi->pthreadslock);
1269 #endif
1270  }
1271  return(0);
1272 }
1273 
1274 /*
1275  #] Sflush :
1276  #[ PutOut : WORD PutOut(term,position,file,ncomp)
1277 */
1300 WORD PutOut(PHEAD WORD *term, POSITION *position, FILEHANDLE *fi, WORD ncomp)
1301 {
1302  GETBIDENTITY
1303  WORD i, *p, ret, *r, *rr, j, k, first;
1304  int dobracketindex = 0;
1305  LONG RetCode;
1306 
1307  if ( AT.SS != AT.S0 ) {
1308 /*
1309  For this case no compression should be used
1310 */
1311  if ( ( i = *term ) <= 0 ) return(0);
1312  ret = i;
1313  ADDPOS(*position,i*sizeof(WORD));
1314  p = fi->POfill;
1315  do {
1316  if ( p >= fi->POstop ) {
1317  if ( fi->handle < 0 ) {
1318  if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
1319 #ifdef GZIPDEBUG
1320  MLOCK(ErrorMessageLock);
1321  MesPrint("%w PutOut created sortfile %s",fi->name);
1322  MUNLOCK(ErrorMessageLock);
1323 #endif
1324  fi->handle = (WORD)RetCode;
1325  PUTZERO(fi->filesize);
1326  PUTZERO(fi->POposition);
1327  }
1328  else {
1329  MLOCK(ErrorMessageLock);
1330  MesPrint("Cannot create scratch file %s",fi->name);
1331  MUNLOCK(ErrorMessageLock);
1332  return(-1);
1333  }
1334  }
1335 #ifdef ALLLOCK
1336  LOCK(fi->pthreadslock);
1337 #endif
1338  if ( fi == AR.hidefile ) {
1339  LOCK(AS.inputslock);
1340  }
1341  SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
1342  if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize) ) != fi->POsize ) {
1343  if ( fi == AR.hidefile ) {
1344  UNLOCK(AS.inputslock);
1345  }
1346 #ifdef ALLLOCK
1347  UNLOCK(fi->pthreadslock);
1348 #endif
1349  MLOCK(ErrorMessageLock);
1350  MesPrint("Write error during sort. Disk full?");
1351  MesPrint("Attempt to write %l bytes on file %d at position %15p",
1352  fi->POsize,fi->handle,&(fi->POposition));
1353  MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
1354  MUNLOCK(ErrorMessageLock);
1355  return(-1);
1356  }
1357  ADDPOS(fi->filesize,fi->POsize);
1358  p = fi->PObuffer;
1359  ADDPOS(fi->POposition,fi->POsize);
1360  if ( fi == AR.hidefile ) {
1361  UNLOCK(AS.inputslock);
1362  }
1363 #ifdef ALLLOCK
1364  UNLOCK(fi->pthreadslock);
1365 #endif
1366 #ifdef WITHPTHREADS
1367  if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
1368  if ( fi->handle >= 0 ) SynchFile(fi->handle);
1369  }
1370 #endif
1371  }
1372  *p++ = *term++;
1373  } while ( --i > 0 );
1374  fi->POfull = fi->POfill = p;
1375  return(ret);
1376  }
1377  if ( ( AP.PreDebug & DUMPOUTTERMS ) == DUMPOUTTERMS ) {
1378  MLOCK(ErrorMessageLock);
1379 #ifdef WITHPTHREADS
1380  sprintf((char *)(THRbuf),"PutOut(%d)",AT.identity);
1381  PrintTerm(term,(char *)(THRbuf));
1382 #else
1383  PrintTerm(term,"PutOut");
1384 #endif
1385  MesPrint("ncomp = %d, AR.NoCompress = %d, AR.sLevel = %d",ncomp,AR.NoCompress,AR.sLevel);
1386  MesPrint("File %s, position %p",fi->name,position);
1387  MUNLOCK(ErrorMessageLock);
1388  }
1389 
1390  if ( AR.sLevel <= 0 && Expressions[AR.CurExpr].newbracketinfo
1391  && ( fi == AR.outfile || fi == AR.hidefile ) ) dobracketindex = 1;
1392  r = rr = AR.CompressPointer;
1393  first = j = k = ret = 0;
1394  if ( ( i = *term ) != 0 ) {
1395  if ( i < 0 ) { /* Compressed term */
1396  i = term[1] + 2;
1397  if ( fi == AR.outfile || fi == AR.hidefile ) {
1398  MLOCK(ErrorMessageLock);
1399  MesPrint("Ran into precompressed term");
1400  MUNLOCK(ErrorMessageLock);
1401  Crash();
1402  return(-1);
1403  }
1404  }
1405  else if ( !AR.NoCompress && ( ncomp > 0 ) && AR.sLevel <= 0 ) { /* Must compress */
1406  if ( dobracketindex ) {
1407  PutBracketInIndex(BHEAD term,position);
1408  }
1409  j = *r++ - 1;
1410  p = term + 1;
1411  i--;
1412  if ( AR.PolyFun ) {
1413  WORD *polystop, *sa;
1414  sa = p + i;
1415  sa -= ABS(sa[-1]);
1416  polystop = p;
1417  while ( polystop < sa && *polystop != AR.PolyFun ) {
1418  polystop += polystop[1];
1419  }
1420  if ( AR.PolyFunType == 2 ) polystop[2] &= ~CLEANPRF;
1421  while ( i > 0 && j > 0 && *p == *r && p < polystop ) {
1422  i--; j--; k--; p++; r++;
1423  }
1424  }
1425  else {
1426  WORD *sa;
1427  sa = p + i;
1428  sa -= ABS(sa[-1]);
1429  while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
1430  }
1431  if ( k > -2 ) {
1432 nocompress:
1433  j = i = *term;
1434  k = 0;
1435  p = term;
1436  r = rr;
1437  NCOPY(r,p,j);
1438  }
1439  else {
1440  *rr = *term;
1441  term = p;
1442  j = i;
1443  NCOPY(r,p,j);
1444  j = i;
1445  i += 2;
1446  first = 2;
1447  }
1448 /* Sabotage getting into the coefficient next time */
1449  r[-(ABS(r[-1]))] = 0;
1450  if ( r >= AR.ComprTop ) {
1451  MLOCK(ErrorMessageLock);
1452  MesPrint("CompressSize of %10l is insufficient",AM.CompressSize);
1453  MUNLOCK(ErrorMessageLock);
1454  Crash();
1455  return(-1);
1456  }
1457  }
1458  else if ( !AR.NoCompress && ( ncomp < 0 ) && AR.sLevel <= 0 ) {
1459  /* No compress but put in compress buffer anyway */
1460  if ( dobracketindex ) {
1461  PutBracketInIndex(BHEAD term,position);
1462  }
1463  j = *r++ - 1;
1464  p = term + 1;
1465  i--;
1466  if ( AR.PolyFun ) {
1467  WORD *polystop, *sa;
1468  sa = p + i;
1469  sa -= ABS(sa[-1]);
1470  polystop = p;
1471  while ( polystop < sa && *polystop != AR.PolyFun ) {
1472  polystop += polystop[1];
1473  }
1474  if ( AR.PolyFunType == 2 ) polystop[2] &= ~CLEANPRF;
1475  while ( i > 0 && j > 0 && *p == *r && p < polystop ) {
1476  i--; j--; k--; p++; r++;
1477  }
1478  }
1479  else {
1480  while ( i > 0 && j > 0 && *p == *r ) { i--; j--; k--; p++; r++; }
1481  }
1482  goto nocompress;
1483  }
1484  else {
1485  if ( AR.PolyFunType == 2 ) {
1486  WORD *t, *tstop;
1487  tstop = term + *term;
1488  tstop -= ABS(tstop[-1]);
1489  t = term+1;
1490  while ( t < tstop ) {
1491  if ( *t == AR.PolyFun ) {
1492  t[2] &= ~CLEANPRF;
1493  }
1494  t += t[1];
1495  }
1496  }
1497  if ( dobracketindex ) {
1498  PutBracketInIndex(BHEAD term,position);
1499  }
1500  }
1501  ret = i;
1502  ADDPOS(*position,i*sizeof(WORD));
1503  p = fi->POfill;
1504  do {
1505  if ( p >= fi->POstop ) {
1506 #ifdef WITHMPI /* [16mar1998 ar] */
1507  if ( PF.me != MASTER && AR.sLevel <= 0 && (fi == AR.outfile || fi == AR.hidefile) && PF.parallel && PF.exprtodo < 0 ) {
1508  PF_BUFFER *sbuf = PF.sbuf;
1509  sbuf->fill[sbuf->active] = fi->POstop;
1510  PF_ISendSbuf(MASTER,PF_BUFFER_MSGTAG);
1511  p = fi->PObuffer = fi->POfill = fi->POfull =
1512  sbuf->buff[sbuf->active];
1513  fi->POstop = sbuf->stop[sbuf->active];
1514  }
1515  else
1516 #endif /* WITHMPI [16mar1998 ar] */
1517  {
1518  if ( fi->handle < 0 ) {
1519  if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
1520 #ifdef GZIPDEBUG
1521  MLOCK(ErrorMessageLock);
1522  MesPrint("%w PutOut created sortfile %s",fi->name);
1523  MUNLOCK(ErrorMessageLock);
1524 #endif
1525  fi->handle = (WORD)RetCode;
1526  PUTZERO(fi->filesize);
1527  PUTZERO(fi->POposition);
1528  }
1529  else {
1530  MLOCK(ErrorMessageLock);
1531  MesPrint("Cannot create scratch file %s",fi->name);
1532  MUNLOCK(ErrorMessageLock);
1533  return(-1);
1534  }
1535  }
1536 #ifdef WITHZLIB
1537  if ( !AR.NoCompress && ncomp > 0 && AR.gzipCompress > 0
1538  && dobracketindex == 0 ) {
1539  fi->POfill = p;
1540  if ( PutOutputGZIP(fi) ) return(-1);
1541  p = fi->PObuffer;
1542  }
1543  else
1544 #endif
1545  {
1546 #ifdef ALLLOCK
1547  LOCK(fi->pthreadslock);
1548 #endif
1549  if ( fi == AR.hidefile ) {
1550  LOCK(AS.inputslock);
1551  }
1552  SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
1553  if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize) ) != fi->POsize ) {
1554  if ( fi == AR.hidefile ) {
1555  UNLOCK(AS.inputslock);
1556  }
1557 #ifdef ALLLOCK
1558  UNLOCK(fi->pthreadslock);
1559 #endif
1560  MLOCK(ErrorMessageLock);
1561  MesPrint("Write error during sort. Disk full?");
1562  MesPrint("Attempt to write %l bytes on file %d at position %15p",
1563  fi->POsize,fi->handle,&(fi->POposition));
1564  MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
1565  MUNLOCK(ErrorMessageLock);
1566  return(-1);
1567  }
1568  ADDPOS(fi->filesize,fi->POsize);
1569  p = fi->PObuffer;
1570  ADDPOS(fi->POposition,fi->POsize);
1571  if ( fi == AR.hidefile ) {
1572  UNLOCK(AS.inputslock);
1573  }
1574 #ifdef ALLLOCK
1575  UNLOCK(fi->pthreadslock);
1576 #endif
1577 #ifdef WITHPTHREADS
1578  if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
1579  if ( fi->handle >= 0 ) SynchFile(fi->handle);
1580  }
1581 #endif
1582  }
1583  }
1584  }
1585  if ( first ) {
1586  if ( first == 2 ) *p++ = k;
1587  else *p++ = j;
1588  first--;
1589  }
1590  else *p++ = *term++;
1591 /*
1592  if ( AP.DebugFlag ) {
1593  TalToLine((UWORD)(p[-1])); TokenToLine((UBYTE *)" ");
1594  }
1595 */
1596  } while ( --i > 0 );
1597  fi->POfull = fi->POfill = p;
1598  }
1599 /*
1600  if ( AP.DebugFlag ) {
1601  AO.OutSkip = 0;
1602  FiniLine();
1603  }
1604 */
1605  return(ret);
1606 }
1607 
1608 /*
1609  #] PutOut :
1610  #[ FlushOut : WORD FlushOut(position,file,compr)
1611 */
1621 WORD FlushOut(POSITION *position, FILEHANDLE *fi, int compr)
1622 {
1623  GETIDENTITY
1624  LONG size, RetCode;
1625  int dobracketindex = 0;
1626 #ifndef WITHZLIB
1627  DUMMYUSE(compr);
1628 #endif
1629  if ( AR.sLevel <= 0 && Expressions[AR.CurExpr].newbracketinfo
1630  && ( fi == AR.outfile || fi == AR.hidefile ) ) dobracketindex = 1;
1631 #ifdef WITHMPI /* [16mar1998 ar] */
1632  if ( PF.me != MASTER && AR.sLevel <= 0 && (fi == AR.outfile || fi == AR.hidefile) && PF.parallel && PF.exprtodo < 0 ) {
1633  PF_BUFFER *sbuf = PF.sbuf;
1634  if ( fi->POfill >= fi->POstop ){
1635  sbuf->fill[sbuf->active] = fi->POstop;
1636  PF_ISendSbuf(MASTER,PF_BUFFER_MSGTAG);
1637  fi->POfull = fi->POfill = fi->PObuffer = sbuf->buff[sbuf->active];
1638  fi->POstop = sbuf->stop[sbuf->active];
1639  }
1640  *(fi->POfill)++ = 0;
1641  sbuf->fill[sbuf->active] = fi->POfill;
1642  PF_ISendSbuf(MASTER,PF_ENDBUFFER_MSGTAG);
1643  fi->PObuffer = fi->POfill = fi->POfull = sbuf->buff[sbuf->active];
1644  fi->POstop = sbuf->stop[sbuf->active];
1645  return(0);
1646  }
1647 #endif /* WITHMPI [16mar1998 ar] */
1648  if ( fi->POfill >= fi->POstop ) {
1649  if ( fi->handle < 0 ) {
1650  if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
1651 #ifdef GZIPDEBUG
1652  MLOCK(ErrorMessageLock);
1653  MesPrint("%w FlushOut created scratch file %s",fi->name);
1654  MUNLOCK(ErrorMessageLock);
1655 #endif
1656  PUTZERO(fi->filesize);
1657  PUTZERO(fi->POposition);
1658  fi->handle = (WORD)RetCode;
1659  }
1660  else {
1661  MLOCK(ErrorMessageLock);
1662  MesPrint("Cannot create scratch file %s",fi->name);
1663  MUNLOCK(ErrorMessageLock);
1664  return(-1);
1665  }
1666  }
1667 #ifdef WITHZLIB
1668  if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
1669  && dobracketindex == 0 && ( compr > 0 ) ) {
1670  if ( PutOutputGZIP(fi) ) return(-1);
1671  fi->POfill = fi->PObuffer;
1672  }
1673  else
1674 #endif
1675  {
1676 #ifdef ALLLOCK
1677  LOCK(fi->pthreadslock);
1678 #endif
1679  if ( fi == AR.hidefile ) {
1680  LOCK(AS.inputslock);
1681  }
1682  SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
1683  if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize) ) != fi->POsize ) {
1684 #ifdef ALLLOCK
1685  UNLOCK(fi->pthreadslock);
1686 #endif
1687  if ( fi == AR.hidefile ) {
1688  UNLOCK(AS.inputslock);
1689  }
1690  MLOCK(ErrorMessageLock);
1691  MesPrint("Write error while sorting. Disk full?");
1692  MesPrint("Attempt to write %l bytes on file %d at position %15p",
1693  fi->POsize,fi->handle,&(fi->POposition));
1694  MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
1695  MUNLOCK(ErrorMessageLock);
1696  return(-1);
1697  }
1698  ADDPOS(fi->filesize,fi->POsize);
1699  fi->POfill = fi->PObuffer;
1700  ADDPOS(fi->POposition,fi->POsize);
1701  if ( fi == AR.hidefile ) {
1702  UNLOCK(AS.inputslock);
1703  }
1704 #ifdef ALLLOCK
1705  UNLOCK(fi->pthreadslock);
1706 #endif
1707 #ifdef WITHPTHREADS
1708  if ( AS.MasterSort && AC.ThreadSortFileSynch && fi != AR.hidefile ) {
1709  if ( fi->handle >= 0 ) SynchFile(fi->handle);
1710  }
1711 #endif
1712  }
1713  }
1714  *(fi->POfill)++ = 0;
1715  fi->POfull = fi->POfill;
1716 /*
1717  {
1718  UBYTE OutBuf[140];
1719  if ( AP.DebugFlag ) {
1720  AO.OutFill = AO.OutputLine = OutBuf;
1721  AO.OutSkip = 3;
1722  FiniLine();
1723  TokenToLine((UBYTE *)"End of expression written");
1724  FiniLine();
1725  }
1726  }
1727 */
1728  size = (fi->POfill-fi->PObuffer)*sizeof(WORD);
1729  if ( fi->handle >= 0 ) {
1730 #ifdef WITHZLIB
1731  if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
1732  && dobracketindex == 0 && ( compr > 0 ) ) {
1733  if ( FlushOutputGZIP(fi) ) return(-1);
1734  fi->POfill = fi->PObuffer;
1735  }
1736  else
1737 #endif
1738  {
1739 #ifdef ALLLOCK
1740  LOCK(fi->pthreadslock);
1741 #endif
1742  if ( fi == AR.hidefile ) {
1743  LOCK(AS.inputslock);
1744  }
1745  SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
1746 /*
1747  MesPrint("FlushOut: writing %l bytes to position %12p",size,&(fi->POposition));
1748 */
1749  if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),size) ) != size ) {
1750 #ifdef ALLLOCK
1751  UNLOCK(fi->pthreadslock);
1752 #endif
1753  if ( fi == AR.hidefile ) {
1754  UNLOCK(AS.inputslock);
1755  }
1756  MLOCK(ErrorMessageLock);
1757  MesPrint("Write error while finishing sorting. Disk full?");
1758  MesPrint("Attempt to write %l bytes on file %d at position %15p",
1759  size,fi->handle,&(fi->POposition));
1760  MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
1761  MUNLOCK(ErrorMessageLock);
1762  return(-1);
1763  }
1764  ADDPOS(fi->filesize,size);
1765  ADDPOS(fi->POposition,size);
1766  fi->POfill = fi->PObuffer;
1767  if ( fi == AR.hidefile ) {
1768  UNLOCK(AS.inputslock);
1769  }
1770 #ifdef ALLLOCK
1771  UNLOCK(fi->pthreadslock);
1772 #endif
1773 #ifdef WITHPTHREADS
1774  if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
1775  if ( fi->handle >= 0 ) SynchFile(fi->handle);
1776  }
1777 #endif
1778  }
1779  }
1780  if ( dobracketindex ) {
1781  BRACKETINFO *b = Expressions[AR.CurExpr].newbracketinfo;
1782  if ( b->indexfill > 0 ) {
1783  DIFPOS(b->indexbuffer[b->indexfill-1].next,*position,Expressions[AR.CurExpr].onfile);
1784  }
1785  }
1786 #ifdef WITHZLIB
1787  if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
1788  && dobracketindex == 0 && ( compr > 0 ) ) {
1789  PUTZERO(*position);
1790  if ( fi->handle >= 0 ) {
1791 #ifdef ALLLOCK
1792  LOCK(fi->pthreadslock);
1793 #endif
1794  SeekFile(fi->handle,position,SEEK_END);
1795 #ifdef ALLLOCK
1796  UNLOCK(fi->pthreadslock);
1797 #endif
1798  }
1799  else {
1800  ADDPOS(*position,((UBYTE *)fi->POfill-(UBYTE *)fi->PObuffer));
1801  }
1802  }
1803  else
1804 #endif
1805  {
1806  ADDPOS(*position,sizeof(WORD));
1807  }
1808  return(0);
1809 }
1810 
1811 /*
1812  #] FlushOut :
1813  #[ AddCoef : WORD AddCoef(pterm1,pterm2)
1814 */
1829 WORD AddCoef(PHEAD WORD **ps1, WORD **ps2)
1830 {
1831  GETBIDENTITY
1832  SORTING *S = AT.SS;
1833  WORD *s1, *s2;
1834  WORD l1, l2, i;
1835  WORD OutLen, *t, j;
1836  UWORD *OutCoef;
1837  OutCoef = AN.SoScratC;
1838  s1 = *ps1; s2 = *ps2;
1839  GETCOEF(s1,l1);
1840  GETCOEF(s2,l2);
1841  if ( AddRat(BHEAD (UWORD *)s1,l1,(UWORD *)s2,l2,OutCoef,&OutLen) ) {
1842  MLOCK(ErrorMessageLock);
1843  MesCall("AddCoef");
1844  MUNLOCK(ErrorMessageLock);
1845  Terminate(-1);
1846  }
1847  if ( AN.ncmod != 0 ) {
1848  if ( ( AC.modmode & POSNEG ) != 0 ) {
1849  NormalModulus(OutCoef,&OutLen);
1850 /*
1851  We had forgotten that this can also become smaller but the
1852  denominator isn't there. Correct in the other case
1853  17-may-2009 [JV]
1854 */
1855  j = ABS(OutLen); OutCoef[j] = 1;
1856  for ( i = 1; i < j; i++ ) OutCoef[j+i] = 0;
1857  }
1858  else if ( BigLong(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod)) >= 0 ) {
1859  SubPLon(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod),OutCoef,&OutLen);
1860  OutCoef[OutLen] = 1;
1861  for ( i = 1; i < OutLen; i++ ) OutCoef[OutLen+i] = 0;
1862  }
1863  }
1864  if ( !OutLen ) { *ps1 = *ps2 = 0; return(0); }
1865  OutLen <<= 1;
1866  if ( OutLen < 0 ) i = - ( --OutLen );
1867  else i = ++OutLen;
1868  if ( l1 < 0 ) l1 = -l1;
1869  l1 <<= 1; l1++;
1870  if ( i <= l1 ) { /* Fits in 1 */
1871  l1 -= i;
1872  **ps1 -= l1;
1873  s2 = (WORD *)OutCoef;
1874  while ( --i > 0 ) *s1++ = *s2++;
1875  *s1++ = OutLen;
1876  while ( --l1 >= 0 ) *s1++ = 0;
1877  goto RegEnd;
1878  }
1879  if ( l2 < 0 ) l2 = -l2;
1880  l2 <<= 1; l2++;
1881  if ( i <= l2 ) { /* Fits in 2 */
1882  l2 -= i;
1883  **ps2 -= l2;
1884  s1 = (WORD *)OutCoef;
1885  while ( --i > 0 ) *s2++ = *s1++;
1886  *s2++ = OutLen;
1887  while ( --l2 >= 0 ) *s2++ = 0;
1888  *ps1 = *ps2;
1889  goto RegEnd;
1890  }
1891 
1892  /* Doesn't fit. Make a new term. */
1893 
1894  t = s1;
1895  s1 = *ps1;
1896  j = *s1++ + i - l1; /* Space needed */
1897  if ( (S->sFill + j) >= S->sTop2 ) {
1898  GarbHand();
1899 
1900  s1 = *ps1;
1901  t = s1 + *s1 - 1;
1902  j = *s1++ + i - l1; /* Space needed */
1903  l1 = *t;
1904  if ( l1 < 0 ) l1 = - l1;
1905  t -= l1-1;
1906  }
1907  s2 = S->sFill;
1908  *s2++ = j;
1909  while ( s1 < t ) *s2++ = *s1++;
1910  s1 = (WORD *)OutCoef;
1911  while ( --i > 0 ) *s2++ = *s1++;
1912  *s2++ = OutLen;
1913  *ps1 = S->sFill;
1914  S->sFill = s2;
1915 RegEnd:
1916  *ps2 = 0;
1917  if ( **ps1 > AM.MaxTer/((LONG)(sizeof(WORD))) ) {
1918  MLOCK(ErrorMessageLock);
1919  MesPrint("Term to complex after polynomial addition. MaxTermSize = %10l",
1920  AM.MaxTer/sizeof(WORD));
1921  MUNLOCK(ErrorMessageLock);
1922  Terminate(-1);
1923  }
1924  return(1);
1925 }
1926 
1927 /*
1928  #] AddCoef :
1929  #[ AddPoly : WORD AddPoly(pterm1,pterm2)
1930 */
1956 WORD AddPoly(PHEAD WORD **ps1, WORD **ps2)
1957 {
1958  GETBIDENTITY
1959  SORTING *S = AT.SS;
1960  WORD i;
1961  WORD *s1, *s2, *m, *w, *t, oldpw = S->PolyWise;
1962  s1 = *ps1 + S->PolyWise;
1963  s2 = *ps2 + S->PolyWise;
1964  w = AT.WorkPointer;
1965 /*
1966  Add here the two arguments. Is a straight merge.
1967 */
1968  if ( S->PolyFlag == 2 ) {
1969  WORD **oldSplitScratch = AN.SplitScratch;
1970  LONG oldSplitScratchSize = AN.SplitScratchSize;
1971  LONG oldInScratch = AN.InScratch;
1972  if ( (WORD *)((UBYTE *)w + AM.MaxTer) >= AT.WorkTop ) {
1973  MLOCK(ErrorMessageLock);
1974  MesPrint("Program was adding polyratfun arguments");
1975  MesWork();
1976  MUNLOCK(ErrorMessageLock);
1977  }
1978  S->PolyWise = 0;
1979  AN.SplitScratch = AN.SplitScratch1;
1980  AN.SplitScratchSize = AN.SplitScratchSize1;
1981  AN.InScratch = AN.InScratch1;
1982  poly_ratfun_add(BHEAD s1,s2);
1983  S->PolyWise = oldpw;
1984  AN.SplitScratch1 = AN.SplitScratch;
1985  AN.SplitScratchSize1 = AN.SplitScratchSize;
1986  AN.InScratch1 = AN.InScratch;
1987  AN.SplitScratch = oldSplitScratch;
1988  AN.SplitScratchSize = oldSplitScratchSize;
1989  AN.InScratch = oldInScratch;
1990  AT.WorkPointer = w;
1991  if ( w[1] <= FUNHEAD ||
1992  ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) ) {
1993  *ps1 = *ps2 = 0; return(0);
1994  }
1995  }
1996  else {
1997  if ( w + s1[1] + s2[1] + 12 + ARGHEAD >= AT.WorkTop ) {
1998  MLOCK(ErrorMessageLock);
1999  MesPrint("Program was adding polyfun arguments");
2000  MesWork();
2001  MUNLOCK(ErrorMessageLock);
2002  }
2003  AddArgs(BHEAD s1,s2,w);
2004  }
2005 /*
2006  Now we need to store the result in a convenient place.
2007 */
2008  if ( w[1] <= FUNHEAD ) { *ps1 = *ps2 = 0; return(0); }
2009  if ( w[1] <= s1[1] || w[1] <= s2[1] ) { /* Fits in place. */
2010  if ( w[1] > s1[1] ) {
2011  *ps1 = *ps2;
2012  s1 = s2;
2013  }
2014  t = s1 + s1[1];
2015  m = *ps1 + **ps1;
2016  i = w[1];
2017  NCOPY(s1,w,i);
2018  if ( s1 != t ) {
2019  while ( t < m ) *s1++ = *t++;
2020  **ps1 = WORDDIF(s1,(*ps1));
2021  }
2022  *ps2 = 0;
2023  }
2024  else { /* Make new term */
2025 #ifdef TESTGARB
2026  s2 = *ps2;
2027 #endif
2028  *ps2 = 0;
2029  if ( (S->sFill + (**ps1 + w[1] - s1[1])) >= S->sTop2 ) {
2030 #ifdef TESTGARB
2031  MesPrint("------Garbage collection-------");
2032 #endif
2033  AT.WorkPointer += w[1];
2034  GarbHand();
2035  AT.WorkPointer = w;
2036  s1 = *ps1;
2037  if ( (S->sFill + (**ps1 + w[1] - s1[1])) >= S->sTop2 ) {
2038 #ifdef TESTGARB
2039  UBYTE OutBuf[140];
2040  MLOCK(ErrorMessageLock);
2041  AO.OutFill = AO.OutputLine = OutBuf;
2042  AO.OutSkip = 3;
2043  FiniLine();
2044  i = *s2;
2045  while ( --i >= 0 ) {
2046  TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)" ");
2047  }
2048  FiniLine();
2049  AO.OutFill = AO.OutputLine = OutBuf;
2050  AO.OutSkip = 3;
2051  FiniLine();
2052  s2 = *ps1;
2053  i = *s2;
2054  while ( --i >= 0 ) {
2055  TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)" ");
2056  }
2057  FiniLine();
2058  AO.OutFill = AO.OutputLine = OutBuf;
2059  AO.OutSkip = 3;
2060  FiniLine();
2061  s2 = w;
2062  i = w[1];
2063  while ( --i >= 0 ) {
2064  TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)" ");
2065  }
2066  FiniLine();
2067  MesPrint("Please increase SmallExtension in %s",setupfilename);
2068  MUNLOCK(ErrorMessageLock);
2069 #else
2070  MLOCK(ErrorMessageLock);
2071  MesPrint("Please increase SmallExtension in %s",setupfilename);
2072  MUNLOCK(ErrorMessageLock);
2073 #endif
2074  Terminate(-1);
2075  }
2076  }
2077  t = *ps1;
2078  s2 = S->sFill;
2079  m = s2;
2080  i = S->PolyWise;
2081  NCOPY(s2,t,i);
2082  i = w[1];
2083  NCOPY(s2,w,i);
2084  t = t + t[1];
2085  w = *ps1 + **ps1;
2086  while ( t < w ) *s2++ = *t++;
2087  *m = WORDDIF(s2,m);
2088  *ps1 = m;
2089  S->sFill = s2;
2090  if ( *m > AM.MaxTer/((LONG)sizeof(WORD)) ) {
2091  MLOCK(ErrorMessageLock);
2092  MesPrint("Term to complex after polynomial addition. MaxTermSize = %10l",
2093  AM.MaxTer/sizeof(WORD));
2094  MUNLOCK(ErrorMessageLock);
2095  Terminate(-1);
2096  }
2097  }
2098  return(1);
2099 }
2100 
2101 /*
2102  #] AddPoly :
2103  #[ AddArgs : VOID AddArgs(arg1,arg2,to)
2104 */
2105 
2106 #define INSLENGTH(x) w[1] = FUNHEAD+ARGHEAD+x; w[FUNHEAD] = ARGHEAD+x;
2107 
2115 VOID AddArgs(PHEAD WORD *s1, WORD *s2, WORD *m)
2116 {
2117  GETBIDENTITY
2118  WORD i1, i2;
2119  WORD *w = m, *mm, *t, *t1, *t2, *tstop1, *tstop2;
2120  WORD tempterm[8+FUNHEAD];
2121 
2122  *m++ = AR.PolyFun; *m++ = 0; FILLFUN(m)
2123  *m++ = 0; *m++ = 0; FILLARG(m)
2124  if ( s1[FUNHEAD] < 0 || s2[FUNHEAD] < 0 ) {
2125  if ( s1[FUNHEAD] < 0 ) {
2126  if ( s2[FUNHEAD] < 0 ) { /* Both are special */
2127  if ( s1[FUNHEAD] <= -FUNCTION ) {
2128  if ( s2[FUNHEAD] == s1[FUNHEAD] ) {
2129  *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
2130  FILLFUN(m)
2131  *m++ = 2; *m++ = 1; *m++ = 3;
2132  INSLENGTH(4+FUNHEAD)
2133  }
2134  else if ( s2[FUNHEAD] <= -FUNCTION ) {
2135  i1 = functions[-FUNCTION-s1[FUNHEAD]].commute != 0;
2136  i2 = functions[-FUNCTION-s2[FUNHEAD]].commute != 0;
2137  if ( ( !i1 && i2 ) || ( i1 == i2 && i1 > i2 ) ) {
2138  i1 = s2[FUNHEAD];
2139  s2[FUNHEAD] = s1[FUNHEAD];
2140  s1[FUNHEAD] = i1;
2141  }
2142  *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
2143  FILLFUN(m)
2144  *m++ = 1; *m++ = 1; *m++ = 3;
2145  *m++ = 4+FUNHEAD; *m++ = -s2[FUNHEAD]; *m++ = FUNHEAD;
2146  FILLFUN(m)
2147  *m++ = 1; *m++ = 1; *m++ = 3;
2148  INSLENGTH(8+2*FUNHEAD)
2149  }
2150  else if ( s2[FUNHEAD] == -SYMBOL ) {
2151  *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s2[FUNHEAD+1]; *m++ = 1;
2152  *m++ = 1; *m++ = 1; *m++ = 3;
2153  *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
2154  FILLFUN(m)
2155  *m++ = 1; *m++ = 1; *m++ = 3;
2156  INSLENGTH(12+FUNHEAD)
2157  }
2158  else { /* number */
2159  *m++ = 4;
2160  *m++ = ABS(s2[FUNHEAD+1]); *m++ = 1; *m++ = s2[FUNHEAD+1] < 0 ? -3: 3;
2161  *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
2162  FILLFUN(m)
2163  *m++ = 1; *m++ = 1; *m++ = 3;
2164  INSLENGTH(8+FUNHEAD)
2165  }
2166  }
2167  else if ( s1[FUNHEAD] == -SYMBOL ) {
2168  if ( s2[FUNHEAD] == s1[FUNHEAD] ) {
2169  if ( s1[FUNHEAD+1] == s2[FUNHEAD+1] ) {
2170  *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s1[FUNHEAD+1];
2171  *m++ = 1; *m++ = 2; *m++ = 1; *m++ = 3;
2172  INSLENGTH(8)
2173  }
2174  else {
2175  if ( s1[FUNHEAD+1] > s2[FUNHEAD+1] )
2176  { i1 = s2[FUNHEAD+1]; i2 = s1[FUNHEAD+1]; }
2177  else { i1 = s1[FUNHEAD+1]; i2 = s2[FUNHEAD+1]; }
2178  *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = i1;
2179  *m++ = 1; *m++ = 1; *m++ = 1; *m++ = 3;
2180  *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = i2;
2181  *m++ = 1; *m++ = 1; *m++ = 1; *m++ = 3;
2182  INSLENGTH(16)
2183  }
2184  }
2185  else if ( s2[FUNHEAD] <= -FUNCTION ) {
2186  *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s1[FUNHEAD+1]; *m++ = 1;
2187  *m++ = 1; *m++ = 1; *m++ = 3;
2188  *m++ = 4+FUNHEAD; *m++ = -s2[FUNHEAD]; *m++ = FUNHEAD;
2189  FILLFUN(m)
2190  *m++ = 1; *m++ = 1; *m++ = 3;
2191  INSLENGTH(12+FUNHEAD)
2192  }
2193  else {
2194  *m++ = 4;
2195  *m++ = ABS(s2[FUNHEAD+1]); *m++ = 1; *m++ = s2[FUNHEAD+1] < 0 ? -3: 3;
2196  *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s1[FUNHEAD+1]; *m++ = 1;
2197  *m++ = 1; *m++ = 1; *m++ = 3;
2198  INSLENGTH(12)
2199  }
2200  }
2201  else { /* Must be -SNUMBER! */
2202  if ( s2[FUNHEAD] <= -FUNCTION ) {
2203  *m++ = 4;
2204  *m++ = ABS(s1[FUNHEAD+1]); *m++ = 1; *m++ = s1[FUNHEAD+1] < 0 ? -3: 3;
2205  *m++ = 4+FUNHEAD; *m++ = -s2[FUNHEAD]; *m++ = FUNHEAD;
2206  FILLFUN(m)
2207  *m++ = 1; *m++ = 1; *m++ = 3;
2208  INSLENGTH(8+FUNHEAD)
2209  }
2210  else if ( s2[FUNHEAD] == -SYMBOL ) {
2211  *m++ = 4;
2212  *m++ = ABS(s1[FUNHEAD+1]); *m++ = 1; *m++ = s1[FUNHEAD+1] < 0 ? -3: 3;
2213  *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s2[FUNHEAD+1]; *m++ = 1;
2214  *m++ = 1; *m++ = 1; *m++ = 3;
2215  INSLENGTH(12)
2216  }
2217  else { /* Both are numbers. add. */
2218  LONG x1;
2219  x1 = (LONG)s1[FUNHEAD+1] + (LONG)s2[FUNHEAD+1];
2220  if ( x1 < 0 ) { i1 = (WORD)(-x1); i2 = -3; }
2221  else { i1 = (WORD)x1; i2 = 3; }
2222  if ( x1 && AN.ncmod != 0 ) {
2223  m[0] = 4;
2224  m[1] = i1;
2225  m[2] = 1;
2226  m[3] = i2;
2227  if ( Modulus(m) ) Terminate(-1);
2228  if ( *m == 0 ) w[1] = 0;
2229  else {
2230  if ( *m == 4 && ( m[1] & MAXPOSITIVE ) == m[1]
2231  && m[3] == 3 ) {
2232  i1 = m[1];
2233  m -= ARGHEAD;
2234  *m++ = -SNUMBER;
2235  *m++ = i1;
2236  INSLENGTH(4)
2237  }
2238  else {
2239  INSLENGTH(*m)
2240  m += *m;
2241  }
2242  }
2243  }
2244  else {
2245  if ( x1 == 0 ) {
2246  w[1] = FUNHEAD;
2247  }
2248  else if ( ( i1 & MAXPOSITIVE ) == i1 ) {
2249  m -= ARGHEAD;
2250  *m++ = -SNUMBER;
2251  *m++ = (WORD)x1;
2252  w[1] = FUNHEAD+2;
2253  }
2254  else {
2255  *m++ = 4; *m++ = i1; *m++ = 1; *m++ = i2;
2256  INSLENGTH(4)
2257  }
2258  }
2259  }
2260  }
2261  }
2262  else { /* Only s1 is special */
2263 s1only:
2264 /*
2265  Compose a term in `tempterm'
2266 */
2267  t = tempterm;
2268  if ( s1[FUNHEAD] <= -FUNCTION ) {
2269  *t++ = 4+FUNHEAD; *t++ = -s1[FUNHEAD]; *t++ = FUNHEAD;
2270  FILLFUN(t)
2271  *t++ = 1; *t++ = 1; *t++ = 3;
2272  }
2273  else if ( s1[FUNHEAD] == -SYMBOL ) {
2274  *t++ = 8; *t++ = SYMBOL; *t++ = 4;
2275  *t++ = s1[FUNHEAD+1]; *t++ = 1;
2276  *t++ = 1; *t++ = 1; *t++ = 3;
2277  }
2278  else {
2279  *t++ = 4; *t++ = ABS(s1[FUNHEAD+1]);
2280  *t++ = 1; *t++ = s1[FUNHEAD+1] < 0 ? -3: 3;
2281  }
2282  tstop1 = t;
2283  s1 = tempterm;
2284  goto twogen;
2285  }
2286  }
2287  else { /* Only s2 is special */
2288  t = s1;
2289  s1 = s2;
2290  s2 = t;
2291  goto s1only;
2292  }
2293  }
2294  else {
2295  tstop1 = s1 + s1[1];
2296  s1 += FUNHEAD+ARGHEAD;
2297 twogen:
2298  tstop2 = s2 + s2[1];
2299  s2 += FUNHEAD+ARGHEAD;
2300 /*
2301  Now we should merge the expressions in s1 and s2 into m.
2302 */
2303  AT.SS->PolyFlag = 0;
2304  while ( s1 < tstop1 && s2 < tstop2 ) {
2305  i1 = CompareTerms(BHEAD s1,s2,(WORD)(-1));
2306  if ( i1 > 0 ) {
2307  i2 = *s1;
2308  NCOPY(m,s1,i2);
2309  }
2310  else if ( i1 < 0 ) {
2311  i2 = *s2;
2312  NCOPY(m,s2,i2);
2313  }
2314  else { /* Coefficients should be added. */
2315  WORD i;
2316  t = s1+*s1;
2317  i1 = t[-1];
2318  i2 = *s1 - ABS(i1);
2319  t2 = s2 + i2;
2320  s2 += *s2;
2321  mm = m;
2322  NCOPY(m,s1,i2);
2323  t1 = s1;
2324  s1 = t;
2325  i2 = s2[-1];
2326 /*
2327  t1,i1 is the first coefficient
2328  t2,i2 is the second coefficient
2329  It should be placed at m,i1
2330 */
2331  i1 = REDLENG(i1);
2332  i2 = REDLENG(i2);
2333  if ( AddRat(BHEAD (UWORD *)t1,i1,(UWORD *)t2,i2,(UWORD *)m,&i) ) {
2334  MLOCK(ErrorMessageLock);
2335  MesPrint("Addition of coefficients of PolyFun");
2336  MUNLOCK(ErrorMessageLock);
2337  Terminate(-1);
2338  }
2339  if ( i == 0 ) {
2340  m = mm;
2341  }
2342  else {
2343  i1 = INCLENG(i);
2344  m += ABS(i1);
2345  m[-1] = i1;
2346  *mm = WORDDIF(m,mm);
2347  if ( AN.ncmod != 0 ) {
2348  if ( Modulus(mm) ) Terminate(-1);
2349  if ( !*mm ) m = mm;
2350  else m = mm + *mm;
2351  }
2352  }
2353  }
2354  }
2355  while ( s1 < tstop1 ) *m++ = *s1++;
2356  while ( s2 < tstop2 ) *m++ = *s2++;
2357  w[1] = WORDDIF(m,w);
2358  w[FUNHEAD] = w[1] - FUNHEAD;
2359  if ( ToFast(w+FUNHEAD,w+FUNHEAD) ) {
2360  if ( w[FUNHEAD] <= -FUNCTION ) w[1] = FUNHEAD+1;
2361  else w[1] = FUNHEAD+2;
2362  if ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) w[1] = FUNHEAD;
2363  }
2364  AT.SS->PolyFlag = AR.PolyFunType;
2365  }
2366 }
2367 
2368 /*
2369  #] AddArgs :
2370  #[ Compare1 : WORD Compare1(term1,term2,level)
2371 */
2397 WORD Compare1(PHEAD WORD *term1, WORD *term2, WORD level)
2398 {
2399  GETBIDENTITY
2400  SORTING *S = AT.SS;
2401  WORD *stopper1, *stopper2, *t2;
2402  WORD *s1, *s2, *t1;
2403  WORD *stopex1, *stopex2;
2404  WORD c1, c2;
2405  WORD prevorder;
2406  WORD count = -1, localPoly, polyhit = -1;
2407 
2408  if ( S->PolyFlag ) {
2409 /*
2410  if ( S->PolyWise != 0 ) {
2411  MLOCK(ErrorMessageLock);
2412  MesPrint("S->PolyWise is not zero!!!!!");
2413  MUNLOCK(ErrorMessageLock);
2414  }
2415 */
2416  count = 0; localPoly = 1; S->PolyWise = polyhit = 0;
2417  S->PolyFlag = AR.PolyFunType;
2418  }
2419  else { localPoly = 0; }
2420  prevorder = 0;
2421  GETSTOP(term1,s1);
2422  stopper1 = s1;
2423  GETSTOP(term2,stopper2);
2424  t1 = term1 + 1;
2425  t2 = term2 + 1;
2426  while ( t1 < stopper1 && t2 < stopper2 ) {
2427  if ( *t1 != *t2 ) {
2428  if ( *t1 == HAAKJE ) return(PREV(-1));
2429  if ( *t2 == HAAKJE ) return(PREV(1));
2430  if ( *t1 >= (FUNCTION-1) ) {
2431  if ( *t2 < (FUNCTION-1) ) return(PREV(-1));
2432  if ( *t1 < FUNCTION && *t2 < FUNCTION ) return(PREV(*t2-*t1));
2433  if ( *t1 < FUNCTION ) return(PREV(1));
2434  if ( *t2 < FUNCTION ) return(PREV(-1));
2435  c1 = functions[*t1-FUNCTION].commute;
2436  c2 = functions[*t2-FUNCTION].commute;
2437  if ( !c1 ) {
2438  if ( c2 ) return(PREV(1));
2439  else return(PREV(*t2-*t1));
2440  }
2441  else {
2442  if ( !c2 ) return(PREV(-1));
2443  else return(PREV(*t2-*t1));
2444  }
2445  }
2446  else return(PREV(*t2-*t1));
2447  }
2448  s1 = t1 + 2;
2449  s2 = t2 + 2;
2450  c1 = *t1;
2451  t1 += t1[1];
2452  t2 += t2[1];
2453  if ( localPoly && c1 < FUNCTION ) {
2454  polyhit = 1;
2455  }
2456  if ( c1 <= (FUNCTION-1)
2457  || ( c1 >= FUNCTION && functions[c1-FUNCTION].spec ) ) {
2458  if ( c1 == SYMBOL ) {
2459  if ( *s1 == FACTORSYMBOL && *s2 == FACTORSYMBOL
2460  && s1[-1] == 4 && s2[-1] == 4
2461  && ( ( t1 < stopper1 && *t1 == HAAKJE )
2462  || ( t1 == stopper1 && AT.fromindex ) ) ) {
2463 /*
2464  We have to be very careful with the criteria here, because
2465  Compare1 is called both in the regular sorting and by the
2466  routine that makes the bracket index. In the last case
2467  there is no HAAKJE subterm.
2468 */
2469  if ( s1[1] != s2[1] ) return(s2[1]-s1[1]);
2470  s1 += 2; s2 += 2;
2471  }
2472  else if ( AR.SortType >= SORTPOWERFIRST ) {
2473  WORD i1 = 0, *r1;
2474  r1 = s1;
2475  while ( s1 < t1 ) { i1 += s1[1]; s1 += 2; }
2476  s1 = r1; r1 = s2;
2477  while ( s2 < t2 ) { i1 -= s2[1]; s2 += 2; }
2478  s2 = r1;
2479  if ( i1 ) {
2480  if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
2481  return(PREV(i1));
2482  }
2483  }
2484  while ( s1 < t1 ) {
2485  if ( s2 >= t2 ) {
2486 /* return(PREV(1)); */
2487  if ( AR.SortType==SORTLOWFIRST ) {
2488  return(PREV((s1[1]>0?-1:1)));
2489  }
2490  else {
2491  return(PREV((s1[1]<0?-1:1)));
2492  }
2493  }
2494  if ( *s1 != *s2 ) {
2495 /* return(PREV(*s2-*s1)); */
2496  if ( AR.SortType==SORTLOWFIRST ) {
2497  if ( *s1 < *s2 ) {
2498  return(PREV((s1[1]<0?1:-1)));
2499  }
2500  else {
2501  return(PREV((s2[1]<0?-1:1)));
2502  }
2503  }
2504  else {
2505  if ( *s1 < *s2 ) {
2506  return(PREV((s1[1]<0?-1:1)));
2507  }
2508  else {
2509  return(PREV((s2[1]<0?1:-1)));
2510  }
2511  }
2512  }
2513  s1++; s2++;
2514  if ( *s1 != *s2 ) return(
2515  PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
2516  s1++; s2++;
2517  }
2518  if ( s2 < t2 ) {
2519 /* return(PREV(-1)); */
2520  if ( AR.SortType==SORTLOWFIRST ) {
2521  return(PREV((s2[1]<0?-1:1)));
2522  }
2523  else {
2524  return(PREV((s2[1]<0?1:-1)));
2525  }
2526  }
2527  }
2528  else if ( c1 == DOTPRODUCT ) {
2529  if ( AR.SortType >= SORTPOWERFIRST ) {
2530  WORD i1 = 0, *r1;
2531  r1 = s1;
2532  while ( s1 < t1 ) { i1 += s1[2]; s1 += 3; }
2533  s1 = r1; r1 = s2;
2534  while ( s2 < t2 ) { i1 -= s2[2]; s2 += 3; }
2535  s2 = r1;
2536  if ( i1 ) {
2537  if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
2538  return(PREV(i1));
2539  }
2540  }
2541  while ( s1 < t1 ) {
2542  if ( s2 >= t2 ) return(PREV(1));
2543  if ( *s1 != *s2 ) return(PREV(*s2-*s1));
2544  s1++; s2++;
2545  if ( *s1 != *s2 ) return(PREV(*s2-*s1));
2546  s1++; s2++;
2547  if ( *s1 != *s2 ) return(
2548  PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
2549  s1++; s2++;
2550  }
2551  if ( s2 < t2 ) return(PREV(-1));
2552  }
2553  else {
2554  while ( s1 < t1 ) {
2555  if ( s2 >= t2 ) return(PREV(1));
2556  if ( *s1 != *s2 ) return(PREV(*s2-*s1));
2557  s1++; s2++;
2558  }
2559  if ( s2 < t2 ) return(PREV(-1));
2560  }
2561  }
2562  else {
2563 #if FUNHEAD != 2
2564  s1 += FUNHEAD-2;
2565  s2 += FUNHEAD-2;
2566 #endif
2567  if ( localPoly && c1 == AR.PolyFun ) {
2568  if ( count == 0 ) {
2569  if ( AR.PolyFunType == 1 ) {
2570  WORD i1, i2;
2571  if ( *s1 > 0 ) i1 = *s1;
2572  else if ( *s1 <= -FUNCTION ) i1 = 1;
2573  else i1 = 2;
2574  if ( *s2 > 0 ) i2 = *s2;
2575  else if ( *s2 <= -FUNCTION ) i2 = 1;
2576  else i2 = 2;
2577  if ( s1+i1 == t1 && s2+i2 == t2 ) { /* This is the stuff */
2578 /*
2579  Test for scalar nature
2580 */
2581  if ( !polyhit ) {
2582  WORD *u1, *u2, *ustop;
2583  if ( *s1 < 0 ) {
2584  if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
2585  goto NoPoly;
2586  }
2587  else {
2588  u1 = s1 + ARGHEAD;
2589  while ( u1 < t1 ) {
2590  u2 = u1 + *u1;
2591  ustop = u2 - ABS(u2[-1]);
2592  u1++;
2593  while ( u1 < ustop ) {
2594  if ( *u1 == INDEX ) goto NoPoly;
2595  u1 += u1[1];
2596  }
2597  u1 = u2;
2598  }
2599  }
2600  if ( *s2 < 0 ) {
2601  if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
2602  goto NoPoly;
2603  }
2604  else {
2605  u1 = s2 + ARGHEAD;
2606  while ( u1 < t2 ) {
2607  u2 = u1 + *u1;
2608  ustop = u2 - ABS(u2[-1]);
2609  u1++;
2610  while ( u1 < ustop ) {
2611  if ( *u1 == INDEX ) goto NoPoly;
2612  u1 += u1[1];
2613  }
2614  u1 = u2;
2615  }
2616  }
2617  }
2618  S->PolyWise = WORDDIF(s1,term1);
2619  S->PolyWise -= FUNHEAD;
2620  count = 1;
2621  continue;
2622  }
2623  else {
2624 NoPoly:
2625  S->PolyWise = localPoly = 0;
2626  }
2627  }
2628  else if ( AR.PolyFunType == 2 ) {
2629  WORD i1, i2, i1a, i2a;
2630  if ( *s1 > 0 ) i1 = *s1;
2631  else if ( *s1 <= -FUNCTION ) i1 = 1;
2632  else i1 = 2;
2633  if ( *s2 > 0 ) i2 = *s2;
2634  else if ( *s2 <= -FUNCTION ) i2 = 1;
2635  else i2 = 2;
2636  if ( s1[i1] > 0 ) i1a = s1[i1];
2637  else if ( s1[i1] <= -FUNCTION ) i1a = 1;
2638  else i1a = 2;
2639  if ( s2[i2] > 0 ) i2a = s2[i2];
2640  else if ( s2[i2] <= -FUNCTION ) i2a = 1;
2641  else i2a = 2;
2642  if ( s1+i1+i1a == t1 && s2+i2+i2a == t2 ) { /* This is the stuff */
2643 /*
2644  Test for scalar nature
2645 */
2646  if ( !polyhit ) {
2647  WORD *u1, *u2, *ustop;
2648  if ( *s1 < 0 ) {
2649  if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
2650  goto NoPoly;
2651  }
2652  else {
2653  u1 = s1 + ARGHEAD;
2654  while ( u1 < s1+i1 ) {
2655  u2 = u1 + *u1;
2656  ustop = u2 - ABS(u2[-1]);
2657  u1++;
2658  while ( u1 < ustop ) {
2659  if ( *u1 == INDEX ) goto NoPoly;
2660  u1 += u1[1];
2661  }
2662  u1 = u2;
2663  }
2664  }
2665  if ( s1[i1] < 0 ) {
2666  if ( s1[i1] != -SNUMBER && s1[i1] != -SYMBOL && s1[i1] > -FUNCTION )
2667  goto NoPoly;
2668  }
2669  else {
2670  u1 = s1 +i1 + ARGHEAD;
2671  while ( u1 < t1 ) {
2672  u2 = u1 + *u1;
2673  ustop = u2 - ABS(u2[-1]);
2674  u1++;
2675  while ( u1 < ustop ) {
2676  if ( *u1 == INDEX ) goto NoPoly;
2677  u1 += u1[1];
2678  }
2679  u1 = u2;
2680  }
2681  }
2682  if ( *s2 < 0 ) {
2683  if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
2684  goto NoPoly;
2685  }
2686  else {
2687  u1 = s2 + ARGHEAD;
2688  while ( u1 < s2+i2 ) {
2689  u2 = u1 + *u1;
2690  ustop = u2 - ABS(u2[-1]);
2691  u1++;
2692  while ( u1 < ustop ) {
2693  if ( *u1 == INDEX ) goto NoPoly;
2694  u1 += u1[1];
2695  }
2696  u1 = u2;
2697  }
2698  }
2699  if ( s2[i2] < 0 ) {
2700  if ( s2[i2] != -SNUMBER && s2[i2] != -SYMBOL && s2[i2] > -FUNCTION )
2701  goto NoPoly;
2702  }
2703  else {
2704  u1 = s2 + i2 + ARGHEAD;
2705  while ( u1 < t2 ) {
2706  u2 = u1 + *u1;
2707  ustop = u2 - ABS(u2[-1]);
2708  u1++;
2709  while ( u1 < ustop ) {
2710  if ( *u1 == INDEX ) goto NoPoly;
2711  u1 += u1[1];
2712  }
2713  u1 = u2;
2714  }
2715  }
2716  }
2717  S->PolyWise = WORDDIF(s1,term1);
2718  S->PolyWise -= FUNHEAD;
2719  count = 1;
2720  continue;
2721  }
2722  else {
2723  S->PolyWise = localPoly = 0;
2724  }
2725  }
2726  else {
2727  S->PolyWise = localPoly = 0;
2728  }
2729  }
2730  else {
2731  t1 = term1 + S->PolyWise;
2732  t2 = term2 + S->PolyWise;
2733  S->PolyWise = 0;
2734  localPoly = 0;
2735  continue;
2736  }
2737  }
2738  while ( s1 < t1 ) {
2739 /*
2740  The next statement was added 9-nov-2001. It made a bad error
2741 */
2742  if ( s2 >= t2 ) return(PREV(-1));
2743 /*
2744  There is a little problem here with fast arguments
2745  We don't want to sacrifice speed, but we like to
2746  keep a rational ordering. This last one suffers in
2747  the solution that has been choosen here.
2748 */
2749  if ( AC.properorderflag ) {
2750  if ( ( c2 = -CompArg(s1,s2) ) != 0 ) return(PREV(c2));
2751  NEXTARG(s1)
2752  NEXTARG(s2)
2753  }
2754  else {
2755  if ( *s1 > 0 ) {
2756  if ( *s2 > 0 ) {
2757  stopex1 = s1 + *s1;
2758  if ( s2 >= t2 ) return(PREV(-1));
2759  stopex2 = s2 + *s2;
2760  s1 += ARGHEAD; s2 += ARGHEAD;
2761  while ( s1 < stopex1 ) {
2762  if ( s2 >= stopex2 ) return(PREV(-1));
2763  if ( ( c2 = CompareTerms(BHEAD s1,s2,(WORD)1) ) != 0 )
2764  return(PREV(c2));
2765  s1 += *s1;
2766  s2 += *s2;
2767  }
2768  if ( s2 < stopex2 ) return(PREV(1));
2769  }
2770  else return(PREV(1));
2771  }
2772  else {
2773  if ( *s2 > 0 ) return(PREV(-1));
2774  if ( *s1 != *s2 ) { return(PREV(*s1-*s2)); }
2775  if ( *s1 > -FUNCTION ) {
2776  if ( *++s1 != *++s2 ) { return(PREV(*s2-*s1)); }
2777  }
2778  s1++; s2++;
2779  }
2780  }
2781  }
2782  if ( s2 < t2 ) return(PREV(1));
2783  }
2784  }
2785  {
2786  if ( AR.SortType != SORTLOWFIRST ) {
2787  if ( t1 < stopper1 ) return(PREV(1));
2788  if ( t2 < stopper2 ) return(PREV(-1));
2789  }
2790  else {
2791  if ( t1 < stopper1 ) return(PREV(-1));
2792  if ( t2 < stopper2 ) return(PREV(1));
2793  }
2794  }
2795  if ( level == 3 ) return(CompCoef(term1,term2));
2796  if ( level >= 1 )
2797  return(CompCoef(term2,term1));
2798  return(0);
2799 }
2800 
2801 /*
2802  #] Compare1 :
2803  #[ CompareSymbols : int CompareSymbols(term1,term2,par)
2804 */
2818 int CompareSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
2819 {
2820  int sum1, sum2;
2821  WORD *t1, *t2, *tt1, *tt2;
2822  DUMMYUSE(par);
2823  t1 = term1 + 1; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); t1 += 2;
2824  t2 = term2 + 1; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); t2 += 2;
2825  if ( AN.polysortflag > 0 ) {
2826  sum1 = 0; sum2 = 0;
2827  while ( t1 < tt1 ) { sum1 += t1[1]; t1 += 2; }
2828  while ( t2 < tt2 ) { sum2 += t2[1]; t2 += 2; }
2829  if ( sum1 < sum2 ) return(-1);
2830  if ( sum1 > sum2 ) return(1);
2831  t1 = term1+3; t2 = term2 + 3;
2832  }
2833  while ( t1 < tt1 && t2 < tt2 ) {
2834  if ( *t1 > *t2 ) return(-1);
2835  if ( *t1 < *t2 ) return(1);
2836  if ( t1[1] < t2[1] ) return(-1);
2837  if ( t1[1] > t2[1] ) return(1);
2838  t1 += 2; t2 += 2;
2839  }
2840  if ( t1 < tt1 ) return(1);
2841  if ( t2 < tt2 ) return(-1);
2842  return(0);
2843 }
2844 
2845 /*
2846  #] CompareSymbols :
2847  #[ ComPress : LONG ComPress(ss,n)
2848 */
2867 LONG ComPress(WORD **ss, LONG *n)
2868 {
2869  GETIDENTITY
2870  WORD *t, *s, j, k;
2871  LONG size = 0;
2872  int newsize, i;
2873 /*
2874  #[ debug :
2875 
2876  WORD **sss = ss;
2877 
2878  if ( AP.DebugFlag ) {
2879  UBYTE OutBuf[140];
2880  MLOCK(ErrorMessageLock);
2881  MesPrint("ComPress:");
2882  AO.OutFill = AO.OutputLine = OutBuf;
2883  AO.OutSkip = 3;
2884  FiniLine();
2885  ss = sss;
2886  while ( *ss ) {
2887  s = *ss++;
2888  j = *s;
2889  if ( j < 0 ) {
2890  j = s[1] + 2;
2891  }
2892  while ( --j >= 0 ) {
2893  TalToLine((UWORD)(*s++)); TokenToLine((UBYTE *)" ");
2894  }
2895  FiniLine();
2896  }
2897  AO.OutSkip = 0;
2898  FiniLine();
2899  MUNLOCK(ErrorMessageLock);
2900  ss = sss;
2901  }
2902 
2903  #] debug :
2904 */
2905  *n = 0;
2906  if ( AT.SS == AT.S0 && !AR.NoCompress ) {
2907  if ( AN.compressSize == 0 ) {
2908  if ( *ss ) { AN.compressSize = **ss + 64; }
2909  else { AN.compressSize = AM.MaxTer/sizeof(WORD) + 2; }
2910  AN.compressSpace = (WORD *)Malloc1(AN.compressSize*sizeof(WORD),"Compression");
2911  }
2912  AN.compressSpace[0] = 0;
2913  while ( *ss ) {
2914  k = 0;
2915  s = *ss;
2916  j = *s++;
2917  if ( j > AN.compressSize ) {
2918  newsize = j + 64;
2919  t = (WORD *)Malloc1(newsize*sizeof(WORD),"Compression");
2920  t[0] = 0;
2921  if ( AN.compressSpace ) {
2922  for ( i = 0; i < *AN.compressSpace; i++ ) t[i] = AN.compressSpace[i];
2923  M_free(AN.compressSpace,"Compression");
2924  }
2925  AN.compressSpace = t;
2926  AN.compressSize = newsize;
2927  }
2928  t = AN.compressSpace;
2929  i = *t - 1;
2930  *t++ = j; j--;
2931  if ( AR.PolyFun ) {
2932  WORD *polystop, *sa;
2933  sa = s + j;
2934  sa -= ABS(sa[-1]);
2935  polystop = s;
2936  while ( polystop < sa && *polystop != AR.PolyFun ) {
2937  polystop += polystop[1];
2938  }
2939  while ( i > 0 && j > 0 && *s == *t && s < polystop ) {
2940  i--; j--; s++; t++; k--;
2941  }
2942  }
2943  else {
2944  WORD *sa;
2945  sa = s + j;
2946  sa -= ABS(sa[-1]);
2947  while ( i > 0 && j > 0 && *s == *t && s < sa ) { i--; j--; s++; t++; k--; }
2948  }
2949  if ( k < -1 ) {
2950  s[-1] = j;
2951  s[-2] = k;
2952  *ss = s-2;
2953  size += j + 2;
2954  }
2955  else {
2956  size += *AN.compressSpace;
2957  if ( k == -1 ) { t--; s--; j++; }
2958  }
2959  while ( --j >= 0 ) *t++ = *s++;
2960 /* Sabotage getting into the coefficient next time */
2961  t = AN.compressSpace + *AN.compressSpace;
2962  t[-(ABS(t[-1]))] = 0;
2963  ss++;
2964  (*n)++;
2965  }
2966  }
2967  else {
2968  while ( *ss ) {
2969  size += *(*ss++);
2970  (*n)++;
2971  }
2972  }
2973 /*
2974  #[ debug :
2975 
2976  if ( AP.DebugFlag ) {
2977  UBYTE OutBuf[140];
2978  AO.OutFill = AO.OutputLine = OutBuf;
2979  AO.OutSkip = 3;
2980  FiniLine();
2981  ss = sss;
2982  while ( *ss ) {
2983  s = *ss++;
2984  j = *s;
2985  if ( j < 0 ) {
2986  j = s[1] + 2;
2987  }
2988  while ( --j >= 0 ) {
2989  TalToLine((UWORD)(*s++)); TokenToLine((UBYTE *)" ");
2990  }
2991  FiniLine();
2992  }
2993  AO.OutSkip = 0;
2994  FiniLine();
2995  }
2996 
2997  #] debug :
2998 */
2999  return(size);
3000 }
3001 
3002 /*
3003  #] ComPress :
3004  #[ SplitMerge : VOID SplitMerge(Point,number)
3005 */
3031 #ifdef NEWSPLITMERGE
3032 
3033 LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
3034 {
3035  GETBIDENTITY
3036  SORTING *S = AT.SS;
3037  WORD **pp3, **pp1, **pp2;
3038  LONG nleft, nright, i, newleft, newright;
3039  WORD **pptop;
3040 
3041  if ( number < 2 ) return(number);
3042  if ( number == 2 ) {
3043  pp1 = Pointer; pp2 = pp1 + 1;
3044  if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
3045  pp3 = (WORD **)(*pp1); *pp1 = *pp2; *pp2 = (WORD *)pp3;
3046  }
3047  else if ( i == 0 ) {
3048  number--;
3049  if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) == 0 ) { number = 0; } }
3050  else { if ( AddCoef(BHEAD pp1,pp2) == 0 ) { number = 0; } }
3051  }
3052  return(number);
3053  }
3054  pptop = Pointer + number;
3055  nleft = number >> 1; nright = number - nleft;
3056  newleft = SplitMerge(BHEAD Pointer,nleft);
3057  newright = SplitMerge(BHEAD Pointer+nleft,nright);
3058 /*
3059  We compare the last of the left with the first of the right
3060  If they are already in order, we will be done quickly.
3061  We may have to compactify the buffer because the recursion may
3062  have created holes. Also this compare may result in equal terms.
3063  Addition of 23-jul-1999. It makes things a bit faster.
3064 */
3065  if ( newleft > 0 && newright > 0 &&
3066  ( i = CompareTerms(BHEAD Pointer[newleft-1],Pointer[nleft],(WORD)0) ) >= 0 ) {
3067  pp2 = Pointer+nleft; pp1 = Pointer+newleft-1;
3068  if ( i == 0 ) {
3069  if ( S->PolyWise ) {
3070  if ( AddPoly(BHEAD pp1,pp2) > 0 ) pp1++;
3071  else newleft--;
3072  }
3073  else {
3074  if ( AddCoef(BHEAD pp1,pp2) > 0 ) pp1++;
3075  else newleft--;
3076  }
3077  *pp2++ = 0; newright--;
3078  }
3079  else pp1++;
3080  newleft += newright;
3081  if ( pp1 < pp2 ) {
3082  while ( --newright >= 0 ) *pp1++ = *pp2++;
3083  while ( pp1 < pptop ) *pp1++ = 0;
3084  }
3085  return(newleft);
3086  }
3087  if ( nleft > AN.SplitScratchSize ) {
3088  AN.SplitScratchSize = (nleft*3)/2+100;
3089  if ( AN.SplitScratchSize > S->Terms2InSmall/2 )
3090  AN.SplitScratchSize = S->Terms2InSmall/2;
3091  if ( AN.SplitScratch ) M_free(AN.SplitScratch,"AN.SplitScratch");
3092  AN.SplitScratch = (WORD **)Malloc1(AN.SplitScratchSize*sizeof(WORD *),"AN.SplitScratch");
3093  }
3094  pp3 = AN.SplitScratch; pp1 = Pointer; i = nleft;
3095  do { *pp3++ = *pp1; *pp1++ = 0; } while ( *pp1 && --i > 0 );
3096  if ( i > 0 ) { *pp3 = 0; i--; }
3097  AN.InScratch = nleft - i;
3098  pp1 = AN.SplitScratch; pp2 = Pointer + nleft; pp3 = Pointer;
3099  while ( nleft > 0 && nright > 0 && *pp1 && *pp2 ) {
3100  if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
3101  *pp3++ = *pp2;
3102  *pp2++ = 0;
3103  nright--;
3104  }
3105  else if ( i > 0 ) {
3106  *pp3++ = *pp1;
3107  *pp1++ = 0;
3108  nleft--;
3109  }
3110  else {
3111  if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3112  else { if ( AddCoef(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3113  *pp1++ = 0; *pp2++ = 0; nleft--; nright--;
3114  }
3115  }
3116  while ( --nleft >= 0 && *pp1 ) { *pp3++ = *pp1; *pp1++ = 0; }
3117  while ( --nright >= 0 && *pp2 ) { *pp3++ = *pp2++; }
3118  nleft = pp3 - Pointer;
3119  while ( pp3 < pptop ) *pp3++ = 0;
3120  AN.InScratch = 0;
3121  return(nleft);
3122 }
3123 
3124 #else
3125 
3126 VOID SplitMerge(PHEAD WORD **Pointer, LONG number)
3127 {
3128  GETBIDENTITY
3129  SORTING *S = AT.SS;
3130  WORD **pp3, **pp1, **pp2;
3131  LONG nleft, nright, i;
3132  WORD **pptop;
3133 
3134  if ( number < 2 ) return;
3135  if ( number == 2 ) {
3136  pp1 = Pointer; pp2 = pp1 + 1;
3137  if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
3138  pp3 = (WORD **)(*pp1); *pp1 = *pp2; *pp2 = (WORD *)pp3;
3139  }
3140  else if ( i == 0 ) {
3141  if ( S->PolyWise ) { if ( !AddPoly(BHEAD pp1,pp2) ) { *pp1 = 0; } }
3142  else { if ( !AddCoef(BHEAD pp1,pp2) ) { *pp1 = 0; } }
3143  *pp2 = 0;
3144  }
3145  return;
3146  }
3147  pptop = Pointer + number;
3148  nleft = number >> 1; nright = number - nleft;
3149  SplitMerge(BHEAD Pointer,nleft);
3150  SplitMerge(BHEAD Pointer+nleft,nright);
3151  if ( nleft > AN.SplitScratchSize ) {
3152  AN.SplitScratchSize = (nleft*3)/2+100;
3153  if ( AN.SplitScratchSize > S->Terms2InSmall/2 )
3154  AN.SplitScratchSize = S->Terms2InSmall/2;
3155  if ( AN.SplitScratch ) M_free(AN.SplitScratch,"AN.SplitScratch");
3156  AN.SplitScratch = (WORD **)Malloc1(AN.SplitScratchSize*sizeof(WORD *),"AN.SplitScratch");
3157  }
3158  pp3 = AN.SplitScratch; pp1 = Pointer; i = nleft;
3159  do { *pp3++ = *pp1; *pp1++ = 0; } while ( *pp1 && --i > 0 );
3160  if ( i > 0 ) { *pp3 = 0; i--; }
3161  AN.InScratch = nleft - i;
3162  pp1 = AN.SplitScratch; pp2 = Pointer + nleft; pp3 = Pointer;
3163  while ( *pp1 && *pp2 && nleft > 0 && nright > 0 ) {
3164  if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
3165  *pp3++ = *pp2;
3166  *pp2++ = 0;
3167  nright--;
3168  }
3169  else if ( i > 0 ) {
3170  *pp3++ = *pp1;
3171  *pp1++ = 0;
3172  nleft--;
3173  }
3174  else {
3175  if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3176  else { if ( AddCoef(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3177  *pp1++ = 0; *pp2++ = 0; nleft--; nright--;
3178  }
3179  }
3180  while ( *pp1 && --nleft >= 0 ) { *pp3++ = *pp1; *pp1++ = 0; }
3181  while ( *pp2 && --nright >= 0 ) { *pp3++ = *pp2++; }
3182  while ( pp3 < pptop ) *pp3++ = 0;
3183  AN.InScratch = 0;
3184 
3185  return;
3186 }
3187 
3188 #endif
3189 
3190 /*
3191  #] SplitMerge :
3192  #[ GarbHand : VOID GarbHand()
3193 */
3209 VOID GarbHand()
3210 {
3211  GETIDENTITY
3212  SORTING *S = AT.SS;
3213  WORD **Point, *s2, *t, *garbuf, i;
3214  LONG k, total = 0;
3215  int tobereturned = 0;
3216 /*
3217  Compute the size needed. Put it in total.
3218 */
3219 #ifdef TESTGARB
3220  MLOCK(ErrorMessageLock);
3221  MesPrint("in: S->sFill = %x, S->sTop2 = %x",S->sFill,S->sTop2);
3222 #endif
3223  Point = S->sPointer;
3224  k = S->sTerms;
3225  while ( --k >= 0 ) {
3226  if ( ( s2 = *Point++ ) != 0 ) { total += *s2; }
3227  }
3228  Point = AN.SplitScratch;
3229  k = AN.InScratch;
3230  while ( --k >= 0 ) {
3231  if ( ( s2 = *Point++ ) != 0 ) { total += *s2; }
3232  }
3233 #ifdef TESTGARB
3234  MesPrint("total = %l, nterms = %l",2*total,AN.InScratch);
3235  MUNLOCK(ErrorMessageLock);
3236 #endif
3237 /*
3238  Test now whether it fits. If so deal with the problem inside
3239  the memory at the tail of the large buffer.
3240 */
3241  if ( S->lBuffer != 0 && S->lFill + total <= S->lTop ) {
3242  garbuf = S->lFill;
3243  }
3244  else {
3245  garbuf = (WORD *)Malloc1(total*sizeof(WORD),"Garbage buffer");
3246  tobereturned = 1;
3247  }
3248  t = garbuf;
3249  Point = S->sPointer;
3250  k = S->sTerms;
3251  while ( --k >= 0 ) {
3252  if ( *Point ) {
3253  s2 = *Point++;
3254  i = *s2;
3255  NCOPY(t,s2,i);
3256  }
3257  else { Point++; }
3258  }
3259  Point = AN.SplitScratch;
3260  k = AN.InScratch;
3261  while ( --k >= 0 ) {
3262  if ( *Point ) {
3263  s2 = *Point++;
3264  i = *s2;
3265  NCOPY(t,s2,i);
3266  }
3267  else Point++;
3268  }
3269  s2 = S->sBuffer;
3270  t = garbuf;
3271  Point = S->sPointer;
3272  k = S->sTerms;
3273  while ( --k >= 0 ) {
3274  if ( *Point ) {
3275  *Point++ = s2;
3276  i = *t;
3277  NCOPY(s2,t,i);
3278  }
3279  else { Point++; }
3280  }
3281  Point = AN.SplitScratch;
3282  k = AN.InScratch;
3283  while ( --k >= 0 ) {
3284  if ( *Point ) {
3285  *Point++ = s2;
3286  i = *t;
3287  NCOPY(s2,t,i);
3288  }
3289  else Point++;
3290  }
3291  S->sFill = s2;
3292 #ifdef TESTGARB
3293  MLOCK(ErrorMessageLock);
3294  MesPrint("out: S->sFill = %x, S->sTop2 = %x",S->sFill,S->sTop2);
3295  if ( S->sFill >= S->sTop2 ) {
3296  MesPrint("We are in deep trouble");
3297  }
3298  MUNLOCK(ErrorMessageLock);
3299 #endif
3300  if ( tobereturned ) M_free(garbuf,"Garbage buffer");
3301  return;
3302 }
3303 
3304 /*
3305  #] GarbHand :
3306  #[ MergePatches : WORD MergePatches(par)
3307 */
3324 WORD MergePatches(WORD par)
3325 {
3326  GETIDENTITY
3327  SORTING *S = AT.SS;
3328  WORD **poin, **poin2, ul, k, i, im, *m1;
3329  WORD *p, lpat, mpat, level, l1, l2, r1, r2, r3, c;
3330  WORD *m2, *m3, r31, r33, ki, *rr;
3331  UWORD *coef;
3332  POSITION position;
3333  FILEHANDLE *fin, *fout;
3334  int fhandle;
3335 /*
3336  UBYTE *s;
3337 */
3338 #ifdef WITHZLIB
3339  POSITION position2;
3340  int oldgzipCompress = AR.gzipCompress;
3341  if ( par == 2 ) {
3342  AR.gzipCompress = 0;
3343  }
3344 #endif
3345  fin = &S->file;
3346  fout = &(AR.FoStage4[0]);
3347  S->PolyFlag = AR.PolyFun ? AR.PolyFunType: 0;
3348 NewMerge:
3349  coef = AN.SoScratC;
3350  poin = S->poina; poin2 = S->poin2a;
3351  rr = AR.CompressPointer;
3352  *rr = 0;
3353 /*
3354  #[ Setup :
3355 */
3356  if ( par == 1 ) {
3357  fout = &(S->file);
3358  if ( fout->handle < 0 ) {
3359 FileMake:
3360  PUTZERO(AN.OldPosOut);
3361  if ( ( fhandle = CreateFile(fout->name) ) < 0 ) {
3362  MLOCK(ErrorMessageLock);
3363  MesPrint("Cannot create file %s",fout->name);
3364  MUNLOCK(ErrorMessageLock);
3365  goto ReturnError;
3366  }
3367 #ifdef GZIPDEBUG
3368  MLOCK(ErrorMessageLock);
3369  MesPrint("%w MergePatches created output file %s",fout->name);
3370  MUNLOCK(ErrorMessageLock);
3371 #endif
3372  fout->handle = fhandle;
3373  PUTZERO(fout->filesize);
3374  PUTZERO(fout->POposition);
3375 #ifdef ALLLOCK
3376  LOCK(fout->pthreadslock);
3377 #endif
3378  SeekFile(fout->handle,&(fout->filesize),SEEK_SET);
3379 #ifdef ALLLOCK
3380  UNLOCK(fout->pthreadslock);
3381 #endif
3382  S->fPatchN = 0;
3383  PUTZERO(S->fPatches[0]);
3384  fout->POfill = fout->PObuffer;
3385  PUTZERO(fout->POposition);
3386  }
3387 ConMer:
3388  StageSort(fout);
3389 #ifdef WITHZLIB
3390  if ( S == AT.S0 && AR.NoCompress == 0 && AR.gzipCompress > 0 )
3391  S->fpcompressed[S->fPatchN] = 1;
3392  else
3393  S->fpcompressed[S->fPatchN] = 0;
3394  SetupOutputGZIP(fout);
3395 #endif
3396  }
3397  else if ( par == 0 && S->stage4 > 0 ) {
3398 /*
3399  We will have to do our job more than once.
3400  Input is from S->file and output will go to AR.FoStage4.
3401  The file corresponding to this last one must be made now.
3402 */
3403  AR.Stage4Name ^= 1;
3404 /*
3405  s = (UBYTE *)(fout->name); while ( *s ) s++;
3406  if ( AR.Stage4Name ) s[-1] += 1;
3407  else s[-1] -= 1;
3408 */
3409  S->iPatches = S->fPatches;
3410  S->fPatches = S->inPatches;
3411  S->inPatches = S->iPatches;
3412  (S->inNum) = S->fPatchN;
3413  AN.OldPosIn = AN.OldPosOut;
3414 #ifdef WITHZLIB
3415  m1 = S->fpincompressed;
3416  S->fpincompressed = S->fpcompressed;
3417  S->fpcompressed = m1;
3418  for ( i = 0; i < S->inNum; i++ ) {
3419  S->fPatchesStop[i] = S->iPatches[i+1];
3420 #ifdef GZIPDEBUG
3421  MLOCK(ErrorMessageLock);
3422  MesPrint("%w fPatchesStop[%d] = %10p",i,&(S->fPatchesStop[i]));
3423  MUNLOCK(ErrorMessageLock);
3424 #endif
3425  }
3426 #endif
3427  S->stage4 = 0;
3428  goto FileMake;
3429  }
3430  else {
3431 #ifdef WITHZLIB
3432 /*
3433  The next statement is just for now
3434 */
3435  AR.gzipCompress = 0;
3436 #endif
3437  if ( par == 0 ) {
3438  S->iPatches = S->fPatches;
3439  S->inNum = S->fPatchN;
3440 #ifdef WITHZLIB
3441  m1 = S->fpincompressed;
3442  S->fpincompressed = S->fpcompressed;
3443  S->fpcompressed = m1;
3444  for ( i = 0; i < S->inNum; i++ ) {
3445  S->fPatchesStop[i] = S->fPatches[i+1];
3446 #ifdef GZIPDEBUG
3447  MLOCK(ErrorMessageLock);
3448  MesPrint("%w fPatchesStop[%d] = %10p",i,&(S->fPatchesStop[i]));
3449  MUNLOCK(ErrorMessageLock);
3450 #endif
3451  }
3452 #endif
3453  }
3454  fout = AR.outfile;
3455  }
3456  if ( par ) { /* Mark end of patches */
3457  S->Patches[S->lPatch] = S->lFill;
3458  for ( i = 0; i < S->lPatch; i++ ) {
3459  S->pStop[i] = S->Patches[i+1]-1;
3460  S->Patches[i] = (WORD *)(((UBYTE *)(S->Patches[i])) + AM.MaxTer);
3461  }
3462  }
3463  else { /* Load the patches */
3464  S->lPatch = (S->inNum);
3465 #ifdef WITHMPI
3466  if ( S->lPatch > 1 || ( (PF.exprtodo <0) && (fout == AR.outfile || fout == AR.hidefile ) ) ) {
3467 #else
3468  if ( S->lPatch > 1 ) {
3469 #endif
3470 #ifdef WITHZLIB
3471  SetupAllInputGZIP(S);
3472 #endif
3473  p = S->lBuffer;
3474  for ( i = 0; i < S->lPatch; i++ ) {
3475  p = (WORD *)(((UBYTE *)p)+2*AM.MaxTer+COMPINC*sizeof(WORD));
3476  S->Patches[i] = p;
3477  p = (WORD *)(((UBYTE *)p) + fin->POsize);
3478  S->pStop[i] = m2 = p;
3479 #ifdef WITHZLIB
3480  PutIn(fin,&(S->iPatches[i]),S->Patches[i],&m2,i);
3481 #else
3482  ADDPOS(S->iPatches[i],PutIn(fin,&(S->iPatches[i]),S->Patches[i],&m2,i));
3483 #endif
3484  }
3485  }
3486  }
3487  if ( fout->handle >= 0 ) {
3488  PUTZERO(position);
3489 #ifdef ALLLOCK
3490  LOCK(fout->pthreadslock);
3491 #endif
3492  SeekFile(fout->handle,&position,SEEK_END);
3493  ADDPOS(position,((fout->POfill-fout->PObuffer)*sizeof(WORD)));
3494 #ifdef ALLLOCK
3495  UNLOCK(fout->pthreadslock);
3496 #endif
3497  }
3498  else {
3499  SETBASEPOSITION(position,(fout->POfill-fout->PObuffer)*sizeof(WORD));
3500  }
3501 /*
3502  #] Setup :
3503 
3504  The old code had to be replaced because all output needs to go
3505  through PutOut. For this we have to go term by term and keep
3506  track of the compression.
3507 */
3508  if ( S->lPatch == 1 ) { /* Single patch --> direct copy. Very rare. */
3509  LONG length;
3510 
3511  if ( fout->handle < 0 ) if ( Sflush(fout) ) goto PatCall;
3512  if ( par ) { /* Memory to file */
3513 #ifdef WITHZLIB
3514 /*
3515  We fix here the problem that the thing needs to go through PutOut
3516 */
3517  m2 = m1 = *S->Patches; /* The m2 is to keep the compiler from complaining */
3518  while ( *m1 ) {
3519  if ( *m1 < 0 ) { /* Need to uncompress */
3520  i = -(*m1++); m2 += i; im = *m1+i+1;
3521  while ( i > 0 ) { *m1-- = *m2--; i--; }
3522  *m1 = im;
3523  }
3524 #ifdef WITHPTHREADS
3525  if ( AS.MasterSort && ( fout == AR.outfile ) ) { im = PutToMaster(BHEAD m1); }
3526  else
3527 #endif
3528  if ( ( im = PutOut(BHEAD m1,&position,fout,1) ) < 0 ) goto ReturnError;
3529  ADDPOS(S->SizeInFile[par],im);
3530  m2 = m1;
3531  m1 += *m1;
3532  }
3533 #ifdef WITHPTHREADS
3534  if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD 0); }
3535  else
3536 #endif
3537  if ( FlushOut(&position,fout,1) ) goto ReturnError;
3538  ADDPOS(S->SizeInFile[par],1);
3539 #else
3540 /* old code */
3541  length = (LONG)(*S->pStop)-(LONG)(*S->Patches)+sizeof(WORD);
3542  if ( WriteFile(fout->handle,(UBYTE *)(*S->Patches),length) != length )
3543  goto PatwCall;
3544  ADDPOS(position,length);
3545  ADDPOS(fout->POposition,length);
3546  ADDPOS(fout->filesize,length);
3547  ADDPOS(S->SizeInFile[par],length/sizeof(WORD));
3548 #endif
3549  }
3550  else { /* File to file */
3551 #ifdef WITHZLIB
3552 /*
3553  Note: if we change FRONTSIZE we need to make the minimum value
3554  of SmallEsize in AllocSort correspondingly larger or smaller.
3555  Theoretically we could get close to 2*AM.MaxTer!
3556 */
3557  #define FRONTSIZE (2*AM.MaxTer)
3558  WORD *copybuf = (WORD *)(((UBYTE *)(S->sBuffer)) + FRONTSIZE);
3559  WORD *copytop;
3560  SetupOutputGZIP(fout);
3561  SetupAllInputGZIP(S);
3562  m1 = m2 = copybuf;
3563  position2 = S->iPatches[0];
3564  while ( ( length = FillInputGZIP(fin,&position2,
3565  (UBYTE *)copybuf,
3566  (S->SmallEsize*sizeof(WORD)-FRONTSIZE),0) ) > 0 ) {
3567  copytop = (WORD *)(((UBYTE *)copybuf)+length);
3568  while ( *m1 && ( ( *m1 > 0 && m1+*m1 < copytop ) ||
3569  ( *m1 < 0 && ( m1+1 < copytop ) && ( m1+m1[1]+1 < copytop ) ) ) )
3570 /*
3571  22-jun-2013 JV Extremely nasty bug that has been around for a while.
3572  What if the end is in the remaining part? We will loose terms!
3573  while ( *m1 && ( (WORD *)(((UBYTE *)(m1)) + AM.MaxTer ) < S->sTop2 ) )
3574 */
3575  {
3576  if ( *m1 < 0 ) { /* Need to uncompress */
3577  i = -(*m1++); m2 += i; im = *m1+i+1;
3578  while ( i > 0 ) { *m1-- = *m2--; i--; }
3579  *m1 = im;
3580  }
3581 #ifdef WITHPTHREADS
3582  if ( AS.MasterSort && ( fout == AR.outfile ) ) {
3583  im = PutToMaster(BHEAD m1);
3584  }
3585  else
3586 #endif
3587  if ( ( im = PutOut(BHEAD m1,&position,fout,1) ) < 0 ) goto ReturnError;
3588  ADDPOS(S->SizeInFile[par],im);
3589  m2 = m1;
3590  m1 += *m1;
3591  }
3592  if ( m1 < copytop && *m1 == 0 ) break;
3593 /*
3594  Now move the remaining part 'back'
3595 */
3596  m3 = copybuf;
3597  m1 = copytop;
3598  while ( m1 > m2 ) *--m3 = *--m1;
3599  m2 = m3;
3600  m1 = m2 + *m2;
3601  }
3602  if ( length < 0 ) {
3603  MLOCK(ErrorMessageLock);
3604  MesPrint("Readerror");
3605  goto PatCall2;
3606  }
3607 #ifdef WITHPTHREADS
3608  if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD 0); }
3609  else
3610 #endif
3611  if ( FlushOut(&position,fout,1) ) goto ReturnError;
3612  ADDPOS(S->SizeInFile[par],1);
3613 #else
3614 /* old code */
3615  SeekFile(fin->handle,&(S->iPatches[0]),SEEK_SET); /* needed for stage4 */
3616  while ( ( length = ReadFile(fin->handle,
3617  (UBYTE *)(S->sBuffer),S->SmallEsize*sizeof(WORD)) ) > 0 ) {
3618  if ( WriteFile(fout->handle,(UBYTE *)(S->sBuffer),length) != length )
3619  goto PatwCall;
3620  ADDPOS(position,length);
3621  ADDPOS(fout->POposition,length);
3622  ADDPOS(fout->filesize,length);
3623  ADDPOS(S->SizeInFile[par],length/sizeof(WORD));
3624  }
3625  if ( length < 0 ) {
3626  MLOCK(ErrorMessageLock);
3627  MesPrint("Readerror");
3628  goto PatCall2;
3629  }
3630 #endif
3631  }
3632  goto EndOfAll;
3633  }
3634  else if ( S->lPatch > 0 ) {
3635 
3636  /* More than one patch. Construct the tree. */
3637 
3638  lpat = 1;
3639  do { lpat <<= 1; } while ( lpat < S->lPatch );
3640  mpat = ( lpat >> 1 ) - 1;
3641  k = lpat - S->lPatch;
3642 
3643  /* k is the number of empty places in the tree. they will
3644  be at the even positions from 2 to 2*k */
3645 
3646  for ( i = 1; i < lpat; i++ ) {
3647  S->tree[i] = -1;
3648  }
3649  for ( i = 1; i <= k; i++ ) {
3650  im = ( i << 1 ) - 1;
3651  poin[im] = S->Patches[i-1];
3652  poin2[im] = poin[im] + *(poin[im]);
3653  S->used[i] = im;
3654  S->ktoi[im] = i-1;
3655  S->tree[mpat+i] = 0;
3656  poin[im-1] = poin2[im-1] = 0;
3657  }
3658  for ( i = (k<<1)+1; i <= lpat; i++ ) {
3659  S->used[i-k] = i;
3660  S->ktoi[i] = i-k-1;
3661  poin[i] = S->Patches[i-k-1];
3662  poin2[i] = poin[i] + *(poin[i]);
3663  }
3664 /*
3665  the array poin tells the position of the i-th element of the S->tree
3666  'S->used' is a stack with the S->tree elements that need to be entered
3667  into the S->tree. at the beginning this is S->lPatch. during the
3668  sort there will be only very few elements.
3669  poin2 is the next value of poin. it has to be determined
3670  before the comparisons as the position or the size of the
3671  term indicated by poin may change.
3672  S->ktoi translates a S->tree element back to its stream number.
3673 
3674  start the sort
3675 */
3676  level = S->lPatch;
3677 
3678  /* introduce one term */
3679 OneTerm:
3680  k = S->used[level];
3681  i = k + lpat - 1;
3682  if ( !*(poin[k]) ) {
3683  do { if ( !( i >>= 1 ) ) goto EndOfMerge; } while ( !S->tree[i] );
3684  if ( S->tree[i] == -1 ) {
3685  S->tree[i] = 0;
3686  level--;
3687  goto OneTerm;
3688  }
3689  k = S->tree[i];
3690  S->used[level] = k;
3691  S->tree[i] = 0;
3692  }
3693 /*
3694  move terms down the tree
3695 */
3696  while ( i >>= 1 ) {
3697  if ( S->tree[i] > 0 ) {
3698  if ( ( c = CompareTerms(BHEAD poin[S->tree[i]],poin[k],(WORD)0) ) > 0 ) {
3699 /*
3700  S->tree[i] is the smaller. Exchange and go on.
3701 */
3702  S->used[level] = S->tree[i];
3703  S->tree[i] = k;
3704  k = S->used[level];
3705  }
3706  else if ( !c ) { /* Terms are equal */
3707  S->TermsLeft--;
3708 /*
3709  Here the terms are equal and their coefficients
3710  have to be added.
3711 */
3712  l1 = *( m1 = poin[S->tree[i]] );
3713  l2 = *( m2 = poin[k] );
3714  if ( S->PolyWise ) { /* Here we work with PolyFun */
3715  WORD *tt1, *w;
3716  tt1 = m1;
3717  m1 += S->PolyWise;
3718  m2 += S->PolyWise;
3719  if ( S->PolyFlag == 2 ) {
3720  w = poly_ratfun_add(BHEAD m1,m2);
3721  if ( *tt1 + w[1] - m1[1] > AM.MaxTer/((LONG)sizeof(WORD)) ) {
3722  MLOCK(ErrorMessageLock);
3723  MesPrint("Term too complex in PolyRatFun addition. MaxTermSize of %10l is too small",AM.MaxTer);
3724  MUNLOCK(ErrorMessageLock);
3725  Terminate(-1);
3726  }
3727  AT.WorkPointer = w;
3728  }
3729  else {
3730  w = AT.WorkPointer;
3731  if ( w + m1[1] + m2[1] > AT.WorkTop ) {
3732  MLOCK(ErrorMessageLock);
3733  MesPrint("A WorkSpace of %10l is too small",AM.WorkSize);
3734  MUNLOCK(ErrorMessageLock);
3735  Terminate(-1);
3736  }
3737  AddArgs(BHEAD m1,m2,w);
3738  }
3739  r1 = w[1];
3740  if ( r1 <= FUNHEAD
3741  || ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) )
3742  { goto cancelled; }
3743  if ( r1 == m1[1] ) {
3744  NCOPY(m1,w,r1);
3745  }
3746  else if ( r1 < m1[1] ) {
3747  r2 = m1[1] - r1;
3748  m2 = w + r1;
3749  m1 += m1[1];
3750  while ( --r1 >= 0 ) *--m1 = *--m2;
3751  m2 = m1 - r2;
3752  r1 = S->PolyWise;
3753  while ( --r1 >= 0 ) *--m1 = *--m2;
3754  *m1 -= r2;
3755  poin[S->tree[i]] = m1;
3756  }
3757  else {
3758  r2 = r1 - m1[1];
3759  m2 = tt1 - r2;
3760  r1 = S->PolyWise;
3761  m1 = tt1;
3762  *m1 += r2;
3763  poin[S->tree[i]] = m2;
3764  NCOPY(m2,m1,r1);
3765  r1 = w[1];
3766  NCOPY(m2,w,r1);
3767  }
3768  }
3769  else {
3770  r1 = *( m1 += l1 - 1 );
3771  m1 -= ABS(r1) - 1;
3772  r1 = ( ( r1 > 0 ) ? (r1-1) : (r1+1) ) >> 1;
3773  r2 = *( m2 += l2 - 1 );
3774  m2 -= ABS(r2) - 1;
3775  r2 = ( ( r2 > 0 ) ? (r2-1) : (r2+1) ) >> 1;
3776 
3777  if ( AddRat(BHEAD (UWORD *)m1,r1,(UWORD *)m2,r2,coef,&r3) ) {
3778  MLOCK(ErrorMessageLock);
3779  MesCall("MergePatches");
3780  MUNLOCK(ErrorMessageLock);
3781  SETERROR(-1)
3782  }
3783 
3784  if ( AN.ncmod != 0 ) {
3785  if ( ( AC.modmode & POSNEG ) != 0 ) {
3786  NormalModulus(coef,&r3);
3787  }
3788  else if ( BigLong(coef,r3,(UWORD *)AC.cmod,ABS(AN.ncmod)) >= 0 ) {
3789  WORD ii;
3790  SubPLon(coef,r3,(UWORD *)AC.cmod,ABS(AN.ncmod),coef,&r3);
3791  coef[r3] = 1;
3792  for ( ii = 1; ii < r3; ii++ ) coef[r3+ii] = 0;
3793  }
3794  }
3795  r3 <<= 1;
3796  r33 = ( r3 > 0 ) ? ( r3 + 1 ) : ( r3 - 1 );
3797  if ( r3 < 0 ) r3 = -r3;
3798  if ( r1 < 0 ) r1 = -r1;
3799  r1 <<= 1;
3800  r31 = r3 - r1;
3801  if ( !r3 ) { /* Terms cancel */
3802 cancelled:
3803  ul = S->used[level] = S->tree[i];
3804  S->tree[i] = -1;
3805 /*
3806  We skip to the next term in stream ul
3807 */
3808  im = *poin2[ul];
3809  if ( im < 0 ) {
3810  r1 = poin2[ul][1] - im + 1;
3811  m1 = poin2[ul] + 2;
3812  m2 = poin[ul] - im + 1;
3813  while ( ++im <= 0 ) *--m1 = *--m2;
3814  *--m1 = r1;
3815  poin2[ul] = m1;
3816  im = r1;
3817  }
3818  poin[ul] = poin2[ul];
3819  ki = S->ktoi[ul];
3820  if ( !par && (poin[ul] + im + COMPINC) >= S->pStop[ki]
3821  && im > 0 ) {
3822 #ifdef WITHZLIB
3823  PutIn(fin,&(S->iPatches[ki]),S->Patches[ki],&(poin[ul]),ki);
3824 #else
3825  ADDPOS(S->iPatches[ki],PutIn(fin,&(S->iPatches[ki]),
3826  S->Patches[ki],&(poin[ul]),ki));
3827 #endif
3828  poin2[ul] = poin[ul] + im;
3829  }
3830  else {
3831  poin2[ul] += im;
3832  }
3833  S->used[++level] = k;
3834  S->TermsLeft--;
3835  }
3836  else if ( !r31 ) { /* copy coef into term1 */
3837  goto CopCof2;
3838  }
3839  else if ( r31 < 0 ) { /* copy coef into term1
3840  and adjust the length of term1 */
3841  goto CopCoef;
3842  }
3843  else {
3844 /*
3845  this is the dreaded calamity.
3846  is there enough space?
3847 */
3848  if( (poin[S->tree[i]]+l1+r31) >= poin2[S->tree[i]] ) {
3849 /*
3850  no space! now the special trick for which
3851  we left 2*maxlng spaces open at the beginning
3852  of each patch.
3853 */
3854  if ( (l1 + r31) > AM.MaxTer/((LONG)sizeof(WORD)) ) {
3855  MLOCK(ErrorMessageLock);
3856  MesPrint("Coefficient overflow during sort");
3857  MUNLOCK(ErrorMessageLock);
3858  goto ReturnError;
3859  }
3860  m2 = poin[S->tree[i]];
3861  m3 = ( poin[S->tree[i]] -= r31 );
3862  do { *m3++ = *m2++; } while ( m2 < m1 );
3863  m1 = m3;
3864  }
3865 CopCoef:
3866  *(poin[S->tree[i]]) += r31;
3867 CopCof2:
3868  m2 = (WORD *)coef; im = r3;
3869  NCOPY(m1,m2,im);
3870  *m1 = r33;
3871  }
3872  }
3873 /*
3874  Now skip to the next term in stream k.
3875 */
3876 NextTerm:
3877  im = poin2[k][0];
3878  if ( im < 0 ) {
3879  r1 = poin2[k][1] - im + 1;
3880  m1 = poin2[k] + 2;
3881  m2 = poin[k] - im + 1;
3882  while ( ++im <= 0 ) *--m1 = *--m2;
3883  *--m1 = r1;
3884  poin2[k] = m1;
3885  im = r1;
3886  }
3887  poin[k] = poin2[k];
3888  ki = S->ktoi[k];
3889  if ( !par && ( (poin[k] + im + COMPINC) >= S->pStop[ki] )
3890  && im > 0 ) {
3891 #ifdef WITHZLIB
3892  PutIn(fin,&(S->iPatches[ki]),S->Patches[ki],&(poin[k]),ki);
3893 #else
3894  ADDPOS(S->iPatches[ki],PutIn(fin,&(S->iPatches[ki]),
3895  S->Patches[ki],&(poin[k]),ki));
3896 #endif
3897  poin2[k] = poin[k] + im;
3898  }
3899  else {
3900  poin2[k] += im;
3901  }
3902  goto OneTerm;
3903  }
3904  }
3905  else if ( S->tree[i] < 0 ) {
3906  S->tree[i] = k;
3907  level--;
3908  goto OneTerm;
3909  }
3910  }
3911 /*
3912  found the smallest in the set. indicated by k.
3913  write to its destination.
3914 */
3915 #ifdef WITHPTHREADS
3916  if ( AS.MasterSort && ( fout == AR.outfile ) ) { im = PutToMaster(BHEAD poin[k]); }
3917  else
3918 #endif
3919  if ( ( im = PutOut(BHEAD poin[k],&position,fout,1) ) < 0 ) {
3920  MLOCK(ErrorMessageLock);
3921  MesPrint("Called from MergePatches with k = %d (stream %d)",k,S->ktoi[k]);
3922  MUNLOCK(ErrorMessageLock);
3923  goto ReturnError;
3924  }
3925  ADDPOS(S->SizeInFile[par],im);
3926  goto NextTerm;
3927  }
3928  else {
3929  goto NormalReturn;
3930  }
3931 EndOfMerge:
3932 #ifdef WITHPTHREADS
3933  if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD 0); }
3934  else
3935 #endif
3936  if ( FlushOut(&position,fout,1) ) goto ReturnError;
3937  ADDPOS(S->SizeInFile[par],1);
3938 EndOfAll:
3939  if ( par == 1 ) { /* Set the fpatch pointers */
3940 #ifdef WITHZLIB
3941  SeekFile(fout->handle,&position,SEEK_CUR);
3942 #endif
3943  (S->fPatchN)++;
3944  S->fPatches[S->fPatchN] = position;
3945  }
3946  if ( par == 0 && fout != AR.outfile ) {
3947 /*
3948  Output went to sortfile. We have two possibilities:
3949  1: We are not finished with the current in-out cycle
3950  In that case we should pop to the next set of patches
3951  2: We finished a cycle and should clean up the in file
3952  Then we restart the sort.
3953 */
3954  (S->fPatchN)++;
3955  S->fPatches[S->fPatchN] = position;
3956  if ( ISNOTZEROPOS(AN.OldPosIn) ) { /* We are not done */
3957 
3958  SeekFile(fin->handle,&(AN.OldPosIn),SEEK_SET);
3959 /*
3960  We don't need extra provisions for the zlib compression here.
3961  If part of an expression has been sorted, the whole has been so.
3962  This means that S->fpincompressed[] will remain the same
3963 */
3964  if ( (ULONG)ReadFile(fin->handle,(UBYTE *)(&(S->inNum)),(LONG)sizeof(WORD)) !=
3965  sizeof(WORD)
3966  || (ULONG)ReadFile(fin->handle,(UBYTE *)(&AN.OldPosIn),(LONG)sizeof(POSITION)) !=
3967  sizeof(POSITION)
3968  || (ULONG)ReadFile(fin->handle,(UBYTE *)S->iPatches,(LONG)((S->inNum)+1)
3969  *sizeof(POSITION)) != ((S->inNum)+1)*sizeof(POSITION) ) {
3970  MLOCK(ErrorMessageLock);
3971  MesPrint("Read error fourth stage sorting");
3972  MUNLOCK(ErrorMessageLock);
3973  goto ReturnError;
3974  }
3975  *rr = 0;
3976 #ifdef WITHZLIB
3977  for ( i = 0; i < S->inNum; i++ ) {
3978  S->fPatchesStop[i] = S->iPatches[i+1];
3979 #ifdef GZIPDEBUG
3980  MLOCK(ErrorMessageLock);
3981  MesPrint("%w fPatchesStop[%d] = %10p",i,&(S->fPatchesStop[i]));
3982  MUNLOCK(ErrorMessageLock);
3983 #endif
3984  }
3985 #endif
3986  goto ConMer;
3987  }
3988  else {
3989 /*
3990  if ( fin == &(AR.FoStage4[0]) ) {
3991  s = (UBYTE *)(fin->name); while ( *s ) s++;
3992  if ( AR.Stage4Name == 1 ) s[-1] -= 1;
3993  else s[-1] += 1;
3994  }
3995 */
3996 /* TruncateFile(fin->handle); */
3997  UpdateMaxSize();
3998  CloseFile(fin->handle);
3999  remove(fin->name); /* Gives diskspace free again. */
4000 #ifdef GZIPDEBUG
4001  MLOCK(ErrorMessageLock);
4002  MesPrint("%w MergePatches removed in file %s",fin->name);
4003  MUNLOCK(ErrorMessageLock);
4004 #endif
4005 /*
4006  if ( fin == &(AR.FoStage4[0]) ) {
4007  s = (UBYTE *)(fin->name); while ( *s ) s++;
4008  if ( AR.Stage4Name == 1 ) s[-1] += 1;
4009  else s[-1] -= 1;
4010  }
4011 */
4012  fin->handle = -1;
4013  { FILEHANDLE *ff = fin; fin = fout; fout = ff; }
4014  PUTZERO(S->SizeInFile[0]);
4015  goto NewMerge;
4016  }
4017  }
4018  if ( par == 0 ) {
4019 /* TruncateFile(fin->handle); */
4020  UpdateMaxSize();
4021  CloseFile(fin->handle);
4022  remove(fin->name);
4023  fin->handle = -1;
4024 #ifdef GZIPDEBUG
4025  MLOCK(ErrorMessageLock);
4026  MesPrint("%w MergePatches removed in file %s",fin->name);
4027  MUNLOCK(ErrorMessageLock);
4028 #endif
4029  }
4030 NormalReturn:
4031 #ifdef WITHZLIB
4032  AR.gzipCompress = oldgzipCompress;
4033 #endif
4034  return(0);
4035 ReturnError:
4036 #ifdef WITHZLIB
4037  AR.gzipCompress = oldgzipCompress;
4038 #endif
4039  return(-1);
4040 #ifndef WITHZLIB
4041 PatwCall:
4042  MLOCK(ErrorMessageLock);
4043  MesPrint("Error while writing to file.");
4044  goto PatCall2;
4045 #endif
4046 PatCall:;
4047  MLOCK(ErrorMessageLock);
4048 PatCall2:;
4049  MesCall("MergePatches");
4050  MUNLOCK(ErrorMessageLock);
4051 #ifdef WITHZLIB
4052  AR.gzipCompress = oldgzipCompress;
4053 #endif
4054  SETERROR(-1)
4055 }
4056 
4057 /*
4058  #] MergePatches :
4059  #[ StoreTerm : WORD StoreTerm(term)
4060 */
4070 WORD StoreTerm(PHEAD WORD *term)
4071 {
4072  GETBIDENTITY
4073  SORTING *S = AT.SS;
4074  WORD **ss, *lfill, j, *t;
4075  POSITION pp;
4076  LONG lSpace, sSpace, RetCode, over, tover;
4077 
4078  if ( ( ( AP.PreDebug & DUMPTOSORT ) == DUMPTOSORT ) && AR.sLevel == 0 ) {
4079 #ifdef WITHPTHREADS
4080  sprintf((char *)(THRbuf),"StoreTerm(%d)",AT.identity);
4081  PrintTerm(term,(char *)(THRbuf));
4082 #else
4083  PrintTerm(term,"StoreTerm");
4084 #endif
4085  }
4086  if ( AM.exitflag && AR.sLevel == 0 ) return(0);
4087  S->sFill = *(S->PoinFill);
4088  if ( S->sTerms >= S->TermsInSmall || ( S->sFill + *term ) >= S->sTop ) {
4089 /*
4090  The small buffer is full. It has to be sorted and written.
4091 */
4092  S->PolyFlag = ( AR.PolyFun != 0 ) ? AR.PolyFunType:0;
4093  tover = over = S->sTerms;
4094  ss = S->sPointer;
4095  ss[over] = 0;
4096 /*
4097  PrintTime();
4098 */
4099  SplitMerge(BHEAD ss,over);
4100  sSpace = 0;
4101  if ( over > 0 ) {
4102  ss[over] = 0;
4103  sSpace = ComPress(ss,&RetCode);
4104  S->TermsLeft -= over - RetCode;
4105  }
4106  sSpace++;
4107 
4108  lSpace = sSpace + (S->lFill - S->lBuffer)
4109  - (AM.MaxTer/sizeof(WORD))*((LONG)S->lPatch);
4110  SETBASEPOSITION(pp,lSpace);
4111  MULPOS(pp,sizeof(WORD));
4112  if ( S->file.handle >= 0 ) {
4113  ADD2POS(pp,S->fPatches[S->fPatchN]);
4114  }
4115  if ( S == AT.S0 ) { /* Only statistics at ground level */
4116  WORD oldLogHandle = AC.LogHandle;
4117  if ( AC.LogHandle >= 0 && AM.LogType ) AC.LogHandle = -1;
4118  WriteStats(&pp,(WORD)0);
4119  AC.LogHandle = oldLogHandle;
4120  }
4121  if ( ( S->lPatch >= S->MaxPatches ) ||
4122  ( ( (WORD *)(((UBYTE *)(S->lFill + sSpace)) + 2*AM.MaxTer ) ) >= S->lTop ) ) {
4123 /*
4124  The large buffer is too full. Merge and write it
4125 */
4126  if ( MergePatches(1) ) goto StoreCall;
4127 /*
4128  pp = S->SizeInFile[1];
4129  ADDPOS(pp,sSpace);
4130  MULPOS(pp,sizeof(WORD));
4131 */
4132  SETBASEPOSITION(pp,sSpace);
4133  MULPOS(pp,sizeof(WORD));
4134  ADD2POS(pp,S->fPatches[S->fPatchN]);
4135 
4136  if ( S == AT.S0 ) { /* Only statistics at ground level */
4137  WORD oldLogHandle = AC.LogHandle;
4138  if ( AC.LogHandle >= 0 && AM.LogType ) AC.LogHandle = -1;
4139  WriteStats(&pp,(WORD)1);
4140  AC.LogHandle = oldLogHandle;
4141  }
4142  S->lPatch = 0;
4143  S->lFill = S->lBuffer;
4144  }
4145  S->Patches[S->lPatch++] = S->lFill;
4146  lfill = (WORD *)(((UBYTE *)(S->lFill)) + AM.MaxTer);
4147  if ( tover > 0 ) {
4148  ss = S->sPointer;
4149  while ( ( t = *ss++ ) != 0 ) {
4150  j = *t;
4151  if ( j < 0 ) j = t[1] + 2;
4152  while ( --j >= 0 ){
4153  *lfill++ = *t++;
4154  }
4155  }
4156  }
4157  *lfill++ = 0;
4158  S->lFill = lfill;
4159  S->sTerms = 0;
4160  S->PoinFill = S->sPointer;
4161  *(S->PoinFill) = S->sFill = S->sBuffer;
4162  }
4163  j = *term;
4164  while ( --j >= 0 ) *S->sFill++ = *term++;
4165  S->sTerms++;
4166  S->GenTerms++;
4167  S->TermsLeft++;
4168  *++S->PoinFill = S->sFill;
4169 
4170  return(0);
4171 
4172 StoreCall:
4173  MLOCK(ErrorMessageLock);
4174  MesCall("StoreTerm");
4175  MUNLOCK(ErrorMessageLock);
4176  SETERROR(-1)
4177 }
4178 
4179 /*
4180  #] StoreTerm :
4181  #[ StageSort : VOID StageSort(FILEHANDLE *fout)
4182 */
4190 {
4191  GETIDENTITY
4192  SORTING *S = AT.SS;
4193  if ( S->fPatchN >= S->MaxFpatches ) {
4194  POSITION position;
4195  PUTZERO(position);
4196  MLOCK(ErrorMessageLock);
4197 #ifdef WITHPTHREADS
4198  MesPrint("StageSort in thread %d",identity);
4199 #elif defined(WITHMPI)
4200  MesPrint("StageSort in process %d",PF.me);
4201 #else
4202  MesPrint("StageSort");
4203 #endif
4204  MUNLOCK(ErrorMessageLock);
4205  SeekFile(fout->handle,&position,SEEK_END);
4206 /*
4207  No extra compression data has to be written.
4208  S->fpincompressed should remain valid.
4209 */
4210  if ( (ULONG)WriteFile(fout->handle,(UBYTE *)(&(S->fPatchN)),(LONG)sizeof(WORD)) !=
4211  sizeof(WORD)
4212  || (ULONG)WriteFile(fout->handle,(UBYTE *)(&(AN.OldPosOut)),(LONG)sizeof(POSITION)) !=
4213  sizeof(POSITION)
4214  || (ULONG)WriteFile(fout->handle,(UBYTE *)(S->fPatches),(LONG)(S->fPatchN+1)
4215  *sizeof(POSITION)) != (S->fPatchN+1)*sizeof(POSITION) ) {
4216  MLOCK(ErrorMessageLock);
4217  MesPrint("Write error while staging sort. Disk full?");
4218  MUNLOCK(ErrorMessageLock);
4219  Terminate(-1);
4220  }
4221  AN.OldPosOut = position;
4222  fout->filesize = position;
4223  ADDPOS(fout->filesize,(S->fPatchN+2)*sizeof(POSITION) + sizeof(WORD));
4224  fout->POposition = fout->filesize;
4225  S->fPatches[0] = fout->filesize;
4226  S->fPatchN = 0;
4227 
4228  if ( AR.FoStage4[0].PObuffer == 0 ) {
4229  AR.FoStage4[0].PObuffer = (WORD *)Malloc1(AR.FoStage4[0].POsize*sizeof(WORD)
4230  ,"Stage 4 buffer");
4231  AR.FoStage4[0].POfill = AR.FoStage4[0].PObuffer;
4232  AR.FoStage4[0].POstop = AR.FoStage4[0].PObuffer
4233  + AR.FoStage4[0].POsize/sizeof(WORD);
4234 #ifdef WITHPTHREADS
4235  AR.FoStage4[0].pthreadslock = dummylock;
4236 #endif
4237  }
4238  if ( AR.FoStage4[1].PObuffer == 0 ) {
4239  AR.FoStage4[1].PObuffer = (WORD *)Malloc1(AR.FoStage4[1].POsize*sizeof(WORD)
4240  ,"Stage 4 buffer");
4241  AR.FoStage4[1].POfill = AR.FoStage4[1].PObuffer;
4242  AR.FoStage4[1].POstop = AR.FoStage4[1].PObuffer
4243  + AR.FoStage4[1].POsize/sizeof(WORD);
4244 #ifdef WITHPTHREADS
4245  AR.FoStage4[1].pthreadslock = dummylock;
4246 #endif
4247  }
4248  S->stage4 = 1;
4249  }
4250 }
4251 
4252 /*
4253  #] StageSort :
4254  #[ SortWild : WORD SortWild(w,nw)
4255 */
4269 WORD SortWild(WORD *w, WORD nw)
4270 {
4271  GETIDENTITY
4272  WORD *v, *s, *m, k, i;
4273  WORD *pScrat, *stop, *sv, error = 0;
4274  pScrat = AT.WorkPointer;
4275  if ( ( AT.WorkPointer + 8 * AM.MaxWildcards ) >= AT.WorkTop ) {
4276  MLOCK(ErrorMessageLock);
4277  MesWork();
4278  MUNLOCK(ErrorMessageLock);
4279  return(-1);
4280  }
4281  stop = w + nw;
4282  i = 0;
4283  while ( i < nw ) {
4284  m = w + i;
4285  v = m + m[1];
4286  while ( v < stop && (
4287  *v == FROMSET || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
4288  while ( v < stop ) {
4289  if ( *v >= 0 ) {
4290  if ( AM.Ordering[*v] < AM.Ordering[*m] ) {
4291  m = v;
4292  }
4293  else if ( *v == *m ) {
4294  if ( v[2] < m[2] ) {
4295  m = v;
4296  }
4297  else if ( v[2] == m[2] ) {
4298  s = m + m[1];
4299  sv = v + v[1];
4300  if ( s < stop && ( *s == FROMSET
4301  || *s == SETTONUM || *s == LOADDOLLAR ) ) {
4302  if ( sv < stop && ( *sv == FROMSET
4303  || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
4304  if ( s[2] != sv[2] ) {
4305  error = -1;
4306  MLOCK(ErrorMessageLock);
4307  MesPrint("&Wildcard set conflict");
4308  MUNLOCK(ErrorMessageLock);
4309  }
4310  }
4311  *v = -1;
4312  }
4313  else {
4314  if ( sv < stop && ( *sv == FROMSET
4315  || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
4316  *m = -1;
4317  m = v;
4318  }
4319  else {
4320  *v = -1;
4321  }
4322  }
4323  }
4324  }
4325  }
4326  v += v[1];
4327  while ( v < stop && ( *v == FROMSET
4328  || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
4329  }
4330  s = pScrat;
4331  v = m;
4332  k = m[1];
4333  NCOPY(s,m,k);
4334  while ( m < stop && ( *m == FROMSET
4335  || *m == SETTONUM || *m == LOADDOLLAR ) ) {
4336  k = m[1];
4337  NCOPY(s,m,k);
4338  }
4339  *v = -1;
4340  pScrat = s;
4341  i = 0;
4342  while ( i < nw && ( w[i] < 0 || w[i] == FROMSET
4343  || w[i] == SETTONUM || w[i] == LOADDOLLAR ) ) i += w[i+1];
4344  }
4345  AC.NwildC = k = WORDDIF(pScrat,AT.WorkPointer);
4346  s = AT.WorkPointer;
4347  m = w;
4348  NCOPY(m,s,k);
4349  AC.WildC = m;
4350  return(error);
4351 }
4352 
4353 /*
4354  #] SortWild :
4355  #[ CleanUpSort : VOID CleanUpSort(num)
4356 */
4361 void CleanUpSort(int num)
4362 {
4363  GETIDENTITY
4364  SORTING *S;
4365  int minnum = num, i;
4366  if ( AN.FunSorts ) {
4367  if ( num == -1 ) {
4368  if ( AN.MaxFunSorts > 3 ) {
4369  minnum = (AN.MaxFunSorts+4)/2;
4370  }
4371  else minnum = 4;
4372  }
4373  else if ( minnum == 0 ) minnum = 1;
4374  for ( i = minnum; i < AN.NumFunSorts; i++ ) {
4375  S = AN.FunSorts[i];
4376  if ( S ) {
4377  if ( S->file.handle >= 0 ) {
4378 /* TruncateFile(S->file.handle); */
4379  UpdateMaxSize();
4380  CloseFile(S->file.handle);
4381  S->file.handle = -1;
4382  remove(S->file.name);
4383 #ifdef GZIPDEBUG
4384  MLOCK(ErrorMessageLock);
4385  MesPrint("%w CleanUpSort removed file %s",S->file.name);
4386  MUNLOCK(ErrorMessageLock);
4387 #endif
4388  }
4389  M_free(S,"sorting struct");
4390  }
4391  AN.FunSorts[i] = 0;
4392  }
4393  AN.MaxFunSorts = minnum;
4394  if ( num == 0 ) {
4395  S = AN.FunSorts[0];
4396  if ( S ) {
4397  if ( S->file.handle >= 0 ) {
4398 /* TruncateFile(S->file.handle); */
4399  UpdateMaxSize();
4400  CloseFile(S->file.handle);
4401  S->file.handle = -1;
4402  remove(S->file.name);
4403 #ifdef GZIPDEBUG
4404  MLOCK(ErrorMessageLock);
4405  MesPrint("%w CleanUpSort removed file %s",S->file.name);
4406  MUNLOCK(ErrorMessageLock);
4407 #endif
4408  }
4409  }
4410  }
4411  }
4412  for ( i = 0; i < 2; i++ ) {
4413  if ( AR.FoStage4[i].handle >= 0 ) {
4414  UpdateMaxSize();
4415  CloseFile(AR.FoStage4[i].handle);
4416  remove(AR.FoStage4[i].name);
4417  AR.FoStage4[i].handle = -1;
4418 #ifdef GZIPDEBUG
4419  MLOCK(ErrorMessageLock);
4420  MesPrint("%w CleanUpSort removed stage4 file %s",AR.FoStage4[i].name);
4421  MUNLOCK(ErrorMessageLock);
4422 #endif
4423  }
4424  }
4425 }
4426 
4427 /*
4428  #] CleanUpSort :
4429  #[ LowerSortLevel : VOID LowerSortLevel()
4430 */
4436 {
4437  GETIDENTITY
4438  if ( AR.sLevel >= 0 ) {
4439  AR.sLevel--;
4440  if ( AR.sLevel >= 0 ) AT.SS = AN.FunSorts[AR.sLevel];
4441  }
4442 }
4443 
4444 /*
4445  #] LowerSortLevel :
4446  #] SortUtilities :
4447 */
int NormalModulus(UWORD *, WORD *)
Definition: reken.c:1370
LONG EndSort(PHEAD WORD *buffer, int par)
Definition: sort.c:632
WORD StoreTerm(PHEAD WORD *term)
Definition: sort.c:4070
WORD Compare1(PHEAD WORD *term1, WORD *term2, WORD level)
Definition: sort.c:2397
Definition: structs.h:618
#define PHEAD
Definition: ftypes.h:56
WORD FlushOut(POSITION *position, FILEHANDLE *fi, int compr)
Definition: sort.c:1621
int PF_EndSort(void)
Definition: parallel.c:864
void CleanUpSort(int num)
Definition: sort.c:4361
int CompareSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
Definition: sort.c:2818
LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
Definition: sort.c:3033
LONG PutIn(FILEHANDLE *file, POSITION *position, WORD *buffer, WORD **take, int npat)
Definition: sort.c:1154
VOID AddArgs(PHEAD WORD *s1, WORD *s2, WORD *m)
Definition: sort.c:2115
int PF_ISendSbuf(int to, int tag)
Definition: mpi.c:261
WORD PutOut(PHEAD WORD *term, POSITION *position, FILEHANDLE *fi, WORD ncomp)
Definition: sort.c:1300
WORD Sflush(FILEHANDLE *fi)
Definition: sort.c:1214
Definition: structs.h:1028
LONG ComPress(WORD **ss, LONG *n)
Definition: sort.c:2867
VOID LowerSortLevel()
Definition: sort.c:4435
BRACKETINDEX * indexbuffer
Definition: structs.h:317
VOID StageSort(FILEHANDLE *fout)
Definition: sort.c:4189
VOID GarbHand()
Definition: sort.c:3209
WORD NewSort(PHEAD0)
Definition: sort.c:553
WORD AddPoly(PHEAD WORD **ps1, WORD **ps2)
Definition: sort.c:1956
WORD AddCoef(PHEAD WORD **ps1, WORD **ps2)
Definition: sort.c:1829
VOID WriteStats(POSITION *plspace, WORD par)
Definition: sort.c:91
WORD CompCoef(WORD *, WORD *)
Definition: reken.c:3012
WORD MergePatches(WORD par)
Definition: sort.c:3324
int handle
Definition: structs.h:646
WORD SortWild(WORD *w, WORD nw)
Definition: sort.c:4269