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

form-dev / form / 18593356546

17 Oct 2025 12:55PM UTC coverage: 56.764% (-0.02%) from 56.779%
18593356546

Pull #730

github

web-flow
Merge 6b4aec53c into 2aba64bb5
Pull Request #730: fix: regression: save file compatibility

46738 of 82337 relevant lines covered (56.76%)

5692539.05 hits per line

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

66.15
/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
//#define COUNTCOMPARES
76
#ifdef COUNTCOMPARES
77
        // This needs to be large enough for the number of threads.
78
        // It is hardcoded here, but 1024 should be enough.
79
        // Enabling this has a performance impact.
80
        LONG numcompares[1024];
81
#endif
82

83
/*
84
          #] Includes : 
85
        #[ SortUtilities :
86
                #[ WriteStats :                                void WriteStats(lspace,par,checkLogType)
87
*/
88
 
89
char *toterms[] = { "   ", " >>", "-->" };
90

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

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

127
void WriteStats(POSITION *plspace, WORD par, WORD checkLogType)
312,978✔
128
{
129
        GETIDENTITY
208,636✔
130
        LONG millitime, y = 0x7FFFFFFFL >> 1;
312,978✔
131
        WORD timepart;
312,978✔
132
        SORTING *S;
312,978✔
133
        POSITION pp;
312,978✔
134
        int use_wtime;
312,978✔
135
        if ( AT.SS == AT.S0 && AC.StatsFlag ) {
312,978✔
136
#ifdef WITHPTHREADS
137
                if ( AC.ThreadStats == 0 && identity > 0 ) return;
35,041✔
138
#elif defined(WITHMPI)
139
                if ( AC.OldParallelStats ) return;
140
                if ( ! AC.ProcessStats && PF.me != MASTER ) return;
141
#endif
142
                if ( Expressions == 0 ) return;
46,415✔
143

144
                if ( par == STATSSPLITMERGE ) {
43,389✔
145
                        if ( AC.ShortStatsMax == 0 ) return;
9,102✔
146
                        AR.ShortSortCount++;
×
147
                        if ( AR.ShortSortCount < AC.ShortStatsMax ) return;
×
148
                }
149
                AR.ShortSortCount = 0;
34,287✔
150

151
                S = AT.SS;
34,287✔
152

153
                char humanGenTermsText[HUMANSTRLEN] = "";
34,287✔
154
                char humanTermsLeftText[HUMANSTRLEN] = "";
34,287✔
155
                char humanBytesText[HUMANSTRLEN] = "";
34,287✔
156
                if ( AC.HumanStatsFlag ) {
34,287✔
157
                        HumanString(humanGenTermsText, (float)(S->GenTerms), humanTermsSuffix);
18✔
158
                        HumanString(humanTermsLeftText, (float)(S->TermsLeft), humanTermsSuffix);
18✔
159
                        HumanString(humanBytesText, (float)(BASEPOSITION(*plspace)), humanBytesSuffix);
18✔
160
                }
161

162
                MLOCK(ErrorMessageLock);
34,287✔
163

164
                /* If the statistics should not go to the log file, temporarily hide the
165
                 * LogHandle. This must be done within the ErrorMessageLock region to
166
                 * avoid a data race between threads. */
167
                const WORD oldLogHandle = AC.LogHandle;
34,287✔
168
                if ( checkLogType && AM.LogType ) {
34,287✔
169
                        AC.LogHandle = -1;
2,071✔
170
                }
171

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

631
                MUNLOCK(ErrorMessageLock);
34,287✔
632
        }
633
}
634

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

649
int NewSort(PHEAD0)
15,700,559✔
650
{
651
        GETBIDENTITY
652
        SORTING *S, **newFS;
15,700,559✔
653
        int i, newsize;
15,700,559✔
654
        if ( AN.SoScratC == 0 )
15,700,559✔
655
                AN.SoScratC = (UWORD *)Malloc1(2*(AM.MaxTal+2)*sizeof(UWORD),"NewSort");
5,056✔
656
        AR.sLevel++;
15,700,559✔
657
        if ( AR.sLevel >= AN.NumFunSorts ) {
15,700,559✔
658
                if ( AN.NumFunSorts == 0 ) newsize = 100;
6,540✔
659
                else newsize = 2*AN.NumFunSorts;
×
660
                newFS = (SORTING **)Malloc1((newsize+1)*sizeof(SORTING *),"FunSort pointers");
6,540✔
661
                for ( i = 0; i < AN.NumFunSorts; i++ ) newFS[i] = AN.FunSorts[i];
13,080✔
662
                for ( ; i <= newsize; i++ ) newFS[i] = 0;
667,080✔
663
                if ( AN.FunSorts ) M_free(AN.FunSorts,"FunSort pointers");
6,540✔
664
                AN.FunSorts = newFS; AN.NumFunSorts = newsize;
6,540✔
665
        }
666
        if ( AR.sLevel == 0 ) {
15,700,559✔
667

668
#ifdef COUNTCOMPARES
669
#ifdef WITHPTHREADS
670
                numcompares[AT.identity] = 0;
671
#else
672
                numcompares[0] = 0;
673
#endif
674
#endif
675

676
                AN.FunSorts[0] = AT.S0;
821,920✔
677
                if ( AR.PolyFun == 0 ) { AT.S0->PolyFlag = 0; }
821,920✔
678
                else if ( AR.PolyFunType == 1 ) { AT.S0->PolyFlag = 1; }
295,782✔
679
                else if ( AR.PolyFunType == 2 ) {
294,882✔
680
                        if ( AR.PolyFunExp == 2
294,882✔
681
                          || AR.PolyFunExp == 3 ) AT.S0->PolyFlag = 1;
294,882✔
682
                        else                      AT.S0->PolyFlag = 2;
186,564✔
683
                }
684
                AR.ShortSortCount = 0;
821,920✔
685
        }
686
        else {
687
                if ( AN.FunSorts[AR.sLevel] == 0 ) {
14,878,639✔
688
                        AN.FunSorts[AR.sLevel] = AllocSort(
3,087✔
689
                                AM.SLargeSize,AM.SSmallSize,AM.SSmallEsize,AM.STermsInSmall
690
                                        ,AM.SMaxPatches,AM.SMaxFpatches,AM.SIOsize,1);
691
                }
692
                AN.FunSorts[AR.sLevel]->PolyFlag = 0;
14,878,639✔
693
        }
694
        AT.SS = S = AN.FunSorts[AR.sLevel];
15,700,559✔
695
        S->sFill = S->sBuffer;
15,700,559✔
696
        S->lFill = S->lBuffer;
15,700,559✔
697
        S->lPatch = 0;
15,700,559✔
698
        S->fPatchN = 0;
15,700,559✔
699
        S->GenTerms = S->TermsLeft = S->GenSpace = S->SpaceLeft = 0;
15,700,559✔
700
        S->PoinFill = S->sPointer;
15,700,559✔
701
        *S->PoinFill = S->sFill;
15,700,559✔
702
        if ( AR.sLevel > 0 ) { S->PolyWise = 0; }
15,700,559✔
703
        PUTZERO(S->SizeInFile[0]); PUTZERO(S->SizeInFile[1]); PUTZERO(S->SizeInFile[2]);
15,700,559✔
704
        S->sTerms = 0;
15,700,559✔
705
        PUTZERO(S->file.POposition);
15,700,559✔
706
        S->stage4 = 0;
15,700,559✔
707
        if ( AR.sLevel > AN.MaxFunSorts ) AN.MaxFunSorts = AR.sLevel;
15,700,559✔
708
/*
709
        The next variable is for the staged sort only.
710
        It should be treated differently
711

712
        PUTZERO(AN.OldPosOut);
713
*/
714
        return(0);
15,700,559✔
715
}
716

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

745
LONG EndSort(PHEAD WORD *buffer, int par)
15,226,393✔
746
{
747
  GETBIDENTITY
748
  SORTING *S = AT.SS;
15,226,393✔
749
  WORD j, **ss, *to, *t;
15,226,393✔
750
  LONG sSpace, over, tover, spare, retval = 0;
15,226,393✔
751
  POSITION position, pp;
15,226,393✔
752
  off_t lSpace;
15,226,393✔
753
  FILEHANDLE *fout = 0, *oldoutfile = 0, *newout = 0;
15,226,393✔
754

755
  if ( AM.exitflag && AR.sLevel == 0 ) return(0);
15,226,393✔
756
#ifdef WITHMPI 
757
  if( (retval = PF_EndSort()) > 0){
758
        oldoutfile = AR.outfile;
759
        retval = 0;
760
        goto RetRetval;
761
  } 
762
  else if(retval < 0){
763
        retval = -1; 
764
        goto RetRetval; 
765
  }
766
        /* PF_EndSort returned 0: for S != AM.S0 and slaves still do the regular sort */
767
#endif /* WITHMPI */
768
        oldoutfile = AR.outfile;
15,226,393✔
769
/*                PolyFlag repair action
770
        if ( S == AT.S0 ) {
771
                if ( AR.PolyFun == 0 ) { S->PolyFlag = 0; }
772
                else if ( AR.PolyFunType == 1 ) { S->PolyFlag = 1; }
773
                else if ( AR.PolyFunType == 2 ) {
774
                        if ( AR.PolyFunExp == 2
775
                          || AR.PolyFunExp == 3 ) S->PolyFlag = 1;
776
                        else                      S->PolyFlag = 2;
777
                }
778
                S->PolyWise = 0;
779
        }
780
        else {
781
                S->PolyFlag = S->PolyWise = 0;
782
        }
783
*/
784
        S->PolyWise = 0;
15,226,393✔
785
        *(S->PoinFill) = 0;
15,226,393✔
786
#ifdef SPLITTIME
787
                PrintTime((UBYTE *)"EndSort, before SplitMerge");
788
#endif
789
        S->sPointer[SplitMerge(BHEAD S->sPointer,S->sTerms)] = 0;
15,226,393✔
790
#ifdef SPLITTIME
791
                PrintTime((UBYTE *)"Endsort,  after SplitMerge");
792
#endif
793
        sSpace = 0;
15,226,373✔
794
        tover = over = S->sTerms;
15,226,373✔
795
        ss = S->sPointer;
15,226,373✔
796
        if ( over >= 0 ) {
15,226,373✔
797
                if ( S->lPatch > 0 || S->file.handle >= 0 ) {
15,226,373✔
798
                        ss[over] = 0;
309✔
799
                        sSpace = ComPress(ss,&spare);
309✔
800
                        S->TermsLeft -= over - spare;
309✔
801
                        if ( par == 1 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
309✔
802
                }
803
                else if ( S != AT.S0 ) {
15,226,064✔
804
                        ss[over] = 0;
14,878,420✔
805
                        if ( par == 2 ) {
14,878,420✔
806
                                sSpace = 3;
807
                                while ( ( t = *ss++ ) != 0 ) { sSpace += *t; }
4,049,690✔
808
                                if ( AN.tryterm > 0 && ( (sSpace+1)*sizeof(WORD) < (size_t)(AM.MaxTer) ) ) {
592,267✔
809
                                        to = TermMalloc("$-sort space");
90✔
810
                                }
811
                                else {
812
                                        LONG allocsp = sSpace+1;
592,177✔
813
                                        if ( allocsp < MINALLOC ) allocsp = MINALLOC;
592,177✔
814
                                        allocsp = ((allocsp+7)/8)*8;
592,177✔
815
                                        to = (WORD *)Malloc1(allocsp*sizeof(WORD),"$-sort space");
592,177✔
816
                                        if ( AN.tryterm > 0 ) AN.tryterm = 0;
592,177✔
817
                                }
818
                                *((WORD **)buffer) = to;
592,267✔
819
                                ss = S->sPointer;
592,267✔
820
                                while ( ( t = *ss++ ) != 0 ) {
4,049,690✔
821
                                        j = *t; while ( --j >= 0 ) *to++ = *t++;
53,554,019✔
822
                                }
823
                                *to = 0;
592,267✔
824
                                retval = sSpace + 1;
592,267✔
825
                        }
826
                        else {
827
                                to = buffer;
828
                                sSpace = 0;
829
                                while ( ( t = *ss++ ) != 0 ) {
44,583,080✔
830
                                        j = *t;
30,296,927✔
831
                                        if ( ( sSpace += j ) > AM.MaxTer/((LONG)sizeof(WORD)) ) {
30,296,927✔
832
                                                /* Too big! Get the total size for useful error message */
833
                                                while ( ( t = *ss++ ) != 0 ) {
×
834
                                                        sSpace += *t;
×
835
                                                }
836
                                                MLOCK(ErrorMessageLock);
×
837
                                                MesPrint("Sorted function argument too long (%d words). Increase MaxTermSize (%l words).", sSpace, AM.MaxTer/((LONG)sizeof(WORD)));
×
838
                                                MUNLOCK(ErrorMessageLock);
×
839
                                                retval = -1; goto RetRetval;
×
840
                                        }
841
                                        while ( --j >= 0 ) *to++ = *t++;
251,911,503✔
842
                                }
843
                                *to = 0;
14,286,153✔
844
                                retval = to - buffer;
14,286,153✔
845
                        }
846
                        goto RetRetval;
14,878,420✔
847
                }
848
                else {
849
                        POSITION oldpos;
347,644✔
850
                        if ( S == AT.S0 ) {
347,644✔
851
                                fout = AR.outfile;
347,644✔
852
                                *AR.CompressPointer = 0;
347,644✔
853
                                SeekScratch(AR.outfile,&position);
347,644✔
854
                        }
855
                        else {
856
                                fout = &(S->file);
857
                                PUTZERO(position);
858
                        }
859
                        oldpos = position;
347,644✔
860
                        S->TermsLeft = 0;
347,644✔
861
/*
862
                        Here we can go directly to the output.
863
*/
864
#ifdef WITHZLIB
865
                        { int oldgzipCompress = AR.gzipCompress;
347,644✔
866
                                AR.gzipCompress = 0;
347,644✔
867
#endif
868
                        if ( tover > 0 ) {
347,644✔
869
                                ss = S->sPointer;
307,125✔
870
                                while ( ( t = *ss++ ) != 0 ) {
6,915,597✔
871
                                        if ( *t ) S->TermsLeft++;
6,608,472✔
872
#ifdef WITHPTHREADS
873
                                        if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD t); }
4,369,160✔
874
                                        else
875
#endif
876
                                        if ( PutOut(BHEAD t,&position,fout,1) < 0 ) {
3,726,592✔
877
                                                retval = -1; goto RetRetval;
×
878
                                        }
879
                                }
880
                        }
881
#ifdef WITHPTHREADS
882
                        if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD 0); }
247,268✔
883
                        else
884
#endif
885
                        if ( FlushOut(&position,fout,1) ) {
277,932✔
886
                                retval = -1; goto RetRetval;
×
887
                        }
888
#ifdef WITHZLIB
889
                                AR.gzipCompress = oldgzipCompress;
347,644✔
890
                        }
891
#endif
892
#ifdef WITHPTHREADS
893
                        if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
247,268✔
894
#endif
895
#ifdef WITHMPI
896
                        if ( PF.me != MASTER && PF.exprtodo < 0 ) goto RetRetval;
897
#endif
898
                        DIFPOS(oldpos,position,oldpos);
