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

tueda / form / 12516247166

27 Dec 2024 12:47PM UTC coverage: 50.678% (-0.05%) from 50.724%
12516247166

push

github

tueda
debug

42035 of 82946 relevant lines covered (50.68%)

1401654.15 hits per line

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

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

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

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

61
#include "form3.h"
62

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

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

75
LONG numcompares;
76

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

85
/**
86
 *                Writes the statistics.
87
 *
88
 *                @param plspace The size in bytes currently occupied
89
 *                @param par
90
 *                par = 0 = STATSSPLITMERGE after a splitmerge.
91
 *                par = 1 = STATSMERGETOFILE after merge to sortfile.
92
 *                par = 2 = STATSPOSTSORT after the sort
93
 *                @param checkLogType == CHECKLOGTYPE: The output should not
94
 *                go to the log file if AM.LogType is 1.
95
 *
96
 *                current expression is to be found in AR.CurExpr.
97
 *                terms are in S->TermsLeft.
98
 *                S->GenTerms.
99
 */
100

101
VOID WriteStats(POSITION *plspace, WORD par, WORD checkLogType)
12,207✔
102
{
103
        GETIDENTITY
6,636✔
104
        LONG millitime, y = 0x7FFFFFFFL >> 1;
12,207✔
105
        WORD timepart;
12,207✔
106
        SORTING *S;
12,207✔
107
        POSITION pp;
12,207✔
108
        int use_wtime;
12,207✔
109
        if ( AT.SS == AT.S0 && AC.StatsFlag ) {
12,207✔
110
#ifdef WITHPTHREADS
111
                if ( AC.ThreadStats == 0 && identity > 0 ) return;
3,740✔
112
#elif defined(WITHMPI)
113
                if ( AC.OldParallelStats ) return;
829✔
114
                if ( ! AC.ProcessStats && PF.me != MASTER ) return;
829✔
115
#endif
116
                if ( Expressions == 0 ) return;
6,447✔
117

118
                if ( par == STATSSPLITMERGE ) {
6,447✔
119
                        if ( AC.ShortStatsMax == 0 ) return;
2,832✔
120
                        AR.ShortSortCount++;
×
121
                        if ( AR.ShortSortCount < AC.ShortStatsMax ) return;
×
122
                }
123
                AR.ShortSortCount = 0;
3,615✔
124

125
                S = AT.SS;
3,615✔
126

127
                MLOCK(ErrorMessageLock);
3,615✔
128

129
                /* If the statistics should not go to the log file, temporarily hide the
130
                 * LogHandle. This must be done within the ErrorMessageLock region to
131
                 * avoid a data race between threads. */
132
                const WORD oldLogHandle = AC.LogHandle;
3,615✔
133
                if ( checkLogType && AM.LogType ) {
3,615✔
134
                        AC.LogHandle = -1;
181✔
135
                }
136

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

596
                MUNLOCK(ErrorMessageLock);
6,479✔
597
        }
598
}
599

600
/*
601
                 #] WriteStats : 
602
                 #[ NewSort :                                WORD NewSort()
603
*/
604
/**
605
 *                Starts a new sort.
606
 *                At the lowest level this is a 'main sort' with the struct according
607
 *                to the parameters in S0. At higher levels this is a sort for
608
 *                functions, subroutines or dollars.
609
 *                We prepare the arrays and structs.
610
 *
611
 *                @return Regular convention (OK -> 0)
612
 */
613

614
WORD NewSort(PHEAD0)
5,390,430✔
615
{
616
        GETBIDENTITY
617
        SORTING *S, **newFS;
5,390,430✔
618
        int i, newsize;
5,390,430✔
619
        if ( AN.SoScratC == 0 )
5,390,430✔
620
                AN.SoScratC = (UWORD *)Malloc1(2*(AM.MaxTal+2)*sizeof(UWORD),"NewSort");
2,794✔
621
        AR.sLevel++;
5,390,430✔
622
        if ( AR.sLevel >= AN.NumFunSorts ) {
5,390,430✔
623
                if ( AN.NumFunSorts == 0 ) newsize = 100;
3,334✔
624
                else newsize = 2*AN.NumFunSorts;
×
625
                newFS = (SORTING **)Malloc1((newsize+1)*sizeof(SORTING *),"FunSort pointers");
3,334✔
626
                for ( i = 0; i < AN.NumFunSorts; i++ ) newFS[i] = AN.FunSorts[i];
6,668✔
627
                for ( ; i <= newsize; i++ ) newFS[i] = 0;
340,068✔
628
                if ( AN.FunSorts ) M_free(AN.FunSorts,"FunSort pointers");
3,334✔
629
                AN.FunSorts = newFS; AN.NumFunSorts = newsize;
3,334✔
630
        }
631
        if ( AR.sLevel == 0 ) {
5,390,430✔
632

633
                numcompares = 0;
37,941✔
634

635
                AN.FunSorts[0] = AT.S0;
37,941✔
636
                if ( AR.PolyFun == 0 ) { AT.S0->PolyFlag = 0; }
37,941✔
637
                else if ( AR.PolyFunType == 1 ) { AT.S0->PolyFlag = 1; }
13,695✔
638
                else if ( AR.PolyFunType == 2 ) {
13,617✔
639
                        if ( AR.PolyFunExp == 2
13,617✔
640
                          || AR.PolyFunExp == 3 ) AT.S0->PolyFlag = 1;
13,617✔
641
                        else                      AT.S0->PolyFlag = 2;
13,363✔
642
                }
643
                AR.ShortSortCount = 0;
37,941✔
644
        }
645
        else {
646
                if ( AN.FunSorts[AR.sLevel] == 0 ) {
5,352,500✔
647
                        AN.FunSorts[AR.sLevel] = AllocSort(
1,546✔
648
                                AM.SLargeSize,AM.SSmallSize,AM.SSmallEsize,AM.STermsInSmall
649
                                        ,AM.SMaxPatches,AM.SMaxFpatches,AM.SIOsize,1);
650
                }
651
                AN.FunSorts[AR.sLevel]->PolyFlag = 0;
5,352,500✔
652
        }
653
        AT.SS = S = AN.FunSorts[AR.sLevel];
5,390,430✔
654
        S->sFill = S->sBuffer;
5,390,430✔
655
        S->lFill = S->lBuffer;
5,390,430✔
656
        S->lPatch = 0;
5,390,430✔
657
        S->fPatchN = 0;
5,390,430✔
658
        S->GenTerms = S->TermsLeft = S->GenSpace = S->SpaceLeft = 0;
5,390,430✔
659
        S->PoinFill = S->sPointer;
5,390,430✔
660
        *S->PoinFill = S->sFill;
5,390,430✔
661
        if ( AR.sLevel > 0 ) { S->PolyWise = 0; }
5,390,430✔
662
        PUTZERO(S->SizeInFile[0]); PUTZERO(S->SizeInFile[1]); PUTZERO(S->SizeInFile[2]);
5,390,430✔
663
        S->sTerms = 0;
5,390,430✔
664
        PUTZERO(S->file.POposition);
5,390,430✔
665
        S->stage4 = 0;
5,390,430✔
666
        if ( AR.sLevel > AN.MaxFunSorts ) AN.MaxFunSorts = AR.sLevel;
5,390,430✔
667
/*
668
        The next variable is for the staged sort only.
669
        It should be treated differently
670

671
        PUTZERO(AN.OldPosOut);
672
*/
673
        return(0);
5,390,430✔
674
}
675

676
/*
677
                 #] NewSort : 
678
                 #[ EndSort :                                WORD EndSort(PHEAD buffer,par)
679
*/
680
/**
681
 *                Finishes a sort.
682
 *                At AR.sLevel == 0 the output is to the regular output stream.
683
 *                When AR.sLevel > 0, the parameter par determines the actual output.
684
 *                The AR.sLevel will be popped.
685
 *                All ongoing stages are finished and if the sortfile is open
686
 *                it is closed.
687
 *                The statistics are printed when AR.sLevel == 0
688
 *                par == 0  Output to the buffer.
689
 *                par == 1  Sort for function arguments.
690
 *                          The output will be copied into the buffer.
691
 *                          It is assumed that this is in the WorkSpace.
692
 *                par == 2  Sort for $-variable. We return the address of the buffer
693
 *                          that contains the output in buffer (treated like WORD **).
694
 *                          We first catch the output in a file (unless we can
695
 *                          intercept things after the small buffer has been sorted)
696
 *                          Then we read from the file into a buffer.
697
 *                Only when par == 0 data compression can be attempted at AT.SS==AT.S0.
698
 *
699
 *                @param buffer buffer for output when needed
700
 *                @param par    See above
701
 *                @return If negative: error. If positive: number of words in output.
702
 */
703

704
LONG EndSort(PHEAD WORD *buffer, int par)
5,376,060✔
705
{
706
  GETBIDENTITY
707
  SORTING *S = AT.SS;
5,376,060✔
708
  WORD j, **ss, *to, *t;
5,376,060✔
709
  LONG sSpace, over, tover, spare, retval = 0, jj;
5,376,060✔
710
  POSITION position, pp;
5,376,060✔
711
  off_t lSpace;
5,376,060✔
712
  FILEHANDLE *fout = 0, *oldoutfile = 0, *newout = 0;
5,376,060✔
713

714
  if ( AM.exitflag && AR.sLevel == 0 ) return(0);
5,376,060✔
715
#ifdef WITHMPI 
716
  if( (retval = PF_EndSort()) > 0){
1,108,830✔
717
        oldoutfile = AR.outfile;
2,092✔
718
        retval = 0;
2,092✔
719
        goto RetRetval;
2,092✔
720
  } 
721
  else if(retval < 0){
1,106,740✔
722
        retval = -1; 
723
        goto RetRetval; 
724
  }
725
        /* PF_EndSort returned 0: for S != AM.S0 and slaves still do the regular sort */
726
#endif /* WITHMPI */
727
        oldoutfile = AR.outfile;
5,373,970✔
728
/*                PolyFlag repair action
729
        if ( S == AT.S0 ) {
730
                if ( AR.PolyFun == 0 ) { S->PolyFlag = 0; }
731
                else if ( AR.PolyFunType == 1 ) { S->PolyFlag = 1; }
732
                else if ( AR.PolyFunType == 2 ) {
733
                        if ( AR.PolyFunExp == 2
734
                          || AR.PolyFunExp == 3 ) S->PolyFlag = 1;
735
                        else                      S->PolyFlag = 2;
736
                }
737
                S->PolyWise = 0;
738
        }
739
        else {
740
                S->PolyFlag = S->PolyWise = 0;
741
        }
742
*/
743
        S->PolyWise = 0;
5,373,970✔
744
        *(S->PoinFill) = 0;
5,373,970✔
745
#ifdef SPLITTIME
746
                PrintTime((UBYTE *)"EndSort, before SplitMerge");
747
#endif
748
        S->sPointer[SplitMerge(BHEAD S->sPointer,S->sTerms)] = 0;
5,373,970✔
749
#ifdef SPLITTIME
750
                PrintTime((UBYTE *)"Endsort,  after SplitMerge");
751
#endif
752
        sSpace = 0;
5,373,960✔
753
        tover = over = S->sTerms;
5,373,960✔
754
        ss = S->sPointer;
5,373,960✔
755
        if ( over >= 0 ) {
5,373,960✔
756
                if ( S->lPatch > 0 || S->file.handle >= 0 ) {
5,373,960✔
757
                        ss[over] = 0;
177✔
758
                        sSpace = ComPress(ss,&spare);
177✔
759
                        S->TermsLeft -= over - spare;
177✔
760
                        if ( par == 1 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
177✔
761
                }
762
                else if ( S != AT.S0 ) {
5,373,770✔
763
                        ss[over] = 0;
5,352,370✔
764
                        if ( par == 2 ) {
5,352,370✔
765
                                sSpace = 3;
766
                                while ( ( t = *ss++ ) != 0 ) { sSpace += *t; }
119,373✔
767
                                if ( AN.tryterm > 0 && ( (sSpace+1)*sizeof(WORD) < (size_t)(AM.MaxTer) ) ) {
26,817✔
768
                                        to = TermMalloc("$-sort space");
2,472✔
769
                                }
770
                                else {
771
                                        LONG allocsp = sSpace+1;
24,345✔
772
                                        if ( allocsp < MINALLOC ) allocsp = MINALLOC;
24,345✔
773
                                        allocsp = ((allocsp+7)/8)*8;
24,345✔
774
                                        to = (WORD *)Malloc1(allocsp*sizeof(WORD),"$-sort space");
24,345✔
775
                                        if ( AN.tryterm > 0 ) AN.tryterm = 0;
24,345✔
776
                                }
777
                                *((WORD **)buffer) = to;
26,817✔
778
                                ss = S->sPointer;
26,817✔
779
                                while ( ( t = *ss++ ) != 0 ) {
119,373✔
780
                                        j = *t; while ( --j >= 0 ) *to++ = *t++;
11,728,590✔
781
                                }
782
                                *to = 0;
26,817✔
783
                                retval = sSpace + 1;
26,817✔
784
                        }
785
                        else {
786
                                to = buffer;
787
                                sSpace = 0;
788
                                while ( ( t = *ss++ ) != 0 ) {
16,018,310✔
789
                                        j = *t;
10,692,760✔
790
                                        if ( ( sSpace += j ) > AM.MaxTer/((LONG)sizeof(WORD)) ) {
10,692,760✔
791
                                                MLOCK(ErrorMessageLock);
×
792
                                                MesPrint("Sorted function argument too long.");
×
793
                                                MUNLOCK(ErrorMessageLock);
×
794
                                                retval = -1; goto RetRetval;
×
795
                                        }
796
                                        while ( --j >= 0 ) *to++ = *t++;
77,285,000✔
797
                                }
798
                                *to = 0;
5,325,560✔
799
                        }
800
                        goto RetRetval;
5,352,370✔
801
                }
802
                else {
803
                        POSITION oldpos;
21,411✔
804
                        if ( S == AT.S0 ) {
21,411✔
805
                                fout = AR.outfile;
21,411✔
806
                                *AR.CompressPointer = 0;
21,411✔
807
                                SeekScratch(AR.outfile,&position);
21,411✔
808
                        }
809
                        else {
810
                                fout = &(S->file);
811
                                PUTZERO(position);
812
                        }
813
                        oldpos = position;
21,411✔
814
                        S->TermsLeft = 0;
21,411✔
815
/*
816
                        Here we can go directly to the output.
817
*/
818
#ifdef WITHZLIB
819
                        { int oldgzipCompress = AR.gzipCompress;
21,411✔
820
                                AR.gzipCompress = 0;
21,411✔
821
#endif
822
                        if ( tover > 0 ) {
21,411✔
823
                                ss = S->sPointer;
9,418✔
824
                                while ( ( t = *ss++ ) != 0 ) {
747,568✔
825
                                        if ( *t ) S->TermsLeft++;
738,150✔
826
#ifdef WITHPTHREADS
827
                                        if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD t); }
357,276✔
828
                                        else
829
#endif
830
                                        if ( PutOut(BHEAD t,&position,fout,1) < 0 ) {
384,074✔
831
                                                retval = -1; goto RetRetval;
×
832
                                        }
833
                                }
834
                        }
835
#ifdef WITHPTHREADS
836
                        if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD 0); }
12,912✔
837
                        else
838
#endif
839
                        if ( FlushOut(&position,fout,1) ) {
8,565✔
840
                                retval = -1; goto RetRetval;
×
841
                        }
842
#ifdef WITHZLIB
843
                                AR.gzipCompress = oldgzipCompress;
21,411✔
844
                        }
845
#endif
846
#ifdef WITHPTHREADS
847
                        if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
12,912✔
848
#endif
849
#ifdef WITHMPI
850
                        if ( PF.me != MASTER && PF.exprtodo < 0 ) goto RetRetval;
6,310✔
851
#endif
852
                        DIFPOS(oldpos,position,oldpos);
2,299✔
853
                        S->SpaceLeft = BASEPOSITION(oldpos);
2,299✔
854
                        WriteStats(&oldpos,STATSPOSTSORT,NOCHECKLOGTYPE);
2,299✔
855
                        pp = oldpos;
2,299✔
856
                        goto RetRetval;
2,299✔
857
                }
858
        }
859
        else if ( par == 1 && newout == 0 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
×
860
        sSpace++;
177✔
861
        lSpace = sSpace + (S->lFill - S->lBuffer) - (LONG)S->lPatch*(AM.MaxTer/sizeof(WORD));
177✔
862
/*         Note wrt MaxTer and lPatch: each patch starts with space for decompression */
863
/*         Not needed if only large buffer, but needed when using files (?) */
864
        SETBASEPOSITION(pp,lSpace);
177✔
865
        MULPOS(pp,sizeof(WORD));
177✔
866
        if ( S->file.handle >= 0 ) {
177✔
867
                ADD2POS(pp,S->fPatches[S->fPatchN]);
20✔
868
        }
869
        if ( S == AT.S0 ) {
177✔
870
                if ( S->lPatch > 0 || S->file.handle >= 0 ) {
48✔
871
                        WriteStats(&pp,STATSSPLITMERGE,CHECKLOGTYPE);
48✔
872
                }
873
        }
874
        if ( par == 2 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
177✔
875
        if ( S->lPatch > 0 ) {
177✔
876
                if ( ( S->lPatch >= S->MaxPatches ) ||
177✔
877
                        ( ( (WORD *)(((UBYTE *)(S->lFill + sSpace)) + 2*AM.MaxTer) ) >= S->lTop ) ) {
176✔
878
/*
879
                        The large buffer is too full. Merge and write it
880
*/
881
#ifdef GZIPDEBUG
882
                        MLOCK(ErrorMessageLock);
883
                        MesPrint("%w EndSort: lPatch = %d, MaxPatches = %d,lFill = %x, sSpace = %ld, MaxTer = %d, lTop = %x"
884
                                        ,S->lPatch,S->MaxPatches,S->lFill,sSpace,AM.MaxTer/sizeof(WORD),S->lTop);
885
                        MUNLOCK(ErrorMessageLock);
886
#endif
887

888
                        if ( MergePatches(1) ) {
3✔
889
                                MLOCK(ErrorMessageLock);
×
890
                                MesCall("EndSort");
×
891
                                MUNLOCK(ErrorMessageLock);
×
892
                                retval = -1; goto RetRetval;
×
893
                        }
894
                        S->lPatch = 0;
3✔
895
                        pp = S->SizeInFile[1];
3✔
896
                        MULPOS(pp,sizeof(WORD));
3✔
897
#ifndef WITHPTHREADS
898
                        if ( S == AT.S0 )
2✔
899
#endif
900
                        {
1✔
901
                                POSITION pppp;
3✔
902
                                SETBASEPOSITION(pppp,0);
3✔
903
                                SeekFile(S->file.handle,&pppp,SEEK_CUR);
3✔
904
                                SeekFile(S->file.handle,&pp,SEEK_END);
3✔
905
                                SeekFile(S->file.handle,&pppp,SEEK_SET);
3✔
906
                                WriteStats(&pp,STATSMERGETOFILE,CHECKLOGTYPE);
3✔
907
                                UpdateMaxSize();
3✔
908
                        }
909
                }
910
                else {
911
                        S->Patches[S->lPatch++] = S->lFill;
174✔
912
                    to = (WORD *)(((UBYTE *)(S->lFill)) + AM.MaxTer);
174✔
913
                        if ( tover > 0 ) {
174✔
914
                                ss = S->sPointer;
174✔
915
                                while ( ( t = *ss++ ) != 0 ) {
1,355,503✔
916
                                        j = *t;
1,355,329✔
917
                                        if ( j < 0 ) j = t[1] + 2;
1,355,329✔
918
                                        while ( --j >= 0 ) *to++ = *t++;
30,379,650✔
919
                                }
920
                        }
921
                        *to++ = 0;
174✔
922
                        S->lFill = to;
174✔
923
                        if ( S->file.handle < 0 ) {
174✔
924
                                if ( MergePatches(2) ) {
155✔
925
                                        MLOCK(ErrorMessageLock);
×
926
                                        MesCall("EndSort");
×
927
                                        MUNLOCK(ErrorMessageLock);
×
928
                                        retval = -1; goto RetRetval;
×
929
                                }
930
                                if ( S == AT.S0 ) {
155✔
931
                                        pp = S->SizeInFile[2];
32✔
932
                                        MULPOS(pp,sizeof(WORD));
32✔
933
#ifdef WITHPTHREADS
934
                                        if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
20✔
935
#endif
936
                                        WriteStats(&pp,STATSPOSTSORT,NOCHECKLOGTYPE);
32✔
937
                                        UpdateMaxSize();
32✔
938
                                }
939
                                else {
940
                                        if ( par == 2 && newout->handle >= 0 ) {
123✔
941
                                                POSITION zeropos;
×
942
                                                PUTZERO(zeropos);
×
943
#ifdef ALLLOCK
944
                                                LOCK(newout->pthreadslock);
945
#endif
946
                                                SeekFile(newout->handle,&zeropos,SEEK_SET);
×
947
                                                to = (WORD *)Malloc1(BASEPOSITION(newout->filesize)+sizeof(WORD)*2
×
948
                                                                ,"$-buffer reading");
949
                                                if ( AN.tryterm > 0 ) AN.tryterm = 0;
×
950
                                                if ( ( retval = ReadFile(newout->handle,(UBYTE *)to,BASEPOSITION(newout->filesize)) ) !=
×
951
                                                                BASEPOSITION(newout->filesize) ) {
×
952
                                                        MLOCK(ErrorMessageLock);
×
953
                                                        MesPrint("Error reading information for $ variable");
×
954
                                                        MUNLOCK(ErrorMessageLock);
×
955
                                                        M_free(to,"$-buffer reading");
×
956
                                                        retval = -1;
×
957
                                                }
958
                                                else {
959
                                                        *((WORD **)buffer) = to;
×
960
                                                        retval /= sizeof(WORD);
×
961
                                                }
962
#ifdef ALLLOCK
963
                                                UNLOCK(newout->pthreadslock);
964
#endif
965
                                        }
966
                                        else if ( newout->handle >= 0 ) {
123✔
967
/*
968
                                                We land here if par == 1 (function arg sort) and PutOut has created a file.
969
                                                This means that the term is larger than SIOsize, which we ensure is at least
970
                                                as large as MaxTermSize in setfile.c. Thus we know already that the term won't fit.
971
*/
972
TooLarge:
×
973
                                                MLOCK(ErrorMessageLock);
×
974
                                                MesPrint("(1)Output should fit inside a single term. Increase MaxTermSize?");
×
975
                                                MesCall("EndSort");
×
976
                                                MUNLOCK(ErrorMessageLock);
×
977
                                                retval = -1; goto RetRetval;
×
978
                                        }
979
                                        else {
980
                                                t = newout->PObuffer;
123✔
981
                                                if ( par == 2 ) {
123✔
982
                                                        jj = newout->POfill - t;
×
983
                                                        if ( AN.tryterm > 0 && ( (jj+2)*sizeof(WORD) < (size_t)(AM.MaxTer) ) ) {
×
984
                                                                to = TermMalloc("$-sort space");
×
985
                                                        }
986
                                                        else {
987
                                                                LONG allocsp = jj+2;
×
988
                                                                if ( allocsp < MINALLOC ) allocsp = MINALLOC;
×
989
                                                                allocsp = ((allocsp+7)/8)*8;
×
990
                                                                to = (WORD *)Malloc1(allocsp*sizeof(WORD),"$-sort space");
×
991
                                                                if ( AN.tryterm > 0 ) AN.tryterm = 0;
×
992
                                                        }
993
                                                        *((WORD **)buffer) = to;
×
994
                                                        NCOPY(to,t,jj);
×
995
                                                }
996
                                                else {
997
                                                        j = newout->POfill - t;
123✔
998
                                                        to = buffer;
123✔
999
                                                        if ( to >= AT.WorkSpace && to < AT.WorkTop && to+j > AT.WorkTop )
123✔
1000
                                                                goto WorkSpaceError;
×
1001
                                                        if ( j > AM.MaxTer ) goto TooLarge;
123✔
1002
                                                        NCOPY(to,t,j);
6,351,610✔
1003
                                                }
1004
                                        }
1005
                                }
1006
                                goto RetRetval;
155✔
1007
                        }
1008
                        if ( MergePatches(1) ) { /* --> SortFile */
19✔
1009
                                MLOCK(ErrorMessageLock);
×
1010
                                MesCall("EndSort");
×
1011
                                MUNLOCK(ErrorMessageLock);
×
1012
                                retval = -1; goto RetRetval;
×
1013
                        }
1014
                        UpdateMaxSize();
19✔
1015
                        pp = S->SizeInFile[1];
19✔
1016
                        MULPOS(pp,sizeof(WORD));
19✔
1017
#ifndef WITHPTHREADS
1018
                        if ( S == AT.S0 )
6✔
1019
#endif
1020
                        {
1021
                                POSITION pppp;
17✔
1022
                                SETBASEPOSITION(pppp,0);
17✔
1023
                                SeekFile(S->file.handle,&pppp,SEEK_CUR);
17✔
1024
                                SeekFile(S->file.handle,&pp,SEEK_END);
17✔
1025
                                SeekFile(S->file.handle,&pppp,SEEK_SET);
17✔
1026
                                WriteStats(&pp,STATSMERGETOFILE,CHECKLOGTYPE);
17✔
1027
                        }
1028
#ifdef WITHERRORXXX
1029
                        if ( S != AT.S0 ) {
1030
/*
1031
                                This is wrong! We have sorted to the sort file.
1032
                                Things are not sitting in the output yet.
1033
*/
1034
                                if ( newout->handle >= 0 ) goto TooLarge;
1035
                                t = newout->PObuffer;
1036
                                j = newout->POfill - t;
1037
                                to = buffer;
1038
                                if ( to >= AT.WorkSpace && to < AT.WorkTop && to+j > AT.WorkTop )
1039
                                        goto WorkSpaceError;
1040
                                if ( j > AM.MaxTer ) goto TooLarge;
1041
                                NCOPY(to,t,j);
1042
                                goto RetRetval;
1043
                        }
1044
#endif
1045
                }
1046
        }
1047
        if ( S->file.handle >= 0 ) {
22✔
1048
#ifdef GZIPDEBUG
1049
                MLOCK(ErrorMessageLock);
1050
                MesPrint("%w EndSort: fPatchN = %d, lPatch = %d, position = %12p"
1051
                        ,S->fPatchN,S->lPatch,&(S->fPatches[S->fPatchN]));
1052
                MUNLOCK(ErrorMessageLock);
1053
#endif
1054
                if ( S->lPatch <= 0 ) {
22✔
1055
                        StageSort(&(S->file));
3✔
1056
                        position = S->fPatches[S->fPatchN];
3✔
1057
                        ss = S->sPointer;
3✔
1058
                        if ( *ss ) {
3✔
1059
                                *AR.CompressPointer = 0;
3✔
1060
#ifdef WITHZLIB
1061
                                if ( S == AT.S0 && AR.NoCompress == 0 && AR.gzipCompress > 0 )
3✔
1062
                                        S->fpcompressed[S->fPatchN] = 1;
3✔
1063
                                else
1064
                                        S->fpcompressed[S->fPatchN] = 0;
×
1065
                                SetupOutputGZIP(&(S->file));
3✔
1066
#endif
1067
                                while ( ( t = *ss++ ) != 0 ) {
23✔
1068
                                        if ( PutOut(BHEAD t,&position,&(S->file),1) < 0 ) {
20✔
1069
                                                retval = -1; goto RetRetval;
×
1070
                                        }
1071
                                }
1072
                                if ( FlushOut(&position,&(S->file),1) ) {
3✔
1073
                                        retval = -1; goto RetRetval;
×
1074
                                }
1075
                                ++(S->fPatchN);
3✔
1076
                                S->fPatches[S->fPatchN] = position;
3✔
1077
                                UpdateMaxSize();
3✔
1078
#ifdef GZIPDEBUG
1079
                                MLOCK(ErrorMessageLock);
1080
                                MesPrint("%w EndSort+: fPatchN = %d, lPatch = %d, position = %12p"
1081
                                        ,S->fPatchN,S->lPatch,&(S->fPatches[S->fPatchN]));
1082
                                MUNLOCK(ErrorMessageLock);
1083
#endif
1084
                        }
1085
                }
1086
                AR.Stage4Name = 0;
22✔
1087
#ifdef WITHPTHREADS
1088
                if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
14✔
1089
                        if ( S->file.handle >= 0 ) {
1090
                                SynchFile(S->file.handle);
1091
                        }
1092
                }
1093
#endif
1094
                UpdateMaxSize();
22✔
1095
                if ( MergePatches(0) ) {
22✔
1096
                        MLOCK(ErrorMessageLock);
×
1097
                        MesCall("EndSort");
×
1098
                        MUNLOCK(ErrorMessageLock);
×
1099
                        retval = -1; goto RetRetval;
×
1100
                }
1101
                S->stage4 = 0;
22✔
1102
#ifdef WITHPTHREADS
1103
                if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
14✔
1104
#endif
1105
                pp = S->SizeInFile[0];
22✔
1106
                MULPOS(pp,sizeof(WORD));
22✔
1107
                WriteStats(&pp,STATSPOSTSORT,NOCHECKLOGTYPE);
22✔
1108
                UpdateMaxSize();
22✔
1109
        }
1110
RetRetval:
×
1111

1112
#ifdef WITHMPI
1113
        /* NOTE: PF_EndSort has been changed such that it sets S->TermsLeft. (TU 30 Jun 2011) */
1114
        if ( AR.sLevel == 0 && (PF.me == MASTER || PF.exprtodo >= 0) ) {
1,108,830✔
1115
                Expressions[AR.CurExpr].counter = S->TermsLeft;
2,136✔
1116
                Expressions[AR.CurExpr].size = pp;
2,136✔
1117
        }
1118
#else
1119
        if ( AR.sLevel == 0 ) {
4,267,220✔
1120
                Expressions[AR.CurExpr].counter = S->TermsLeft;
15,139✔
1121
                Expressions[AR.CurExpr].size = pp;
15,139✔
1122
        }/*if ( AR.sLevel == 0 )*/
1123
#endif
1124
/*:[25nov2003 mt]*/
1125
        if ( S->file.handle >= 0 && ( par != 1 ) && ( par != 2 ) ) {
5,376,050✔
1126
                                /* sortfile is still open */
1127
                UpdateMaxSize();
×
1128
#ifdef WITHZLIB
1129
                ClearSortGZIP(&(S->file));
×
1130
#endif
1131
                CloseFile(S->file.handle);
×
1132
                S->file.handle = -1;
×
1133
                remove(S->file.name);
×
1134
#ifdef GZIPDEBUG
1135
                MLOCK(ErrorMessageLock);
1136
                MesPrint("%wEndSort: sortfile %s removed",S->file.name);
1137
                MUNLOCK(ErrorMessageLock);
1138
#endif
1139
        }
1140
        AR.outfile = oldoutfile;
5,376,050✔
1141
        AR.sLevel--;
5,376,050✔
1142
        if ( AR.sLevel >= 0 ) AT.SS = AN.FunSorts[AR.sLevel];
5,376,050✔
1143
        if ( par == 1 ) {
5,376,050✔
1144
                if ( retval < 0 ) {
5,286,660✔
1145
                        UpdateMaxSize();
×
1146
                        if ( newout ) {
×
1147
                                DeAllocFileHandle(newout);
×
1148
                                newout = 0;
×
1149
                        }
1150
                }
1151
                else if ( newout ) {
5,286,660✔
1152
                  if ( newout->handle >= 0 ) {
129✔
1153
                        MLOCK(ErrorMessageLock);
×
1154
                        MesPrint("(2)Output should fit inside a single term. Increase MaxTermSize?");
×
1155
                        MesCall("EndSort");
×
1156
                        MUNLOCK(ErrorMessageLock);
×
1157
                        Terminate(-1);
×
1158
                  }
1159
                  else if ( newout->POfill > newout->PObuffer ) {
129✔
1160
/*
1161
                        Here we have to copy the contents of the 'file' into
1162
                        the buffer. We assume that this buffer lies in the WorkSpace.
1163
                        Hence
1164
*/
1165
                        j = newout->POfill-newout->PObuffer;
129✔
1166
                        if ( buffer >= AT.WorkSpace && buffer < AT.WorkTop && buffer+j > AT.WorkTop )
129✔
1167
                                goto WorkSpaceError;
×
1168
                        else {
1169
                                to = buffer; t = newout->PObuffer;
1170
                                while ( j-- > 0 ) *to++ = *t++;
6,459,670✔
1171
                        }
1172
                        UpdateMaxSize();
129✔
1173
                  }
1174
                  DeAllocFileHandle(newout);
129✔
1175
                  newout = 0;
129✔
1176
                }
1177
        }
1178
        else if ( par == 2 ) {
89,387✔
1179
                if ( newout ) {
26,817✔
1180
                        if ( retval == 0 ) {
×
1181
                          if ( newout->handle >= 0 ) {
×
1182
/*
1183
                                output resides at the moment in a file
1184
                                Find the size, make a buffer, copy into the buffer and clean up.
1185
*/
1186
                                POSITION zeropos;
×
1187
                                PUTZERO(position);
×
1188
#ifdef ALLLOCK
1189
                                LOCK(newout->pthreadslock);
1190
#endif
1191
                                SeekFile(newout->handle,&position,SEEK_END);
×
1192
                                PUTZERO(zeropos);
×
1193
                                SeekFile(newout->handle,&zeropos,SEEK_SET);
×
1194
                                to = (WORD *)Malloc1(BASEPOSITION(position)+sizeof(WORD)*3
×
1195
                                                ,"$-buffer reading");
1196
                                if ( AN.tryterm > 0 ) AN.tryterm = 0;
×
1197
                                if ( ( retval = ReadFile(newout->handle,(UBYTE *)to,BASEPOSITION(position)) ) !=
×
1198
                                BASEPOSITION(position) ) {
×
1199
                                        MLOCK(ErrorMessageLock);
×
1200
                                        MesPrint("Error reading information for $ variable");
×
1201
                                        MUNLOCK(ErrorMessageLock);
×
1202
                                        M_free(to,"$-buffer reading");
×
1203
                                        retval = -1;
×
1204
                                }
1205
                                else {
1206
                                        *((WORD **)buffer) = to;
×
1207
                                        retval /= sizeof(WORD);
×
1208
                                }
1209
#ifdef ALLLOCK
1210
                                UNLOCK(newout->pthreadslock);
1211
#endif
1212
                          }
1213
                          else {
1214
/*
1215
                                output resides in the cache buffer and the file was never opened
1216
*/
1217
                                LONG wsiz = newout->POfill - newout->PObuffer;
×
1218
                                if ( AN.tryterm > 0 && ( (wsiz+2)*sizeof(WORD) < (size_t)(AM.MaxTer) ) ) {
×
1219
                                        to = TermMalloc("$-sort space");
×
1220
                                }
1221
                                else {
1222
                                        LONG allocsp = wsiz+2;
×
1223
                                        if ( allocsp < MINALLOC ) allocsp = MINALLOC;
×
1224
                                        allocsp = ((allocsp+7)/8)*8;
×
1225
                                        to = (WORD *)Malloc1(allocsp*sizeof(WORD),"$-buffer reading");
×
1226
                                        if ( AN.tryterm > 0 ) AN.tryterm = 0;
×
1227
                                }
1228
                                *((WORD **)buffer) = to; t = newout->PObuffer;
×
1229
                                retval = wsiz;
×
1230
                                NCOPY(to,t,wsiz);
×
1231
                          }
1232
                        }
1233
                        UpdateMaxSize();
×
1234
                        DeAllocFileHandle(newout);
×
1235
                        newout = 0;
×
1236
                }
1237
        }
1238
        else {
1239
                if ( newout ) {
62,570✔
1240
                        DeAllocFileHandle(newout);
×
1241
                        newout = 0;
×
1242
                }
1243
        }
1244
/*
1245
        if ( AR.sLevel < 0 ) {
1246
                MesPrint(" number of calls to compare was %l",numcompares);
1247
        }
1248
*/
1249
        return(retval);
1250
WorkSpaceError:
×
1251
        MLOCK(ErrorMessageLock);
×
1252
        MesWork();
×
1253
        MesCall("EndSort");
×
1254
        MUNLOCK(ErrorMessageLock);
×
1255
        Terminate(-1);
×
1256
        return(-1);
×
1257
}
1258

