• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

form-dev / form / 16168866371

09 Jul 2025 12:07PM UTC coverage: 50.836% (-0.01%) from 50.85%
16168866371

push

github

jodavies
feature: add "On humanstats;" for human-readable units in stats

Off by default.

11 of 39 new or added lines in 2 files covered. (28.21%)

9 existing lines in 2 files now uncovered.

42194 of 83001 relevant lines covered (50.84%)

2135674.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

62.61
/sources/sort.c
1
/** @file sort.c
2
 * 
3
 *  Contains the sort routines.
4
 *        We distinguish levels of sorting.
5
 *        The ground level is the sorting of terms in an expression.
6
 *        When a term has functions, the arguments can contain terms that need
7
 *        sorting, which this then done by raising the level. This can happen
8
 *        recursively. NewSort and EndSort automatically raise and lower the
9
 *        level. Because the ground level does some special things, sometimes
10
 *        we have to raise immediately to the second level skipping the ground level.
11
 *
12
 *        Special routines for the parallel sorting are in the file threads.c
13
 *        Also the sorting of terms in polynomials is special but most of that is
14
 *        controlled by changing the address of the compare routine. Other routines
15
 *        relevant for adding rational polynomials are in the file polynito.c
16
 */
17
/* #[ License : */
18
/*
19
 *   Copyright (C) 1984-2023 J.A.M. Vermaseren
20
 *   When using this file you are requested to refer to the publication
21
 *   J.A.M.Vermaseren "New features of FORM" math-ph/0010025
22
 *   This is considered a matter of courtesy as the development was paid
23
 *   for by FOM the Dutch physics granting agency and we would like to
24
 *   be able to track its scientific use to convince FOM of its value
25
 *   for the community.
26
 *
27
 *   This file is part of FORM.
28
 *
29
 *   FORM is free software: you can redistribute it and/or modify it under the
30
 *   terms of the GNU General Public License as published by the Free Software
31
 *   Foundation, either version 3 of the License, or (at your option) any later
32
 *   version.
33
 *
34
 *   FORM is distributed in the hope that it will be useful, but WITHOUT ANY
35
 *   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
36
 *   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
37
 *   details.
38
 *
39
 *   You should have received a copy of the GNU General Public License along
40
 *   with FORM.  If not, see <http://www.gnu.org/licenses/>.
41
 */
42
/* #] License : */ 
43
/*
44
          #[ Includes : sort.c
45

46
        Sort routines according to new conventions (25-jun-1997).
47
        This is more object oriented.
48
        The active sort is indicated by AT.SS which should agree with
49
        AN.FunSorts[AR.sLevel];
50

51
#define GZIPDEBUG
52
*/
53
#define NEWSPLITMERGE
54
/* Comment to turn off Timsort in SplitMerge for debugging: */
55
#define NEWSPLITMERGETIMSORT
56
/* During SplitMerge, print pointer array state on entry. Very spammy, for debugging. */
57
/* #define SPLITMERGEDEBUG */
58
/* Debug printing for GarbHand */
59
/* #define TESTGARB */
60

61
#include "form3.h"
62

63
#ifdef WITHPTHREADS
64
UBYTE THRbuf[100];
65
#endif
66

67
#ifdef WITHSTATS
68
extern LONG numwrites;
69
extern LONG numreads;
70
extern LONG numseeks;
71
extern LONG nummallocs;
72
extern LONG numfrees;
73
#endif
74

75
LONG numcompares;
76

77
/*
78
          #] Includes : 
79
        #[ SortUtilities :
80
                #[ WriteStats :                                void WriteStats(lspace,par,checkLogType)
81
*/
82
 
83
char *toterms[] = { "   ", " >>", "-->" };
84

85
#define HUMANSTRLEN 12
86
#define HUMANSUFFLEN 4
87
const char humanTermsSuffix[HUMANSUFFLEN][4] = {"K  ","M  ","B  ","T  "};
88
const char humanBytesSuffix[HUMANSUFFLEN][4] = {"KiB","MiB","GiB","TiB"};
NEW
89
void HumanString(char* string, float input, const char suffix[HUMANSUFFLEN][4]) {
×
NEW
90
        int ind = -1;
×
NEW
91
        while (ind < 0 || (input >= 1000.0 && ind < HUMANSUFFLEN) ) {
×
NEW
92
                input /= 1000.0;
×
NEW
93
                ind++;
×
94
        }
NEW
95
        if ( input < 0.5 ) {
×
NEW
96
                snprintf(string, HUMANSTRLEN,
×
NEW
97
                        "  ( <1 %s)", suffix[ind]);
×
98
        }
99
        else {
NEW
100
                snprintf(string, HUMANSTRLEN,
×
NEW
101
                        "  (%3.f %s)", input, suffix[ind]);
×
102
        }
NEW
103
}
×
104

105
/**
106
 *                Writes the statistics.
107
 *
108
 *                @param plspace The size in bytes currently occupied
109
 *                @param par
110
 *                par = 0 = STATSSPLITMERGE after a splitmerge.
111
 *                par = 1 = STATSMERGETOFILE after merge to sortfile.
112
 *                par = 2 = STATSPOSTSORT after the sort
113
 *                @param checkLogType == CHECKLOGTYPE: The output should not
114
 *                go to the log file if AM.LogType is 1.
115
 *
116
 *                current expression is to be found in AR.CurExpr.
117
 *                terms are in S->TermsLeft.
118
 *                S->GenTerms.
119
 */
120