277,932✔
899
                        S->SpaceLeft = BASEPOSITION(oldpos);
277,932✔
900
                        WriteStats(&oldpos,STATSPOSTSORT,NOCHECKLOGTYPE);
277,932✔
901
                        pp = oldpos;
277,932✔
902
                        goto RetRetval;
277,932✔
903
                }
904
        }
905
        else if ( par == 1 && newout == 0 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
×
906
        sSpace++;
309✔
907
        lSpace = sSpace + (S->lFill - S->lBuffer) - (LONG)S->lPatch*(AM.MaxTer/sizeof(WORD));
309✔
908
/*         Note wrt MaxTer and lPatch: each patch starts with space for decompression */
909
/*         Not needed if only large buffer, but needed when using files (?) */
910
        SETBASEPOSITION(pp,lSpace);
309✔
911
        MULPOS(pp,sizeof(WORD));
309✔
912
        if ( S->file.handle >= 0 ) {
309✔
913
                ADD2POS(pp,S->fPatches[S->fPatchN]);
76✔
914
        }
915
        if ( S == AT.S0 ) {
309✔
916
                if ( S->lPatch > 0 || S->file.handle >= 0 ) {
102✔
917
                        WriteStats(&pp,STATSSPLITMERGE,CHECKLOGTYPE);
102✔
918
                }
919
        }
920
        if ( par == 2 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
309✔
921
        if ( S->lPatch > 0 ) {
309✔
922
                if ( ( S->lPatch >= S->MaxPatches ) ||
309✔
923
                        ( ( (WORD *)(((UBYTE *)(S->lFill + sSpace)) + 2*AM.MaxTer) ) >= S->lTop ) ) {
272✔
924
/*
925
                        The large buffer is too full. Merge and write it
926
*/
927
#ifdef GZIPDEBUG
928
                        MLOCK(ErrorMessageLock);
929
                        MesPrint("%w EndSort: lPatch = %d, MaxPatches = %d,lFill = %x, sSpace = %ld, MaxTer = %d, lTop = %x"
930
                                        ,S->lPatch,S->MaxPatches,S->lFill,sSpace,AM.MaxTer/sizeof(WORD),S->lTop);
931
                        MUNLOCK(ErrorMessageLock);
932
#endif
933

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

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

1283
#ifdef COUNTCOMPARES
1284
        if ( AR.sLevel < 0 ) {
1285
#ifdef WITHPTHREADS
1286
                MLOCK(ErrorMessageLock);
1287
                MesPrint(">>>number of calls to Compare: %l (tid %d)", numcompares[AT.identity], AT.identity);
1288
                MUNLOCK(ErrorMessageLock);
1289
#else
1290
                MesPrint(">>>number of calls to Compare: %l", numcompares[0]);
1291
#endif
1292
        }
1293
#endif
1294

1295
        return(retval);
1296
WorkSpaceError:
×
1297
        MLOCK(ErrorMessageLock);
×
1298
        MesWork();
×
1299
        MesCall("EndSort");
×
1300
        MUNLOCK(ErrorMessageLock);
×
1301
        Terminate(-1);
×
1302
        return(-1);
×
1303
}
1304

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

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

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

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

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

1470
WORD PutOut(PHEAD WORD *term, POSITION *position, FILEHANDLE *fi, WORD ncomp)
26,066,299✔
1471
{
1472
        GETBIDENTITY
1473
        WORD i, *p, ret, *r, *rr, j, k, first;
26,066,299✔
1474
        int dobracketindex = 0;
26,066,299✔
1475
        LONG RetCode;
26,066,299✔
1476

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

1566
        if ( AR.sLevel <= 0 && Expressions[AR.CurExpr].newbracketinfo
25,346,202✔
1567
                && ( fi == AR.outfile || fi == AR.hidefile ) ) dobracketindex = 1;
1,152,294✔
1568
        r = rr = AR.CompressPointer;
25,346,202✔
1569
        first = j = k = ret = 0;
25,346,202✔
1570
        if ( ( i = *term ) != 0 ) {
25,346,202✔
1571
                if ( i < 0 ) {                        /* Compressed term */
25,346,202✔
1572
                        i = term[1] + 2;
64✔
1573
                        if ( fi == AR.outfile || fi == AR.hidefile ) {
64✔
1574
                                MLOCK(ErrorMessageLock);
×
1575
                                MesPrint("Ran into precompressed term");
×
1576
                                MUNLOCK(ErrorMessageLock);
×
1577
                                Crash();
×
1578
                                return(-1);
×
1579
                        }
1580
                }
1581
                else if ( !AR.NoCompress && ( ncomp > 0 ) && AR.sLevel <= 0 ) {        /* Must compress */
25,346,138✔
1582
                        if ( dobracketindex ) {
12,000,600✔
1583
                                PutBracketInIndex(BHEAD term,position);
1,152,294✔
1584
                        }
1585
                        j = *r++ - 1;
12,000,600✔
1586
                        p = term + 1;
12,000,600✔
1587
                        i--;
12,000,600✔
1588
                        if ( AR.PolyFun ) {
12,000,600✔
1589
                                WORD *polystop, *sa;
3,170,970✔
1590
                                sa = p + i;
3,170,970✔
1591
                                sa -= ABS(sa[-1]);
3,170,970✔
1592
                                polystop = p;
3,170,970✔
1593
                                while ( polystop < sa && *polystop != AR.PolyFun ) {
12,289,374✔
1594
                                        polystop += polystop[1];
9,118,404✔
1595
                                }
1596
                                if ( polystop < sa ) {
3,170,970✔
1597
                                        if ( AR.PolyFunType == 2 ) polystop[2] &= ~MUSTCLEANPRF;
3,170,970✔
1598
                                        while ( i > 0 && j > 0 && *p == *r && p < polystop ) {
49,904,190✔
1599
                                                i--; j--; k--; p++; r++;
46,733,220✔
1600
                                        }
1601
                                }
1602
                                else {
1603
                                        while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
×
1604
                                }
1605
                        }
1606
#ifdef WITHFLOAT
1607
                        else if ( AC.DefaultPrecision ) {
8,829,630✔
1608
                                WORD *floatstop, *sa;
8,829,630✔
1609
                                sa = p + i;
8,829,630✔
1610
                                sa -= ABS(sa[-1]);
8,829,630✔
1611
                                floatstop = p;
8,829,630✔
1612
                                while ( floatstop < sa && *floatstop != FLOATFUN ) {
20,912,985✔
1613
                                        floatstop += floatstop[1];
12,083,355✔
1614
                                }
1615
                                if ( floatstop < sa ) {
8,829,630✔
1616
                                        while ( i > 0 && j > 0 && *p == *r && p < floatstop ) {
16,914✔
1617
                                                i--; j--; k--; p++; r++;
12,948✔
1618
                                        }
1619
                                }
1620
                                else {
1621
                                        while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
52,446,276✔
1622
                                }
1623
                        }
1624
#endif
1625
                        else {
1626
                                WORD *sa;
×
1627
                                sa = p + i;
×
1628
                                sa -= ABS(sa[-1]);
×
1629
                                while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
×
1630
                        }
1631
                        if ( k > -2 ) {
12,000,600✔
1632
nocompress:
1,276,293✔
1633
                                j = i = *term;
1,435,461✔
1634
                                k = 0;
1,435,461✔
1635
                                p = term;
1,435,461✔
1636
                                r = rr;
1,435,461✔
1637
                                NCOPY(r,p,j);
90,204,590✔
1638
                        }
1639
                        else {
1640
                                *rr = *term;
10,724,307✔
1641
                                term = p;
10,724,307✔
1642
                                j = i;
10,724,307✔
1643
                                NCOPY(r,p,j);
342,993,544✔
1644
                                j = i;
10,724,307✔
1645
                                i += 2;
10,724,307✔
1646
                                first = 2;
10,724,307✔
1647
                        }
1648
/*                                        Sabotage getting into the coefficient next time */
1649
                        r[-(ABS(r[-1]))] = 0;
12,159,768✔
1650
                        if ( r >= AR.ComprTop ) {
12,159,768✔
1651
                                MLOCK(ErrorMessageLock);
×
1652
                                MesPrint("CompressSize of %10l is insufficient",AM.CompressSize);
×
1653
                                MUNLOCK(ErrorMessageLock);
×
1654
                                Crash();
×
1655
                                return(-1);
×
1656
                        }
1657
                }
1658
                else if ( !AR.NoCompress && ( ncomp < 0 ) && AR.sLevel <= 0 ) {
13,345,538✔
1659
                                /* No compress but put in compress buffer anyway */
1660
                        if ( dobracketindex ) {
159,168✔
1661
                                PutBracketInIndex(BHEAD term,position);
×
1662
                        }
1663
                        j = *r++ - 1;
159,168✔
1664
                        p = term + 1;
159,168✔
1665
                        i--;
159,168✔
1666
                        if ( AR.PolyFun ) {
159,168✔
1667
                                WORD *polystop, *sa;
31,278✔
1668
                                sa = p + i;
31,278✔
1669
                                sa -= ABS(sa[-1]);
31,278✔
1670
                                polystop = p;
31,278✔
1671
                                while ( polystop < sa && *polystop != AR.PolyFun ) {
34,938✔
1672
                                        polystop += polystop[1];
3,660✔
1673
                                }
1674
                                if ( polystop < sa ) {
31,278✔
1675
                                        if ( AR.PolyFunType == 2 ) polystop[2] &= ~MUSTCLEANPRF;
31,278✔
1676
                                        while ( i > 0 && j > 0 && *p == *r && p < polystop ) {
31,278✔
1677
                                                i--; j--; k--; p++; r++;
×
1678
                                        }
1679
                                }
1680
                                else {
1681
                                        while ( i > 0 && j > 0 && *p == *r ) { i--; j--; k--; p++; r++; }
×
1682
                                }
1683
                        }
1684
                        else {
1685
                                while ( i > 0 && j > 0 && *p == *r ) { i--; j--; k--; p++; r++; }
127,890✔
1686
                        }
1687
                        goto nocompress;
159,168✔
1688
                }
1689
                else {
1690
                        if ( AR.PolyFunType == 2 ) {
13,186,370✔
1691
                                WORD *t, *tstop;
240,348✔
1692
                                tstop = term + *term;
240,348✔
1693
                                tstop -= ABS(tstop[-1]);
240,348✔
1694
                                t = term+1;
240,348✔
1695
                                while ( t < tstop ) {
480,696✔
1696
                                        if ( *t == AR.PolyFun ) {
240,348✔
1697
                                                t[2] &= ~MUSTCLEANPRF;
×
1698
                                        }
1699
                                        t += t[1];
240,348✔
1700
                                }
1701
                        }
1702
                        if ( dobracketindex ) {
13,186,370✔
1703
                                PutBracketInIndex(BHEAD term,position);
×
1704
                        }
1705
                }
1706
                ret = i;
25,346,202✔
1707
                ADDPOS(*position,i*sizeof(WORD));
25,346,202✔
1708
                p = fi->POfill;
25,346,202✔
1709
                do {
719,585,219✔
1710
                        if ( p >= fi->POstop ) {
719,585,219✔
1711
#ifdef WITHMPI /* [16mar1998 ar] */
1712
                          if ( PF.me != MASTER && AR.sLevel <= 0 && (fi == AR.outfile || fi == AR.hidefile) && PF.parallel && PF.exprtodo < 0 ) {
1713
                                PF_BUFFER *sbuf = PF.sbuf;
1714
                                sbuf->fill[sbuf->active] = fi->POstop;
1715
                                PF_ISendSbuf(MASTER,PF_BUFFER_MSGTAG);
1716
                                p = fi->PObuffer = fi->POfill = fi->POfull =
1717
                                  sbuf->buff[sbuf->active];
1718
                                fi->POstop = sbuf->stop[sbuf->active];
1719
                          }
1720
                          else
1721
#endif /* WITHMPI [16mar1998 ar] */
1722
                          {
1723
                                if ( fi->handle < 0 ) {
204✔
1724
                                        if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
18✔
1725
#ifdef GZIPDEBUG
1726
                                                MLOCK(ErrorMessageLock);
1727
                                                MesPrint("%w PutOut created sortfile %s",fi->name);
1728
                                                MUNLOCK(ErrorMessageLock);
1729
#endif
1730
                                                fi->handle = (WORD)RetCode;
18✔
1731
                                                PUTZERO(fi->filesize);
18✔
1732
                                                PUTZERO(fi->POposition);
18✔
1733
/*
1734
                                                Should not be here?
1735
#ifdef WITHZLIB
1736
                                                fi->ziobuffer = 0;
1737
#endif
1738
*/
1739
                                        }
1740
                                        else {
1741
                                                MLOCK(ErrorMessageLock);
×
1742
                                                MesPrint("Cannot create scratch file %s",fi->name);
×
1743
                                                MUNLOCK(ErrorMessageLock);
×
1744
                                                return(-1);
×
1745
                                        }
1746
                                }
1747
#ifdef WITHZLIB
1748
                                if ( !AR.NoCompress && ncomp > 0 && AR.gzipCompress > 0
204✔
1749
                                        && dobracketindex == 0 && fi->zsp != 0 ) {
46✔
1750
                                        fi->POfill = p;
46✔
1751
                                        if ( PutOutputGZIP(fi) ) return(-1);
46✔
1752
                                        p = fi->PObuffer;
46✔
1753
                                }
1754
                                else
1755
#endif
1756
                                {
1757
#ifdef ALLLOCK
1758
                                  LOCK(fi->pthreadslock);
1759
#endif
1760
                                  if ( fi == AR.hidefile ) {
158✔
1761
                                        LOCK(AS.inputslock);
90✔
1762
                                  }
1763
                                  SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
158✔
1764
                                  if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize) ) != fi->POsize ) {
158✔
1765
                                        if ( fi == AR.hidefile ) {
×
1766
                                                UNLOCK(AS.inputslock);
×
1767
                                        }
1768
#ifdef ALLLOCK
1769
                                        UNLOCK(fi->pthreadslock);
1770
#endif
1771
                                        MLOCK(ErrorMessageLock);
×
1772
                                        MesPrint("Write error during sort. Disk full?");
×
1773
                                        MesPrint("Attempt to write %l bytes on file %d at position %15p",
×
1774
                                                                fi->POsize,fi->handle,&(fi->POposition));
1775
                                        MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
×
1776
                                        MUNLOCK(ErrorMessageLock);
×
1777
                                        return(-1);
×
1778
                                  }
1779
                                  ADDPOS(fi->filesize,fi->POsize);
158✔
1780
                                  p = fi->PObuffer;
158✔
1781
                                  ADDPOS(fi->POposition,fi->POsize);
158✔
1782
                                  if ( fi == AR.hidefile ) {
158✔
1783
                                        UNLOCK(AS.inputslock);
244,351,372✔
1784
                                  }
1785
#ifdef ALLLOCK
1786
                                  UNLOCK(fi->pthreadslock);
1787
#endif
1788
#ifdef WITHPTHREADS
1789
                                  if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
68✔
1790
                                        if ( fi->handle >= 0 ) SynchFile(fi->handle);
1791
                                  }
1792
#endif
1793
                                }
1794
                          }
1795
                        } 
1796
                        if ( first ) {
719,585,219✔
1797
                                if ( first == 2 ) *p++ = k;
21,448,614✔
1798
                                else *p++ = j;
10,724,307✔
1799
                                first--;
21,448,614✔
1800
                        }
1801
                        else *p++ = *term++;
698,136,605✔
1802
/*
1803
                        if ( AP.DebugFlag ) {
1804
                                TalToLine((UWORD)(p[-1])); TokenToLine((UBYTE *)"  ");
1805
                        }
1806
*/
1807
                } while ( --i > 0 );