1259
/*
1260
                 #] EndSort : 
1261
                 #[ PutIn :                                        LONG PutIn(handle,position,buffer,take,npat)
1262
*/
1263
/**
1264
 *        Reads a new patch from position in file handle.
1265
 *        It is put at buffer, anything after take is moved forward.
1266
 *        This would be part of a term that hasn't been used yet.
1267
 *        Because of this there should be some space before the start of the buffer
1268
 *
1269
 *        @param file     The file system from which to read
1270
 *        @param position The position from which to read
1271
 *        @param buffer   The buffer into which to read
1272
 *        @param take     The unused tail should be moved before the buffer
1273
 *        @param npat                The number of the patch. Is needed if the information
1274
 *                        was compressed with gzip, because each patch has its
1275
 *                        own independent gzip encoding.
1276
 */
1277

1278
LONG PutIn(FILEHANDLE *file, POSITION *position, WORD *buffer, WORD **take, int npat)
368✔
1279
{
1280
        LONG i, RetCode;
368✔
1281
        WORD *from, *to;
368✔
1282
#ifndef WITHZLIB
1283
        DUMMYUSE(npat);
1284
#endif
1285
        from = buffer + ( file->POsize * sizeof(UBYTE) )/sizeof(WORD);
368✔
1286
        i = from - *take;
368✔
1287
        if ( i*((LONG)(sizeof(WORD))) > AM.MaxTer ) {
368✔
1288
                MLOCK(ErrorMessageLock);
×
1289
                MesPrint("Problems in PutIn");
×
1290
                MUNLOCK(ErrorMessageLock);
×
1291
                Terminate(-1);
×
1292
        }
1293
        to = buffer;
1294
        while ( --i >= 0 ) *--to = *--from;
1,066✔
1295
        *take = to;
368✔
1296
#ifdef WITHZLIB
1297
        if ( ( RetCode = FillInputGZIP(file,position,(UBYTE *)buffer
368✔
1298
                                                                        ,file->POsize,npat) ) < 0 ) {
1299
                MLOCK(ErrorMessageLock);
×
1300
                MesPrint("PutIn: We have RetCode = %x while reading %x bytes",
×
1301
                        RetCode,file->POsize);
1302
                MUNLOCK(ErrorMessageLock);
×
1303
                Terminate(-1);
×
1304
        }
1305
#else
1306
#ifdef ALLLOCK
1307
        LOCK(file->pthreadslock);
1308
#endif
1309
        SeekFile(file->handle,position,SEEK_SET);
1310
        if ( ( RetCode = ReadFile(file->handle,(UBYTE *)buffer,file->POsize) ) < 0 ) {
1311
#ifdef ALLLOCK
1312
                UNLOCK(file->pthreadslock);
1313
#endif
1314
                MLOCK(ErrorMessageLock);
1315
                MesPrint("PutIn: We have RetCode = %x while reading %x bytes",
1316
                        RetCode,file->POsize);
1317
                MUNLOCK(ErrorMessageLock);
1318
                Terminate(-1);
1319
        }
1320
#ifdef ALLLOCK
1321
        UNLOCK(file->pthreadslock);
1322
#endif
1323
#endif
1324
        return(RetCode);
368✔
1325
}
1326

1327
/*
1328
                 #] PutIn : 
1329
                 #[ Sflush :                                        WORD Sflush(file)
1330
*/
1331
/**
1332
 *        Puts the contents of a buffer to output
1333
 *        Only to be used when there is a single patch in the large buffer.
1334
 *
1335
 *        @param fi  The filesystem (or its cache) to which the patch should be written
1336
 */
1337

1338
WORD Sflush(FILEHANDLE *fi)
×
1339
{
1340
        LONG size, RetCode;
×
1341
#ifdef WITHZLIB
1342
        GETIDENTITY
1343
        int dobracketindex = 0;
×
1344
        if ( AR.sLevel <= 0 && Expressions[AR.CurExpr].newbracketinfo
×
1345
                && ( fi == AR.outfile || fi == AR.hidefile ) ) dobracketindex = 1;
×
1346
#endif
1347
        if ( fi->handle < 0 ) {
×
1348
                if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
×
1349
#ifdef GZIPDEBUG
1350
                        MLOCK(ErrorMessageLock);
1351
                        MesPrint("%w Sflush created scratch file %s",fi->name);
1352
                        MUNLOCK(ErrorMessageLock);
1353
#endif
1354
                        fi->handle = (WORD)RetCode;
×
1355
                        PUTZERO(fi->filesize);
×
1356
                        PUTZERO(fi->POposition);
×
1357
                }
1358
                else {
1359
                        MLOCK(ErrorMessageLock);
×
1360
                        MesPrint("Cannot create scratch file %s",fi->name);
×
1361
                        MUNLOCK(ErrorMessageLock);
×
1362
                        return(-1);
×
1363
                }
1364
        }
1365
#ifdef WITHZLIB
1366
        if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
×
1367
        && dobracketindex == 0 ) {
×
1368
                if ( FlushOutputGZIP(fi) ) return(-1);
×
1369
                fi->POfill = fi->PObuffer;
×
1370
        }
1371
        else
1372
#endif
1373
        {
1374
#ifdef ALLLOCK
1375
          LOCK(fi->pthreadslock);
1376
#endif
1377
          size = (fi->POfill-fi->PObuffer)*sizeof(WORD);
×
1378
          SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
×
1379
          if ( WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),size) != size ) {
×
1380
#ifdef ALLLOCK
1381
                UNLOCK(fi->pthreadslock);
1382
#endif
1383
                MLOCK(ErrorMessageLock);
×
1384
                MesPrint("Write error while finishing sort. Disk full?");
×
1385
                MUNLOCK(ErrorMessageLock);
×
1386
                return(-1);
×
1387
          }
1388
          ADDPOS(fi->filesize,size);
×
1389
          ADDPOS(fi->POposition,size);
×
1390
          fi->POfill = fi->PObuffer;
×
1391
#ifdef ALLLOCK
1392
          UNLOCK(fi->pthreadslock);
1393
#endif
1394
        }
1395
        return(0);
1396
}
1397

1398
/*
1399
                 #] Sflush : 
1400
                 #[ PutOut :                                        WORD PutOut(term,position,file,ncomp)
1401
*/
1402
/**
1403
 *        Routine writes one term to file handle at position. It returns
1404
 *        the new value of the position.
1405
 *
1406
 *        NOTE:
1407
 *                For 'final output' we may have to index the brackets.
1408
 *                See the struct BRACKETINDEX.
1409
 *                We should maintain:
1410
 *                1: a list with brackets
1411
 *                        array with the brackets
1412
 *                2: a list of objects of type BRACKETINDEX. It contains
1413
 *                        array with either pointers or offsets to the list of brackets.
1414
 *                        starting positions in the file.
1415
 *                The index may be tied to a maximum size. In that case we may have to
1416
 *                prune the list occasionally.
1417
 *
1418
 *        @param term     The term to be written
1419
 *        @param position The position in the file. Afterwards it is updated
1420
 *        @param fi       The file (or its cache) to which should be written
1421
 *        @param ncomp    Information about what type of compression should be used
1422
 */
1423

1424
WORD PutOut(PHEAD WORD *term, POSITION *position, FILEHANDLE *fi, WORD ncomp)
15,096,280✔
1425
{
1426
        GETBIDENTITY
1427
        WORD i, *p, ret, *r, *rr, j, k, first;
15,096,280✔
1428
        int dobracketindex = 0;
15,096,280✔
1429
        LONG RetCode;
15,096,280✔
1430

1431
        if ( AT.SS != AT.S0 ) {
15,096,280✔
1432
/*
1433
                For this case no compression should be used
1434
*/
1435
                if ( ( i = *term ) <= 0 ) return(0);
466,752✔
1436
                ret = i;
466,752✔
1437
                ADDPOS(*position,i*sizeof(WORD));
466,752✔
1438
                p = fi->POfill;
466,752✔
1439
                do {
6,690,400✔
1440
                        if ( p >= fi->POstop ) {
6,690,400✔
1441
                                if ( fi->handle < 0 ) {
×
1442
                                        if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
×
1443
#ifdef GZIPDEBUG
1444
                                                MLOCK(ErrorMessageLock);
1445
                                                MesPrint("%w PutOut created sortfile %s",fi->name);
1446
                                                MUNLOCK(ErrorMessageLock);
1447
#endif
1448
                                                fi->handle = (WORD)RetCode;
×
1449
                                                PUTZERO(fi->filesize);
×
1450
                                                PUTZERO(fi->POposition);
×
1451
/*
1452
                                                Should not be here anymore?
1453
#ifdef WITHZLIB
1454
                                                fi->ziobuffer = 0;
1455
#endif
1456
*/
1457
                                        }
1458
                                        else {
1459
                                                MLOCK(ErrorMessageLock);
×
1460
                                                MesPrint("Cannot create scratch file %s",fi->name);
×
1461
                                                MUNLOCK(ErrorMessageLock);
×
1462
                                                return(-1);
×
1463
                                        }
1464
                                }
1465
#ifdef ALLLOCK
1466
                                LOCK(fi->pthreadslock);
1467
#endif
1468
                                if ( fi == AR.hidefile ) {
×
1469
                                        LOCK(AS.inputslock);
×
1470
                                }
1471
                                SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
×
1472
                                if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize) ) != fi->POsize ) {
×
1473
                                        if ( fi == AR.hidefile ) {
×
1474
                                                UNLOCK(AS.inputslock);
×
1475
                                        }
1476
#ifdef ALLLOCK
1477
                                        UNLOCK(fi->pthreadslock);
1478
#endif
1479
                                        MLOCK(ErrorMessageLock);
×
1480
                                        MesPrint("Write error during sort. Disk full?");
×
1481
                                        MesPrint("Attempt to write %l bytes on file %d at position %15p",
×
1482
                                                                fi->POsize,fi->handle,&(fi->POposition));
1483
                                        MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
×
1484
                                        MUNLOCK(ErrorMessageLock);
×
1485
                                        return(-1);
×
1486
                                }
1487
                                ADDPOS(fi->filesize,fi->POsize);
×
1488
                                p = fi->PObuffer;
×
1489
                                ADDPOS(fi->POposition,fi->POsize);
×
1490
                                if ( fi == AR.hidefile ) {
×
1491
                                        UNLOCK(AS.inputslock);
3,305,600✔
1492
                                }
1493
#ifdef ALLLOCK
1494
                                UNLOCK(fi->pthreadslock);
1495
#endif
1496
#ifdef WITHPTHREADS
1497
                                if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
1498
                                        if ( fi->handle >= 0 ) SynchFile(fi->handle);
1499
                                }
1500
#endif
1501
                        } 
1502
                        *p++ = *term++;
6,690,400✔
1503
                } while ( --i > 0 );
6,690,400✔
1504
                fi->POfull = fi->POfill = p;
466,752✔
1505
                return(ret);
466,752✔
1506
        }
1507
        if ( ( AP.PreDebug & DUMPOUTTERMS ) == DUMPOUTTERMS ) {
14,629,540✔
1508
                        MLOCK(ErrorMessageLock);
×
1509
#ifdef WITHPTHREADS
1510
                        snprintf((char *)(THRbuf),100,"PutOut(%d)",AT.identity);
1511
                        PrintTerm(term,(char *)(THRbuf));
1512
#else
1513
                        PrintTerm(term,"PutOut");
1514
#endif
1515
                        MesPrint("ncomp = %d, AR.NoCompress = %d, AR.sLevel = %d",ncomp,AR.NoCompress,AR.sLevel);
×
1516
                        MesPrint("File %s, position %p",fi->name,position);
×
1517
                        MUNLOCK(ErrorMessageLock);
3,168,020✔
1518
        }
1519

1520
        if ( AR.sLevel <= 0 && Expressions[AR.CurExpr].newbracketinfo
14,629,540✔
1521
                && ( fi == AR.outfile || fi == AR.hidefile ) ) dobracketindex = 1;
31,684✔
1522
        r = rr = AR.CompressPointer;
14,629,540✔
1523
        first = j = k = ret = 0;
14,629,540✔
1524
        if ( ( i = *term ) != 0 ) {
14,629,540✔
1525
                if ( i < 0 ) {                        /* Compressed term */
14,629,540✔
1526
                        i = term[1] + 2;
17✔
1527
                        if ( fi == AR.outfile || fi == AR.hidefile ) {
17✔
1528
                                MLOCK(ErrorMessageLock);
×
1529
                                MesPrint("Ran into precompressed term");
×
1530
                                MUNLOCK(ErrorMessageLock);
×
1531
                                Crash();
×
1532
                                return(-1);
×
1533
                        }
1534
                }
1535
                else if ( !AR.NoCompress && ( ncomp > 0 ) && AR.sLevel <= 0 ) {        /* Must compress */
14,629,510✔
1536
                        if ( dobracketindex ) {
4,467,990✔
1537
                                PutBracketInIndex(BHEAD term,position);
31,684✔
1538
                        }
1539
                        j = *r++ - 1;
4,467,990✔
1540
                        p = term + 1;
4,467,990✔
1541
                        i--;
4,467,990✔
1542
                        if ( AR.PolyFun ) {
4,467,990✔
1543
                                WORD *polystop, *sa;
15,384✔
1544
                                sa = p + i;
15,384✔
1545
                                sa -= ABS(sa[-1]);
15,384✔
1546
                                polystop = p;
15,384✔
1547
                                while ( polystop < sa && *polystop != AR.PolyFun ) {
34,591✔
1548
                                        polystop += polystop[1];
19,207✔
1549
                                }
1550
                                if ( polystop < sa ) {
15,384✔
1551
                                        if ( AR.PolyFunType == 2 ) polystop[2] &= ~MUSTCLEANPRF;
15,384✔
1552
                                        while ( i > 0 && j > 0 && *p == *r && p < polystop ) {
163,867✔
1553
                                                i--; j--; k--; p++; r++;
148,483✔
1554
                                        }
1555
                                }
1556
                                else {
1557
                                        while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
×
1558
                                }
1559
                        }
1560
#ifdef WITHFLOAT
1561
                        else if ( AC.DefaultPrecision ) {
4,452,620✔
1562
                                WORD *floatstop, *sa;
4,452,620✔
1563
                                sa = p + i;
4,452,620✔
1564
                                sa -= ABS(sa[-1]);
4,452,620✔
1565
                                floatstop = p;
4,452,620✔
1566
                                while ( floatstop < sa && *floatstop != FLOATFUN ) {
11,270,930✔
1567
                                        floatstop += floatstop[1];
6,818,330✔
1568
                                }
1569
                                if ( floatstop < sa ) {
4,452,620✔
1570
                                        while ( i > 0 && j > 0 && *p == *r && p < floatstop ) {
×
1571
                                                i--; j--; k--; p++; r++;
×
1572
                                        }
1573
                                }
1574
                                else {
1575
                                        while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
25,605,990✔
1576
                                }
1577
                        }
1578
#endif
1579
                        else {
1580
                                WORD *sa;
×
1581
                                sa = p + i;
×
1582
                                sa -= ABS(sa[-1]);
×
1583
                                while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
×
1584
                        }
1585
                        if ( k > -2 ) {
4,467,990✔
1586
nocompress:
55,563✔
1587
                                j = i = *term;
55,618✔
1588
                                k = 0;
55,618✔
1589
                                p = term;
55,618✔
1590
                                r = rr;
55,618✔
1591
                                NCOPY(r,p,j);
3,634,469✔
1592
                        }
1593
                        else {
1594
                                *rr = *term;
4,412,420✔
1595
                                term = p;
4,412,420✔
1596
                                j = i;
4,412,420✔
1597
                                NCOPY(r,p,j);
77,584,800✔
1598
                                j = i;
4,412,420✔
1599
                                i += 2;
4,412,420✔
1600
                                first = 2;
4,412,420✔
1601
                        }
1602
/*                                        Sabotage getting into the coefficient next time */
1603
                        r[-(ABS(r[-1]))] = 0;
4,468,060✔
1604
                        if ( r >= AR.ComprTop ) {
4,468,060✔
1605
                                MLOCK(ErrorMessageLock);
×
1606
                                MesPrint("CompressSize of %10l is insufficient",AM.CompressSize);
×
1607
                                MUNLOCK(ErrorMessageLock);
×
1608
                                Crash();
×
1609
                                return(-1);
×
1610
                        }
1611
                }
1612
                else if ( !AR.NoCompress && ( ncomp < 0 ) && AR.sLevel <= 0 ) {
10,161,530✔
1613
                                /* No compress but put in compress buffer anyway */
1614
                        if ( dobracketindex ) {
55✔
1615
                                PutBracketInIndex(BHEAD term,position);
×
1616
                        }
1617
                        j = *r++ - 1;
55✔
1618
                        p = term + 1;
55✔
1619
                        i--;
55✔
1620
                        if ( AR.PolyFun ) {
55✔
1621
                                WORD *polystop, *sa;
×
1622
                                sa = p + i;
×
1623
                                sa -= ABS(sa[-1]);
×
1624
                                polystop = p;
×
1625
                                while ( polystop < sa && *polystop != AR.PolyFun ) {
×
1626
                                        polystop += polystop[1];
×
1627
                                }
1628
                                if ( polystop < sa ) {
×
1629
                                        if ( AR.PolyFunType == 2 ) polystop[2] &= ~MUSTCLEANPRF;
×
1630
                                        while ( i > 0 && j > 0 && *p == *r && p < polystop ) {
×
1631
                                                i--; j--; k--; p++; r++;
×
1632
                                        }
1633
                                }
1634
                                else {
1635
                                        while ( i > 0 && j > 0 && *p == *r ) { i--; j--; k--; p++; r++; }
×
1636
                                }
1637
                        }
1638
                        else {
1639
                                while ( i > 0 && j > 0 && *p == *r ) { i--; j--; k--; p++; r++; }
55✔
1640
                        }
1641
                        goto nocompress;
55✔
1642
                }
1643
                else {
1644
                        if ( AR.PolyFunType == 2 ) {
10,161,470✔
1645
                                WORD *t, *tstop;
5,078✔
1646
                                tstop = term + *term;
5,078✔
1647
                                tstop -= ABS(tstop[-1]);
5,078✔
1648
                                t = term+1;
5,078✔
1649
                                while ( t < tstop ) {
10,156✔
1650
                                        if ( *t == AR.PolyFun ) {
5,078✔
1651
                                                t[2] &= ~MUSTCLEANPRF;
×
1652
                                        }
1653
                                        t += t[1];
5,078✔
1654
                                }
1655
                        }
1656
                        if ( dobracketindex ) {
10,161,470✔
1657
                                PutBracketInIndex(BHEAD term,position);
×
1658
                        }
1659
                }
1660
                ret = i;
14,629,540✔
1661
                ADDPOS(*position,i*sizeof(WORD));
14,629,540✔
1662
                p = fi->POfill;
14,629,540✔
1663
                do {
309,046,700✔
1664
                        if ( p >= fi->POstop ) {
309,046,700✔
1665
#ifdef WITHMPI /* [16mar1998 ar] */
1666
                          if ( PF.me != MASTER && AR.sLevel <= 0 && (fi == AR.outfile || fi == AR.hidefile) && PF.parallel && PF.exprtodo < 0 ) {
41✔
1667
                                PF_BUFFER *sbuf = PF.sbuf;
10✔
1668
                                sbuf->fill[sbuf->active] = fi->POstop;
10✔
1669
                                PF_ISendSbuf(MASTER,PF_BUFFER_MSGTAG);
10✔
1670
                                p = fi->PObuffer = fi->POfill = fi->POfull =
10✔
1671
                                  sbuf->buff[sbuf->active];
10✔
1672
                                fi->POstop = sbuf->stop[sbuf->active];
10✔
1673
                          }
1674
                          else
1675
#endif /* WITHMPI [16mar1998 ar] */
1676
                          {
1677
                                if ( fi->handle < 0 ) {
178✔
1678
                                        if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
10✔
1679
#ifdef GZIPDEBUG
1680
                                                MLOCK(ErrorMessageLock);
1681
                                                MesPrint("%w PutOut created sortfile %s",fi->name);
1682
                                                MUNLOCK(ErrorMessageLock);
1683
#endif
1684
                                                fi->handle = (WORD)RetCode;
10✔
1685
                                                PUTZERO(fi->filesize);
10✔
1686
                                                PUTZERO(fi->POposition);
10✔
1687
/*
1688
                                                Should not be here?
1689
#ifdef WITHZLIB
1690
                                                fi->ziobuffer = 0;
1691
#endif
1692
*/
1693
                                        }
1694
                                        else {
1695
                                                MLOCK(ErrorMessageLock);
×
1696
                                                MesPrint("Cannot create scratch file %s",fi->name);
×
1697
                                                MUNLOCK(ErrorMessageLock);
×
1698
                                                return(-1);
×
1699
                                        }
1700
                                }
1701
#ifdef WITHZLIB
1702
                                if ( !AR.NoCompress && ncomp > 0 && AR.gzipCompress > 0
178✔
1703
                                        && dobracketindex == 0 && fi->zsp != 0 ) {
91✔
1704
                                        fi->POfill = p;
91✔
1705
                                        if ( PutOutputGZIP(fi) ) return(-1);
91✔
1706
                                        p = fi->PObuffer;
91✔
1707
                                }
1708
                                else
1709
#endif
1710
                                {
1711
#ifdef ALLLOCK
1712
                                  LOCK(fi->pthreadslock);
1713
#endif
1714
                                  if ( fi == AR.hidefile ) {
87✔
1715
                                        LOCK(AS.inputslock);
53✔
1716
                                  }
1717
                                  SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
87✔
1718
                                  if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize) ) != fi->POsize ) {
87✔
1719
                                        if ( fi == AR.hidefile ) {
×
1720
                                                UNLOCK(AS.inputslock);
×
1721
                                        }
1722
#ifdef ALLLOCK
1723
                                        UNLOCK(fi->pthreadslock);
1724
#endif
1725
                                        MLOCK(ErrorMessageLock);
×
1726
                                        MesPrint("Write error during sort. Disk full?");
×
1727
                                        MesPrint("Attempt to write %l bytes on file %d at position %15p",
×
1728
                                                                fi->POsize,fi->handle,&(fi->POposition));
1729
                                        MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
×
1730
                                        MUNLOCK(ErrorMessageLock);
×
1731
                                        return(-1);
×
1732
                                  }
1733
                                  ADDPOS(fi->filesize,fi->POsize);
87✔
1734
                                  p = fi->PObuffer;
87✔
1735
                                  ADDPOS(fi->POposition,fi->POsize);
87✔
1736
                                  if ( fi == AR.hidefile ) {
87✔
1737
                                        UNLOCK(AS.inputslock);
182,782,600✔
1738
                                  }
1739
#ifdef ALLLOCK
1740
                                  UNLOCK(fi->pthreadslock);
1741
#endif
1742
#ifdef WITHPTHREADS
1743
                                  if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
34✔
1744
                                        if ( fi->handle >= 0 ) SynchFile(fi->handle);
1745
                                  }