121
void WriteStats(POSITION *plspace, WORD par, WORD checkLogType)
276,968✔
122
{
123
        GETIDENTITY
184,602✔
124
        LONG millitime, y = 0x7FFFFFFFL >> 1;
276,968✔
125
        WORD timepart;
276,968✔
126
        SORTING *S;
276,968✔
127
        POSITION pp;
276,968✔
128
        int use_wtime;
276,968✔
129
        if ( AT.SS == AT.S0 && AC.StatsFlag ) {
276,968✔
130
#ifdef WITHPTHREADS
131
                if ( AC.ThreadStats == 0 && identity > 0 ) return;
11,592✔
132
#elif defined(WITHMPI)
133
                if ( AC.OldParallelStats ) return;
134
                if ( ! AC.ProcessStats && PF.me != MASTER ) return;
135
#endif
136
                if ( Expressions == 0 ) return;
13,589✔
137

138
                if ( par == STATSSPLITMERGE ) {
11,707✔
139
                        if ( AC.ShortStatsMax == 0 ) return;
5,657✔
140
                        AR.ShortSortCount++;
×
141
                        if ( AR.ShortSortCount < AC.ShortStatsMax ) return;
×
142
                }
143
                AR.ShortSortCount = 0;
6,050✔
144

145
                S = AT.SS;
6,050✔
146

147
                char humanGenTermsText[HUMANSTRLEN] = "";
6,050✔
148
                char humanTermsLeftText[HUMANSTRLEN] = "";
6,050✔
149
                char humanBytesText[HUMANSTRLEN] = "";
6,050✔
150
                if ( AC.HumanStatsFlag ) {
6,050✔
NEW
151
                        HumanString(humanGenTermsText, (float)(S->GenTerms), humanTermsSuffix);
×
NEW
152
                        HumanString(humanTermsLeftText, (float)(S->TermsLeft), humanTermsSuffix);
×
NEW
153
                        HumanString(humanBytesText, (float)(BASEPOSITION(*plspace)), humanBytesSuffix);
×
154
                }
155

156
                MLOCK(ErrorMessageLock);
6,050✔
157

158
                /* If the statistics should not go to the log file, temporarily hide the
159
                 * LogHandle. This must be done within the ErrorMessageLock region to
160
                 * avoid a data race between threads. */
161
                const WORD oldLogHandle = AC.LogHandle;
6,050✔
162
                if ( checkLogType && AM.LogType ) {
6,050✔
163
                        AC.LogHandle = -1;
362✔
164
                }
165

166
                if ( AC.ShortStats ) {}
6,050✔
167
                else {
168
#ifdef WITHPTHREADS
169
                        if ( identity > 0 ) {
4,026✔
170
                                MesPrint("             Thread %d reporting",identity);
270✔
171
                        }
172
                        else {
173
                                MesPrint("");
3,756✔
174
                        }
175
#elif defined(WITHMPI)
176
                        if ( PF.me != MASTER ) {
177
                                MesPrint("             Process %d reporting",PF.me);
178
                        }
179
                        else {
180
                                MesPrint("");
181
                        }
182
#else
183
                        MesPrint("");
2,000✔
184
#endif
185
                }
186
                /*
187
                 * We define WTimeStatsFlag as a flag to print the wall-clock time on
188
                 * the *master*, not in workers. This can be confusing in thread
189
                 * statistics when short statistics is used. Technically,
190
                 * TimeWallClock() is not thread-safe in TFORM.
191
                 */
192
                use_wtime = AC.WTimeStatsFlag;
6,050✔
193
#if defined(WITHPTHREADS)
194
                if ( use_wtime && identity > 0 ) use_wtime = 0;
4,042✔
195
#elif defined(WITHMPI)
196
                if ( use_wtime && PF.me != MASTER ) use_wtime = 0;
197
#endif
198
                millitime = use_wtime ? TimeWallClock(1) * 10 : TimeCPU(1);
6,050✔
199
                timepart = (WORD)(millitime%1000);
6,050✔
200
                millitime /= 1000;
6,050✔
201
                timepart /= 10;
6,050✔
202
                if ( AC.ShortStats ) {
6,050✔
203
#if defined(WITHPTHREADS) || defined(WITHMPI)
204
#ifdef WITHPTHREADS
205
                  if ( identity > 0 ) {
16✔
206
#else
207
                  if ( PF.me != MASTER ) {
208
                        const int identity = PF.me;
209
#endif
210
                        if ( par == STATSSPLITMERGE || par == STATSPOSTSORT ) {
211
                                SETBASEPOSITION(pp,y);
212
                                if ( ISLESSPOS(*plspace,pp) ) {
213
                                        MesPrint("%d: %7l.%2is %8l>%10l%3s%10l:%10p %s %s",identity,
214
                                        millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
215
                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
216
/*
217
                                        MesPrint("%d: %14s %17s %7l.%2is %8l>%10l%3s%10l:%10p",identity,
218
                                        EXPRNAME(AR.CurExpr),AC.Commercial,millitime,timepart,
219
                                        AN.ninterms,S->GenTerms,toterms[par],S->TermsLeft,plspace);
220
*/
221
                                }
222
                                else {
223
                                        y = 1000000000L;
224
                                        SETBASEPOSITION(pp,y);
225
                                        MULPOS(pp,100);
226
                                        if ( ISLESSPOS(*plspace,pp) ) {
227
                                                MesPrint("%d: %7l.%2is %8l>%10l%3s%10l:%11p %s %s",identity,
228
                                                millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
229
                                                S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
230
                                        }
231
                                        else {
232
                                                MULPOS(pp,10);
233
                                                if ( ISLESSPOS(*plspace,pp) ) {
234
                                                        MesPrint("%d: %7l.%2is %8l>%10l%3s%10l:%12p %s %s",identity,
235
                                                        millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
236
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
237
                                                }
238
                                                else {
239
                                                MULPOS(pp,10);
240
                                                if ( ISLESSPOS(*plspace,pp) ) {
241
                                                        MesPrint("%d: %7l.%2is %8l>%10l%3s%10l:%13p %s %s",identity,
242
                                                        millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
243
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
244
                                                }
245
                                                else {
246
                                                MULPOS(pp,10);
247
                                                if ( ISLESSPOS(*plspace,pp) ) {
248
                                                        MesPrint("%d: %7l.%2is %8l>%10l%3s%10l:%14p %s %s",identity,
249
                                                        millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
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 %8l>%10l%3s%10l:%15p %s %s",identity,
256
                                                        millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
257
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
258
                                                }
259
                                                else {
260
                                                MULPOS(pp,10);
261
                                                if ( ISLESSPOS(*plspace,pp) ) {
262
                                                        MesPrint("%d: %7l.%2is %8l>%10l%3s%10l:%16p %s %s",identity,
263
                                                        millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
264
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
265
                                                }
266
                                                else {
267
                                                MULPOS(pp,10);
268
                                                if ( ISLESSPOS(*plspace,pp) ) {
269
                                                        MesPrint("%d: %7l.%2is %8l>%10l%3s%10l:%17p %s %s",identity,
270
                                                        millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
271
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
272
                                                }
273
                                                } } } } }
274
                                        }
275
                                }
276
                        }
277
                        else if ( par == STATSMERGETOFILE ) {
278
                                SETBASEPOSITION(pp,y);
279
                                if ( ISLESSPOS(*plspace,pp) ) {
280
                                        MesPrint("%d: %7l.%2is %10l:%10p",identity,millitime,timepart,
281
                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
282
                                }
283
                                else {
284
                                        y = 1000000000L;
285
                                        SETBASEPOSITION(pp,y);
286
                                        MULPOS(pp,100);
287
                                        if ( ISLESSPOS(*plspace,pp) ) {
288
                                                MesPrint("%d: %7l.%2is %10l:%11p",identity,millitime,timepart,
289
                                                S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
290
                                        }
291
                                        else {
292
                                                MULPOS(pp,10);
293
                                                if ( ISLESSPOS(*plspace,pp) ) {
294
                                                        MesPrint("%d: %7l.%2is %10l:%12p",identity,millitime,timepart,
295
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
296
                                                }
297
                                                else {
298
                                                MULPOS(pp,10);
299
                                                if ( ISLESSPOS(*plspace,pp) ) {
300
                                                        MesPrint("%d: %7l.%2is %10l:%13p",identity,millitime,timepart,
301
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
302
                                                }
303
                                                else {
304
                                                MULPOS(pp,10);
305
                                                if ( ISLESSPOS(*plspace,pp) ) {
306
                                                        MesPrint("%d: %7l.%2is %10l:%14p",identity,millitime,timepart,
307
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
308
                                                }
309
                                                else {
310
                                                MULPOS(pp,10);
311
                                                if ( ISLESSPOS(*plspace,pp) ) {
312
                                                        MesPrint("%d: %7l.%2is %10l:%15p",identity,millitime,timepart,
313
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
314
                                                }
315
                                                else {
316
                                                MULPOS(pp,10);
317
                                                if ( ISLESSPOS(*plspace,pp) ) {
318
                                                        MesPrint("%d: %7l.%2is %10l:%16p",identity,millitime,timepart,
319
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
320
                                                }
321
                                                else {
322
                                                MULPOS(pp,10);
323
                                                if ( ISLESSPOS(*plspace,pp) ) {
324
                                                        MesPrint("%d: %7l.%2is %10l:%17p",identity,millitime,timepart,
325
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
326
                                                }
327
                                                } } } } }
328
                                        }
329
                                }
330
                        } } else
331
#endif
332
                        {
333
                        if ( par == STATSSPLITMERGE || par == STATSPOSTSORT ) {
24✔
334
                                SETBASEPOSITION(pp,y);
24✔
335
                                if ( ISLESSPOS(*plspace,pp) ) {
24✔
336
                                        MesPrint("%7l.%2is %8l>%10l%3s%10l:%10p %s %s",
24✔
337
                                        millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
338
                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
24✔
339
/*
340
                                        MesPrint("%14s %17s %7l.%2is %8l>%10l%3s%10l:%10p",
341
                                        EXPRNAME(AR.CurExpr),AC.Commercial,millitime,timepart,
342
                                        AN.ninterms,S->GenTerms,toterms[par],S->TermsLeft,plspace);
343
*/
344
                                }
345
                                else {
346
                                        y = 1000000000L;
×
347
                                        SETBASEPOSITION(pp,y);
×
348
                                        MULPOS(pp,100);
×
349
                                        if ( ISLESSPOS(*plspace,pp) ) {
×
350
                                                MesPrint("%7l.%2is %8l>%10l%3s%10l:%11p %s %s",
×
351
                                                millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
352
                                                S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
×
353
                                        }
354
                                        else {
355
                                                MULPOS(pp,10);
×
356
                                                if ( ISLESSPOS(*plspace,pp) ) {
×
357
                                                        MesPrint("%7l.%2is %8l>%10l%3s%10l:%12p %s %s",
×
358
                                                        millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
359
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
×
360
                                                }
361
                                                else {
362
                                                MULPOS(pp,10);
×
363
                                                if ( ISLESSPOS(*plspace,pp) ) {
×
364
                                                        MesPrint("%7l.%2is %8l>%10l%3s%10l:%13p %s %s",
×
365
                                                        millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
366
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
×
367
                                                }
368
                                                else {
369
                                                MULPOS(pp,10);
×
370
                                                if ( ISLESSPOS(*plspace,pp) ) {
×
371
                                                        MesPrint("%7l.%2is %8l>%10l%3s%10l:%14p %s %s",
×
372
                                                        millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
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 %8l>%10l%3s%10l:%15p %s %s",
×
379
                                                        millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
380
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
×
381
                                                }
382
                                                else {
383
                                                MULPOS(pp,10);
×
384
                                                if ( ISLESSPOS(*plspace,pp) ) {
×
385
                                                        MesPrint("%7l.%2is %8l>%10l%3s%10l:%16p %s %s",
×
386
                                                        millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
387
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
×
388
                                                }
389
                                                else {
390
                                                MULPOS(pp,10);
×
391
                                                if ( ISLESSPOS(*plspace,pp) ) {
×
392
                                                        MesPrint("%7l.%2is %8l>%10l%3s%10l:%17p %s %s",
×
393
                                                        millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
394
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
×
395
                                                }
396
                                                } } } } }
397
                                        }
398
                                }
399
                        }
400
                        else if ( par == STATSMERGETOFILE ) {
×
401
                                SETBASEPOSITION(pp,y);
×
402
                                if ( ISLESSPOS(*plspace,pp) ) {
×
403
                                        MesPrint("%7l.%2is %10l:%10p",millitime,timepart,
×
404
                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
×
405
                                }
406
                                else {
407
                                        y = 1000000000L;
×
408
                                        SETBASEPOSITION(pp,y);
×
409
                                        MULPOS(pp,100);
×
410
                                        if ( ISLESSPOS(*plspace,pp) ) {
×
411
                                                MesPrint("%7l.%2is %10l:%11p",millitime,timepart,
×
412
                                                S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
×
413
                                        }
414
                                        else {
415
                                                MULPOS(pp,10);
×
416
                                                if ( ISLESSPOS(*plspace,pp) ) {
×
417
                                                        MesPrint("%7l.%2is %10l:%12p",millitime,timepart,
×
418
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
×
419
                                                }
420
                                                else {
421
                                                MULPOS(pp,10);
×
422
                                                if ( ISLESSPOS(*plspace,pp) ) {
×
423
                                                        MesPrint("%7l.%2is %10l:%13p",millitime,timepart,
×
424
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
×
425
                                                }
426
                                                else {
427
                                                MULPOS(pp,10);
×
428
                                                if ( ISLESSPOS(*plspace,pp) ) {
×
429
                                                        MesPrint("%7l.%2is %10l:%14p",millitime,timepart,
×
430
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
×
431
                                                }
432
                                                else {
433
                                                MULPOS(pp,10);
×
434
                                                if ( ISLESSPOS(*plspace,pp) ) {
×
435
                                                        MesPrint("%7l.%2is %10l:%15p",millitime,timepart,
×
436
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
×
437
                                                }
438
                                                else {
439
                                                MULPOS(pp,10);
×
440
                                                if ( ISLESSPOS(*plspace,pp) ) {
×
441
                                                        MesPrint("%7l.%2is %10l:%16p",millitime,timepart,
×
442
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
×
443
                                                }
444
                                                else {
445
                                                MULPOS(pp,10);
×
446
                                                if ( ISLESSPOS(*plspace,pp) ) {
×
447
                                                        MesPrint("%7l.%2is %10l:%17p",millitime,timepart,
×
448
                                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
×
449
                                                }
450
                                                } } } } }
451
                                        }
452
                                }
453
                        }
454
                } }
455
                else {
456
                if ( par == STATSMERGETOFILE ) {
6,026✔
457
                        if ( use_wtime ) {
362✔
458
                                MesPrint("WTime = %7l.%2i sec",millitime,timepart);
×
459
                        }
460
                        else {
461
                                MesPrint("Time = %7l.%2i sec",millitime,timepart);
362✔
462
                        }
463
                }
464
                else {
465
#if ( BITSINLONG > 32 )
466
                        if ( S->GenTerms >= 10000000000L ) {
5,664✔
467
                                if ( use_wtime ) {
×
NEW
468
                                        MesPrint("WTime = %7l.%2i sec   Generated terms = %16l%s",
×
469
                                                millitime,timepart,S->GenTerms,humanGenTermsText);
470
                                }
471
                                else {
NEW
472
                                        MesPrint("Time = %7l.%2i sec    Generated terms = %16l%s",
×
473
                                                millitime,timepart,S->GenTerms,humanGenTermsText);
474
                                }
475
                        }
476
                        else {
477
                                if ( use_wtime ) {
5,664✔
NEW
478
                                        MesPrint("WTime = %7l.%2i sec   Generated terms = %10l%s",
×
479
                                                millitime,timepart,S->GenTerms,humanGenTermsText);
480
                                }
481
                                else {
482
                                        MesPrint("Time = %7l.%2i sec    Generated terms = %10l%s",
5,664✔
483
                                                millitime,timepart,S->GenTerms,humanGenTermsText);
484
                                }
485
                        }
486
#else
487
                        if ( use_wtime ) {
488
                                MesPrint("WTime = %7l.%2i sec   Generated terms = %10l%s",
489
                                        millitime,timepart,S->GenTerms,humanGenTermsText);
490
                        }
491
                        else {
492
                                MesPrint("Time = %7l.%2i sec    Generated terms = %10l%s",
493
                                        millitime,timepart,S->GenTerms,humanGenTermsText);
494
                        }
495
#endif
496
                }
497
#if ( BITSINLONG > 32 )
498
                if ( par == STATSSPLITMERGE )
6,026✔
499
                        if ( S->TermsLeft >= 10000000000L ) {
×
NEW
500
                                MesPrint("%16s%8l Terms %s = %16l%s",EXPRNAME(AR.CurExpr),
×
501
                                AN.ninterms,FG.swmes[par],S->TermsLeft,humanTermsLeftText);
502
                        }
503
                        else {
NEW
504
                                MesPrint("%16s%8l Terms %s = %10l%s",EXPRNAME(AR.CurExpr),
×
505
                                AN.ninterms,FG.swmes[par],S->TermsLeft,humanTermsLeftText);
506
                        }
507
                else {
508
                        if ( S->TermsLeft >= 10000000000L ) {
6,026✔
509
#ifdef WITHPTHREADS
510
                                if ( identity > 0 && par == STATSPOSTSORT ) {
511
                                        MesPrint("%16s         Terms in thread = %16l%s",
512
                                        EXPRNAME(AR.CurExpr),S->TermsLeft,humanTermsLeftText);
513
                                }
514
                                else
515
#elif defined(WITHMPI)
516
                                if ( PF.me != MASTER && par == STATSPOSTSORT ) {
517
                                        MesPrint("%16s         Terms in process= %16l%s",
518
                                        EXPRNAME(AR.CurExpr),S->TermsLeft,humanTermsLeftText);
519
                                }
520
                                else
521
#endif
522
                                {
NEW
523
                                        MesPrint("%16s         Terms %s = %16l%s",
×
NEW
524
                                        EXPRNAME(AR.CurExpr),FG.swmes[par],S->TermsLeft,humanTermsLeftText);
×
525
                                }
526
                        }
527
                        else {
528
#ifdef WITHPTHREADS
529
                                if ( identity > 0 && par == STATSPOSTSORT ) {
4,026✔
530
                                        MesPrint("%16s         Terms in thread = %10l%s",
28✔
531
                                        EXPRNAME(AR.CurExpr),S->TermsLeft,humanTermsLeftText);
28✔
532
                                }
533
                                else
534
#elif defined(WITHMPI)
535
                                if ( PF.me != MASTER && par == STATSPOSTSORT ) {
536
                                        MesPrint("%16s         Terms in process= %10l%s",
537
                                        EXPRNAME(AR.CurExpr),S->TermsLeft,humanTermsLeftText);
538
                                }
539
                                else
540
#endif
541
                                {
542
                                        MesPrint("%16s         Terms %s = %10l%s",
5,998✔
543
                                        EXPRNAME(AR.CurExpr),FG.swmes[par],S->TermsLeft,humanTermsLeftText);
5,998✔
544
                                }
545
                        }
546
                }
547
#else
548
                if ( par == STATSSPLITMERGE )
549
                        MesPrint("%16s%8l Terms %s = %10l%s",EXPRNAME(AR.CurExpr),
550
                        AN.ninterms,FG.swmes[par],S->TermsLeft,humanTermsLeftText);
551
                else {
552
#ifdef WITHPTHREADS
553
                        if ( identity > 0 && par == STATSPOSTSORT ) {
554
                                MesPrint("%16s         Terms in thread = %10l%s",
555
                                EXPRNAME(AR.CurExpr),S->TermsLeft,humanTermsLeftText);
556
                        }
557
                        else
558
#elif defined(WITHMPI)
559
                        if ( PF.me != MASTER && par == STATSPOSTSORT ) {
560
                                MesPrint("%16s         Terms in process= %10l%s",
561
                                EXPRNAME(AR.CurExpr),S->TermsLeft,humanTermsLeftText);
562
                        }
563
                        else
564
#endif
565
                        {
566
                                MesPrint("%16s         Terms %s = %10l%s",
567
                                EXPRNAME(AR.CurExpr),FG.swmes[par],S->TermsLeft,humanTermsLeftText);
568
                        }
569
                }
570
#endif
571
                SETBASEPOSITION(pp,y);
6,026✔
572
                if ( ISLESSPOS(*plspace,pp) ) {
6,026✔
573
                        MesPrint("%24s Bytes used      = %10p%s",AC.Commercial,plspace,humanBytesText);
6,026✔
574
                }
575
                else {
576
                        y = 1000000000L;
×
577
                        SETBASEPOSITION(pp,y);
×
578
                        MULPOS(pp,100);
×
579
                        if ( ISLESSPOS(*plspace,pp) ) {
×
NEW
580
                                MesPrint("%24s Bytes used      =%11p%s",AC.Commercial,plspace,humanBytesText);
×
581
                        }
582
                        else {
583
                                MULPOS(pp,10);
×
584
                                if ( ISLESSPOS(*plspace,pp) ) {
×
NEW
585
                                MesPrint("%24s Bytes used     =%12p%s",AC.Commercial,plspace,humanBytesText);
×
586
                                }
587
                                else {
588
                                MULPOS(pp,10);
×
589
                                if ( ISLESSPOS(*plspace,pp) ) {
×
NEW
590
                                MesPrint("%24s Bytes used    =%13p%s",AC.Commercial,plspace,humanBytesText);
×
591
                                }
592
                                else {
593
                                MULPOS(pp,10);
×
594
                                if ( ISLESSPOS(*plspace,pp) ) {
×
NEW
595
                                MesPrint("%24s Bytes used   =%14p%s",AC.Commercial,plspace,humanBytesText);
×
596
                                }
597
                                else {
598
                                MULPOS(pp,10);
×
599
                                if ( ISLESSPOS(*plspace,pp) ) {
×
NEW
600
                                MesPrint("%24s Bytes used  =%15p%s",AC.Commercial,plspace,humanBytesText);
×
601
                                }
602
                                else {
603
                                MULPOS(pp,10);
×
604
                                if ( ISLESSPOS(*plspace,pp) ) {
×
NEW
605
                                MesPrint("%24s Bytes used =%16p%s",AC.Commercial,plspace,humanBytesText);
×
606
                                }
607
                                else {
608
                                MULPOS(pp,10);
×
609
                                if ( ISLESSPOS(*plspace,pp) ) {
×
NEW
610
                                MesPrint("%24s Bytes used=%17p%s",AC.Commercial,plspace,humanBytesText);
×
611
                                }
612
                                } } } } }
613
                        }
614
                } }
615
#ifdef WITHSTATS
616
                MesPrint("Total number of writes: %l, reads: %l, seeks, %l"
617
                        ,numwrites,numreads,numseeks);
618
                MesPrint("Total number of mallocs: %l, frees: %l"
619
                        ,nummallocs,numfrees);
620
#endif
621
                /* Put back the original LogHandle, it was changed if the statistics were
622
                 * not printed in the log file. */
623
                AC.LogHandle = oldLogHandle;
6,050✔
624

625
                MUNLOCK(ErrorMessageLock);
6,050✔
626
        }
627
}
628

629
/*
630
                 #] WriteStats : 
631
                 #[ NewSort :                                WORD NewSort()
632
*/
633
/**
634
 *                Starts a new sort.
635
 *                At the lowest level this is a 'main sort' with the struct according
636
 *                to the parameters in S0. At higher levels this is a sort for
637
 *                functions, subroutines or dollars.
638
 *                We prepare the arrays and structs.
639
 *
640
 *                @return Regular convention (OK -> 0)
641
 */
642

643
WORD NewSort(PHEAD0)
9,694,023✔
644
{
645
        GETBIDENTITY
646
        SORTING *S, **newFS;
9,694,023✔
647
        int i, newsize;
9,694,023✔
648
        if ( AN.SoScratC == 0 )
9,694,023✔
649
                AN.SoScratC = (UWORD *)Malloc1(2*(AM.MaxTal+2)*sizeof(UWORD),"NewSort");
4,354✔
650
        AR.sLevel++;
9,694,023✔
651
        if ( AR.sLevel >= AN.NumFunSorts ) {
9,694,023✔
652
                if ( AN.NumFunSorts == 0 ) newsize = 100;
5,642✔
653
                else newsize = 2*AN.NumFunSorts;
×
654
                newFS = (SORTING **)Malloc1((newsize+1)*sizeof(SORTING *),"FunSort pointers");
5,642✔
655
                for ( i = 0; i < AN.NumFunSorts; i++ ) newFS[i] = AN.FunSorts[i];
11,284✔
656
                for ( ; i <= newsize; i++ ) newFS[i] = 0;
575,484✔
657
                if ( AN.FunSorts ) M_free(AN.FunSorts,"FunSort pointers");
5,642✔
658
                AN.FunSorts = newFS; AN.NumFunSorts = newsize;
5,642✔
659
        }
660
        if ( AR.sLevel == 0 ) {
9,694,023✔
661

662
                numcompares = 0;
300,018✔
663

664
                AN.FunSorts[0] = AT.S0;
300,018✔
665
                if ( AR.PolyFun == 0 ) { AT.S0->PolyFlag = 0; }
300,018✔
666
                else if ( AR.PolyFunType == 1 ) { AT.S0->PolyFlag = 1; }
65,562✔
667
                else if ( AR.PolyFunType == 2 ) {
65,454✔
668
                        if ( AR.PolyFunExp == 2
65,454✔
669
                          || AR.PolyFunExp == 3 ) AT.S0->PolyFlag = 1;
65,454✔
670
                        else                      AT.S0->PolyFlag = 2;
65,106✔
671
                }
672
                AR.ShortSortCount = 0;
300,018✔
673
        }
674
        else {
675
                if ( AN.FunSorts[AR.sLevel] == 0 ) {
9,394,005✔
676
                        AN.FunSorts[AR.sLevel] = AllocSort(
2,580✔
677
                                AM.SLargeSize,AM.SSmallSize,AM.SSmallEsize,AM.STermsInSmall
678
                                        ,AM.SMaxPatches,AM.SMaxFpatches,AM.SIOsize,1);
679
                }
680
                AN.FunSorts[AR.sLevel]->PolyFlag = 0;
9,394,005✔
681
        }
682
        AT.SS = S = AN.FunSorts[AR.sLevel];
9,694,023✔
683
        S->sFill = S->sBuffer;
9,694,023✔
684
        S->lFill = S->lBuffer;
9,694,023✔
685
        S->lPatch = 0;
9,694,023✔
686
        S->fPatchN = 0;
9,694,023✔
687
        S->GenTerms = S->TermsLeft = S->GenSpace = S->SpaceLeft = 0;
9,694,023✔
688
        S->PoinFill = S->sPointer;
9,694,023✔
689
        *S->PoinFill = S->sFill;
9,694,023✔
690
        if ( AR.sLevel > 0 ) { S->PolyWise = 0; }
9,694,023✔
691
        PUTZERO(S->SizeInFile[0]); PUTZERO(S->SizeInFile[1]); PUTZERO(S->SizeInFile[2]);
9,694,023✔
692
        S->sTerms = 0;
9,694,023✔
693
        PUTZERO(S->file.POposition);
9,694,023✔
694
        S->stage4 = 0;
9,694,023✔
695
        if ( AR.sLevel > AN.MaxFunSorts ) AN.MaxFunSorts = AR.sLevel;
9,694,023✔
696
/*
697
        The next variable is for the staged sort only.
698
        It should be treated differently
699

700
        PUTZERO(AN.OldPosOut);
701
*/
702
        return(0);
9,694,023✔
703
}
704

705
/*
706
                 #] NewSort : 
707
                 #[ EndSort :                                WORD EndSort(PHEAD buffer,par)
708
*/
709
/**
710
 *                Finishes a sort.
711
 *                At AR.sLevel == 0 the output is to the regular output stream.
712
 *                When AR.sLevel > 0, the parameter par determines the actual output.
713
 *                The AR.sLevel will be popped.
714
 *                All ongoing stages are finished and if the sortfile is open
715
 *                it is closed.
716
 *                The statistics are printed when AR.sLevel == 0
717
 *                par == 0  Output to the buffer.
718
 *                par == 1  Sort for function arguments.
719
 *                          The output will be copied into the buffer.
720
 *                          It is assumed that this is in the WorkSpace.
721
 *                par == 2  Sort for $-variable. We return the address of the buffer
722
 *                          that contains the output in buffer (treated like WORD **).
723
 *                          We first catch the output in a file (unless we can
724
 *                          intercept things after the small buffer has been sorted)
725
 *                          Then we read from the file into a buffer.
726
 *                Only when par == 0 data compression can be attempted at AT.SS==AT.S0.
727
 *
728
 *                @param buffer buffer for output when needed
729
 *                @param par    See above
730
 *                @return If negative: error. If positive: number of words in output.
731
 */
732

733
LONG EndSort(PHEAD WORD *buffer, int par)
9,672,517✔
734
{
735
  GETBIDENTITY
736
  SORTING *S = AT.SS;
9,672,517✔
737
  WORD j, **ss, *to, *t;
9,672,517✔
738
  LONG sSpace, over, tover, spare, retval = 0, jj;
9,672,517✔
739
  POSITION position, pp;
9,672,517✔
740
  off_t lSpace;
9,672,517✔
741
  FILEHANDLE *fout = 0, *oldoutfile = 0, *newout = 0;
9,672,517✔
742

743
  if ( AM.exitflag && AR.sLevel == 0 ) return(0);
9,672,517✔
744
#ifdef WITHMPI 
745
  if( (retval = PF_EndSort()) > 0){
746
        oldoutfile = AR.outfile;
747
        retval = 0;
748
        goto RetRetval;
749
  } 
750
  else if(retval < 0){
751
        retval = -1; 
752
        goto RetRetval; 
753
  }
754
        /* PF_EndSort returned 0: for S != AM.S0 and slaves still do the regular sort */
755
#endif /* WITHMPI */
756
        oldoutfile = AR.outfile;
9,672,517✔
757
/*                PolyFlag repair action
758
        if ( S == AT.S0 ) {
759
                if ( AR.PolyFun == 0 ) { S->PolyFlag = 0; }
760
                else if ( AR.PolyFunType == 1 ) { S->PolyFlag = 1; }
761
                else if ( AR.PolyFunType == 2 ) {
762
                        if ( AR.PolyFunExp == 2
763
                          || AR.PolyFunExp == 3 ) S->PolyFlag = 1;
764
                        else                      S->PolyFlag = 2;
765
                }
766
                S->PolyWise = 0;
767
        }
768
        else {
769
                S->PolyFlag = S->PolyWise = 0;
770
        }
771
*/
772
        S->PolyWise = 0;
9,672,517✔
773
        *(S->PoinFill) = 0;
9,672,517✔
774
#ifdef SPLITTIME
775
                PrintTime((UBYTE *)"EndSort, before SplitMerge");
776
#endif
777
        S->sPointer[SplitMerge(BHEAD S->sPointer,S->sTerms)] = 0;
9,672,517✔
778
#ifdef SPLITTIME
779
                PrintTime((UBYTE *)"Endsort,  after SplitMerge");
780
#endif
781
        sSpace = 0;
9,672,497✔
782
        tover = over = S->sTerms;
9,672,497✔
783
        ss = S->sPointer;
9,672,497✔
784
        if ( over >= 0 ) {
9,672,497✔
785
                if ( S->lPatch > 0 || S->file.handle >= 0 ) {
9,672,497✔
786
                        ss[over] = 0;
261✔
787
                        sSpace = ComPress(ss,&spare);
261✔
788
                        S->TermsLeft -= over - spare;
261✔
789
                        if ( par == 1 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
261✔
790
                }
791
                else if ( S != AT.S0 ) {
9,672,236✔
792
                        ss[over] = 0;
9,393,792✔
793
                        if ( par == 2 ) {
9,393,792✔
794
                                sSpace = 3;
795
                                while ( ( t = *ss++ ) != 0 ) { sSpace += *t; }
3,468,782✔
796
                                if ( AN.tryterm > 0 && ( (sSpace+1)*sizeof(WORD) < (size_t)(AM.MaxTer) ) ) {
262,729✔
797
                                        to = TermMalloc("$-sort space");
90✔
798
                                }
799
                                else {
800
                                        LONG allocsp = sSpace+1;
262,639✔
801
                                        if ( allocsp < MINALLOC ) allocsp = MINALLOC;
262,639✔
802
                                        allocsp = ((allocsp+7)/8)*8;
262,639✔
803
                                        to = (WORD *)Malloc1(allocsp*sizeof(WORD),"$-sort space");
262,639✔
804
                                        if ( AN.tryterm > 0 ) AN.tryterm = 0;
262,639✔
805
                                }
806
                                *((WORD **)buffer) = to;
262,729✔
807
                                ss = S->sPointer;
262,729✔
808
                                while ( ( t = *ss++ ) != 0 ) {
3,468,782✔
809
                                        j = *t; while ( --j >= 0 ) *to++ = *t++;
50,423,681✔
810
                                }
811
                                *to = 0;
262,729✔
812
                                retval = sSpace + 1;
262,729✔
813
                        }
814
                        else {
815
                                to = buffer;
816
                                sSpace = 0;
817
                                while ( ( t = *ss++ ) != 0 ) {
32,107,647✔
818
                                        j = *t;
22,976,584✔
819
                                        if ( ( sSpace += j ) > AM.MaxTer/((LONG)sizeof(WORD)) ) {
22,976,584✔
820
                                                /* Too big! Get the total size for useful error message */
821
                                                while ( ( t = *ss++ ) != 0 ) {
×
822
                                                        sSpace += *t;
×
823
                                                }
824
                                                MLOCK(ErrorMessageLock);
×
825
                                                MesPrint("Sorted function argument too long (%d words). Increase MaxTermSize (%l words).", sSpace, AM.MaxTer/((LONG)sizeof(WORD)));
×
826
                                                MUNLOCK(ErrorMessageLock);
×
827
                                                retval = -1; goto RetRetval;
×
828
                                        }
829
                                        while ( --j >= 0 ) *to++ = *t++;
190,294,808✔
830
                                }
831
                                *to = 0;
9,131,063✔
832
                                retval = to - buffer;
9,131,063✔
833
                        }
834
                        goto RetRetval;
9,393,792✔
835
                }
836
                else {
837
                        POSITION oldpos;
278,444✔
838
                        if ( S == AT.S0 ) {
278,444✔
839
                                fout = AR.outfile;
278,444✔
840
                                *AR.CompressPointer = 0;
278,444✔
841
                                SeekScratch(AR.outfile,&position);
278,444✔
842
                        }
843
                        else {
844
                                fout = &(S->file);
845
                                PUTZERO(position);
846
                        }
847
                        oldpos = position;
278,444✔
848
                        S->TermsLeft = 0;
278,444✔
849
/*
850
                        Here we can go directly to the output.
851
*/
852
#ifdef WITHZLIB
853
                        { int oldgzipCompress = AR.gzipCompress;
278,444✔
854
                                AR.gzipCompress = 0;
278,444✔
855
#endif
856
                        if ( tover > 0 ) {
278,444✔
857
                                ss = S->sPointer;
248,348✔
858
                                while ( ( t = *ss++ ) != 0 ) {
3,537,419✔
859
                                        if ( *t ) S->TermsLeft++;
3,289,071✔
860
#ifdef WITHPTHREADS
861
                                        if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD t); }
2,131,167✔
862
                                        else
863
#endif
864
                                        if ( PutOut(BHEAD t,&position,fout,1) < 0 ) {
2,602,972✔
865
                                                retval = -1; goto RetRetval;
×
866
                                        }
867
                                }
868
                        }
869
#ifdef WITHPTHREADS
870
                        if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD 0); }
188,324✔
871
                        else
872
#endif
873
                        if ( FlushOut(&position,fout,1) ) {
266,332✔
874
                                retval = -1; goto RetRetval;
×
875
                        }
876
#ifdef WITHZLIB
877
                                AR.gzipCompress = oldgzipCompress;
278,444✔
878
                        }
879
#endif
880
#ifdef WITHPTHREADS
881
                        if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
188,324✔
882
#endif
883
#ifdef WITHMPI
884
                        if ( PF.me != MASTER && PF.exprtodo < 0 ) goto RetRetval;
885
#endif
886
                        DIFPOS(oldpos,position,oldpos);
266,332✔
887
                        S->SpaceLeft = BASEPOSITION(oldpos);
266,332✔
888
                        WriteStats(&oldpos,STATSPOSTSORT,NOCHECKLOGTYPE);
266,332✔
889
                        pp = oldpos;
266,332✔
890
                        goto RetRetval;
266,332✔
891
                }
892
        }
893
        else if ( par == 1 && newout == 0 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
×
894
        sSpace++;
261✔
895
        lSpace = sSpace + (S->lFill - S->lBuffer) - (LONG)S->lPatch*(AM.MaxTer/sizeof(WORD));
261✔
896
/*         Note wrt MaxTer and lPatch: each patch starts with space for decompression */
897
/*         Not needed if only large buffer, but needed when using files (?) */
898
        SETBASEPOSITION(pp,lSpace);
261✔
899
        MULPOS(pp,sizeof(WORD));
261✔
900
        if ( S->file.handle >= 0 ) {
261✔
901
                ADD2POS(pp,S->fPatches[S->fPatchN]);
34✔
902
        }
903
        if ( S == AT.S0 ) {
261✔
904
                if ( S->lPatch > 0 || S->file.handle >= 0 ) {
60✔
905
                        WriteStats(&pp,STATSSPLITMERGE,CHECKLOGTYPE);
60✔
906
                }
907
        }
908
        if ( par == 2 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
261✔
909
        if ( S->lPatch > 0 ) {
261✔
910
                if ( ( S->lPatch >= S->MaxPatches ) ||
261✔
911
                        ( ( (WORD *)(((UBYTE *)(S->lFill + sSpace)) + 2*AM.MaxTer) ) >= S->lTop ) ) {
247✔
912
/*
913
                        The large buffer is too full. Merge and write it
914
*/
915
#ifdef GZIPDEBUG
916
                        MLOCK(ErrorMessageLock);
917
                        MesPrint("%w EndSort: lPatch = %d, MaxPatches = %d,lFill = %x, sSpace = %ld, MaxTer = %d, lTop = %x"
918
                                        ,S->lPatch,S->MaxPatches,S->lFill,sSpace,AM.MaxTer/sizeof(WORD),S->lTop);
919
                        MUNLOCK(ErrorMessageLock);
920
#endif
921

922
                        if ( MergePatches(1) ) {
14✔
923
                                MLOCK(ErrorMessageLock);
×
924
                                MesCall("EndSort");
×
925
                                MUNLOCK(ErrorMessageLock);
×
926
                                retval = -1; goto RetRetval;
×
927
                        }
928
                        S->lPatch = 0;
14✔
929
                        pp = S->SizeInFile[1];
14✔
930
                        MULPOS(pp,sizeof(WORD));
14✔
931
#ifndef WITHPTHREADS
932
                        if ( S == AT.S0 )
6✔
933
#endif
934
                        {
8✔
935
                                POSITION pppp;
14✔
936
                                SETBASEPOSITION(pppp,0);
14✔
937
                                SeekFile(S->file.handle,&pppp,SEEK_CUR);
14✔
938
                                SeekFile(S->file.handle,&pp,SEEK_END);
14✔
939
                                SeekFile(S->file.handle,&pppp,SEEK_SET);
14✔
940
                                WriteStats(&pp,STATSMERGETOFILE,CHECKLOGTYPE);
14✔
941
                                UpdateMaxSize();
14✔
942
                        }
943
                }
944
                else {
945
                        S->Patches[S->lPatch++] = S->lFill;
247✔
946
                    to = (WORD *)(((UBYTE *)(S->lFill)) + AM.MaxTer);
247✔
947
                        if ( tover > 0 ) {
247✔
948
                                ss = S->sPointer;
247✔
949
                                while ( ( t = *ss++ ) != 0 ) {
2,025,494✔
950
                                        j = *t;
2,025,247✔
951
                                        if ( j < 0 ) j = t[1] + 2;
2,025,247✔
952
                                        while ( --j >= 0 ) *to++ = *t++;
45,516,299✔
953
                                }
954
                        }
955
                        *to++ = 0;
247✔
956
                        S->lFill = to;
247✔
957
                        if ( S->file.handle < 0 ) {
247✔
958
                                if ( MergePatches(2) ) {
213✔
959
                                        MLOCK(ErrorMessageLock);
×
960
                                        MesCall("EndSort");
×
961
                                        MUNLOCK(ErrorMessageLock);
×
962
                                        retval = -1; goto RetRetval;
×
963
                                }
964
                                if ( S == AT.S0 ) {
213✔
965
                                        pp = S->SizeInFile[2];
24✔
966
                                        MULPOS(pp,sizeof(WORD));
24✔
967
#ifdef WITHPTHREADS
968
                                        if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
20✔
969
#endif
970
                                        WriteStats(&pp,STATSPOSTSORT,NOCHECKLOGTYPE);
24✔
971
                                        UpdateMaxSize();
24✔
972
                                }
973
                                else {
974
                                        if ( par == 2 && newout->handle >= 0 ) {
189✔
975
                                                POSITION zeropos;
×
976
                                                PUTZERO(zeropos);
×
977
#ifdef ALLLOCK
978
                                                LOCK(newout->pthreadslock);
979
#endif
980
                                                SeekFile(newout->handle,&zeropos,SEEK_SET);
×
981
                                                to = (WORD *)Malloc1(BASEPOSITION(newout->filesize)+sizeof(WORD)*2
×
982
                                                                ,"$-buffer reading");
983
                                                if ( AN.tryterm > 0 ) AN.tryterm = 0;
×
984
                                                if ( ( retval = ReadFile(newout->handle,(UBYTE *)to,BASEPOSITION(newout->filesize)) ) !=
×
985
                                                                BASEPOSITION(newout->filesize) ) {
×
986
                                                        MLOCK(ErrorMessageLock);
×
987
                                                        MesPrint("Error reading information for $ variable");
×
988
                                                        MUNLOCK(ErrorMessageLock);
×
989
                                                        M_free(to,"$-buffer reading");
×
990
                                                        retval = -1;
×
991
                                                }
992
                                                else {
993
                                                        *((WORD **)buffer) = to;
×
994
                                                        retval /= sizeof(WORD);
×
995
                                                }
996
#ifdef ALLLOCK
997
                                                UNLOCK(newout->pthreadslock);
998
#endif
999
                                        }
1000
                                        else if ( newout->handle >= 0 ) {
189✔
1001
/*
1002
                                                We land here if par == 1 (function arg sort) and PutOut has created a file.
1003
                                                This means that the term is larger than SIOsize, which we ensure is at least
1004
                                                as large as MaxTermSize in setfile.c. Thus we know already that the term won't fit.
1005
*/
1006
TooLarge:
×
1007
                                                MLOCK(ErrorMessageLock);
×
1008
                                                MesPrint("(1)Output should fit inside a single term. Increase MaxTermSize?");
×
1009
                                                MesCall("EndSort");
×
1010
                                                MUNLOCK(ErrorMessageLock);
×
1011
                                                retval = -1; goto RetRetval;
×
1012
                                        }
1013
                                        else {
1014
                                                t = newout->PObuffer;
189✔
1015
                                                if ( par == 2 ) {
189✔
1016
                                                        jj = newout->POfill - t;
×
1017
                                                        if ( AN.tryterm > 0 && ( (jj+2)*sizeof(WORD) < (size_t)(AM.MaxTer) ) ) {
×
1018
                                                                to = TermMalloc("$-sort space");
×
1019
                                                        }
1020
                                                        else {
1021
                                                                LONG allocsp = jj+2;
×
1022
                                                                if ( allocsp < MINALLOC ) allocsp = MINALLOC;
×
1023
                                                                allocsp = ((allocsp+7)/8)*8;
×
1024
                                                                to = (WORD *)Malloc1(allocsp*sizeof(WORD),"$-sort space");
×
1025
                                                                if ( AN.tryterm > 0 ) AN.tryterm = 0;
×
1026
                                                        }
1027
                                                        *((WORD **)buffer) = to;
×
1028
                                                        NCOPY(to,t,jj);
×
1029
                                                        /* we should not set retval here in this par==2 case, it being 0 has meaning
1030
                                                           after RetRetval, and it is set properly there. */
1031
                                                }
1032
                                                else {
1033
                                                        j = newout->POfill - t;
189✔
1034
                                                        to = buffer;
189✔
1035
                                                        if ( to >= AT.WorkSpace && to < AT.WorkTop && to+j > AT.WorkTop )
189✔
1036
                                                                goto WorkSpaceError;
×
1037
                                                        if ( j > AM.MaxTer ) {
189✔
1038
                                                                MLOCK(ErrorMessageLock);
×
1039
                                                                MesPrint("Encountered term of size: %d words.", j/(LONG)sizeof(WORD) );
×
1040
                                                                MUNLOCK(ErrorMessageLock);
×
1041
                                                                goto TooLarge;
×
1042
                                                        }
1043
                                                        NCOPY(to,t,j);
9,553,026✔
1044
                                                        retval = to - buffer - 1;
189✔
1045
                                                }
1046
                                        }
1047
                                }
1048
                                goto RetRetval;
213✔
1049
                        }
1050
                        if ( MergePatches(1) ) { /* --> SortFile */
34✔
1051
                                MLOCK(ErrorMessageLock);
×
1052
                                MesCall("EndSort");
×
1053
                                MUNLOCK(ErrorMessageLock);
×
1054
                                retval = -1; goto RetRetval;
×
1055
                        }
1056
                        UpdateMaxSize();
34✔
1057
                        pp = S->SizeInFile[1];
34✔
1058
                        MULPOS(pp,sizeof(WORD));
34✔
1059
#ifndef WITHPTHREADS
1060
                        if ( S == AT.S0 )
10✔
1061
#endif
1062
                        {
1063
                                POSITION pppp;
30✔
1064
                                SETBASEPOSITION(pppp,0);
30✔
1065
                                SeekFile(S->file.handle,&pppp,SEEK_CUR);
30✔
1066
                                SeekFile(S->file.handle,&pp,SEEK_END);
30✔
1067
                                SeekFile(S->file.handle,&pppp,SEEK_SET);
30✔
1068
                                WriteStats(&pp,STATSMERGETOFILE,CHECKLOGTYPE);
30✔
1069
                        }
1070
#ifdef WITHERRORXXX
1071
                        if ( S != AT.S0 ) {
1072
/*
1073
                                This is wrong! We have sorted to the sort file.
1074
                                Things are not sitting in the output yet.
1075
*/
1076
                                if ( newout->handle >= 0 ) goto TooLarge;
1077
                                t = newout->PObuffer;
1078
                                j = newout->POfill - t;
1079
                                to = buffer;
1080
                                if ( to >= AT.WorkSpace && to < AT.WorkTop && to+j > AT.WorkTop )
1081
                                        goto WorkSpaceError;
1082
                                if ( j > AM.MaxTer ) goto TooLarge;
1083
                                NCOPY(to,t,j);
1084
                                goto RetRetval;
1085
                        }
1086
#endif
1087
                }
1088
        }
1089
        if ( S->file.handle >= 0 ) {
48✔
1090
#ifdef GZIPDEBUG
1091
                MLOCK(ErrorMessageLock);
1092
                MesPrint("%w EndSort: fPatchN = %d, lPatch = %d, position = %12p"
1093
                        ,S->fPatchN,S->lPatch,&(S->fPatches[S->fPatchN]));
1094
                MUNLOCK(ErrorMessageLock);
1095
#endif
1096
                if ( S->lPatch <= 0 ) {
48✔
1097
                        StageSort(&(S->file));
14✔
1098
                        position = S->fPatches[S->fPatchN];
14✔
1099
                        ss = S->sPointer;
14✔
1100
                        if ( *ss ) {
14✔
1101
                                *AR.CompressPointer = 0;
14✔
1102
#ifdef WITHZLIB
1103
                                if ( S == AT.S0 && AR.NoCompress == 0 && AR.gzipCompress > 0 )
14✔
1104
                                        S->fpcompressed[S->fPatchN] = 1;
14✔
1105
                                else
1106
                                        S->fpcompressed[S->fPatchN] = 0;
×
1107
                                SetupOutputGZIP(&(S->file));
14✔
1108
#endif
1109
                                while ( ( t = *ss++ ) != 0 ) {
40✔
1110
                                        if ( PutOut(BHEAD t,&position,&(S->file),1) < 0 ) {
26✔
1111
                                                retval = -1; goto RetRetval;
×
1112
                                        }
1113
                                }
1114
                                if ( FlushOut(&position,&(S->file),1) ) {
14✔
1115
                                        retval = -1; goto RetRetval;
×
1116
                                }
1117
                                ++(S->fPatchN);
14✔
1118
                                S->fPatches[S->fPatchN] = position;
14✔
1119
                                UpdateMaxSize();
14✔
1120
#ifdef GZIPDEBUG
1121
                                MLOCK(ErrorMessageLock);
1122
                                MesPrint("%w EndSort+: fPatchN = %d, lPatch = %d, position = %12p"
1123
                                        ,S->fPatchN,S->lPatch,&(S->fPatches[S->fPatchN]));
1124
                                MUNLOCK(ErrorMessageLock);
1125
#endif
1126
                        }
1127
                }
1128
                AR.Stage4Name = 0;
48✔
1129
#ifdef WITHPTHREADS
1130
                if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
32✔
1131
                        if ( S->file.handle >= 0 ) {
1132
                                SynchFile(S->file.handle);
1133
                        }
1134
                }
1135
#endif
1136
                UpdateMaxSize();
48✔
1137
                if ( MergePatches(0) ) {
48✔
1138
                        MLOCK(ErrorMessageLock);
×
1139
                        MesCall("EndSort");
×
1140
                        MUNLOCK(ErrorMessageLock);
×
1141
                        retval = -1; goto RetRetval;
×
1142
                }
1143
                S->stage4 = 0;
48✔
1144
#ifdef WITHPTHREADS
1145
                if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
32✔
1146
#endif
1147
                pp = S->SizeInFile[0];
48✔
1148
                MULPOS(pp,sizeof(WORD));
48✔
1149
                WriteStats(&pp,STATSPOSTSORT,NOCHECKLOGTYPE);
48✔
1150
                UpdateMaxSize();
48✔
1151
        }
1152
RetRetval:
×
1153

1154
#ifdef WITHMPI
1155
        /* NOTE: PF_EndSort has been changed such that it sets S->TermsLeft. (TU 30 Jun 2011) */
1156
        if ( AR.sLevel == 0 && (PF.me == MASTER || PF.exprtodo >= 0) ) {
1157
                Expressions[AR.CurExpr].counter = S->TermsLeft;
1158
                Expressions[AR.CurExpr].size = pp;
1159
        }
1160
#else
1161
        if ( AR.sLevel == 0 ) {
9,672,497✔
1162
                Expressions[AR.CurExpr].counter = S->TermsLeft;
278,504✔
1163
                Expressions[AR.CurExpr].size = pp;
278,504✔
1164
        }/*if ( AR.sLevel == 0 )*/
1165
#endif
1166
/*:[25nov2003 mt]*/
1167
        if ( S->file.handle >= 0 && ( par != 1 ) && ( par != 2 ) ) {
9,672,497✔
1168
                                /* sortfile is still open */
1169
                UpdateMaxSize();
×
1170
#ifdef WITHZLIB
1171
                ClearSortGZIP(&(S->file));
×
1172
#endif
1173
                CloseFile(S->file.handle);
×
1174
                S->file.handle = -1;
×
1175
                remove(S->file.name);
×
1176
#ifdef GZIPDEBUG
1177
                MLOCK(ErrorMessageLock);
1178
                MesPrint("%wEndSort: sortfile %s removed",S->file.name);
1179
                MUNLOCK(ErrorMessageLock);
1180
#endif
1181
        }
1182
        AR.outfile = oldoutfile;
9,672,497✔
1183
        AR.sLevel--;
9,672,497✔
1184
        if ( AR.sLevel >= 0 ) AT.SS = AN.FunSorts[AR.sLevel];
9,672,497✔
1185
        if ( par == 1 ) {
9,672,497✔
1186
                if ( retval < 0 ) {
9,065,358✔
1187
                        UpdateMaxSize();
×
1188
                        if ( newout ) {
×
1189
                                DeAllocFileHandle(newout);
×
1190
                                newout = 0;
×
1191
                        }
1192
                }
1193
                else if ( newout ) {
9,065,358✔
1194
                  if ( newout->handle >= 0 ) {
201✔
1195
                        MLOCK(ErrorMessageLock);
×
1196
                        MesPrint("(2)Output should fit inside a single term. Increase MaxTermSize?");
×
1197
                        MesCall("EndSort");
×
1198
                        MUNLOCK(ErrorMessageLock);
×
1199
                        Terminate(-1);
×
1200
                  }
1201
                  else if ( newout->POfill > newout->PObuffer ) {
201✔
1202
/*
1203
                        Here we have to copy the contents of the 'file' into
1204
                        the buffer. We assume that this buffer lies in the WorkSpace.
1205
                        Hence
1206
*/
1207
                        j = newout->POfill-newout->PObuffer;
201✔
1208
                        if ( buffer >= AT.WorkSpace && buffer < AT.WorkTop && buffer+j > AT.WorkTop )
201✔
1209
                                goto WorkSpaceError;
×
1210
                        else {
1211
                                to = buffer; t = newout->PObuffer;
1212
                                while ( j-- > 0 ) *to++ = *t++;
9,769,158✔
1213
                        }
1214
                        UpdateMaxSize();
201✔
1215
                  }
1216
                  DeAllocFileHandle(newout);
201✔
1217
                  newout = 0;
201✔
1218
                }
1219
        }
1220
        else if ( par == 2 ) {
607,139✔
1221
                if ( newout ) {
262,729✔
1222
                        if ( retval == 0 ) {
×
1223
                          if ( newout->handle >= 0 ) {
×
1224
/*
1225
                                output resides at the moment in a file
1226
                                Find the size, make a buffer, copy into the buffer and clean up.
1227
*/
1228
                                POSITION zeropos;
×
1229
                                PUTZERO(position);
×
1230
#ifdef ALLLOCK
1231
                                LOCK(newout->pthreadslock);
1232
#endif
1233
                                SeekFile(newout->handle,&position,SEEK_END);
×
1234
                                PUTZERO(zeropos);
×
1235
                                SeekFile(newout->handle,&zeropos,SEEK_SET);
×
1236
                                to = (WORD *)Malloc1(BASEPOSITION(position)+sizeof(WORD)*3
×
1237
                                                ,"$-buffer reading");
1238
                                if ( AN.tryterm > 0 ) AN.tryterm = 0;
×
1239
                                if ( ( retval = ReadFile(newout->handle,(UBYTE *)to,BASEPOSITION(position)) ) !=
×
1240
                                BASEPOSITION(position) ) {
×
1241
                                        MLOCK(ErrorMessageLock);
×
1242
                                        MesPrint("Error reading information for $ variable");
×
1243
                                        MUNLOCK(ErrorMessageLock);
×
1244
                                        M_free(to,"$-buffer reading");
×
1245
                                        retval = -1;
×
1246
                                }
1247
                                else {
1248
                                        *((WORD **)buffer) = to;
×
1249
                                        retval /= sizeof(WORD);
×
1250
                                }
1251
#ifdef ALLLOCK
1252
                                UNLOCK(newout->pthreadslock);
1253
#endif
1254
                          }
1255
                          else {
1256
/*
1257
                                output resides in the cache buffer and the file was never opened
1258
*/
1259
                                LONG wsiz = newout->POfill - newout->PObuffer;
×
1260
                                if ( AN.tryterm > 0 && ( (wsiz+2)*sizeof(WORD) < (size_t)(AM.MaxTer) ) ) {
×
1261
                                        to = TermMalloc("$-sort space");
×
1262
                                }
1263
                                else {
1264
                                        LONG allocsp = wsiz+2;
×
1265
                                        if ( allocsp < MINALLOC ) allocsp = MINALLOC;
×
1266
                                        allocsp = ((allocsp+7)/8)*8;
×
1267
                                        to = (WORD *)Malloc1(allocsp*sizeof(WORD),"$-buffer reading");
×
1268
                                        if ( AN.tryterm > 0 ) AN.tryterm = 0;
×
1269
                                }
1270
                                *((WORD **)buffer) = to; t = newout->PObuffer;
×
1271
                                retval = wsiz;
×
1272
                                NCOPY(to,t,wsiz);
×
1273
                          }
1274
                        }
1275
                        UpdateMaxSize();
×
1276
                        DeAllocFileHandle(newout);
×
1277
                        newout = 0;
×
1278
                }
1279
        }
1280
        else {
1281
                if ( newout ) {
344,410✔
1282
                        DeAllocFileHandle(newout);
×
1283
                        newout = 0;
×
1284
                }
1285
        }
1286
/*
1287
        if ( AR.sLevel < 0 ) {
1288
                MesPrint(" number of calls to compare was %l",numcompares);
1289
        }
1290
*/
1291
        return(retval);
1292
WorkSpaceError:
×
1293
        MLOCK(ErrorMessageLock);
×
1294
        MesWork();
×
1295
        MesCall("EndSort");
×
1296
        MUNLOCK(ErrorMessageLock);
×
1297
        Terminate(-1);
×
1298
        return(-1);
×
1299
}
1300

1301
/*
1302
                 #] EndSort : 
1303
                 #[ PutIn :                                        LONG PutIn(handle,position,buffer,take,npat)
1304
*/
1305
/**
1306
 *        Reads a new patch from position in file handle.
1307
 *        It is put at buffer, anything after take is moved forward.
1308
 *        This would be part of a term that hasn't been used yet.
1309
 *        Because of this there should be some space before the start of the buffer
1310
 *
1311
 *        @param file     The file system from which to read
1312
 *        @param position The position from which to read
1313
 *        @param buffer   The buffer into which to read
1314
 *        @param take     The unused tail should be moved before the buffer
1315
 *        @param npat                The number of the patch. Is needed if the information
1316
 *                        was compressed with gzip, because each patch has its
1317
 *                        own independent gzip encoding.
1318
 */
1319

1320
LONG PutIn(FILEHANDLE *file, POSITION *position, WORD *buffer, WORD **take, int npat)
598✔
1321
{
1322
        LONG i, RetCode;
598✔
1323
        WORD *from, *to;
598✔
1324
#ifndef WITHZLIB
1325
        DUMMYUSE(npat);
1326
#endif
1327
        from = buffer + ( file->POsize * sizeof(UBYTE) )/sizeof(WORD);
598✔
1328
        i = from - *take;
598✔
1329
        if ( i*((LONG)(sizeof(WORD))) > AM.MaxTer ) {
598✔
1330
                MLOCK(ErrorMessageLock);
×
1331
                MesPrint("Problems in PutIn");
×
1332
                MUNLOCK(ErrorMessageLock);
×
1333
                Terminate(-1);
×
1334
        }
1335
        to = buffer;
1336
        while ( --i >= 0 ) *--to = *--from;
950✔
1337
        *take = to;
598✔
1338
#ifdef WITHZLIB
1339
        if ( ( RetCode = FillInputGZIP(file,position,(UBYTE *)buffer
598✔
1340
                                                                        ,file->POsize,npat) ) < 0 ) {
1341
                MLOCK(ErrorMessageLock);
×
1342
                MesPrint("PutIn: We have RetCode = %x while reading %x bytes",
×
1343
                        RetCode,file->POsize);
1344
                MUNLOCK(ErrorMessageLock);
×
1345
                Terminate(-1);
×
1346
        }
1347
#else
1348
#ifdef ALLLOCK
1349
        LOCK(file->pthreadslock);
1350
#endif
1351
        SeekFile(file->handle,position,SEEK_SET);
1352
        if ( ( RetCode = ReadFile(file->handle,(UBYTE *)buffer,file->POsize) ) < 0 ) {
1353
#ifdef ALLLOCK
1354
                UNLOCK(file->pthreadslock);
1355
#endif
1356
                MLOCK(ErrorMessageLock);
1357
                MesPrint("PutIn: We have RetCode = %x while reading %x bytes",
1358
                        RetCode,file->POsize);
1359
                MUNLOCK(ErrorMessageLock);
1360
                Terminate(-1);
1361
        }
1362
#ifdef ALLLOCK
1363
        UNLOCK(file->pthreadslock);
1364
#endif
1365
#endif
1366
        return(RetCode);
598✔
1367
}
1368

1369
/*
1370
                 #] PutIn : 
1371
                 #[ Sflush :                                        WORD Sflush(file)
1372
*/
1373
/**
1374
 *        Puts the contents of a buffer to output
1375
 *        Only to be used when there is a single patch in the large buffer.
1376
 *
1377
 *        @param fi  The filesystem (or its cache) to which the patch should be written
1378
 */
1379

1380
WORD Sflush(FILEHANDLE *fi)
×
1381
{
1382
        LONG size, RetCode;
×
1383
#ifdef WITHZLIB
1384
        GETIDENTITY
1385
        int dobracketindex = 0;
×
1386
        if ( AR.sLevel <= 0 && Expressions[AR.CurExpr].newbracketinfo
×
1387
                && ( fi == AR.outfile || fi == AR.hidefile ) ) dobracketindex = 1;
×
1388
#endif
1389
        if ( fi->handle < 0 ) {
×
1390
                if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
×
1391
#ifdef GZIPDEBUG
1392
                        MLOCK(ErrorMessageLock);
1393
                        MesPrint("%w Sflush created scratch file %s",fi->name);
1394
                        MUNLOCK(ErrorMessageLock);
1395
#endif
1396
                        fi->handle = (WORD)RetCode;
×
1397
                        PUTZERO(fi->filesize);
×
1398
                        PUTZERO(fi->POposition);
×
1399
                }
1400
                else {
1401
                        MLOCK(ErrorMessageLock);
×
1402
                        MesPrint("Cannot create scratch file %s",fi->name);
×
1403
                        MUNLOCK(ErrorMessageLock);
×
1404
                        return(-1);
×
1405
                }
1406
        }
1407
#ifdef WITHZLIB
1408
        if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
×
1409
        && dobracketindex == 0 ) {
×
1410
                if ( FlushOutputGZIP(fi) ) return(-1);
×
1411
                fi->POfill = fi->PObuffer;
×
1412
        }
1413
        else
1414
#endif
1415
        {
1416
#ifdef ALLLOCK
1417
          LOCK(fi->pthreadslock);
1418
#endif
1419
          size = (fi->POfill-fi->PObuffer)*sizeof(WORD);
×
1420
          SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
×
1421
          if ( WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),size) != size ) {
×
1422
#ifdef ALLLOCK
1423
                UNLOCK(fi->pthreadslock);
1424
#endif
1425
                MLOCK(ErrorMessageLock);
×
1426
                MesPrint("Write error while finishing sort. Disk full?");
×
1427
                MUNLOCK(ErrorMessageLock);
×
1428
                return(-1);
×
1429
          }
1430
          ADDPOS(fi->filesize,size);
×
1431
          ADDPOS(fi->POposition,size);
×
1432
          fi->POfill = fi->PObuffer;
×
1433
#ifdef ALLLOCK
1434
          UNLOCK(fi->pthreadslock);
1435
#endif
1436
        }
1437
        return(0);
1438
}
1439

1440
/*
1441
                 #] Sflush : 
1442
                 #[ PutOut :                                        WORD PutOut(term,position,file,ncomp)
1443
*/
1444
/**
1445
 *        Routine writes one term to file handle at position. It returns
1446
 *        the new value of the position.
1447
 *
1448
 *        NOTE:
1449
 *                For 'final output' we may have to index the brackets.
1450
 *                See the struct BRACKETINDEX.
1451
 *                We should maintain:
1452
 *                1: a list with brackets
1453
 *                        array with the brackets
1454
 *                2: a list of objects of type BRACKETINDEX. It contains
1455
 *                        array with either pointers or offsets to the list of brackets.
1456
 *                        starting positions in the file.
1457
 *                The index may be tied to a maximum size. In that case we may have to
1458
 *                prune the list occasionally.
1459
 *
1460
 *        @param term     The term to be written
1461
 *        @param position The position in the file. Afterwards it is updated
1462
 *        @param fi       The file (or its cache) to which should be written
1463
 *        @param ncomp    Information about what type of compression should be used
1464
 */
1465

1466
WORD PutOut(PHEAD WORD *term, POSITION *position, FILEHANDLE *fi, WORD ncomp)
22,692,689✔
1467
{
1468
        GETBIDENTITY
1469
        WORD i, *p, ret, *r, *rr, j, k, first;
22,692,689✔
1470
        int dobracketindex = 0;
22,692,689✔
1471
        LONG RetCode;
22,692,689✔
1472

1473
        if ( AT.SS != AT.S0 ) {
22,692,689✔
1474
/*
1475
                For this case no compression should be used
1476
*/
1477
                if ( ( i = *term ) <= 0 ) return(0);
713,125✔
1478
                ret = i;
713,125✔
1479
                ADDPOS(*position,i*sizeof(WORD));
713,125✔
1480
                p = fi->POfill;
713,125✔
1481
                do {
10,161,642✔
1482
                        if ( p >= fi->POstop ) {
10,161,642✔
1483
                                if ( fi->handle < 0 ) {
×
1484
                                        if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
×
1485
#ifdef GZIPDEBUG
1486
                                                MLOCK(ErrorMessageLock);
1487
                                                MesPrint("%w PutOut created sortfile %s",fi->name);
1488
                                                MUNLOCK(ErrorMessageLock);
1489
#endif
1490
                                                fi->handle = (WORD)RetCode;
×
1491
                                                PUTZERO(fi->filesize);
×
1492
                                                PUTZERO(fi->POposition);
×
1493
/*
1494
                                                Should not be here anymore?
1495
#ifdef WITHZLIB
1496
                                                fi->ziobuffer = 0;
1497
#endif
1498
*/
1499
                                        }
1500
                                        else {
1501
                                                MLOCK(ErrorMessageLock);
×
1502
                                                MesPrint("Cannot create scratch file %s",fi->name);
×
1503
                                                MUNLOCK(ErrorMessageLock);
×
1504
                                                return(-1);
×
1505
                                        }
1506
                                }
1507
#ifdef ALLLOCK
1508
                                LOCK(fi->pthreadslock);
1509
#endif
1510
                                if ( fi == AR.hidefile ) {
×
1511
                                        LOCK(AS.inputslock);
×
1512
                                }
1513
                                SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
×
1514
                                if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize) ) != fi->POsize ) {
×
1515
                                        if ( fi == AR.hidefile ) {
×
1516
                                                UNLOCK(AS.inputslock);
×
1517
                                        }
1518
#ifdef ALLLOCK
1519
                                        UNLOCK(fi->pthreadslock);
1520
#endif
1521
                                        MLOCK(ErrorMessageLock);
×
1522
                                        MesPrint("Write error during sort. Disk full?");
×
1523
                                        MesPrint("Attempt to write %l bytes on file %d at position %15p",
×
1524
                                                                fi->POsize,fi->handle,&(fi->POposition));
1525
                                        MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
×
1526
                                        MUNLOCK(ErrorMessageLock);
×
1527
                                        return(-1);
×
1528
                                }
1529
                                ADDPOS(fi->filesize,fi->POsize);
×
1530
                                p = fi->PObuffer;
×
1531
                                ADDPOS(fi->POposition,fi->POsize);
×
1532
                                if ( fi == AR.hidefile ) {
×
1533
                                        UNLOCK(AS.inputslock);
3,386,554✔
1534
                                }
1535
#ifdef ALLLOCK
1536
                                UNLOCK(fi->pthreadslock);
1537
#endif
1538
#ifdef WITHPTHREADS
1539
                                if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
1540
                                        if ( fi->handle >= 0 ) SynchFile(fi->handle);
1541
                                }
1542
#endif
1543
                        } 
1544
                        *p++ = *term++;
10,161,642✔
1545
                } while ( --i > 0 );
10,161,642✔
1546
                fi->POfull = fi->POfill = p;
713,125✔
1547
                return(ret);
713,125✔
1548
        }
1549
        if ( ( AP.PreDebug & DUMPOUTTERMS ) == DUMPOUTTERMS ) {
21,979,564✔
1550
                        MLOCK(ErrorMessageLock);
×
1551
#ifdef WITHPTHREADS
1552
                        snprintf((char *)(THRbuf),100,"PutOut(%d)",AT.identity);
1553
                        PrintTerm(term,(char *)(THRbuf));
1554
#else
1555
                        PrintTerm(term,"PutOut");
1556
#endif
1557
                        MesPrint("ncomp = %d, AR.NoCompress = %d, AR.sLevel = %d",ncomp,AR.NoCompress,AR.sLevel);
×
1558
                        MesPrint("File %s, position %p",fi->name,position);
×
1559
                        MUNLOCK(ErrorMessageLock);
8,069,876✔
1560
        }
1561

1562
        if ( AR.sLevel <= 0 && Expressions[AR.CurExpr].newbracketinfo
21,979,564✔
1563
                && ( fi == AR.outfile || fi == AR.hidefile ) ) dobracketindex = 1;
62,526✔
1564
        r = rr = AR.CompressPointer;
21,979,564✔
1565
        first = j = k = ret = 0;
21,979,564✔
1566
        if ( ( i = *term ) != 0 ) {
21,979,564✔
1567
                if ( i < 0 ) {                        /* Compressed term */
21,979,564✔
1568
                        i = term[1] + 2;
12✔
1569
                        if ( fi == AR.outfile || fi == AR.hidefile ) {
12✔
1570
                                MLOCK(ErrorMessageLock);
×
1571
                                MesPrint("Ran into precompressed term");
×
1572
                                MUNLOCK(ErrorMessageLock);
×
1573
                                Crash();
×
1574
                                return(-1);
×
1575
                        }
1576
                }
1577
                else if ( !AR.NoCompress && ( ncomp > 0 ) && AR.sLevel <= 0 ) {        /* Must compress */
21,979,552✔
1578
                        if ( dobracketindex ) {
8,676,978✔
1579
                                PutBracketInIndex(BHEAD term,position);
62,526✔
1580
                        }
1581
                        j = *r++ - 1;
8,676,978✔
1582
                        p = term + 1;
8,676,978✔
1583
                        i--;
8,676,978✔
1584
                        if ( AR.PolyFun ) {
8,676,978✔
1585
                                WORD *polystop, *sa;
71,508✔
1586
                                sa = p + i;
71,508✔
1587
                                sa -= ABS(sa[-1]);
71,508✔
1588
                                polystop = p;
71,508✔
1589
                                while ( polystop < sa && *polystop != AR.PolyFun ) {
86,418✔
1590
                                        polystop += polystop[1];
14,910✔
1591
                                }
1592
                                if ( polystop < sa ) {
71,508✔
1593
                                        if ( AR.PolyFunType == 2 ) polystop[2] &= ~MUSTCLEANPRF;
71,508✔
1594
                                        while ( i > 0 && j > 0 && *p == *r && p < polystop ) {
142,278✔
1595
                                                i--; j--; k--; p++; r++;
70,770✔
1596
                                        }
1597
                                }
1598
                                else {
1599
                                        while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
×
1600
                                }
1601
                        }
1602
#ifdef WITHFLOAT
1603
                        else if ( AC.DefaultPrecision ) {
8,605,470✔
1604
                                WORD *floatstop, *sa;
8,605,470✔
1605
                                sa = p + i;
8,605,470✔
1606
                                sa -= ABS(sa[-1]);
8,605,470✔
1607
                                floatstop = p;
8,605,470✔
1608
                                while ( floatstop < sa && *floatstop != FLOATFUN ) {
20,094,400✔
1609
                                        floatstop += floatstop[1];
11,488,930✔
1610
                                }
1611
                                if ( floatstop < sa ) {
8,605,470✔
1612
                                        while ( i > 0 && j > 0 && *p == *r && p < floatstop ) {
1,266✔
1613
                                                i--; j--; k--; p++; r++;
684✔
1614
                                        }
1615
                                }
1616
                                else {
1617
                                        while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
50,304,167✔
1618
                                }
1619
                        }
1620
#endif
1621
                        else {
1622
                                WORD *sa;
×
1623
                                sa = p + i;
×
1624
                                sa -= ABS(sa[-1]);
×
1625
                                while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
×
1626
                        }
1627
                        if ( k > -2 ) {
8,676,978✔
1628
nocompress:
492,948✔
1629
                                j = i = *term;
648,636✔
1630
                                k = 0;
648,636✔
1631
                                p = term;
648,636✔
1632
                                r = rr;
648,636✔
1633
                                NCOPY(r,p,j);
30,986,040✔
1634
                        }
1635
                        else {
1636
                                *rr = *term;
8,184,030✔
1637
                                term = p;
8,184,030✔
1638
                                j = i;
8,184,030✔
1639
                                NCOPY(r,p,j);
113,515,503✔
1640
                                j = i;
8,184,030✔
1641
                                i += 2;
8,184,030✔
1642
                                first = 2;
8,184,030✔
1643
                        }
1644
/*                                        Sabotage getting into the coefficient next time */
1645
                        r[-(ABS(r[-1]))] = 0;
8,832,666✔
1646
                        if ( r >= AR.ComprTop ) {
8,832,666✔
1647
                                MLOCK(ErrorMessageLock);
×
1648
                                MesPrint("CompressSize of %10l is insufficient",AM.CompressSize);
×
1649
                                MUNLOCK(ErrorMessageLock);
×
1650
                                Crash();
×
1651
                                return(-1);
×
1652
                        }
1653
                }
1654
                else if ( !AR.NoCompress && ( ncomp < 0 ) && AR.sLevel <= 0 ) {
13,302,574✔
1655
                                /* No compress but put in compress buffer anyway */
1656
                        if ( dobracketindex ) {
155,688✔
1657
                                PutBracketInIndex(BHEAD term,position);
×
1658
                        }
1659
                        j = *r++ - 1;
155,688✔
1660
                        p = term + 1;
155,688✔
1661
                        i--;
155,688✔
1662
                        if ( AR.PolyFun ) {
155,688✔
1663
                                WORD *polystop, *sa;
29,856✔
1664
                                sa = p + i;
29,856✔
1665
                                sa -= ABS(sa[-1]);
29,856✔
1666
                                polystop = p;
29,856✔
1667
                                while ( polystop < sa && *polystop != AR.PolyFun ) {
29,856✔
1668
                                        polystop += polystop[1];
×
1669
                                }
1670
                                if ( polystop < sa ) {
29,856✔
1671
                                        if ( AR.PolyFunType == 2 ) polystop[2] &= ~MUSTCLEANPRF;
29,856✔
1672
                                        while ( i > 0 && j > 0 && *p == *r && p < polystop ) {
29,856✔
1673
                                                i--; j--; k--; p++; r++;
×
1674
                                        }
1675
                                }
1676
                                else {
1677
                                        while ( i > 0 && j > 0 && *p == *r ) { i--; j--; k--; p++; r++; }
×
1678
                                }
1679
                        }
1680
                        else {
1681
                                while ( i > 0 && j > 0 && *p == *r ) { i--; j--; k--; p++; r++; }
125,832✔
1682
                        }
1683
                        goto nocompress;
155,688✔
1684
                }
1685
                else {
1686
                        if ( AR.PolyFunType == 2 ) {
13,146,886✔
1687
                                WORD *t, *tstop;
211,038✔
1688
                                tstop = term + *term;
211,038✔
1689
                                tstop -= ABS(tstop[-1]);
211,038✔
1690
                                t = term+1;
211,038✔
1691
                                while ( t < tstop ) {
422,076✔
1692
                                        if ( *t == AR.PolyFun ) {
211,038✔
1693
                                                t[2] &= ~MUSTCLEANPRF;
×
1694
                                        }
1695
                                        t += t[1];
211,038✔
1696
                                }
1697
                        }
1698
                        if ( dobracketindex ) {
13,146,886✔
1699
                                PutBracketInIndex(BHEAD term,position);
×
1700
                        }
1701
                }
1702
                ret = i;
21,979,564✔
1703
                ADDPOS(*position,i*sizeof(WORD));
21,979,564✔
1704
                p = fi->POfill;
21,979,564✔
1705
                do {
428,779,503✔
1706
                        if ( p >= fi->POstop ) {
428,779,503✔
1707
#ifdef WITHMPI /* [16mar1998 ar] */
1708
                          if ( PF.me != MASTER && AR.sLevel <= 0 && (fi == AR.outfile || fi == AR.hidefile) && PF.parallel && PF.exprtodo < 0 ) {
1709
                                PF_BUFFER *sbuf = PF.sbuf;
1710
                                sbuf->fill[sbuf->active] = fi->POstop;
1711
                                PF_ISendSbuf(MASTER,PF_BUFFER_MSGTAG);
1712
                                p = fi->PObuffer = fi->POfill = fi->POfull =
1713
                                  sbuf->buff[sbuf->active];
1714
                                fi->POstop = sbuf->stop[sbuf->active];
1715
                          }
1716
                          else
1717
#endif /* WITHMPI [16mar1998 ar] */
1718
                          {
1719
                                if ( fi->handle < 0 ) {
204✔
1720
                                        if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
18✔
1721
#ifdef GZIPDEBUG
1722
                                                MLOCK(ErrorMessageLock);
1723
                                                MesPrint("%w PutOut created sortfile %s",fi->name);
1724
                                                MUNLOCK(ErrorMessageLock);
1725
#endif
1726
                                                fi->handle = (WORD)RetCode;
18✔
1727
                                                PUTZERO(fi->filesize);
18✔
1728
                                                PUTZERO(fi->POposition);
18✔
1729
/*
1730
                                                Should not be here?
1731
#ifdef WITHZLIB
1732
                                                fi->ziobuffer = 0;
1733
#endif
1734
*/
1735
                                        }
1736
                                        else {
1737
                                                MLOCK(ErrorMessageLock);
×
1738
                                                MesPrint("Cannot create scratch file %s",fi->name);
×
1739
                                                MUNLOCK(ErrorMessageLock);
×
1740
                                                return(-1);
×
1741
                                        }
1742
                                }
1743
#ifdef WITHZLIB
1744
                                if ( !AR.NoCompress && ncomp > 0 && AR.gzipCompress > 0
204✔
1745
                                        && dobracketindex == 0 && fi->zsp != 0 ) {
46✔
1746
                                        fi->POfill = p;
46✔
1747
                                        if ( PutOutputGZIP(fi) ) return(-1);
46✔
1748
                                        p = fi->PObuffer;
46✔
1749
                                }
1750
                                else
1751
#endif
1752
                                {
1753
#ifdef ALLLOCK
1754
                                  LOCK(fi->pthreadslock);
1755
#endif
1756
                                  if ( fi == AR.hidefile ) {
158✔
1757
                                        LOCK(AS.inputslock);
90✔
1758
                                  }
1759
                                  SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
158✔
1760
                                  if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize) ) != fi->POsize ) {
158✔
1761
                                        if ( fi == AR.hidefile ) {
×
1762
                                                UNLOCK(AS.inputslock);
×
1763
                                        }
1764
#ifdef ALLLOCK
1765
                                        UNLOCK(fi->pthreadslock);
1766
#endif
1767
                                        MLOCK(ErrorMessageLock);
×
1768
                                        MesPrint("Write error during sort. Disk full?");
×
1769
                                        MesPrint("Attempt to write %l bytes on file %d at position %15p",
×
1770
                                                                fi->POsize,fi->handle,&(fi->POposition));
1771
                                        MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
×
1772
                                        MUNLOCK(ErrorMessageLock);
×
1773
                                        return(-1);
×
1774
                                  }
1775
                                  ADDPOS(fi->filesize,fi->POsize);
158✔
1776
                                  p = fi->PObuffer;
158✔
1777
                                  ADDPOS(fi->POposition,fi->POsize);
158✔
1778
                                  if ( fi == AR.hidefile ) {
158✔
1779
                                        UNLOCK(AS.inputslock);
147,387,046✔
1780
                                  }
1781
#ifdef ALLLOCK
1782
                                  UNLOCK(fi->pthreadslock);
1783
#endif
1784
#ifdef WITHPTHREADS
1785
                                  if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
68✔
1786
                                        if ( fi->handle >= 0 ) SynchFile(fi->handle);
1787
                                  }
1788
#endif
1789
                                }
1790
                          }
1791
                        } 
1792
                        if ( first ) {
428,779,503✔
1793
                                if ( first == 2 ) *p++ = k;
16,368,060✔
1794
                                else *p++ = j;
8,184,030✔
1795
                                first--;
16,368,060✔
1796
                        }
1797
                        else *p++ = *term++;
412,411,443✔
1798
/*
1799
                        if ( AP.DebugFlag ) {
1800
                                TalToLine((UWORD)(p[-1])); TokenToLine((UBYTE *)"  ");
1801
                        }
1802
*/
1803
                } while ( --i > 0 );
428,779,503✔
1804
                fi->POfull = fi->POfill = p;
21,979,564✔
1805
        }
1806
/*
1807
        if ( AP.DebugFlag ) {
1808
                AO.OutSkip = 0;
1809
                FiniLine();
1810
        }
1811
*/
1812
        return(ret);
1813
}
1814

1815
/*
1816
                 #] PutOut : 
1817
                 #[ FlushOut :                                WORD FlushOut(position,file,compr)
1818
*/
1819
/**
1820
 *        Completes output to an output file and writes the trailing zero.
1821
 *
1822
 *        @param position The position in the file after writing
1823
 *        @param fi       The file (or its cache)
1824
 *        @param compr        Indicates whether there should be compression with gzip.
1825
 *        @return   Regular conventions (OK -> 0).
1826
 */
1827

1828
WORD FlushOut(POSITION *position, FILEHANDLE *fi, int compr)
711,283✔
1829
{
1830
        GETIDENTITY
474,180✔
1831
        LONG size, RetCode;
711,283✔
1832
        int dobracketindex = 0;
711,283✔
1833
#ifndef WITHZLIB
1834
        DUMMYUSE(compr);
1835
#endif
1836
        if ( AR.sLevel <= 0 && Expressions[AR.CurExpr].newbracketinfo
711,283✔
1837
                && ( fi == AR.outfile || fi == AR.hidefile ) ) dobracketindex = 1;
222✔
1838
#ifdef WITHMPI /* [16mar1998 ar] */
1839
        if ( PF.me != MASTER && AR.sLevel <= 0 && (fi == AR.outfile || fi == AR.hidefile) && PF.parallel && PF.exprtodo < 0 ) {
1840
                PF_BUFFER *sbuf = PF.sbuf;
1841
                if ( fi->POfill >= fi->POstop ){
1842
                  sbuf->fill[sbuf->active] = fi->POstop;
1843
                  PF_ISendSbuf(MASTER,PF_BUFFER_MSGTAG);
1844
                  fi->POfull = fi->POfill = fi->PObuffer = sbuf->buff[sbuf->active];
1845
                  fi->POstop = sbuf->stop[sbuf->active];
1846
                }
1847
                *(fi->POfill)++ = 0;
1848
                sbuf->fill[sbuf->active] = fi->POfill;
1849
                PF_ISendSbuf(MASTER,PF_ENDBUFFER_MSGTAG);
1850
                fi->PObuffer = fi->POfill = fi->POfull = sbuf->buff[sbuf->active];
1851
                fi->POstop = sbuf->stop[sbuf->active];
1852
                return(0);
1853
        }
1854
#endif /* WITHMPI [16mar1998 ar] */
1855
        if ( fi->POfill >= fi->POstop ) {
711,283✔
1856
                if ( fi->handle < 0 ) {
×
1857
                        if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
×
1858
#ifdef GZIPDEBUG
1859
                                MLOCK(ErrorMessageLock);
1860
                                MesPrint("%w FlushOut created scratch file %s",fi->name);
1861
                                MUNLOCK(ErrorMessageLock);
1862
#endif
1863
                                PUTZERO(fi->filesize);
×
1864
                                PUTZERO(fi->POposition);
×
1865
                                fi->handle = (WORD)RetCode;
×
1866
/*
1867
                                Should not be here?
1868
#ifdef WITHZLIB
1869
                                fi->ziobuffer = 0;
1870
#endif
1871
*/
1872
                        }
1873
                        else {
1874
                                MLOCK(ErrorMessageLock);
×
1875
                                MesPrint("Cannot create scratch file %s",fi->name);
×
1876
                                MUNLOCK(ErrorMessageLock);
×
1877
                                return(-1);
×
1878
                        }
1879
                }
1880
#ifdef WITHZLIB
1881
                if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
×
1882
                && dobracketindex == 0 && ( compr > 0 ) && fi->zsp != 0 ) {
×
1883
                        if ( PutOutputGZIP(fi) ) return(-1);
×
1884
                        fi->POfill = fi->PObuffer;
×
1885
                }
1886
                else
1887
#endif
1888
                {
1889
#ifdef ALLLOCK
1890
                  LOCK(fi->pthreadslock);
1891
#endif
1892
                  if ( fi == AR.hidefile ) {
×
1893
                        LOCK(AS.inputslock);
×
1894
                  }
1895
                  SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
×
1896
                  if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize) ) != fi->POsize ) {
×
1897
#ifdef ALLLOCK
1898
                        UNLOCK(fi->pthreadslock);
1899
#endif
1900
                        if ( fi == AR.hidefile ) {
×
1901
                                UNLOCK(AS.inputslock);
×
1902
                        }
1903
                        MLOCK(ErrorMessageLock);
×
1904
                        MesPrint("Write error while sorting. Disk full?");
×
1905
                        MesPrint("Attempt to write %l bytes on file %d at position %15p",
×
1906
                                                fi->POsize,fi->handle,&(fi->POposition));
1907
                        MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
×
1908
                        MUNLOCK(ErrorMessageLock);
×
1909
                        return(-1);
×
1910
                  }
1911
                  ADDPOS(fi->filesize,fi->POsize);
×
1912
                  fi->POfill = fi->PObuffer;
×
1913
                  ADDPOS(fi->POposition,fi->POsize);
×
1914
                  if ( fi == AR.hidefile ) {
×
1915
                        UNLOCK(AS.inputslock);
237,103✔
1916
                  }
1917
#ifdef ALLLOCK
1918
                  UNLOCK(fi->pthreadslock);
1919
#endif
1920
#ifdef WITHPTHREADS
1921
                  if ( AS.MasterSort && AC.ThreadSortFileSynch && fi != AR.hidefile ) {
1922
                        if ( fi->handle >= 0 ) SynchFile(fi->handle);
1923
                  }
1924
#endif
1925
                }
1926
        } 
1927
        *(fi->POfill)++ = 0;
711,283✔
1928
        fi->POfull = fi->POfill;
711,283✔
1929
/*
1930
        {
1931
                UBYTE OutBuf[140];
1932
                if ( AP.DebugFlag ) {
1933
                        AO.OutFill = AO.OutputLine = OutBuf;
1934
                        AO.OutSkip = 3;
1935
                        FiniLine();
1936
                        TokenToLine((UBYTE *)"End of expression written");
1937
                        FiniLine();
1938
                }
1939
        }
1940
*/
1941
        size = (fi->POfill-fi->PObuffer)*sizeof(WORD);
711,283✔
1942
        if ( fi->handle >= 0 ) {
711,283✔
1943
#ifdef WITHZLIB
1944
                if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
604✔
1945
                && dobracketindex == 0 && ( compr > 0 ) && fi->zsp != 0 ) {
514✔
1946
                        if ( FlushOutputGZIP(fi) ) return(-1);
514✔
1947
                        fi->POfill = fi->PObuffer;
514✔
1948
                }
1949
                else
1950
#endif
1951
                {
1952
#ifdef ALLLOCK
1953
                  LOCK(fi->pthreadslock);
1954
#endif
1955
                  if ( fi == AR.hidefile ) {
90✔
1956
                        LOCK(AS.inputslock);
30✔
1957
                  }
1958
                  SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
90✔
1959
/*
1960
                  MesPrint("FlushOut: writing %l bytes to position %12p",size,&(fi->POposition));
1961
*/
1962
                  if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),size) ) != size ) {
90✔
1963
#ifdef ALLLOCK
1964
                        UNLOCK(fi->pthreadslock);
1965
#endif
1966
                        if ( fi == AR.hidefile ) {
×
1967
                                UNLOCK(AS.inputslock);
×
1968
                        }
1969
                        MLOCK(ErrorMessageLock);
×
1970
                        MesPrint("Write error while finishing sorting. Disk full?");
×
1971
                        MesPrint("Attempt to write %l bytes on file %d at position %15p",
×
1972
                                                size,fi->handle,&(fi->POposition));
1973
                        MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
×
1974
                        MUNLOCK(ErrorMessageLock);
×
1975
                        return(-1);
×
1976
                  }
1977
                  ADDPOS(fi->filesize,size);
90✔
1978
                  ADDPOS(fi->POposition,size);
90✔
1979
                  fi->POfill = fi->PObuffer;
90✔
1980
                  if ( fi == AR.hidefile ) {
90✔
1981
                        UNLOCK(AS.inputslock);
237,103✔
1982
                  }
1983
#ifdef ALLLOCK
1984
                  UNLOCK(fi->pthreadslock);
1985
#endif
1986
#ifdef WITHPTHREADS
1987
                  if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
60✔
1988
                        if ( fi->handle >= 0 ) SynchFile(fi->handle);
1989
                  }
1990
#endif
1991
                }
1992
        }
1993
        if ( dobracketindex ) {
711,283✔
1994
                BRACKETINFO *b = Expressions[AR.CurExpr].newbracketinfo;
222✔
1995
                if ( b->indexfill > 0 ) {
222✔
1996
                        DIFPOS(b->indexbuffer[b->indexfill-1].next,*position,Expressions[AR.CurExpr].onfile);
210✔
1997
                }
1998
        }
1999
#ifdef WITHZLIB
2000
        if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
711,283✔
2001
                && dobracketindex == 0 && ( compr > 0 ) && fi->zsp != 0 ) {
437,326✔
2002
                PUTZERO(*position);
514✔
2003
                if ( fi->handle >= 0 ) {
514✔
2004
#ifdef ALLLOCK
2005
                        LOCK(fi->pthreadslock);
2006
#endif
2007
                        SeekFile(fi->handle,position,SEEK_END);
514✔
2008
#ifdef ALLLOCK
2009
                        UNLOCK(fi->pthreadslock);
2010
#endif
2011
                }
2012
                else {
2013
                        ADDPOS(*position,((UBYTE *)fi->POfill-(UBYTE *)fi->PObuffer));
×
2014
                }
2015
        }
2016
        else
2017
#endif
2018
        {
2019
                ADDPOS(*position,sizeof(WORD));
710,769✔
2020
        }
2021
        return(0);
2022
}
2023

2024
/*
2025
                 #] FlushOut : 
2026
                 #[ AddCoef :                                WORD AddCoef(pterm1,pterm2)
2027
*/
2028
/**
2029
 *                Adds the coefficients of the terms *ps1 and *ps2.
2030
 *                The problem comes when there is not enough space for a new
2031
 *                longer coefficient. First a local solution is tried.
2032
 *                If this is not successful we need to move terms around.
2033
 *                The possibility of a garbage collection should not be
2034
 *                ignored, as avoiding this costs very much extra space which
2035
 *                is nearly wasted otherwise.
2036
 *
2037
 *                If the return value is zero the terms cancelled.
2038
 *
2039
 *                The resulting term is left in *ps1.
2040
 */
2041

2042
WORD AddCoef(PHEAD WORD **ps1, WORD **ps2)
10,281,483✔
2043
{
2044
        GETBIDENTITY
2045
        SORTING *S = AT.SS;
10,281,483✔
2046
        WORD *s1, *s2;
10,281,483✔
2047
        WORD l1, l2, i;
10,281,483✔
2048
        WORD OutLen, *t, j;
10,281,483✔
2049
        UWORD *OutCoef;
10,281,483✔
2050
#ifdef WITHFLOAT
2051
        if ( AT.SortFloatMode ) return(AddWithFloat(BHEAD ps1,ps2));
10,281,483✔
2052
#endif
2053
        OutCoef = AN.SoScratC;
10,281,483✔
2054
        s1 = *ps1; s2 = *ps2;
10,281,483✔
2055
        GETCOEF(s1,l1);
10,281,483✔
2056
        GETCOEF(s2,l2);
10,281,483✔
2057
        if ( AddRat(BHEAD (UWORD *)s1,l1,(UWORD *)s2,l2,OutCoef,&OutLen) ) {
10,281,483✔
2058
                MLOCK(ErrorMessageLock);
×
2059
                MesCall("AddCoef");
×
2060
                MUNLOCK(ErrorMessageLock);
×
2061
                Terminate(-1);
×
2062
        }
2063
        if ( AN.ncmod != 0 ) {
10,281,483✔
2064
                if ( ( AC.modmode & POSNEG ) != 0 ) {
×
2065
                        NormalModulus(OutCoef,&OutLen);
×
2066
/*
2067
                        We had forgotten that this can also become smaller but the
2068
                        denominator isn't there. Correct in the other case
2069
                        17-may-2009 [JV]
2070
*/
2071
                        j = ABS(OutLen); OutCoef[j] = 1;
×
2072
                        for ( i = 1; i < j; i++ ) OutCoef[j+i] = 0;
×
2073
                }
2074
                else if ( BigLong(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod)) >= 0 ) {
×
2075
                        SubPLon(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod),OutCoef,&OutLen);
×
2076
                        OutCoef[OutLen] = 1;
×
2077
                        for ( i = 1; i < OutLen; i++ ) OutCoef[OutLen+i] = 0;
×
2078
                }
2079
        }