719,585,219✔
1808
                fi->POfull = fi->POfill = p;
25,346,202✔
1809
        }
1810
/*
1811
        if ( AP.DebugFlag ) {
1812
                AO.OutSkip = 0;
1813
                FiniLine();
1814
        }
1815
*/
1816
        return(ret);
1817
}
1818

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

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

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

2046
int AddCoef(PHEAD WORD **ps1, WORD **ps2)
14,542,546✔
2047
{
2048
        GETBIDENTITY
2049
        SORTING *S = AT.SS;
14,542,546✔
2050
        WORD *s1, *s2;
14,542,546✔
2051
        WORD l1, l2, i;
14,542,546✔
2052
        WORD OutLen, *t, j;
14,542,546✔
2053
        UWORD *OutCoef;
14,542,546✔
2054
#ifdef WITHFLOAT
2055
        if ( AT.SortFloatMode ) return(AddWithFloat(BHEAD ps1,ps2));
14,542,546✔
2056
#endif
2057
        OutCoef = AN.SoScratC;
14,542,372✔
2058
        s1 = *ps1; s2 = *ps2;
14,542,372✔
2059
        GETCOEF(s1,l1);
14,542,372✔
2060
        GETCOEF(s2,l2);
14,542,372✔
2061
        if ( AddRat(BHEAD (UWORD *)s1,l1,(UWORD *)s2,l2,OutCoef,&OutLen) ) {
14,542,372✔
2062
                MLOCK(ErrorMessageLock);
×
2063
                MesCall("AddCoef");
×
2064
                MUNLOCK(ErrorMessageLock);
×
2065
                Terminate(-1);
×
2066
        }
2067
        if ( AN.ncmod != 0 ) {
14,542,372✔
2068
                if ( ( AC.modmode & POSNEG ) != 0 ) {
×
2069
                        NormalModulus(OutCoef,&OutLen);
×
2070
/*
2071
                        We had forgotten that this can also become smaller but the
2072
                        denominator isn't there. Correct in the other case
2073
                        17-may-2009 [JV]
2074
*/
2075
                        j = ABS(OutLen); OutCoef[j] = 1;
×
2076
                        for ( i = 1; i < j; i++ ) OutCoef[j+i] = 0;
×
2077
                }
2078
                else if ( BigLong(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod)) >= 0 ) {
×
2079
                        SubPLon(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod),OutCoef,&OutLen);
×
2080
                        OutCoef[OutLen] = 1;
×
2081
                        for ( i = 1; i < OutLen; i++ ) OutCoef[OutLen+i] = 0;
×
2082
                }
2083
        }
2084
        if ( !OutLen ) { *ps1 = *ps2 = 0; return(0); }
14,542,372✔
2085
        OutLen *= 2;
12,347,391✔
2086
        if ( OutLen < 0 ) i = - ( --OutLen );
12,347,391✔
2087
        else                          i = ++OutLen;
9,975,184✔
2088
        if ( l1 < 0 ) l1 = -l1;
12,347,391✔
2089
        l1 *= 2; l1++;
12,347,391✔
2090
        if ( i <= l1 ) {        /* Fits in 1 */
12,347,391✔
2091
                l1 -= i;
12,197,505✔
2092
                **ps1 -= l1;
12,197,505✔
2093
                s2 = (WORD *)OutCoef;
12,197,505✔
2094
                while ( --i > 0 ) *s1++ = *s2++;
37,653,213✔
2095
                *s1++ = OutLen;
12,197,505✔
2096
                while ( --l1 >= 0 ) *s1++ = 0;
12,219,045✔
2097
                goto RegEnd;
12,197,505✔
2098
        }
2099
        if ( l2 < 0 ) l2 = -l2;
149,886✔
2100
        l2 *= 2; l2++;
149,886✔
2101
        if ( i <= l2 ) {        /* Fits in 2 */
149,886✔
2102
                l2 -= i;
109,528✔
2103
                **ps2 -= l2;
109,528✔
2104
                s1 = (WORD *)OutCoef;
109,528✔
2105
                while ( --i > 0 ) *s2++ = *s1++;
657,808✔
2106
                *s2++ = OutLen;
109,528✔
2107
                while ( --l2 >= 0 ) *s2++ = 0;
109,736✔
2108
                *ps1 = *ps2;
109,528✔
2109
                goto RegEnd;
109,528✔
2110
        }
2111

2112
        /* Doesn't fit. Make a new term. */
2113

2114
        t = s1;
40,358✔
2115
        s1 = *ps1;
40,358✔
2116
        j = *s1++ + i - l1;                /* Space needed */
40,358✔
2117
        if ( (S->sFill + j) >= S->sTop2 ) {
40,358✔
2118
                GarbHand();
×
2119
                s1 = *ps1;
×
2120
                t = s1 + *s1 - 1;
×
2121
                j = *s1++ + i - l1;                /* Space needed */
×
2122
                l1 = *t;
×
2123
                if ( l1 < 0 ) l1  = - l1;
×
2124
                t -= l1-1;
×
2125
        }
2126
        s2 = S->sFill;
40,358✔
2127
        *s2++ = j;
40,358✔
2128
        while ( s1 < t ) *s2++ = *s1++;
280,140✔
2129
        s1 = (WORD *)OutCoef;
2130
        while ( --i > 0 ) *s2++ = *s1++;
330,200✔
2131
        *s2++ = OutLen;
40,358✔
2132
        *ps1 = S->sFill;
40,358✔
2133
        S->sFill = s2;
40,358✔
2134
RegEnd:
12,347,391✔
2135
        *ps2 = 0;
12,347,391✔
2136
        if ( **ps1 > AM.MaxTer/((LONG)(sizeof(WORD))) ) {
12,347,391✔
2137
                MLOCK(ErrorMessageLock);
×
2138
                MesPrint("Term too complex after addition in sort. MaxTermSize = %10l",
×
2139
                AM.MaxTer/sizeof(WORD));
×
2140
                MUNLOCK(ErrorMessageLock);
×
2141
                Terminate(-1);
×
2142
        }
2143
        return(1);
2144
}
2145

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

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

2333
/*
2334
                 #] AddPoly : 
2335
                 #[ AddArgs :                                void AddArgs(arg1,arg2,to)
2336
*/
2337
 
2338
#define INSLENGTH(x)  w[1] = FUNHEAD+ARGHEAD+x; w[FUNHEAD] = ARGHEAD+x;
2339

2340
/**
2341
 *        Adds the arguments of two occurrences of the PolyFun.
2342
 *        @param s1 Pointer to the first occurrence.
2343
 *        @param s2 Pointer to the second occurrence.
2344
 *        @param m  Pointer to where the answer should be.
2345
 */
2346