1746
#endif
1747
                                }
1748
                          }
1749
                        } 
1750
                        if ( first ) {
309,046,700✔
1751
                                if ( first == 2 ) *p++ = k;
8,824,870✔
1752
                                else *p++ = j;
4,412,420✔
1753
                                first--;
8,824,870✔
1754
                        }
1755
                        else *p++ = *term++;
300,221,900✔
1756
/*
1757
                        if ( AP.DebugFlag ) {
1758
                                TalToLine((UWORD)(p[-1])); TokenToLine((UBYTE *)"  ");
1759
                        }
1760
*/
1761
                } while ( --i > 0 );
309,046,700✔
1762
                fi->POfull = fi->POfill = p;
14,629,540✔
1763
        }
1764
/*
1765
        if ( AP.DebugFlag ) {
1766
                AO.OutSkip = 0;
1767
                FiniLine();
1768
        }
1769
*/
1770
        return(ret);
1771
}
1772

1773
/*
1774
                 #] PutOut : 
1775
                 #[ FlushOut :                                WORD FlushOut(position,file,compr)
1776
*/
1777
/**
1778
 *        Completes output to an output file and writes the trailing zero.
1779
 *
1780
 *        @param position The position in the file after writing
1781
 *        @param fi       The file (or its cache)
1782
 *        @param compr        Indicates whether there should be compression with gzip.
1783
 *        @return   Regular conventions (OK -> 0).
1784
 */
1785

1786
WORD FlushOut(POSITION *position, FILEHANDLE *fi, int compr)
22,718✔
1787
{
1788
        GETIDENTITY
6,770✔
1789
        LONG size, RetCode;
22,718✔
1790
        int dobracketindex = 0;
22,718✔
1791
#ifndef WITHZLIB
1792
        DUMMYUSE(compr);
1793
#endif
1794
        if ( AR.sLevel <= 0 && Expressions[AR.CurExpr].newbracketinfo
22,718✔
1795
                && ( fi == AR.outfile || fi == AR.hidefile ) ) dobracketindex = 1;
147✔
1796
#ifdef WITHMPI /* [16mar1998 ar] */
1797
        if ( PF.me != MASTER && AR.sLevel <= 0 && (fi == AR.outfile || fi == AR.hidefile) && PF.parallel && PF.exprtodo < 0 ) {
12,528✔
1798
                PF_BUFFER *sbuf = PF.sbuf;
6,276✔
1799
                if ( fi->POfill >= fi->POstop ){
6,276✔
1800
                  sbuf->fill[sbuf->active] = fi->POstop;
1801
                  PF_ISendSbuf(MASTER,PF_BUFFER_MSGTAG);
1802
                  fi->POfull = fi->POfill = fi->PObuffer = sbuf->buff[sbuf->active];
1803
                  fi->POstop = sbuf->stop[sbuf->active];
1804
                }
1805
                *(fi->POfill)++ = 0;
6,276✔
1806
                sbuf->fill[sbuf->active] = fi->POfill;
6,276✔
1807
                PF_ISendSbuf(MASTER,PF_ENDBUFFER_MSGTAG);
6,276✔
1808
                fi->PObuffer = fi->POfill = fi->POfull = sbuf->buff[sbuf->active];
6,276✔
1809
                fi->POstop = sbuf->stop[sbuf->active];
6,276✔
1810
                return(0);
6,276✔
1811
        }
1812
#endif /* WITHMPI [16mar1998 ar] */
1813
        if ( fi->POfill >= fi->POstop ) {
16,442✔
1814
                if ( fi->handle < 0 ) {
×
1815
                        if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
×
1816
#ifdef GZIPDEBUG
1817
                                MLOCK(ErrorMessageLock);
1818
                                MesPrint("%w FlushOut created scratch file %s",fi->name);
1819
                                MUNLOCK(ErrorMessageLock);
1820
#endif
1821
                                PUTZERO(fi->filesize);
×
1822
                                PUTZERO(fi->POposition);
×
1823
                                fi->handle = (WORD)RetCode;
×
1824
/*
1825
                                Should not be here?
1826
#ifdef WITHZLIB
1827
                                fi->ziobuffer = 0;
1828
#endif
1829
*/
1830
                        }
1831
                        else {
1832
                                MLOCK(ErrorMessageLock);
×
1833
                                MesPrint("Cannot create scratch file %s",fi->name);
×
1834
                                MUNLOCK(ErrorMessageLock);
×
1835
                                return(-1);
×
1836
                        }
1837
                }
1838
#ifdef WITHZLIB
1839
                if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
×
1840
                && dobracketindex == 0 && ( compr > 0 ) && fi->zsp != 0 ) {
×
1841
                        if ( PutOutputGZIP(fi) ) return(-1);
×
1842
                        fi->POfill = fi->PObuffer;
×
1843
                }
1844
                else
1845
#endif
1846
                {
1847
#ifdef ALLLOCK
1848
                  LOCK(fi->pthreadslock);
1849
#endif
1850
                  if ( fi == AR.hidefile ) {
×
1851
                        LOCK(AS.inputslock);
×
1852
                  }
1853
                  SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
×
1854
                  if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize) ) != fi->POsize ) {
×
1855
#ifdef ALLLOCK
1856
                        UNLOCK(fi->pthreadslock);
1857
#endif
1858
                        if ( fi == AR.hidefile ) {
×
1859
                                UNLOCK(AS.inputslock);
×
1860
                        }
1861
                        MLOCK(ErrorMessageLock);
×
1862
                        MesPrint("Write error while sorting. Disk full?");
×
1863
                        MesPrint("Attempt to write %l bytes on file %d at position %15p",
×
1864
                                                fi->POsize,fi->handle,&(fi->POposition));
1865
                        MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
×
1866
                        MUNLOCK(ErrorMessageLock);
×
1867
                        return(-1);
×
1868
                  }
1869
                  ADDPOS(fi->filesize,fi->POsize);
×
1870
                  fi->POfill = fi->PObuffer;
×
1871
                  ADDPOS(fi->POposition,fi->POsize);
×
1872
                  if ( fi == AR.hidefile ) {
×
1873
                        UNLOCK(AS.inputslock);
9,672✔
1874
                  }
1875
#ifdef ALLLOCK
1876
                  UNLOCK(fi->pthreadslock);
1877
#endif
1878
#ifdef WITHPTHREADS
1879
                  if ( AS.MasterSort && AC.ThreadSortFileSynch && fi != AR.hidefile ) {
1880
                        if ( fi->handle >= 0 ) SynchFile(fi->handle);
1881
                  }
1882
#endif
1883
                }
1884
        } 
1885
        *(fi->POfill)++ = 0;
16,442✔
1886
        fi->POfull = fi->POfill;
16,442✔
1887
/*
1888
        {
1889
                UBYTE OutBuf[140];
1890
                if ( AP.DebugFlag ) {
1891
                        AO.OutFill = AO.OutputLine = OutBuf;
1892
                        AO.OutSkip = 3;
1893
                        FiniLine();
1894
                        TokenToLine((UBYTE *)"End of expression written");
1895
                        FiniLine();
1896
                }
1897
        }
1898
*/
1899
        size = (fi->POfill-fi->PObuffer)*sizeof(WORD);
16,442✔
1900
        if ( fi->handle >= 0 ) {
16,442✔
1901
#ifdef WITHZLIB
1902
                if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
304✔
1903
                && dobracketindex == 0 && ( compr > 0 ) && fi->zsp != 0 ) {
258✔
1904
                        if ( FlushOutputGZIP(fi) ) return(-1);
258✔
1905
                        fi->POfill = fi->PObuffer;
258✔
1906
                }
1907
                else
1908
#endif
1909
                {
1910
#ifdef ALLLOCK
1911
                  LOCK(fi->pthreadslock);
1912
#endif
1913
                  if ( fi == AR.hidefile ) {
46✔
1914
                        LOCK(AS.inputslock);
16✔
1915
                  }
1916
                  SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
46✔
1917
/*
1918
                  MesPrint("FlushOut: writing %l bytes to position %12p",size,&(fi->POposition));
1919
*/
1920
                  if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),size) ) != size ) {
46✔
1921
#ifdef ALLLOCK
1922
                        UNLOCK(fi->pthreadslock);
1923
#endif
1924
                        if ( fi == AR.hidefile ) {
×
1925
                                UNLOCK(AS.inputslock);
×
1926
                        }
1927
                        MLOCK(ErrorMessageLock);
×
1928
                        MesPrint("Write error while finishing sorting. Disk full?");
×
1929
                        MesPrint("Attempt to write %l bytes on file %d at position %15p",
×
1930
                                                size,fi->handle,&(fi->POposition));
1931
                        MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
×
1932
                        MUNLOCK(ErrorMessageLock);
×
1933
                        return(-1);
×
1934
                  }
1935
                  ADDPOS(fi->filesize,size);
46✔
1936
                  ADDPOS(fi->POposition,size);
46✔
1937
                  fi->POfill = fi->PObuffer;
46✔
1938
                  if ( fi == AR.hidefile ) {
46✔
1939
                        UNLOCK(AS.inputslock);
9,672✔
1940
                  }
1941
#ifdef ALLLOCK
1942
                  UNLOCK(fi->pthreadslock);
1943
#endif
1944
#ifdef WITHPTHREADS
1945
                  if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
30✔
1946
                        if ( fi->handle >= 0 ) SynchFile(fi->handle);
1947
                  }
1948
#endif
1949
                }
1950
        }
1951
        if ( dobracketindex ) {
16,442✔
1952
                BRACKETINFO *b = Expressions[AR.CurExpr].newbracketinfo;
147✔
1953
                if ( b->indexfill > 0 ) {
147✔
1954
                        DIFPOS(b->indexbuffer[b->indexfill-1].next,*position,Expressions[AR.CurExpr].onfile);
139✔
1955
                }
1956
        }
1957
#ifdef WITHZLIB
1958
        if ( AT.SS == AT.S0 && !AR.NoCompress && AR.gzipCompress > 0
16,442✔
1959
                && dobracketindex == 0 && ( compr > 0 ) && fi->zsp != 0 ) {
4,013✔
1960
                PUTZERO(*position);
258✔
1961
                if ( fi->handle >= 0 ) {
258✔
1962
#ifdef ALLLOCK
1963
                        LOCK(fi->pthreadslock);
1964
#endif
1965
                        SeekFile(fi->handle,position,SEEK_END);
258✔
1966
#ifdef ALLLOCK
1967
                        UNLOCK(fi->pthreadslock);
1968
#endif
1969
                }
1970
                else {
1971
                        ADDPOS(*position,((UBYTE *)fi->POfill-(UBYTE *)fi->PObuffer));
×
1972
                }
1973
        }
1974
        else
1975
#endif
1976
        {
1977
                ADDPOS(*position,sizeof(WORD));
16,184✔
1978
        }
1979
        return(0);
1980
}
1981

1982
/*
1983
                 #] FlushOut : 
1984
                 #[ AddCoef :                                WORD AddCoef(pterm1,pterm2)
1985
*/
1986
/**
1987
 *                Adds the coefficients of the terms *ps1 and *ps2.
1988
 *                The problem comes when there is not enough space for a new
1989
 *                longer coefficient. First a local solution is tried.
1990
 *                If this is not successful we need to move terms around.
1991
 *                The possibility of a garbage collection should not be
1992
 *                ignored, as avoiding this costs very much extra space which
1993
 *                is nearly wasted otherwise.
1994
 *
1995
 *                If the return value is zero the terms cancelled.
1996
 *
1997
 *                The resulting term is left in *ps1.
1998
 */
1999

2000
WORD AddCoef(PHEAD WORD **ps1, WORD **ps2)
4,699,950✔
2001
{
2002
        GETBIDENTITY
2003
        SORTING *S = AT.SS;
4,699,950✔
2004
        WORD *s1, *s2;
4,699,950✔
2005
        WORD l1, l2, i;
4,699,950✔
2006
        WORD OutLen, *t, j;
4,699,950✔
2007
        UWORD *OutCoef;
4,699,950✔
2008
#ifdef WITHFLOAT
2009
        if ( AT.SortFloatMode ) return(AddWithFloat(BHEAD ps1,ps2));
4,699,950✔
2010
#endif
2011
        OutCoef = AN.SoScratC;
4,699,950✔
2012
        s1 = *ps1; s2 = *ps2;
4,699,950✔
2013
        GETCOEF(s1,l1);
4,699,950✔
2014
        GETCOEF(s2,l2);
4,699,950✔
2015
        if ( AddRat(BHEAD (UWORD *)s1,l1,(UWORD *)s2,l2,OutCoef,&OutLen) ) {
4,699,950✔
2016
                MLOCK(ErrorMessageLock);
×
2017
                MesCall("AddCoef");
×
2018
                MUNLOCK(ErrorMessageLock);
×
2019
                Terminate(-1);
×
2020
        }
2021
        if ( AN.ncmod != 0 ) {
4,699,950✔
2022
                if ( ( AC.modmode & POSNEG ) != 0 ) {
×
2023
                        NormalModulus(OutCoef,&OutLen);
×
2024
/*
2025
                        We had forgotten that this can also become smaller but the
2026
                        denominator isn't there. Correct in the other case
2027
                        17-may-2009 [JV]
2028
*/
2029
                        j = ABS(OutLen); OutCoef[j] = 1;
×
2030
                        for ( i = 1; i < j; i++ ) OutCoef[j+i] = 0;
×
2031
                }
2032
                else if ( BigLong(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod)) >= 0 ) {
×
2033
                        SubPLon(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod),OutCoef,&OutLen);
×
2034
                        OutCoef[OutLen] = 1;
×
2035
                        for ( i = 1; i < OutLen; i++ ) OutCoef[OutLen+i] = 0;
×
2036
                }
2037
        }
2038
        if ( !OutLen ) { *ps1 = *ps2 = 0; return(0); }
4,699,950✔
2039
        OutLen *= 2;
4,675,081✔
2040
        if ( OutLen < 0 ) i = - ( --OutLen );
4,675,081✔
2041
        else                          i = ++OutLen;
4,488,209✔
2042
        if ( l1 < 0 ) l1 = -l1;
4,675,081✔
2043
        l1 *= 2; l1++;
4,675,081✔
2044
        if ( i <= l1 ) {        /* Fits in 1 */
4,675,081✔
2045
                l1 -= i;
4,636,746✔
2046
                **ps1 -= l1;
4,636,746✔
2047
                s2 = (WORD *)OutCoef;
4,636,746✔
2048
                while ( --i > 0 ) *s1++ = *s2++;
14,234,180✔
2049
                *s1++ = OutLen;
4,636,746✔
2050
                while ( --l1 >= 0 ) *s1++ = 0;
4,637,002✔
2051
                goto RegEnd;
4,636,746✔
2052
        }
2053
        if ( l2 < 0 ) l2 = -l2;
38,331✔
2054
        l2 *= 2; l2++;
38,331✔
2055
        if ( i <= l2 ) {        /* Fits in 2 */
38,331✔
2056
                l2 -= i;
21,485✔
2057
                **ps2 -= l2;
21,485✔
2058
                s1 = (WORD *)OutCoef;
21,485✔
2059
                while ( --i > 0 ) *s2++ = *s1++;
180,175✔
2060
                *s2++ = OutLen;
21,485✔
2061
                while ( --l2 >= 0 ) *s2++ = 0;
21,613✔
2062
                *ps1 = *ps2;
21,485✔
2063
                goto RegEnd;
21,485✔
2064
        }
2065

2066
        /* Doesn't fit. Make a new term. */
2067

2068
        t = s1;
16,846✔
2069
        s1 = *ps1;
16,846✔
2070
        j = *s1++ + i - l1;                /* Space needed */
16,846✔
2071
        if ( (S->sFill + j) >= S->sTop2 ) {
16,846✔
2072
                GarbHand();
×
2073
                s1 = *ps1;
×
2074
                t = s1 + *s1 - 1;
×
2075
                j = *s1++ + i - l1;                /* Space needed */
×
2076
                l1 = *t;
×
2077
                if ( l1 < 0 ) l1  = - l1;
×
2078
                t -= l1-1;
×
2079
        }
2080
        s2 = S->sFill;
16,846✔
2081
        *s2++ = j;
16,846✔
2082
        while ( s1 < t ) *s2++ = *s1++;
126,154✔
2083
        s1 = (WORD *)OutCoef;
2084
        while ( --i > 0 ) *s2++ = *s1++;
169,212✔
2085
        *s2++ = OutLen;
16,846✔
2086
        *ps1 = S->sFill;
16,846✔
2087
        S->sFill = s2;
16,846✔
2088
RegEnd:
4,675,081✔
2089
        *ps2 = 0;
4,675,081✔
2090
        if ( **ps1 > AM.MaxTer/((LONG)(sizeof(WORD))) ) {
4,675,081✔
2091
                MLOCK(ErrorMessageLock);
×
2092
                MesPrint("Term too complex after addition in sort. MaxTermSize = %10l",
×
2093
                AM.MaxTer/sizeof(WORD));
×
2094
                MUNLOCK(ErrorMessageLock);
×
2095
                Terminate(-1);
×
2096
        }
2097
        return(1);
2098
}
2099

2100
/*
2101
                 #] AddCoef : 
2102
                 #[ AddPoly :                                WORD AddPoly(pterm1,pterm2)
2103
*/
2104
/**
2105
 *                Routine should be called when S->PolyWise != 0. It points then
2106
 *                to the position of AR.PolyFun in both terms.
2107
 *
2108
 *                We add the contents of the arguments of the two polynomials.
2109
 *                Special attention has to be given to special arguments.
2110
 *                We have to reserve a space equal to the size of one term + the
2111
 *                size of the argument of the other. The addition has to be done
2112
 *                in this routine because not all objects are reentrant.
2113
 *
2114
 *                Newer addition (12-nov-2007).
2115
 *                The PolyFun can have two arguments.
2116
 *                In that case S->PolyFlag is 2 and we have to call the routine for
2117
 *                adding rational polynomials.
2118
 *                We have to be rather careful what happens with:
2119
 *                        The location of the output
2120
 *                        The order of the terms in the arguments
2121
 *                At first we allow only univariate polynomials in the PolyFun.
2122
 *                This restriction will be lifted a.s.a.p.
2123
 *
2124
 *                @param ps1 A pointer to the position of the first term
2125
 *                @param ps2 A pointer to the position of the second term
2126
 *                @return If zero the terms cancel. Otherwise the new term is in *ps1.
2127
 */
2128

2129
WORD AddPoly(PHEAD WORD **ps1, WORD **ps2)
440,325✔
2130
{
2131
        GETBIDENTITY
2132
        SORTING *S = AT.SS;
440,325✔
2133
        WORD i;
440,325✔
2134
        WORD *s1, *s2, *m, *w, *t, oldpw = S->PolyWise;
440,325✔
2135
        s1 = *ps1 + S->PolyWise;
440,325✔
2136
        s2 = *ps2 + S->PolyWise;
440,325✔
2137
        w = AT.WorkPointer;
440,325✔
2138
/*
2139
        Add here the two arguments. Is a straight merge.
2140
*/
2141
        if ( S->PolyFlag == 2 && AR.PolyFunExp != 2 && AR.PolyFunExp != 3 ) {
440,325✔
2142
                WORD **oldSplitScratch = AN.SplitScratch;
440,314✔
2143
                LONG oldSplitScratchSize = AN.SplitScratchSize;
440,314✔
2144
                LONG oldInScratch = AN.InScratch;
440,314✔
2145
                WORD oldtype = AR.SortType;
440,314✔
2146
                if ( (WORD *)((UBYTE *)w + AM.MaxTer) >= AT.WorkTop ) {
440,314✔
2147
                        MLOCK(ErrorMessageLock);
×
2148
                        MesPrint("Program was adding polyratfun arguments");
×
2149
                        MesWork();
×
2150
                        MUNLOCK(ErrorMessageLock);
118,293✔
2151
                }
2152
                AR.SortType = SORTHIGHFIRST;
440,314✔
2153
                S->PolyWise = 0;
440,314✔
2154
                AN.SplitScratch = AN.SplitScratch1;
440,314✔
2155
                AN.SplitScratchSize = AN.SplitScratchSize1;
440,314✔
2156
                AN.InScratch = AN.InScratch1;
440,314✔
2157
                poly_ratfun_add(BHEAD s1,s2);
440,314✔
2158
                S->PolyWise = oldpw;
440,314✔
2159
                AN.SplitScratch1 = AN.SplitScratch;
440,314✔
2160
                AN.SplitScratchSize1 = AN.SplitScratchSize;
440,314✔
2161
                AN.InScratch1 = AN.InScratch;
440,314✔
2162
                AN.SplitScratch = oldSplitScratch;
440,314✔
2163
                AN.SplitScratchSize = oldSplitScratchSize;
440,314✔
2164
                AN.InScratch = oldInScratch;
440,314✔
2165
                AT.WorkPointer = w;
440,314✔
2166
                AR.SortType = oldtype;
440,314✔
2167
                if ( w[1] <= FUNHEAD ||
440,314✔
2168
                        ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) ) {
440,314✔
2169
                        *ps1 = *ps2 = 0; return(0);
2,594✔
2170
                }
2171
        }
2172
        else {
2173
                if ( w + s1[1] + s2[1] + 12 + ARGHEAD >= AT.WorkTop ) {
11✔
2174
                        MLOCK(ErrorMessageLock);
×
2175
                        MesPrint("Program was adding polyfun arguments");
×
2176
                        MesWork();
×
2177
                        MUNLOCK(ErrorMessageLock);
4✔
2178
                }
2179
                AddArgs(BHEAD s1,s2,w);
11✔
2180
        }
2181
/*
2182
        Now we need to store the result in a convenient place.
2183
*/
2184
        if ( w[1] <= FUNHEAD ) { *ps1 = *ps2 = 0; return(0); }
437,731✔
2185
        if ( w[1] <= s1[1] || w[1] <= s2[1] ) {   /* Fits in place. */
437,731✔
2186
                if ( w[1] > s1[1] ) {
5,693✔
2187
                        *ps1 = *ps2;
907✔
2188
                        s1 = s2;
907✔
2189
                }
2190
                t = s1 + s1[1];
5,693✔
2191
                m = *ps1 + **ps1;
5,693✔
2192
                i = w[1];
5,693✔
2193
                NCOPY(s1,w,i);
1,654,880✔
2194
                if ( s1 != t ) {
5,693✔
2195
                        while ( t < m ) *s1++ = *t++;
2,264✔
2196
                        **ps1 = WORDDIF(s1,(*ps1));
566✔
2197
                }
2198
                *ps2 = 0;
5,693✔
2199
        }
2200
        else {                /* Make new term */
2201
#ifdef TESTGARB
2202
                s2 = *ps2;
2203
#endif
2204
                *ps2 = 0;
432,038✔
2205
                if ( (S->sFill + (**ps1 + w[1] - s1[1])) >= S->sTop2 ) {
432,038✔
2206
#ifdef TESTGARB
2207
                        MesPrint("------Garbage collection-------");
2208
#endif
2209
                        AT.WorkPointer += w[1];
417✔
2210
                        GarbHand();
417✔
2211
                        AT.WorkPointer = w;
413✔
2212
                        s1 = *ps1;
413✔
2213
                        if ( (S->sFill + (**ps1 + w[1] - s1[1])) >= S->sTop2 ) {
413✔
2214
#ifdef TESTGARB
2215
                                UBYTE OutBuf[140];
2216
                                MLOCK(ErrorMessageLock);
2217
                                AO.OutFill = AO.OutputLine = OutBuf;
2218
                                AO.OutSkip = 3;
2219
                                FiniLine();
2220
                                i = *s2;
2221
                                while ( --i >= 0 ) {
2222
                                        TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)"  ");
2223
                                }
2224
                                FiniLine();
2225
                                AO.OutFill = AO.OutputLine = OutBuf;
2226
                                AO.OutSkip = 3;
2227
                                FiniLine();
2228
                                s2 = *ps1;
2229
                                i = *s2;
2230
                                while ( --i >= 0 ) {
2231
                                        TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)"  ");
2232
                                }
2233
                                FiniLine();
2234
                                AO.OutFill = AO.OutputLine = OutBuf;
2235
                                AO.OutSkip = 3;
2236
                                FiniLine();
2237
                                s2 = w;
2238
                                i = w[1];
2239
                                while ( --i >= 0 ) {
2240
                                        TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)"  ");
2241
                                }
2242
                                FiniLine();
2243
                                if ( AR.sLevel > 0 ) {
2244
                                        MesPrint("Please increase SubSmallExtension setup parameter.");
2245
                                }