2080
        if ( !OutLen ) { *ps1 = *ps2 = 0; return(0); }
10,281,483✔
2081
        OutLen *= 2;
9,179,606✔
2082
        if ( OutLen < 0 ) i = - ( --OutLen );
9,179,606✔
2083
        else                          i = ++OutLen;
8,069,135✔
2084
        if ( l1 < 0 ) l1 = -l1;
9,179,606✔
2085
        l1 *= 2; l1++;
9,179,606✔
2086
        if ( i <= l1 ) {        /* Fits in 1 */
9,179,606✔
2087
                l1 -= i;
9,122,046✔
2088
                **ps1 -= l1;
9,122,046✔
2089
                s2 = (WORD *)OutCoef;
9,122,046✔
2090
                while ( --i > 0 ) *s1++ = *s2++;
27,852,034✔
2091
                *s1++ = OutLen;
9,122,046✔
2092
                while ( --l1 >= 0 ) *s1++ = 0;
9,122,498✔
2093
                goto RegEnd;
9,122,046✔
2094
        }
2095
        if ( l2 < 0 ) l2 = -l2;
57,560✔
2096
        l2 *= 2; l2++;
57,560✔
2097
        if ( i <= l2 ) {        /* Fits in 2 */
57,560✔
2098
                l2 -= i;
32,277✔
2099
                **ps2 -= l2;
32,277✔
2100
                s1 = (WORD *)OutCoef;
32,277✔
2101
                while ( --i > 0 ) *s2++ = *s1++;
270,643✔
2102
                *s2++ = OutLen;
32,277✔
2103
                while ( --l2 >= 0 ) *s2++ = 0;
32,469✔
2104
                *ps1 = *ps2;
32,277✔
2105
                goto RegEnd;
32,277✔
2106
        }