2347
void AddArgs(PHEAD WORD *s1, WORD *s2, WORD *m)
18,509✔
2348
{
2349
        GETBIDENTITY
2350
        WORD i1, i2;
18,509✔
2351
        WORD *w = m, *mm, *t, *t1, *t2, *tstop1, *tstop2;
18,509✔
2352
        WORD tempterm[8+FUNHEAD];
18,509✔
2353

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

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

2640
WORD Compare1(PHEAD WORD *term1, WORD *term2, WORD level)
122,201,685✔
2641
{
2642
        SORTING *S = AT.SS;
122,201,685✔
2643
        WORD *stopper1, *stopper2, *t2;
122,201,685✔
2644
        WORD *s1, *s2, *t1;
122,201,685✔
2645
        WORD *stopex1, *stopex2;
122,201,685✔
2646
        WORD c1, c2;
122,201,685✔
2647
        WORD prevorder;
122,201,685✔
2648
        WORD count = -1, localPoly, polyhit = -1;
122,201,685✔
2649

2650
#ifdef COUNTCOMPARES
2651
        if ( AR.sLevel == 0 ) {
2652
#ifdef WITHPTHREADS
2653
                numcompares[AT.identity]++;
2654
#else
2655
                numcompares[0]++;
2656
#endif
2657
        }
2658
#endif
2659

2660
        if ( S->PolyFlag ) {
122,201,685✔
2661
/*
2662
                if ( S->PolyWise != 0 ) {
2663
                        MLOCK(ErrorMessageLock);
2664
                        MesPrint("S->PolyWise is not zero!!!!!");
2665
                        MUNLOCK(ErrorMessageLock);
2666
                }
2667
*/
2668
                count = 0; localPoly = 1; S->PolyWise = polyhit = 0;
19,342,582✔
2669
                S->PolyFlag = AR.PolyFunType;
19,342,582✔
2670
                if ( AR.PolyFunType == 2 &&
19,342,582✔
2671
                         ( AR.PolyFunExp == 2 || AR.PolyFunExp == 3 ) ) S->PolyFlag = 1;
19,255,621✔
2672
        }
2673
        else { localPoly = 0; }
2674
#ifdef WITHFLOAT
2675
        AT.SortFloatMode = 0;
122,201,685✔
2676
#endif
2677
        prevorder = 0;
122,201,685✔
2678
        GETSTOP(term1,s1);
122,201,685✔
2679
        stopper1 = s1;
122,201,685✔
2680
        GETSTOP(term2,stopper2);
122,201,685✔
2681
        t1 = term1 + 1;
122,201,685✔
2682
        t2 = term2 + 1;
122,201,685✔
2683
        while ( t1 < stopper1 && t2 < stopper2 ) {
166,974,011✔
2684
                if ( *t1 != *t2 ) {
142,692,134✔
2685
                        if ( *t1 == HAAKJE ) return(PREV(-1));
397,102✔
2686
                        if ( *t2 == HAAKJE ) return(PREV(1));
372,594✔
2687
                        if ( *t1 >= (FUNCTION-1) ) {
369,327✔
2688
                                if ( *t2 < (FUNCTION-1) ) return(PREV(-1));
293,139✔
2689
                                if ( *t1 < FUNCTION && *t2 < FUNCTION ) return(PREV(*t2-*t1));
64,660✔
2690
                                if ( *t1 < FUNCTION ) return(PREV(1));
64,660✔
2691
                                if ( *t2 < FUNCTION ) return(PREV(-1));
64,660✔
2692
                                c1 = functions[*t1-FUNCTION].commute;
64,660✔
2693
                                c2 = functions[*t2-FUNCTION].commute;
64,660✔
2694
                                if ( !c1 ) {
64,660✔
2695
                                        if ( c2 ) return(PREV(1));
63,339✔
2696
                                        else return(PREV(*t2-*t1));
62,529✔
2697
                                }
2698
                                else {
2699
                                        if ( !c2 ) return(PREV(-1));
1,321✔
2700
                                        else return(PREV(*t2-*t1));
132✔
2701
                                }
2702
                        }
2703
                        else return(PREV(*t2-*t1));
76,188✔
2704
                }
2705
                s1 = t1 + 2;
142,295,032✔
2706
                s2 = t2 + 2;
142,295,032✔
2707
                c1 = *t1;
142,295,032✔
2708
                t1 += t1[1];
142,295,032✔
2709
                t2 += t2[1];
142,295,032✔
2710
                if ( localPoly && c1 < FUNCTION ) {
142,295,032✔
2711
                        polyhit = 1;
2712
                }
2713
                if ( c1 <= (FUNCTION-1)
121,030,331✔
2714
                || ( c1 >= FUNCTION && functions[c1-FUNCTION].spec > 0 ) ) {
57,990,732✔
2715
                        if ( c1 == SYMBOL ) {
84,687,309✔
2716
                                if ( *s1 == FACTORSYMBOL && *s2 == FACTORSYMBOL
42,898,055✔
2717
                                 && s1[-1] == 4 && s2[-1] == 4
5,191✔
2718
                                 && ( ( t1 < stopper1 && *t1 == HAAKJE )
5,191✔
2719
                                 || ( t1 == stopper1 && AT.fromindex ) ) ) {
×
2720
/*
2721
                                        We have to be very careful with the criteria here, because
2722
                                        Compare1 is called both in the regular sorting and by the
2723
                                        routine that makes the bracket index. In the last case
2724
                                        there is no HAAKJE subterm.
2725
*/
2726
                                        if ( s1[1] != s2[1] ) return(s2[1]-s1[1]);
5,191✔
2727
                                        s1 += 2; s2 += 2;
3,107✔
2728
                                }
2729
                                else if ( AR.SortType >= SORTPOWERFIRST ) {
42,892,864✔
2730
                                        WORD i1 = 0, *r1;
2731
                                        r1 = s1;
2732
                                        while ( s1 < t1 ) { i1 += s1[1]; s1 += 2; }
×
2733
                                        s1 = r1; r1 = s2;
×
2734
                                        while ( s2 < t2 ) { i1 -= s2[1]; s2 += 2; }
×
2735
                                        s2 = r1;
×
2736
                                        if ( i1 ) {
×
2737
                                                if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
×
2738
                                                return(PREV(i1));
×
2739
                                        }
2740
                                }
2741
                                while ( s1 < t1 ) {
74,151,674✔
2742
                                        if ( s2 >= t2 ) {
67,553,377✔
2743
/*                                                return(PREV(1));  */
2744
                                                if ( AR.SortType==SORTLOWFIRST ) {
90,230✔
2745
                                                        return(PREV((s1[1]>0?-1:1)));
103,500✔
2746
                                                }
2747
                                                else {
2748
                                                        return(PREV((s1[1]<0?-1:1)));
3,744✔
2749
                                                }
2750
                                        }
2751
                                        if ( *s1 != *s2 ) {
67,463,147✔
2752
/*                                                return(PREV(*s2-*s1)); */
2753
                                                if ( AR.SortType==SORTLOWFIRST ) {
3,855,410✔
2754
                                                        if ( *s1 < *s2 ) {
3,835,628✔
2755
                                                                return(PREV((s1[1]<0?1:-1)));
4,112,033✔
2756
                                                        }
2757
                                                        else {
2758
                                                                return(PREV((s2[1]<0?-1:1)));
3,259,787✔
2759
                                                        }
2760
                                                }
2761
                                                else {
2762
                                                        if ( *s1 < *s2 ) {
19,782✔
2763
                                                                return(PREV((s1[1]<0?-1:1)));
16,944✔
2764
                                                        }
2765
                                                        else {
2766
                                                                return(PREV((s2[1]<0?1:-1)));
22,620✔
2767
                                                        }
2768
                                                }
2769
                                        }
2770
                                        s1++; s2++;
63,607,737✔
2771
                                        if ( *s1 != *s2 ) return(
63,607,737✔
2772
                                                PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
32,352,034✔
2773
                                        s1++; s2++;
31,255,703✔
2774
                                }
2775
                                if ( s2 < t2 ) {
6,598,297✔
2776
/*                                        return(PREV(-1));  */
2777
                                        if ( AR.SortType==SORTLOWFIRST ) {
109,858✔
2778
                                                return(PREV((s2[1]<0?-1:1)));
203,374✔
2779
                                        }
2780
                                        else {
2781
                                                return(PREV((s2[1]<0?1:-1)));
264✔
2782
                                        }
2783
                                }
2784
                        }
2785
                        else if ( c1 == DOTPRODUCT ) {
41,789,254✔
2786
                                if ( AR.SortType >= SORTPOWERFIRST ) {
17,172,290✔
2787
                                        WORD i1 = 0, *r1;
2788
                                        r1 = s1;
2789
                                        while ( s1 < t1 ) { i1 += s1[2]; s1 += 3; }
×
2790
                                        s1 = r1; r1 = s2;
×
2791
                                        while ( s2 < t2 ) { i1 -= s2[2]; s2 += 3; }
×
2792
                                        s2 = r1;
×
2793
                                        if ( i1 ) {
×
2794
                                                if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
×
2795
                                                return(PREV(i1));
×
2796
                                        }
2797
                                }
2798
                                while ( s1 < t1 ) {
54,207,139✔
2799
                                        if ( s2 >= t2 ) return(PREV(1));
51,976,775✔
2800
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
51,910,266✔
2801
                                        s1++; s2++;
47,386,551✔
2802
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
47,386,551✔
2803
                                        s1++; s2++;
43,923,367✔
2804
                                        if ( *s1 != *s2 ) return(
43,923,367✔
2805
                                                PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
6,888,518✔
2806
                                        s1++; s2++;
37,034,849✔
2807
                                }
2808
                                if ( s2 < t2 ) return(PREV(-1));
2,230,364✔
2809
                        }
2810
                        else {
2811
                                while ( s1 < t1 ) {
188,981,754✔
2812
                                        if ( s2 >= t2 ) return(PREV(1));
187,121,075✔
2813
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
187,120,492✔
2814
                                        s1++; s2++;
164,364,790✔
2815
                                }
2816
                                if ( s2 < t2 ) return(PREV(-1));
1,860,679✔
2817
                        }
2818
                }
2819
                else {
2820
#if FUNHEAD != 2
2821
                        s1 += FUNHEAD-2;
57,607,723✔
2822
                        s2 += FUNHEAD-2;
57,607,723✔
2823
#endif
2824
                        if ( localPoly && c1 == AR.PolyFun ) {
57,607,723✔
2825
                                if ( count == 0 ) {
1,304,723✔
2826
                                  if ( S->PolyFlag == 1 ) {
1,304,723✔
2827
                                        WORD i1, i2;
18,509✔
2828
                                        if ( *s1 > 0 ) i1 = *s1;
18,509✔
2829
                                        else if ( *s1 <= -FUNCTION ) i1 = 1;
31✔
2830
                                        else i1 = 2;
31✔
2831
                                        if ( *s2 > 0 ) i2 = *s2;
18,509✔
2832
                                        else if ( *s2 <= -FUNCTION ) i2 = 1;
41✔
2833
                                        else i2 = 2;
41✔
2834
                                        if ( s1+i1 == t1 && s2+i2 == t2 ) {        /* This is the stuff */
18,509✔
2835
/*
2836
                                                Test for scalar nature
2837
*/
2838
                                                if ( !polyhit ) {
18,509✔
2839
                                                        WORD *u1, *u2, *ustop;
84✔
2840
                                                        if ( *s1 < 0 ) {
84✔
2841
                                                                if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
×
2842
                                                                        goto NoPoly;
×
2843
                                                        }
2844
                                                        else {
2845
                                                                u1 = s1 + ARGHEAD;
84✔
2846
                                                                while ( u1 < t1 ) {
522✔
2847
                                                                        u2 = u1 + *u1;
438✔
2848
                                                                        ustop = u2 - ABS(u2[-1]);
438✔
2849
                                                                        u1++;
438✔
2850
                                                                        while ( u1 < ustop ) {
870✔
2851
                                                                                if ( *u1 == INDEX ) goto NoPoly;
432✔
2852
                                                                                u1 += u1[1];
432✔
2853
                                                                        }
2854
                                                                        u1 = u2;
2855
                                                                }
2856
                                                        }
2857
                                                        if ( *s2 < 0 ) {
84✔
2858
                                                                if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
×
2859
                                                                        goto NoPoly;
×
2860
                                                        }
2861
                                                        else {
2862
                                                                u1 = s2 + ARGHEAD;
84✔
2863
                                                                while ( u1 < t2 ) {
516✔
2864
                                                                        u2 = u1 + *u1;
432✔
2865
                                                                        ustop = u2 - ABS(u2[-1]);
432✔
2866
                                                                        u1++;
432✔
2867
                                                                        while ( u1 < ustop ) {
858✔
2868
                                                                                if ( *u1 == INDEX ) goto NoPoly;
426✔
2869
                                                                                u1 += u1[1];
426✔
2870
                                                                        }
2871
                                                                        u1 = u2;
2872
                                                                }
2873
                                                        }
2874
                                                }
2875
                                                S->PolyWise = WORDDIF(s1,term1);
18,509✔
2876
                                                S->PolyWise -= FUNHEAD;
18,509✔
2877
                                                count = 1;
18,509✔
2878
                                                continue;
18,509✔
2879
                                        }
2880
                                        else {
2881
NoPoly:
×
2882
                                                S->PolyWise = localPoly = 0;
×
2883
                                        }
2884
                                  }
2885
                                  else if ( AR.PolyFunType == 2 ) {
1,286,214✔
2886
                                        WORD i1, i2, i1a, i2a;
1,286,214✔
2887
                                        if ( *s1 > 0 ) i1 = *s1;
1,286,214✔
2888
                                        else if ( *s1 <= -FUNCTION ) i1 = 1;
48,817✔
2889
                                        else i1 = 2;
48,817✔
2890
                                        if ( *s2 > 0 ) i2 = *s2;
1,286,214✔
2891
                                        else if ( *s2 <= -FUNCTION ) i2 = 1;
51,217✔
2892
                                        else i2 = 2;
51,217✔
2893
                                        if ( s1[i1] > 0 ) i1a = s1[i1];
1,286,214✔
2894
                                        else if ( s1[i1] <= -FUNCTION ) i1a = 1;
228,118✔
2895
                                        else i1a = 2;
228,118✔
2896
                                        if ( s2[i2] > 0 ) i2a = s2[i2];
1,286,214✔
2897
                                        else if ( s2[i2] <= -FUNCTION ) i2a = 1;
222,816✔
2898
                                        else i2a = 2;
222,816✔
2899
                                        if ( s1+i1+i1a == t1 && s2+i2+i2a == t2 ) {        /* This is the stuff */
1,286,214✔
2900
/*
2901
                                                Test for scalar nature
2902
*/
2903
                                                if ( !polyhit ) {
1,286,214✔
2904
                                                        WORD *u1, *u2, *ustop;
765,760✔
2905
                                                        if ( *s1 < 0 ) {
765,760✔
2906
                                                                if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
16,501✔
2907
                                                                        goto NoPoly;
×
2908
                                                        }
2909
                                                        else {
2910
                                                                u1 = s1 + ARGHEAD;
749,259✔
2911
                                                                while ( u1 < s1+i1 ) {
4,282,749✔
2912
                                                                        u2 = u1 + *u1;
3,533,490✔
2913
                                                                        ustop = u2 - ABS(u2[-1]);
3,533,490✔
2914
                                                                        u1++;
3,533,490✔
2915
                                                                        while ( u1 < ustop ) {
6,333,314✔
2916
                                                                                if ( *u1 == INDEX ) goto NoPoly;
2,799,824✔
2917
                                                                                u1 += u1[1];
2,799,824✔
2918
                                                                        }
2919
                                                                        u1 = u2;
2920
                                                                }
2921
                                                        }
2922
                                                        if ( s1[i1] < 0 ) {
765,760✔
2923
                                                                if ( s1[i1] != -SNUMBER && s1[i1] != -SYMBOL && s1[i1] > -FUNCTION )
21,474✔
2924
                                                                        goto NoPoly;
×
2925
                                                        }
2926
                                                        else {
2927
                                                                u1 = s1 +i1 + ARGHEAD;
744,286✔
2928
                                                                while ( u1 < t1 ) {
4,366,737✔
2929
                                                                        u2 = u1 + *u1;
3,622,451✔
2930
                                                                        ustop = u2 - ABS(u2[-1]);
3,622,451✔
2931
                                                                        u1++;
3,622,451✔
2932
                                                                        while ( u1 < ustop ) {
6,512,082✔
2933
                                                                                if ( *u1 == INDEX ) goto NoPoly;
2,889,631✔
2934
                                                                                u1 += u1[1];
2,889,631✔
2935
                                                                        }
2936
                                                                        u1 = u2;
2937
                                                                }
2938
                                                        }
2939
                                                        if ( *s2 < 0 ) {
765,760✔
2940
                                                                if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
21,383✔
2941
                                                                        goto NoPoly;
×
2942
                                                        }
2943
                                                        else {
2944
                                                                u1 = s2 + ARGHEAD;
744,377✔
2945
                                                                while ( u1 < s2+i2 ) {
4,327,181✔
2946
                                                                        u2 = u1 + *u1;
3,582,804✔
2947
                                                                        ustop = u2 - ABS(u2[-1]);
3,582,804✔
2948
                                                                        u1++;
3,582,804✔
2949
                                                                        while ( u1 < ustop ) {
6,432,758✔
2950
                                                                                if ( *u1 == INDEX ) goto NoPoly;
2,849,954✔
2951
                                                                                u1 += u1[1];
2,849,954✔
2952
                                                                        }
2953
                                                                        u1 = u2;
2954
                                                                }
2955
                                                        }
2956
                                                        if ( s2[i2] < 0 ) {
765,760✔
2957
                                                                if ( s2[i2] != -SNUMBER && s2[i2] != -SYMBOL && s2[i2] > -FUNCTION )
16,710✔
2958
                                                                        goto NoPoly;
×
2959
                                                        }
2960
                                                        else {
2961
                                                                u1 = s2 + i2 + ARGHEAD;
749,050✔
2962
                                                                while ( u1 < t2 ) {
4,692,444✔
2963
                                                                        u2 = u1 + *u1;
3,943,394✔
2964
                                                                        ustop = u2 - ABS(u2[-1]);
3,943,394✔
2965
                                                                        u1++;
3,943,394✔
2966
                                                                        while ( u1 < ustop ) {
7,153,152✔
2967
                                                                                if ( *u1 == INDEX ) goto NoPoly;
3,209,758✔
2968
                                                                                u1 += u1[1];
3,209,758✔
2969
                                                                        }
2970
                                                                        u1 = u2;
2971
                                                                }
2972
                                                        }
2973
                                                }
2974
                                                S->PolyWise = WORDDIF(s1,term1);
1,286,214✔
2975
                                                S->PolyWise -= FUNHEAD;
1,286,214✔
2976
                                                count = 1;
1,286,214✔
2977
                                                continue;
1,286,214✔
2978
                                        }
2979
                                        else {
2980
                                                S->PolyWise = localPoly = 0;
×
2981
                                        }
2982
                                  }
2983
                                  else {
2984
                                        S->PolyWise = localPoly = 0;
×
2985
                                  }
2986
                                }
2987
                                else {
2988
                                        t1 = term1 + S->PolyWise;
×
2989
                                        t2 = term2 + S->PolyWise;
×
2990
                                        S->PolyWise = 0;
×
2991
                                        localPoly = 0;
×
2992
                                        continue;
×
2993
                                }
2994
                        }
2995
#ifdef WITHFLOAT
2996
                        if ( level == 0 && c1 == FLOATFUN && t1 == stopper1 && t2 == stopper2 && AT.aux_ != 0 ) {
56,303,000✔
2997
/*
2998
                                We have two FLOATFUN's. Test whether they are 'legal'
2999
*/
3000
                                if ( TestFloat(s1-FUNHEAD) ) {
168✔
3001
                                        if ( TestFloat(s2-FUNHEAD) ) { AT.SortFloatMode = 3; return(0); }
168✔
3002
                                        else { return(1); }
3003
                                }
3004
                                else if ( TestFloat(s2-FUNHEAD) ) { return(-1); }
×
3005
                        }
3006
#endif
3007
                        while ( s1 < t1 ) {
98,147,942✔
3008
/*
3009
                                The next statement was added 9-nov-2001. It repaired a bad error
3010
*/
3011
                                if ( s2 >= t2 ) return(PREV(-1));
65,136,481✔
3012
/*
3013
                                There is a little problem here with fast arguments
3014
                                We don't want to sacrifice speed, but we like to
3015
                                keep a rational ordering. This last one suffers in
3016
                                the solution that has been chosen here.
3017
*/
3018
                                if ( AC.properorderflag ) {
65,133,151✔
3019
                                        WORD oldpolyflag;
×
3020
                                        oldpolyflag = S->PolyFlag;
×
3021
                                        S->PolyFlag = 0;
×
3022
                                        if ( ( c2 = -CompArg(s1,s2) ) != 0 ) {
×
3023
                                                S->PolyFlag = oldpolyflag; return(PREV(c2));
×
3024
                                        }
3025
                                        S->PolyFlag = oldpolyflag;
×
3026
                                        NEXTARG(s1)
×
3027
                                        NEXTARG(s2)
×
3028
                                }
3029
                                else {
3030
                                        if ( *s1 > 0 ) {
65,133,151✔
3031
                                                if ( *s2 > 0 ) {
417,858✔
3032
                                                        WORD oldpolyflag;
414,234✔
3033
                                                        stopex1 = s1 + *s1;
414,234✔
3034
                                                        if ( s2 >= t2 ) return(PREV(-1));
414,234✔
3035
                                                        stopex2 = s2 + *s2;
414,234✔
3036
                                                        s1 += ARGHEAD; s2 += ARGHEAD;
414,234✔
3037
                                                        oldpolyflag = S->PolyFlag;
414,234✔
3038
                                                        S->PolyFlag = 0;
414,234✔
3039
                                                        while ( s1 < stopex1 ) {
1,333,568✔
3040
                                                                if ( s2 >= stopex2 ) {
1,133,920✔
3041
                                                                        S->PolyFlag = oldpolyflag; return(PREV(-1));
3,170✔
3042
                                                                }
3043
                                                                if ( ( c2 = CompareTerms(BHEAD s1,s2,(WORD)1) ) != 0 ) {
1,130,750✔
3044
                                                                        S->PolyFlag = oldpolyflag; return(PREV(c2));
211,416✔
3045
                                                                }
3046
                                                                s1 += *s1;
919,334✔
3047
                                                                s2 += *s2;
919,334✔
3048
                                                        }
3049
                                                        S->PolyFlag = oldpolyflag;
199,648✔
3050
                                                        if ( s2 < stopex2 ) return(PREV(1));
199,648✔
3051
                                                }
3052
                                                else return(PREV(1));
3053
                                        }
3054
                                        else {
3055
                                                if ( *s2 > 0 ) return(PREV(-1));
64,715,293✔
3056
                                                if ( *s1 != *s2 ) { return(PREV(*s1-*s2)); }
64,711,203✔
3057
                                                if ( *s1 > -FUNCTION ) {
64,657,181✔
3058
                                                        if ( *++s1 != *++s2 ) { return(PREV(*s2-*s1)); }
64,634,563✔
3059
                                                }
3060
                                                s1++; s2++;
41,664,092✔
3061
                                        }
3062
                                }
3063
                        }
3064
                        if ( s2 < t2 ) return(PREV(1));
33,011,461✔
3065
                }
3066
        }
3067
#ifdef WITHFLOAT
3068
        if ( level == 0 && t1 < stopper1 && *t1 == FLOATFUN && t1+t1[1] == stopper1
24,281,877✔
3069
                        && TestFloat(t1) && AT.aux_ != 0 ) {
6✔
3070
                AT.SortFloatMode = 1; return(0);
×
3071
        }
3072
        else if ( level == 0 && t2 < stopper2 && *t2 == FLOATFUN && t2+t2[1] == stopper2
24,281,877✔
3073
                        && TestFloat(t2) && AT.aux_ != 0 ) {
6✔
3074
                AT.SortFloatMode = 2; return(0);
6✔
3075
        }
3076
#endif
3077
        {
3078
                if ( AR.SortType != SORTLOWFIRST ) {
24,281,871✔
3079
                        if ( t1 < stopper1 ) return(PREV(1));
4,554,432✔
3080
                        if ( t2 < stopper2 ) return(PREV(-1));
793,284✔
3081
                }
3082
                else {
3083
                        if ( t1 < stopper1 ) return(PREV(-1));
19,727,439✔
3084
                        if ( t2 < stopper2 ) return(PREV(1));
19,151,253✔
3085
                }
3086
        }
3087
        if ( level == 3 ) return(CompCoef(term1,term2));
17,390,149✔
3088
        if ( level >= 1 )
17,390,149✔
3089
                return(CompCoef(term2,term1));
947,239✔
3090
        return(0);
3091
}
3092

3093
/*
3094
                 #] Compare1 : 
3095
                 #[ CompareSymbols :                        WORD CompareSymbols(term1,term2,par)
3096
*/
3097
/**
3098
 *        Compares the terms, based on the value of AN.polysortflag.
3099
 *        If term1 < term2 the return value is -1
3100
 *        If term1 > term2 the return value is  1
3101
 *        If term1 = term2 the return value is  0
3102
 *        The coefficients may differ.
3103
 *        The terms contain only a single subterm of type SYMBOL.
3104
 *        If AN.polysortflag = 0 it is a 'regular' compare.
3105
 *        If AN.polysortflag = 1 the sum of the powers is more important
3106
 *        par is a dummy parameter to make the parameter field identical
3107
 *        to that of Compare1 which is the regular compare routine in sort.c
3108
 */
3109

3110
WORD CompareSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
11,695,791✔
3111
{
3112
        int sum1, sum2;
11,695,791✔
3113
        WORD *t1, *t2, *tt1, *tt2;
11,695,791✔
3114
        int low, high;
11,695,791✔
3115
        DUMMYUSE(par);
11,695,791✔
3116
        if ( AR.SortType == SORTLOWFIRST ) { low = 1; high = -1; }
11,695,791✔
3117
        else { low = -1; high = 1; }
11,396,436✔
3118
        t1 = term1 + 1; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); t1 += 2;
11,695,791✔
3119
        t2 = term2 + 1; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); t2 += 2;
11,695,791✔
3120
        if ( AN.polysortflag > 0 ) {
11,695,791✔
3121
                sum1 = 0; sum2 = 0;
×
3122
                while ( t1 < tt1 ) { sum1 += t1[1]; t1 += 2; }
×
3123
                while ( t2 < tt2 ) { sum2 += t2[1]; t2 += 2; }
×
3124
                if ( sum1 < sum2 ) return(low);
×
3125
                if ( sum1 > sum2 ) return(high);
×
3126
                t1 = term1+3; t2 = term2 + 3;
3127
        }
3128
        while ( t1 < tt1 && t2 < tt2 ) {
14,980,582✔
3129
                if ( *t1 > *t2 ) return(low);
10,269,517✔
3130
                if ( *t1 < *t2 ) return(high);
9,658,399✔
3131
                if ( t1[1] < t2[1] ) return(low);
9,460,554✔
3132
                if ( t1[1] > t2[1] ) return(high);
5,421,115✔
3133
                t1 += 2; t2 += 2;
3,284,791✔
3134
        }
3135
        if ( t1 < tt1 ) return(high);
4,711,065✔
3136
        if ( t2 < tt2 ) return(low);
1,111,752✔
3137
        return(0);
3138
}
3139

3140
/*
3141
                 #] CompareSymbols : 
3142
                 #[ CompareHSymbols :                WORD CompareHSymbols(term1,term2,par)
3143
*/
3144
/**
3145
 *        Compares terms that can have only SYMBOL and HAAKJE subterms.
3146
 *        If term1 < term2 the return value is -1
3147
 *        If term1 > term2 the return value is  1
3148
 *        If term1 = term2 the return value is  0
3149
 *        par is a dummy parameter to make the parameter field identical
3150
 *        to that of Compare1 which is the regular compare routine in sort.c
3151
 */
3152

3153
WORD CompareHSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
×
3154
{
3155
        WORD *t1, *t2, *tt1, *tt2, *ttt1, *ttt2;
×
3156
        DUMMYUSE(par);
×
3157
        DUMMYUSE(AT.WorkPointer);
×
3158
        t1 = term1 + 1; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); t1 += 2;
×
3159
        t2 = term2 + 1; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); t2 += 2;