2246
                                else {
2247
                                        MesPrint("Please increase SmallExtension setup parameter.");
2248
                                }
2249
                                MUNLOCK(ErrorMessageLock);
2250
#else
2251
                                MLOCK(ErrorMessageLock);
6✔
2252
                                if ( AR.sLevel > 0 ) {
6✔
2253
                                        MesPrint("Please increase SubSmallExtension setup parameter.");
3✔
2254
                                }
2255
                                else {
2256
                                        MesPrint("Please increase SmallExtension setup parameter.");
3✔
2257
                                }
2258
                                MUNLOCK(ErrorMessageLock);
6✔
2259
#endif
2260
                                Terminate(-1);
6✔
2261
                        }
2262
                }
2263
                t = *ps1;
432,028✔
2264
                s2 = S->sFill;
432,028✔
2265
                m = s2;
432,028✔
2266
                i = S->PolyWise;
432,028✔
2267
                NCOPY(s2,t,i);
3,052,248✔
2268
                i = w[1];
432,028✔
2269
                NCOPY(s2,w,i);
120,311,500✔
2270
                t = t + t[1];
432,028✔
2271
                w = *ps1 + **ps1;
432,028✔
2272
                while ( t < w ) *s2++ = *t++;
1,728,112✔
2273
                *m = WORDDIF(s2,m);
432,028✔
2274
                *ps1 = m;
432,028✔
2275
                S->sFill = s2;
432,028✔
2276
                if ( *m > AM.MaxTer/((LONG)sizeof(WORD)) ) {
432,028✔
2277
                        MLOCK(ErrorMessageLock);
×
2278
                        MesPrint("Term too complex after polynomial addition. MaxTermSize = %10l",
×
2279
                        AM.MaxTer/sizeof(WORD));
×
2280
                        MUNLOCK(ErrorMessageLock);
×
2281
                        Terminate(-1);
×
2282
                }
2283
        }
2284
        return(1);
2285
}
2286

2287
/*
2288
                 #] AddPoly : 
2289
                 #[ AddArgs :                                VOID AddArgs(arg1,arg2,to)
2290
*/
2291
 
2292
#define INSLENGTH(x)  w[1] = FUNHEAD+ARGHEAD+x; w[FUNHEAD] = ARGHEAD+x;
2293

2294
/**
2295
 *        Adds the arguments of two occurrences of the PolyFun.
2296
 *        @param s1 Pointer to the first occurrence.
2297
 *        @param s2 Pointer to the second occurrence.
2298
 *        @param m  Pointer to where the answer should be.
2299
 */
2300

2301
VOID AddArgs(PHEAD WORD *s1, WORD *s2, WORD *m)
16✔
2302
{
2303
        GETBIDENTITY
2304
        WORD i1, i2;
16✔
2305
        WORD *w = m, *mm, *t, *t1, *t2, *tstop1, *tstop2;
16✔
2306
        WORD tempterm[8+FUNHEAD];
16✔
2307

2308
        *m++ = AR.PolyFun; *m++ = 0; FILLFUN(m)
16✔
2309
        *m++ = 0; *m++ = 0; FILLARG(m)
16✔
2310
        if ( s1[FUNHEAD] < 0 || s2[FUNHEAD] < 0 ) {
16✔
2311
                if ( s1[FUNHEAD] < 0 ) {
×
2312
                        if ( s2[FUNHEAD] < 0 ) {        /* Both are special */
×
2313
                                if ( s1[FUNHEAD] <= -FUNCTION ) {
×
2314
                                        if ( s2[FUNHEAD] == s1[FUNHEAD] ) {
×
2315
                                                *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
×
2316
                                                FILLFUN(m)
×
2317
                                                *m++ = 2; *m++ = 1; *m++ = 3;
×
2318
                                                INSLENGTH(4+FUNHEAD)
×
2319
                                        }
2320
                                        else if ( s2[FUNHEAD] <= -FUNCTION ) {
×
2321
                                                i1 = functions[-FUNCTION-s1[FUNHEAD]].commute != 0;
×
2322
                                                i2 = functions[-FUNCTION-s2[FUNHEAD]].commute != 0;
×
2323
                                                if ( ( !i1 && i2 ) || ( i1 == i2 && i1 > i2 ) ) {
×
2324
                                                        i1 = s2[FUNHEAD];
×
2325
                                                        s2[FUNHEAD] = s1[FUNHEAD];
×
2326
                                                        s1[FUNHEAD] = i1;
×
2327
                                                }
2328
                                                *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
×
2329
                                                FILLFUN(m)
×
2330
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2331
                                                *m++ = 4+FUNHEAD; *m++ = -s2[FUNHEAD]; *m++ = FUNHEAD;
×
2332
                                                FILLFUN(m)
×
2333
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2334
                                                INSLENGTH(8+2*FUNHEAD)
×
2335
                                        }
2336
                                        else if ( s2[FUNHEAD] == -SYMBOL ) {
×
2337
                                                *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s2[FUNHEAD+1]; *m++ = 1;
×
2338
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2339
                                                *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
×
2340
                                                FILLFUN(m)
×
2341
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2342
                                                INSLENGTH(12+FUNHEAD)
×
2343
                                        }
2344
                                        else {                /* number */
2345
                                                *m++ = 4;
×
2346
                                                *m++ = ABS(s2[FUNHEAD+1]); *m++ = 1; *m++ = s2[FUNHEAD+1] < 0 ? -3: 3;
×
2347
                                                *m++ = 4+FUNHEAD; *m++ = -s1[FUNHEAD]; *m++ = FUNHEAD;
×
2348
                                                FILLFUN(m)
×
2349
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2350
                                                INSLENGTH(8+FUNHEAD)
×
2351
                                        }
2352
                                }
2353
                                else if ( s1[FUNHEAD] == -SYMBOL ) {
×
2354
                                        if ( s2[FUNHEAD] == s1[FUNHEAD] ) {
×
2355
                                                if ( s1[FUNHEAD+1] == s2[FUNHEAD+1] ) {
×
2356
                                                        *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s1[FUNHEAD+1];
×
2357
                                                        *m++ = 1; *m++ = 2; *m++ = 1; *m++ = 3;
×
2358
                                                        INSLENGTH(8)
×
2359
                                                }
2360
                                                else {
2361
                                                        if ( s1[FUNHEAD+1] > s2[FUNHEAD+1] )
×
2362
                                                                { i1 = s2[FUNHEAD+1]; i2 = s1[FUNHEAD+1]; }
2363
                                                        else { i1 = s1[FUNHEAD+1]; i2 = s2[FUNHEAD+1]; }
×
2364
                                                        *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = i1;
×
2365
                                                        *m++ = 1; *m++ = 1; *m++ = 1; *m++ = 3;
×
2366
                                                        *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = i2;
×
2367
                                                        *m++ = 1; *m++ = 1; *m++ = 1; *m++ = 3;
×
2368
                                                        INSLENGTH(16)
×
2369
                                                }
2370
                                        }
2371
                                        else if ( s2[FUNHEAD] <= -FUNCTION ) {
×
2372
                                                *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s1[FUNHEAD+1]; *m++ = 1;
×
2373
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2374
                                                *m++ = 4+FUNHEAD; *m++ = -s2[FUNHEAD]; *m++ = FUNHEAD;
×
2375
                                                FILLFUN(m)
×
2376
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2377
                                                INSLENGTH(12+FUNHEAD)
×
2378
                                        }
2379
                                        else {
2380
                                                *m++ = 4;
×
2381
                                                *m++ = ABS(s2[FUNHEAD+1]); *m++ = 1; *m++ = s2[FUNHEAD+1] < 0 ? -3: 3;
×
2382
                                                *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s1[FUNHEAD+1]; *m++ = 1;
×
2383
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2384
                                                INSLENGTH(12)
×
2385
                                        }
2386
                                }
2387
                                else {        /* Must be -SNUMBER! */
2388
                                        if ( s2[FUNHEAD] <= -FUNCTION ) {
×
2389
                                                *m++ = 4;
×
2390
                                                *m++ = ABS(s1[FUNHEAD+1]); *m++ = 1; *m++ = s1[FUNHEAD+1] < 0 ? -3: 3;
×
2391
                                                *m++ = 4+FUNHEAD; *m++ = -s2[FUNHEAD]; *m++ = FUNHEAD;
×
2392
                                                FILLFUN(m)
×
2393
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2394
                                                INSLENGTH(8+FUNHEAD)
×
2395
                                        }
2396
                                        else if ( s2[FUNHEAD] == -SYMBOL ) {
×
2397
                                                *m++ = 4;
×
2398
                                                *m++ = ABS(s1[FUNHEAD+1]); *m++ = 1; *m++ = s1[FUNHEAD+1] < 0 ? -3: 3;
×
2399
                                                *m++ = 8; *m++ = SYMBOL; *m++ = 4; *m++ = s2[FUNHEAD+1]; *m++ = 1;
×
2400
                                                *m++ = 1; *m++ = 1; *m++ = 3;
×
2401
                                                INSLENGTH(12)
×
2402
                                        }
2403
                                        else {                /* Both are numbers. add. */
2404
                                                LONG x1;
×
2405
                                                x1 = (LONG)s1[FUNHEAD+1] + (LONG)s2[FUNHEAD+1];
×
2406
                                                if ( x1 < 0 ) { i1 = (WORD)(-x1); i2 = -3; }
×
2407
                                                else { i1 = (WORD)x1; i2 = 3; }
×
2408
                                                if ( x1 && AN.ncmod != 0 ) {
×
2409
                                                        m[0] = 4;
×
2410
                                                        m[1] = i1;
×
2411
                                                        m[2] = 1;
×
2412
                                                        m[3] = i2;
×
2413
                                                        if ( Modulus(m) ) Terminate(-1);
×
2414
                                                        if ( *m == 0 ) w[1] = 0;
×
2415
                                                        else {
2416
                                                                if ( *m == 4 && ( m[1] & MAXPOSITIVE ) == m[1]
×
2417
                                                                && m[3] == 3 ) {
×
2418
                                                                        i1 = m[1];
×
2419
                                                                        m -= ARGHEAD;
×
2420
                                                                        *m++ = -SNUMBER;
×
2421
                                                                        *m++ = i1;
×
2422
                                                                        INSLENGTH(4)
×
2423
                                                                }
2424
                                                                else {
2425
                                                                        INSLENGTH(*m)
×
2426
                                                                        m += *m;
×
2427
                                                                }
2428
                                                        }                                                        
2429
                                                }
2430
                                                else {
2431
                                                        if ( x1 == 0 ) {
×
2432
                                                                w[1] = FUNHEAD;
×
2433
                                                        }
2434
                                                        else if ( ( i1 & MAXPOSITIVE ) == i1 ) {
×
2435
                                                                m -= ARGHEAD;
×
2436
                                                                *m++ = -SNUMBER;
×
2437
                                                                *m++ = (WORD)x1;
×
2438
                                                                w[1] = FUNHEAD+2;
×
2439
                                                        }
2440
                                                        else {
2441
                                                                *m++ = 4; *m++ = i1; *m++ = 1; *m++ = i2;
×
2442
                                                                INSLENGTH(4)
×
2443
                                                        }
2444
                                                }
2445
                                        }
2446
                                }
2447
                        }
2448
                        else {        /* Only s1 is special */
2449
s1only:
×
2450
/*
2451
                        Compose a term in `tempterm'
2452
*/
2453
                                t = tempterm;
×
2454
                                if ( s1[FUNHEAD] <= -FUNCTION ) {
×
2455
                                        *t++ = 4+FUNHEAD; *t++ = -s1[FUNHEAD]; *t++ = FUNHEAD;
×
2456
                                        FILLFUN(t)
×
2457
                                        *t++ = 1; *t++ = 1; *t++ = 3;
×
2458
                                }
2459
                                else if ( s1[FUNHEAD] == -SYMBOL ) {
×
2460
                                        *t++ = 8; *t++ = SYMBOL; *t++ = 4;
×
2461
                                        *t++ = s1[FUNHEAD+1]; *t++ = 1;
×
2462
                                        *t++ = 1; *t++ = 1; *t++ = 3;
×
2463
                                }
2464
                                else {
2465
                                        *t++ = 4;   *t++ = ABS(s1[FUNHEAD+1]);
×
2466
                                        *t++ = 1;   *t++ = s1[FUNHEAD+1] < 0 ? -3: 3;
×
2467
                                }
2468
                                tstop1 = t;
×
2469
                                s1 = tempterm;
×
2470
                                goto twogen;
×
2471
                        }
2472
                }
2473
                else {                /* Only s2 is special */
2474
                        t = s1;
×
2475
                        s1 = s2;
×
2476
                        s2 = t;
×
2477
                        goto s1only;
×
2478
                }
2479
        }
2480
        else {
2481
                int oldPolyFlag;
16✔
2482
                tstop1 = s1 + s1[1];
16✔
2483
                s1 += FUNHEAD+ARGHEAD;
16✔
2484
twogen:
16✔
2485
                tstop2 = s2 + s2[1];
16✔
2486
                s2 += FUNHEAD+ARGHEAD;
16✔
2487
/*
2488
                Now we should merge the expressions in s1 and s2 into m.
2489
*/
2490
                oldPolyFlag = AT.SS->PolyFlag;
16✔
2491
                AT.SS->PolyFlag = 0;
16✔
2492
                while ( s1 < tstop1 && s2 < tstop2 ) {
55✔
2493
                        i1 = CompareTerms(BHEAD s1,s2,(WORD)(-1));
39✔
2494
                        if ( i1 > 0 ) {
39✔
2495
                                i2 = *s1;
11✔
2496
                                NCOPY(m,s1,i2);
99✔
2497
                        }
2498
                        else if ( i1 < 0 ) {
28✔
2499
                                i2 = *s2;
×
2500
                                NCOPY(m,s2,i2);
×
2501
                        }
2502
                        else {        /* Coefficients should be added. */
2503
                                WORD i;
28✔
2504
                                t = s1+*s1;
28✔
2505
                                i1 = t[-1];
28✔
2506
                                i2 = *s1 - ABS(i1);
28✔
2507
                                t2 = s2 + i2;
28✔
2508
                                s2 += *s2;
28✔
2509
                                mm = m;
28✔
2510
                                NCOPY(m,s1,i2);
136✔
2511
                                t1 = s1;
28✔
2512
                                s1 = t;
28✔
2513
                                i2 = s2[-1];
28✔
2514
/*
2515
                                t1,i1 is the first coefficient
2516
                                t2,i2 is the second coefficient
2517
                                It should be placed at m,i1
2518
*/
2519
                                i1 = REDLENG(i1);
28✔
2520
                                i2 = REDLENG(i2);
28✔
2521
                                if ( AddRat(BHEAD (UWORD *)t1,i1,(UWORD *)t2,i2,(UWORD *)m,&i) ) {
28✔
2522
                                        MLOCK(ErrorMessageLock);
×
2523
                                        MesPrint("Addition of coefficients of PolyFun");
×
2524
                                        MUNLOCK(ErrorMessageLock);
×
2525
                                        Terminate(-1);
×
2526
                                }
2527
                                if ( i == 0 ) {
28✔
2528
                                        m = mm;
2529
                                }
2530
                                else {
2531
                                        i1 = INCLENG(i);
20✔
2532
                                        m += ABS(i1);
20✔
2533
                                        m[-1] = i1;
20✔
2534
                                        *mm = WORDDIF(m,mm);
20✔
2535
                                        if ( AN.ncmod != 0 ) {
20✔
2536
                                                if ( Modulus(mm) ) Terminate(-1);
×
2537
                                                if ( !*mm ) m = mm;
×
2538
                                                else m = mm + *mm;
×
2539
                                        }
2540
                                }
2541
                        }
2542
                }
2543
                while ( s1 < tstop1 ) *m++ = *s1++;
48✔
2544
                while ( s2 < tstop2 ) *m++ = *s2++;
48✔
2545
                w[1] = WORDDIF(m,w);
16✔
2546
                w[FUNHEAD] = w[1] - FUNHEAD;
16✔
2547
                if ( ToFast(w+FUNHEAD,w+FUNHEAD) ) {
16✔
2548
                        if ( w[FUNHEAD] <= -FUNCTION ) w[1] = FUNHEAD+1;
×
2549
                        else w[1] = FUNHEAD+2;
×
2550
                        if ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) w[1] = FUNHEAD;
×
2551
                }
2552
/*                AT.SS->PolyFlag = AR.PolyFunType;*/
2553
                AT.SS->PolyFlag = oldPolyFlag;
16✔
2554
        }
2555
}
16✔
2556

2557
/*
2558
                 #] AddArgs : 
2559
                 #[ Compare1 :                                WORD Compare1(term1,term2,level)
2560
*/
2561
/**
2562
 *        Compares two terms. The answer is:
2563
 *        0        equal ( with exception of the coefficient if level == 0. )
2564
 *        >0        term1 comes first.
2565
 *        <0        term2 comes first.
2566
 *        Some special precautions may be needed to keep the CompCoef routine
2567
 *        from generating overflows, although this is very unlikely in subterms.
2568
 *        This routine should not return an error condition.
2569
 *
2570
 *        Originally this routine was called Compare.
2571
 *        With the treatment of special polynomials with terms that contain only
2572
 *        symbols and the need for extreme speed for the polynomial routines we
2573
 *        made a special compare routine and now we store the address of the 
2574
 *        current compare routine in AR.CompareRoutine and have a macro Compare
2575
 *        which makes all existing code work properly and we can just replace the
2576
 *        routine on a thread by thread basis (each thread has its own AR struct).
2577
 *
2578
 *        @param term1 First input term
2579
 *        @param term2 Second input term
2580
 *        @param level The sorting level (may influence on the result)
2581
 *        @return 0        equal ( with exception of the coefficient if level == 0. )
2582
 *                >0        term1 comes first.
2583
 *                <0        term2 comes first.
2584
 *
2585
 *  When there are floating point numbers active (float_ = FLOATFUN)
2586
 *  the presence of one or more float_ functions is returned in
2587
 *  AT.SortFloatMode:
2588
 *        0: no float_
2589
 *        1: float_ in term1 only
2590
 *        2: float_ in term2 only
2591
 *        3: float_ in both terms
2592
 */
2593