2107

2108
        /* Doesn't fit. Make a new term. */
2109

2110
        t = s1;
25,283✔
2111
        s1 = *ps1;
25,283✔
2112
        j = *s1++ + i - l1;                /* Space needed */
25,283✔
2113
        if ( (S->sFill + j) >= S->sTop2 ) {
25,283✔
2114
                GarbHand();
×
2115
                s1 = *ps1;
×
2116
                t = s1 + *s1 - 1;
×
2117
                j = *s1++ + i - l1;                /* Space needed */
×
2118
                l1 = *t;
×
2119
                if ( l1 < 0 ) l1  = - l1;
×
2120
                t -= l1-1;
×
2121
        }
2122
        s2 = S->sFill;
25,283✔
2123
        *s2++ = j;
25,283✔
2124
        while ( s1 < t ) *s2++ = *s1++;
189,245✔
2125
        s1 = (WORD *)OutCoef;
2126
        while ( --i > 0 ) *s2++ = *s1++;
253,945✔
2127
        *s2++ = OutLen;
25,283✔
2128
        *ps1 = S->sFill;
25,283✔
2129
        S->sFill = s2;
25,283✔
2130
RegEnd:
9,179,606✔
2131
        *ps2 = 0;
9,179,606✔
2132
        if ( **ps1 > AM.MaxTer/((LONG)(sizeof(WORD))) ) {
9,179,606✔
2133
                MLOCK(ErrorMessageLock);
×
2134
                MesPrint("Term too complex after addition in sort. MaxTermSize = %10l",
×
2135
                AM.MaxTer/sizeof(WORD));
×
2136
                MUNLOCK(ErrorMessageLock);
×
2137
                Terminate(-1);
×
2138
        }
2139
        return(1);
2140
}
2141

2142
/*
2143
                 #] AddCoef : 
2144
                 #[ AddPoly :                                WORD AddPoly(pterm1,pterm2)
2145
*/
2146
/**
2147
 *                Routine should be called when S->PolyWise != 0. It points then
2148
 *                to the position of AR.PolyFun in both terms.
2149
 *
2150
 *                We add the contents of the arguments of the two polynomials.
2151
 *                Special attention has to be given to special arguments.
2152
 *                We have to reserve a space equal to the size of one term + the
2153
 *                size of the argument of the other. The addition has to be done
2154
 *                in this routine because not all objects are reentrant.
2155
 *
2156
 *                Newer addition (12-nov-2007).
2157
 *                The PolyFun can have two arguments.
2158
 *                In that case S->PolyFlag is 2 and we have to call the routine for
2159
 *                adding rational polynomials.
2160
 *                We have to be rather careful what happens with:
2161
 *                        The location of the output
2162
 *                        The order of the terms in the arguments
2163
 *                At first we allow only univariate polynomials in the PolyFun.
2164
 *                This restriction will be lifted a.s.a.p.
2165
 *
2166
 *                @param ps1 A pointer to the position of the first term
2167
 *                @param ps2 A pointer to the position of the second term
2168
 *                @return If zero the terms cancel. Otherwise the new term is in *ps1.
2169
 */
2170

2171
WORD AddPoly(PHEAD WORD **ps1, WORD **ps2)
761,841✔
2172
{
2173
        GETBIDENTITY
2174
        SORTING *S = AT.SS;
761,841✔
2175
        WORD i;
761,841✔
2176
        WORD *s1, *s2, *m, *w, *t, oldpw = S->PolyWise;
761,841✔
2177
        s1 = *ps1 + S->PolyWise;
761,841✔
2178
        s2 = *ps2 + S->PolyWise;
761,841✔
2179
        w = AT.WorkPointer;
761,841✔
2180
/*
2181
        Add here the two arguments. Is a straight merge.
2182
*/
2183
        if ( S->PolyFlag == 2 && AR.PolyFunExp != 2 && AR.PolyFunExp != 3 ) {
761,841✔
2184
                WORD **oldSplitScratch = AN.SplitScratch;
761,823✔
2185
                LONG oldSplitScratchSize = AN.SplitScratchSize;
761,823✔
2186
                LONG oldInScratch = AN.InScratch;
761,823✔
2187
                WORD oldtype = AR.SortType;
761,823✔
2188
                if ( (WORD *)((UBYTE *)w + AM.MaxTer) >= AT.WorkTop ) {
761,823✔
2189
                        MLOCK(ErrorMessageLock);
×
2190
                        MesPrint("Program was adding polyratfun arguments");
×
2191
                        MesWork();
×
2192
                        MUNLOCK(ErrorMessageLock);
244,324✔
2193
                }
2194
                AR.SortType = SORTHIGHFIRST;
761,823✔
2195
                S->PolyWise = 0;
761,823✔
2196
                AN.SplitScratch = AN.SplitScratch1;
761,823✔
2197
                AN.SplitScratchSize = AN.SplitScratchSize1;
761,823✔
2198
                AN.InScratch = AN.InScratch1;
761,823✔
2199
                poly_ratfun_add(BHEAD s1,s2);
761,823✔
2200
                S->PolyWise = oldpw;
761,823✔
2201
                AN.SplitScratch1 = AN.SplitScratch;
761,823✔
2202
                AN.SplitScratchSize1 = AN.SplitScratchSize;
761,823✔
2203
                AN.InScratch1 = AN.InScratch;
761,823✔
2204
                AN.SplitScratch = oldSplitScratch;
761,823✔
2205
                AN.SplitScratchSize = oldSplitScratchSize;
761,823✔
2206
                AN.InScratch = oldInScratch;
761,823✔
2207
                AT.WorkPointer = w;
761,823✔
2208
                AR.SortType = oldtype;
761,823✔
2209
                if ( w[1] <= FUNHEAD ||
761,823✔
2210
                        ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) ) {
761,823✔
2211
                        *ps1 = *ps2 = 0; return(0);
3,344✔
2212
                }
2213
        }
2214
        else {
2215
                if ( w + s1[1] + s2[1] + 12 + ARGHEAD >= AT.WorkTop ) {
18✔
2216
                        MLOCK(ErrorMessageLock);
×
2217
                        MesPrint("Program was adding polyfun arguments");
×
2218
                        MesWork();
×
2219
                        MUNLOCK(ErrorMessageLock);
8✔
2220
                }
2221
                AddArgs(BHEAD s1,s2,w);
18✔
2222
        }
2223
/*
2224
        Now we need to store the result in a convenient place.
2225
*/
2226
        if ( w[1] <= FUNHEAD ) { *ps1 = *ps2 = 0; return(0); }
758,497✔
2227
        if ( w[1] <= s1[1] || w[1] <= s2[1] ) {   /* Fits in place. */
758,497✔
2228
                if ( w[1] > s1[1] ) {
13,631✔
2229
                        *ps1 = *ps2;
1,700✔
2230
                        s1 = s2;
1,700✔
2231
                }
2232
                t = s1 + s1[1];
13,631✔
2233
                m = *ps1 + **ps1;
13,631✔
2234
                i = w[1];
13,631✔
2235
                NCOPY(s1,w,i);
2,576,866✔
2236
                if ( s1 != t ) {
13,631✔
2237
                        while ( t < m ) *s1++ = *t++;
628✔
2238
                        **ps1 = WORDDIF(s1,(*ps1));
157✔
2239
                }
2240
                *ps2 = 0;
13,631✔
2241
        }
2242
        else {                /* Make new term */
2243
#ifdef TESTGARB
2244
                s2 = *ps2;
2245
#endif
2246
                *ps2 = 0;
744,866✔
2247
                if ( (S->sFill + (**ps1 + w[1] - s1[1])) >= S->sTop2 ) {
744,866✔
2248
#ifdef TESTGARB
2249
                        MesPrint("------Garbage collection-------");
2250
#endif
2251
                        AT.WorkPointer += w[1];
773✔
2252
                        GarbHand();
773✔
2253
                        AT.WorkPointer = w;
765✔
2254
                        s1 = *ps1;
765✔
2255
                        if ( (S->sFill + (**ps1 + w[1] - s1[1])) >= S->sTop2 ) {
765✔
2256
#ifdef TESTGARB
2257
                                UBYTE OutBuf[140];
2258
                                MLOCK(ErrorMessageLock);
2259
                                AO.OutFill = AO.OutputLine = OutBuf;
2260
                                AO.OutSkip = 3;
2261
                                FiniLine();
2262
                                i = *s2;
2263
                                while ( --i >= 0 ) {
2264
                                        TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)"  ");
2265
                                }
2266
                                FiniLine();
2267
                                AO.OutFill = AO.OutputLine = OutBuf;
2268
                                AO.OutSkip = 3;
2269
                                FiniLine();
2270
                                s2 = *ps1;
2271
                                i = *s2;
2272
                                while ( --i >= 0 ) {
2273
                                        TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)"  ");
2274
                                }
2275
                                FiniLine();
2276
                                AO.OutFill = AO.OutputLine = OutBuf;
2277
                                AO.OutSkip = 3;
2278
                                FiniLine();
2279
                                s2 = w;
2280
                                i = w[1];
2281
                                while ( --i >= 0 ) {
2282
                                        TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)"  ");
2283
                                }
2284
                                FiniLine();
2285
                                if ( AR.sLevel > 0 ) {
2286
                                        MesPrint("Please increase SubSmallExtension setup parameter.");
2287
                                }
2288
                                else {
2289
                                        MesPrint("Please increase SmallExtension setup parameter.");
2290
                                }
2291
                                MUNLOCK(ErrorMessageLock);
2292
#else
2293
                                MLOCK(ErrorMessageLock);
12✔
2294
                                if ( AR.sLevel > 0 ) {
12✔
2295
                                        MesPrint("Please increase SubSmallExtension setup parameter.");
6✔
2296
                                }
2297
                                else {
2298
                                        MesPrint("Please increase SmallExtension setup parameter.");
6✔
2299
                                }
2300
                                MUNLOCK(ErrorMessageLock);
12✔
2301
#endif
2302
                                Terminate(-1);
12✔
2303
                        }
2304
                }
2305
                t = *ps1;
744,846✔
2306
                s2 = S->sFill;
744,846✔
2307
                m = s2;
744,846✔
2308
                i = S->PolyWise;
744,846✔
2309
                NCOPY(s2,t,i);
5,115,598✔
2310
                i = w[1];
744,846✔
2311
                NCOPY(s2,w,i);
210,601,106✔
2312
                t = t + t[1];
744,846✔
2313
                w = *ps1 + **ps1;
744,846✔
2314
                while ( t < w ) *s2++ = *t++;
2,979,384✔
2315
                *m = WORDDIF(s2,m);
744,846✔
2316
                *ps1 = m;
744,846✔
2317
                S->sFill = s2;
744,846✔
2318
                if ( *m > AM.MaxTer/((LONG)sizeof(WORD)) ) {
744,846✔
2319
                        MLOCK(ErrorMessageLock);
×
2320
                        MesPrint("Term too complex after polynomial addition. MaxTermSize = %10l",
×
2321
                        AM.MaxTer/sizeof(WORD));
×
2322
                        MUNLOCK(ErrorMessageLock);
×
2323
                        Terminate(-1);
×
2324
                }
2325
        }
2326
        return(1);
2327
}
2328

2329
/*
2330
                 #] AddPoly : 
2331
                 #[ AddArgs :                                void AddArgs(arg1,arg2,to)
2332
*/
2333
 
2334
#define INSLENGTH(x)  w[1] = FUNHEAD+ARGHEAD+x; w[FUNHEAD] = ARGHEAD+x;
2335

2336
/**
2337
 *        Adds the arguments of two occurrences of the PolyFun.
2338
 *        @param s1 Pointer to the first occurrence.
2339
 *        @param s2 Pointer to the second occurrence.
2340
 *        @param m  Pointer to where the answer should be.
2341
 */
2342

2343
void AddArgs(PHEAD WORD *s1, WORD *s2, WORD *m)
24✔
2344
{
2345
        GETBIDENTITY
2346
        WORD i1, i2;
24✔
2347
        WORD *w = m, *mm, *t, *t1, *t2, *tstop1, *tstop2;
24✔
2348
        WORD tempterm[8+FUNHEAD];
24✔
2349

2350
        *m++ = AR.PolyFun; *m++ = 0; FILLFUN(m)
24✔
2351
        *m++ = 0; *m++ = 0; FILLARG(m)
24✔
2352
        if ( s1[FUNHEAD] < 0 || s2[FUNHEAD] < 0 ) {
24✔
2353
                if ( s1[FUNHEAD] < 0 ) {
×
2354
                        if ( s2[FUNHEAD] < 0 ) {        /* Both are special */
×
2355
                                if ( s1[FUNHEAD] <= -FUNCTION ) {
×
2356
                                        if ( s2[FUNHEAD] == s1[FUNHEAD] ) {
×
2357
                                                *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
×
2358
                                                FILLFUN(m)
×
2359
                                                *m++ = 2; *m++ = 1; *m++ = 3;
×
2360
                                                INSLENGTH(4+FUNHEAD)
×
2361
                                        }
2362
                                        else if ( s2[FUNHEAD] <= -FUNCTION ) {
×
2363
                                                i1 = functions[-FUNCTION-s1[FUNHEAD]].commute != 0;
×
2364
                                                i2 = functions[-FUNCTION-s2[FUNHEAD]].commute != 0;
×
2365
                                                if ( ( !i1 && i2 ) || ( i1 == i2 && i1 > i2 ) ) {
×
2366
                                                        i1 = s2[FUNHEAD];
×
2367
                                                        s2[FUNHEAD] = s1[FUNHEAD];
×
2368
                                                        s1[FUNHEAD] = i1;
×
2369
                                                }
2370
                                                *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
×
2371
                                                FILLFUN(m)
×
2372
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2373
                                                *m++ = 4+FUNHEAD; *m++ = -s2[FUNHEAD]; *m++ = FUNHEAD;
×
2374
                                                FILLFUN(m)
×
2375
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2376
                                                INSLENGTH(8+2*FUNHEAD)
×
2377
                                        }
2378
                                        else if ( s2[FUNHEAD] == -SYMBOL ) {
×
2379
                                                *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s2[FUNHEAD+1]; *m++ = 1;
×
2380
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2381
                                                *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
×
2382
                                                FILLFUN(m)
×
2383
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2384
                                                INSLENGTH(12+FUNHEAD)
×
2385
                                        }
2386
                                        else {                /* number */
2387
                                                *m++ = 4;
×
2388
                                                *m++ = ABS(s2[FUNHEAD+1]); *m++ = 1; *m++ = s2[FUNHEAD+1] < 0 ? -3: 3;
×
2389
                                                *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
×
2390
                                                FILLFUN(m)
×
2391
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2392
                                                INSLENGTH(8+FUNHEAD)
×
2393
                                        }
2394
                                }
2395
                                else if ( s1[FUNHEAD] == -SYMBOL ) {
×
2396
                                        if ( s2[FUNHEAD] == s1[FUNHEAD] ) {
×
2397
                                                if ( s1[FUNHEAD+1] == s2[FUNHEAD+1] ) {
×
2398
                                                        *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s1[FUNHEAD+1];
×
2399
                                                        *m++ = 1; *m++ = 2; *m++ = 1; *m++ = 3;
×
2400
                                                        INSLENGTH(8)
×
2401
                                                }
2402
                                                else {
2403
                                                        if ( s1[FUNHEAD+1] > s2[FUNHEAD+1] )
×
2404
                                                                { i1 = s2[FUNHEAD+1]; i2 = s1[FUNHEAD+1]; }
2405
                                                        else { i1 = s1[FUNHEAD+1]; i2 = s2[FUNHEAD+1]; }
×
2406
                                                        *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = i1;
×
2407
                                                        *m++ = 1; *m++ = 1; *m++ = 1; *m++ = 3;
×
2408
                                                        *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = i2;
×
2409
                                                        *m++ = 1; *m++ = 1; *m++ = 1; *m++ = 3;
×
2410
                                                        INSLENGTH(16)
×
2411
                                                }
2412
                                        }
2413
                                        else if ( s2[FUNHEAD] <= -FUNCTION ) {
×
2414
                                                *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s1[FUNHEAD+1]; *m++ = 1;
×
2415
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2416
                                                *m++ = 4+FUNHEAD; *m++ = -s2[FUNHEAD]; *m++ = FUNHEAD;
×
2417
                                                FILLFUN(m)
×
2418
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2419
                                                INSLENGTH(12+FUNHEAD)
×
2420
                                        }
2421
                                        else {
2422
                                                *m++ = 4;
×
2423
                                                *m++ = ABS(s2[FUNHEAD+1]); *m++ = 1; *m++ = s2[FUNHEAD+1] < 0 ? -3: 3;
×
2424
                                                *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s1[FUNHEAD+1]; *m++ = 1;
×
2425
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2426
                                                INSLENGTH(12)
×
2427
                                        }
2428
                                }
2429
                                else {        /* Must be -SNUMBER! */
2430
                                        if ( s2[FUNHEAD] <= -FUNCTION ) {
×
2431
                                                *m++ = 4;
×
2432
                                                *m++ = ABS(s1[FUNHEAD+1]); *m++ = 1; *m++ = s1[FUNHEAD+1] < 0 ? -3: 3;
×
2433
                                                *m++ = 4+FUNHEAD; *m++ = -s2[FUNHEAD]; *m++ = FUNHEAD;
×
2434
                                                FILLFUN(m)
×
2435
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2436
                                                INSLENGTH(8+FUNHEAD)
×
2437
                                        }
2438
                                        else if ( s2[FUNHEAD] == -SYMBOL ) {
×
2439
                                                *m++ = 4;
×
2440
                                                *m++ = ABS(s1[FUNHEAD+1]); *m++ = 1; *m++ = s1[FUNHEAD+1] < 0 ? -3: 3;
×
2441
                                                *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s2[FUNHEAD+1]; *m++ = 1;
×
2442
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2443
                                                INSLENGTH(12)
×
2444
                                        }
2445
                                        else {                /* Both are numbers. add. */
2446
                                                LONG x1;
×
2447
                                                x1 = (LONG)s1[FUNHEAD+1] + (LONG)s2[FUNHEAD+1];
×
2448
                                                if ( x1 < 0 ) { i1 = (WORD)(-x1); i2 = -3; }
×
2449
                                                else { i1 = (WORD)x1; i2 = 3; }
×
2450
                                                if ( x1 && AN.ncmod != 0 ) {
×
2451
                                                        m[0] = 4;
×
2452
                                                        m[1] = i1;
×
2453
                                                        m[2] = 1;
×
2454
                                                        m[3] = i2;
×
2455
                                                        if ( Modulus(m) ) Terminate(-1);
×
2456
                                                        if ( *m == 0 ) w[1] = 0;
×
2457
                                                        else {
2458
                                                                if ( *m == 4 && ( m[1] & MAXPOSITIVE ) == m[1]
×
2459
                                                                && m[3] == 3 ) {
×
2460
                                                                        i1 = m[1];
×
2461
                                                                        m -= ARGHEAD;
×
2462
                                                                        *m++ = -SNUMBER;
×
2463
                                                                        *m++ = i1;
×
2464
                                                                        INSLENGTH(4)
×
2465
                                                                }
2466
                                                                else {
2467
                                                                        INSLENGTH(*m)
×
2468
                                                                        m += *m;
×
2469
                                                                }
2470
                                                        }                                                        
2471
                                                }
2472
                                                else {
2473
                                                        if ( x1 == 0 ) {
×
2474
                                                                w[1] = FUNHEAD;
×
2475
                                                        }
2476
                                                        else if ( ( i1 & MAXPOSITIVE ) == i1 ) {
×
2477
                                                                m -= ARGHEAD;
×
2478
                                                                *m++ = -SNUMBER;
×
2479
                                                                *m++ = (WORD)x1;
×
2480
                                                                w[1] = FUNHEAD+2;
×
2481
                                                        }
2482
                                                        else {
2483
                                                                *m++ = 4; *m++ = i1; *m++ = 1; *m++ = i2;
×
2484
                                                                INSLENGTH(4)
×
2485
                                                        }
2486
                                                }
2487
                                        }
2488
                                }
2489
                        }
2490
                        else {        /* Only s1 is special */
2491
s1only:
×
2492
/*
2493
                        Compose a term in `tempterm'
2494
*/
2495
                                t = tempterm;
×
2496
                                if ( s1[FUNHEAD] <= -FUNCTION ) {
×
2497
                                        *t++ = 4+FUNHEAD; *t++ = -s1[FUNHEAD]; *t++ = FUNHEAD;
×
2498
                                        FILLFUN(t)
×
2499
                                        *t++ = 1; *t++ = 1; *t++ = 3;
×
2500
                                }
2501
                                else if ( s1[FUNHEAD] == -SYMBOL ) {
×
2502
                                        *t++ = 8; *t++ = SYMBOL; *t++ = 4;
×
2503
                                        *t++ = s1[FUNHEAD+1]; *t++ = 1;
×
2504
                                        *t++ = 1; *t++ = 1; *t++ = 3;
×
2505
                                }
2506
                                else {
2507
                                        *t++ = 4;   *t++ = ABS(s1[FUNHEAD+1]);
×
2508
                                        *t++ = 1;   *t++ = s1[FUNHEAD+1] < 0 ? -3: 3;
×
2509
                                }
2510
                                tstop1 = t;
×
2511
                                s1 = tempterm;
×
2512
                                goto twogen;
×
2513
                        }
2514
                }
2515
                else {                /* Only s2 is special */
2516
                        t = s1;
×
2517
                        s1 = s2;
×
2518
                        s2 = t;
×
2519
                        goto s1only;
×
2520
                }
2521
        }
2522
        else {
2523
                int oldPolyFlag;
24✔
2524
                tstop1 = s1 + s1[1];
24✔
2525
                s1 += FUNHEAD+ARGHEAD;
24✔
2526
twogen:
24✔
2527
                tstop2 = s2 + s2[1];
24✔
2528
                s2 += FUNHEAD+ARGHEAD;
24✔
2529
/*
2530
                Now we should merge the expressions in s1 and s2 into m.
2531
*/
2532
                oldPolyFlag = AT.SS->PolyFlag;
24✔
2533
                AT.SS->PolyFlag = 0;
24✔
2534
                while ( s1 < tstop1 && s2 < tstop2 ) {
81✔
2535
                        i1 = CompareTerms(BHEAD s1,s2,(WORD)(-1));
57✔
2536
                        if ( i1 > 0 ) {
57✔
2537
                                i2 = *s1;
13✔
2538
                                NCOPY(m,s1,i2);
117✔
2539
                        }
2540
                        else if ( i1 < 0 ) {
44✔
2541
                                i2 = *s2;
2✔
2542
                                NCOPY(m,s2,i2);
18✔
2543
                        }
2544
                        else {        /* Coefficients should be added. */
2545
                                WORD i;
42✔
2546
                                t = s1+*s1;
42✔
2547
                                i1 = t[-1];
42✔
2548
                                i2 = *s1 - ABS(i1);
42✔
2549
                                t2 = s2 + i2;
42✔
2550
                                s2 += *s2;
42✔
2551
                                mm = m;
42✔
2552
                                NCOPY(m,s1,i2);
204✔
2553
                                t1 = s1;
42✔
2554
                                s1 = t;
42✔
2555
                                i2 = s2[-1];
42✔
2556
/*
2557
                                t1,i1 is the first coefficient
2558
                                t2,i2 is the second coefficient
2559
                                It should be placed at m,i1
2560
*/
2561
                                i1 = REDLENG(i1);
42✔
2562
                                i2 = REDLENG(i2);
42✔
2563
                                if ( AddRat(BHEAD (UWORD *)t1,i1,(UWORD *)t2,i2,(UWORD *)m,&i) ) {
42✔
2564
                                        MLOCK(ErrorMessageLock);
×
2565
                                        MesPrint("Addition of coefficients of PolyFun");
×
2566
                                        MUNLOCK(ErrorMessageLock);
×
2567
                                        Terminate(-1);
×
2568
                                }
2569
                                if ( i == 0 ) {
42✔
2570
                                        m = mm;
2571
                                }
2572
                                else {
2573
                                        i1 = INCLENG(i);
30✔
2574
                                        m += ABS(i1);
30✔
2575
                                        m[-1] = i1;
30✔
2576
                                        *mm = WORDDIF(m,mm);
30✔
2577
                                        if ( AN.ncmod != 0 ) {
30✔
2578
                                                if ( Modulus(mm) ) Terminate(-1);
×
2579
                                                if ( !*mm ) m = mm;
×
2580
                                                else m = mm + *mm;
×
2581
                                        }
2582
                                }
2583
                        }
2584
                }
2585
                while ( s1 < tstop1 ) *m++ = *s1++;
72✔
2586
                while ( s2 < tstop2 ) *m++ = *s2++;
72✔
2587
                w[1] = WORDDIF(m,w);
24✔
2588
                w[FUNHEAD] = w[1] - FUNHEAD;
24✔
2589
                if ( ToFast(w+FUNHEAD,w+FUNHEAD) ) {
24✔
2590
                        if ( w[FUNHEAD] <= -FUNCTION ) w[1] = FUNHEAD+1;
×
2591
                        else w[1] = FUNHEAD+2;
×
2592
                        if ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) w[1] = FUNHEAD;
×
2593
                }
2594
/*                AT.SS->PolyFlag = AR.PolyFunType;*/
2595
                AT.SS->PolyFlag = oldPolyFlag;
24✔
2596
        }