×
3160
        while ( t1 < tt1 && t2 < tt2 ) {
×
3161
                if ( *t1 != *t2 ) {
×
3162
                        if ( t1[0] < t2[0] ) return(-1);
×
3163
                        return(1);
×
3164
                }
3165
                else if ( *t1 == HAAKJE ) {
×
3166
                        t1 += 3; t2 += 3; continue;
×
3167
                }
3168
                ttt1 = t1+t1[1]; ttt2 = t2+t2[1];
×
3169
                while ( t1 < ttt1 && t2 < ttt2 ) {
×
3170
                        if ( *t1 > *t2 ) return(-1);
×
3171
                        if ( *t1 < *t2 ) return(1);
×
3172
                        if ( t1[1] < t2[1] ) return(-1);
×
3173
                        if ( t1[1] > t2[1] ) return(1);
×
3174
                        t1 += 2; t2 += 2;
×
3175
                }
3176
                if ( t1 < ttt1 ) return(1);
×
3177
                if ( t2 < ttt2 ) return(-1);
×
3178
        }
3179
        if ( t1 < tt1 ) return(1);
×
3180
        if ( t2 < tt2 ) return(-1);
×
3181
        return(0);
3182
}
3183

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

3206
LONG ComPress(WORD **ss, LONG *n)
10,789✔
3207
{
3208
        GETIDENTITY
7,143✔
3209
        WORD *t, *s, j, k;
10,789✔
3210
        LONG size = 0;
10,789✔
3211
        int newsize, i;
10,789✔
3212
/*
3213
                        #[ debug :
3214

3215
        WORD **sss = ss;
3216

3217
        if ( AP.DebugFlag ) {
3218
                UBYTE OutBuf[140];
3219
                MLOCK(ErrorMessageLock);
3220
                MesPrint("ComPress:");
3221
                AO.OutFill = AO.OutputLine = OutBuf;
3222
                AO.OutSkip = 3;
3223
                FiniLine();
3224
                ss = sss;
3225
                while ( *ss ) {
3226
                        s = *ss++;
3227
                        j = *s;
3228
                        if ( j < 0 ) {
3229
                                j = s[1] + 2;
3230
                        }
3231
                        while ( --j >= 0 ) {
3232
                                TalToLine((UWORD)(*s++)); TokenToLine((UBYTE *)"  ");
3233
                        }
3234
                        FiniLine();
3235
                }
3236
                AO.OutSkip = 0;
3237
                FiniLine();
3238
                MUNLOCK(ErrorMessageLock);
3239
                ss = sss;
3240
        }
3241

3242
                        #] debug : 
3243
*/
3244
        *n = 0;
10,789✔
3245
        if ( AT.SS == AT.S0 && !AR.NoCompress ) {
10,789✔
3246
                if ( AN.compressSize == 0 ) {
9,557✔
3247
                        if ( *ss ) { AN.compressSize = **ss + 64; }
48✔
3248
                        else       { AN.compressSize = AM.MaxTer/sizeof(WORD) + 2; }
×
3249
                        AN.compressSpace = (WORD *)Malloc1(AN.compressSize*sizeof(WORD),"Compression");
48✔
3250
                }
3251
                AN.compressSpace[0] = 0;
9,557✔
3252
                while ( *ss ) {
1,522,455✔
3253
                        k = 0;
1,512,898✔
3254
                        s = *ss;
1,512,898✔
3255
                        j = *s++;
1,512,898✔
3256
                        if ( j > AN.compressSize ) {
1,512,898✔
3257
                                newsize = j + 64;
×
3258
                                t = (WORD *)Malloc1(newsize*sizeof(WORD),"Compression");
×
3259
                                t[0] = 0;
×
3260
                                if ( AN.compressSpace ) {
×
3261
                                        for ( i = 0; i < *AN.compressSpace; i++ ) t[i] = AN.compressSpace[i];
×
3262
                                        M_free(AN.compressSpace,"Compression");
×
3263
                                }
3264
                                AN.compressSpace = t;
×
3265
                                AN.compressSize = newsize;
×
3266
                        }
3267
                        t = AN.compressSpace;
1,512,898✔
3268
                        i = *t - 1;
1,512,898✔
3269
                        *t++ = j; j--;
1,512,898✔
3270
                        if ( AR.PolyFun ) {
1,512,898✔
3271
                                WORD *polystop, *sa;
×
3272
                                sa = s + j;
×
3273
                                sa -= ABS(sa[-1]);
×
3274
                                polystop = s;
×
3275
                                while ( polystop < sa && *polystop != AR.PolyFun ) {
×
3276
                                        polystop += polystop[1];
×
3277
                                }
3278
                                while ( i > 0 && j > 0 && *s == *t && s < polystop ) {
×
3279
                                        i--; j--; s++; t++; k--;
×
3280
                                }
3281
                        }
3282
                        else {
3283
                                WORD *sa;
1,512,898✔
3284
                                sa = s + j;
1,512,898✔
3285
                                sa -= ABS(sa[-1]);
1,512,898✔
3286
                                while ( i > 0 && j > 0 && *s == *t && s < sa ) { i--; j--; s++; t++; k--; }
8,003,604✔
3287
                        }
3288
                        if ( k < -1 ) {
1,512,898✔
3289
                                s[-1] = j;
1,480,088✔
3290
                                s[-2] = k;
1,480,088✔
3291
                                *ss = s-2;
1,480,088✔
3292
                                size += j + 2;
1,480,088✔
3293
                        }
3294
                        else {
3295
                                size += *AN.compressSpace;
32,810✔
3296
                                if ( k == -1 ) { t--; s--; j++; }
32,810✔
3297
                        }
3298
                        while ( --j >= 0 ) *t++ = *s++;
7,865,963✔
3299
/*                                        Sabotage getting into the coefficient next time */
3300
                        t = AN.compressSpace + *AN.compressSpace;
1,512,898✔
3301
                        t[-(ABS(t[-1]))] = 0;
1,512,898✔
3302
                        ss++;
1,512,898✔
3303
                        (*n)++;
1,512,898✔
3304
                }
3305
        }
3306
        else {
3307
                while ( *ss ) {
12,882,377✔
3308
                        size += *(*ss++);
12,881,145✔
3309
                        (*n)++;
12,881,145✔
3310
                }
3311
        }
3312
/*
3313
                        #[ debug :
3314

3315
        if ( AP.DebugFlag ) {
3316
                UBYTE OutBuf[140];
3317
                AO.OutFill = AO.OutputLine = OutBuf;
3318
                AO.OutSkip = 3;
3319
                FiniLine();
3320
                ss = sss;
3321
                while ( *ss ) {
3322
                        s = *ss++;
3323
                        j = *s;
3324
                        if ( j < 0 ) {
3325
                                j = s[1] + 2;
3326
                        }
3327
                        while ( --j >= 0 ) {
3328
                                TalToLine((UWORD)(*s++)); TokenToLine((UBYTE *)"  ");
3329
                        }
3330
                        FiniLine();
3331
                }
3332
                AO.OutSkip = 0;
3333
                FiniLine();
3334
        }
3335

3336
                        #] debug : 
3337
*/
3338
        return(size);
10,789✔
3339
}
3340

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

3370
#ifdef NEWSPLITMERGE
3371

3372
LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
68,709,730✔
3373
{
3374
        GETBIDENTITY
3375
        SORTING *S = AT.SS;
68,709,730✔
3376
        WORD **pp3, **pp1, **pp2, **pptop;
68,709,730✔
3377
        LONG i, newleft, newright, split;
68,709,730✔
3378

3379
#ifdef SPLITMERGEDEBUG
3380
        /* Print current array state on entry. */
3381
        printf("%4ld: ", number);
3382
        for (int ii = 0; ii < S->sTerms; ii++) {
3383
                if ( (S->sPointer)[ii] ) {
3384
                        printf("%4d ", (unsigned)(S->sPointer[ii]-S->sBuffer));
3385
                }
3386
                else {
3387
                        printf(".... ");
3388
                }
3389
        }
3390
        printf("\n");
3391
        fflush(stdout);
3392
#endif
3393

3394
        if ( number < 2 ) return(number);
68,709,730✔
3395
        if ( number == 2 ) {
57,776,364✔
3396
                pp1 = Pointer; pp2 = pp1 + 1;
31,039,911✔
3397
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
31,039,911✔
3398
                        pp3 = (WORD **)(*pp1); *pp1 = *pp2; *pp2 = (WORD *)pp3;
3,438,097✔
3399
                }
3400
                else if ( i == 0 ) {
27,601,814✔
3401
                        number--;
3,152,988✔
3402
                        if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) == 0 ) number = 0; }
3,152,988✔
3403
                        else               { if ( AddCoef(BHEAD pp1,pp2) == 0 ) number = 0; }
2,829,085✔
3404
                }
3405
                return(number);
31,039,911✔
3406
        }
3407
        pptop = Pointer + number;
26,736,453✔
3408
        split = number/2;
26,736,453✔
3409
        newleft  = SplitMerge(BHEAD Pointer,split);
26,736,453✔
3410
        newright = SplitMerge(BHEAD Pointer+split,number-split);
26,736,404✔
3411
        if ( newright == 0 ) return(newleft);