2594
WORD Compare1(PHEAD WORD *term1, WORD *term2, WORD level)
41,643,940✔
2595
{
2596
        SORTING *S = AT.SS;
41,643,940✔
2597
        WORD *stopper1, *stopper2, *t2;
41,643,940✔
2598
        WORD *s1, *s2, *t1;
41,643,940✔
2599
        WORD *stopex1, *stopex2;
41,643,940✔
2600
        WORD c1, c2;
41,643,940✔
2601
        WORD prevorder;
41,643,940✔
2602
        WORD count = -1, localPoly, polyhit = -1;
41,643,940✔
2603

2604
        if ( AR.sLevel == 0 ) {
41,643,940✔
2605
                numcompares++;
36,421,610✔
2606
        }
2607

2608
        if ( S->PolyFlag ) {
41,643,940✔
2609
/*
2610
                if ( S->PolyWise != 0 ) {
2611
                        MLOCK(ErrorMessageLock);
2612
                        MesPrint("S->PolyWise is not zero!!!!!");
2613
                        MUNLOCK(ErrorMessageLock);
2614
                }
2615
*/
2616
                count = 0; localPoly = 1; S->PolyWise = polyhit = 0;
549,388✔
2617
                S->PolyFlag = AR.PolyFunType;
549,388✔
2618
                if ( AR.PolyFunType == 2 &&
549,388✔
2619
                         ( AR.PolyFunExp == 2 || AR.PolyFunExp == 3 ) ) S->PolyFlag = 1;
549,352✔
2620
        }
2621
        else { localPoly = 0; }
2622
#ifdef WITHFLOAT
2623
        AT.SortFloatMode = 0;
41,643,940✔
2624
#endif
2625
        prevorder = 0;
41,643,940✔
2626
        GETSTOP(term1,s1);
41,643,940✔
2627
        stopper1 = s1;
41,643,940✔
2628
        GETSTOP(term2,stopper2);
41,643,940✔
2629
        t1 = term1 + 1;
41,643,940✔
2630
        t2 = term2 + 1;
41,643,940✔
2631
        while ( t1 < stopper1 && t2 < stopper2 ) {
57,043,280✔
2632
                if ( *t1 != *t2 ) {
48,356,270✔
2633
                        if ( *t1 == HAAKJE ) return(PREV(-1));
67,905✔
2634
                        if ( *t2 == HAAKJE ) return(PREV(1));
55,325✔
2635
                        if ( *t1 >= (FUNCTION-1) ) {
54,055✔
2636
                                if ( *t2 < (FUNCTION-1) ) return(PREV(-1));
31,647✔
2637
                                if ( *t1 < FUNCTION && *t2 < FUNCTION ) return(PREV(*t2-*t1));
20,657✔
2638
                                if ( *t1 < FUNCTION ) return(PREV(1));
20,657✔
2639
                                if ( *t2 < FUNCTION ) return(PREV(-1));
20,657✔
2640
                                c1 = functions[*t1-FUNCTION].commute;
20,657✔
2641
                                c2 = functions[*t2-FUNCTION].commute;
20,657✔
2642
                                if ( !c1 ) {
20,657✔
2643
                                        if ( c2 ) return(PREV(1));
20,657✔
2644
                                        else return(PREV(*t2-*t1));
20,657✔
2645
                                }
2646
                                else {
2647
                                        if ( !c2 ) return(PREV(-1));
×
2648
                                        else return(PREV(*t2-*t1));
×
2649
                                }
2650
                        }
2651
                        else return(PREV(*t2-*t1));
22,408✔
2652
                }
2653
                s1 = t1 + 2;
48,288,280✔
2654
                s2 = t2 + 2;
48,288,280✔
2655
                c1 = *t1;
48,288,280✔
2656
                t1 += t1[1];
48,288,280✔
2657
                t2 += t2[1];
48,288,280✔
2658
                if ( localPoly && c1 < FUNCTION ) {
48,288,280✔
2659
                        polyhit = 1;
13,308✔
2660
                }
2661
                if ( c1 <= (FUNCTION-1)
48,288,280✔
2662
                || ( c1 >= FUNCTION && functions[c1-FUNCTION].spec > 0 ) ) {
26,179,922✔
2663
                        if ( c1 == SYMBOL ) {
22,348,040✔
2664
                                if ( *s1 == FACTORSYMBOL && *s2 == FACTORSYMBOL
6,824,340✔
2665
                                 && s1[-1] == 4 && s2[-1] == 4
3,430✔
2666
                                 && ( ( t1 < stopper1 && *t1 == HAAKJE )
3,430✔
2667
                                 || ( t1 == stopper1 && AT.fromindex ) ) ) {
×
2668
/*
2669
                                        We have to be very careful with the criteria here, because
2670
                                        Compare1 is called both in the regular sorting and by the
2671
                                        routine that makes the bracket index. In the last case
2672
                                        there is no HAAKJE subterm.
2673
*/
2674
                                        if ( s1[1] != s2[1] ) return(s2[1]-s1[1]);
3,430✔
2675
                                        s1 += 2; s2 += 2;
2,058✔
2676
                                }
2677
                                else if ( AR.SortType >= SORTPOWERFIRST ) {
6,820,900✔
2678
                                        WORD i1 = 0, *r1;
2679
                                        r1 = s1;
×
2680
                                        while ( s1 < t1 ) { i1 += s1[1]; s1 += 2; }
×
2681
                                        s1 = r1; r1 = s2;
×
2682
                                        while ( s2 < t2 ) { i1 -= s2[1]; s2 += 2; }
×
2683
                                        s2 = r1;
×
2684
                                        if ( i1 ) {
×
2685
                                                if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
×
2686
                                                return(PREV(i1));
×
2687
                                        }
2688
                                }
2689
                                while ( s1 < t1 ) {
10,021,090✔
2690
                                        if ( s2 >= t2 ) {
9,481,860✔
2691
/*                                                return(PREV(1));  */
2692
                                                if ( AR.SortType==SORTLOWFIRST ) {
8,766✔
2693
                                                        return(PREV((s1[1]>0?-1:1)));
8,429✔
2694
                                                }
2695
                                                else {
2696
                                                        return(PREV((s1[1]<0?-1:1)));
337✔
2697
                                                }
2698
                                        }
2699
                                        if ( *s1 != *s2 ) {
9,473,100✔
2700
/*                                                return(PREV(*s2-*s1)); */
2701
                                                if ( AR.SortType==SORTLOWFIRST ) {
1,028,087✔
2702
                                                        if ( *s1 < *s2 ) {
954,933✔
2703
                                                                return(PREV((s1[1]<0?1:-1)));
648,077✔
2704
                                                        }
2705
                                                        else {
2706
                                                                return(PREV((s2[1]<0?-1:1)));
306,856✔
2707
                                                        }
2708
                                                }
2709
                                                else {
2710
                                                        if ( *s1 < *s2 ) {
73,154✔
2711
                                                                return(PREV((s1[1]<0?-1:1)));
52,560✔
2712
                                                        }
2713
                                                        else {
2714
                                                                return(PREV((s2[1]<0?1:-1)));
20,594✔
2715
                                                        }
2716
                                                }
2717
                                        }
2718
                                        s1++; s2++;
8,445,020✔
2719
                                        if ( *s1 != *s2 ) return(
8,445,020✔
2720
                                                PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
5,246,890✔
2721
                                        s1++; s2++;
3,198,120✔
2722
                                }
2723
                                if ( s2 < t2 ) {
539,219✔
2724
/*                                        return(PREV(-1));  */
2725
                                        if ( AR.SortType==SORTLOWFIRST ) {
11,873✔
2726
                                                return(PREV((s2[1]<0?-1:1)));
11,859✔
2727
                                        }
2728
                                        else {
2729
                                                return(PREV((s2[1]<0?1:-1)));
14✔
2730
                                        }
2731
                                }
2732
                        }
2733
                        else if ( c1 == DOTPRODUCT ) {
15,523,700✔
2734
                                if ( AR.SortType >= SORTPOWERFIRST ) {
1,240✔
2735
                                        WORD i1 = 0, *r1;
2736
                                        r1 = s1;
×
2737
                                        while ( s1 < t1 ) { i1 += s1[2]; s1 += 3; }
×
2738
                                        s1 = r1; r1 = s2;
×
2739
                                        while ( s2 < t2 ) { i1 -= s2[2]; s2 += 3; }
×
2740
                                        s2 = r1;
×
2741
                                        if ( i1 ) {
×
2742
                                                if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
×
2743
                                                return(PREV(i1));
×
2744
                                        }
2745
                                }
2746
                                while ( s1 < t1 ) {
2,392✔
2747
                                        if ( s2 >= t2 ) return(PREV(1));
1,240✔
2748
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
1,240✔
2749
                                        s1++; s2++;
1,240✔
2750
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
1,240✔
2751
                                        s1++; s2++;
1,232✔
2752
                                        if ( *s1 != *s2 ) return(
1,232✔
2753
                                                PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
80✔
2754
                                        s1++; s2++;
1,152✔
2755
                                }
2756
                                if ( s2 < t2 ) return(PREV(-1));
1,152✔
2757
                        }
2758
                        else {
2759
                                while ( s1 < t1 ) {
124,127,200✔
2760
                                        if ( s2 >= t2 ) return(PREV(1));
123,770,700✔
2761
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
123,770,700✔
2762
                                        s1++; s2++;
108,604,700✔
2763
                                }
2764
                                if ( s2 < t2 ) return(PREV(-1));
356,495✔
2765
                        }
2766
                }
2767
                else {
2768
#if FUNHEAD != 2
2769
                        s1 += FUNHEAD-2;
25,940,281✔
2770
                        s2 += FUNHEAD-2;
25,940,281✔
2771
#endif
2772
                        if ( localPoly && c1 == AR.PolyFun ) {
25,940,281✔
2773
                                if ( count == 0 ) {
443,404✔
2774
                                  if ( S->PolyFlag == 1 ) {
443,404✔
2775
                                        WORD i1, i2;
16✔
2776
                                        if ( *s1 > 0 ) i1 = *s1;
16✔
2777
                                        else if ( *s1 <= -FUNCTION ) i1 = 1;
×
2778
                                        else i1 = 2;
×
2779
                                        if ( *s2 > 0 ) i2 = *s2;
16✔
2780
                                        else if ( *s2 <= -FUNCTION ) i2 = 1;
×
2781
                                        else i2 = 2;
×
2782
                                        if ( s1+i1 == t1 && s2+i2 == t2 ) {        /* This is the stuff */
16✔
2783
/*
2784
                                                Test for scalar nature
2785
*/
2786
                                                if ( !polyhit ) {
16✔
2787
                                                        WORD *u1, *u2, *ustop;
12✔
2788
                                                        if ( *s1 < 0 ) {
12✔
2789
                                                                if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
×
2790
                                                                        goto NoPoly;
×
2791
                                                        }
2792
                                                        else {
2793
                                                                u1 = s1 + ARGHEAD;
12✔
2794
                                                                while ( u1 < t1 ) {
43✔
2795
                                                                        u2 = u1 + *u1;
31✔
2796
                                                                        ustop = u2 - ABS(u2[-1]);
31✔
2797
                                                                        u1++;
31✔
2798
                                                                        while ( u1 < ustop ) {
58✔
2799
                                                                                if ( *u1 == INDEX ) goto NoPoly;
27✔
2800
                                                                                u1 += u1[1];
27✔
2801
                                                                        }
2802
                                                                        u1 = u2;
2803
                                                                }
2804
                                                        }
2805
                                                        if ( *s2 < 0 ) {
12✔
2806
                                                                if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
×
2807
                                                                        goto NoPoly;
×
2808
                                                        }
2809
                                                        else {
2810
                                                                u1 = s2 + ARGHEAD;
12✔
2811
                                                                while ( u1 < t2 ) {
32✔
2812
                                                                        u2 = u1 + *u1;
20✔
2813
                                                                        ustop = u2 - ABS(u2[-1]);
20✔
2814
                                                                        u1++;
20✔
2815
                                                                        while ( u1 < ustop ) {
36✔
2816
                                                                                if ( *u1 == INDEX ) goto NoPoly;
16✔
2817
                                                                                u1 += u1[1];
16✔
2818
                                                                        }
2819
                                                                        u1 = u2;
2820
                                                                }
2821
                                                        }
2822
                                                }
2823
                                                S->PolyWise = WORDDIF(s1,term1);
16✔
2824
                                                S->PolyWise -= FUNHEAD;
16✔
2825
                                                count = 1;
16✔
2826
                                                continue;
16✔
2827
                                        }
2828
                                        else {
2829
NoPoly:
×
2830
                                                S->PolyWise = localPoly = 0;
×
2831
                                        }
2832
                                  }
2833
                                  else if ( AR.PolyFunType == 2 ) {
443,388✔
2834
                                        WORD i1, i2, i1a, i2a;
443,388✔
2835
                                        if ( *s1 > 0 ) i1 = *s1;
443,388✔
2836
                                        else if ( *s1 <= -FUNCTION ) i1 = 1;
1,507✔
2837
                                        else i1 = 2;
1,507✔
2838
                                        if ( *s2 > 0 ) i2 = *s2;
443,388✔
2839
                                        else if ( *s2 <= -FUNCTION ) i2 = 1;
981✔
2840
                                        else i2 = 2;
981✔
2841
                                        if ( s1[i1] > 0 ) i1a = s1[i1];
443,388✔
2842
                                        else if ( s1[i1] <= -FUNCTION ) i1a = 1;
1,636✔
2843
                                        else i1a = 2;
1,636✔
2844
                                        if ( s2[i2] > 0 ) i2a = s2[i2];
443,388✔
2845
                                        else if ( s2[i2] <= -FUNCTION ) i2a = 1;
1,544✔
2846
                                        else i2a = 2;
1,544✔
2847
                                        if ( s1+i1+i1a == t1 && s2+i2+i2a == t2 ) {        /* This is the stuff */
443,388✔
2848
/*
2849
                                                Test for scalar nature
2850
*/
2851
                                                if ( !polyhit ) {
443,388✔
2852
                                                        WORD *u1, *u2, *ustop;
439,220✔
2853
                                                        if ( *s1 < 0 ) {
439,220✔
2854
                                                                if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
795✔
2855
                                                                        goto NoPoly;
×
2856
                                                        }
2857
                                                        else {
2858
                                                                u1 = s1 + ARGHEAD;
438,425✔
2859
                                                                while ( u1 < s1+i1 ) {
2,487,319✔
2860
                                                                        u2 = u1 + *u1;
2,048,894✔
2861
                                                                        ustop = u2 - ABS(u2[-1]);
2,048,894✔
2862
                                                                        u1++;
2,048,894✔
2863
                                                                        while ( u1 < ustop ) {
3,662,896✔
2864
                                                                                if ( *u1 == INDEX ) goto NoPoly;
1,613,998✔
2865
                                                                                u1 += u1[1];
1,613,998✔
2866
                                                                        }
2867
                                                                        u1 = u2;
2868
                                                                }
2869
                                                        }
2870
                                                        if ( s1[i1] < 0 ) {
439,220✔
2871
                                                                if ( s1[i1] != -SNUMBER && s1[i1] != -SYMBOL && s1[i1] > -FUNCTION )
868✔
2872
                                                                        goto NoPoly;
×
2873
                                                        }
2874
                                                        else {
2875
                                                                u1 = s1 +i1 + ARGHEAD;
438,352✔
2876
                                                                while ( u1 < t1 ) {
2,583,468✔
2877
                                                                        u2 = u1 + *u1;
2,145,116✔
2878
                                                                        ustop = u2 - ABS(u2[-1]);
2,145,116✔
2879
                                                                        u1++;
2,145,116✔
2880
                                                                        while ( u1 < ustop ) {
3,855,332✔
2881
                                                                                if ( *u1 == INDEX ) goto NoPoly;
1,710,220✔
2882
                                                                                u1 += u1[1];
1,710,220✔
2883
                                                                        }
2884
                                                                        u1 = u2;
2885
                                                                }
2886
                                                        }
2887
                                                        if ( *s2 < 0 ) {
439,220✔
2888
                                                                if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
697✔
2889
                                                                        goto NoPoly;
×
2890
                                                        }
2891
                                                        else {
2892
                                                                u1 = s2 + ARGHEAD;
438,523✔
2893
                                                                while ( u1 < s2+i2 ) {
2,554,449✔
2894
                                                                        u2 = u1 + *u1;
2,115,926✔
2895
                                                                        ustop = u2 - ABS(u2[-1]);
2,115,926✔
2896
                                                                        u1++;
2,115,926✔
2897
                                                                        while ( u1 < ustop ) {
3,796,960✔
2898
                                                                                if ( *u1 == INDEX ) goto NoPoly;
1,681,030✔
2899
                                                                                u1 += u1[1];
1,681,030✔
2900
                                                                        }
2901
                                                                        u1 = u2;
2902
                                                                }
2903
                                                        }
2904
                                                        if ( s2[i2] < 0 ) {
439,220✔
2905
                                                                if ( s2[i2] != -SNUMBER && s2[i2] != -SYMBOL && s2[i2] > -FUNCTION )
876✔
2906
                                                                        goto NoPoly;
×
2907
                                                        }
2908
                                                        else {
2909
                                                                u1 = s2 + i2 + ARGHEAD;
438,344✔
2910
                                                                while ( u1 < t2 ) {
2,734,545✔
2911
                                                                        u2 = u1 + *u1;
2,296,201✔
2912
                                                                        ustop = u2 - ABS(u2[-1]);
2,296,201✔
2913
                                                                        u1++;
2,296,201✔
2914
                                                                        while ( u1 < ustop ) {
4,157,512✔
2915
                                                                                if ( *u1 == INDEX ) goto NoPoly;
1,861,305✔
2916
                                                                                u1 += u1[1];
1,861,305✔
2917
                                                                        }
2918
                                                                        u1 = u2;
2919
                                                                }
2920
                                                        }
2921
                                                }
2922
                                                S->PolyWise = WORDDIF(s1,term1);
443,388✔
2923
                                                S->PolyWise -= FUNHEAD;
443,388✔
2924
                                                count = 1;
443,388✔
2925
                                                continue;
443,388✔
2926
                                        }
2927
                                        else {
2928
                                                S->PolyWise = localPoly = 0;
×
2929
                                        }
2930
                                  }
2931
                                  else {
2932
                                        S->PolyWise = localPoly = 0;
×
2933
                                  }
2934
                                }
2935
                                else {
2936
                                        t1 = term1 + S->PolyWise;
×
2937
                                        t2 = term2 + S->PolyWise;
×
2938
                                        S->PolyWise = 0;
×
2939
                                        localPoly = 0;
×
2940
                                        continue;
×
2941
                                }
2942
                        }
2943
#ifdef WITHFLOAT
2944
                        if ( c1 == FLOATFUN && t1 == stopper1 && t2 == stopper2 && AT.aux_ != 0 ) {
25,496,872✔
2945
/*
2946
                                We have two FLOATFUN's. Test whether they are 'legal'
2947
*/
2948
                                if ( TestFloat(s1-FUNHEAD) ) {
×
2949
                                        if ( TestFloat(s2-FUNHEAD) ) { AT.SortFloatMode = 3; return(0); }
×
2950
                                        else { return(1); }
2951
                                }
2952
                                else if ( TestFloat(s2-FUNHEAD) ) { return(-1); }
×
2953
                        }
2954
#endif
2955
                        while ( s1 < t1 ) {
39,794,961✔
2956
/*
2957
                                The next statement was added 9-nov-2001. It repaired a bad error
2958
*/
2959
                                if ( s2 >= t2 ) return(PREV(-1));
25,724,153✔
2960
/*
2961
                                There is a little problem here with fast arguments
2962
                                We don't want to sacrifice speed, but we like to
2963
                                keep a rational ordering. This last one suffers in
2964
                                the solution that has been chosen here.
2965
*/
2966
                                if ( AC.properorderflag ) {
25,724,153✔
2967
                                        WORD oldpolyflag;
×
2968
                                        oldpolyflag = S->PolyFlag;
×
2969
                                        S->PolyFlag = 0;
×
2970
                                        if ( ( c2 = -CompArg(s1,s2) ) != 0 ) {
×
2971
                                                S->PolyFlag = oldpolyflag; return(PREV(c2));
×
2972
                                        }
2973
                                        S->PolyFlag = oldpolyflag;
×
2974
                                        NEXTARG(s1)
×
2975
                                        NEXTARG(s2)
×
2976
                                }
2977
                                else {
2978
                                        if ( *s1 > 0 ) {
25,724,153✔
2979
                                                if ( *s2 > 0 ) {
277,660✔
2980
                                                        WORD oldpolyflag;
275,551✔
2981
                                                        stopex1 = s1 + *s1;
275,551✔
2982
                                                        if ( s2 >= t2 ) return(PREV(-1));
275,551✔
2983
                                                        stopex2 = s2 + *s2;
275,551✔
2984
                                                        s1 += ARGHEAD; s2 += ARGHEAD;
275,551✔
2985
                                                        oldpolyflag = S->PolyFlag;
275,551✔
2986
                                                        S->PolyFlag = 0;
275,551✔
2987
                                                        while ( s1 < stopex1 ) {
677,721✔
2988
                                                                if ( s2 >= stopex2 ) {
527,808✔
2989
                                                                        S->PolyFlag = oldpolyflag; return(PREV(-1));
2,896✔
2990
                                                                }
2991
                                                                if ( ( c2 = CompareTerms(BHEAD s1,s2,(WORD)1) ) != 0 ) {
524,912✔
2992
                                                                        S->PolyFlag = oldpolyflag; return(PREV(c2));
122,742✔
2993
                                                                }
2994
                                                                s1 += *s1;
402,170✔
2995
                                                                s2 += *s2;
402,170✔
2996
                                                        }
2997
                                                        S->PolyFlag = oldpolyflag;
149,913✔
2998
                                                        if ( s2 < stopex2 ) return(PREV(1));
149,913✔
2999
                                                }
3000
                                                else return(PREV(1));
3001
                                        }
3002
                                        else {
3003
                                                if ( *s2 > 0 ) return(PREV(-1));
25,446,493✔
3004
                                                if ( *s1 != *s2 ) { return(PREV(*s1-*s2)); }
25,443,383✔
3005
                                                if ( *s1 > -FUNCTION ) {
25,429,575✔
3006
                                                        if ( *++s1 != *++s2 ) { return(PREV(*s2-*s1)); }
25,414,551✔
3007
                                                }
3008
                                                s1++; s2++;
14,161,032✔
3009
                                        }
3010
                                }
3011
                        }
3012
                        if ( s2 < t2 ) return(PREV(1));
14,070,898✔
3013
                }
3014
        }
3015
#ifdef WITHFLOAT
3016
        if ( t1 < stopper1 && *t1 == FLOATFUN && t1+t1[1] == stopper1
8,686,960✔
3017
                        && TestFloat(t1) ) {
×
3018
                AT.SortFloatMode = 1; return(0);
×
3019
        }
3020
        else if ( t2 < stopper2 && *t2 == FLOATFUN && t2+t2[1] == stopper2
8,686,960✔
3021
                        && TestFloat(t2) ) {
×
3022
                AT.SortFloatMode = 2; return(0);
×
3023
        }
3024
#endif
3025
        {
3026
                if ( AR.SortType != SORTLOWFIRST ) {
8,686,960✔
3027
                        if ( t1 < stopper1 ) return(PREV(1));
3,169,999✔
3028
                        if ( t2 < stopper2 ) return(PREV(-1));
669,227✔
3029
                }
3030
                else {
3031
                        if ( t1 < stopper1 ) return(PREV(-1));
5,516,963✔
3032
                        if ( t2 < stopper2 ) return(PREV(1));
5,508,779✔
3033
                }
3034
        }
3035
        if ( level == 3 ) return(CompCoef(term1,term2));
5,640,931✔
3036
        if ( level >= 1 )
5,640,931✔
3037
                return(CompCoef(term2,term1));
414,997✔
3038
        return(0);
3039
}
3040

3041
/*
3042
                 #] Compare1 : 
3043
                 #[ CompareSymbols :                        WORD CompareSymbols(term1,term2,par)
3044
*/
3045
/**
3046
 *        Compares the terms, based on the value of AN.polysortflag.
3047
 *        If term1 < term2 the return value is -1
3048
 *        If term1 > term2 the return value is  1
3049
 *        If term1 = term2 the return value is  0
3050
 *        The coefficients may differ.
3051
 *        The terms contain only a single subterm of type SYMBOL.
3052
 *        If AN.polysortflag = 0 it is a 'regular' compare.
3053
 *        If AN.polysortflag = 1 the sum of the powers is more important
3054
 *        par is a dummy parameter to make the parameter field identical
3055
 *        to that of Compare1 which is the regular compare routine in sort.c
3056
 */
3057

3058
WORD CompareSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
4,094,827✔
3059
{
3060
        int sum1, sum2;
4,094,827✔
3061
        WORD *t1, *t2, *tt1, *tt2;
4,094,827✔
3062
        int low, high;
4,094,827✔
3063
        DUMMYUSE(par);
4,094,827✔
3064
        if ( AR.SortType == SORTLOWFIRST ) { low = 1; high = -1; }
4,094,827✔
3065
        else { low = -1; high = 1; }
3,972,427✔
3066
        t1 = term1 + 1; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); t1 += 2;
4,094,827✔
3067
        t2 = term2 + 1; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); t2 += 2;
4,094,827✔
3068
        if ( AN.polysortflag > 0 ) {
4,094,827✔
3069
                sum1 = 0; sum2 = 0;
×
3070
                while ( t1 < tt1 ) { sum1 += t1[1]; t1 += 2; }
×
3071
                while ( t2 < tt2 ) { sum2 += t2[1]; t2 += 2; }
×
3072
                if ( sum1 < sum2 ) return(low);
×
3073
                if ( sum1 > sum2 ) return(high);
×
3074
                t1 = term1+3; t2 = term2 + 3;
×
3075
        }
3076
        while ( t1 < tt1 && t2 < tt2 ) {
5,621,720✔
3077
                if ( *t1 > *t2 ) return(low);
3,402,686✔
3078
                if ( *t1 < *t2 ) return(high);
3,013,379✔
3079
                if ( t1[1] < t2[1] ) return(low);
2,883,762✔
3080
                if ( t1[1] > t2[1] ) return(high);
2,055,127✔
3081
                t1 += 2; t2 += 2;
1,526,897✔
3082
        }
3083
        if ( t1 < tt1 ) return(high);
2,219,037✔
3084
        if ( t2 < tt2 ) return(low);
284,848✔
3085
        return(0);
3086
}
3087

3088
/*
3089
                 #] CompareSymbols : 
3090
                 #[ CompareHSymbols :                WORD CompareHSymbols(term1,term2,par)
3091
*/
3092
/**
3093
 *        Compares terms that can have only SYMBOL and HAAKJE subterms.
3094
 *        If term1 < term2 the return value is -1
3095
 *        If term1 > term2 the return value is  1
3096
 *        If term1 = term2 the return value is  0
3097
 *        par is a dummy parameter to make the parameter field identical
3098
 *        to that of Compare1 which is the regular compare routine in sort.c
3099
 */
3100

3101
WORD CompareHSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
×
3102
{
3103
        WORD *t1, *t2, *tt1, *tt2, *ttt1, *ttt2;
×
3104
        DUMMYUSE(par);
×
3105
        DUMMYUSE(AT.WorkPointer);
×
3106
        t1 = term1 + 1; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); t1 += 2;
×
3107
        t2 = term2 + 1; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); t2 += 2;
×
3108
        while ( t1 < tt1 && t2 < tt2 ) {
×
3109
                if ( *t1 != *t2 ) {
×
3110
                        if ( t1[0] < t2[0] ) return(-1);
×
3111
                        return(1);
×
3112
                }
3113
                else if ( *t1 == HAAKJE ) {
×
3114
                        t1 += 3; t2 += 3; continue;
×
3115
                }
3116
                ttt1 = t1+t1[1]; ttt2 = t2+t2[1];
×
3117
                while ( t1 < ttt1 && t2 < ttt2 ) {
×
3118
                        if ( *t1 > *t2 ) return(-1);
×
3119
                        if ( *t1 < *t2 ) return(1);
×
3120
                        if ( t1[1] < t2[1] ) return(-1);
×
3121
                        if ( t1[1] > t2[1] ) return(1);
×
3122
                        t1 += 2; t2 += 2;
×
3123
                }
3124
                if ( t1 < ttt1 ) return(1);
×
3125
                if ( t2 < ttt2 ) return(-1);
×
3126
        }
3127
        if ( t1 < tt1 ) return(1);
×
3128
        if ( t2 < tt2 ) return(-1);
×
3129
        return(0);
3130
}
3131

3132
/*
3133
                 #] CompareHSymbols : 
3134
                 #[ ComPress :                                LONG ComPress(ss,n)
3135
*/
3136
/**
3137
 *                Gets a list of pointers to terms and compresses the terms.
3138
 *                In n it collects the number of terms and the return value
3139
 *                of the function is the space that is occupied.
3140
 *
3141
 *                We have to pay some special attention to the compression of
3142
 *                terms with a PolyFun. This PolyFun should occur only straight
3143
 *                before the coefficient, so we can use the same trick as for
3144
 *                the coefficient to sabotage compression of this object
3145
 *                (Replace in the history the function pointer by zero. This
3146
 *                is safe, because terms that would be identical otherwise would
3147
 *                have been added).
3148
 *
3149
 *                @param ss Array of pointers to terms to be compressed.
3150
 *                @param n  Number of pointers in ss.
3151
 *                @return   Total number of words needed for the compressed result.
3152
 */
3153

3154
LONG ComPress(WORD **ss, LONG *n)
3,932✔
3155
{
3156
        GETIDENTITY
2,497✔
3157
        WORD *t, *s, j, k;
3,932✔
3158
        LONG size = 0;
3,932✔
3159
        int newsize, i;
3,932✔
3160
/*
3161
                        #[ debug :
3162

3163
        WORD **sss = ss;
3164

3165
        if ( AP.DebugFlag ) {
3166
                UBYTE OutBuf[140];
3167
                MLOCK(ErrorMessageLock);
3168
                MesPrint("ComPress:");
3169
                AO.OutFill = AO.OutputLine = OutBuf;
3170
                AO.OutSkip = 3;
3171
                FiniLine();
3172
                ss = sss;
3173
                while ( *ss ) {
3174
                        s = *ss++;
3175
                        j = *s;
3176
                        if ( j < 0 ) {
3177
                                j = s[1] + 2;
3178
                        }
3179
                        while ( --j >= 0 ) {
3180
                                TalToLine((UWORD)(*s++)); TokenToLine((UBYTE *)"  ");
3181
                        }
3182
                        FiniLine();
3183
                }
3184
                AO.OutSkip = 0;
3185
                FiniLine();
3186
                MUNLOCK(ErrorMessageLock);
3187
                ss = sss;
3188
        }
3189

3190
                        #] debug : 
3191
*/
3192
        *n = 0;
3,932✔
3193
        if ( AT.SS == AT.S0 && !AR.NoCompress ) {
3,932✔
3194
                if ( AN.compressSize == 0 ) {
3,262✔
3195
                        if ( *ss ) { AN.compressSize = **ss + 64; }
29✔
3196
                        else       { AN.compressSize = AM.MaxTer/sizeof(WORD) + 2; }
×
3197
                        AN.compressSpace = (WORD *)Malloc1(AN.compressSize*sizeof(WORD),"Compression");
29✔
3198
                }
3199
                AN.compressSpace[0] = 0;
3,262✔
3200
                while ( *ss ) {
1,537,146✔
3201
                        k = 0;
1,533,884✔
3202
                        s = *ss;
1,533,884✔
3203
                        j = *s++;
1,533,884✔
3204
                        if ( j > AN.compressSize ) {
1,533,884✔
3205
                                newsize = j + 64;
×
3206
                                t = (WORD *)Malloc1(newsize*sizeof(WORD),"Compression");
×
3207
                                t[0] = 0;
×
3208
                                if ( AN.compressSpace ) {
×
3209
                                        for ( i = 0; i < *AN.compressSpace; i++ ) t[i] = AN.compressSpace[i];
×
3210
                                        M_free(AN.compressSpace,"Compression");
×
3211
                                }
3212
                                AN.compressSpace = t;
×
3213
                                AN.compressSize = newsize;
×
3214
                        }
3215
                        t = AN.compressSpace;
1,533,884✔
3216
                        i = *t - 1;
1,533,884✔
3217
                        *t++ = j; j--;
1,533,884✔
3218
                        if ( AR.PolyFun ) {
1,533,884✔
3219
                                WORD *polystop, *sa;
×
3220
                                sa = s + j;
×
3221
                                sa -= ABS(sa[-1]);
×
3222
                                polystop = s;
×
3223
                                while ( polystop < sa && *polystop != AR.PolyFun ) {
×
3224
                                        polystop += polystop[1];
×
3225
                                }
3226
                                while ( i > 0 && j > 0 && *s == *t && s < polystop ) {
×
3227
                                        i--; j--; s++; t++; k--;
×
3228
                                }
3229
                        }
3230
                        else {
3231
                                WORD *sa;
1,533,884✔
3232
                                sa = s + j;
1,533,884✔
3233
                                sa -= ABS(sa[-1]);
1,533,884✔
3234
                                while ( i > 0 && j > 0 && *s == *t && s < sa ) { i--; j--; s++; t++; k--; }
7,109,120✔
3235
                        }
3236
                        if ( k < -1 ) {
1,533,884✔
3237
                                s[-1] = j;
1,530,618✔
3238
                                s[-2] = k;
1,530,618✔
3239
                                *ss = s-2;
1,530,618✔
3240
                                size += j + 2;
1,530,618✔
3241
                        }
3242
                        else {
3243
                                size += *AN.compressSpace;
3,266✔
3244
                                if ( k == -1 ) { t--; s--; j++; }
3,266✔
3245
                        }
3246
                        while ( --j >= 0 ) *t++ = *s++;
7,684,490✔
3247
/*                                        Sabotage getting into the coefficient next time */
3248
                        t = AN.compressSpace + *AN.compressSpace;
1,533,884✔
3249
                        t[-(ABS(t[-1]))] = 0;
1,533,884✔
3250
                        ss++;
1,533,884✔
3251
                        (*n)++;
1,533,884✔
3252
                }
3253
        }
3254
        else {
3255
                while ( *ss ) {
8,575,790✔
3256
                        size += *(*ss++);
8,575,110✔
3257
                        (*n)++;
8,575,110✔
3258
                }
3259
        }
3260
/*
3261
                        #[ debug :
3262

3263
        if ( AP.DebugFlag ) {
3264
                UBYTE OutBuf[140];
3265
                AO.OutFill = AO.OutputLine = OutBuf;
3266
                AO.OutSkip = 3;
3267
                FiniLine();
3268
                ss = sss;
3269
                while ( *ss ) {
3270
                        s = *ss++;
3271
                        j = *s;
3272
                        if ( j < 0 ) {
3273
                                j = s[1] + 2;
3274
                        }
3275
                        while ( --j >= 0 ) {
3276
                                TalToLine((UWORD)(*s++)); TokenToLine((UBYTE *)"  ");
3277
                        }
3278
                        FiniLine();
3279
                }
3280
                AO.OutSkip = 0;
3281
                FiniLine();
3282
        }
3283

3284
                        #] debug : 
3285
*/
3286
        return(size);
3,932✔
3287
}
3288

3289
/*
3290
                 #] ComPress : 
3291
                 #[ SplitMerge :                                VOID SplitMerge(Point,number)
3292
*/
3293
/**
3294
 *                Algorithm by J.A.M.Vermaseren (31-7-1988)
3295
 *
3296
 *                Note that AN.SplitScratch and AN.InScratch are used also in GarbHand
3297
 *
3298
 *                Merge sort in memory. The input is an array of pointers.
3299
 *                Sorting is done recursively by dividing the array in two equal parts
3300
 *                and calling SplitMerge for each.
3301
 *                When the parts are small enough we can do the compare and take the
3302
 *                appropriate action.
3303
 *                An addition is that we look for 'runs'. Sequences that are already
3304
 *                ordered. This happens a lot when there is very little action in a
3305
 *                module. This made FORM faster by a few percent.
3306
 *
3307
 *                @param  Pointer The array of pointers to the terms to be sorted.
3308
 *                @param  number  The number of pointers in Pointer.
3309
 *
3310
 *                The terms are supposed to be sitting in the small buffer and there
3311
 *                is supposed to be an extension to this buffer for when there are
3312
 *                two terms that should be added and the result takes more space than
3313
 *                each of the original terms. The notation guarantees that the result
3314
 *                never needs more space than the sum of the spaces of the original
3315
 *                terms.
3316
 */
3317

3318
#ifdef NEWSPLITMERGE
3319

3320
LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
24,738,670✔
3321
{
3322
        GETBIDENTITY
3323
        SORTING *S = AT.SS;
24,738,670✔
3324
        WORD **pp3, **pp1, **pp2, **pptop;
24,738,670✔
3325
        LONG i, newleft, newright, split;
24,738,670✔
3326

3327
#ifdef SPLITMERGEDEBUG
3328
        /* Print current array state on entry. */
3329
        printf("%4ld: ", number);
3330
        for (int ii = 0; ii < S->sTerms; ii++) {
3331
                if ( (S->sPointer)[ii] ) {
3332
                        printf("%4d ", (unsigned)(S->sPointer[ii]-S->sBuffer));
3333
                }
3334
                else {
3335
                        printf(".... ");
3336
                }
3337
        }
3338
        printf("\n");
3339
        fflush(stdout);
3340
#endif
3341

3342
        if ( number < 2 ) return(number);
24,738,670✔
3343
        if ( number == 2 ) {
21,437,430✔
3344
                pp1 = Pointer; pp2 = pp1 + 1;
11,756,930✔
3345
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
11,756,930✔
3346
                        pp3 = (WORD **)(*pp1); *pp1 = *pp2; *pp2 = (WORD *)pp3;
798,460✔
3347
                }
3348
                else if ( i == 0 ) {
10,958,470✔
3349
                        number--;
790,590✔
3350
                        if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) == 0 ) number = 0; }