2597
}
24✔
2598

2599
/*
2600
                 #] AddArgs : 
2601
                 #[ Compare1 :                                WORD Compare1(term1,term2,level)
2602
*/
2603
/**
2604
 *        Compares two terms. The answer is:
2605
 *        0        equal ( with exception of the coefficient if level == 0. )
2606
 *        >0        term1 comes first.
2607
 *        <0        term2 comes first.
2608
 *        Some special precautions may be needed to keep the CompCoef routine
2609
 *        from generating overflows, although this is very unlikely in subterms.
2610
 *        This routine should not return an error condition.
2611
 *
2612
 *        Originally this routine was called Compare.
2613
 *        With the treatment of special polynomials with terms that contain only
2614
 *        symbols and the need for extreme speed for the polynomial routines we
2615
 *        made a special compare routine and now we store the address of the 
2616
 *        current compare routine in AR.CompareRoutine and have a macro Compare
2617
 *        which makes all existing code work properly and we can just replace the
2618
 *        routine on a thread by thread basis (each thread has its own AR struct).
2619
 *
2620
 *        @param term1 First input term
2621
 *        @param term2 Second input term
2622
 *        @param level The sorting level (may influence on the result)
2623
 *        @return 0        equal ( with exception of the coefficient if level == 0. )
2624
 *                >0        term1 comes first.
2625
 *                <0        term2 comes first.
2626
 *
2627
 *  When there are floating point numbers active (float_ = FLOATFUN)
2628
 *  the presence of one or more float_ functions is returned in
2629
 *  AT.SortFloatMode:
2630
 *        0: no float_
2631
 *        1: float_ in term1 only
2632
 *        2: float_ in term2 only
2633
 *        3: float_ in both terms
2634
 */
2635

2636
WORD Compare1(PHEAD WORD *term1, WORD *term2, WORD level)
92,555,722✔
2637
{
2638
        SORTING *S = AT.SS;
92,555,722✔
2639
        WORD *stopper1, *stopper2, *t2;
92,555,722✔
2640
        WORD *s1, *s2, *t1;
92,555,722✔
2641
        WORD *stopex1, *stopex2;
92,555,722✔
2642
        WORD c1, c2;
92,555,722✔
2643
        WORD prevorder;
92,555,722✔
2644
        WORD count = -1, localPoly, polyhit = -1;
92,555,722✔
2645

2646
        if ( AR.sLevel == 0 ) {
92,555,722✔
2647
                numcompares++;
68,491,579✔
2648
        }
2649

2650
        if ( S->PolyFlag ) {
92,555,722✔
2651
/*
2652
                if ( S->PolyWise != 0 ) {
2653
                        MLOCK(ErrorMessageLock);
2654
                        MesPrint("S->PolyWise is not zero!!!!!");
2655
                        MUNLOCK(ErrorMessageLock);
2656
                }
2657
*/
2658
                count = 0; localPoly = 1; S->PolyWise = polyhit = 0;
900,307✔
2659
                S->PolyFlag = AR.PolyFunType;
900,307✔
2660
                if ( AR.PolyFunType == 2 &&
900,307✔
2661
                         ( AR.PolyFunExp == 2 || AR.PolyFunExp == 3 ) ) S->PolyFlag = 1;
900,255✔
2662
        }
2663
        else { localPoly = 0; }
2664
#ifdef WITHFLOAT
2665
        AT.SortFloatMode = 0;
92,555,722✔
2666
#endif
2667
        prevorder = 0;
92,555,722✔
2668
        GETSTOP(term1,s1);
92,555,722✔
2669
        stopper1 = s1;
92,555,722✔
2670
        GETSTOP(term2,stopper2);
92,555,722✔
2671
        t1 = term1 + 1;
92,555,722✔
2672
        t2 = term2 + 1;
92,555,722✔
2673
        while ( t1 < stopper1 && t2 < stopper2 ) {
124,941,105✔
2674
                if ( *t1 != *t2 ) {
107,730,663✔
2675
                        if ( *t1 == HAAKJE ) return(PREV(-1));
57,317✔
2676
                        if ( *t2 == HAAKJE ) return(PREV(1));
38,681✔
2677
                        if ( *t1 >= (FUNCTION-1) ) {
36,822✔
2678
                                if ( *t2 < (FUNCTION-1) ) return(PREV(-1));
32,537✔
2679
                                if ( *t1 < FUNCTION && *t2 < FUNCTION ) return(PREV(*t2-*t1));
29,519✔
2680
                                if ( *t1 < FUNCTION ) return(PREV(1));
29,519✔
2681
                                if ( *t2 < FUNCTION ) return(PREV(-1));
29,519✔
2682
                                c1 = functions[*t1-FUNCTION].commute;
29,519✔
2683
                                c2 = functions[*t2-FUNCTION].commute;
29,519✔
2684
                                if ( !c1 ) {
29,519✔
2685
                                        if ( c2 ) return(PREV(1));
29,453✔
2686
                                        else return(PREV(*t2-*t1));
29,453✔
2687
                                }
2688
                                else {
2689
                                        if ( !c2 ) return(PREV(-1));
66✔
2690
                                        else return(PREV(*t2-*t1));
66✔
2691
                                }
2692
                        }
2693
                        else return(PREV(*t2-*t1));
4,285✔
2694
                }
2695
                s1 = t1 + 2;
107,673,346✔
2696
                s2 = t2 + 2;
107,673,346✔
2697
                c1 = *t1;
107,673,346✔
2698
                t1 += t1[1];
107,673,346✔
2699
                t2 += t2[1];
107,673,346✔
2700
                if ( localPoly && c1 < FUNCTION ) {
107,673,346✔
2701
                        polyhit = 1;
2702
                }
2703
                if ( c1 <= (FUNCTION-1)
107,673,278✔
2704
                || ( c1 >= FUNCTION && functions[c1-FUNCTION].spec > 0 ) ) {
51,180,048✔
2705
                        if ( c1 == SYMBOL ) {
56,852,764✔
2706
                                if ( *s1 == FACTORSYMBOL && *s2 == FACTORSYMBOL
33,523,054✔
2707
                                 && s1[-1] == 4 && s2[-1] == 4
5,190✔
2708
                                 && ( ( t1 < stopper1 && *t1 == HAAKJE )
5,190✔
2709
                                 || ( t1 == stopper1 && AT.fromindex ) ) ) {
×
2710
/*
2711
                                        We have to be very careful with the criteria here, because
2712
                                        Compare1 is called both in the regular sorting and by the
2713
                                        routine that makes the bracket index. In the last case
2714
                                        there is no HAAKJE subterm.
2715
*/
2716
                                        if ( s1[1] != s2[1] ) return(s2[1]-s1[1]);
5,190✔
2717
                                        s1 += 2; s2 += 2;
3,107✔
2718
                                }
2719
                                else if ( AR.SortType >= SORTPOWERFIRST ) {
33,517,864✔
2720
                                        WORD i1 = 0, *r1;
2721
                                        r1 = s1;
2722
                                        while ( s1 < t1 ) { i1 += s1[1]; s1 += 2; }
×
2723
                                        s1 = r1; r1 = s2;
×
2724
                                        while ( s2 < t2 ) { i1 -= s2[1]; s2 += 2; }
×
2725
                                        s2 = r1;
×
2726
                                        if ( i1 ) {
×
2727
                                                if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
×
2728
                                                return(PREV(i1));
×
2729
                                        }
2730
                                }
2731
                                while ( s1 < t1 ) {
55,547,116✔
2732
                                        if ( s2 >= t2 ) {
51,938,145✔
2733
/*                                                return(PREV(1));  */
2734
                                                if ( AR.SortType==SORTLOWFIRST ) {
67,397✔
2735
                                                        return(PREV((s1[1]>0?-1:1)));
70,618✔
2736
                                                }
2737
                                                else {
2738
                                                        return(PREV((s1[1]<0?-1:1)));
3,744✔
2739
                                                }
2740
                                        }
2741
                                        if ( *s1 != *s2 ) {
51,870,748✔
2742
/*                                                return(PREV(*s2-*s1)); */
2743
                                                if ( AR.SortType==SORTLOWFIRST ) {
1,856,855✔
2744
                                                        if ( *s1 < *s2 ) {
1,837,073✔
2745
                                                                return(PREV((s1[1]<0?1:-1)));
2,437,177✔
2746
                                                        }
2747
                                                        else {
2748
                                                                return(PREV((s2[1]<0?-1:1)));
1,181,954✔
2749
                                                        }
2750
                                                }
2751
                                                else {
2752
                                                        if ( *s1 < *s2 ) {
19,782✔
2753
                                                                return(PREV((s1[1]<0?-1:1)));
16,944✔
2754
                                                        }
2755
                                                        else {
2756
                                                                return(PREV((s2[1]<0?1:-1)));
22,620✔
2757
                                                        }
2758
                                                }
2759
                                        }
2760
                                        s1++; s2++;
50,013,893✔
2761
                                        if ( *s1 != *s2 ) return(
50,013,893✔
2762
                                                PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
27,987,748✔
2763
                                        s1++; s2++;
22,026,145✔
2764
                                }
2765
                                if ( s2 < t2 ) {
3,608,971✔
2766
/*                                        return(PREV(-1));  */
2767
                                        if ( AR.SortType==SORTLOWFIRST ) {
84,667✔
2768
                                                return(PREV((s2[1]<0?-1:1)));
166,106✔
2769
                                        }
2770
                                        else {
2771
                                                return(PREV((s2[1]<0?1:-1)));
264✔
2772
                                        }
2773
                                }
2774
                        }
2775
                        else if ( c1 == DOTPRODUCT ) {
23,329,710✔
2776
                                if ( AR.SortType >= SORTPOWERFIRST ) {
1,860✔
2777
                                        WORD i1 = 0, *r1;
2778
                                        r1 = s1;
2779
                                        while ( s1 < t1 ) { i1 += s1[2]; s1 += 3; }
×
2780
                                        s1 = r1; r1 = s2;
×
2781
                                        while ( s2 < t2 ) { i1 -= s2[2]; s2 += 3; }
×
2782
                                        s2 = r1;
×
2783
                                        if ( i1 ) {
×
2784
                                                if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
×
2785
                                                return(PREV(i1));
×
2786
                                        }
2787
                                }
2788
                                while ( s1 < t1 ) {
3,588✔
2789
                                        if ( s2 >= t2 ) return(PREV(1));
1,860✔
2790
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
1,860✔
2791
                                        s1++; s2++;
1,860✔
2792
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
1,860✔
2793
                                        s1++; s2++;
1,848✔
2794
                                        if ( *s1 != *s2 ) return(
1,848✔
2795
                                                PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
120✔
2796
                                        s1++; s2++;
1,728✔
2797
                                }
2798
                                if ( s2 < t2 ) return(PREV(-1));
1,728✔
2799
                        }
2800
                        else {
2801
                                while ( s1 < t1 ) {
186,331,740✔
2802
                                        if ( s2 >= t2 ) return(PREV(1));
185,752,880✔
2803
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
185,752,880✔
2804
                                        s1++; s2++;
163,003,890✔
2805
                                }
2806
                                if ( s2 < t2 ) return(PREV(-1));
578,860✔
2807
                        }
2808
                }
2809
                else {
2810
#if FUNHEAD != 2
2811
                        s1 += FUNHEAD-2;
50,820,582✔
2812
                        s2 += FUNHEAD-2;
50,820,582✔
2813
#endif
2814
                        if ( localPoly && c1 == AR.PolyFun ) {
50,820,582✔
2815
                                if ( count == 0 ) {
765,955✔
2816
                                  if ( S->PolyFlag == 1 ) {
765,955✔
2817
                                        WORD i1, i2;
24✔
2818
                                        if ( *s1 > 0 ) i1 = *s1;
24✔
2819
                                        else if ( *s1 <= -FUNCTION ) i1 = 1;
×
2820
                                        else i1 = 2;
×
2821
                                        if ( *s2 > 0 ) i2 = *s2;
24✔
2822
                                        else if ( *s2 <= -FUNCTION ) i2 = 1;
×
2823
                                        else i2 = 2;
×
2824
                                        if ( s1+i1 == t1 && s2+i2 == t2 ) {        /* This is the stuff */
24✔
2825
/*
2826
                                                Test for scalar nature
2827
*/
2828
                                                if ( !polyhit ) {
24✔
2829
                                                        WORD *u1, *u2, *ustop;
18✔
2830
                                                        if ( *s1 < 0 ) {
18✔
2831
                                                                if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
×
2832
                                                                        goto NoPoly;
×
2833
                                                        }
2834
                                                        else {
2835
                                                                u1 = s1 + ARGHEAD;
18✔
2836
                                                                while ( u1 < t1 ) {
61✔
2837
                                                                        u2 = u1 + *u1;
43✔
2838
                                                                        ustop = u2 - ABS(u2[-1]);
43✔
2839
                                                                        u1++;
43✔
2840
                                                                        while ( u1 < ustop ) {
80✔
2841
                                                                                if ( *u1 == INDEX ) goto NoPoly;
37✔
2842
                                                                                u1 += u1[1];
37✔
2843
                                                                        }
2844
                                                                        u1 = u2;
2845
                                                                }
2846
                                                        }
2847
                                                        if ( *s2 < 0 ) {
18✔
2848
                                                                if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
×
2849
                                                                        goto NoPoly;
×
2850
                                                        }
2851
                                                        else {
2852
                                                                u1 = s2 + ARGHEAD;
18✔
2853
                                                                while ( u1 < t2 ) {
50✔
2854
                                                                        u2 = u1 + *u1;
32✔
2855
                                                                        ustop = u2 - ABS(u2[-1]);
32✔
2856
                                                                        u1++;
32✔
2857
                                                                        while ( u1 < ustop ) {
58✔
2858
                                                                                if ( *u1 == INDEX ) goto NoPoly;
26✔
2859
                                                                                u1 += u1[1];
26✔
2860
                                                                        }
2861
                                                                        u1 = u2;
2862
                                                                }
2863
                                                        }
2864
                                                }
2865
                                                S->PolyWise = WORDDIF(s1,term1);
24✔
2866
                                                S->PolyWise -= FUNHEAD;
24✔
2867
                                                count = 1;
24✔
2868
                                                continue;
24✔
2869
                                        }
2870
                                        else {
2871
NoPoly:
×
2872
                                                S->PolyWise = localPoly = 0;
×
2873
                                        }
2874
                                  }
2875
                                  else if ( AR.PolyFunType == 2 ) {
765,931✔
2876
                                        WORD i1, i2, i1a, i2a;
765,931✔
2877
                                        if ( *s1 > 0 ) i1 = *s1;
765,931✔
2878
                                        else if ( *s1 <= -FUNCTION ) i1 = 1;
16,524✔
2879
                                        else i1 = 2;
16,524✔
2880
                                        if ( *s2 > 0 ) i2 = *s2;
765,931✔
2881
                                        else if ( *s2 <= -FUNCTION ) i2 = 1;
21,372✔
2882
                                        else i2 = 2;
21,372✔
2883
                                        if ( s1[i1] > 0 ) i1a = s1[i1];
765,931✔
2884
                                        else if ( s1[i1] <= -FUNCTION ) i1a = 1;
21,474✔
2885
                                        else i1a = 2;
21,474✔
2886
                                        if ( s2[i2] > 0 ) i2a = s2[i2];
765,931✔
2887
                                        else if ( s2[i2] <= -FUNCTION ) i2a = 1;
16,710✔
2888
                                        else i2a = 2;
16,710✔
2889
                                        if ( s1+i1+i1a == t1 && s2+i2+i2a == t2 ) {        /* This is the stuff */
765,931✔
2890
/*
2891
                                                Test for scalar nature
2892
*/
2893
                                                if ( !polyhit ) {
765,931✔
2894
                                                        WORD *u1, *u2, *ustop;
765,913✔
2895
                                                        if ( *s1 < 0 ) {
765,913✔
2896
                                                                if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
16,518✔
2897
                                                                        goto NoPoly;
×
2898
                                                        }
2899
                                                        else {
2900
                                                                u1 = s1 + ARGHEAD;
749,395✔
2901
                                                                while ( u1 < s1+i1 ) {
4,283,683✔
2902
                                                                        u2 = u1 + *u1;
3,534,288✔
2903
                                                                        ustop = u2 - ABS(u2[-1]);
3,534,288✔
2904
                                                                        u1++;
3,534,288✔
2905
                                                                        while ( u1 < ustop ) {
6,334,757✔
2906
                                                                                if ( *u1 == INDEX ) goto NoPoly;
2,800,469✔
2907
                                                                                u1 += u1[1];
2,800,469✔
2908
                                                                        }
2909
                                                                        u1 = u2;
2910
                                                                }
2911
                                                        }
2912
                                                        if ( s1[i1] < 0 ) {
765,913✔
2913
                                                                if ( s1[i1] != -SNUMBER && s1[i1] != -SYMBOL && s1[i1] > -FUNCTION )
21,474✔
2914
                                                                        goto NoPoly;
×
2915
                                                        }
2916
                                                        else {
2917
                                                                u1 = s1 +i1 + ARGHEAD;
744,439✔
2918
                                                                while ( u1 < t1 ) {
4,367,731✔
2919
                                                                        u2 = u1 + *u1;
3,623,292✔
2920
                                                                        ustop = u2 - ABS(u2[-1]);
3,623,292✔
2921
                                                                        u1++;
3,623,292✔
2922
                                                                        while ( u1 < ustop ) {
6,513,593✔
2923
                                                                                if ( *u1 == INDEX ) goto NoPoly;
2,890,301✔
2924
                                                                                u1 += u1[1];
2,890,301✔
2925
                                                                        }
2926
                                                                        u1 = u2;
2927
                                                                }
2928
                                                        }
2929
                                                        if ( *s2 < 0 ) {
765,913✔
2930
                                                                if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
21,366✔
2931
                                                                        goto NoPoly;
×
2932
                                                        }
2933
                                                        else {
2934
                                                                u1 = s2 + ARGHEAD;
744,547✔
2935
                                                                while ( u1 < s2+i2 ) {
4,328,061✔
2936
                                                                        u2 = u1 + *u1;
3,583,514✔
2937
                                                                        ustop = u2 - ABS(u2[-1]);
3,583,514✔
2938
                                                                        u1++;
3,583,514✔
2939
                                                                        while ( u1 < ustop ) {
6,434,025✔
2940
                                                                                if ( *u1 == INDEX ) goto NoPoly;
2,850,511✔
2941
                                                                                u1 += u1[1];
2,850,511✔
2942
                                                                        }
2943
                                                                        u1 = u2;
2944
                                                                }
2945
                                                        }
2946
                                                        if ( s2[i2] < 0 ) {
765,913✔
2947
                                                                if ( s2[i2] != -SNUMBER && s2[i2] != -SYMBOL && s2[i2] > -FUNCTION )
16,710✔
2948
                                                                        goto NoPoly;
×
2949
                                                        }
2950
                                                        else {
2951
                                                                u1 = s2 + i2 + ARGHEAD;
749,203✔
2952
                                                                while ( u1 < t2 ) {
4,692,112✔
2953
                                                                        u2 = u1 + *u1;
3,942,909✔
2954
                                                                        ustop = u2 - ABS(u2[-1]);
3,942,909✔
2955
                                                                        u1++;
3,942,909✔
2956
                                                                        while ( u1 < ustop ) {
7,152,011✔
2957
                                                                                if ( *u1 == INDEX ) goto NoPoly;
3,209,102✔
2958
                                                                                u1 += u1[1];
3,209,102✔
2959
                                                                        }
2960
                                                                        u1 = u2;
2961
                                                                }
2962
                                                        }
2963
                                                }
2964
                                                S->PolyWise = WORDDIF(s1,term1);
765,931✔
2965
                                                S->PolyWise -= FUNHEAD;
765,931✔
2966
                                                count = 1;
765,931✔
2967
                                                continue;
765,931✔
2968
                                        }
2969
                                        else {
2970
                                                S->PolyWise = localPoly = 0;
×
2971
                                        }
2972
                                  }
2973
                                  else {
2974
                                        S->PolyWise = localPoly = 0;
×
2975
                                  }
2976
                                }
2977
                                else {
2978
                                        t1 = term1 + S->PolyWise;
×
2979
                                        t2 = term2 + S->PolyWise;
×
2980
                                        S->PolyWise = 0;
×
2981
                                        localPoly = 0;
×
2982
                                        continue;
×
2983
                                }
2984
                        }
2985
#ifdef WITHFLOAT
2986
                        if ( c1 == FLOATFUN && t1 == stopper1 && t2 == stopper2 && AT.aux_ != 0 ) {
50,054,627✔
2987
/*
2988
                                We have two FLOATFUN's. Test whether they are 'legal'
2989
*/
2990
                                if ( TestFloat(s1-FUNHEAD) ) {
×
2991
                                        if ( TestFloat(s2-FUNHEAD) ) { AT.SortFloatMode = 3; return(0); }
×
2992
                                        else { return(1); }
2993
                                }
2994
                                else if ( TestFloat(s2-FUNHEAD) ) { return(-1); }
×
2995
                        }
2996
#endif
2997
                        while ( s1 < t1 ) {
77,939,597✔
2998
/*
2999
                                The next statement was added 9-nov-2001. It repaired a bad error
3000
*/
3001
                                if ( s2 >= t2 ) return(PREV(-1));
50,425,055✔
3002
/*
3003
                                There is a little problem here with fast arguments
3004
                                We don't want to sacrifice speed, but we like to
3005
                                keep a rational ordering. This last one suffers in
3006
                                the solution that has been chosen here.
3007
*/
3008
                                if ( AC.properorderflag ) {
50,425,019✔
3009
                                        WORD oldpolyflag;
×
3010
                                        oldpolyflag = S->PolyFlag;
×
3011
                                        S->PolyFlag = 0;
×
3012
                                        if ( ( c2 = -CompArg(s1,s2) ) != 0 ) {
×
3013
                                                S->PolyFlag = oldpolyflag; return(PREV(c2));
×
3014
                                        }
3015
                                        S->PolyFlag = oldpolyflag;
×
3016
                                        NEXTARG(s1)
×
3017
                                        NEXTARG(s2)
×
3018
                                }
3019
                                else {
3020
                                        if ( *s1 > 0 ) {
50,425,019✔
3021
                                                if ( *s2 > 0 ) {
356,014✔
3022
                                                        WORD oldpolyflag;
352,971✔
3023
                                                        stopex1 = s1 + *s1;
352,971✔
3024
                                                        if ( s2 >= t2 ) return(PREV(-1));
352,971✔
3025
                                                        stopex2 = s2 + *s2;
352,971✔
3026
                                                        s1 += ARGHEAD; s2 += ARGHEAD;
352,971✔
3027
                                                        oldpolyflag = S->PolyFlag;
352,971✔
3028
                                                        S->PolyFlag = 0;
352,971✔
3029
                                                        while ( s1 < stopex1 ) {
1,228,973✔
3030
                                                                if ( s2 >= stopex2 ) {
1,063,197✔
3031
                                                                        S->PolyFlag = oldpolyflag; return(PREV(-1));
2,880✔
3032
                                                                }
3033
                                                                if ( ( c2 = CompareTerms(BHEAD s1,s2,(WORD)1) ) != 0 ) {
1,060,317✔
3034
                                                                        S->PolyFlag = oldpolyflag; return(PREV(c2));
184,315✔
3035
                                                                }
3036
                                                                s1 += *s1;
876,002✔
3037
                                                                s2 += *s2;
876,002✔
3038
                                                        }
3039
                                                        S->PolyFlag = oldpolyflag;
165,776✔
3040
                                                        if ( s2 < stopex2 ) return(PREV(1));
165,776✔
3041
                                                }
3042
                                                else return(PREV(1));
3043
                                        }
3044
                                        else {
3045
                                                if ( *s2 > 0 ) return(PREV(-1));
50,069,005✔
3046
                                                if ( *s1 != *s2 ) { return(PREV(*s1-*s2)); }
50,065,871✔
3047
                                                if ( *s1 > -FUNCTION ) {
50,044,962✔
3048
                                                        if ( *++s1 != *++s2 ) { return(PREV(*s2-*s1)); }
50,022,348✔
3049
                                                }
3050
                                                s1++; s2++;
27,737,881✔
3051
                                        }
3052
                                }
3053
                        }
3054
                        if ( s2 < t2 ) return(PREV(1));
27,514,542✔
3055
                }
3056
        }
3057
#ifdef WITHFLOAT
3058
        if ( t1 < stopper1 && *t1 == FLOATFUN && t1+t1[1] == stopper1
17,210,442✔
3059
                        && TestFloat(t1) ) {
×
3060
                AT.SortFloatMode = 1; return(0);
×
3061
        }
3062
        else if ( t2 < stopper2 && *t2 == FLOATFUN && t2+t2[1] == stopper2
17,210,442✔
3063
                        && TestFloat(t2) ) {
×
3064
                AT.SortFloatMode = 2; return(0);
×
3065
        }
3066
#endif
3067
        {
3068
                if ( AR.SortType != SORTLOWFIRST ) {
17,210,442✔
3069
                        if ( t1 < stopper1 ) return(PREV(1));
4,554,432✔
3070
                        if ( t2 < stopper2 ) return(PREV(-1));
793,284✔
3071
                }
3072
                else {
3073
                        if ( t1 < stopper1 ) return(PREV(-1));
12,656,010✔
3074
                        if ( t2 < stopper2 ) return(PREV(1));
12,354,165✔
3075
                }
3076
        }
3077
        if ( level == 3 ) return(CompCoef(term1,term2));
12,130,227✔
3078
        if ( level >= 1 )
12,130,227✔
3079
                return(CompCoef(term2,term1));
895,479✔
3080
        return(0);
3081
}
3082

3083
/*
3084
                 #] Compare1 : 
3085
                 #[ CompareSymbols :                        WORD CompareSymbols(term1,term2,par)
3086
*/
3087
/**
3088
 *        Compares the terms, based on the value of AN.polysortflag.
3089
 *        If term1 < term2 the return value is -1
3090
 *        If term1 > term2 the return value is  1
3091
 *        If term1 = term2 the return value is  0
3092
 *        The coefficients may differ.
3093
 *        The terms contain only a single subterm of type SYMBOL.
3094
 *        If AN.polysortflag = 0 it is a 'regular' compare.
3095
 *        If AN.polysortflag = 1 the sum of the powers is more important
3096
 *        par is a dummy parameter to make the parameter field identical
3097
 *        to that of Compare1 which is the regular compare routine in sort.c
3098
 */
3099

3100
WORD CompareSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
10,337,396✔
3101
{
3102
        int sum1, sum2;
10,337,396✔
3103
        WORD *t1, *t2, *tt1, *tt2;
10,337,396✔
3104
        int low, high;
10,337,396✔
3105
        DUMMYUSE(par);
10,337,396✔
3106
        if ( AR.SortType == SORTLOWFIRST ) { low = 1; high = -1; }
10,337,396✔
3107
        else { low = -1; high = 1; }
10,050,472✔
3108
        t1 = term1 + 1; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); t1 += 2;
10,337,396✔
3109
        t2 = term2 + 1; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); t2 += 2;
10,337,396✔
3110
        if ( AN.polysortflag > 0 ) {
10,337,396✔
3111
                sum1 = 0; sum2 = 0;
×
3112
                while ( t1 < tt1 ) { sum1 += t1[1]; t1 += 2; }
×
3113
                while ( t2 < tt2 ) { sum2 += t2[1]; t2 += 2; }
×
3114
                if ( sum1 < sum2 ) return(low);
×
3115
                if ( sum1 > sum2 ) return(high);
×
3116
                t1 = term1+3; t2 = term2 + 3;
3117
        }
3118
        while ( t1 < tt1 && t2 < tt2 ) {
13,546,870✔
3119
                if ( *t1 > *t2 ) return(low);
9,587,725✔
3120
                if ( *t1 < *t2 ) return(high);
8,976,559✔
3121
                if ( t1[1] < t2[1] ) return(low);
8,778,666✔
3122
                if ( t1[1] > t2[1] ) return(high);
5,231,514✔
3123
                t1 += 2; t2 += 2;
3,209,474✔
3124
        }
3125
        if ( t1 < tt1 ) return(high);
3,959,145✔
3126
        if ( t2 < tt2 ) return(low);
594,816✔
3127
        return(0);
3128
}
3129

3130
/*
3131
                 #] CompareSymbols : 
3132
                 #[ CompareHSymbols :                WORD CompareHSymbols(term1,term2,par)
3133
*/
3134
/**
3135
 *        Compares terms that can have only SYMBOL and HAAKJE subterms.
3136
 *        If term1 < term2 the return value is -1
3137
 *        If term1 > term2 the return value is  1
3138
 *        If term1 = term2 the return value is  0
3139
 *        par is a dummy parameter to make the parameter field identical
3140
 *        to that of Compare1 which is the regular compare routine in sort.c
3141
 */
3142

3143
WORD CompareHSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
×
3144
{
3145
        WORD *t1, *t2, *tt1, *tt2, *ttt1, *ttt2;
×
3146
        DUMMYUSE(par);
×
3147
        DUMMYUSE(AT.WorkPointer);
×
3148
        t1 = term1 + 1; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); t1 += 2;
×
3149
        t2 = term2 + 1; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); t2 += 2;
×
3150
        while ( t1 < tt1 && t2 < tt2 ) {
×
3151
                if ( *t1 != *t2 ) {
×
3152
                        if ( t1[0] < t2[0] ) return(-1);
×
3153
                        return(1);
×
3154
                }
3155
                else if ( *t1 == HAAKJE ) {
×
3156
                        t1 += 3; t2 += 3; continue;
×
3157
                }
3158
                ttt1 = t1+t1[1]; ttt2 = t2+t2[1];
×
3159
                while ( t1 < ttt1 && t2 < ttt2 ) {
×
3160
                        if ( *t1 > *t2 ) return(-1);
×
3161
                        if ( *t1 < *t2 ) return(1);
×
3162
                        if ( t1[1] < t2[1] ) return(-1);
×
3163
                        if ( t1[1] > t2[1] ) return(1);
×
3164
                        t1 += 2; t2 += 2;
×
3165
                }
3166
                if ( t1 < ttt1 ) return(1);
×
3167
                if ( t2 < ttt2 ) return(-1);
×
3168
        }
3169
        if ( t1 < tt1 ) return(1);
×
3170
        if ( t2 < tt2 ) return(-1);
×
3171
        return(0);
3172
}
3173