26,736,342✔
3412
/*
3413
        We compare the last of the left with the first of the right
3414
        If they are already in order, we will be done quickly.
3415
        We may have to compactify the buffer because the recursion may
3416
        have created holes. Also this compare may result in equal terms.
3417
        Addition of 23-jul-1999. It makes things a bit faster.
3418
*/
3419
        if ( newleft > 0 && newright > 0 &&
26,504,332✔
3420
        ( i = CompareTerms(BHEAD Pointer[newleft-1],Pointer[split],(WORD)0) ) >= 0 ) {
26,424,284✔
3421
                pp2 = Pointer+split; pp1 = Pointer+newleft-1;
21,460,191✔
3422
                if ( i == 0 ) {
21,460,191✔
3423
                        if ( S->PolyWise ) {
2,107,773✔
3424
                                if ( AddPoly(BHEAD pp1,pp2) > 0 ) pp1++;
452,792✔
3425
                                else newleft--;
371✔
3426
                        }
3427
                        else {
3428
                                if ( AddCoef(BHEAD pp1,pp2) > 0 ) pp1++;
1,654,981✔
3429
                                else newleft--;
247,536✔
3430
                        }
3431
                        *pp2++ = 0; newright--;
2,107,753✔
3432
                }
3433
                else pp1++;
19,352,418✔
3434
                newleft += newright;
21,460,171✔
3435
                if ( pp1 < pp2 ) {
21,460,171✔
3436
                        while ( --newright >= 0 ) *pp1++ = *pp2++;
3,427,137✔
3437
                        while ( pp1 < pptop ) *pp1++ = 0;
26,730,281✔
3438
                }
3439
                return(newleft);
21,460,171✔
3440
        }
3441

3442
        if ( split >= AN.SplitScratchSize ) {
5,044,141✔
3443
                AN.SplitScratchSize = (split*3)/2+100;
2,380✔
3444
                if ( AN.SplitScratchSize > S->Terms2InSmall/2 )
2,380✔
3445
                        AN.SplitScratchSize = S->Terms2InSmall/2;
20✔
3446
                if ( AN.SplitScratch ) M_free(AN.SplitScratch,"AN.SplitScratch");
2,380✔
3447
                AN.SplitScratch = (WORD **)Malloc1(AN.SplitScratchSize*sizeof(WORD *),"AN.SplitScratch");
2,380✔
3448
        }
3449

3450
        pp3 = AN.SplitScratch; pp1 = Pointer;
5,044,141✔
3451
        /* Move rather than copy, so GarbHand can't double-count. */
3452
        for ( i = 0; i < newleft; i++ ) { *pp3++ = *pp1; *pp1++ = 0; }
46,747,159✔
3453
        AN.InScratch = newleft;
5,044,141✔
3454
        pp1 = AN.SplitScratch; pp2 = Pointer + split; pp3 = Pointer;
5,044,141✔
3455

3456
#ifdef NEWSPLITMERGETIMSORT
3457
/*
3458
                An improvement in the style of Timsort
3459
*/
3460
        while ( newleft > 8 ) {
5,175,441✔
3461
                /* Check the middle of the LHS terms */
3462
                LONG nnleft = newleft/2;
913,223✔
3463
                if ( ( i = CompareTerms(BHEAD pp1[nnleft],*pp2,(WORD)0) ) < 0 ) {
913,223✔
3464
                        /* The terms are not in order. Break out and continue as normal. */
3465
                        break;
3466
                }
3467
                /* The terms merge or are in order. Copy pointers up to this point. */
3468
                /* In the copy, zero the skipped pointers so GarbHand can't double-count. */
3469
                for (int iii = 0; iii < nnleft; iii++) {
2,767,111✔
3470
                        *pp3++ = *pp1;
2,628,123✔
3471
                        *pp1++ = 0;
2,628,123✔
3472
                }
3473
                newleft -= nnleft;
138,988✔
3474
                if ( i == 0 ) {
138,988✔
3475
                        if ( S->PolyWise ) { i = AddPoly(BHEAD pp1,pp2); }
7,688✔
3476
                        else               { i = AddCoef(BHEAD pp1,pp2); }
7,159✔
3477
                        if ( i == 0 ) {
7,688✔
3478
                                /* The terms cancelled. The next term goes in *pp3. Don't move. */
3479
                        }
3480
                        else {
3481
                                /* The terms added. Advance pp3. */
3482
                                *pp3++ = *pp1;
7,684✔
3483
                        }
3484
                        /* We have taken a LHS (copy) and RHS term. */
3485
                        *pp2++ = 0;
7,688✔
3486
                        newright--;
7,688✔
3487
                        *pp1++ = 0;
7,688✔
3488
                        newleft--;
7,688✔
3489
                        break;
7,688✔
3490
                }
3491
        }
3492
#endif
3493

3494
        while ( newleft > 0 && newright > 0 ) {
57,695,300✔
3495
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
52,651,159✔
3496
                        *pp3++ = *pp2;
26,089,225✔
3497
                        *pp2++ = 0;
26,089,225✔
3498
                        newright--;
26,089,225✔
3499
                }
3500
                else if ( i > 0 ) {
26,561,934✔
3501
                        *pp3++ = *pp1;
16,043,998✔
3502
                        *pp1++ = 0;
16,043,998✔
3503
                        newleft--;
16,043,998✔
3504
                }