790,590✔
3351
                        else               { if ( AddCoef(BHEAD pp1,pp2) == 0 ) number = 0; }
617,588✔
3352
                }
3353
                return(number);
11,756,930✔
3354
        }
3355
        pptop = Pointer + number;
9,680,480✔
3356
        split = number/2;
9,680,480✔
3357
        newleft  = SplitMerge(BHEAD Pointer,split);
9,680,480✔
3358
        newright = SplitMerge(BHEAD Pointer+split,number-split);
9,680,460✔
3359
        if ( newright == 0 ) return(newleft);
9,680,420✔
3360
/*
3361
        We compare the last of the left with the first of the right
3362
        If they are already in order, we will be done quickly.
3363
        We may have to compactify the buffer because the recursion may
3364
        have created holes. Also this compare may result in equal terms.
3365
        Addition of 23-jul-1999. It makes things a bit faster.
3366
*/
3367
        if ( newleft > 0 && newright > 0 &&
9,679,760✔
3368
        ( i = CompareTerms(BHEAD Pointer[newleft-1],Pointer[split],(WORD)0) ) >= 0 ) {
9,676,810✔
3369
                pp2 = Pointer+split; pp1 = Pointer+newleft-1;
8,991,660✔
3370
                if ( i == 0 ) {
8,991,660✔
3371
                        if ( S->PolyWise ) {
1,140,071✔
3372
                                if ( AddPoly(BHEAD pp1,pp2) > 0 ) pp1++;
256,464✔
3373
                                else newleft--;
12✔
3374
                        }
3375
                        else {
3376
                                if ( AddCoef(BHEAD pp1,pp2) > 0 ) pp1++;
883,607✔
3377
                                else newleft--;
1,359✔
3378
                        }
3379
                        *pp2++ = 0; newright--;
1,140,061✔
3380
                }
3381
                else pp1++;
7,851,590✔
3382
                newleft += newright;
8,991,660✔
3383
                if ( pp1 < pp2 ) {
8,991,660✔
3384
                        while ( --newright >= 0 ) *pp1++ = *pp2++;
1,182,365✔
3385
                        while ( pp1 < pptop ) *pp1++ = 0;
22,539,210✔
3386
                }
3387
                return(newleft);
8,991,660✔
3388
        }
3389

3390
        if ( split >= AN.SplitScratchSize ) {
688,097✔
3391
                AN.SplitScratchSize = (split*3)/2+100;
905✔
3392
                if ( AN.SplitScratchSize > S->Terms2InSmall/2 )
905✔
3393
                        AN.SplitScratchSize = S->Terms2InSmall/2;
4✔
3394
                if ( AN.SplitScratch ) M_free(AN.SplitScratch,"AN.SplitScratch");
905✔
3395
                AN.SplitScratch = (WORD **)Malloc1(AN.SplitScratchSize*sizeof(WORD *),"AN.SplitScratch");
905✔
3396
        }
3397

3398
        pp3 = AN.SplitScratch; pp1 = Pointer;
688,097✔
3399
        /* Move rather than copy, so GarbHand can't double-count. */
3400
        for ( i = 0; i < newleft; i++ ) { *pp3++ = *pp1; *pp1++ = 0; }
9,682,786✔
3401
        AN.InScratch = newleft;
688,097✔
3402
        pp1 = AN.SplitScratch; pp2 = Pointer + split; pp3 = Pointer;
688,097✔
3403

3404
#ifdef NEWSPLITMERGETIMSORT
3405
/*
3406
                An improvement in the style of Timsort
3407
*/
3408
        while ( newleft > 8 ) {
712,021✔
3409
                /* Check the middle of the LHS terms */
3410
                LONG nnleft = newleft/2;
179,975✔
3411
                if ( ( i = CompareTerms(BHEAD pp1[nnleft],*pp2,(WORD)0) ) < 0 ) {
179,975✔
3412
                        /* The terms are not in order. Break out and continue as normal. */
3413
                        break;
3414
                }
3415
                /* The terms merge or are in order. Copy pointers up to this point. */
3416
                /* In the copy, zero the skipped pointers so GarbHand can't double-count. */
3417
                for (int iii = 0; iii < nnleft; iii++) {
477,020✔
3418
                        *pp3++ = *pp1;
452,127✔
3419
                        *pp1++ = 0;
452,127✔
3420
                }
3421
                newleft -= nnleft;
24,893✔
3422
                if ( i == 0 ) {
24,893✔
3423
                        if ( S->PolyWise ) { i = AddPoly(BHEAD pp1,pp2); }
969✔
3424
                        else               { i = AddCoef(BHEAD pp1,pp2); }
861✔
3425
                        if ( i == 0 ) {
969✔
3426
                                /* The terms cancelled. The next term goes in *pp3. Don't move. */
3427
                        }
3428
                        else {
3429
                                /* The terms added. Advance pp3. */
3430
                                *pp3++ = *pp1;
969✔
3431
                        }
3432
                        /* We have taken a LHS (copy) and RHS term. */
3433
                        *pp2++ = 0;
969✔
3434
                        newright--;
969✔
3435
                        *pp1++ = 0;
969✔
3436
                        newleft--;
969✔
3437
                        break;
969✔
3438
                }
3439
        }
3440
#endif
3441

3442
        while ( newleft > 0 && newright > 0 ) {
11,824,556✔
3443
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
11,136,459✔
3444
                        *pp3++ = *pp2;
4,925,763✔
3445
                        *pp2++ = 0;
4,925,763✔
3446
                        newright--;
4,925,763✔
3447
                }
3448
                else if ( i > 0 ) {
6,210,686✔
3449
                        *pp3++ = *pp1;
3,002,045✔
3450
                        *pp1++ = 0;
3,002,045✔
3451
                        newleft--;
3,002,045✔
3452
                }
3453
                else {
3454
                        if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3,208,646✔
3455
                        else {               if ( AddCoef(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3,197,884✔
3456
                        *pp1++ = 0; *pp2++ = 0; newleft--; newright--;
3,208,646✔
3457
                }
3458
        }
3459
        for ( i = 0; i < newleft; i++ ) { *pp3++ = *pp1; *pp1++ = 0; }
3,019,000✔
3460
        if ( pp3 == pp2 ) {
688,097✔
3461
                pp3 += newright;
549,171✔
3462
        } else {
3463
                for ( i = 0; i < newright; i++ ) { *pp3++ = *pp2++; }
576,301✔
3464
        }
3465
        newleft = pp3 - Pointer;
688,097✔
3466
        while ( pp3 < pptop ) *pp3++ = 0;
33,413,528✔
3467
        AN.InScratch = 0;
688,097✔
3468
        return(newleft);
688,097✔
3469
}
3470

3471
#else
3472

3473
LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
3474
{
3475
        GETBIDENTITY
3476
        SORTING *S = AT.SS;
3477
        WORD **pp3, **pp1, **pp2;
3478
        LONG nleft, nright, i, newleft, newright;
3479
        WORD **pptop;
3480

3481
#ifdef SPLITMERGEDEBUG
3482
        /* Print current array state on entry. */
3483
        printf("%4ld: ", number);
3484
        for (int ii = 0; ii < S->sTerms; ii++) {
3485
                if ( (S->sPointer)[ii] ) {
3486
                        printf("%4d ", (unsigned)(S->sPointer[ii]-S->sBuffer));
3487
                }
3488
                else {
3489
                        printf(".... ");
3490
                }
3491
        }
3492
        printf("\n");
3493
        fflush(stdout);
3494
#endif
3495

3496
        if ( number < 2 ) return(number);
3497
        if ( number == 2 ) {
3498
                pp1 = Pointer; pp2 = pp1 + 1;
3499
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
3500
                        pp3 = (WORD **)(*pp1); *pp1 = *pp2; *pp2 = (WORD *)pp3;
3501
                }
3502
                else if ( i == 0 ) {
3503
                  number--;
3504
                  if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) == 0 ) { number = 0; } }
3505
                  else {               if ( AddCoef(BHEAD pp1,pp2) == 0 ) { number = 0; } }
3506
                }
3507
                return(number);
3508
        }
3509
        pptop = Pointer + number;
3510
        nleft = number >> 1; nright = number - nleft;
3511
        newleft  = SplitMerge(BHEAD Pointer,nleft);
3512
        newright = SplitMerge(BHEAD Pointer+nleft,nright);
3513
/*
3514
        We compare the last of the left with the first of the right
3515
        If they are already in order, we will be done quickly.
3516
        We may have to compactify the buffer because the recursion may
3517
        have created holes. Also this compare may result in equal terms.
3518
        Addition of 23-jul-1999. It makes things a bit faster.
3519
*/
3520
        if ( newleft > 0 && newright > 0 &&
3521
        ( i = CompareTerms(BHEAD Pointer[newleft-1],Pointer[nleft],(WORD)0) ) >= 0 ) {
3522
                pp2 = Pointer+nleft; pp1 = Pointer+newleft-1;
3523
                if ( i == 0 ) {
3524
                  if ( S->PolyWise ) {
3525
                        if ( AddPoly(BHEAD pp1,pp2) > 0 ) pp1++;
3526
                        else newleft--;
3527
                  }
3528
                  else {
3529
                        if ( AddCoef(BHEAD pp1,pp2) > 0 ) pp1++;
3530
                        else newleft--;
3531
                  }
3532
                  *pp2++ = 0; newright--;
3533
                }
3534
                else pp1++;
3535
                newleft += newright;
3536
                if ( pp1 < pp2 ) {
3537
                        while ( --newright >= 0 ) *pp1++ = *pp2++;
3538
                        while ( pp1 < pptop ) *pp1++ = 0;
3539
                }
3540
                return(newleft);
3541
        }
3542
        if ( nleft > AN.SplitScratchSize ) {
3543
                AN.SplitScratchSize = (nleft*3)/2+100;
3544
                if ( AN.SplitScratchSize > S->Terms2InSmall/2 )
3545
                         AN.SplitScratchSize = S->Terms2InSmall/2;
3546
                if ( AN.SplitScratch ) M_free(AN.SplitScratch,"AN.SplitScratch");
3547
                AN.SplitScratch = (WORD **)Malloc1(AN.SplitScratchSize*sizeof(WORD *),"AN.SplitScratch");
3548
        }
3549
        pp3 = AN.SplitScratch; pp1 = Pointer; i = nleft;
3550
        do { *pp3++ = *pp1; *pp1++ = 0; } while ( *pp1 && --i > 0 );
3551
        if ( i > 0 ) { *pp3 = 0; i--; }
3552
        AN.InScratch = nleft - i;
3553
        pp1 = AN.SplitScratch; pp2 = Pointer + nleft; pp3 = Pointer;
3554
        while ( nleft > 0 && nright > 0 && *pp1 && *pp2 ) {
3555
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
3556
                        *pp3++ = *pp2;
3557
                        *pp2++ = 0;
3558
                        nright--;
3559
                }
3560
                else if ( i > 0 ) {
3561
                        *pp3++ = *pp1;
3562
                        *pp1++ = 0;
3563
                        nleft--;
3564
                }
3565
                else {
3566
                  if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3567
                  else {               if ( AddCoef(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3568
                  *pp1++ = 0; *pp2++ = 0; nleft--; nright--;
3569
                }
3570
        }
3571
        while ( --nleft  >= 0 && *pp1 ) { *pp3++ = *pp1; *pp1++ = 0; }
3572
        while ( --nright >= 0 && *pp2 ) { *pp3++ = *pp2++; }
3573
        nleft = pp3 - Pointer;
3574
        while ( pp3 < pptop ) *pp3++ = 0;
3575
        AN.InScratch = 0;
3576
        return(nleft);
3577
}
3578

3579
#endif
3580

3581
/*
3582
                 #] SplitMerge : 
3583
                 #[ GarbHand :                                VOID GarbHand()
3584
*/
3585
/**
3586
 *                Garbage collection that takes place when the small extension is full
3587
 *                and we need to place more terms there.
3588
 *                When this is the case there are many holes in the small buffer and
3589
 *                the whole can be compactified.
3590
 *                The major complication is the buffer for SplitMerge.
3591
 *                There are to options for temporary memory:
3592
 *                1: find some buffer that has enough space (maybe in the large
3593
 *                   buffer).
3594
 *                2: allocate a buffer. Give it back afterwards of course.
3595
 *                If the small extension is properly dimensioned this routine should
3596
 *                be called very rarely. Most of the time it will be called when the
3597
 *                polyfun or polyratfun is active.
3598
 */
3599

3600
VOID GarbHand(VOID)
417✔
3601
{
3602
        GETIDENTITY
305✔
3603
        SORTING *S = AT.SS;
417✔
3604
        WORD **Point, *s2, *t, *garbuf, i;
417✔
3605
        LONG k, total = 0;
417✔
3606
        int tobereturned = 0;
417✔
3607
/*
3608
        Compute the size needed. Put it in total.
3609
*/
3610
#ifdef TESTGARB
3611
        MLOCK(ErrorMessageLock);
3612
        MesPrint("in:  S->sFill = %l, S->sTop2 = %l",S->sFill-S->sBuffer,S->sTop2-S->sBuffer);
3613
#endif
3614
        Point = S->sPointer;
417✔
3615
        k = S->sTerms;
417✔
3616
        while ( --k >= 0 ) {
8,332,305✔
3617
                if ( ( s2 = *Point++ ) != 0 ) { total += *s2; }
8,331,890✔
3618
        }
3619
        Point = AN.SplitScratch;
417✔
3620
        k = AN.InScratch;
417✔
3621
        while ( --k >= 0 ) {
419✔
3622
                if ( ( s2 = *Point++ ) != 0 ) { total += *s2; }
2✔
3623
        }
3624
#ifdef TESTGARB
3625
        MesPrint("total = %l, nterms = %l",total,AN.InScratch);
3626
        MUNLOCK(ErrorMessageLock);
3627
#endif
3628
/*
3629
        Test now whether it fits. If so deal with the problem inside
3630
        the memory at the tail of the large buffer.
3631
*/
3632
        if ( S->lBuffer != 0 && S->lFill + total <= S->lTop ) {
417✔
3633
                garbuf = S->lFill;
3634
        }
3635
        else {
3636
                garbuf = (WORD *)Malloc1(total*sizeof(WORD),"Garbage buffer");
×
3637
                tobereturned = 1;
×
3638
        }
3639
        t = garbuf;
417✔
3640
        Point = S->sPointer;
417✔
3641
        k = S->sTerms;
417✔
3642
        while ( --k >= 0 ) {
8,305,995✔
3643
                if ( *Point ) {
8,305,580✔
3644
                        s2 = *Point++;
2,859,453✔
3645
                        i = *s2;
2,859,453✔
3646
                        NCOPY(t,s2,i);
550,352,400✔
3647
                }
3648
                else { Point++; }
5,446,127✔
3649
        }
3650
        Point = AN.SplitScratch;
417✔
3651
        k = AN.InScratch;
417✔
3652
        while ( --k >= 0 ) {
419✔
3653
                if ( *Point ) {
2✔
3654
                        s2 = *Point++;
1✔
3655
                        i = *s2;
1✔
3656
                        NCOPY(t,s2,i);
667✔
3657
                }
3658
                else Point++;
1✔
3659
        }
3660
        s2 = S->sBuffer;
417✔
3661
        t = garbuf;
417✔
3662
        Point = S->sPointer;
417✔
3663
        k = S->sTerms;
417✔
3664
        while ( --k >= 0 ) {
8,283,055✔
3665
                if ( *Point ) {
8,282,640✔
3666
                        *Point++ = s2;
2,856,308✔
3667
                        i = *t;
2,856,308✔
3668
                        NCOPY(s2,t,i);
548,948,400✔
3669
                }
3670
                else { Point++; }
5,426,327✔
3671
        }
3672
        Point = AN.SplitScratch;
417✔
3673
        k = AN.InScratch;
417✔
3674
        while ( --k >= 0 ) {
419✔
3675
                if ( *Point ) {
2✔
3676
                        *Point++ = s2;
1✔
3677
                        i = *t;
1✔
3678
                        NCOPY(s2,t,i);
667✔
3679
                }
3680
                else Point++;
1✔
3681
        }
3682
        S->sFill = s2;
417✔
3683
#ifdef TESTGARB
3684
        MLOCK(ErrorMessageLock);
3685
        MesPrint("out: S->sFill = %l, S->sTop2 = %l",S->sFill-S->sBuffer,S->sTop2-S->sBuffer);
3686
        if ( S->sFill >= S->sTop2 ) {
3687
                MesPrint("We are in deep trouble");
3688
        }
3689
        MUNLOCK(ErrorMessageLock);
3690
#endif
3691
        if ( tobereturned ) M_free(garbuf,"Garbage buffer");
417✔
3692
        return;
417✔
3693
}
3694

3695
/*
3696
                 #] GarbHand : 
3697
                 #[ MergePatches :                        WORD MergePatches(par)
3698
*/
3699
/**
3700
 *        The general merge routine. Can be used for the large buffer
3701
 *        and the file merging. The array S->Patches tells where the patches
3702
 *        start S->pStop tells where they end (has to be computed first).
3703
 *        The end of a 'line to be merged' is indicated by a zero. If
3704
 *        the end is reached without running into a zero or a term
3705
 *        runs over the boundary of a patch it is a file merging operation
3706
 *        and a new piece from the file is read in.
3707
 *
3708
 *        @param par
3709
 *        If par == 0 the sort is for file -> outputfile.
3710
 *        If par == 1 the sort is for large buffer -> sortfile.
3711
 *        If par == 2 the sort is for large buffer -> outputfile.
3712
 *
3713
 */
3714

3715
WORD MergePatches(WORD par)
411✔
3716
{
3717
        GETIDENTITY
251✔
3718
        SORTING *S = AT.SS;
411✔
3719
        WORD **poin, **poin2, ul, k, i, im, *m1;
411✔
3720
        WORD *p, lpat, mpat, level, l1, l2, r1, r2, r3, c;
411✔
3721
        WORD *m2, *m3, r31, r33, ki, *rr;
411✔
3722
        UWORD *coef;
411✔
3723
        POSITION position;
411✔
3724
        FILEHANDLE *fin, *fout;
411✔
3725
        int fhandle;
411✔
3726
/*
3727
        UBYTE *s;
3728
*/
3729
#ifdef WITHZLIB
3730
        POSITION position2;
411✔
3731
        int oldgzipCompress = AR.gzipCompress;
411✔
3732
        if ( par == 2 ) {
411✔
3733
                AR.gzipCompress = 0;
155✔
3734
        }
3735
#endif
3736
        fin = &S->file;
411✔
3737
        fout = &(AR.FoStage4[0]);
411✔
3738
NewMerge:
427✔
3739
        coef = AN.SoScratC;
427✔
3740
        poin = S->poina; poin2 = S->poin2a;
427✔
3741
        rr = AR.CompressPointer;
427✔
3742
        *rr = 0;
427✔
3743
/*
3744
                 #[ Setup :
3745
*/
3746
        if ( par == 1 ) {
427✔
3747
                fout = &(S->file);
234✔
3748
                if ( fout->handle < 0 ) {
234✔
3749
FileMake:
25✔
3750
                        PUTZERO(AN.OldPosOut);
41✔
3751
                        if ( ( fhandle = CreateFile(fout->name) ) < 0 ) {
41✔
3752
                                MLOCK(ErrorMessageLock);
×
3753
                                MesPrint("Cannot create file %s",fout->name);
×
3754
                                MUNLOCK(ErrorMessageLock);
×
3755
                                goto ReturnError;
×
3756
                        }
3757
#ifdef GZIPDEBUG
3758
                        MLOCK(ErrorMessageLock);
3759
                        MesPrint("%w MergePatches created output file %s",fout->name);
3760
                        MUNLOCK(ErrorMessageLock);
3761
#endif
3762
                        fout->handle = fhandle;
41✔
3763
                        PUTZERO(fout->filesize);
41✔
3764
                        PUTZERO(fout->POposition);
41✔
3765
/*
3766
                        Should not be here?
3767
#ifdef WITHZLIB
3768
                        fout->ziobuffer = 0;
3769
#endif
3770
*/
3771
#ifdef ALLLOCK
3772
                        LOCK(fout->pthreadslock);
3773
#endif
3774
                        SeekFile(fout->handle,&(fout->filesize),SEEK_SET);
41✔
3775
#ifdef ALLLOCK
3776
                        UNLOCK(fout->pthreadslock);
3777
#endif
3778
                        S->fPatchN = 0;
41✔
3779
                        PUTZERO(S->fPatches[0]);
41✔
3780
                        fout->POfill = fout->PObuffer;        
41✔
3781
                        PUTZERO(fout->POposition);
41✔
3782
                }
3783
ConMer:
209✔
3784
                StageSort(fout);
294✔
3785
#ifdef WITHZLIB
3786
                if ( S == AT.S0 && AR.NoCompress == 0 && AR.gzipCompress > 0 )
291✔
3787
                        S->fpcompressed[S->fPatchN] = 1;
255✔
3788
                else
3789
                        S->fpcompressed[S->fPatchN] = 0;
36✔
3790
                SetupOutputGZIP(fout);
291✔
3791
#endif
3792
        }
3793
        else if ( par == 0 && S->stage4 > 0 ) {
193✔
3794
/*
3795
                We will have to do our job more than once.
3796
                Input is from S->file and output will go to AR.FoStage4.
3797
                The file corresponding to this last one must be made now.
3798
*/
3799
                AR.Stage4Name ^= 1;
16✔
3800
/*
3801
                s = (UBYTE *)(fout->name); while ( *s ) s++;
3802
                if ( AR.Stage4Name ) s[-1] += 1;
3803
                else                s[-1] -= 1;
3804
*/
3805
                S->iPatches = S->fPatches;
16✔
3806
                S->fPatches = S->inPatches;
16✔
3807
                S->inPatches = S->iPatches;
16✔
3808
                (S->inNum) = S->fPatchN;
16✔
3809
                AN.OldPosIn = AN.OldPosOut;
16✔
3810
#ifdef WITHZLIB
3811
                m1 = S->fpincompressed;
16✔
3812
                S->fpincompressed = S->fpcompressed;
16✔
3813
                S->fpcompressed = m1;
16✔
3814
                for ( i = 0; i < S->inNum; i++ ) {
57✔
3815
                        S->fPatchesStop[i] = S->iPatches[i+1];
41✔
3816
#ifdef GZIPDEBUG
3817
                        MLOCK(ErrorMessageLock);
3818
                        MesPrint("%w fPatchesStop[%d] = %10p",i,&(S->fPatchesStop[i]));
3819
                        MUNLOCK(ErrorMessageLock);
3820
#endif
3821
                }
3822
#endif
3823
                S->stage4 = 0;
16✔
3824
                goto FileMake;
16✔
3825
        }
3826
        else {
3827
#ifdef WITHZLIB
3828
/*
3829
                The next statement is just for now
3830
*/
3831
                AR.gzipCompress = 0;
177✔
3832
#endif
3833
                if ( par == 0 ) {
177✔
3834
                        S->iPatches = S->fPatches;
22✔
3835
                        S->inNum = S->fPatchN;
22✔
3836
#ifdef WITHZLIB
3837
                        m1 = S->fpincompressed;
22✔
3838
                        S->fpincompressed = S->fpcompressed;
22✔
3839
                        S->fpcompressed = m1;
22✔
3840
                        for ( i = 0; i < S->inNum; i++ ) {
87✔
3841
                                S->fPatchesStop[i] = S->fPatches[i+1];
65✔
3842
#ifdef GZIPDEBUG
3843
                                MLOCK(ErrorMessageLock);
3844
                                MesPrint("%w fPatchesStop[%d] = %10p",i,&(S->fPatchesStop[i]));
3845
                                MUNLOCK(ErrorMessageLock);
3846
#endif
3847
                        }
3848
#endif
3849
                }
3850
                fout = AR.outfile;
177✔
3851
        }
3852
        if ( par ) {                                /* Mark end of patches */
468✔
3853
                S->Patches[S->lPatch] = S->lFill;
386✔
3854
                for ( i = 0; i < S->lPatch; i++ ) {
4,288✔
3855
                        S->pStop[i] = S->Patches[i+1]-1;
3,902✔
3856
                    S->Patches[i] = (WORD *)(((UBYTE *)(S->Patches[i])) + AM.MaxTer);
3,902✔
3857
                }
3858
        }
3859
        else {        /* Load the patches */
3860
                S->lPatch = (S->inNum);
82✔
3861
#ifdef WITHMPI
3862
                if ( S->lPatch > 1 || ( (PF.exprtodo <0) && (fout == AR.outfile || fout == AR.hidefile ) ) ) {
2✔
3863
#else
3864
                if ( S->lPatch > 1 ) {
80✔
3865
#endif
3866
#ifdef WITHZLIB
3867
                        SetupAllInputGZIP(S);
77✔
3868
#endif
3869
                        p = S->lBuffer;
77✔
3870
                        for ( i = 0; i < S->lPatch; i++ ) {
354✔
3871
                                p = (WORD *)(((UBYTE *)p)+2*AM.MaxTer+COMPINC*sizeof(WORD));
277✔
3872
                                S->Patches[i] = p;
277✔
3873
                                p = (WORD *)(((UBYTE *)p) + fin->POsize);
277✔
3874
                                S->pStop[i] = m2 = p;
277✔
3875
#ifdef WITHZLIB
3876
                                PutIn(fin,&(S->iPatches[i]),S->Patches[i],&m2,i);
277✔
3877
#else
3878
                                ADDPOS(S->iPatches[i],PutIn(fin,&(S->iPatches[i]),S->Patches[i],&m2,i));
3879
#endif
3880
                        }
3881
                }
3882
        }
3883
        if ( fout->handle >= 0 ) {
468✔
3884
                PUTZERO(position);
291✔
3885
#ifdef ALLLOCK
3886
                LOCK(fout->pthreadslock);
3887
#endif
3888
                SeekFile(fout->handle,&position,SEEK_END);
291✔
3889
                ADDPOS(position,((fout->POfill-fout->PObuffer)*sizeof(WORD)));
291✔
3890
#ifdef ALLLOCK
3891
                UNLOCK(fout->pthreadslock);
3892
#endif
3893
        }
3894
        else {
3895
                SETBASEPOSITION(position,(fout->POfill-fout->PObuffer)*sizeof(WORD));
177✔
3896
        }
3897
/*
3898
                 #] Setup : 
3899

3900
        The old code had to be replaced because all output needs to go
3901
        through PutOut. For this we have to go term by term and keep
3902
        track of the compression.
3903
*/
3904
        if ( S->lPatch == 1 ) {        /* Single patch --> direct copy. Very rare. */
468✔
3905
                LONG length;
5✔
3906

3907
                if ( fout->handle < 0 ) if ( Sflush(fout) ) goto PatCall;
5✔
3908
                if ( par ) {                /* Memory to file */
5✔
3909
#ifdef WITHZLIB
3910
/*
3911
                        We fix here the problem that the thing needs to go through PutOut
3912
*/
3913
                        m2 = m1 = *S->Patches; /* The m2 is to keep the compiler from complaining */
×
3914
                        while ( *m1 ) {
×
3915
                                if ( *m1 < 0 ) { /* Need to uncompress */
×
3916
                                        i = -(*m1++); m2 += i; im = *m1+i+1;
×
3917
                                        while ( i > 0 ) { *m1-- = *m2--; i--; }
×
3918
                                        *m1 = im;
×
3919
                                }
3920
#ifdef WITHPTHREADS
3921
                                /* Check here (and in the following) that we are at ground level
3922
                                   (so S == AT.S0) to use PutToMaster. Control can reach here,
3923
                                   with AS.MasterSort, but with S != AT.S0, when the SortBots are
3924
                                   adding PolyRatFun and the sorting of their arguments requires
3925
                                   large buffer patches to be merged. In this case, terms escape
3926
                                   the PolyRatFun argument and end up at ground level, if we use
3927
                                   PutToMaster. */
3928
                                if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
3929
                                        im = PutToMaster(BHEAD m1);
3930
                                }
3931
                                else
3932
#endif
3933
                                if ( ( im = PutOut(BHEAD m1,&position,fout,1) ) < 0 ) goto ReturnError;
×
3934
                                ADDPOS(S->SizeInFile[par],im);
×
3935
                                m2 = m1;
×
3936
                                m1 += *m1;
×
3937
                        }
3938
#ifdef WITHPTHREADS
3939
                        if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
3940
                                PutToMaster(BHEAD 0);
3941
                        }
3942
                        else
3943
#endif
3944
                        if ( FlushOut(&position,fout,1) ) goto ReturnError;
×
3945
                        ADDPOS(S->SizeInFile[par],1);
×
3946
#else
3947
/* old code */
3948
                        length = (LONG)(*S->pStop)-(LONG)(*S->Patches)+sizeof(WORD);
3949
                        if ( WriteFile(fout->handle,(UBYTE *)(*S->Patches),length) != length )
3950
                                goto PatwCall;
3951
                        ADDPOS(position,length);
3952
                        ADDPOS(fout->POposition,length);
3953
                        ADDPOS(fout->filesize,length);
3954
                        ADDPOS(S->SizeInFile[par],length/sizeof(WORD));
3955
#endif
3956
                }
3957
                else {                                /* File to file */
3958
#ifdef WITHZLIB
3959
/*
3960
                        Note: if we change FRONTSIZE we need to make the minimum value
3961
                        of SmallEsize in AllocSort correspondingly larger or smaller.
3962
                        Theoretically we could get close to 2*AM.MaxTer!
3963
*/
3964
                        #define FRONTSIZE (2*AM.MaxTer)
3965
                        WORD *copybuf = (WORD *)(((UBYTE *)(S->sBuffer)) + FRONTSIZE);
5✔
3966
                        WORD *copytop;
5✔
3967
                        SetupAllInputGZIP(S);
5✔
3968
                        m1 = m2 = copybuf;
5✔
3969
                        position2 = S->iPatches[0];
5✔
3970
                        while ( ( length = FillInputGZIP(fin,&position2,
10✔
3971
                                        (UBYTE *)copybuf,
3972
                                        (S->SmallEsize*sizeof(WORD)-FRONTSIZE),0) ) > 0 ) {
5✔
3973
                                copytop = (WORD *)(((UBYTE *)copybuf)+length);
5✔
3974
                                while ( *m1 && ( ( *m1 > 0 && m1+*m1 < copytop ) ||
40,965✔
3975
                                ( *m1 < 0 && ( m1+1 < copytop ) && ( m1+m1[1]+1 < copytop ) ) ) )
40,955✔
3976
/*
3977
        22-jun-2013 JV  Extremely nasty bug that has been around for a while.
3978
                        What if the end is in the remaining part? We will loose terms!
3979
                                while ( *m1 && ( (WORD *)(((UBYTE *)(m1)) + AM.MaxTer ) < S->sTop2 ) )
3980
*/
3981
                                {
3982
                                        if ( *m1 < 0 ) { /* Need to uncompress */
40,960✔
3983
                                                i = -(*m1++); m2 += i; im = *m1+i+1;
40,955✔
3984
                                                while ( i > 0 ) { *m1-- = *m2--; i--; }
204,775✔
3985
                                                *m1 = im;
40,955✔
3986
                                        }
3987
#ifdef WITHPTHREADS
3988
                                        if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
32,768✔
3989
                                                im = PutToMaster(BHEAD m1);
3990
                                        }
3991
                                        else
3992
#endif
3993
                                        if ( ( im = PutOut(BHEAD m1,&position,fout,1) ) < 0 ) goto ReturnError;
40,960✔
3994
                                        ADDPOS(S->SizeInFile[par],im);
40,960✔
3995
                                        m2 = m1;
40,960✔
3996
                                        m1 += *m1;
40,960✔
3997
                                }
3998
                                if ( m1 < copytop && *m1 == 0 ) break;
5✔
3999
/*
4000
                                Now move the remaining part 'back'
4001
*/
4002
                            m3 = copybuf;
4003
                                m1 = copytop;
4004
                                while ( m1 > m2 ) *--m3 = *--m1;
×
4005
                                m2 = m3;
×
4006
                                m1 = m2 + *m2;
×
4007
                        }
4008
                        if ( length < 0 ) {
5✔
4009
                                MLOCK(ErrorMessageLock);
×
4010
                                MesPrint("Readerror");
×
4011
                                goto PatCall2;
×
4012
                        }
4013
#ifdef WITHPTHREADS
4014
                        if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
4✔
4015
                                PutToMaster(BHEAD 0);
4016
                        }
4017
                        else
4018
#endif
4019
                        if ( FlushOut(&position,fout,1) ) goto ReturnError;
5✔
4020
                        ADDPOS(S->SizeInFile[par],1);
5✔
4021
#else
4022
/* old code */
4023
                        SeekFile(fin->handle,&(S->iPatches[0]),SEEK_SET); /* needed for stage4 */
4024
                        while ( ( length = ReadFile(fin->handle,
4025
                                        (UBYTE *)(S->sBuffer),S->SmallEsize*sizeof(WORD)) ) > 0 ) {
4026
                                if ( WriteFile(fout->handle,(UBYTE *)(S->sBuffer),length) != length )
4027
                                        goto PatwCall;
4028
                                ADDPOS(position,length);
4029
                                ADDPOS(fout->POposition,length);
4030
                                ADDPOS(fout->filesize,length);
4031
                                ADDPOS(S->SizeInFile[par],length/sizeof(WORD));
4032
                        }
4033
                        if ( length < 0 ) {
4034
                                MLOCK(ErrorMessageLock);
4035
                                MesPrint("Readerror");
4036
                                goto PatCall2;
4037
                        }
4038
#endif
4039
                }