3174
/*
3175
                 #] CompareHSymbols : 
3176
                 #[ ComPress :                                LONG ComPress(ss,n)
3177
*/
3178
/**
3179
 *                Gets a list of pointers to terms and compresses the terms.
3180
 *                In n it collects the number of terms and the return value
3181
 *                of the function is the space that is occupied.
3182
 *
3183
 *                We have to pay some special attention to the compression of
3184
 *                terms with a PolyFun. This PolyFun should occur only straight
3185
 *                before the coefficient, so we can use the same trick as for
3186
 *                the coefficient to sabotage compression of this object
3187
 *                (Replace in the history the function pointer by zero. This
3188
 *                is safe, because terms that would be identical otherwise would
3189
 *                have been added).
3190
 *
3191
 *                @param ss Array of pointers to terms to be compressed.
3192
 *                @param n  Number of pointers in ss.
3193
 *                @return   Total number of words needed for the compressed result.
3194
 */
3195

3196
LONG ComPress(WORD **ss, LONG *n)
7,288✔
3197
{
3198
        GETIDENTITY
4,804✔
3199
        WORD *t, *s, j, k;
7,288✔
3200
        LONG size = 0;
7,288✔
3201
        int newsize, i;
7,288✔
3202
/*
3203
                        #[ debug :
3204

3205
        WORD **sss = ss;
3206

3207
        if ( AP.DebugFlag ) {
3208
                UBYTE OutBuf[140];
3209
                MLOCK(ErrorMessageLock);
3210
                MesPrint("ComPress:");
3211
                AO.OutFill = AO.OutputLine = OutBuf;
3212
                AO.OutSkip = 3;
3213
                FiniLine();
3214
                ss = sss;
3215
                while ( *ss ) {
3216
                        s = *ss++;
3217
                        j = *s;
3218
                        if ( j < 0 ) {
3219
                                j = s[1] + 2;
3220
                        }
3221
                        while ( --j >= 0 ) {
3222
                                TalToLine((UWORD)(*s++)); TokenToLine((UBYTE *)"  ");
3223
                        }
3224
                        FiniLine();
3225
                }
3226
                AO.OutSkip = 0;
3227
                FiniLine();
3228
                MUNLOCK(ErrorMessageLock);
3229
                ss = sss;
3230
        }
3231

3232
                        #] debug : 
3233
*/
3234
        *n = 0;
7,288✔
3235
        if ( AT.SS == AT.S0 && !AR.NoCompress ) {
7,288✔
3236
                if ( AN.compressSize == 0 ) {
6,110✔
3237
                        if ( *ss ) { AN.compressSize = **ss + 64; }
34✔
3238
                        else       { AN.compressSize = AM.MaxTer/sizeof(WORD) + 2; }
×
3239
                        AN.compressSpace = (WORD *)Malloc1(AN.compressSize*sizeof(WORD),"Compression");
34✔
3240
                }
3241
                AN.compressSpace[0] = 0;
6,110✔
3242
                while ( *ss ) {
1,471,539✔
3243
                        k = 0;
1,465,429✔
3244
                        s = *ss;
1,465,429✔
3245
                        j = *s++;
1,465,429✔
3246
                        if ( j > AN.compressSize ) {
1,465,429✔
3247
                                newsize = j + 64;
×
3248
                                t = (WORD *)Malloc1(newsize*sizeof(WORD),"Compression");
×
3249
                                t[0] = 0;
×
3250
                                if ( AN.compressSpace ) {
×
3251
                                        for ( i = 0; i < *AN.compressSpace; i++ ) t[i] = AN.compressSpace[i];
×
3252
                                        M_free(AN.compressSpace,"Compression");
×
3253
                                }
3254
                                AN.compressSpace = t;
×
3255
                                AN.compressSize = newsize;
×
3256
                        }
3257
                        t = AN.compressSpace;
1,465,429✔
3258
                        i = *t - 1;
1,465,429✔
3259
                        *t++ = j; j--;
1,465,429✔
3260
                        if ( AR.PolyFun ) {
1,465,429✔
3261
                                WORD *polystop, *sa;
×
3262
                                sa = s + j;
×
3263
                                sa -= ABS(sa[-1]);
×
3264
                                polystop = s;
×
3265
                                while ( polystop < sa && *polystop != AR.PolyFun ) {
×
3266
                                        polystop += polystop[1];
×
3267
                                }
3268
                                while ( i > 0 && j > 0 && *s == *t && s < polystop ) {
×
3269
                                        i--; j--; s++; t++; k--;
×
3270
                                }
3271
                        }
3272
                        else {
3273
                                WORD *sa;
1,465,429✔
3274
                                sa = s + j;
1,465,429✔
3275
                                sa -= ABS(sa[-1]);
1,465,429✔
3276
                                while ( i > 0 && j > 0 && *s == *t && s < sa ) { i--; j--; s++; t++; k--; }
7,810,099✔
3277
                        }
3278
                        if ( k < -1 ) {
1,465,429✔
3279
                                s[-1] = j;
1,459,317✔
3280
                                s[-2] = k;
1,459,317✔
3281
                                *ss = s-2;
1,459,317✔
3282
                                size += j + 2;
1,459,317✔
3283
                        }
3284
                        else {
3285
                                size += *AN.compressSpace;
6,112✔
3286
                                if ( k == -1 ) { t--; s--; j++; }
6,112✔
3287
                        }
3288
                        while ( --j >= 0 ) *t++ = *s++;
7,356,956✔
3289
/*                                        Sabotage getting into the coefficient next time */
3290
                        t = AN.compressSpace + *AN.compressSpace;
1,465,429✔
3291
                        t[-(ABS(t[-1]))] = 0;
1,465,429✔
3292
                        ss++;
1,465,429✔
3293
                        (*n)++;
1,465,429✔
3294
                }
3295
        }
3296
        else {
3297
                while ( *ss ) {
12,876,317✔
3298
                        size += *(*ss++);
12,875,139✔
3299
                        (*n)++;
12,875,139✔
3300
                }
3301
        }
3302
/*
3303
                        #[ debug :
3304

3305
        if ( AP.DebugFlag ) {
3306
                UBYTE OutBuf[140];
3307
                AO.OutFill = AO.OutputLine = OutBuf;
3308
                AO.OutSkip = 3;
3309
                FiniLine();
3310
                ss = sss;
3311
                while ( *ss ) {
3312
                        s = *ss++;
3313
                        j = *s;
3314
                        if ( j < 0 ) {
3315
                                j = s[1] + 2;
3316
                        }
3317
                        while ( --j >= 0 ) {
3318
                                TalToLine((UWORD)(*s++)); TokenToLine((UBYTE *)"  ");
3319
                        }
3320
                        FiniLine();
3321
                }
3322
                AO.OutSkip = 0;
3323
                FiniLine();
3324
        }
3325

3326
                        #] debug : 
3327
*/
3328
        return(size);
7,288✔
3329
}
3330

3331
/*
3332
                 #] ComPress : 
3333
                 #[ SplitMerge :                                void SplitMerge(Point,number)
3334
*/
3335
/**
3336
 *                Algorithm by J.A.M.Vermaseren (31-7-1988)
3337
 *
3338
 *                Note that AN.SplitScratch and AN.InScratch are used also in GarbHand
3339
 *
3340
 *                Merge sort in memory. The input is an array of pointers.
3341
 *                Sorting is done recursively by dividing the array in two equal parts
3342
 *                and calling SplitMerge for each.
3343
 *                When the parts are small enough we can do the compare and take the
3344
 *                appropriate action.
3345
 *                An addition is that we look for 'runs'. Sequences that are already
3346
 *                ordered. This happens a lot when there is very little action in a
3347
 *                module. This made FORM faster by a few percent.
3348
 *
3349
 *                @param  Pointer The array of pointers to the terms to be sorted.
3350
 *                @param  number  The number of pointers in Pointer.
3351
 *
3352
 *                The terms are supposed to be sitting in the small buffer and there
3353
 *                is supposed to be an extension to this buffer for when there are
3354
 *                two terms that should be added and the result takes more space than
3355
 *                each of the original terms. The notation guarantees that the result
3356
 *                never needs more space than the sum of the spaces of the original
3357
 *                terms.
3358
 */
3359

3360
#ifdef NEWSPLITMERGE
3361

3362
LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
53,586,399✔
3363
{
3364
        GETBIDENTITY
3365
        SORTING *S = AT.SS;
53,586,399✔
3366
        WORD **pp3, **pp1, **pp2, **pptop;
53,586,399✔
3367
        LONG i, newleft, newright, split;
53,586,399✔
3368

3369
#ifdef SPLITMERGEDEBUG
3370
        /* Print current array state on entry. */
3371
        printf("%4ld: ", number);
3372
        for (int ii = 0; ii < S->sTerms; ii++) {
3373
                if ( (S->sPointer)[ii] ) {
3374
                        printf("%4d ", (unsigned)(S->sPointer[ii]-S->sBuffer));
3375
                }
3376
                else {
3377
                        printf(".... ");
3378
                }
3379
        }
3380
        printf("\n");
3381
        fflush(stdout);
3382
#endif
3383

3384
        if ( number < 2 ) return(number);
53,586,399✔
3385
        if ( number == 2 ) {
46,315,024✔
3386
                pp1 = Pointer; pp2 = pp1 + 1;
24,361,569✔
3387
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
24,361,569✔
3388
                        pp3 = (WORD **)(*pp1); *pp1 = *pp2; *pp2 = (WORD *)pp3;
2,603,834✔
3389
                }
3390
                else if ( i == 0 ) {
21,757,735✔
3391
                        number--;
1,081,120✔
3392
                        if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) == 0 ) number = 0; }
1,081,120✔
3393
                        else               { if ( AddCoef(BHEAD pp1,pp2) == 0 ) number = 0; }
770,187✔
3394
                }
3395
                return(number);
24,361,569✔
3396
        }
3397
        pptop = Pointer + number;
21,953,455✔
3398
        split = number/2;
21,953,455✔
3399
        newleft  = SplitMerge(BHEAD Pointer,split);
21,953,455✔
3400
        newright = SplitMerge(BHEAD Pointer+split,number-split);
21,953,400✔
3401
        if ( newright == 0 ) return(newleft);
21,953,330✔
3402
/*
3403
        We compare the last of the left with the first of the right
3404
        If they are already in order, we will be done quickly.
3405
        We may have to compactify the buffer because the recursion may
3406
        have created holes. Also this compare may result in equal terms.
3407
        Addition of 23-jul-1999. It makes things a bit faster.
3408
*/
3409
        if ( newleft > 0 && newright > 0 &&
21,952,399✔
3410
        ( i = CompareTerms(BHEAD Pointer[newleft-1],Pointer[split],(WORD)0) ) >= 0 ) {
21,947,902✔
3411
                pp2 = Pointer+split; pp1 = Pointer+newleft-1;
18,434,364✔
3412
                if ( i == 0 ) {
18,434,364✔
3413
                        if ( S->PolyWise ) {
1,151,476✔
3414
                                if ( AddPoly(BHEAD pp1,pp2) > 0 ) pp1++;
438,259✔
UNCOV
3415
                                else newleft--;
×
3416
                        }
3417
                        else {
3418
                                if ( AddCoef(BHEAD pp1,pp2) > 0 ) pp1++;
713,217✔
3419
                                else newleft--;
2,036✔
3420
                        }
3421
                        *pp2++ = 0; newright--;
1,151,456✔
3422
                }
3423
                else pp1++;
17,282,888✔
3424
                newleft += newright;
18,434,344✔
3425
                if ( pp1 < pp2 ) {
18,434,344✔
3426
                        while ( --newright >= 0 ) *pp1++ = *pp2++;
1,260,927✔
3427
                        while ( pp1 < pptop ) *pp1++ = 0;
22,402,520✔
3428
                }
3429
                return(newleft);
18,434,344✔
3430
        }
3431

3432
        if ( split >= AN.SplitScratchSize ) {
3,518,035✔
3433
                AN.SplitScratchSize = (split*3)/2+100;
1,881✔
3434
                if ( AN.SplitScratchSize > S->Terms2InSmall/2 )
1,881✔
3435
                        AN.SplitScratchSize = S->Terms2InSmall/2;
6✔
3436
                if ( AN.SplitScratch ) M_free(AN.SplitScratch,"AN.SplitScratch");
1,881✔
3437
                AN.SplitScratch = (WORD **)Malloc1(AN.SplitScratchSize*sizeof(WORD *),"AN.SplitScratch");
1,881✔
3438
        }
3439

3440
        pp3 = AN.SplitScratch; pp1 = Pointer;
3,518,035✔
3441
        /* Move rather than copy, so GarbHand can't double-count. */
3442
        for ( i = 0; i < newleft; i++ ) { *pp3++ = *pp1; *pp1++ = 0; }
33,796,755✔
3443
        AN.InScratch = newleft;
3,518,035✔
3444
        pp1 = AN.SplitScratch; pp2 = Pointer + split; pp3 = Pointer;
3,518,035✔
3445

3446
#ifdef NEWSPLITMERGETIMSORT
3447
/*
3448
                An improvement in the style of Timsort
3449
*/
3450
        while ( newleft > 8 ) {
3,582,291✔
3451
                /* Check the middle of the LHS terms */
3452
                LONG nnleft = newleft/2;
669,162✔
3453
                if ( ( i = CompareTerms(BHEAD pp1[nnleft],*pp2,(WORD)0) ) < 0 ) {
669,162✔
3454
                        /* The terms are not in order. Break out and continue as normal. */
3455
                        break;
3456
                }
3457
                /* The terms merge or are in order. Copy pointers up to this point. */
3458
                /* In the copy, zero the skipped pointers so GarbHand can't double-count. */
3459
                for (int iii = 0; iii < nnleft; iii++) {
1,119,715✔
3460
                        *pp3++ = *pp1;
1,048,197✔
3461
                        *pp1++ = 0;
1,048,197✔
3462
                }
3463
                newleft -= nnleft;
71,518✔
3464
                if ( i == 0 ) {
71,518✔
3465
                        if ( S->PolyWise ) { i = AddPoly(BHEAD pp1,pp2); }
7,262✔
3466
                        else               { i = AddCoef(BHEAD pp1,pp2); }
7,100✔
3467
                        if ( i == 0 ) {
7,262✔
3468
                                /* The terms cancelled. The next term goes in *pp3. Don't move. */
3469
                        }
3470
                        else {
3471
                                /* The terms added. Advance pp3. */
3472
                                *pp3++ = *pp1;
7,262✔
3473
                        }
3474
                        /* We have taken a LHS (copy) and RHS term. */
3475
                        *pp2++ = 0;
7,262✔
3476
                        newright--;
7,262✔
3477
                        *pp1++ = 0;
7,262✔
3478
                        newleft--;
7,262✔
3479
                        break;
7,262✔
3480
                }
3481
        }
3482
#endif
3483

3484
        while ( newleft > 0 && newright > 0 ) {
41,164,678✔
3485
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
37,646,643✔
3486
                        *pp3++ = *pp2;
19,368,255✔
3487
                        *pp2++ = 0;
19,368,255✔
3488
                        newright--;
19,368,255✔
3489
                }
3490
                else if ( i > 0 ) {
18,278,388✔
3491
                        *pp3++ = *pp1;
9,474,922✔
3492
                        *pp1++ = 0;
9,474,922✔
3493
                        newleft--;
9,474,922✔
3494
                }
3495
                else {
3496
                        if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
8,803,466✔
3497
                        else {               if ( AddCoef(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
8,790,979✔
3498
                        *pp1++ = 0; *pp2++ = 0; newleft--; newright--;
8,803,466✔
3499
                }
3500
        }
3501
        for ( i = 0; i < newleft; i++ ) { *pp3++ = *pp1; *pp1++ = 0; }
14,462,908✔
3502
        if ( pp3 == pp2 ) {
3,518,035✔
3503
                pp3 += newright;
2,942,059✔
3504
        } else {
3505
                for ( i = 0; i < newright; i++ ) { *pp3++ = *pp2++; }
2,368,922✔
3506
        }
3507
        newleft = pp3 - Pointer;
3,518,035✔
3508
        while ( pp3 < pptop ) *pp3++ = 0;
74,292,651✔
3509
        AN.InScratch = 0;
3,518,035✔
3510
        return(newleft);
3,518,035✔
3511
}
3512

3513
#else
3514

3515
LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
3516
{
3517
        GETBIDENTITY
3518
        SORTING *S = AT.SS;
3519
        WORD **pp3, **pp1, **pp2;
3520
        LONG nleft, nright, i, newleft, newright;
3521
        WORD **pptop;
3522

3523
#ifdef SPLITMERGEDEBUG
3524
        /* Print current array state on entry. */
3525
        printf("%4ld: ", number);
3526
        for (int ii = 0; ii < S->sTerms; ii++) {
3527
                if ( (S->sPointer)[ii] ) {
3528
                        printf("%4d ", (unsigned)(S->sPointer[ii]-S->sBuffer));
3529
                }
3530
                else {
3531
                        printf(".... ");
3532
                }
3533
        }
3534
        printf("\n");
3535
        fflush(stdout);
3536
#endif
3537

3538
        if ( number < 2 ) return(number);
3539
        if ( number == 2 ) {
3540
                pp1 = Pointer; pp2 = pp1 + 1;
3541
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
3542
                        pp3 = (WORD **)(*pp1); *pp1 = *pp2; *pp2 = (WORD *)pp3;
3543
                }
3544
                else if ( i == 0 ) {
3545
                  number--;
3546
                  if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) == 0 ) { number = 0; } }
3547
                  else {               if ( AddCoef(BHEAD pp1,pp2) == 0 ) { number = 0; } }
3548
                }
3549
                return(number);
3550
        }
3551
        pptop = Pointer + number;
3552
        nleft = number >> 1; nright = number - nleft;
3553
        newleft  = SplitMerge(BHEAD Pointer,nleft);
3554
        newright = SplitMerge(BHEAD Pointer+nleft,nright);
3555
/*
3556
        We compare the last of the left with the first of the right
3557
        If they are already in order, we will be done quickly.
3558
        We may have to compactify the buffer because the recursion may
3559
        have created holes. Also this compare may result in equal terms.
3560
        Addition of 23-jul-1999. It makes things a bit faster.
3561
*/
3562
        if ( newleft > 0 && newright > 0 &&
3563
        ( i = CompareTerms(BHEAD Pointer[newleft-1],Pointer[nleft],(WORD)0) ) >= 0 ) {
3564
                pp2 = Pointer+nleft; pp1 = Pointer+newleft-1;
3565
                if ( i == 0 ) {
3566
                  if ( S->PolyWise ) {
3567
                        if ( AddPoly(BHEAD pp1,pp2) > 0 ) pp1++;
3568
                        else newleft--;
3569
                  }
3570
                  else {
3571
                        if ( AddCoef(BHEAD pp1,pp2) > 0 ) pp1++;
3572
                        else newleft--;
3573
                  }
3574
                  *pp2++ = 0; newright--;
3575
                }
3576
                else pp1++;
3577
                newleft += newright;
3578
                if ( pp1 < pp2 ) {
3579
                        while ( --newright >= 0 ) *pp1++ = *pp2++;
3580
                        while ( pp1 < pptop ) *pp1++ = 0;
3581
                }
3582
                return(newleft);
3583
        }
3584
        if ( nleft > AN.SplitScratchSize ) {
3585
                AN.SplitScratchSize = (nleft*3)/2+100;
3586
                if ( AN.SplitScratchSize > S->Terms2InSmall/2 )
3587
                         AN.SplitScratchSize = S->Terms2InSmall/2;
3588
                if ( AN.SplitScratch ) M_free(AN.SplitScratch,"AN.SplitScratch");
3589
                AN.SplitScratch = (WORD **)Malloc1(AN.SplitScratchSize*sizeof(WORD *),"AN.SplitScratch");
3590
        }
3591
        pp3 = AN.SplitScratch; pp1 = Pointer; i = nleft;
3592
        do { *pp3++ = *pp1; *pp1++ = 0; } while ( *pp1 && --i > 0 );
3593
        if ( i > 0 ) { *pp3 = 0; i--; }
3594
        AN.InScratch = nleft - i;
3595
        pp1 = AN.SplitScratch; pp2 = Pointer + nleft; pp3 = Pointer;
3596
        while ( nleft > 0 && nright > 0 && *pp1 && *pp2 ) {
3597
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
3598
                        *pp3++ = *pp2;
3599
                        *pp2++ = 0;
3600
                        nright--;
3601
                }
3602
                else if ( i > 0 ) {
3603
                        *pp3++ = *pp1;
3604
                        *pp1++ = 0;
3605
                        nleft--;
3606
                }
3607
                else {
3608
                  if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3609
                  else {               if ( AddCoef(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3610
                  *pp1++ = 0; *pp2++ = 0; nleft--; nright--;
3611
                }
3612
        }
3613
        while ( --nleft  >= 0 && *pp1 ) { *pp3++ = *pp1; *pp1++ = 0; }
3614
        while ( --nright >= 0 && *pp2 ) { *pp3++ = *pp2++; }
3615
        nleft = pp3 - Pointer;
3616
        while ( pp3 < pptop ) *pp3++ = 0;
3617
        AN.InScratch = 0;
3618
        return(nleft);
3619
}
3620

3621
#endif
3622

3623
/*
3624
                 #] SplitMerge : 
3625
                 #[ GarbHand :                                void GarbHand()
3626
*/
3627
/**
3628
 *                Garbage collection that takes place when the small extension is full
3629
 *                and we need to place more terms there.
3630
 *                When this is the case there are many holes in the small buffer and
3631
 *                the whole can be compactified.
3632
 *                The major complication is the buffer for SplitMerge.
3633
 *                There are to options for temporary memory:
3634
 *                1: find some buffer that has enough space (maybe in the large
3635
 *                   buffer).
3636
 *                2: allocate a buffer. Give it back afterwards of course.
3637
 *                If the small extension is properly dimensioned this routine should
3638
 *                be called very rarely. Most of the time it will be called when the
3639
 *                polyfun or polyratfun is active.
3640
 */
3641

3642
void GarbHand(void)
773✔
3643
{
3644
        GETIDENTITY
599✔
3645
        SORTING *S = AT.SS;
772✔
3646
        WORD **Point, *s2, *t, *garbuf, i;
772✔
3647
        LONG k, total = 0;
772✔
3648
        int tobereturned = 0;
772✔
3649
/*
3650
        Compute the size needed. Put it in total.
3651
*/
3652
#ifdef TESTGARB
3653
        MLOCK(ErrorMessageLock);
3654
        MesPrint("in:  S->sFill = %l, S->sTop2 = %l",S->sFill-S->sBuffer,S->sTop2-S->sBuffer);
3655
#endif
3656
        Point = S->sPointer;
772✔
3657
        k = S->sTerms;
772✔
3658
        while ( --k >= 0 ) {
15,756,657✔
3659
                if ( ( s2 = *Point++ ) != 0 ) { total += *s2; }
15,755,885✔
3660
        }
3661
        Point = AN.SplitScratch;
772✔
3662
        k = AN.InScratch;
772✔
3663
        while ( --k >= 0 ) {
772✔
3664
                if ( ( s2 = *Point++ ) != 0 ) { total += *s2; }
×
3665
        }
3666
#ifdef TESTGARB
3667
        MesPrint("total = %l, nterms = %l",total,AN.InScratch);
3668
        MUNLOCK(ErrorMessageLock);
3669
#endif
3670
/*
3671
        Test now whether it fits. If so deal with the problem inside
3672
        the memory at the tail of the large buffer.
3673
*/
3674
        if ( S->lBuffer != 0 && S->lFill + total <= S->lTop ) {
772✔
3675
                garbuf = S->lFill;
3676
        }
3677
        else {
3678
                garbuf = (WORD *)Malloc1(total*sizeof(WORD),"Garbage buffer");
×
3679
                tobereturned = 1;
×
3680
        }
3681
        t = garbuf;
772✔
3682
        Point = S->sPointer;
772✔
3683
        k = S->sTerms;
772✔
3684
        while ( --k >= 0 ) {
15,694,419✔
3685
                if ( *Point ) {
15,693,647✔
3686
                        s2 = *Point++;
5,546,107✔
3687
                        i = *s2;
5,546,107✔
3688
                        NCOPY(t,s2,i);
1,034,386,783✔
3689
                }
3690
                else { Point++; }
10,147,540✔
3691
        }
3692
        Point = AN.SplitScratch;
772✔
3693
        k = AN.InScratch;
772✔
3694
        while ( --k >= 0 ) {
772✔
3695
                if ( *Point ) {
×
3696
                        s2 = *Point++;
×
3697
                        i = *s2;
×
3698
                        NCOPY(t,s2,i);
×
3699
                }
3700
                else Point++;
×
3701
        }
3702
        s2 = S->sBuffer;
772✔
3703
        t = garbuf;
772✔
3704
        Point = S->sPointer;
772✔
3705
        k = S->sTerms;
772✔
3706
        while ( --k >= 0 ) {
15,637,218✔
3707
                if ( *Point ) {
15,636,446✔
3708
                        *Point++ = s2;
5,543,826✔
3709
                        i = *t;
5,543,826✔
3710
                        NCOPY(s2,t,i);
1,030,205,088✔
3711
                }
3712
                else { Point++; }
10,092,620✔
3713
        }
3714
        Point = AN.SplitScratch;
772✔
3715
        k = AN.InScratch;
772✔
3716
        while ( --k >= 0 ) {
772✔
3717
                if ( *Point ) {
×
3718
                        *Point++ = s2;
×
3719
                        i = *t;
×
3720
                        NCOPY(s2,t,i);
×
3721
                }
3722
                else Point++;
×
3723
        }
3724
        S->sFill = s2;
772✔
3725
#ifdef TESTGARB
3726
        MLOCK(ErrorMessageLock);
3727
        MesPrint("out: S->sFill = %l, S->sTop2 = %l",S->sFill-S->sBuffer,S->sTop2-S->sBuffer);
3728
        if ( S->sFill >= S->sTop2 ) {
3729
                MesPrint("We are in deep trouble");
3730
        }
3731
        MUNLOCK(ErrorMessageLock);
3732
#endif
3733
        if ( tobereturned ) M_free(garbuf,"Garbage buffer");
772✔
3734
        return;
772✔
3735
}
3736

3737
/*
3738
                 #] GarbHand : 
3739
                 #[ MergePatches :                        WORD MergePatches(par)
3740
*/
3741
/**
3742
 *        The general merge routine. Can be used for the large buffer
3743
 *        and the file merging. The array S->Patches tells where the patches
3744
 *        start S->pStop tells where they end (has to be computed first).
3745
 *        The end of a 'line to be merged' is indicated by a zero. If
3746
 *        the end is reached without running into a zero or a term
3747
 *        runs over the boundary of a patch it is a file merging operation
3748
 *        and a new piece from the file is read in.
3749
 *
3750
 *        @param par
3751
 *        If par == 0 the sort is for file -> outputfile.
3752
 *        If par == 1 the sort is for large buffer -> sortfile.
3753
 *        If par == 2 the sort is for large buffer -> outputfile.
3754
 *
3755
 */
3756

3757
WORD MergePatches(WORD par)
719✔
3758
{
3759
        GETIDENTITY
480✔
3760
        SORTING *S = AT.SS;
719✔
3761
        WORD **poin, **poin2, ul, k, i, im, *m1;
719✔
3762
        WORD *p, lpat, mpat, level, l1, l2, r1, r2, r3, c;
719✔
3763
        WORD *m2, *m3, r31, r33, ki, *rr;
719✔
3764
        UWORD *coef;
719✔
3765
        POSITION position;
719✔
3766
        FILEHANDLE *fin, *fout;
719✔
3767
        int fhandle;
719✔
3768
/*
3769
        UBYTE *s;
3770
*/
3771
#ifdef WITHZLIB
3772
        POSITION position2;
719✔
3773
        int oldgzipCompress = AR.gzipCompress;
719✔
3774
        if ( par == 2 ) {
719✔
3775
                AR.gzipCompress = 0;
213✔
3776
        }
3777
#endif
3778
        fin = &S->file;
719✔
3779
        fout = &(AR.FoStage4[0]);
719✔
3780
NewMerge:
751✔
3781
        coef = AN.SoScratC;
751✔
3782
        poin = S->poina; poin2 = S->poin2a;
751✔
3783
        rr = AR.CompressPointer;
751✔
3784
        *rr = 0;
751✔
3785
/*
3786
                 #[ Setup :
3787
*/
3788
        if ( par == 1 ) {
751✔
3789
                fout = &(S->file);
458✔
3790
                if ( fout->handle < 0 ) {
458✔
3791
FileMake:
54✔
3792
                        PUTZERO(AN.OldPosOut);
86✔
3793
                        if ( ( fhandle = CreateFile(fout->name) ) < 0 ) {
86✔
3794
                                MLOCK(ErrorMessageLock);
×
3795
                                MesPrint("Cannot create file %s",fout->name);
×
3796
                                MUNLOCK(ErrorMessageLock);
×
3797
                                goto ReturnError;
×
3798
                        }
3799
#ifdef GZIPDEBUG
3800
                        MLOCK(ErrorMessageLock);
3801
                        MesPrint("%w MergePatches created output file %s",fout->name);
3802
                        MUNLOCK(ErrorMessageLock);
3803
#endif
3804
                        fout->handle = fhandle;
86✔
3805
                        PUTZERO(fout->filesize);
86✔
3806
                        PUTZERO(fout->POposition);
86✔
3807
/*
3808
                        Should not be here?
3809
#ifdef WITHZLIB
3810
                        fout->ziobuffer = 0;
3811
#endif
3812
*/
3813
#ifdef ALLLOCK
3814
                        LOCK(fout->pthreadslock);
3815
#endif
3816
                        SeekFile(fout->handle,&(fout->filesize),SEEK_SET);
86✔
3817
#ifdef ALLLOCK
3818
                        UNLOCK(fout->pthreadslock);
3819
#endif
3820
                        S->fPatchN = 0;
86✔
3821
                        PUTZERO(S->fPatches[0]);
86✔
3822
                        fout->POfill = fout->PObuffer;        
86✔
3823
                        PUTZERO(fout->POposition);
86✔
3824
                }
3825
ConMer:
404✔
3826
                StageSort(fout);
578✔
3827
#ifdef WITHZLIB
3828
                if ( S == AT.S0 && AR.NoCompress == 0 && AR.gzipCompress > 0 )
572✔
3829
                        S->fpcompressed[S->fPatchN] = 1;
500✔
3830
                else
3831
                        S->fpcompressed[S->fPatchN] = 0;
72✔
3832
                SetupOutputGZIP(fout);
572✔
3833
#endif
3834
        }
3835
        else if ( par == 0 && S->stage4 > 0 ) {
293✔
3836
/*
3837
                We will have to do our job more than once.
3838
                Input is from S->file and output will go to AR.FoStage4.
3839
                The file corresponding to this last one must be made now.
3840
*/
3841
                AR.Stage4Name ^= 1;
32✔
3842
/*
3843
                s = (UBYTE *)(fout->name); while ( *s ) s++;
3844
                if ( AR.Stage4Name ) s[-1] += 1;
3845
                else                s[-1] -= 1;
3846
*/
3847
                S->iPatches = S->fPatches;
32✔
3848
                S->fPatches = S->inPatches;
32✔
3849
                S->inPatches = S->iPatches;
32✔
3850
                (S->inNum) = S->fPatchN;
32✔
3851
                AN.OldPosIn = AN.OldPosOut;
32✔
3852
#ifdef WITHZLIB
3853
                m1 = S->fpincompressed;
32✔
3854
                S->fpincompressed = S->fpcompressed;
32✔
3855
                S->fpcompressed = m1;
32✔
3856
                for ( i = 0; i < S->inNum; i++ ) {
112✔
3857
                        S->fPatchesStop[i] = S->iPatches[i+1];
80✔
3858
#ifdef GZIPDEBUG
3859
                        MLOCK(ErrorMessageLock);
3860
                        MesPrint("%w fPatchesStop[%d] = %10p",i,&(S->fPatchesStop[i]));
3861
                        MUNLOCK(ErrorMessageLock);
3862
#endif
3863
                }
3864
#endif
3865
                S->stage4 = 0;
32✔
3866
                goto FileMake;
32✔
3867
        }
3868
        else {
3869
#ifdef WITHZLIB
3870
/*
3871
                The next statement is just for now
3872
*/
3873
                AR.gzipCompress = 0;
261✔
3874
#endif
3875
                if ( par == 0 ) {
213✔
3876
                        S->iPatches = S->fPatches;
48✔
3877
                        S->inNum = S->fPatchN;
48✔
3878
#ifdef WITHZLIB
3879
                        m1 = S->fpincompressed;
48✔
3880
                        S->fpincompressed = S->fpcompressed;
48✔
3881
                        S->fpcompressed = m1;
48✔
3882
                        for ( i = 0; i < S->inNum; i++ ) {
178✔
3883
                                S->fPatchesStop[i] = S->fPatches[i+1];
130✔
3884
#ifdef GZIPDEBUG
3885
                                MLOCK(ErrorMessageLock);
3886
                                MesPrint("%w fPatchesStop[%d] = %10p",i,&(S->fPatchesStop[i]));
3887
                                MUNLOCK(ErrorMessageLock);
3888
#endif
3889
                        }
3890
#endif
3891
                }
3892
                fout = AR.outfile;
261✔
3893
        }
3894
        if ( par ) {                                /* Mark end of patches */
833✔
3895
                S->Patches[S->lPatch] = S->lFill;
665✔
3896
                for ( i = 0; i < S->lPatch; i++ ) {
7,885✔
3897
                        S->pStop[i] = S->Patches[i+1]-1;
7,220✔
3898
                    S->Patches[i] = (WORD *)(((UBYTE *)(S->Patches[i])) + AM.MaxTer);
7,220✔
3899
                }
3900
        }
3901
        else {        /* Load the patches */
3902
                S->lPatch = (S->inNum);
168✔
3903
#ifdef WITHMPI
3904
                if ( S->lPatch > 1 || ( (PF.exprtodo <0) && (fout == AR.outfile || fout == AR.hidefile ) ) ) {
3905
#else
3906
                if ( S->lPatch > 1 ) {
168✔
3907
#endif
3908
#ifdef WITHZLIB
3909
                        SetupAllInputGZIP(S);
158✔
3910
#endif
3911
                        p = S->lBuffer;
158✔
3912
                        for ( i = 0; i < S->lPatch; i++ ) {
710✔
3913
                                p = (WORD *)(((UBYTE *)p)+2*AM.MaxTer+COMPINC*sizeof(WORD));
552✔
3914
                                S->Patches[i] = p;
552✔
3915
                                p = (WORD *)(((UBYTE *)p) + fin->POsize);
552✔
3916
                                S->pStop[i] = m2 = p;
552✔
3917
#ifdef WITHZLIB
3918
                                PutIn(fin,&(S->iPatches[i]),S->Patches[i],&m2,i);
552✔
3919
#else
3920
                                ADDPOS(S->iPatches[i],PutIn(fin,&(S->iPatches[i]),S->Patches[i],&m2,i));
3921
#endif
3922
                        }
3923
                }
3924
        }
3925
        if ( fout->handle >= 0 ) {
833✔
3926
                PUTZERO(position);
572✔
3927
#ifdef ALLLOCK
3928
                LOCK(fout->pthreadslock);
3929
#endif
3930
                SeekFile(fout->handle,&position,SEEK_END);
572✔
3931
                ADDPOS(position,((fout->POfill-fout->PObuffer)*sizeof(WORD)));
572✔
3932
#ifdef ALLLOCK
3933
                UNLOCK(fout->pthreadslock);
3934
#endif
3935
        }
3936
        else {
3937
                SETBASEPOSITION(position,(fout->POfill-fout->PObuffer)*sizeof(WORD));
261✔
3938
        }
3939
/*
3940
                 #] Setup : 
3941

3942
        The old code had to be replaced because all output needs to go
3943
        through PutOut. For this we have to go term by term and keep
3944
        track of the compression.
3945
*/
3946
        if ( S->lPatch == 1 ) {        /* Single patch --> direct copy. Very rare. */
833✔
3947
                LONG length;
10✔
3948

3949
                if ( fout->handle < 0 ) if ( Sflush(fout) ) goto PatCall;
10✔
3950
                if ( par ) {                /* Memory to file */
10✔
3951
#ifdef WITHZLIB
3952
/*
3953
                        We fix here the problem that the thing needs to go through PutOut
3954
*/
3955
                        m2 = m1 = *S->Patches; /* The m2 is to keep the compiler from complaining */
×
3956
                        while ( *m1 ) {
×
3957
                                if ( *m1 < 0 ) { /* Need to uncompress */
×
3958
                                        i = -(*m1++); m2 += i; im = *m1+i+1;
×
3959
                                        while ( i > 0 ) { *m1-- = *m2--; i--; }
×
3960
                                        *m1 = im;
×
3961
                                }
3962
#ifdef WITHPTHREADS
3963
                                /* Check here (and in the following) that we are at ground level
3964
                                   (so S == AT.S0) to use PutToMaster. Control can reach here,
3965
                                   with AS.MasterSort, but with S != AT.S0, when the SortBots are
3966
                                   adding PolyRatFun and the sorting of their arguments requires
3967
                                   large buffer patches to be merged. In this case, terms escape
3968
                                   the PolyRatFun argument and end up at ground level, if we use
3969
                                   PutToMaster. */
3970
                                if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
3971
                                        im = PutToMaster(BHEAD m1);
3972
                                }
3973
                                else
3974
#endif
3975
                                if ( ( im = PutOut(BHEAD m1,&position,fout,1) ) < 0 ) goto ReturnError;
×
3976
                                ADDPOS(S->SizeInFile[par],im);
×
3977
                                m2 = m1;
×
3978
                                m1 += *m1;
×
3979
                        }
3980
#ifdef WITHPTHREADS
3981
                        if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
3982
                                PutToMaster(BHEAD 0);
3983
                        }
3984
                        else
3985
#endif
3986
                        if ( FlushOut(&position,fout,1) ) goto ReturnError;
×
3987
                        ADDPOS(S->SizeInFile[par],1);
×
3988
#else
3989
/* old code */
3990
                        length = (LONG)(*S->pStop)-(LONG)(*S->Patches)+sizeof(WORD);
3991
                        if ( WriteFile(fout->handle,(UBYTE *)(*S->Patches),length) != length )
3992
                                goto PatwCall;
3993
                        ADDPOS(position,length);
3994
                        ADDPOS(fout->POposition,length);
3995
                        ADDPOS(fout->filesize,length);
3996
                        ADDPOS(S->SizeInFile[par],length/sizeof(WORD));
3997
#endif
3998
                }
3999
                else {                                /* File to file */
4000
#ifdef WITHZLIB
4001
/*
4002
                        Note: if we change FRONTSIZE we need to make the minimum value
4003
                        of SmallEsize in AllocSort correspondingly larger or smaller.
4004
                        Theoretically we could get close to 2*AM.MaxTer!
4005
*/
4006
                        #define FRONTSIZE (2*AM.MaxTer)
4007
                        WORD *copybuf = (WORD *)(((UBYTE *)(S->sBuffer)) + FRONTSIZE);
10✔
4008
                        WORD *copytop;
10✔
4009
                        SetupAllInputGZIP(S);
10✔
4010
                        m1 = m2 = copybuf;
10✔
4011
                        position2 = S->iPatches[0];
10✔
4012
                        while ( ( length = FillInputGZIP(fin,&position2,
10✔
4013
                                        (UBYTE *)copybuf,
4014
                                        (S->SmallEsize*sizeof(WORD)-FRONTSIZE),0) ) > 0 ) {
10✔
4015
                                copytop = (WORD *)(((UBYTE *)copybuf)+length);
10✔
4016
                                while ( *m1 && ( ( *m1 > 0 && m1+*m1 < copytop ) ||
81,930✔
4017
                                ( *m1 < 0 && ( m1+1 < copytop ) && ( m1+m1[1]+1 < copytop ) ) ) )
81,910✔
4018
/*
4019
        22-jun-2013 JV  Extremely nasty bug that has been around for a while.
4020
                        What if the end is in the remaining part? We will loose terms!
4021
                                while ( *m1 && ( (WORD *)(((UBYTE *)(m1)) + AM.MaxTer ) < S->sTop2 ) )
4022
*/
4023
                                {
4024
                                        if ( *m1 < 0 ) { /* Need to uncompress */
81,920✔
4025
                                                i = -(*m1++); m2 += i; im = *m1+i+1;
81,910✔
4026
                                                while ( i > 0 ) { *m1-- = *m2--; i--; }
409,550✔
4027
                                                *m1 = im;
81,910✔
4028
                                        }
4029
#ifdef WITHPTHREADS
4030
                                        if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
65,536✔
4031
                                                im = PutToMaster(BHEAD m1);
4032
                                        }
4033
                                        else
4034
#endif
4035
                                        if ( ( im = PutOut(BHEAD m1,&position,fout,1) ) < 0 ) goto ReturnError;
81,920✔
4036
                                        ADDPOS(S->SizeInFile[par],im);
81,920✔
4037
                                        m2 = m1;
81,920✔
4038
                                        m1 += *m1;
81,920✔
4039
                                }
4040
                                if ( m1 < copytop && *m1 == 0 ) break;
10✔
4041
/*
4042
                                Now move the remaining part 'back'
4043
*/
4044
                            m3 = copybuf;
4045
                                m1 = copytop;
4046
                                while ( m1 > m2 ) *--m3 = *--m1;
×
4047
                                m2 = m3;
×
4048
                                m1 = m2 + *m2;
×
4049
                        }
4050
                        if ( length < 0 ) {
10✔
4051
                                MLOCK(ErrorMessageLock);
×
4052
                                MesPrint("Readerror");
×
4053
                                goto PatCall2;
×
4054
                        }
4055
#ifdef WITHPTHREADS
4056
                        if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
8✔
4057
                                PutToMaster(BHEAD 0);
4058
                        }
4059
                        else
4060
#endif
4061
                        if ( FlushOut(&position,fout,1) ) goto ReturnError;
10✔
4062
                        ADDPOS(S->SizeInFile[par],1);
10✔
4063
#else
4064
/* old code */
4065
                        SeekFile(fin->handle,&(S->iPatches[0]),SEEK_SET); /* needed for stage4 */
4066
                        while ( ( length = ReadFile(fin->handle,
4067
                                        (UBYTE *)(S->sBuffer),S->SmallEsize*sizeof(WORD)) ) > 0 ) {
4068
                                if ( WriteFile(fout->handle,(UBYTE *)(S->sBuffer),length) != length )
4069
                                        goto PatwCall;
4070
                                ADDPOS(position,length);
4071
                                ADDPOS(fout->POposition,length);
4072
                                ADDPOS(fout->filesize,length);
4073
                                ADDPOS(S->SizeInFile[par],length/sizeof(WORD));
4074
                        }
4075
                        if ( length < 0 ) {
4076
                                MLOCK(ErrorMessageLock);
4077
                                MesPrint("Readerror");
4078
                                goto PatCall2;
4079
                        }
4080
#endif
4081
                }