3505
                else {
3506
                        if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
10,517,936✔
3507
                        else {               if ( AddCoef(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
10,051,321✔
3508
                        *pp1++ = 0; *pp2++ = 0; newleft--; newright--;
10,517,936✔
3509
                }
3510
        }
3511
        for ( i = 0; i < newleft; i++ ) { *pp3++ = *pp1; *pp1++ = 0; }
17,549,414✔
3512
        if ( pp3 == pp2 ) {
5,044,141✔
3513
                pp3 += newright;
4,014,150✔
3514
        } else {
3515
                for ( i = 0; i < newright; i++ ) { *pp3++ = *pp2++; }
4,648,281✔
3516
        }
3517
        newleft = pp3 - Pointer;
5,044,141✔
3518
        while ( pp3 < pptop ) *pp3++ = 0;
81,870,616✔
3519
        AN.InScratch = 0;
5,044,141✔
3520
        return(newleft);
5,044,141✔
3521
}
3522

3523
#else
3524

3525
LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
3526
{
3527
        GETBIDENTITY
3528
        SORTING *S = AT.SS;
3529
        WORD **pp3, **pp1, **pp2;
3530
        LONG nleft, nright, i, newleft, newright;
3531
        WORD **pptop;
3532

3533
#ifdef SPLITMERGEDEBUG
3534
        /* Print current array state on entry. */
3535
        printf("%4ld: ", number);
3536
        for (int ii = 0; ii < S->sTerms; ii++) {
3537
                if ( (S->sPointer)[ii] ) {
3538
                        printf("%4d ", (unsigned)(S->sPointer[ii]-S->sBuffer));
3539
                }
3540
                else {
3541
                        printf(".... ");
3542
                }
3543
        }
3544
        printf("\n");
3545
        fflush(stdout);
3546
#endif
3547

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

3631
#endif
3632

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

3652
void GarbHand(void)
776✔
3653
{
3654
        GETIDENTITY
602✔
3655
        SORTING *S = AT.SS;
776✔
3656
        WORD **Point, *s2, *t, *garbuf, i;
776✔
3657
        LONG k, total = 0;
776✔
3658
        int tobereturned = 0;
776✔
3659
/*
3660
        Compute the size needed. Put it in total.
3661
*/
3662
#ifdef TESTGARB
3663
        MLOCK(ErrorMessageLock);
3664
        MesPrint("in:  S->sFill = %l, S->sTop2 = %l",S->sFill-S->sBuffer,S->sTop2-S->sBuffer);
3665
#endif
3666
        Point = S->sPointer;
776✔
3667
        k = S->sTerms;
776✔
3668
        while ( --k >= 0 ) {
15,851,842✔
3669
                if ( ( s2 = *Point++ ) != 0 ) { total += *s2; }
15,851,066✔
3670
        }
3671
        Point = AN.SplitScratch;
776✔
3672
        k = AN.InScratch;
776✔
3673
        while ( --k >= 0 ) {
776✔
3674
                if ( ( s2 = *Point++ ) != 0 ) { total += *s2; }
×
3675
        }
3676
#ifdef TESTGARB
3677
        MesPrint("total = %l, nterms = %l",total,AN.InScratch);
3678
        MUNLOCK(ErrorMessageLock);
3679
#endif
3680
/*
3681
        Test now whether it fits. If so deal with the problem inside
3682
        the memory at the tail of the large buffer.
3683
*/
3684
        if ( S->lBuffer != 0 && S->lFill + total <= S->lTop ) {
776✔
3685
                garbuf = S->lFill;
3686
        }
3687
        else {
3688
                garbuf = (WORD *)Malloc1(total*sizeof(WORD),"Garbage buffer");
×
3689
                tobereturned = 1;
×
3690
        }
3691
        t = garbuf;
776✔
3692
        Point = S->sPointer;
776✔
3693
        k = S->sTerms;
776✔
3694
        while ( --k >= 0 ) {
15,776,934✔
3695
                if ( *Point ) {
15,776,158✔
3696
                        s2 = *Point++;
5,566,880✔
3697
                        i = *s2;
5,566,880✔
3698
                        NCOPY(t,s2,i);
1,040,974,964✔
3699
                }
3700
                else { Point++; }
10,209,278✔
3701
        }
3702
        Point = AN.SplitScratch;
776✔
3703
        k = AN.InScratch;
776✔
3704
        while ( --k >= 0 ) {
776✔
3705
                if ( *Point ) {
×
3706
                        s2 = *Point++;
×
3707
                        i = *s2;
×
3708
                        NCOPY(t,s2,i);
×
3709
                }
3710
                else Point++;
×
3711
        }
3712
        s2 = S->sBuffer;
776✔
3713
        t = garbuf;
776✔
3714
        Point = S->sPointer;
776✔
3715
        k = S->sTerms;
776✔
3716
        while ( --k >= 0 ) {
15,734,276✔
3717
                if ( *Point ) {
15,733,500✔
3718
                        *Point++ = s2;
5,563,307✔
3719
                        i = *t;
5,563,307✔
3720
                        NCOPY(s2,t,i);
1,036,851,102✔
3721
                }
3722
                else { Point++; }
10,170,193✔
3723
        }
3724
        Point = AN.SplitScratch;
776✔
3725
        k = AN.InScratch;
776✔
3726
        while ( --k >= 0 ) {
776✔
3727
                if ( *Point ) {
×
3728
                        *Point++ = s2;
×
3729
                        i = *t;
×
3730
                        NCOPY(s2,t,i);
×
3731
                }
3732
                else Point++;
×
3733
        }
3734
        S->sFill = s2;
776✔
3735
#ifdef TESTGARB
3736
        MLOCK(ErrorMessageLock);
3737
        MesPrint("out: S->sFill = %l, S->sTop2 = %l",S->sFill-S->sBuffer,S->sTop2-S->sBuffer);
3738
        if ( S->sFill >= S->sTop2 ) {
3739
                MesPrint("We are in deep trouble");
3740
        }
3741
        MUNLOCK(ErrorMessageLock);
3742
#endif
3743
        if ( tobereturned ) M_free(garbuf,"Garbage buffer");
776✔
3744
        return;
776✔
3745
}
3746

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

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

3952
        The old code had to be replaced because all output needs to go
3953
        through PutOut. For this we have to go term by term and keep
3954
        track of the compression.
3955
*/
3956
        if ( S->lPatch == 1 ) {        /* Single patch --> direct copy. Very rare. */
2,885✔
3957
                LONG length;
12✔
3958

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

4096
                /* More than one patch. Construct the tree. */
4097

4098
                lpat = 1;
4099
                do { lpat *= 2; } while ( lpat < S->lPatch );
4,878✔
4100
                mpat = ( lpat >> 1 ) - 1;
2,873✔
4101
                k = lpat - S->lPatch;
2,873✔
4102

4103
                /* k is the number of empty places in the tree. they will
4104
                   be at the even positions from 2 to 2*k */
4105

4106
                for ( i = 1; i < lpat; i++ ) {
13,872✔
4107
                        S->tree[i] = -1;
10,999✔
4108
                }
4109
                for ( i = 1; i <= k; i++ ) {
3,470✔
4110
                        im = ( i * 2 ) - 1;
597✔
4111
                        poin[im] = S->Patches[i-1];
597✔
4112
                        poin2[im] = poin[im] + *(poin[im]);
597✔
4113
                        S->used[i] = im;
597✔
4114
                        S->ktoi[im] = i-1;
597✔
4115
                        S->tree[mpat+i] = 0;
597✔
4116
                        poin[im-1] = poin2[im-1] = 0;
597✔
4117
                }
4118
                for ( i = (k*2)+1; i <= lpat; i++ ) {
15,551✔
4119
                        S->used[i-k] = i;
12,678✔
4120
                        S->ktoi[i] = i-k-1;
12,678✔
4121
                        poin[i] = S->Patches[i-k-1];
12,678✔
4122
                        poin2[i] = poin[i] + *(poin[i]);
12,678✔
4123
                }
4124
/*
4125
                the array poin tells the position of the i-th element of the S->tree
4126
                'S->used' is a stack with the S->tree elements that need to be entered
4127
                into the S->tree. at the beginning this is S->lPatch. during the
4128
                sort there will be only very few elements.
4129
                poin2 is the next value of poin. it has to be determined
4130
                before the comparisons as the position or the size of the
4131
                term indicated by poin may change.
4132
                S->ktoi translates a S->tree element back to its stream number.
4133

4134
                start the sort
4135
*/
4136
                level = S->lPatch;
2,873✔
4137

4138
                /* introduce one term */
4139
OneTerm:
16,853,148✔
4140
                k = S->used[level];
16,856,021✔
4141
                i = k + lpat - 1;
16,856,021✔
4142
                if ( !*(poin[k]) ) {
16,856,021✔
4143
                        do { if ( !( i >>= 1 ) ) goto EndOfMerge; } while ( !S->tree[i] );
24,274✔
4144
                        if ( S->tree[i] == -1 ) {
10,402✔
4145
                                S->tree[i] = 0;
52✔
4146
                                level--;
52✔
4147
                                goto OneTerm;
52✔
4148
                        }
4149
                        k = S->tree[i];
10,350✔
4150
                        S->used[level] = k;
10,350✔
4151
                        S->tree[i] = 0;
10,350✔
4152
                }
4153
/*
4154
                move terms down the tree
4155
*/
4156
                while ( i >>= 1 ) {
43,162,823✔
4157
                        if ( S->tree[i] > 0 ) {
26,692,979✔
4158
                                if ( ( c = CompareTerms(BHEAD poin[S->tree[i]],poin[k],(WORD)0) ) > 0 ) {
16,555,177✔
4159
/*
4160
                                        S->tree[i] is the smaller. Exchange and go on.
4161
*/
4162
                                        S->used[level] = S->tree[i];
125,011✔
4163
                                        S->tree[i] = k;
125,011✔
4164
                                        k = S->used[level];
125,011✔
4165
                                }
4166
                                else if ( !c ) {        /* Terms are equal */
16,430,166✔
4167
                                        S->TermsLeft--;
216,010✔
4168
/*
4169
                                                Here the terms are equal and their coefficients
4170
                                                have to be added.
4171
*/
4172
                                        l1 = *( m1 = poin[S->tree[i]] );
216,010✔
4173
                                        l2 = *( m2 = poin[k] );
216,010✔
4174
                                        if ( S->PolyWise ) {  /* Here we work with PolyFun */
216,010✔
4175
                                                WORD *tt1, *w;
×
4176
                                                tt1 = m1;
×
4177
                                                m1 += S->PolyWise;
×
4178
                                                m2 += S->PolyWise;
×
4179
                                                if ( S->PolyFlag == 2 ) {
×
4180
                                                        w = poly_ratfun_add(BHEAD m1,m2);
×
4181
                                                        if ( *tt1 + w[1] - m1[1] > AM.MaxTer/((LONG)sizeof(WORD)) ) {
×
4182
                                                                MLOCK(ErrorMessageLock);
×
4183
                                                                MesPrint("Term too complex in PolyRatFun addition. MaxTermSize of %10l is too small",AM.MaxTer);
×
4184
                                                                MUNLOCK(ErrorMessageLock);
×
4185
                                                                Terminate(-1);
×
4186
                                                        }
4187
                                                        AT.WorkPointer = w;
×
4188
                                                }
4189
                                                else {
4190
                                                        w = AT.WorkPointer;
×
4191
                                                        if ( w + m1[1] + m2[1] > AT.WorkTop ) {
×
4192
                                                                MLOCK(ErrorMessageLock);
×
4193
                                                                MesPrint("A WorkSpace of %10l is too small",AM.WorkSize);
×
4194
                                                                MUNLOCK(ErrorMessageLock);
×
4195
                                                                Terminate(-1);
×
4196
                                                        }
4197
                                                        AddArgs(BHEAD m1,m2,w);
×
4198
                                                }
4199
                                                r1 = w[1];
×
4200
                                                if ( r1 <= FUNHEAD
×
4201
                                                        || ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) )
×
4202
                                                                 { goto cancelled; }
×
4203
                                                if ( r1 == m1[1] ) {
×
4204
                                                        NCOPY(m1,w,r1);
×
4205
                                                }
4206
                                                else if ( r1 < m1[1] ) {
×
4207
                                                        r2 = m1[1] - r1;
×
4208
                                                        m2 = w + r1;
×
4209
                                                        m1 += m1[1];
×
4210
                                                        while ( --r1 >= 0 ) *--m1 = *--m2;
×
4211
                                                        m2 = m1 - r2;
×
4212
                                                        r1 = S->PolyWise;
×
4213
                                                        while ( --r1 >= 0 ) *--m1 = *--m2;
×
4214
                                                        *m1 -= r2;
×
4215
                                                        poin[S->tree[i]] = m1;
×
4216
                                                }
4217
                                                else {
4218
                                                        r2 = r1 - m1[1];
×
4219
                                                        m2 = tt1 - r2;
×
4220
                                                        r1 = S->PolyWise;
×
4221
                                                        m1 = tt1;
×
4222
                                                        *m1 += r2;
×
4223
                                                        poin[S->tree[i]] = m2;
×
4224
                                                        NCOPY(m2,m1,r1);
×
4225
                                                        r1 = w[1];
×
4226
                                                        NCOPY(m2,w,r1);
×
4227
                                                }
4228
                                        }
4229
#ifdef WITHFLOAT
4230
                                        else if ( AT.SortFloatMode ) {
216,010✔
4231
                                                WORD *term1, *term2;
×
4232
                                                term1 = poin[S->tree[i]];
×
4233
                                                term2 = poin[k];
×
4234
                                                if ( MergeWithFloat(BHEAD &term1,&term2) == 0 )
×
4235
                                                        goto cancelled;
×
4236
                                                poin[S->tree[i]] = term1;
×
4237
                                        }
4238
#endif
4239
                                        else {
4240
                                          r1 = *( m1 += l1 - 1 );
216,010✔
4241
                                          m1 -= ABS(r1) - 1;
216,010✔
4242
                                          r1 = ( ( r1 > 0 ) ? (r1-1) : (r1+1) ) >> 1;
216,010✔
4243
                                          r2 = *( m2 += l2 - 1 );
216,010✔
4244
                                          m2 -= ABS(r2) - 1;
216,010✔
4245
                                          r2 = ( ( r2 > 0 ) ? (r2-1) : (r2+1) ) >> 1;
216,010✔
4246

4247
                                          if ( AddRat(BHEAD (UWORD *)m1,r1,(UWORD *)m2,r2,coef,&r3) ) {
216,010✔
4248
                                                MLOCK(ErrorMessageLock);
×
4249
                                                MesCall("MergePatches");
×
4250
                                                MUNLOCK(ErrorMessageLock);
×
4251
                                                SETERROR(-1)
×
4252
                                          }
4253

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

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

4537
/*
4538
                 #] MergePatches : 
4539
                 #[ StoreTerm :                                WORD StoreTerm(term)
4540
*/
4541
/**
4542
 *        The central routine to accept terms, store them and keep things
4543
 *        at least partially sorted. A call to EndSort will then complete
4544
 *        storing and sorting.
4545
 *
4546
 *        @param term The term to be stored
4547
 *        @return  Regular return conventions (OK -> 0)
4548
 */
4549

4550
int StoreTerm(PHEAD WORD *term)
72,840,743✔
4551
{
4552
        GETBIDENTITY
4553
        SORTING *S = AT.SS;
72,840,743✔
4554
        WORD **ss, *lfill, j, *t;
72,840,743✔
4555
        POSITION pp;
72,840,743✔
4556
        LONG lSpace, sSpace, RetCode, over, tover;
72,840,743✔
4557

4558
        if ( ( ( AP.PreDebug & DUMPTOSORT ) == DUMPTOSORT ) && AR.sLevel == 0 ) {
72,840,743✔
4559
#ifdef WITHPTHREADS
4560
                snprintf((char *)(THRbuf),100,"StoreTerm(%d)",AT.identity);
4561
                PrintTerm(term,(char *)(THRbuf));
4562
#else
4563
                PrintTerm(term,"StoreTerm");
4564
#endif
4565
        }
4566
        if ( AM.exitflag && AR.sLevel == 0 ) return(0);
72,840,743✔
4567
        S->sFill = *(S->PoinFill);
72,840,743✔
4568
        if ( S->sTerms >= S->TermsInSmall || ( S->sFill + *term ) >= S->sTop ) {
72,840,743✔
4569
/*
4570
        The small buffer is full. It has to be sorted and written.
4571
*/
4572
                tover = over = S->sTerms;
10,480✔
4573
                ss = S->sPointer;
10,480✔
4574
                ss[over] = 0;
10,480✔
4575
#ifdef SPLITTIME
4576
                PrintTime((UBYTE *)"Before SplitMerge");
4577
#endif
4578
                ss[SplitMerge(BHEAD ss,over)] = 0;
10,480✔
4579
#ifdef SPLITTIME
4580
                PrintTime((UBYTE *)"After SplitMerge");
4581
#endif
4582
                sSpace = 0;
10,480✔
4583
                if ( over > 0 ) {
10,480✔
4584
                        sSpace = ComPress(ss,&RetCode);
10,480✔
4585
                        S->TermsLeft -= over - RetCode;
10,480✔
4586
                }
4587
                sSpace++;
10,480✔
4588

4589
                lSpace = sSpace + (S->lFill - S->lBuffer)
10,480✔
4590
                                 - (AM.MaxTer/sizeof(WORD))*((LONG)S->lPatch);
10,480✔
4591
                SETBASEPOSITION(pp,lSpace);
10,480✔
4592
                MULPOS(pp,sizeof(WORD));
10,480✔
4593
                if ( S->file.handle >= 0 ) {
10,480✔
4594
                        ADD2POS(pp,S->fPatches[S->fPatchN]);
9,008✔
4595
                }
4596
                if ( S == AT.S0 ) {        /* Only statistics at ground level */
10,480✔
4597
                        WriteStats(&pp,STATSSPLITMERGE,CHECKLOGTYPE);
9,469✔
4598
                }
4599
                if ( ( S->lPatch >= S->MaxPatches ) ||
10,480✔
4600
                        ( ( (WORD *)(((UBYTE *)(S->lFill + sSpace)) + 2*AM.MaxTer ) ) >= S->lTop ) ) {
8,405✔
4601
/*
4602
                        The large buffer is too full. Merge and write it
4603
*/
4604
                        if ( MergePatches(1) ) goto StoreCall;
2,077✔
4605
/*
4606
                        pp = S->SizeInFile[1];
4607
                        ADDPOS(pp,sSpace);
4608
                        MULPOS(pp,sizeof(WORD));
4609
*/
4610
                        SETBASEPOSITION(pp,sSpace);
2,071✔
4611
                        MULPOS(pp,sizeof(WORD));
2,071✔
4612
                        ADD2POS(pp,S->fPatches[S->fPatchN]);
2,071✔
4613

4614
                        if ( S == AT.S0 ) {        /* Only statistics at ground level */
2,071✔
4615
                                WriteStats(&pp,STATSMERGETOFILE,CHECKLOGTYPE);
2,011✔
4616
                        }
4617
                        S->lPatch = 0;
2,071✔
4618
                        S->lFill = S->lBuffer;
2,071✔
4619
                }
4620
                S->Patches[S->lPatch++] = S->lFill;
10,474✔
4621
            lfill = (WORD *)(((UBYTE *)(S->lFill)) + AM.MaxTer);
10,474✔
4622
                if ( tover > 0 ) {
10,474✔
4623
                        ss = S->sPointer;
10,474✔
4624
                        while ( ( t = *ss++ ) != 0 ) {
12,378,164✔
4625
                                j = *t;
12,367,690✔
4626
                                if ( j < 0 ) j = t[1] + 2;
12,367,690✔
4627
                                while ( --j >= 0 ){
256,101,869✔
4628
                                  *lfill++ = *t++;
243,734,179✔
4629
                                }
4630
                        }
4631
                }
4632
                *lfill++ = 0;
10,474✔
4633
                S->lFill = lfill;
10,474✔
4634
                S->sTerms = 0;
10,474✔
4635
                S->PoinFill = S->sPointer;
10,474✔
4636
                *(S->PoinFill) = S->sFill = S->sBuffer;
10,474✔
4637
        }
4638
        j = *term;
72,840,737✔
4639
        while ( --j >= 0 ) *S->sFill++ = *term++;
1,307,648,143✔
4640
        S->sTerms++;
72,840,737✔
4641
        S->GenTerms++;
72,840,737✔
4642
        S->TermsLeft++;
72,840,737✔
4643
        *++S->PoinFill = S->sFill;
72,840,737✔
4644

4645
        return(0);
72,840,737✔
4646

4647
StoreCall:
×
4648
        MLOCK(ErrorMessageLock);
×
4649
        MesCall("StoreTerm");
×
4650
        MUNLOCK(ErrorMessageLock);
×
4651
        SETERROR(-1)
×
4652
}
4653

4654
/*
4655
                 #] StoreTerm : 
4656
                 #[ StageSort :                                void StageSort(FILEHANDLE *fout)
4657
*/
4658
/**
4659
 *                Prepares a stage 4 or higher sort.
4660
 *                Stage 4 sorts occur when the sort file contains more patches than
4661
 *                can be merged in one pass.
4662
 */
4663

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

4722
                if ( AR.FoStage4[0].PObuffer == 0 ) {
341✔
4723
                        AR.FoStage4[0].PObuffer = (WORD *)Malloc1(AR.FoStage4[0].POsize*sizeof(WORD)
28✔
4724
                                                                                                ,"Stage 4 buffer");
4725
                        AR.FoStage4[0].POfill   = AR.FoStage4[0].PObuffer;
28✔
4726
                        AR.FoStage4[0].POstop   = AR.FoStage4[0].PObuffer
28✔
4727
                                                 + AR.FoStage4[0].POsize/sizeof(WORD);
28✔
4728
#ifdef WITHPTHREADS
4729
                        AR.FoStage4[0].pthreadslock = dummylock;
24✔
4730
#endif
4731
                }
4732
                if ( AR.FoStage4[1].PObuffer == 0 ) {
341✔
4733
                        AR.FoStage4[1].PObuffer = (WORD *)Malloc1(AR.FoStage4[1].POsize*sizeof(WORD)
28✔
4734
                                                                                                ,"Stage 4 buffer");
4735
                        AR.FoStage4[1].POfill   = AR.FoStage4[1].PObuffer;
28✔
4736
                        AR.FoStage4[1].POstop   = AR.FoStage4[1].PObuffer
28✔
4737
                                                 + AR.FoStage4[1].POsize/sizeof(WORD);
28✔
4738
#ifdef WITHPTHREADS
4739
                        AR.FoStage4[1].pthreadslock = dummylock;
24✔
4740
#endif
4741
                }
4742
                S->stage4 = 1;
341✔
4743
        }
4744
}
2,613✔
4745

4746
/*
4747
                 #] StageSort : 
4748
                 #[ SortWild :                                WORD SortWild(w,nw)
4749
*/
4750
/**
4751
 *        Sorts the wildcard entries in the parameter w. Double entries
4752
 *        are removed. Full space taken is nw words.
4753
 *        Routine serves for the reading of wildcards in the compiler.
4754
 *        The entries come in the format:
4755
 *        (type,4,number,0) in which the zero is reserved for the
4756
 *        future replacement of 'number'.
4757
 *
4758
 *        @param w  buffer with wildcard entries.
4759
 *        @param nw number of wildcard entries.
4760
 *        @return  Normal conventions (OK -> 0)
4761
 */
4762

4763
int SortWild(WORD *w, WORD nw)
227,004✔
4764
{
4765
        GETIDENTITY
151,336✔
4766
        WORD *v, *s, *m, k, i;
227,004✔
4767
        WORD *pScrat, *stop, *sv;
227,004✔
4768
        int error = 0;
227,004✔
4769
        pScrat = AT.WorkPointer;
227,004✔
4770
        if ( ( AT.WorkPointer + 8 * AM.MaxWildcards ) >= AT.WorkTop ) {
227,004✔
4771
                MLOCK(ErrorMessageLock);
×
4772
                MesWork();
×
4773
                MUNLOCK(ErrorMessageLock);
×
4774
                return(-1);
×
4775
        }
4776
        stop = w + nw;
227,004✔
4777
        i = 0;
227,004✔
4778
        while ( i < nw ) {
1,454,892✔
4779
                m = w + i;
1,227,888✔
4780
                v = m + m[1];
1,227,888✔
4781
                while ( v < stop && (
2,123,112✔
4782
                         *v == FROMSET || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
1,932,246✔
4783
                while ( v < stop ) {
8,555,670✔
4784
                        if ( *v >= 0 ) {
7,327,782✔
4785
                                if ( AM.Ordering[*v] < AM.Ordering[*m] ) {
6,196,944✔
4786
                                        m = v;
4787
                                }
4788
                                else if ( *v == *m ) {
6,136,854✔
4789
                                        if ( v[2] < m[2] ) {
5,989,356✔
4790
                                                m = v;
4791
                                        }
4792
                                        else if ( v[2] == m[2] ) {
5,875,296✔
4793
                                                s = m + m[1];
196,038✔
4794
                                                sv = v + v[1];
196,038✔
4795
                                                if ( s < stop && ( *s == FROMSET
196,038✔
4796
                                                 || *s == SETTONUM || *s == LOADDOLLAR ) ) {
196,038✔
4797
                                                        if ( sv < stop && ( *sv == FROMSET
179,736✔
4798
                                                        || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
179,736✔
4799
                                                                if ( s[2] != sv[2] ) {
179,736✔
4800
                                                                        error = -1;
×
4801
                                                                        MLOCK(ErrorMessageLock);
×
4802
                                                                        MesPrint("&Wildcard set conflict");
×
4803
                                                                        MUNLOCK(ErrorMessageLock);
59,912✔
4804
                                                                }
4805
                                                        }
4806
                                                        *v = -1;
179,736✔
4807
                                                }
4808
                                                else {
4809
                                                        if ( sv < stop && ( *sv == FROMSET
16,302✔
4810
                                                        || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
12,870✔
4811
                                                                *m = -1;
×
4812
                                                                m = v;
×
4813
                                                        }
4814
                                                        else {
4815
                                                                *v = -1;
16,302✔
4816
                                                        }
4817
                                                }
4818
                                        }
4819
                                }
4820
                        }
4821
                        v += v[1];
7,327,782✔
4822
                        while ( v < stop && ( *v == FROMSET
13,520,022✔
4823
                         || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
12,483,000✔
4824
                }
4825
                s = pScrat;
1,227,888✔
4826
                v = m;
1,227,888✔
4827
                k = m[1];
1,227,888✔
4828
                NCOPY(s,m,k);
6,139,440✔
4829
                while ( m < stop && ( *m == FROMSET
4,046,184✔
4830
                 || *m == SETTONUM || *m == LOADDOLLAR ) ) {
1,921,710✔
4831
                        k = m[1];
896,586✔
4832
                        NCOPY(s,m,k);
5,710,818✔
4833
                }
4834
                *v = -1;
1,227,888✔
4835
                pScrat = s;
1,227,888✔
4836
                i = 0;
1,227,888✔
4837
                while ( i < nw && ( w[i] < 0 || w[i] == FROMSET
12,883,824✔
4838
                || w[i] == SETTONUM || w[i] == LOADDOLLAR ) ) i += w[i+1];
12,656,820✔
4839
        }
4840
        AC.NwildC = k = WORDDIF(pScrat,AT.WorkPointer);
227,004✔
4841
        s = AT.WorkPointer;
227,004✔
4842
        m = w;
227,004✔
4843
        NCOPY(m,s,k);
8,724,900✔
4844
        AC.WildC = m;
227,004✔
4845
        return(error);
227,004✔
4846
}
4847

4848
/*
4849
                 #] SortWild : 
4850
                 #[ CleanUpSort :                        void CleanUpSort(num)
4851
*/
4852
/**
4853
 *                Partially or completely frees function sort buffers.
4854
 */
4855

4856
void CleanUpSort(int num)
34,614✔
4857
{
4858
        GETIDENTITY
23,084✔
4859
        SORTING *S;
34,614✔
4860
        int minnum = num, i;
34,614✔
4861
        if ( AN.FunSorts ) {
34,614✔
4862
                if ( num == -1 ) {
34,350✔
4863
                        if ( AN.MaxFunSorts > 3 ) {
32,130✔
4864
                                minnum = (AN.MaxFunSorts+4)/2;
30,110✔
4865
                        }
4866
                        else minnum = 4;
4867
                }
4868
                else if ( minnum == 0 ) minnum = 1;
2,220✔
4869
                for ( i = minnum; i < AN.NumFunSorts; i++ ) {
3,338,610✔
4870
                        S = AN.FunSorts[i];
3,304,260✔
4871
                        if ( S ) {
3,304,260✔
4872
                                if ( S->file.handle >= 0 ) {
1,717✔
4873
/*                                        TruncateFile(S->file.handle); */
4874
                                        UpdateMaxSize();
6✔
4875
#ifdef WITHZLIB
4876
                                        ClearSortGZIP(&(S->file));
6✔
4877
#endif
4878
                                        CloseFile(S->file.handle);
6✔
4879
                                        S->file.handle = -1;
6✔
4880
                                        remove(S->file.name);
6✔
4881
#ifdef GZIPDEBUG
4882
                                        MLOCK(ErrorMessageLock);
4883
                                        MesPrint("%w CleanUpSort removed file %s",S->file.name);
4884
                                        MUNLOCK(ErrorMessageLock);
4885
#endif
4886
                                }
4887
                                M_free(S->sPointer, "CleanUpSort: sPointer");
1,717✔
4888
                                M_free(S->Patches, "CleanUpSort: Patches");
1,717✔
4889
                                M_free(S->pStop, "CleanUpSort: pStop");
1,717✔
4890
                                M_free(S->poina, "CleanUpSort: poina");
1,717✔
4891
                                M_free(S->poin2a, "CleanUpSort: poin2a");
1,717✔
4892
                                M_free(S->fPatches, "CleanUpSort: fPatches");
1,717✔
4893
                                M_free(S->fPatchesStop, "CleanUpSort: fPatchesStop");
1,717✔
4894
                                M_free(S->inPatches, "CleanUpSort: inPatches");
1,717✔
4895
                                M_free(S->tree, "CleanUpSort: tree");
1,717✔
4896
                                M_free(S->used, "CleanUpSort: used");
1,717✔
4897
#ifdef WITHZLIB
4898
                                M_free(S->fpcompressed, "CleanUpSort: fpcompressed");
1,717✔
4899
                                M_free(S->fpincompressed, "CleanUpSort: fpincompressed");
1,717✔
4900
#endif
4901
                                M_free(S->ktoi, "CleanUpSort: ktoi");
1,717✔
4902
                                M_free(S->lBuffer, "CleanUpSort: lBuffer+sBuffer");
1,717✔
4903
                                M_free(S->file.PObuffer, "CleanUpSort: PObuffer");
1,717✔
4904
                                M_free(S, "CleanUpSort: sorting struct");
1,717✔
4905
                        }
4906
                        AN.FunSorts[i] = 0;
3,304,260✔
4907
                }
4908
                AN.MaxFunSorts = minnum;
34,350✔
4909
                if ( num == 0 ) {
34,350✔
4910
                        S = AN.FunSorts[0];
2,220✔
4911
                        if ( S ) {
2,220✔
4912
                                if ( S->file.handle >= 0 ) {
2,220✔
4913
/*                                        TruncateFile(S->file.handle); */
4914
                                        UpdateMaxSize();
×
4915
#ifdef WITHZLIB
4916
                                        ClearSortGZIP(&(S->file));
×
4917
#endif
4918
                                        CloseFile(S->file.handle);
×
4919
                                        S->file.handle = -1;
×
4920
                                        remove(S->file.name);
×
4921
#ifdef GZIPDEBUG
4922
                                        MLOCK(ErrorMessageLock);
4923
                                        MesPrint("%w CleanUpSort removed file %s",S->file.name);
4924
                                        MUNLOCK(ErrorMessageLock);
4925
#endif
4926
                                }
4927
                        }
4928
                }
4929
        }
4930
        for ( i = 0; i < 2; i++ ) {
103,842✔
4931
                if ( AR.FoStage4[i].handle >= 0 ) {
69,228✔
4932
                        UpdateMaxSize();
×
4933
#ifdef WITHZLIB
4934
                        ClearSortGZIP(&(AR.FoStage4[i]));
×
4935
#endif
4936
                        CloseFile(AR.FoStage4[i].handle);
×
4937
                        remove(AR.FoStage4[i].name);
×
4938
                        AR.FoStage4[i].handle = -1;
×
4939
#ifdef GZIPDEBUG
4940
                        MLOCK(ErrorMessageLock);
4941
                        MesPrint("%w CleanUpSort removed stage4 file %s",AR.FoStage4[i].name);
4942
                        MUNLOCK(ErrorMessageLock);
4943
#endif
4944
                }
4945
        }
4946
}
34,614✔
4947

4948
/*
4949
                 #] CleanUpSort : 
4950
                 #[ LowerSortLevel :         void LowerSortLevel()
4951
*/
4952
/**
4953
 *                Lowers the level in the sort system.
4954
 */
4955

4956
void LowerSortLevel(void)
450,346✔
4957
{
4958
        GETIDENTITY
300,232✔
4959
        if ( AR.sLevel >= 0 ) {
450,346✔
4960
                AR.sLevel--;
450,346✔
4961
                if ( AR.sLevel >= 0 ) AT.SS = AN.FunSorts[AR.sLevel];
450,346✔
4962
        }
4963
}
450,346✔
4964

4965
/*
4966
                 #] LowerSortLevel : 
4967
                 #[ PolyRatFunSpecial :
4968

4969
                Keeps only the most divergent term in AR.PolyFunVar
4970
                We assume that the terms are already in that notation.
4971
*/
4972

4973
WORD *PolyRatFunSpecial(PHEAD WORD *t1, WORD *t2)
×
4974
{
4975
        WORD *oldworkpointer = AT.WorkPointer, *t, *r;
×
4976
        WORD exp1, exp2;
×
4977
        int i;
×
4978
        t = t1+FUNHEAD;
×
4979
        if ( *t == -SYMBOL ) {
×
4980
                if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
4981
                exp1 = 1;
×
4982
                if ( t[2] != -SNUMBER ) goto Illegal;
×
4983
                t[3] = 1;
×
4984
        }
4985
        else if ( *t == -SNUMBER ) {
×
4986
                t[1] = 1;
×
4987
                t += 2;
×
4988
                if ( *t == -SYMBOL ) {
×
4989
                        if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
4990
                        exp1 = -1;
4991
                }
4992
                else if ( *t == -SNUMBER ) {
×
4993
                        t[1] = 1;
×
4994
                        exp1 = 0;
×
4995
                }
4996
                else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
4997
                        && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
4998
                        t[ARGHEAD+5] = 1;
×
4999
                        t[ARGHEAD+6] = 1;
×
5000
                        t[ARGHEAD+7] = 3;
×
5001
                        exp1 = -t[ARGHEAD+4];
×
5002
                }
5003
                else goto Illegal;
×
5004
        }
5005
        else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
5006
                && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
5007
                t[ARGHEAD+5] = 1;
×
5008
                t[ARGHEAD+6] = 1;
×
5009
                t[ARGHEAD+7] = 3;
×
5010
                exp1 = t[ARGHEAD+4];
×
5011
                t += *t;
×
5012
                if ( *t != -SNUMBER ) goto Illegal;
×
5013
                t[1] = 1;
×
5014
        }
5015
        else goto Illegal;
×
5016

5017
        t = t2+FUNHEAD;
×
5018
        if ( *t == -SYMBOL ) {
×
5019
                if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
5020
                exp2 = 1;
×
5021
                if ( t[2] != -SNUMBER ) goto Illegal;
×
5022
                t[3] = 1;
×
5023
        }
5024
        else if ( *t == -SNUMBER ) {
×
5025
                t[1] = 1;
×
5026
                t += 2;
×
5027
                if ( *t == -SYMBOL ) {
×
5028
                        if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
5029
                        exp2 = -1;
5030
                }
5031
                else if ( *t == -SNUMBER ) {
×
5032
                        t[1] = 1;
×
5033
                        exp2 = 0;
×
5034
                }
5035
                else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
5036
                        && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
5037
                        t[ARGHEAD+5] = 1;
×
5038
                        t[ARGHEAD+6] = 1;
×
5039
                        t[ARGHEAD+7] = 3;
×
5040
                        exp2 = -t[ARGHEAD+4];
×
5041
                }
5042
                else goto Illegal;
×
5043
        }
5044
        else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
5045
                && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
5046
                t[ARGHEAD+5] = 1;
×
5047
                t[ARGHEAD+6] = 1;
×
5048
                t[ARGHEAD+7] = 3;
×
5049
                exp2 = t[ARGHEAD+4];
×
5050
                t += *t;
×
5051
                if ( *t != -SNUMBER ) goto Illegal;
×
5052
                t[1] = 1;
×
5053
        }
5054
        else goto Illegal;
×
5055

5056
        if ( exp1 <= exp2 ) { i = t1[1]; r = t1; }
×
5057
        else                { i = t2[1]; r = t2; }
×
5058
        t = oldworkpointer;
5059
        NCOPY(t,r,i)
×
5060

5061
        return(oldworkpointer);
5062
Illegal:
×
5063
        MesPrint("Illegal occurrence of PolyRatFun with divergent option");
×
5064
        Terminate(-1);
×
5065
        return(0);
×
5066
}
5067

5068
/*
5069
                 #] PolyRatFunSpecial : 
5070
                 #[ SimpleSplitMerge :
5071

5072
                Sorts an array of WORDs. No adding of equal objects.
5073
*/
5074

5075
void SimpleSplitMergeRec(WORD *array,WORD num,WORD *auxarray)
×
5076
{
5077
        WORD n1,n2,i,j,k,*t1,*t2;
×
5078
        if ( num < 2 ) return;
×
5079
        if ( num == 2 ) {
×
5080
                if ( array[0] > array[1] ) {
×
5081
                        EXCH(array[0],array[1])
×
5082
                }
5083
                return;
×
5084
        }
5085
        n1 = num/2;
×
5086
        n2 = num - n1;
×
5087
        SimpleSplitMergeRec(array,n1,auxarray);
×
5088
        SimpleSplitMergeRec(array+n1,n2,auxarray);
×
5089
        if ( array[n1-1] <= array[n1] ) return;
×
5090

5091
        t1 = array; t2 = auxarray; i = n1; NCOPY(t2,t1,i);
×
5092
        i = 0; j = n1; k = 0;
5093
        while ( i < n1 && j < num ) {
×
5094
                if ( auxarray[i] <= array[j] ) { array[k++] = auxarray[i++]; }
×
5095
                else { array[k++] = array[j++]; }
×
5096
        }
5097
        while ( i < n1 ) array[k++] = auxarray[i++];
×
5098
/*
5099
        Remember: remnants of j are still in place!
5100
*/
5101
}
5102

5103
void SimpleSplitMerge(WORD *array,WORD num)
×
5104
{
5105
        WORD *auxarray = Malloc1(sizeof(WORD)*num/2,"SimpleSplitMerge");
×
5106
        SimpleSplitMergeRec(array,num,auxarray);
×
5107
        M_free(auxarray,"SimpleSplitMerge");
×
5108
}
×
5109

5110
/*
5111
                 #] SimpleSplitMerge : 
5112
                 #[ BinarySearch :
5113

5114
                Searches in the sorted array with length num for the object x.
5115
                If x is in the list, it returns the number of the array element
5116
                that matched. If it is not in the list, it returns -1.
5117
                If there are identical objects in the list, which one will
5118
                match is quasi random.
5119
*/
5120

5121
WORD BinarySearch(WORD *array,WORD num,WORD x)
×
5122
{
5123
        WORD i, bot, top, med;
×
5124
        if ( num < 8 ) {
×
5125
                for ( i = 0; i < num; i++ ) if ( array[i] == x ) return(i);
×
5126
                return(-1);
5127
        }
5128
        if ( array[0] > x || array[num-1] < x ) return(-1);
×
5129
        bot = 0; top = num-1; med = (top+bot)/2;
×
5130
        do {
×
5131
                if ( array[med] == x ) return(med);
×
5132
                if ( array[med] < x ) { bot = med+1; }
×
5133
                else { top = med-1; }
×
5134
                med = (top+bot)/2;
×
5135
        } while ( med >= bot && med <= top );
×
5136
        return(-1);
5137
}
5138

5139
/*
5140
                 #] BinarySearch : 
5141
        #] SortUtilities :
5142
*/
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