4040
                goto EndOfAll;
5✔
4041
        }
4042
        else if ( S->lPatch > 0 ) {
463✔
4043

4044
                /* More than one patch. Construct the tree. */
4045

4046
                lpat = 1;
4047
                do { lpat *= 2; } while ( lpat < S->lPatch );
1,282✔
4048
                mpat = ( lpat >> 1 ) - 1;
463✔
4049
                k = lpat - S->lPatch;
463✔
4050

4051
                /* k is the number of empty places in the tree. they will
4052
                   be at the even positions from 2 to 2*k */
4053

4054
                for ( i = 1; i < lpat; i++ ) {
4,508✔
4055
                        S->tree[i] = -1;
4,045✔
4056
                }
4057
                for ( i = 1; i <= k; i++ ) {
792✔
4058
                        im = ( i * 2 ) - 1;
329✔
4059
                        poin[im] = S->Patches[i-1];
329✔
4060
                        poin2[im] = poin[im] + *(poin[im]);
329✔
4061
                        S->used[i] = im;
329✔
4062
                        S->ktoi[im] = i-1;
329✔
4063
                        S->tree[mpat+i] = 0;
329✔
4064
                        poin[im-1] = poin2[im-1] = 0;
329✔
4065
                }
4066
                for ( i = (k*2)+1; i <= lpat; i++ ) {
4,313✔
4067
                        S->used[i-k] = i;
3,850✔
4068
                        S->ktoi[i] = i-k-1;
3,850✔
4069
                        poin[i] = S->Patches[i-k-1];
3,850✔
4070
                        poin2[i] = poin[i] + *(poin[i]);
3,850✔
4071
                }
4072
/*
4073
                the array poin tells the position of the i-th element of the S->tree
4074
                'S->used' is a stack with the S->tree elements that need to be entered
4075
                into the S->tree. at the beginning this is S->lPatch. during the
4076
                sort there will be only very few elements.
4077
                poin2 is the next value of poin. it has to be determined
4078
                before the comparisons as the position or the size of the
4079
                term indicated by poin may change.
4080
                S->ktoi translates a S->tree element back to its stream number.
4081

4082
                start the sort
4083
*/
4084
                level = S->lPatch;
463✔
4085

4086
                /* introduce one term */
4087
OneTerm:
12,122,460✔
4088
                k = S->used[level];
12,122,940✔
4089
                i = k + lpat - 1;
12,122,940✔
4090
                if ( !*(poin[k]) ) {
12,122,940✔
4091
                        do { if ( !( i >>= 1 ) ) goto EndOfMerge; } while ( !S->tree[i] );
8,224✔
4092
                        if ( S->tree[i] == -1 ) {
3,716✔
4093
                                S->tree[i] = 0;
18✔
4094
                                level--;
18✔
4095
                                goto OneTerm;
18✔
4096
                        }
4097
                        k = S->tree[i];
3,698✔
4098
                        S->used[level] = k;
3,698✔
4099
                        S->tree[i] = 0;
3,698✔
4100
                }
4101
/*
4102
                move terms down the tree
4103
*/
4104
                while ( i >>= 1 ) {
32,055,980✔
4105
                        if ( S->tree[i] > 0 ) {
20,059,560✔
4106
                                if ( ( c = CompareTerms(BHEAD poin[S->tree[i]],poin[k],(WORD)0) ) > 0 ) {
12,005,130✔
4107
/*
4108
                                        S->tree[i] is the smaller. Exchange and go on.
4109
*/
4110
                                        S->used[level] = S->tree[i];
31,963✔
4111
                                        S->tree[i] = k;
31,963✔
4112
                                        k = S->used[level];
31,963✔
4113
                                }
4114
                                else if ( !c ) {        /* Terms are equal */
11,973,170✔
4115
                                        S->TermsLeft--;
70,367✔
4116
/*
4117
                                                Here the terms are equal and their coefficients
4118
                                                have to be added.
4119
*/
4120
                                        l1 = *( m1 = poin[S->tree[i]] );
70,367✔
4121
                                        l2 = *( m2 = poin[k] );
70,367✔
4122
                                        if ( S->PolyWise ) {  /* Here we work with PolyFun */
70,367✔
4123
                                                WORD *tt1, *w;
×
4124
                                                tt1 = m1;
×
4125
                                                m1 += S->PolyWise;
×
4126
                                                m2 += S->PolyWise;
×
4127
                                                if ( S->PolyFlag == 2 ) {
×
4128
                                                        w = poly_ratfun_add(BHEAD m1,m2);
×
4129
                                                        if ( *tt1 + w[1] - m1[1] > AM.MaxTer/((LONG)sizeof(WORD)) ) {
×
4130
                                                                MLOCK(ErrorMessageLock);
×
4131
                                                                MesPrint("Term too complex in PolyRatFun addition. MaxTermSize of %10l is too small",AM.MaxTer);
×
4132
                                                                MUNLOCK(ErrorMessageLock);
×
4133
                                                                Terminate(-1);
×
4134
                                                        }
4135
                                                        AT.WorkPointer = w;
×
4136
                                                }
4137
                                                else {
4138
                                                        w = AT.WorkPointer;
×
4139
                                                        if ( w + m1[1] + m2[1] > AT.WorkTop ) {
×
4140
                                                                MLOCK(ErrorMessageLock);
×
4141
                                                                MesPrint("A WorkSpace of %10l is too small",AM.WorkSize);
×
4142
                                                                MUNLOCK(ErrorMessageLock);
×
4143
                                                                Terminate(-1);
×
4144
                                                        }
4145
                                                        AddArgs(BHEAD m1,m2,w);
×
4146
                                                }
4147
                                                r1 = w[1];
×
4148
                                                if ( r1 <= FUNHEAD
×
4149
                                                        || ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) )
×
4150
                                                                 { goto cancelled; }
×
4151
                                                if ( r1 == m1[1] ) {
×
4152
                                                        NCOPY(m1,w,r1);
×
4153
                                                }
4154
                                                else if ( r1 < m1[1] ) {
×
4155
                                                        r2 = m1[1] - r1;
×
4156
                                                        m2 = w + r1;
×
4157
                                                        m1 += m1[1];
×
4158
                                                        while ( --r1 >= 0 ) *--m1 = *--m2;
×
4159
                                                        m2 = m1 - r2;
×
4160
                                                        r1 = S->PolyWise;
×
4161
                                                        while ( --r1 >= 0 ) *--m1 = *--m2;
×
4162
                                                        *m1 -= r2;
×
4163
                                                        poin[S->tree[i]] = m1;
×
4164
                                                }
4165
                                                else {
4166
                                                        r2 = r1 - m1[1];
×
4167
                                                        m2 = tt1 - r2;
×
4168
                                                        r1 = S->PolyWise;
×
4169
                                                        m1 = tt1;
×
4170
                                                        *m1 += r2;
×
4171
                                                        poin[S->tree[i]] = m2;
×
4172
                                                        NCOPY(m2,m1,r1);
×
4173
                                                        r1 = w[1];
×
4174
                                                        NCOPY(m2,w,r1);
×
4175
                                                }
4176
                                        }
4177
#ifdef WITHFLOAT
4178
                                        else if ( AT.SortFloatMode ) {
70,367✔
4179
                                                WORD *term1, *term2;
×
4180
                                                term1 = poin[S->tree[i]];
×
4181
                                                term2 = poin[k];
×
4182
                                                if ( MergeWithFloat(BHEAD &term1,&term2) == 0 )
×
4183
                                                        goto cancelled;
×
4184
                                                poin[S->tree[i]] = term1;
×
4185
                                        }
4186
#endif
4187
                                        else {
4188
                                          r1 = *( m1 += l1 - 1 );
70,367✔
4189
                                          m1 -= ABS(r1) - 1;
70,367✔
4190
                                          r1 = ( ( r1 > 0 ) ? (r1-1) : (r1+1) ) >> 1;
70,367✔
4191
                                          r2 = *( m2 += l2 - 1 );
70,367✔
4192
                                          m2 -= ABS(r2) - 1;
70,367✔
4193
                                          r2 = ( ( r2 > 0 ) ? (r2-1) : (r2+1) ) >> 1;
70,367✔
4194

4195
                                          if ( AddRat(BHEAD (UWORD *)m1,r1,(UWORD *)m2,r2,coef,&r3) ) {
70,367✔
4196
                                                MLOCK(ErrorMessageLock);
×
4197
                                                MesCall("MergePatches");
×
4198
                                                MUNLOCK(ErrorMessageLock);
×
4199
                                                SETERROR(-1)
×
4200
                                          }
4201

4202
                                          if ( AN.ncmod != 0 ) {
70,367✔
4203
                                                if ( ( AC.modmode & POSNEG ) != 0 ) {
×
4204
                                                        NormalModulus(coef,&r3);
×
4205
                                                }
4206
                                                else if ( BigLong(coef,r3,(UWORD *)AC.cmod,ABS(AN.ncmod)) >= 0 ) {
×
4207
                                                        WORD ii;
×
4208
                                                        SubPLon(coef,r3,(UWORD *)AC.cmod,ABS(AN.ncmod),coef,&r3);
×
4209
                                                        coef[r3] = 1;
×
4210
                                                        for ( ii = 1; ii < r3; ii++ ) coef[r3+ii] = 0;
×
4211
                                                }
4212
                                          }
4213
                                          r3 *= 2;
70,367✔
4214
                                          r33 = ( r3 > 0 ) ? ( r3 + 1 ) : ( r3 - 1 );
70,367✔
4215
                                          if ( r3 < 0 ) r3 = -r3;
70,367✔
4216
                                          if ( r1 < 0 ) r1 = -r1;
70,367✔
4217
                                          r1 *= 2;
70,367✔
4218
                                          r31 = r3 - r1;
70,367✔
4219
                                          if ( !r3 ) {                /* Terms cancel */
70,367✔
4220
cancelled:
51,975✔
4221
                                                ul = S->used[level] = S->tree[i];
51,975✔
4222
                                                S->tree[i] = -1;
51,975✔
4223
/*
4224
                                                We skip to the next term in stream ul
4225
*/
4226
                                                im = *poin2[ul];
51,975✔
4227
                                                if ( im < 0 ) {
51,975✔
4228
                                                        r1 = poin2[ul][1] - im + 1;
51,877✔
4229
                                                        m1 = poin2[ul] + 2;
51,877✔
4230
                                                        m2 = poin[ul] - im + 1;
51,877✔
4231
                                                        while ( ++im <= 0 ) *--m1 = *--m2;
259,385✔
4232
                                                        *--m1 = r1;
51,877✔
4233
                                                        poin2[ul] = m1;
51,877✔
4234
                                                        im = r1;
51,877✔
4235
                                                }
4236
                                                poin[ul] = poin2[ul];
51,975✔
4237
                                                ki = S->ktoi[ul];
51,975✔
4238
                                                if ( !par && (poin[ul] + im + COMPINC) >= S->pStop[ki]
51,975✔
4239
                                                && im > 0 ) {
×
4240
#ifdef WITHZLIB
4241
                                                        PutIn(fin,&(S->iPatches[ki]),S->Patches[ki],&(poin[ul]),ki);
×
4242
#else
4243
                                                        ADDPOS(S->iPatches[ki],PutIn(fin,&(S->iPatches[ki]),
4244
                                                        S->Patches[ki],&(poin[ul]),ki));
4245
#endif
4246
                                                        poin2[ul] = poin[ul] + im;
×
4247
                                                }
4248
                                                else {
4249
                                                        poin2[ul] += im;
51,975✔
4250
                                                }
4251
                                                S->used[++level] = k;
51,975✔
4252
                                                S->TermsLeft--;
51,975✔
4253
                                          }
4254
                                          else if ( !r31 ) {                /* copy coef into term1 */
18,392✔
4255
                                                goto CopCof2;
18,363✔
4256
                                          }
4257
                                          else if ( r31 < 0 ) {                /* copy coef into term1
29✔
4258
                                                                                        and adjust the length of term1 */
4259
                                                goto CopCoef;
×
4260
                                          }
4261
                                          else {
4262
/*
4263
                                                        this is the dreaded calamity.
4264
                                                        is there enough space?
4265
*/
4266
                                                if( (poin[S->tree[i]]+l1+r31) >= poin2[S->tree[i]] ) {
29✔
4267
/*
4268
                                                                no space! now the special trick for which
4269
                                                                we left 2*maxlng spaces open at the beginning
4270
                                                                of each patch.
4271
*/
4272
                                                        if ( (l1 + r31) > AM.MaxTer/((LONG)sizeof(WORD)) ) {
29✔
4273
                                                                MLOCK(ErrorMessageLock);
×
4274
                                                                MesPrint("Coefficient overflow during sort");
×
4275
                                                                MUNLOCK(ErrorMessageLock);
×
4276
                                                                goto ReturnError;
×
4277
                                                        }
4278
                                                        m2 = poin[S->tree[i]];
29✔
4279
                                                        m3 = ( poin[S->tree[i]] -= r31 );
29✔
4280
                                                        do { *m3++ = *m2++; } while ( m2 < m1 );
29✔
4281
                                                        m1 = m3;
4282
                                                }
4283
CopCoef:
×
4284
                                                *(poin[S->tree[i]]) += r31;
29✔
4285
CopCof2:
18,392✔
4286
                                                m2 = (WORD *)coef; im = r3;
18,392✔
4287
                                                NCOPY(m1,m2,im);
55,272✔
4288
                                                *m1 = r33;
18,392✔
4289
                                          }
4290
                                        }
4291
/*
4292
                                        Now skip to the next term in stream k.
4293
*/
4294
NextTerm:
12,066,790✔
4295
                                        im = poin2[k][0];
12,066,790✔
4296
                                        if ( im < 0 ) {
12,066,790✔
4297
                                                r1 = poin2[k][1] - im + 1;
3,477,959✔
4298
                                                m1 = poin2[k] + 2;
3,477,959✔
4299
                                                m2 = poin[k] - im + 1;
3,477,959✔
4300
                                                while ( ++im <= 0 ) *--m1 = *--m2;
15,774,320✔
4301
                                                *--m1 = r1;
3,477,959✔
4302
                                                poin2[k] = m1;
3,477,959✔
4303
                                                im = r1;
3,477,959✔
4304
                                        }
4305
                                        poin[k] = poin2[k];
12,066,790✔
4306
                                        ki = S->ktoi[k];
12,066,790✔
4307
                                        if ( !par && ( (poin[k] + im + COMPINC) >= S->pStop[ki] )
12,066,790✔
4308
                                        && im > 0 ) {
91✔
4309
#ifdef WITHZLIB
4310
                                                PutIn(fin,&(S->iPatches[ki]),S->Patches[ki],&(poin[k]),ki);
91✔
4311
#else
4312
                                                ADDPOS(S->iPatches[ki],PutIn(fin,&(S->iPatches[ki]),
4313
                                                S->Patches[ki],&(poin[k]),ki));
4314
#endif
4315
                                                poin2[k] = poin[k] + im;
91✔
4316
                                        }
4317
                                        else {
4318
                                                poin2[k] += im;
12,066,690✔
4319
                                        }
4320
                                        goto OneTerm;
12,066,790✔
4321
                                }
4322
                        }
4323
                        else if ( S->tree[i] < 0 ) {
8,054,410✔
4324
                                S->tree[i] = k;
55,673✔
4325
                                level--;
55,673✔
4326
                                goto OneTerm;
55,673✔
4327
                        }
4328
                }
4329
/*
4330
                        found the smallest in the set. indicated by k.
4331
                        write to its destination.
4332
*/
4333
#ifdef WITHPTHREADS
4334
                if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
6,279,820✔
4335
                        im = PutToMaster(BHEAD poin[k]);
4,909,470✔
4336
                }
4337
                else
4338
#endif
4339
                if ( ( im = PutOut(BHEAD poin[k],&position,fout,1) ) < 0 ) {
7,086,948✔
4340
                        MLOCK(ErrorMessageLock);
×
4341
                        MesPrint("Called from MergePatches with k = %d (stream %d)",k,S->ktoi[k]);
×
4342
                        MUNLOCK(ErrorMessageLock);
×
4343
                        goto ReturnError;
×
4344
                }
4345
                ADDPOS(S->SizeInFile[par],im);
11,996,420✔
4346
                goto NextTerm;
11,996,420✔
4347
        }
4348
        else {
4349
                goto NormalReturn;
×
4350
        }
4351
EndOfMerge:
463✔
4352
#ifdef WITHPTHREADS
4353
                if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
285✔
4354
                        PutToMaster(BHEAD 0);
30✔
4355
                }
4356
                else
4357
#endif
4358
        if ( FlushOut(&position,fout,1) ) goto ReturnError;
433✔
4359
        ADDPOS(S->SizeInFile[par],1);
463✔
4360
EndOfAll:
468✔
4361
        if ( par == 1 ) {        /* Set the fpatch pointers */
468✔
4362
#ifdef WITHZLIB
4363
                SeekFile(fout->handle,&position,SEEK_CUR);
231✔
4364
#endif
4365
                (S->fPatchN)++;
231✔
4366
                S->fPatches[S->fPatchN] = position;
231✔
4367
        }
4368
        if ( par == 0 && fout != AR.outfile ) {
468✔
4369
/*
4370
                        Output went to sortfile. We have two possibilities:
4371
                        1:        We are not finished with the current in-out cycle
4372
                                In that case we should pop to the next set of patches
4373
                        2:        We finished a cycle and should clean up the in file
4374
                                Then we restart the sort.
4375
*/
4376
                (S->fPatchN)++;
60✔
4377
                S->fPatches[S->fPatchN] = position;
60✔
4378
                if ( ISNOTZEROPOS(AN.OldPosIn) ) {                /* We are not done */
60✔
4379

4380
                        SeekFile(fin->handle,&(AN.OldPosIn),SEEK_SET);
44✔
4381
/*
4382
                        We don't need extra provisions for the zlib compression here.
4383
                        If part of an expression has been sorted, the whole has been so.
4384
                        This means that S->fpincompressed[] will remain the same
4385
*/
4386
                        if ( (ULONG)ReadFile(fin->handle,(UBYTE *)(&(S->inNum)),(LONG)sizeof(WORD)) !=
44✔
4387
                                sizeof(WORD)
4388
                          || (ULONG)ReadFile(fin->handle,(UBYTE *)(&AN.OldPosIn),(LONG)sizeof(POSITION)) !=
44✔
4389
                                sizeof(POSITION)
4390
                          || (ULONG)ReadFile(fin->handle,(UBYTE *)S->iPatches,(LONG)((S->inNum)+1)
88✔
4391
                                        *sizeof(POSITION)) != ((S->inNum)+1)*sizeof(POSITION) ) {
44✔
4392
                                MLOCK(ErrorMessageLock);
×
4393
                                MesPrint("Read error fourth stage sorting");
×
4394
                                MUNLOCK(ErrorMessageLock);
×
4395
                                goto ReturnError;
×
4396
                        }
4397
                        *rr = 0;
44✔
4398
#ifdef WITHZLIB
4399
                        for ( i = 0; i < S->inNum; i++ ) {
220✔
4400
                                S->fPatchesStop[i] = S->iPatches[i+1];
176✔
4401
#ifdef GZIPDEBUG
4402
                                MLOCK(ErrorMessageLock);
4403
                                MesPrint("%w fPatchesStop[%d] = %10p",i,&(S->fPatchesStop[i]));
4404
                                MUNLOCK(ErrorMessageLock);
4405
#endif
4406
                        }
4407
#endif
4408
                        goto ConMer;
44✔
4409
                }
4410
                else {
4411
/*
4412
                        if ( fin == &(AR.FoStage4[0]) ) {
4413
                                s = (UBYTE *)(fin->name); while ( *s ) s++;
4414
                                if ( AR.Stage4Name == 1 ) s[-1] -= 1;
4415
                                else                      s[-1] += 1;
4416
                        }
4417
*/
4418
/*                        TruncateFile(fin->handle); */
4419
                        UpdateMaxSize();
16✔
4420
#ifdef WITHZLIB
4421
                        ClearSortGZIP(fin);
16✔
4422
#endif
4423
                        CloseFile(fin->handle);
16✔
4424
                        remove(fin->name);                /* Gives diskspace free again. */
16✔
4425
#ifdef GZIPDEBUG
4426
                        MLOCK(ErrorMessageLock);
4427
                        MesPrint("%w MergePatches removed in file %s",fin->name);
4428
                        MUNLOCK(ErrorMessageLock);
4429
#endif
4430
/*
4431
                        if ( fin == &(AR.FoStage4[0]) ) {
4432
                                s = (UBYTE *)(fin->name); while ( *s ) s++;
4433
                                if ( AR.Stage4Name == 1 ) s[-1] += 1;
4434
                                else                      s[-1] -= 1;
4435
                        }
4436
*/
4437
                        fin->handle = -1;
16✔
4438
                        { FILEHANDLE *ff = fin; fin = fout; fout = ff; }
16✔
4439
                        PUTZERO(S->SizeInFile[0]);
16✔
4440
                        goto NewMerge;
16✔
4441
                }
4442
        }
4443
        if ( par == 0 ) {
408✔
4444
/*                TruncateFile(fin->handle); */
4445
                UpdateMaxSize();
22✔
4446
#ifdef WITHZLIB
4447
                ClearSortGZIP(fin);
22✔
4448
#endif
4449
                CloseFile(fin->handle);
22✔
4450
                remove(fin->name);
22✔
4451
                fin->handle = -1;
22✔
4452
#ifdef GZIPDEBUG
4453
                MLOCK(ErrorMessageLock);
4454
                MesPrint("%w MergePatches removed in file %s",fin->name);
4455
                MUNLOCK(ErrorMessageLock);
4456
#endif
4457
        }
4458
NormalReturn:
386✔
4459
#ifdef WITHZLIB
4460
        AR.gzipCompress = oldgzipCompress;
408✔
4461
#endif
4462
        return(0);
408✔
4463
ReturnError:
×
4464
#ifdef WITHZLIB
4465
        AR.gzipCompress = oldgzipCompress;