4082
                goto EndOfAll;
10✔
4083
        }
4084
        else if ( S->lPatch > 0 ) {
823✔
4085

4086
                /* More than one patch. Construct the tree. */
4087

4088
                lpat = 1;
4089
                do { lpat *= 2; } while ( lpat < S->lPatch );
2,330✔
4090
                mpat = ( lpat >> 1 ) - 1;
823✔
4091
                k = lpat - S->lPatch;
823✔
4092

4093
                /* k is the number of empty places in the tree. they will
4094
                   be at the even positions from 2 to 2*k */
4095

4096
                for ( i = 1; i < lpat; i++ ) {
8,232✔
4097
                        S->tree[i] = -1;
7,409✔
4098
                }
4099
                for ( i = 1; i <= k; i++ ) {
1,283✔
4100
                        im = ( i * 2 ) - 1;
460✔
4101
                        poin[im] = S->Patches[i-1];
460✔
4102
                        poin2[im] = poin[im] + *(poin[im]);
460✔
4103
                        S->used[i] = im;
460✔
4104
                        S->ktoi[im] = i-1;
460✔
4105
                        S->tree[mpat+i] = 0;
460✔
4106
                        poin[im-1] = poin2[im-1] = 0;
460✔
4107
                }
4108
                for ( i = (k*2)+1; i <= lpat; i++ ) {
8,135✔
4109
                        S->used[i-k] = i;
7,312✔
4110
                        S->ktoi[i] = i-k-1;
7,312✔
4111
                        poin[i] = S->Patches[i-k-1];
7,312✔
4112
                        poin2[i] = poin[i] + *(poin[i]);
7,312✔
4113
                }
4114
/*
4115
                the array poin tells the position of the i-th element of the S->tree
4116
                'S->used' is a stack with the S->tree elements that need to be entered
4117
                into the S->tree. at the beginning this is S->lPatch. during the
4118
                sort there will be only very few elements.
4119
                poin2 is the next value of poin. it has to be determined
4120
                before the comparisons as the position or the size of the
4121
                term indicated by poin may change.
4122
                S->ktoi translates a S->tree element back to its stream number.
4123

4124
                start the sort
4125
*/
4126
                level = S->lPatch;
823✔
4127

4128
                /* introduce one term */
4129
OneTerm:
16,754,551✔
4130
                k = S->used[level];
16,755,374✔
4131
                i = k + lpat - 1;
16,755,374✔
4132
                if ( !*(poin[k]) ) {
16,755,374✔
4133
                        do { if ( !( i >>= 1 ) ) goto EndOfMerge; } while ( !S->tree[i] );
15,181✔
4134
                        if ( S->tree[i] == -1 ) {
6,949✔
4135
                                S->tree[i] = 0;
45✔
4136
                                level--;
45✔
4137
                                goto OneTerm;
45✔
4138
                        }
4139
                        k = S->tree[i];
6,904✔
4140
                        S->used[level] = k;
6,904✔
4141
                        S->tree[i] = 0;
6,904✔
4142
                }
4143
/*
4144
                move terms down the tree
4145
*/
4146
                while ( i >>= 1 ) {
42,907,477✔
4147
                        if ( S->tree[i] > 0 ) {
26,458,252✔
4148
                                if ( ( c = CompareTerms(BHEAD poin[S->tree[i]],poin[k],(WORD)0) ) > 0 ) {
16,385,796✔
4149
/*
4150
                                        S->tree[i] is the smaller. Exchange and go on.
4151
*/
4152
                                        S->used[level] = S->tree[i];
52,342✔
4153
                                        S->tree[i] = k;
52,342✔
4154
                                        k = S->used[level];
52,342✔
4155
                                }
4156
                                else if ( !c ) {        /* Terms are equal */
16,333,454✔
4157
                                        S->TermsLeft--;
163,311✔
4158
/*
4159
                                                Here the terms are equal and their coefficients
4160
                                                have to be added.
4161
*/
4162
                                        l1 = *( m1 = poin[S->tree[i]] );
163,311✔
4163
                                        l2 = *( m2 = poin[k] );
163,311✔
4164
                                        if ( S->PolyWise ) {  /* Here we work with PolyFun */
163,311✔
4165
                                                WORD *tt1, *w;
×
4166
                                                tt1 = m1;
×
4167
                                                m1 += S->PolyWise;
×
4168
                                                m2 += S->PolyWise;
×
4169
                                                if ( S->PolyFlag == 2 ) {
×
4170
                                                        w = poly_ratfun_add(BHEAD m1,m2);
×
4171
                                                        if ( *tt1 + w[1] - m1[1] > AM.MaxTer/((LONG)sizeof(WORD)) ) {
×
4172
                                                                MLOCK(ErrorMessageLock);
×
4173
                                                                MesPrint("Term too complex in PolyRatFun addition. MaxTermSize of %10l is too small",AM.MaxTer);
×
4174
                                                                MUNLOCK(ErrorMessageLock);
×
4175
                                                                Terminate(-1);
×
4176
                                                        }
4177
                                                        AT.WorkPointer = w;
×
4178
                                                }
4179
                                                else {
4180
                                                        w = AT.WorkPointer;
×
4181
                                                        if ( w + m1[1] + m2[1] > AT.WorkTop ) {
×
4182
                                                                MLOCK(ErrorMessageLock);
×
4183
                                                                MesPrint("A WorkSpace of %10l is too small",AM.WorkSize);
×
4184
                                                                MUNLOCK(ErrorMessageLock);
×
4185
                                                                Terminate(-1);
×
4186
                                                        }
4187
                                                        AddArgs(BHEAD m1,m2,w);
×
4188
                                                }
4189
                                                r1 = w[1];
×
4190
                                                if ( r1 <= FUNHEAD
×
4191
                                                        || ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) )
×
4192
                                                                 { goto cancelled; }
×
4193
                                                if ( r1 == m1[1] ) {
×
4194
                                                        NCOPY(m1,w,r1);
×
4195
                                                }
4196
                                                else if ( r1 < m1[1] ) {
×
4197
                                                        r2 = m1[1] - r1;
×
4198
                                                        m2 = w + r1;
×
4199
                                                        m1 += m1[1];
×
4200
                                                        while ( --r1 >= 0 ) *--m1 = *--m2;
×
4201
                                                        m2 = m1 - r2;
×
4202
                                                        r1 = S->PolyWise;
×
4203
                                                        while ( --r1 >= 0 ) *--m1 = *--m2;
×
4204
                                                        *m1 -= r2;
×
4205
                                                        poin[S->tree[i]] = m1;
×
4206
                                                }
4207
                                                else {
4208
                                                        r2 = r1 - m1[1];
×
4209
                                                        m2 = tt1 - r2;
×
4210
                                                        r1 = S->PolyWise;
×
4211
                                                        m1 = tt1;
×
4212
                                                        *m1 += r2;
×
4213
                                                        poin[S->tree[i]] = m2;
×
4214
                                                        NCOPY(m2,m1,r1);
×
4215
                                                        r1 = w[1];
×
4216
                                                        NCOPY(m2,w,r1);
×
4217
                                                }
4218
                                        }
4219
#ifdef WITHFLOAT
4220
                                        else if ( AT.SortFloatMode ) {
163,311✔
4221
                                                WORD *term1, *term2;
×
4222
                                                term1 = poin[S->tree[i]];
×
4223
                                                term2 = poin[k];
×
4224
                                                if ( MergeWithFloat(BHEAD &term1,&term2) == 0 )
×
4225
                                                        goto cancelled;
×
4226
                                                poin[S->tree[i]] = term1;
×
4227
                                        }
4228
#endif
4229
                                        else {
4230
                                          r1 = *( m1 += l1 - 1 );
163,311✔
4231
                                          m1 -= ABS(r1) - 1;
163,311✔
4232
                                          r1 = ( ( r1 > 0 ) ? (r1-1) : (r1+1) ) >> 1;
163,311✔
4233
                                          r2 = *( m2 += l2 - 1 );
163,311✔
4234
                                          m2 -= ABS(r2) - 1;
163,311✔
4235
                                          r2 = ( ( r2 > 0 ) ? (r2-1) : (r2+1) ) >> 1;
163,311✔
4236

4237
                                          if ( AddRat(BHEAD (UWORD *)m1,r1,(UWORD *)m2,r2,coef,&r3) ) {
163,311✔
4238
                                                MLOCK(ErrorMessageLock);
×
4239
                                                MesCall("MergePatches");
×
4240
                                                MUNLOCK(ErrorMessageLock);
×
4241
                                                SETERROR(-1)
×
4242
                                          }
4243

4244
                                          if ( AN.ncmod != 0 ) {
163,311✔
4245
                                                if ( ( AC.modmode & POSNEG ) != 0 ) {
×
4246
                                                        NormalModulus(coef,&r3);
×
4247
                                                }
4248
                                                else if ( BigLong(coef,r3,(UWORD *)AC.cmod,ABS(AN.ncmod)) >= 0 ) {
×
4249
                                                        WORD ii;
×
4250
                                                        SubPLon(coef,r3,(UWORD *)AC.cmod,ABS(AN.ncmod),coef,&r3);
×
4251
                                                        coef[r3] = 1;
×
4252
                                                        for ( ii = 1; ii < r3; ii++ ) coef[r3+ii] = 0;
×
4253
                                                }
4254
                                          }
4255
                                          r3 *= 2;
163,311✔
4256
                                          r33 = ( r3 > 0 ) ? ( r3 + 1 ) : ( r3 - 1 );
163,311✔
4257
                                          if ( r3 < 0 ) r3 = -r3;
163,311✔
4258
                                          if ( r1 < 0 ) r1 = -r1;
163,311✔
4259
                                          r1 *= 2;
163,311✔
4260
                                          r31 = r3 - r1;
163,311✔
4261
                                          if ( !r3 ) {                /* Terms cancel */
163,311✔
4262
cancelled:
135,066✔
4263
                                                ul = S->used[level] = S->tree[i];
135,066✔
4264
                                                S->tree[i] = -1;
135,066✔
4265
/*
4266
                                                We skip to the next term in stream ul
4267
*/
4268
                                                im = *poin2[ul];
135,066✔
4269
                                                if ( im < 0 ) {
135,066✔
4270
                                                        r1 = poin2[ul][1] - im + 1;
134,873✔
4271
                                                        m1 = poin2[ul] + 2;
134,873✔
4272
                                                        m2 = poin[ul] - im + 1;
134,873✔
4273
                                                        while ( ++im <= 0 ) *--m1 = *--m2;
674,365✔
4274
                                                        *--m1 = r1;
134,873✔
4275
                                                        poin2[ul] = m1;
134,873✔
4276
                                                        im = r1;
134,873✔
4277
                                                }
4278
                                                poin[ul] = poin2[ul];
135,066✔
4279
                                                ki = S->ktoi[ul];
135,066✔
4280
                                                if ( !par && (poin[ul] + im + COMPINC) >= S->pStop[ki]
135,066✔
4281
                                                && im > 0 ) {
×
4282
#ifdef WITHZLIB
4283
                                                        PutIn(fin,&(S->iPatches[ki]),S->Patches[ki],&(poin[ul]),ki);
×
4284
#else
4285
                                                        ADDPOS(S->iPatches[ki],PutIn(fin,&(S->iPatches[ki]),
4286
                                                        S->Patches[ki],&(poin[ul]),ki));
4287
#endif
4288
                                                        poin2[ul] = poin[ul] + im;
×
4289
                                                }
4290
                                                else {
4291
                                                        poin2[ul] += im;
135,066✔
4292
                                                }
4293
                                                S->used[++level] = k;
135,066✔
4294
                                                S->TermsLeft--;
135,066✔
4295
                                          }
4296
                                          else if ( !r31 ) {                /* copy coef into term1 */
28,245✔
4297
                                                goto CopCof2;
28,229✔
4298
                                          }
4299
                                          else if ( r31 < 0 ) {                /* copy coef into term1
16✔
4300
                                                                                        and adjust the length of term1 */
4301
                                                goto CopCoef;
×
4302
                                          }
4303
                                          else {
4304
/*
4305
                                                        this is the dreaded calamity.
4306
                                                        is there enough space?
4307
*/
4308
                                                if( (poin[S->tree[i]]+l1+r31) >= poin2[S->tree[i]] ) {
16✔
4309
/*
4310
                                                                no space! now the special trick for which
4311
                                                                we left 2*maxlng spaces open at the beginning
4312
                                                                of each patch.
4313
*/
4314
                                                        if ( (l1 + r31) > AM.MaxTer/((LONG)sizeof(WORD)) ) {
16✔
4315
                                                                MLOCK(ErrorMessageLock);
×
4316
                                                                MesPrint("Coefficient overflow during sort");
×
4317
                                                                MUNLOCK(ErrorMessageLock);
×
4318
                                                                goto ReturnError;
×
4319
                                                        }
4320
                                                        m2 = poin[S->tree[i]];
16✔
4321
                                                        m3 = ( poin[S->tree[i]] -= r31 );
16✔
4322
                                                        do { *m3++ = *m2++; } while ( m2 < m1 );
16✔
4323
                                                        m1 = m3;
4324
                                                }
4325
CopCoef:
×
4326
                                                *(poin[S->tree[i]]) += r31;
16✔
4327
CopCof2:
28,245✔
4328
                                                m2 = (WORD *)coef; im = r3;
28,245✔
4329
                                                NCOPY(m1,m2,im);
84,787✔
4330
                                                *m1 = r33;
28,245✔
4331
                                          }
4332
                                        }
4333
/*
4334
                                        Now skip to the next term in stream k.
4335
*/
4336
NextTerm:
16,612,536✔
4337
                                        im = poin2[k][0];
16,612,536✔
4338
                                        if ( im < 0 ) {
16,612,536✔
4339
                                                r1 = poin2[k][1] - im + 1;
3,710,430✔
4340
                                                m1 = poin2[k] + 2;
3,710,430✔
4341
                                                m2 = poin[k] - im + 1;
3,710,430✔
4342
                                                while ( ++im <= 0 ) *--m1 = *--m2;
18,523,832✔
4343
                                                *--m1 = r1;
3,710,430✔
4344
                                                poin2[k] = m1;
3,710,430✔
4345
                                                im = r1;
3,710,430✔
4346
                                        }
4347
                                        poin[k] = poin2[k];
16,612,536✔
4348
                                        ki = S->ktoi[k];
16,612,536✔
4349
                                        if ( !par && ( (poin[k] + im + COMPINC) >= S->pStop[ki] )
16,612,536✔
4350
                                        && im > 0 ) {
46✔
4351
#ifdef WITHZLIB
4352
                                                PutIn(fin,&(S->iPatches[ki]),S->Patches[ki],&(poin[k]),ki);
46✔
4353
#else
4354
                                                ADDPOS(S->iPatches[ki],PutIn(fin,&(S->iPatches[ki]),
4355
                                                S->Patches[ki],&(poin[k]),ki));
4356
#endif
4357
                                                poin2[k] = poin[k] + im;
46✔
4358
                                        }
4359
                                        else {
4360
                                                poin2[k] += im;
16,612,490✔
4361
                                        }
4362
                                        goto OneTerm;
16,612,536✔
4363
                                }
4364
                        }
4365
                        else if ( S->tree[i] < 0 ) {
10,072,456✔
4366
                                S->tree[i] = k;
141,970✔
4367
                                level--;
141,970✔
4368
                                goto OneTerm;
141,970✔
4369
                        }
4370
                }
4371
/*
4372
                        found the smallest in the set. indicated by k.
4373
                        write to its destination.
4374
*/
4375
#ifdef WITHPTHREADS
4376
                if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
10,351,830✔
4377
                        im = PutToMaster(BHEAD poin[k]);
8,689,028✔
4378
                }
4379
                else
4380
#endif
4381
                if ( ( im = PutOut(BHEAD poin[k],&position,fout,1) ) < 0 ) {
7,760,197✔
4382
                        MLOCK(ErrorMessageLock);
×
4383
                        MesPrint("Called from MergePatches with k = %d (stream %d)",k,S->ktoi[k]);
×
4384
                        MUNLOCK(ErrorMessageLock);
×
4385
                        goto ReturnError;
×
4386
                }
4387
                ADDPOS(S->SizeInFile[par],im);
16,449,225✔
4388
                goto NextTerm;
16,449,225✔
4389
        }
4390
        else {
4391
                goto NormalReturn;
×
4392
        }
4393
EndOfMerge:
823✔
4394
#ifdef WITHPTHREADS
4395
                if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
548✔
4396
                        PutToMaster(BHEAD 0);
44✔
4397
                }
4398
                else
4399
#endif
4400
        if ( FlushOut(&position,fout,1) ) goto ReturnError;
779✔
4401
        ADDPOS(S->SizeInFile[par],1);
823✔
4402
EndOfAll:
833✔
4403
        if ( par == 1 ) {        /* Set the fpatch pointers */
833✔
4404
#ifdef WITHZLIB
4405
                SeekFile(fout->handle,&position,SEEK_CUR);
452✔
4406
#endif
4407
                (S->fPatchN)++;
452✔
4408
                S->fPatches[S->fPatchN] = position;
452✔
4409
        }
4410
        if ( par == 0 && fout != AR.outfile ) {
833✔
4411
/*
4412
                        Output went to sortfile. We have two possibilities:
4413
                        1:        We are not finished with the current in-out cycle
4414
                                In that case we should pop to the next set of patches
4415
                        2:        We finished a cycle and should clean up the in file
4416
                                Then we restart the sort.
4417
*/
4418
                (S->fPatchN)++;
120✔
4419
                S->fPatches[S->fPatchN] = position;
120✔
4420
                if ( ISNOTZEROPOS(AN.OldPosIn) ) {                /* We are not done */
120✔
4421

4422
                        SeekFile(fin->handle,&(AN.OldPosIn),SEEK_SET);
88✔
4423
/*
4424
                        We don't need extra provisions for the zlib compression here.
4425
                        If part of an expression has been sorted, the whole has been so.
4426
                        This means that S->fpincompressed[] will remain the same
4427
*/
4428
                        if ( (ULONG)ReadFile(fin->handle,(UBYTE *)(&(S->inNum)),(LONG)sizeof(WORD)) !=
88✔
4429
                                sizeof(WORD)
4430
                          || (ULONG)ReadFile(fin->handle,(UBYTE *)(&AN.OldPosIn),(LONG)sizeof(POSITION)) !=
88✔
4431
                                sizeof(POSITION)
4432
                          || (ULONG)ReadFile(fin->handle,(UBYTE *)S->iPatches,(LONG)((S->inNum)+1)
176✔
4433
                                        *sizeof(POSITION)) != ((S->inNum)+1)*sizeof(POSITION) ) {
88✔
4434
                                MLOCK(ErrorMessageLock);
×
4435
                                MesPrint("Read error fourth stage sorting");
×
4436
                                MUNLOCK(ErrorMessageLock);
×
4437
                                goto ReturnError;
×
4438
                        }
4439
                        *rr = 0;
88✔
4440
#ifdef WITHZLIB
4441
                        for ( i = 0; i < S->inNum; i++ ) {
440✔
4442
                                S->fPatchesStop[i] = S->iPatches[i+1];
352✔
4443
#ifdef GZIPDEBUG
4444
                                MLOCK(ErrorMessageLock);
4445
                                MesPrint("%w fPatchesStop[%d] = %10p",i,&(S->fPatchesStop[i]));
4446
                                MUNLOCK(ErrorMessageLock);
4447
#endif
4448
                        }
4449
#endif
4450
                        goto ConMer;
88✔
4451
                }
4452
                else {
4453
/*
4454
                        if ( fin == &(AR.FoStage4[0]) ) {
4455
                                s = (UBYTE *)(fin->name); while ( *s ) s++;
4456
                                if ( AR.Stage4Name == 1 ) s[-1] -= 1;
4457
                                else                      s[-1] += 1;
4458
                        }
4459
*/
4460
/*                        TruncateFile(fin->handle); */
4461
                        UpdateMaxSize();
32✔
4462
#ifdef WITHZLIB
4463
                        ClearSortGZIP(fin);
32✔
4464
#endif
4465
                        CloseFile(fin->handle);
32✔
4466
                        remove(fin->name);                /* Gives diskspace free again. */
32✔
4467
#ifdef GZIPDEBUG
4468
                        MLOCK(ErrorMessageLock);
4469
                        MesPrint("%w MergePatches removed in file %s",fin->name);
4470
                        MUNLOCK(ErrorMessageLock);
4471
#endif
4472
/*
4473
                        if ( fin == &(AR.FoStage4[0]) ) {
4474
                                s = (UBYTE *)(fin->name); while ( *s ) s++;
4475
                                if ( AR.Stage4Name == 1 ) s[-1] += 1;
4476
                                else                      s[-1] -= 1;
4477
                        }
4478
*/
4479
                        fin->handle = -1;
32✔
4480
                        { FILEHANDLE *ff = fin; fin = fout; fout = ff; }
32✔
4481
                        PUTZERO(S->SizeInFile[0]);
32✔
4482
                        goto NewMerge;
32✔
4483
                }
4484
        }