×
4466
#endif
4467
        return(-1);
×
4468
#ifndef WITHZLIB
4469
PatwCall:
4470
        MLOCK(ErrorMessageLock);
4471
        MesPrint("Error while writing to file.");
4472
        goto PatCall2;
4473
#endif
4474
PatCall:;
×
4475
        MLOCK(ErrorMessageLock);
×
4476
PatCall2:;
×
4477
        MesCall("MergePatches");
×
4478
        MUNLOCK(ErrorMessageLock);
×
4479
#ifdef WITHZLIB
4480
        AR.gzipCompress = oldgzipCompress;
×
4481
#endif
4482
        SETERROR(-1)
×
4483
}
4484

4485
/*
4486
                 #] MergePatches : 
4487
                 #[ StoreTerm :                                WORD StoreTerm(term)
4488
*/
4489
/**
4490
 *        The central routine to accept terms, store them and keep things
4491
 *        at least partially sorted. A call to EndSort will then complete
4492
 *        storing and sorting.
4493
 *
4494
 *        @param term The term to be stored
4495
 *        @return  Regular return conventions (OK -> 0)
4496
 */
4497

4498
WORD StoreTerm(PHEAD WORD *term)
26,843,450✔
4499
{
4500
        GETBIDENTITY
4501
        SORTING *S = AT.SS;
26,843,450✔
4502
        WORD **ss, *lfill, j, *t;
26,843,450✔
4503
        POSITION pp;
26,843,450✔
4504
        LONG lSpace, sSpace, RetCode, over, tover;
26,843,450✔
4505

4506
        if ( ( ( AP.PreDebug & DUMPTOSORT ) == DUMPTOSORT ) && AR.sLevel == 0 ) {
26,843,450✔
4507
#ifdef WITHPTHREADS
4508
                snprintf((char *)(THRbuf),100,"StoreTerm(%d)",AT.identity);
4509
                PrintTerm(term,(char *)(THRbuf));
4510
#else
4511
                PrintTerm(term,"StoreTerm");
4512
#endif
4513
        }
4514
        if ( AM.exitflag && AR.sLevel == 0 ) return(0);
26,843,450✔
4515
        S->sFill = *(S->PoinFill);
26,843,450✔
4516
        if ( S->sTerms >= S->TermsInSmall || ( S->sFill + *term ) >= S->sTop ) {
26,843,450✔
4517
/*
4518
        The small buffer is full. It has to be sorted and written.
4519
*/
4520
                tover = over = S->sTerms;
3,755✔
4521
                ss = S->sPointer;
3,755✔
4522
                ss[over] = 0;
3,755✔
4523
#ifdef SPLITTIME
4524
                PrintTime((UBYTE *)"Before SplitMerge");
4525
#endif
4526
                ss[SplitMerge(BHEAD ss,over)] = 0;
3,755✔
4527
#ifdef SPLITTIME
4528
                PrintTime((UBYTE *)"After SplitMerge");
4529
#endif
4530
                sSpace = 0;
3,755✔
4531
                if ( over > 0 ) {
3,755✔
4532
                        sSpace = ComPress(ss,&RetCode);
3,755✔
4533
                        S->TermsLeft -= over - RetCode;
3,755✔
4534
                }
4535
                sSpace++;
3,755✔
4536

4537
                lSpace = sSpace + (S->lFill - S->lBuffer)
3,755✔
4538
                                 - (AM.MaxTer/sizeof(WORD))*((LONG)S->lPatch);
3,755✔
4539
                SETBASEPOSITION(pp,lSpace);
3,755✔
4540
                MULPOS(pp,sizeof(WORD));
3,755✔
4541
                if ( S->file.handle >= 0 ) {
3,755✔
4542
                        ADD2POS(pp,S->fPatches[S->fPatchN]);
2,897✔
4543
                }
4544
                if ( S == AT.S0 ) {        /* Only statistics at ground level */
3,755✔
4545
                        WriteStats(&pp,STATSSPLITMERGE,CHECKLOGTYPE);
3,223✔
4546
                }
4547
                if ( ( S->lPatch >= S->MaxPatches ) ||
3,755✔
4548
                        ( ( (WORD *)(((UBYTE *)(S->lFill + sSpace)) + 2*AM.MaxTer ) ) >= S->lTop ) ) {
3,551✔
4549
/*
4550
                        The large buffer is too full. Merge and write it
4551
*/
4552
                        if ( MergePatches(1) ) goto StoreCall;
212✔
4553
/*
4554
                        pp = S->SizeInFile[1];
4555
                        ADDPOS(pp,sSpace);
4556
                        MULPOS(pp,sizeof(WORD));
4557
*/
4558
                        SETBASEPOSITION(pp,sSpace);
209✔
4559
                        MULPOS(pp,sizeof(WORD));
209✔
4560
                        ADD2POS(pp,S->fPatches[S->fPatchN]);
209✔
4561

4562
                        if ( S == AT.S0 ) {        /* Only statistics at ground level */
209✔
4563
                                WriteStats(&pp,STATSMERGETOFILE,CHECKLOGTYPE);
179✔
4564
                        }
4565
                        S->lPatch = 0;
209✔
4566
                        S->lFill = S->lBuffer;
209✔
4567
                }
4568
                S->Patches[S->lPatch++] = S->lFill;
3,752✔
4569
            lfill = (WORD *)(((UBYTE *)(S->lFill)) + AM.MaxTer);
3,752✔
4570
                if ( tover > 0 ) {
3,752✔
4571
                        ss = S->sPointer;
3,752✔
4572
                        while ( ( t = *ss++ ) != 0 ) {
8,757,210✔
4573
                                j = *t;
8,753,460✔
4574
                                if ( j < 0 ) j = t[1] + 2;
8,753,460✔
4575
                                while ( --j >= 0 ){
174,085,800✔
4576
                                  *lfill++ = *t++;
165,332,400✔
4577
                                }
4578
                        }
4579
                }
4580
                *lfill++ = 0;
3,752✔
4581
                S->lFill = lfill;
3,752✔
4582
                S->sTerms = 0;
3,752✔
4583
                S->PoinFill = S->sPointer;
3,752✔
4584
                *(S->PoinFill) = S->sFill = S->sBuffer;
3,752✔
4585
        }
4586
        j = *term;
26,843,450✔
4587
        while ( --j >= 0 ) *S->sFill++ = *term++;
412,512,200✔
4588
        S->sTerms++;
26,843,450✔
4589
        S->GenTerms++;
26,843,450✔
4590
        S->TermsLeft++;
26,843,450✔
4591
        *++S->PoinFill = S->sFill;
26,843,450✔
4592

4593
        return(0);
26,843,450✔
4594

4595
StoreCall:
×
4596
        MLOCK(ErrorMessageLock);
×
4597
        MesCall("StoreTerm");
×
4598
        MUNLOCK(ErrorMessageLock);
×
4599
        SETERROR(-1)
×
4600
}
4601

4602
/*
4603
                 #] StoreTerm : 
4604
                 #[ StageSort :                                VOID StageSort(FILEHANDLE *fout)
4605
*/
4606
/**
4607
 *                Prepares a stage 4 or higher sort.
4608
 *                Stage 4 sorts occur when the sort file contains more patches than
4609
 *                can be merged in one pass.
4610
 */
4611

4612
VOID StageSort(FILEHANDLE *fout)
297✔
4613
{
4614
        GETIDENTITY
196✔
4615
        SORTING *S = AT.SS;
297✔
4616
        if ( S->fPatchN >= S->MaxFpatches ) {
297✔
4617
                POSITION position;
47✔
4618
                if ( S != AT.S0 ) {
47✔
4619
/*
4620
                        There are no proper provisions for stage 4 or higher sorts
4621
                        for function arguments and $ variables. The reason:
4622
                        The current code maps out the patches, based on the size of
4623
                        the buffers in the FoStage4 structs, while they are used
4624
                        inside the S->file struct that may have far smaller buffers.
4625
                        By itself that might still be repairable, but it goes completely
4626
                        wrong when during the sort polyRatFuns have to be added and they
4627
                        would go into stage4 (very rare but possible).
4628
                        The only really correct solution would be to put FoStage4 structs
4629
                        in all sort levels. Messy. (JV 8-oct-2018).
4630
*/
4631
                        MLOCK(ErrorMessageLock);
3✔
4632
                        MesPrint("Currently Stage 4 sorts are not allowed for function arguments or $ variables.");
3✔
4633
                        MesPrint("Please increase correspondingsorting parameters (sub-) in the setup.");
3✔
4634
                        MUNLOCK(ErrorMessageLock);
3✔
4635
                        Terminate(-1);
3✔
4636
                }
4637
                PUTZERO(position);
44✔
4638
                MLOCK(ErrorMessageLock);
44✔
4639
#ifdef WITHPTHREADS
4640
                MesPrint("StageSort in thread %d",identity);
28✔
4641
#elif defined(WITHMPI)
4642
                MesPrint("StageSort in process %d",PF.me);
4643
#else
4644
                MesPrint("StageSort");
16✔
4645
#endif
4646
                MUNLOCK(ErrorMessageLock);
44✔
4647
                SeekFile(fout->handle,&position,SEEK_END);
44✔
4648
/*
4649
                No extra compression data has to be written.
4650
                S->fpincompressed should remain valid.
4651
*/
4652
                if ( (ULONG)WriteFile(fout->handle,(UBYTE *)(&(S->fPatchN)),(LONG)sizeof(WORD)) !=
44✔
4653
                        sizeof(WORD)
4654
                  || (ULONG)WriteFile(fout->handle,(UBYTE *)(&(AN.OldPosOut)),(LONG)sizeof(POSITION)) !=
44✔
4655
                        sizeof(POSITION)
4656
                  || (ULONG)WriteFile(fout->handle,(UBYTE *)(S->fPatches),(LONG)(S->fPatchN+1)
88✔
4657
                                        *sizeof(POSITION)) != (S->fPatchN+1)*sizeof(POSITION) ) {
44✔
4658
                        MLOCK(ErrorMessageLock);
×
4659
                        MesPrint("Write error while staging sort. Disk full?");
×
4660
                        MUNLOCK(ErrorMessageLock);
×
4661
                        Terminate(-1);
×
4662
                }
4663
                AN.OldPosOut = position;
44✔
4664
                fout->filesize = position;
44✔
4665
                ADDPOS(fout->filesize,(S->fPatchN+2)*sizeof(POSITION) + sizeof(WORD));
44✔
4666
                fout->POposition = fout->filesize;
44✔
4667
                S->fPatches[0] = fout->filesize;
44✔
4668
                S->fPatchN = 0;
44✔
4669

4670
                if ( AR.FoStage4[0].PObuffer == 0 ) {
44✔
4671
                        AR.FoStage4[0].PObuffer = (WORD *)Malloc1(AR.FoStage4[0].POsize*sizeof(WORD)
7✔
4672
                                                                                                ,"Stage 4 buffer");
4673
                        AR.FoStage4[0].POfill   = AR.FoStage4[0].PObuffer;
7✔
4674
                        AR.FoStage4[0].POstop   = AR.FoStage4[0].PObuffer
7✔
4675
                                                 + AR.FoStage4[0].POsize/sizeof(WORD);
7✔
4676
#ifdef WITHPTHREADS
4677
                        AR.FoStage4[0].pthreadslock = dummylock;
6✔
4678
#endif
4679
                }
4680
                if ( AR.FoStage4[1].PObuffer == 0 ) {
44✔
4681
                        AR.FoStage4[1].PObuffer = (WORD *)Malloc1(AR.FoStage4[1].POsize*sizeof(WORD)
7✔
4682
                                                                                                ,"Stage 4 buffer");
4683
                        AR.FoStage4[1].POfill   = AR.FoStage4[1].PObuffer;
7✔
4684
                        AR.FoStage4[1].POstop   = AR.FoStage4[1].PObuffer
7✔
4685
                                                 + AR.FoStage4[1].POsize/sizeof(WORD);
7✔
4686
#ifdef WITHPTHREADS
4687
                        AR.FoStage4[1].pthreadslock = dummylock;
6✔
4688
#endif
4689
                }
4690
                S->stage4 = 1;
44✔
4691
        }
4692
}
294✔
4693

4694
/*
4695
                 #] StageSort : 
4696
                 #[ SortWild :                                WORD SortWild(w,nw)
4697
*/
4698
/**
4699
 *        Sorts the wildcard entries in the parameter w. Double entries
4700
 *        are removed. Full space taken is nw words.
4701
 *        Routine serves for the reading of wildcards in the compiler.
4702
 *        The entries come in the format:
4703
 *        (type,4,number,0) in which the zero is reserved for the
4704
 *        future replacement of 'number'.
4705
 *
4706
 *        @param w  buffer with wildcard entries.
4707
 *        @param nw number of wildcard entries.
4708
 *        @return  Normal conventions (OK -> 0)
4709
 */
4710

4711
WORD SortWild(WORD *w, WORD nw)
6,853✔
4712
{
4713
        GETIDENTITY
1,966✔
4714
        WORD *v, *s, *m, k, i;
6,853✔
4715
        WORD *pScrat, *stop, *sv, error = 0;
6,853✔
4716
        pScrat = AT.WorkPointer;
6,853✔
4717
        if ( ( AT.WorkPointer + 8 * AM.MaxWildcards ) >= AT.WorkTop ) {
6,853✔
4718
                MLOCK(ErrorMessageLock);
×
4719
                MesWork();
×
4720
                MUNLOCK(ErrorMessageLock);
×
4721
                return(-1);
×
4722
        }
4723
        stop = w + nw;
6,853✔
4724
        i = 0;
6,853✔
4725
        while ( i < nw ) {
25,368✔
4726
                m = w + i;
18,515✔
4727
                v = m + m[1];
18,515✔
4728
                while ( v < stop && (
30,982✔
4729
                         *v == FROMSET || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
24,255✔
4730
                while ( v < stop ) {
42,658✔
4731
                        if ( *v >= 0 ) {
24,143✔
4732
                                if ( AM.Ordering[*v] < AM.Ordering[*m] ) {
23,128✔
4733
                                        m = v;
4734
                                }
4735
                                else if ( *v == *m ) {
22,617✔
4736
                                        if ( v[2] < m[2] ) {
21,413✔
4737
                                                m = v;
4738
                                        }
4739
                                        else if ( v[2] == m[2] ) {
21,392✔
4740
                                                s = m + m[1];
112✔
4741
                                                sv = v + v[1];
112✔
4742
                                                if ( s < stop && ( *s == FROMSET
112✔
4743
                                                 || *s == SETTONUM || *s == LOADDOLLAR ) ) {
112✔
4744
                                                        if ( sv < stop && ( *sv == FROMSET
×
4745
                                                        || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
×
4746
                                                                if ( s[2] != sv[2] ) {
×
4747
                                                                        error = -1;
×
4748
                                                                        MLOCK(ErrorMessageLock);
×
4749
                                                                        MesPrint("&Wildcard set conflict");
×
4750
                                                                        MUNLOCK(ErrorMessageLock);
×
4751
                                                                }
4752
                                                        }
4753
                                                        *v = -1;
×
4754
                                                }
4755
                                                else {
4756
                                                        if ( sv < stop && ( *sv == FROMSET
112✔
4757
                                                        || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
56✔
4758
                                                                *m = -1;
×
4759
                                                                m = v;
×
4760
                                                        }
4761
                                                        else {
4762
                                                                *v = -1;
112✔
4763
                                                        }
4764
                                                }
4765
                                        }
4766
                                }
4767
                        }
4768
                        v += v[1];
24,143✔
4769
                        while ( v < stop && ( *v == FROMSET
42,966✔
4770
                         || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
31,178✔
4771
                }
4772
                s = pScrat;
18,515✔
4773
                v = m;
18,515✔
4774
                k = m[1];
18,515✔
4775
                NCOPY(s,m,k);
92,575✔
4776
                while ( m < stop && ( *m == FROMSET
55,223✔
4777
                 || *m == SETTONUM || *m == LOADDOLLAR ) ) {
24,213✔
4778
                        k = m[1];
12,495✔
4779
                        NCOPY(s,m,k);
80,990✔
4780
                }
4781
                *v = -1;
18,515✔
4782
                pScrat = s;
18,515✔
4783
                i = 0;
18,515✔
4784
                while ( i < nw && ( w[i] < 0 || w[i] == FROMSET
90,811✔
4785
                || w[i] == SETTONUM || w[i] == LOADDOLLAR ) ) i += w[i+1];
83,958✔
4786
        }
4787
        AC.NwildC = k = WORDDIF(pScrat,AT.WorkPointer);
6,853✔
4788
        s = AT.WorkPointer;
6,853✔
4789
        m = w;
6,853✔
4790
        NCOPY(m,s,k);
130,893✔
4791
        AC.WildC = m;
6,853✔
4792
        return(error);
6,853✔
4793
}
4794

4795
/*
4796
                 #] SortWild : 
4797
                 #[ CleanUpSort :                        VOID CleanUpSort(num)
4798
*/
4799
/**
4800
 *                Partially or completely frees function sort buffers.
4801
 */
4802

4803
void CleanUpSort(int num)
3,580✔
4804
{
4805
        GETIDENTITY
1,048✔
4806
        SORTING *S;
3,580✔
4807
        int minnum = num, i;
3,580✔
4808
        if ( AN.FunSorts ) {
3,580✔
4809
                if ( num == -1 ) {
3,476✔
4810
                        if ( AN.MaxFunSorts > 3 ) {
3,476✔
4811
                                minnum = (AN.MaxFunSorts+4)/2;
1,779✔
4812
                        }
4813
                        else minnum = 4;
4814
                }
4815
                else if ( minnum == 0 ) minnum = 1;
×
4816
                for ( i = minnum; i < AN.NumFunSorts; i++ ) {
337,172✔
4817
                        S = AN.FunSorts[i];
333,696✔
4818
                        if ( S ) {
333,696✔
4819
                                if ( S->file.handle >= 0 ) {
8✔
4820
/*                                        TruncateFile(S->file.handle); */
4821
                                        UpdateMaxSize();
×
4822
#ifdef WITHZLIB
4823
                                        ClearSortGZIP(&(S->file));
×
4824
#endif
4825
                                        CloseFile(S->file.handle);
×
4826
                                        S->file.handle = -1;
×
4827
                                        remove(S->file.name);
×
4828
#ifdef GZIPDEBUG
4829
                                        MLOCK(ErrorMessageLock);
4830
                                        MesPrint("%w CleanUpSort removed file %s",S->file.name);
4831
                                        MUNLOCK(ErrorMessageLock);
4832
#endif
4833
                                }
4834
                                M_free(S->sPointer, "CleanUpSort: sPointer");
8✔
4835
                                M_free(S->Patches, "CleanUpSort: Patches");
8✔
4836
                                M_free(S->pStop, "CleanUpSort: pStop");
8✔
4837
                                M_free(S->poina, "CleanUpSort: poina");
8✔
4838
                                M_free(S->poin2a, "CleanUpSort: poin2a");
8✔
4839
                                M_free(S->fPatches, "CleanUpSort: fPatches");
8✔
4840
                                M_free(S->fPatchesStop, "CleanUpSort: fPatchesStop");
8✔
4841
                                M_free(S->inPatches, "CleanUpSort: inPatches");
8✔
4842
                                M_free(S->tree, "CleanUpSort: tree");
8✔
4843
                                M_free(S->used, "CleanUpSort: used");
8✔
4844
#ifdef WITHZLIB
4845
                                M_free(S->fpcompressed, "CleanUpSort: fpcompressed");
8✔
4846
                                M_free(S->fpincompressed, "CleanUpSort: fpincompressed");
8✔
4847
#endif
4848
                                M_free(S->ktoi, "CleanUpSort: ktoi");
8✔
4849
                                M_free(S->lBuffer, "CleanUpSort: lBuffer+sBuffer");
8✔
4850
                                M_free(S->file.PObuffer, "CleanUpSort: PObuffer");
8✔
4851
                                M_free(S, "CleanUpSort: sorting struct");
8✔
4852
                        }
4853
                        AN.FunSorts[i] = 0;
333,696✔
4854
                }
4855
                AN.MaxFunSorts = minnum;
3,476✔
4856
                if ( num == 0 ) {
3,476✔
4857
                        S = AN.FunSorts[0];
×
4858
                        if ( S ) {
×
4859
                                if ( S->file.handle >= 0 ) {
×
4860
/*                                        TruncateFile(S->file.handle); */
4861
                                        UpdateMaxSize();
×
4862
#ifdef WITHZLIB
4863
                                        ClearSortGZIP(&(S->file));
×
4864
#endif
4865
                                        CloseFile(S->file.handle);
×
4866
                                        S->file.handle = -1;
×
4867
                                        remove(S->file.name);
×
4868
#ifdef GZIPDEBUG
4869
                                        MLOCK(ErrorMessageLock);
4870
                                        MesPrint("%w CleanUpSort removed file %s",S->file.name);
4871
                                        MUNLOCK(ErrorMessageLock);
4872
#endif
4873
                                }
4874
                        }
4875
                }
4876
        }
4877
        for ( i = 0; i < 2; i++ ) {
10,740✔
4878
                if ( AR.FoStage4[i].handle >= 0 ) {
7,160✔
4879
                        UpdateMaxSize();
×
4880
#ifdef WITHZLIB
4881
                        ClearSortGZIP(&(AR.FoStage4[i]));
×
4882
#endif
4883
                        CloseFile(AR.FoStage4[i].handle);
×
4884
                        remove(AR.FoStage4[i].name);
×
4885
                        AR.FoStage4[i].handle = -1;
×
4886
#ifdef GZIPDEBUG
4887
                        MLOCK(ErrorMessageLock);
4888
                        MesPrint("%w CleanUpSort removed stage4 file %s",AR.FoStage4[i].name);
4889
                        MUNLOCK(ErrorMessageLock);
4890
#endif
4891
                }
4892
        }
4893
}
3,580✔
4894

4895
/*
4896
                 #] CleanUpSort : 
4897
                 #[ LowerSortLevel :         VOID LowerSortLevel()
4898
*/
4899
/**
4900
 *                Lowers the level in the sort system.
4901
 */
4902

4903
VOID LowerSortLevel(VOID)
9,924✔
4904
{
4905
        GETIDENTITY
2,874✔
4906
        if ( AR.sLevel >= 0 ) {
9,924✔
4907
                AR.sLevel--;
9,924✔
4908
                if ( AR.sLevel >= 0 ) AT.SS = AN.FunSorts[AR.sLevel];
9,924✔
4909
        }
4910
}
9,924✔
4911

4912
/*
4913
                 #] LowerSortLevel : 
4914
                 #[ PolyRatFunSpecial :
4915

4916
                Keeps only the most divergent term in AR.PolyFunVar
4917
                We assume that the terms are already in that notation.
4918
*/
4919

4920
WORD *PolyRatFunSpecial(PHEAD WORD *t1, WORD *t2)
×
4921
{
4922
        WORD *oldworkpointer = AT.WorkPointer, *t, *r;
×
4923
        WORD exp1, exp2;
×
4924
        int i;
×
4925
        t = t1+FUNHEAD;
×
4926
        if ( *t == -SYMBOL ) {
×
4927
                if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
4928
                exp1 = 1;
×
4929
                if ( t[2] != -SNUMBER ) goto Illegal;
×
4930
                t[3] = 1;
×
4931
        }
4932
        else if ( *t == -SNUMBER ) {
×
4933
                t[1] = 1;
×
4934
                t += 2;
×
4935
                if ( *t == -SYMBOL ) {
×
4936
                        if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
4937
                        exp1 = -1;
4938
                }
4939
                else if ( *t == -SNUMBER ) {
×
4940
                        t[1] = 1;
×
4941
                        exp1 = 0;
×
4942
                }
4943
                else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
4944
                        && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
4945
                        t[ARGHEAD+5] = 1;
×
4946
                        t[ARGHEAD+6] = 1;
×
4947
                        t[ARGHEAD+7] = 3;
×
4948
                        exp1 = -t[ARGHEAD+4];
×
4949
                }
4950
                else goto Illegal;
×
4951
        }
4952
        else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
4953
                && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
4954
                t[ARGHEAD+5] = 1;
×
4955
                t[ARGHEAD+6] = 1;
×
4956
                t[ARGHEAD+7] = 3;
×
4957
                exp1 = t[ARGHEAD+4];
×
4958
                t += *t;
×
4959
                if ( *t != -SNUMBER ) goto Illegal;
×
4960
                t[1] = 1;
×
4961
        }
4962
        else goto Illegal;
×
4963

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

5003
        if ( exp1 <= exp2 ) { i = t1[1]; r = t1; }
×
5004
        else                { i = t2[1]; r = t2; }
×
5005
        t = oldworkpointer;
5006
        NCOPY(t,r,i)
×
5007

5008
        return(oldworkpointer);
5009
Illegal:
×
5010
        MesPrint("Illegal occurrence of PolyRatFun with divergent option");
×
5011
        Terminate(-1);
×
5012
        return(0);
×
5013
}
5014

5015
/*
5016
                 #] PolyRatFunSpecial : 
5017
                 #[ SimpleSplitMerge :
5018

5019
                Sorts an array of WORDs. No adding of equal objects.
5020
*/
5021

5022
VOID SimpleSplitMergeRec(WORD *array,WORD num,WORD *auxarray)
×
5023
{
5024
        WORD n1,n2,i,j,k,*t1,*t2;
×
5025
        if ( num < 2 ) return;
×
5026
        if ( num == 2 ) {
×
5027
                if ( array[0] > array[1] ) {
×
5028
                        EXCH(array[0],array[1])
×
5029
                }
5030
                return;
×
5031
        }
5032
        n1 = num/2;
×
5033
        n2 = num - n1;
×
5034
        SimpleSplitMergeRec(array,n1,auxarray);
×
5035
        SimpleSplitMergeRec(array+n1,n2,auxarray);
×
5036
        if ( array[n1-1] <= array[n1] ) return;
×
5037

5038
        t1 = array; t2 = auxarray; i = n1; NCOPY(t2,t1,i);
×
5039
        i = 0; j = n1; k = 0;
5040
        while ( i < n1 && j < num ) {
×
5041
                if ( auxarray[i] <= array[j] ) { array[k++] = auxarray[i++]; }
×
5042
                else { array[k++] = array[j++]; }
×
5043
        }
5044
        while ( i < n1 ) array[k++] = auxarray[i++];
×
5045
/*
5046
        Remember: remnants of j are still in place!
5047
*/
5048
}
5049

5050
VOID SimpleSplitMerge(WORD *array,WORD num)
×
5051
{
5052
        WORD *auxarray = Malloc1(sizeof(WORD)*num/2,"SimpleSplitMerge");
×
5053
        SimpleSplitMergeRec(array,num,auxarray);
×
5054
        M_free(auxarray,"SimpleSplitMerge");
×
5055
}
×
5056

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

5061
                Searches in the sorted array with length num for the object x.
5062
                If x is in the list, it returns the number of the array element
5063
                that matched. If it is not in the list, it returns -1.
5064
                If there are identical objects in the list, which one will
5065
                match is quasi random.
5066
*/
5067

5068
WORD BinarySearch(WORD *array,WORD num,WORD x)
×
5069
{
5070
        WORD i, bot, top, med;
×
5071
        if ( num < 8 ) {
×
5072
                for ( i = 0; i < num; i++ ) if ( array[i] == x ) return(i);
×
5073
                return(-1);
5074
        }
5075
        if ( array[0] > x || array[num-1] < x ) return(-1);
×
5076
        bot = 0; top = num-1; med = (top+bot)/2;
×
5077
        do {
×
5078
                if ( array[med] == x ) return(med);
×
5079
                if ( array[med] < x ) { bot = med+1; }
×
5080
                else { top = med-1; }
×
5081
                med = (top+bot)/2;
×
5082
        } while ( med >= bot && med <= top );
×
5083
        return(-1);
5084
}
5085

5086
/*
5087
                 #] BinarySearch : 
5088
        #] SortUtilities :
5089
*/
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