4485
        if ( par == 0 ) {
713✔
4486
/*                TruncateFile(fin->handle); */
4487
                UpdateMaxSize();
48✔
4488
#ifdef WITHZLIB
4489
                ClearSortGZIP(fin);
48✔
4490
#endif
4491
                CloseFile(fin->handle);
48✔
4492
                remove(fin->name);
48✔
4493
                fin->handle = -1;
48✔
4494
#ifdef GZIPDEBUG
4495
                MLOCK(ErrorMessageLock);
4496
                MesPrint("%w MergePatches removed in file %s",fin->name);
4497
                MUNLOCK(ErrorMessageLock);
4498
#endif
4499
        }
4500
NormalReturn:
665✔
4501
#ifdef WITHZLIB
4502
        AR.gzipCompress = oldgzipCompress;
713✔
4503
#endif
4504
        return(0);
713✔
4505
ReturnError:
×
4506
#ifdef WITHZLIB
4507
        AR.gzipCompress = oldgzipCompress;
×
4508
#endif
4509
        return(-1);
×
4510
#ifndef WITHZLIB
4511
PatwCall:
4512
        MLOCK(ErrorMessageLock);
4513
        MesPrint("Error while writing to file.");
4514
        goto PatCall2;
4515
#endif
4516
PatCall:;
×
4517
        MLOCK(ErrorMessageLock);
×
4518
PatCall2:;
×
4519
        MesCall("MergePatches");
×
4520
        MUNLOCK(ErrorMessageLock);
×
4521
#ifdef WITHZLIB
4522
        AR.gzipCompress = oldgzipCompress;
×
4523
#endif
4524
        SETERROR(-1)
×
4525
}
4526

4527
/*
4528
                 #] MergePatches : 
4529
                 #[ StoreTerm :                                WORD StoreTerm(term)
4530
*/
4531
/**
4532
 *        The central routine to accept terms, store them and keep things
4533
 *        at least partially sorted. A call to EndSort will then complete
4534
 *        storing and sorting.
4535
 *
4536
 *        @param term The term to be stored
4537
 *        @return  Regular return conventions (OK -> 0)
4538
 */
4539

4540
WORD StoreTerm(PHEAD WORD *term)
56,049,320✔
4541
{
4542
        GETBIDENTITY
4543
        SORTING *S = AT.SS;
56,049,320✔
4544
        WORD **ss, *lfill, j, *t;
56,049,320✔
4545
        POSITION pp;
56,049,320✔
4546
        LONG lSpace, sSpace, RetCode, over, tover;
56,049,320✔
4547

4548
        if ( ( ( AP.PreDebug & DUMPTOSORT ) == DUMPTOSORT ) && AR.sLevel == 0 ) {
56,049,320✔
4549
#ifdef WITHPTHREADS
4550
                snprintf((char *)(THRbuf),100,"StoreTerm(%d)",AT.identity);
4551
                PrintTerm(term,(char *)(THRbuf));
4552
#else
4553
                PrintTerm(term,"StoreTerm");
4554
#endif
4555
        }
4556
        if ( AM.exitflag && AR.sLevel == 0 ) return(0);
56,049,320✔
4557
        S->sFill = *(S->PoinFill);
56,049,320✔
4558
        if ( S->sTerms >= S->TermsInSmall || ( S->sFill + *term ) >= S->sTop ) {
56,049,320✔
4559
/*
4560
        The small buffer is full. It has to be sorted and written.
4561
*/
4562
                tover = over = S->sTerms;
7,027✔
4563
                ss = S->sPointer;
7,027✔
4564
                ss[over] = 0;
7,027✔
4565
#ifdef SPLITTIME
4566
                PrintTime((UBYTE *)"Before SplitMerge");
4567
#endif
4568
                ss[SplitMerge(BHEAD ss,over)] = 0;
7,027✔
4569
#ifdef SPLITTIME
4570
                PrintTime((UBYTE *)"After SplitMerge");
4571
#endif
4572
                sSpace = 0;
7,027✔
4573
                if ( over > 0 ) {
7,027✔
4574
                        sSpace = ComPress(ss,&RetCode);
7,027✔
4575
                        S->TermsLeft -= over - RetCode;
7,027✔
4576
                }
4577
                sSpace++;
7,027✔
4578

4579
                lSpace = sSpace + (S->lFill - S->lBuffer)
7,027✔
4580
                                 - (AM.MaxTer/sizeof(WORD))*((LONG)S->lPatch);
7,027✔
4581
                SETBASEPOSITION(pp,lSpace);
7,027✔
4582
                MULPOS(pp,sizeof(WORD));
7,027✔
4583
                if ( S->file.handle >= 0 ) {
7,027✔
4584
                        ADD2POS(pp,S->fPatches[S->fPatchN]);
5,731✔
4585
                }
4586
                if ( S == AT.S0 ) {        /* Only statistics at ground level */
7,027✔
4587
                        WriteStats(&pp,STATSSPLITMERGE,CHECKLOGTYPE);
6,064✔
4588
                }
4589
                if ( ( S->lPatch >= S->MaxPatches ) ||
7,027✔
4590
                        ( ( (WORD *)(((UBYTE *)(S->lFill + sSpace)) + 2*AM.MaxTer ) ) >= S->lTop ) ) {
6,619✔
4591
/*
4592
                        The large buffer is too full. Merge and write it
4593
*/
4594
                        if ( MergePatches(1) ) goto StoreCall;
410✔
4595
/*
4596
                        pp = S->SizeInFile[1];
4597
                        ADDPOS(pp,sSpace);
4598
                        MULPOS(pp,sizeof(WORD));
4599
*/
4600
                        SETBASEPOSITION(pp,sSpace);
404✔
4601
                        MULPOS(pp,sizeof(WORD));
404✔
4602
                        ADD2POS(pp,S->fPatches[S->fPatchN]);
404✔
4603

4604
                        if ( S == AT.S0 ) {        /* Only statistics at ground level */
404✔
4605
                                WriteStats(&pp,STATSMERGETOFILE,CHECKLOGTYPE);
344✔
4606
                        }
4607
                        S->lPatch = 0;
404✔
4608
                        S->lFill = S->lBuffer;
404✔
4609
                }
4610
                S->Patches[S->lPatch++] = S->lFill;
7,021✔
4611
            lfill = (WORD *)(((UBYTE *)(S->lFill)) + AM.MaxTer);
7,021✔
4612
                if ( tover > 0 ) {
7,021✔
4613
                        ss = S->sPointer;
7,021✔
4614
                        while ( ( t = *ss++ ) != 0 ) {
12,321,932✔
4615
                                j = *t;
12,314,911✔
4616
                                if ( j < 0 ) j = t[1] + 2;
12,314,911✔
4617
                                while ( --j >= 0 ){
255,477,468✔
4618
                                  *lfill++ = *t++;
243,162,557✔
4619
                                }
4620
                        }
4621
                }
4622
                *lfill++ = 0;
7,021✔
4623
                S->lFill = lfill;
7,021✔
4624
                S->sTerms = 0;
7,021✔
4625
                S->PoinFill = S->sPointer;
7,021✔
4626
                *(S->PoinFill) = S->sFill = S->sBuffer;
7,021✔
4627
        }
4628
        j = *term;
56,049,314✔
4629
        while ( --j >= 0 ) *S->sFill++ = *term++;
821,624,942✔
4630
        S->sTerms++;
56,049,314✔
4631
        S->GenTerms++;
56,049,314✔
4632
        S->TermsLeft++;
56,049,314✔
4633
        *++S->PoinFill = S->sFill;
56,049,314✔
4634

4635
        return(0);
56,049,314✔
4636

4637
StoreCall:
×
4638
        MLOCK(ErrorMessageLock);
×
4639
        MesCall("StoreTerm");
×
4640
        MUNLOCK(ErrorMessageLock);
×
4641
        SETERROR(-1)
×
4642
}
4643

4644
/*
4645
                 #] StoreTerm : 
4646
                 #[ StageSort :                                void StageSort(FILEHANDLE *fout)
4647
*/
4648
/**
4649
 *                Prepares a stage 4 or higher sort.
4650
 *                Stage 4 sorts occur when the sort file contains more patches than
4651
 *                can be merged in one pass.
4652
 */
4653

4654
void StageSort(FILEHANDLE *fout)
592✔
4655
{
4656
        GETIDENTITY
390✔
4657
        SORTING *S = AT.SS;
592✔
4658
        if ( S->fPatchN >= S->MaxFpatches ) {
592✔
4659
                POSITION position;
94✔
4660
                if ( S != AT.S0 ) {
94✔
4661
/*
4662
                        There are no proper provisions for stage 4 or higher sorts
4663
                        for function arguments and $ variables. The reason:
4664
                        The current code maps out the patches, based on the size of
4665
                        the buffers in the FoStage4 structs, while they are used
4666
                        inside the S->file struct that may have far smaller buffers.
4667
                        By itself that might still be repairable, but it goes completely
4668
                        wrong when during the sort polyRatFuns have to be added and they
4669
                        would go into stage4 (very rare but possible).
4670
                        The only really correct solution would be to put FoStage4 structs
4671
                        in all sort levels. Messy. (JV 8-oct-2018).
4672
*/
4673
                        MLOCK(ErrorMessageLock);
6✔
4674
                        MesPrint("Currently Stage 4 sorts are not allowed for function arguments or $ variables.");
6✔
4675
                        MesPrint("Please increase correspondingsorting parameters (sub-) in the setup.");
6✔
4676
                        MUNLOCK(ErrorMessageLock);
6✔
4677
                        Terminate(-1);
6✔
4678
                }
4679
                PUTZERO(position);
88✔
4680
                MLOCK(ErrorMessageLock);
88✔
4681
#ifdef WITHPTHREADS
4682
                MesPrint("StageSort in thread %d",identity);
56✔
4683
#elif defined(WITHMPI)
4684
                MesPrint("StageSort in process %d",PF.me);
4685
#else
4686
                MesPrint("StageSort");
32✔
4687
#endif
4688
                MUNLOCK(ErrorMessageLock);
88✔
4689
                SeekFile(fout->handle,&position,SEEK_END);
88✔
4690
/*
4691
                No extra compression data has to be written.
4692
                S->fpincompressed should remain valid.
4693
*/
4694
                if ( (ULONG)WriteFile(fout->handle,(UBYTE *)(&(S->fPatchN)),(LONG)sizeof(WORD)) !=
88✔
4695
                        sizeof(WORD)
4696
                  || (ULONG)WriteFile(fout->handle,(UBYTE *)(&(AN.OldPosOut)),(LONG)sizeof(POSITION)) !=
88✔
4697
                        sizeof(POSITION)
4698
                  || (ULONG)WriteFile(fout->handle,(UBYTE *)(S->fPatches),(LONG)(S->fPatchN+1)
176✔
4699
                                        *sizeof(POSITION)) != (S->fPatchN+1)*sizeof(POSITION) ) {
88✔
4700
                        MLOCK(ErrorMessageLock);
×
4701
                        MesPrint("Write error while staging sort. Disk full?");
×
4702
                        MUNLOCK(ErrorMessageLock);
×
4703
                        Terminate(-1);
×
4704
                }
4705
                AN.OldPosOut = position;
88✔
4706
                fout->filesize = position;
88✔
4707
                ADDPOS(fout->filesize,(S->fPatchN+2)*sizeof(POSITION) + sizeof(WORD));
88✔
4708
                fout->POposition = fout->filesize;
88✔
4709
                S->fPatches[0] = fout->filesize;
88✔
4710
                S->fPatchN = 0;
88✔
4711

4712
                if ( AR.FoStage4[0].PObuffer == 0 ) {
88✔
4713
                        AR.FoStage4[0].PObuffer = (WORD *)Malloc1(AR.FoStage4[0].POsize*sizeof(WORD)
14✔
4714
                                                                                                ,"Stage 4 buffer");
4715
                        AR.FoStage4[0].POfill   = AR.FoStage4[0].PObuffer;
14✔
4716
                        AR.FoStage4[0].POstop   = AR.FoStage4[0].PObuffer
14✔
4717
                                                 + AR.FoStage4[0].POsize/sizeof(WORD);
14✔
4718
#ifdef WITHPTHREADS
4719
                        AR.FoStage4[0].pthreadslock = dummylock;
12✔
4720
#endif
4721
                }
4722
                if ( AR.FoStage4[1].PObuffer == 0 ) {
88✔
4723
                        AR.FoStage4[1].PObuffer = (WORD *)Malloc1(AR.FoStage4[1].POsize*sizeof(WORD)
14✔
4724
                                                                                                ,"Stage 4 buffer");
4725
                        AR.FoStage4[1].POfill   = AR.FoStage4[1].PObuffer;
14✔
4726
                        AR.FoStage4[1].POstop   = AR.FoStage4[1].PObuffer
14✔
4727
                                                 + AR.FoStage4[1].POsize/sizeof(WORD);
14✔
4728
#ifdef WITHPTHREADS
4729
                        AR.FoStage4[1].pthreadslock = dummylock;
12✔
4730
#endif
4731
                }
4732
                S->stage4 = 1;
88✔
4733
        }
4734
}
586✔
4735

4736
/*
4737
                 #] StageSort : 
4738
                 #[ SortWild :                                WORD SortWild(w,nw)
4739
*/
4740
/**
4741
 *        Sorts the wildcard entries in the parameter w. Double entries
4742
 *        are removed. Full space taken is nw words.
4743
 *        Routine serves for the reading of wildcards in the compiler.
4744
 *        The entries come in the format:
4745
 *        (type,4,number,0) in which the zero is reserved for the
4746
 *        future replacement of 'number'.
4747
 *
4748
 *        @param w  buffer with wildcard entries.
4749
 *        @param nw number of wildcard entries.
4750
 *        @return  Normal conventions (OK -> 0)
4751
 */
4752

4753
WORD SortWild(WORD *w, WORD nw)
5,078✔
4754
{
4755
        GETIDENTITY
3,384✔
4756
        WORD *v, *s, *m, k, i;
5,078✔
4757
        WORD *pScrat, *stop, *sv, error = 0;
5,078✔
4758
        pScrat = AT.WorkPointer;
5,078✔
4759
        if ( ( AT.WorkPointer + 8 * AM.MaxWildcards ) >= AT.WorkTop ) {
5,078✔
4760
                MLOCK(ErrorMessageLock);
×
4761
                MesWork();
×
4762
                MUNLOCK(ErrorMessageLock);
×
4763
                return(-1);
×
4764
        }
4765
        stop = w + nw;
5,078✔
4766
        i = 0;
5,078✔
4767
        while ( i < nw ) {
19,768✔
4768
                m = w + i;
14,690✔
4769
                v = m + m[1];
14,690✔
4770
                while ( v < stop && (
25,366✔
4771
                         *v == FROMSET || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
20,396✔
4772
                while ( v < stop ) {
35,054✔
4773
                        if ( *v >= 0 ) {
20,364✔
4774
                                if ( AM.Ordering[*v] < AM.Ordering[*m] ) {
19,470✔
4775
                                        m = v;
4776
                                }
4777
                                else if ( *v == *m ) {
19,008✔
4778
                                        if ( v[2] < m[2] ) {
17,994✔
4779
                                                m = v;
4780
                                        }
4781
                                        else if ( v[2] == m[2] ) {
17,976✔
4782
                                                s = m + m[1];
96✔
4783
                                                sv = v + v[1];
96✔
4784
                                                if ( s < stop && ( *s == FROMSET
96✔
4785
                                                 || *s == SETTONUM || *s == LOADDOLLAR ) ) {
96✔
4786
                                                        if ( sv < stop && ( *sv == FROMSET
×
4787
                                                        || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
×
4788
                                                                if ( s[2] != sv[2] ) {
×
4789
                                                                        error = -1;
×
4790
                                                                        MLOCK(ErrorMessageLock);
×
4791
                                                                        MesPrint("&Wildcard set conflict");
×
4792
                                                                        MUNLOCK(ErrorMessageLock);
×
4793
                                                                }
4794
                                                        }
4795
                                                        *v = -1;
×
4796
                                                }
4797
                                                else {
4798
                                                        if ( sv < stop && ( *sv == FROMSET
96✔
4799
                                                        || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
48✔
4800
                                                                *m = -1;
×
4801
                                                                m = v;
×
4802
                                                        }
4803
                                                        else {
4804
                                                                *v = -1;
96✔
4805
                                                        }
4806
                                                }
4807
                                        }
4808
                                }
4809
                        }
4810
                        v += v[1];
20,364✔
4811
                        while ( v < stop && ( *v == FROMSET
36,546✔
4812
                         || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
26,826✔
4813
                }
4814
                s = pScrat;
14,690✔
4815
                v = m;
14,690✔
4816
                k = m[1];
14,690✔
4817
                NCOPY(s,m,k);
73,450✔
4818
                while ( m < stop && ( *m == FROMSET
45,798✔
4819
                 || *m == SETTONUM || *m == LOADDOLLAR ) ) {
20,384✔
4820
                        k = m[1];
10,724✔
4821
                        NCOPY(s,m,k);
68,310✔
4822
                }
4823
                *v = -1;
14,690✔
4824
                pScrat = s;
14,690✔
4825
                i = 0;
14,690✔
4826
                while ( i < nw && ( w[i] < 0 || w[i] == FROMSET
75,180✔
4827
                || w[i] == SETTONUM || w[i] == LOADDOLLAR ) ) i += w[i+1];
70,102✔
4828
        }
4829
        AC.NwildC = k = WORDDIF(pScrat,AT.WorkPointer);
5,078✔
4830
        s = AT.WorkPointer;
5,078✔
4831
        m = w;
5,078✔
4832
        NCOPY(m,s,k);
106,734✔
4833
        AC.WildC = m;
5,078✔
4834
        return(error);
5,078✔
4835
}
4836

4837
/*
4838
                 #] SortWild : 
4839
                 #[ CleanUpSort :                        void CleanUpSort(num)
4840
*/
4841
/**
4842
 *                Partially or completely frees function sort buffers.
4843
 */
4844

4845
void CleanUpSort(int num)
5,976✔
4846
{
4847
        GETIDENTITY
3,976✔
4848
        SORTING *S;
5,976✔
4849
        int minnum = num, i;
5,976✔
4850
        if ( AN.FunSorts ) {
5,976✔
4851
                if ( num == -1 ) {
5,748✔
4852
                        if ( AN.MaxFunSorts > 3 ) {
3,814✔
4853
                                minnum = (AN.MaxFunSorts+4)/2;
2,080✔
4854
                        }
4855
                        else minnum = 4;
4856
                }
4857
                else if ( minnum == 0 ) minnum = 1;
1,934✔
4858
                for ( i = minnum; i < AN.NumFunSorts; i++ ) {
563,358✔
4859
                        S = AN.FunSorts[i];
557,610✔
4860
                        if ( S ) {
557,610✔
4861
                                if ( S->file.handle >= 0 ) {
1,544✔
4862
/*                                        TruncateFile(S->file.handle); */
4863
                                        UpdateMaxSize();
6✔
4864
#ifdef WITHZLIB
4865
                                        ClearSortGZIP(&(S->file));
6✔
4866
#endif
4867
                                        CloseFile(S->file.handle);
6✔
4868
                                        S->file.handle = -1;
6✔
4869
                                        remove(S->file.name);
6✔
4870
#ifdef GZIPDEBUG
4871
                                        MLOCK(ErrorMessageLock);
4872
                                        MesPrint("%w CleanUpSort removed file %s",S->file.name);
4873
                                        MUNLOCK(ErrorMessageLock);
4874
#endif
4875
                                }
4876
                                M_free(S->sPointer, "CleanUpSort: sPointer");
1,544✔
4877
                                M_free(S->Patches, "CleanUpSort: Patches");
1,544✔
4878
                                M_free(S->pStop, "CleanUpSort: pStop");
1,544✔
4879
                                M_free(S->poina, "CleanUpSort: poina");
1,544✔
4880
                                M_free(S->poin2a, "CleanUpSort: poin2a");
1,544✔
4881
                                M_free(S->fPatches, "CleanUpSort: fPatches");
1,544✔
4882
                                M_free(S->fPatchesStop, "CleanUpSort: fPatchesStop");
1,544✔
4883
                                M_free(S->inPatches, "CleanUpSort: inPatches");
1,544✔
4884
                                M_free(S->tree, "CleanUpSort: tree");
1,544✔
4885
                                M_free(S->used, "CleanUpSort: used");
1,544✔
4886
#ifdef WITHZLIB
4887
                                M_free(S->fpcompressed, "CleanUpSort: fpcompressed");
1,544✔
4888
                                M_free(S->fpincompressed, "CleanUpSort: fpincompressed");
1,544✔
4889
#endif
4890
                                M_free(S->ktoi, "CleanUpSort: ktoi");
1,544✔
4891
                                M_free(S->lBuffer, "CleanUpSort: lBuffer+sBuffer");
1,544✔
4892
                                M_free(S->file.PObuffer, "CleanUpSort: PObuffer");
1,544✔
4893
                                M_free(S, "CleanUpSort: sorting struct");
1,544✔
4894
                        }
4895
                        AN.FunSorts[i] = 0;
557,610✔
4896
                }
4897
                AN.MaxFunSorts = minnum;
5,748✔
4898
                if ( num == 0 ) {
5,748✔
4899
                        S = AN.FunSorts[0];
1,934✔
4900
                        if ( S ) {
1,934✔
4901
                                if ( S->file.handle >= 0 ) {
1,934✔
4902
/*                                        TruncateFile(S->file.handle); */
4903
                                        UpdateMaxSize();
×
4904
#ifdef WITHZLIB
4905
                                        ClearSortGZIP(&(S->file));
×
4906
#endif
4907
                                        CloseFile(S->file.handle);
×
4908
                                        S->file.handle = -1;
×
4909
                                        remove(S->file.name);
×
4910
#ifdef GZIPDEBUG
4911
                                        MLOCK(ErrorMessageLock);
4912
                                        MesPrint("%w CleanUpSort removed file %s",S->file.name);
4913
                                        MUNLOCK(ErrorMessageLock);
4914
#endif
4915
                                }
4916
                        }
4917
                }
4918
        }
4919
        for ( i = 0; i < 2; i++ ) {
17,928✔
4920
                if ( AR.FoStage4[i].handle >= 0 ) {
11,952✔
4921
                        UpdateMaxSize();
×
4922
#ifdef WITHZLIB
4923
                        ClearSortGZIP(&(AR.FoStage4[i]));
×
4924
#endif
4925
                        CloseFile(AR.FoStage4[i].handle);
×
4926
                        remove(AR.FoStage4[i].name);
×
4927
                        AR.FoStage4[i].handle = -1;
×
4928
#ifdef GZIPDEBUG
4929
                        MLOCK(ErrorMessageLock);
4930
                        MesPrint("%w CleanUpSort removed stage4 file %s",AR.FoStage4[i].name);
4931
                        MUNLOCK(ErrorMessageLock);
4932
#endif
4933
                }
4934
        }
4935
}
5,976✔
4936

4937
/*
4938
                 #] CleanUpSort : 
4939
                 #[ LowerSortLevel :         void LowerSortLevel()
4940
*/
4941
/**
4942
 *                Lowers the level in the sort system.
4943
 */
4944

4945
void LowerSortLevel(void)
16,898✔
4946
{
4947
        GETIDENTITY
11,264✔
4948
        if ( AR.sLevel >= 0 ) {
16,898✔
4949
                AR.sLevel--;
16,898✔
4950
                if ( AR.sLevel >= 0 ) AT.SS = AN.FunSorts[AR.sLevel];
16,898✔
4951
        }
4952
}
16,898✔
4953

4954
/*
4955
                 #] LowerSortLevel : 
4956
                 #[ PolyRatFunSpecial :
4957

4958
                Keeps only the most divergent term in AR.PolyFunVar
4959
                We assume that the terms are already in that notation.
4960
*/
4961

4962
WORD *PolyRatFunSpecial(PHEAD WORD *t1, WORD *t2)
×
4963
{
4964
        WORD *oldworkpointer = AT.WorkPointer, *t, *r;
×
4965
        WORD exp1, exp2;
×
4966
        int i;
×
4967
        t = t1+FUNHEAD;
×
4968
        if ( *t == -SYMBOL ) {
×
4969
                if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
4970
                exp1 = 1;
×
4971
                if ( t[2] != -SNUMBER ) goto Illegal;
×
4972
                t[3] = 1;
×
4973
        }
4974
        else if ( *t == -SNUMBER ) {
×
4975
                t[1] = 1;
×
4976
                t += 2;
×
4977
                if ( *t == -SYMBOL ) {
×
4978
                        if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
4979
                        exp1 = -1;
4980
                }
4981
                else if ( *t == -SNUMBER ) {
×
4982
                        t[1] = 1;
×
4983
                        exp1 = 0;
×
4984
                }
4985
                else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
4986
                        && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
4987
                        t[ARGHEAD+5] = 1;
×
4988
                        t[ARGHEAD+6] = 1;
×
4989
                        t[ARGHEAD+7] = 3;
×
4990
                        exp1 = -t[ARGHEAD+4];
×
4991
                }
4992
                else goto Illegal;
×
4993
        }
4994
        else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
4995
                && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
4996
                t[ARGHEAD+5] = 1;
×
4997
                t[ARGHEAD+6] = 1;
×
4998
                t[ARGHEAD+7] = 3;
×
4999
                exp1 = t[ARGHEAD+4];
×
5000
                t += *t;
×
5001
                if ( *t != -SNUMBER ) goto Illegal;
×
5002
                t[1] = 1;
×
5003
        }
5004
        else goto Illegal;
×
5005

5006
        t = t2+FUNHEAD;
×
5007
        if ( *t == -SYMBOL ) {
×
5008
                if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
5009
                exp2 = 1;
×
5010
                if ( t[2] != -SNUMBER ) goto Illegal;
×
5011
                t[3] = 1;
×
5012
        }
5013
        else if ( *t == -SNUMBER ) {
×
5014
                t[1] = 1;
×
5015
                t += 2;
×
5016
                if ( *t == -SYMBOL ) {
×
5017
                        if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
5018
                        exp2 = -1;
5019
                }
5020
                else if ( *t == -SNUMBER ) {
×
5021
                        t[1] = 1;
×
5022
                        exp2 = 0;
×
5023
                }
5024
                else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
5025
                        && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
5026
                        t[ARGHEAD+5] = 1;
×
5027
                        t[ARGHEAD+6] = 1;
×
5028
                        t[ARGHEAD+7] = 3;
×
5029
                        exp2 = -t[ARGHEAD+4];
×
5030
                }
5031
                else goto Illegal;
×
5032
        }
5033
        else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
5034
                && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
5035
                t[ARGHEAD+5] = 1;
×
5036
                t[ARGHEAD+6] = 1;
×
5037
                t[ARGHEAD+7] = 3;
×
5038
                exp2 = t[ARGHEAD+4];
×
5039
                t += *t;
×
5040
                if ( *t != -SNUMBER ) goto Illegal;
×
5041
                t[1] = 1;
×
5042
        }
5043
        else goto Illegal;
×
5044

5045
        if ( exp1 <= exp2 ) { i = t1[1]; r = t1; }
×
5046
        else                { i = t2[1]; r = t2; }
×
5047
        t = oldworkpointer;
5048
        NCOPY(t,r,i)
×
5049

5050
        return(oldworkpointer);
5051
Illegal:
×
5052
        MesPrint("Illegal occurrence of PolyRatFun with divergent option");
×
5053
        Terminate(-1);
×
5054
        return(0);
×
5055
}
5056

5057
/*
5058
                 #] PolyRatFunSpecial : 
5059
                 #[ SimpleSplitMerge :
5060

5061
                Sorts an array of WORDs. No adding of equal objects.
5062
*/
5063

5064
void SimpleSplitMergeRec(WORD *array,WORD num,WORD *auxarray)
×
5065
{
5066
        WORD n1,n2,i,j,k,*t1,*t2;
×
5067
        if ( num < 2 ) return;
×
5068
        if ( num == 2 ) {
×
5069
                if ( array[0] > array[1] ) {
×
5070
                        EXCH(array[0],array[1])
×
5071
                }
5072
                return;
×
5073
        }
5074
        n1 = num/2;
×
5075
        n2 = num - n1;
×
5076
        SimpleSplitMergeRec(array,n1,auxarray);
×
5077
        SimpleSplitMergeRec(array+n1,n2,auxarray);
×
5078
        if ( array[n1-1] <= array[n1] ) return;
×
5079

5080
        t1 = array; t2 = auxarray; i = n1; NCOPY(t2,t1,i);
×
5081
        i = 0; j = n1; k = 0;
5082
        while ( i < n1 && j < num ) {
×
5083
                if ( auxarray[i] <= array[j] ) { array[k++] = auxarray[i++]; }
×
5084
                else { array[k++] = array[j++]; }
×
5085
        }
5086
        while ( i < n1 ) array[k++] = auxarray[i++];
×
5087
/*
5088
        Remember: remnants of j are still in place!
5089
*/
5090
}
5091

5092
void SimpleSplitMerge(WORD *array,WORD num)
×
5093
{
5094
        WORD *auxarray = Malloc1(sizeof(WORD)*num/2,"SimpleSplitMerge");
×
5095
        SimpleSplitMergeRec(array,num,auxarray);
×
5096
        M_free(auxarray,"SimpleSplitMerge");
×
5097
}
×
5098

5099
/*
5100
                 #] SimpleSplitMerge : 
5101
                 #[ BinarySearch :
5102

5103
                Searches in the sorted array with length num for the object x.
5104
                If x is in the list, it returns the number of the array element
5105
                that matched. If it is not in the list, it returns -1.
5106
                If there are identical objects in the list, which one will
5107
                match is quasi random.
5108
*/
5109

5110
WORD BinarySearch(WORD *array,WORD num,WORD x)
×
5111
{
5112
        WORD i, bot, top, med;
×
5113
        if ( num < 8 ) {
×
5114
                for ( i = 0; i < num; i++ ) if ( array[i] == x ) return(i);
×
5115
                return(-1);
5116
        }
5117
        if ( array[0] > x || array[num-1] < x ) return(-1);
×
5118
        bot = 0; top = num-1; med = (top+bot)/2;
×
5119
        do {
×
5120
                if ( array[med] == x ) return(med);
×
5121
                if ( array[med] < x ) { bot = med+1; }
×
5122
                else { top = med-1; }
×
5123
                med = (top+bot)/2;
×
5124
        } while ( med >= bot && med <= top );
×
5125
        return(-1);
5126
}
5127

5128
/*
5129
                 #] BinarySearch : 
5130
        #] SortUtilities :
5131
*/
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc