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

form-dev / form / 15701338753

17 Jun 2025 07:49AM UTC coverage: 50.382% (-0.004%) from 50.386%
15701338753

Pull #662

github

web-flow
Merge f1f68c050 into 207386593
Pull Request #662: Cleanup: change VOID into void

178 of 245 new or added lines in 34 files covered. (72.65%)

2 existing lines in 1 file now uncovered.

41784 of 82935 relevant lines covered (50.38%)

2640008.85 hits per line

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

62.85
/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)
484,206✔
102
{
103
        GETIDENTITY
322,762✔
104
        LONG millitime, y = 0x7FFFFFFFL >> 1;
484,206✔
105
        WORD timepart;
484,206✔
106
        SORTING *S;
484,206✔
107
        POSITION pp;
484,206✔
108
        int use_wtime;
484,206✔
109
        if ( AT.SS == AT.S0 && AC.StatsFlag ) {
484,206✔
110
#ifdef WITHPTHREADS
111
                if ( AC.ThreadStats == 0 && identity > 0 ) return;
11,365✔
112
#elif defined(WITHMPI)
113
                if ( AC.OldParallelStats ) return;
114
                if ( ! AC.ProcessStats && PF.me != MASTER ) return;
115
#endif
116
                if ( Expressions == 0 ) return;
13,244✔
117

118
                if ( par == STATSSPLITMERGE ) {
11,362✔
119
                        if ( AC.ShortStatsMax == 0 ) return;
5,659✔
120
                        AR.ShortSortCount++;
×
121
                        if ( AR.ShortSortCount < AC.ShortStatsMax ) return;
×
122
                }
123
                AR.ShortSortCount = 0;
5,703✔
124

125
                S = AT.SS;
5,703✔
126

127
                MLOCK(ErrorMessageLock);
5,703✔
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;
5,703✔
133
                if ( checkLogType && AM.LogType ) {
5,703✔
134
                        AC.LogHandle = -1;
363✔
135
                }
136

137
                if ( AC.ShortStats ) {}
5,703✔
138
                else {
139
#ifdef WITHPTHREADS
140
                        if ( identity > 0 ) {
3,795✔
141
                                MesPrint("             Thread %d reporting",identity);
271✔
142
                        }
143
                        else {
144
                                MesPrint("");
3,524✔
145
                        }
146
#elif defined(WITHMPI)
147
                        if ( PF.me != MASTER ) {
148
                                MesPrint("             Process %d reporting",PF.me);
149
                        }
150
                        else {
151
                                MesPrint("");
152
                        }
153
#else
154
                        MesPrint("");
1,884✔
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;
5,703✔
164
#if defined(WITHPTHREADS)
165
                if ( use_wtime && identity > 0 ) use_wtime = 0;
3,811✔
166
#elif defined(WITHMPI)
167
                if ( use_wtime && PF.me != MASTER ) use_wtime = 0;
168
#endif
169
                millitime = use_wtime ? TimeWallClock(1) * 10 : TimeCPU(1);
5,703✔
170
                timepart = (WORD)(millitime%1000);
5,703✔
171
                millitime /= 1000;
5,703✔
172
                timepart /= 10;
5,703✔
173
                if ( AC.ShortStats ) {
5,703✔
174
#if defined(WITHPTHREADS) || defined(WITHMPI)
175
#ifdef WITHPTHREADS
176
                  if ( identity > 0 ) {
16✔
177
#else
178
                  if ( PF.me != MASTER ) {
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 ) {
24✔
305
                                SETBASEPOSITION(pp,y);
24✔
306
                                if ( ISLESSPOS(*plspace,pp) ) {
24✔
307
                                        MesPrint("%7l.%2is %8l>%10l%3s%10l:%10p %s %s",
24✔
308
                                        millitime,timepart,AN.ninterms,S->GenTerms,toterms[par],
309
                                        S->TermsLeft,plspace,EXPRNAME(AR.CurExpr),AC.Commercial);
24✔
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 ) {
5,679✔
428
                        if ( use_wtime ) {
363✔
429
                                MesPrint("WTime = %7l.%2i sec",millitime,timepart);
×
430
                        }
431
                        else {
432
                                MesPrint("Time = %7l.%2i sec",millitime,timepart);
363✔
433
                        }
434
                }
435
                else {
436
#if ( BITSINLONG > 32 )
437
                        if ( S->GenTerms >= 10000000000L ) {
5,316✔
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 ) {
5,316✔
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",
5,316✔
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 )
5,679✔
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 ) {
5,679✔
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 ) {
3,795✔
501
                                        MesPrint("%16s         Terms in thread = %10l",
28✔
502
                                        EXPRNAME(AR.CurExpr),S->TermsLeft);
28✔
503
                                }
504
                                else
505
#elif defined(WITHMPI)
506
                                if ( PF.me != MASTER && par == STATSPOSTSORT ) {
507
                                        MesPrint("%16s         Terms in process= %10l",
508
                                        EXPRNAME(AR.CurExpr),S->TermsLeft);
509
                                }
510
                                else
511
#endif
512
                                {
513
                                        MesPrint("%16s         Terms %s = %10l",
5,651✔
514
                                        EXPRNAME(AR.CurExpr),FG.swmes[par],S->TermsLeft);
5,651✔
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);
5,679✔
543
                if ( ISLESSPOS(*plspace,pp) ) {
5,679✔
544
                        MesPrint("%24s Bytes used      = %10p",AC.Commercial,plspace);
5,679✔
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;
5,703✔
595

596
                MUNLOCK(ErrorMessageLock);
163,373✔
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)
10,767,921✔
615
{
616
        GETBIDENTITY
617
        SORTING *S, **newFS;
10,767,921✔
618
        int i, newsize;
10,767,921✔
619
        if ( AN.SoScratC == 0 )
10,767,921✔
620
                AN.SoScratC = (UWORD *)Malloc1(2*(AM.MaxTal+2)*sizeof(UWORD),"NewSort");
4,074✔
621
        AR.sLevel++;
10,767,921✔
622
        if ( AR.sLevel >= AN.NumFunSorts ) {
10,767,921✔
623
                if ( AN.NumFunSorts == 0 ) newsize = 100;
5,282✔
624
                else newsize = 2*AN.NumFunSorts;
×
625
                newFS = (SORTING **)Malloc1((newsize+1)*sizeof(SORTING *),"FunSort pointers");
5,282✔
626
                for ( i = 0; i < AN.NumFunSorts; i++ ) newFS[i] = AN.FunSorts[i];
10,564✔
627
                for ( ; i <= newsize; i++ ) newFS[i] = 0;
538,764✔
628
                if ( AN.FunSorts ) M_free(AN.FunSorts,"FunSort pointers");
5,282✔
629
                AN.FunSorts = newFS; AN.NumFunSorts = newsize;
5,282✔
630
        }
631
        if ( AR.sLevel == 0 ) {
10,767,921✔
632

633
                numcompares = 0;
513,894✔
634

635
                AN.FunSorts[0] = AT.S0;
513,894✔
636
                if ( AR.PolyFun == 0 ) { AT.S0->PolyFlag = 0; }
513,894✔
637
                else if ( AR.PolyFunType == 1 ) { AT.S0->PolyFlag = 1; }
96,462✔
638
                else if ( AR.PolyFunType == 2 ) {
96,354✔
639
                        if ( AR.PolyFunExp == 2
96,354✔
640
                          || AR.PolyFunExp == 3 ) AT.S0->PolyFlag = 1;
96,354✔
641
                        else                      AT.S0->PolyFlag = 2;
96,006✔
642
                }
643
                AR.ShortSortCount = 0;
513,894✔
644
        }
645
        else {
646
                if ( AN.FunSorts[AR.sLevel] == 0 ) {
10,254,027✔
647
                        AN.FunSorts[AR.sLevel] = AllocSort(
2,455✔
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;
10,254,027✔
652
        }
653
        AT.SS = S = AN.FunSorts[AR.sLevel];
10,767,921✔
654
        S->sFill = S->sBuffer;
10,767,921✔
655
        S->lFill = S->lBuffer;
10,767,921✔
656
        S->lPatch = 0;
10,767,921✔
657
        S->fPatchN = 0;
10,767,921✔
658
        S->GenTerms = S->TermsLeft = S->GenSpace = S->SpaceLeft = 0;
10,767,921✔
659
        S->PoinFill = S->sPointer;
10,767,921✔
660
        *S->PoinFill = S->sFill;
10,767,921✔
661
        if ( AR.sLevel > 0 ) { S->PolyWise = 0; }
10,767,921✔
662
        PUTZERO(S->SizeInFile[0]); PUTZERO(S->SizeInFile[1]); PUTZERO(S->SizeInFile[2]);
10,767,921✔
663
        S->sTerms = 0;
10,767,921✔
664
        PUTZERO(S->file.POposition);
10,767,921✔
665
        S->stage4 = 0;
10,767,921✔
666
        if ( AR.sLevel > AN.MaxFunSorts ) AN.MaxFunSorts = AR.sLevel;
10,767,921✔
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);
10,767,921✔
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)
10,739,277✔
705
{
706
  GETBIDENTITY
707
  SORTING *S = AT.SS;
10,739,277✔
708
  WORD j, **ss, *to, *t;
10,739,277✔
709
  LONG sSpace, over, tover, spare, retval = 0, jj;
10,739,277✔
710
  POSITION position, pp;
10,739,277✔
711
  off_t lSpace;
10,739,277✔
712
  FILEHANDLE *fout = 0, *oldoutfile = 0, *newout = 0;
10,739,277✔
713

714
  if ( AM.exitflag && AR.sLevel == 0 ) return(0);
10,739,277✔
715
#ifdef WITHMPI 
716
  if( (retval = PF_EndSort()) > 0){
717
        oldoutfile = AR.outfile;
718
        retval = 0;
719
        goto RetRetval;
720
  } 
721
  else if(retval < 0){
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;
10,739,277✔
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;
10,739,277✔
744
        *(S->PoinFill) = 0;
10,739,277✔
745
#ifdef SPLITTIME
746
                PrintTime((UBYTE *)"EndSort, before SplitMerge");
747
#endif
748
        S->sPointer[SplitMerge(BHEAD S->sPointer,S->sTerms)] = 0;
10,739,277✔
749
#ifdef SPLITTIME
750
                PrintTime((UBYTE *)"Endsort,  after SplitMerge");
751
#endif
752
        sSpace = 0;
10,739,257✔
753
        tover = over = S->sTerms;
10,739,257✔
754
        ss = S->sPointer;
10,739,257✔
755
        if ( over >= 0 ) {
10,739,257✔
756
                if ( S->lPatch > 0 || S->file.handle >= 0 ) {
10,739,257✔
757
                        ss[over] = 0;
261✔
758
                        sSpace = ComPress(ss,&spare);
261✔
759
                        S->TermsLeft -= over - spare;
261✔
760
                        if ( par == 1 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
261✔
761
                }
762
                else if ( S != AT.S0 ) {
10,738,996✔
763
                        ss[over] = 0;
10,253,814✔
764
                        if ( par == 2 ) {
10,253,814✔
765
                                sSpace = 3;
766
                                while ( ( t = *ss++ ) != 0 ) { sSpace += *t; }
10,448,955✔
767
                                if ( AN.tryterm > 0 && ( (sSpace+1)*sizeof(WORD) < (size_t)(AM.MaxTer) ) ) {
506,134✔
768
                                        to = TermMalloc("$-sort space");
90✔
769
                                }
770
                                else {
771
                                        LONG allocsp = sSpace+1;
506,044✔
772
                                        if ( allocsp < MINALLOC ) allocsp = MINALLOC;
506,044✔
773
                                        allocsp = ((allocsp+7)/8)*8;
506,044✔
774
                                        to = (WORD *)Malloc1(allocsp*sizeof(WORD),"$-sort space");
506,044✔
775
                                        if ( AN.tryterm > 0 ) AN.tryterm = 0;
506,044✔
776
                                }
777
                                *((WORD **)buffer) = to;
506,134✔
778
                                ss = S->sPointer;
506,134✔
779
                                while ( ( t = *ss++ ) != 0 ) {
10,448,955✔
780
                                        j = *t; while ( --j >= 0 ) *to++ = *t++;
128,150,059✔
781
                                }
782
                                *to = 0;
506,134✔
783
                                retval = sSpace + 1;
506,134✔
784
                        }
785
                        else {
786
                                to = buffer;
787
                                sSpace = 0;
788
                                while ( ( t = *ss++ ) != 0 ) {
49,674,097✔
789
                                        j = *t;
39,926,417✔
790
                                        if ( ( sSpace += j ) > AM.MaxTer/((LONG)sizeof(WORD)) ) {
39,926,417✔
791
                                                /* Too big! Get the total size for useful error message */
792
                                                while ( ( t = *ss++ ) != 0 ) {
×
793
                                                        sSpace += *t;
×
794
                                                }
795
                                                MLOCK(ErrorMessageLock);
×
796
                                                MesPrint("Sorted function argument too long (%d words). Increase MaxTermSize (%l words).", sSpace, AM.MaxTer/((LONG)sizeof(WORD)));
×
797
                                                MUNLOCK(ErrorMessageLock);
×
798
                                                retval = -1; goto RetRetval;
×
799
                                        }
800
                                        while ( --j >= 0 ) *to++ = *t++;
385,896,791✔
801
                                }
802
                                *to = 0;
9,747,680✔
803
                                retval = to - buffer;
9,747,680✔
804
                        }
805
                        goto RetRetval;
10,253,814✔
806
                }
807
                else {
808
                        POSITION oldpos;
485,182✔
809
                        if ( S == AT.S0 ) {
485,182✔
810
                                fout = AR.outfile;
485,182✔
811
                                *AR.CompressPointer = 0;
485,182✔
812
                                SeekScratch(AR.outfile,&position);
485,182✔
813
                        }
814
                        else {
815
                                fout = &(S->file);
816
                                PUTZERO(position);
817
                        }
818
                        oldpos = position;
485,182✔
819
                        S->TermsLeft = 0;
485,182✔
820
/*
821
                        Here we can go directly to the output.
822
*/
823
#ifdef WITHZLIB
824
                        { int oldgzipCompress = AR.gzipCompress;
485,182✔
825
                                AR.gzipCompress = 0;
485,182✔
826
#endif
827
                        if ( tover > 0 ) {
485,182✔
828
                                ss = S->sPointer;
443,294✔
829
                                while ( ( t = *ss++ ) != 0 ) {
7,917,129✔
830
                                        if ( *t ) S->TermsLeft++;
7,473,835✔
831
#ifdef WITHPTHREADS
832
                                        if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD t); }
4,920,729✔
833
                                        else
834
#endif
835
                                        if ( PutOut(BHEAD t,&position,fout,1) < 0 ) {
6,789,374✔
836
                                                retval = -1; goto RetRetval;
×
837
                                        }
838
                                }
839
                        }
840
#ifdef WITHPTHREADS
841
                        if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD 0); }
325,984✔
842
                        else
843
#endif
844
                        if ( FlushOut(&position,fout,1) ) {
473,814✔
845
                                retval = -1; goto RetRetval;
×
846
                        }
847
#ifdef WITHZLIB
848
                                AR.gzipCompress = oldgzipCompress;
485,182✔
849
                        }
850
#endif
851
#ifdef WITHPTHREADS
852
                        if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
325,984✔
853
#endif
854
#ifdef WITHMPI
855
                        if ( PF.me != MASTER && PF.exprtodo < 0 ) goto RetRetval;
856
#endif
857
                        DIFPOS(oldpos,position,oldpos);
473,814✔
858
                        S->SpaceLeft = BASEPOSITION(oldpos);
473,814✔
859
                        WriteStats(&oldpos,STATSPOSTSORT,NOCHECKLOGTYPE);
473,814✔
860
                        pp = oldpos;
473,814✔
861
                        goto RetRetval;
473,814✔
862
                }
863
        }
864
        else if ( par == 1 && newout == 0 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
×
865
        sSpace++;
261✔
866
        lSpace = sSpace + (S->lFill - S->lBuffer) - (LONG)S->lPatch*(AM.MaxTer/sizeof(WORD));
261✔
867
/*         Note wrt MaxTer and lPatch: each patch starts with space for decompression */
868
/*         Not needed if only large buffer, but needed when using files (?) */
869
        SETBASEPOSITION(pp,lSpace);
261✔
870
        MULPOS(pp,sizeof(WORD));
261✔
871
        if ( S->file.handle >= 0 ) {
261✔
872
                ADD2POS(pp,S->fPatches[S->fPatchN]);
34✔
873
        }
874
        if ( S == AT.S0 ) {
261✔
875
                if ( S->lPatch > 0 || S->file.handle >= 0 ) {
60✔
876
                        WriteStats(&pp,STATSSPLITMERGE,CHECKLOGTYPE);
60✔
877
                }
878
        }
879
        if ( par == 2 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
261✔
880
        if ( S->lPatch > 0 ) {
261✔
881
                if ( ( S->lPatch >= S->MaxPatches ) ||
261✔
882
                        ( ( (WORD *)(((UBYTE *)(S->lFill + sSpace)) + 2*AM.MaxTer) ) >= S->lTop ) ) {
246✔
883
/*
884
                        The large buffer is too full. Merge and write it
885
*/
886
#ifdef GZIPDEBUG
887
                        MLOCK(ErrorMessageLock);
888
                        MesPrint("%w EndSort: lPatch = %d, MaxPatches = %d,lFill = %x, sSpace = %ld, MaxTer = %d, lTop = %x"
889
                                        ,S->lPatch,S->MaxPatches,S->lFill,sSpace,AM.MaxTer/sizeof(WORD),S->lTop);
890
                        MUNLOCK(ErrorMessageLock);
891
#endif
892

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

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

1271
/*
1272
                 #] EndSort : 
1273
                 #[ PutIn :                                        LONG PutIn(handle,position,buffer,take,npat)
1274
*/
1275
/**
1276
 *        Reads a new patch from position in file handle.
1277
 *        It is put at buffer, anything after take is moved forward.
1278
 *        This would be part of a term that hasn't been used yet.
1279
 *        Because of this there should be some space before the start of the buffer
1280
 *
1281
 *        @param file     The file system from which to read
1282
 *        @param position The position from which to read
1283
 *        @param buffer   The buffer into which to read
1284
 *        @param take     The unused tail should be moved before the buffer
1285
 *        @param npat                The number of the patch. Is needed if the information
1286
 *                        was compressed with gzip, because each patch has its
1287
 *                        own independent gzip encoding.
1288
 */
1289

1290
LONG PutIn(FILEHANDLE *file, POSITION *position, WORD *buffer, WORD **take, int npat)
600✔
1291
{
1292
        LONG i, RetCode;
600✔
1293
        WORD *from, *to;
600✔
1294
#ifndef WITHZLIB
1295
        DUMMYUSE(npat);
1296
#endif
1297
        from = buffer + ( file->POsize * sizeof(UBYTE) )/sizeof(WORD);
600✔
1298
        i = from - *take;
600✔
1299
        if ( i*((LONG)(sizeof(WORD))) > AM.MaxTer ) {
600✔
1300
                MLOCK(ErrorMessageLock);
×
1301
                MesPrint("Problems in PutIn");
×
1302
                MUNLOCK(ErrorMessageLock);
×
1303
                Terminate(-1);
×
1304
        }
1305
        to = buffer;
1306
        while ( --i >= 0 ) *--to = *--from;
952✔
1307
        *take = to;
600✔
1308
#ifdef WITHZLIB
1309
        if ( ( RetCode = FillInputGZIP(file,position,(UBYTE *)buffer
600✔
1310
                                                                        ,file->POsize,npat) ) < 0 ) {
1311
                MLOCK(ErrorMessageLock);
×
1312
                MesPrint("PutIn: We have RetCode = %x while reading %x bytes",
×
1313
                        RetCode,file->POsize);
1314
                MUNLOCK(ErrorMessageLock);
×
1315
                Terminate(-1);
×
1316
        }
1317
#else
1318
#ifdef ALLLOCK
1319
        LOCK(file->pthreadslock);
1320
#endif
1321
        SeekFile(file->handle,position,SEEK_SET);
1322
        if ( ( RetCode = ReadFile(file->handle,(UBYTE *)buffer,file->POsize) ) < 0 ) {
1323
#ifdef ALLLOCK
1324
                UNLOCK(file->pthreadslock);
1325
#endif
1326
                MLOCK(ErrorMessageLock);
1327
                MesPrint("PutIn: We have RetCode = %x while reading %x bytes",
1328
                        RetCode,file->POsize);
1329
                MUNLOCK(ErrorMessageLock);
1330
                Terminate(-1);
1331
        }
1332
#ifdef ALLLOCK
1333
        UNLOCK(file->pthreadslock);
1334
#endif
1335
#endif
1336
        return(RetCode);
600✔
1337
}
1338

1339
/*
1340
                 #] PutIn : 
1341
                 #[ Sflush :                                        WORD Sflush(file)
1342
*/
1343
/**
1344
 *        Puts the contents of a buffer to output
1345
 *        Only to be used when there is a single patch in the large buffer.
1346
 *
1347
 *        @param fi  The filesystem (or its cache) to which the patch should be written
1348
 */
1349

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

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

1436
WORD PutOut(PHEAD WORD *term, POSITION *position, FILEHANDLE *fi, WORD ncomp)
31,690,033✔
1437
{
1438
        GETBIDENTITY
1439
        WORD i, *p, ret, *r, *rr, j, k, first;
31,690,033✔
1440
        int dobracketindex = 0;
31,690,033✔
1441
        LONG RetCode;
31,690,033✔
1442

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

1532
        if ( AR.sLevel <= 0 && Expressions[AR.CurExpr].newbracketinfo
30,977,310✔
1533
                && ( fi == AR.outfile || fi == AR.hidefile ) ) dobracketindex = 1;
62,526✔
1534
        r = rr = AR.CompressPointer;
30,977,310✔
1535
        first = j = k = ret = 0;
30,977,310✔
1536
        if ( ( i = *term ) != 0 ) {
30,977,310✔
1537
                if ( i < 0 ) {                        /* Compressed term */
30,977,310✔
1538
                        i = term[1] + 2;
41✔
1539
                        if ( fi == AR.outfile || fi == AR.hidefile ) {
41✔
1540
                                MLOCK(ErrorMessageLock);
×
1541
                                MesPrint("Ran into precompressed term");
×
1542
                                MUNLOCK(ErrorMessageLock);
×
1543
                                Crash();
×
1544
                                return(-1);
×
1545
                        }
1546
                }
1547
                else if ( !AR.NoCompress && ( ncomp > 0 ) && AR.sLevel <= 0 ) {        /* Must compress */
30,977,269✔
1548
                        if ( dobracketindex ) {
16,796,307✔
1549
                                PutBracketInIndex(BHEAD term,position);
62,526✔
1550
                        }
1551
                        j = *r++ - 1;
16,796,307✔
1552
                        p = term + 1;
16,796,307✔
1553
                        i--;
16,796,307✔
1554
                        if ( AR.PolyFun ) {
16,796,307✔
1555
                                WORD *polystop, *sa;
102,696✔
1556
                                sa = p + i;
102,696✔
1557
                                sa -= ABS(sa[-1]);
102,696✔
1558
                                polystop = p;
102,696✔
1559
                                while ( polystop < sa && *polystop != AR.PolyFun ) {
117,516✔
1560
                                        polystop += polystop[1];
14,820✔
1561
                                }
1562
                                if ( polystop < sa ) {
102,696✔
1563
                                        if ( AR.PolyFunType == 2 ) polystop[2] &= ~MUSTCLEANPRF;
102,696✔
1564
                                        while ( i > 0 && j > 0 && *p == *r && p < polystop ) {
173,346✔
1565
                                                i--; j--; k--; p++; r++;
70,650✔
1566
                                        }
1567
                                }
1568
                                else {
1569
                                        while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
×
1570
                                }
1571
                        }
1572
#ifdef WITHFLOAT
1573
                        else if ( AC.DefaultPrecision ) {
16,693,611✔
1574
                                WORD *floatstop, *sa;
16,693,611✔
1575
                                sa = p + i;
16,693,611✔
1576
                                sa -= ABS(sa[-1]);
16,693,611✔
1577
                                floatstop = p;
16,693,611✔
1578
                                while ( floatstop < sa && *floatstop != FLOATFUN ) {
36,217,030✔
1579
                                        floatstop += floatstop[1];
19,523,419✔
1580
                                }
1581
                                if ( floatstop < sa ) {
16,693,611✔
1582
                                        while ( i > 0 && j > 0 && *p == *r && p < floatstop ) {
114✔
1583
                                                i--; j--; k--; p++; r++;
×
1584
                                        }
1585
                                }
1586
                                else {
1587
                                        while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
98,175,326✔
1588
                                }
1589
                        }
1590
#endif
1591
                        else {
1592
                                WORD *sa;
×
1593
                                sa = p + i;
×
1594
                                sa -= ABS(sa[-1]);
×
1595
                                while ( i > 0 && j > 0 && *p == *r && p < sa ) { i--; j--; k--; p++; r++; }
×
1596
                        }
1597
                        if ( k > -2 ) {
16,796,307✔
1598
nocompress:
1,105,538✔
1599
                                j = i = *term;
1,385,318✔
1600
                                k = 0;
1,385,318✔
1601
                                p = term;
1,385,318✔
1602
                                r = rr;
1,385,318✔
1603
                                NCOPY(r,p,j);
108,994,928✔
1604
                        }
1605
                        else {
1606
                                *rr = *term;
15,690,769✔
1607
                                term = p;
15,690,769✔
1608
                                j = i;
15,690,769✔
1609
                                NCOPY(r,p,j);
163,629,918✔
1610
                                j = i;
15,690,769✔
1611
                                i += 2;
15,690,769✔
1612
                                first = 2;
15,690,769✔
1613
                        }
1614
/*                                        Sabotage getting into the coefficient next time */
1615
                        r[-(ABS(r[-1]))] = 0;
17,076,087✔
1616
                        if ( r >= AR.ComprTop ) {
17,076,087✔
1617
                                MLOCK(ErrorMessageLock);
×
1618
                                MesPrint("CompressSize of %10l is insufficient",AM.CompressSize);
×
1619
                                MUNLOCK(ErrorMessageLock);
×
1620
                                Crash();
×
1621
                                return(-1);
×
1622
                        }
1623
                }
1624
                else if ( !AR.NoCompress && ( ncomp < 0 ) && AR.sLevel <= 0 ) {
14,180,962✔
1625
                                /* No compress but put in compress buffer anyway */
1626
                        if ( dobracketindex ) {
279,780✔
1627
                                PutBracketInIndex(BHEAD term,position);
×
1628
                        }
1629
                        j = *r++ - 1;
279,780✔
1630
                        p = term + 1;
279,780✔
1631
                        i--;
279,780✔
1632
                        if ( AR.PolyFun ) {
279,780✔
1633
                                WORD *polystop, *sa;
45,504✔
1634
                                sa = p + i;
45,504✔
1635
                                sa -= ABS(sa[-1]);
45,504✔
1636
                                polystop = p;
45,504✔
1637
                                while ( polystop < sa && *polystop != AR.PolyFun ) {
45,504✔
1638
                                        polystop += polystop[1];
×
1639
                                }
1640
                                if ( polystop < sa ) {
45,504✔
1641
                                        if ( AR.PolyFunType == 2 ) polystop[2] &= ~MUSTCLEANPRF;
45,504✔
1642
                                        while ( i > 0 && j > 0 && *p == *r && p < polystop ) {
45,504✔
1643
                                                i--; j--; k--; p++; r++;
×
1644
                                        }
1645
                                }
1646
                                else {
1647
                                        while ( i > 0 && j > 0 && *p == *r ) { i--; j--; k--; p++; r++; }
×
1648
                                }
1649
                        }
1650
                        else {
1651
                                while ( i > 0 && j > 0 && *p == *r ) { i--; j--; k--; p++; r++; }
234,276✔
1652
                        }
1653
                        goto nocompress;
279,780✔
1654
                }
1655
                else {
1656
                        if ( AR.PolyFunType == 2 ) {
13,901,182✔
1657
                                WORD *t, *tstop;
320,508✔
1658
                                tstop = term + *term;
320,508✔
1659
                                tstop -= ABS(tstop[-1]);
320,508✔
1660
                                t = term+1;
320,508✔
1661
                                while ( t < tstop ) {
641,016✔
1662
                                        if ( *t == AR.PolyFun ) {
320,508✔
1663
                                                t[2] &= ~MUSTCLEANPRF;
×
1664
                                        }
1665
                                        t += t[1];
320,508✔
1666
                                }
1667
                        }
1668
                        if ( dobracketindex ) {
13,901,182✔
1669
                                PutBracketInIndex(BHEAD term,position);
×
1670
                        }
1671
                }
1672
                ret = i;
30,977,310✔
1673
                ADDPOS(*position,i*sizeof(WORD));
30,977,310✔
1674
                p = fi->POfill;
30,977,310✔
1675
                do {
570,461,701✔
1676
                        if ( p >= fi->POstop ) {
570,461,701✔
1677
#ifdef WITHMPI /* [16mar1998 ar] */
1678
                          if ( PF.me != MASTER && AR.sLevel <= 0 && (fi == AR.outfile || fi == AR.hidefile) && PF.parallel && PF.exprtodo < 0 ) {
1679
                                PF_BUFFER *sbuf = PF.sbuf;
1680
                                sbuf->fill[sbuf->active] = fi->POstop;
1681
                                PF_ISendSbuf(MASTER,PF_BUFFER_MSGTAG);
1682
                                p = fi->PObuffer = fi->POfill = fi->POfull =
1683
                                  sbuf->buff[sbuf->active];
1684
                                fi->POstop = sbuf->stop[sbuf->active];
1685
                          }
1686
                          else
1687
#endif /* WITHMPI [16mar1998 ar] */
1688
                          {
1689
                                if ( fi->handle < 0 ) {
204✔
1690
                                        if ( ( RetCode = CreateFile(fi->name) ) >= 0 ) {
18✔
1691
#ifdef GZIPDEBUG
1692
                                                MLOCK(ErrorMessageLock);
1693
                                                MesPrint("%w PutOut created sortfile %s",fi->name);
1694
                                                MUNLOCK(ErrorMessageLock);
1695
#endif
1696
                                                fi->handle = (WORD)RetCode;
18✔
1697
                                                PUTZERO(fi->filesize);
18✔
1698
                                                PUTZERO(fi->POposition);
18✔
1699
/*
1700
                                                Should not be here?
1701
#ifdef WITHZLIB
1702
                                                fi->ziobuffer = 0;
1703
#endif
1704
*/
1705
                                        }
1706
                                        else {
1707
                                                MLOCK(ErrorMessageLock);
×
1708
                                                MesPrint("Cannot create scratch file %s",fi->name);
×
1709
                                                MUNLOCK(ErrorMessageLock);
×
1710
                                                return(-1);
×
1711
                                        }
1712
                                }
1713
#ifdef WITHZLIB
1714
                                if ( !AR.NoCompress && ncomp > 0 && AR.gzipCompress > 0
204✔
1715
                                        && dobracketindex == 0 && fi->zsp != 0 ) {
46✔
1716
                                        fi->POfill = p;
46✔
1717
                                        if ( PutOutputGZIP(fi) ) return(-1);
46✔
1718
                                        p = fi->PObuffer;
46✔
1719
                                }
1720
                                else
1721
#endif
1722
                                {
1723
#ifdef ALLLOCK
1724
                                  LOCK(fi->pthreadslock);
1725
#endif
1726
                                  if ( fi == AR.hidefile ) {
158✔
1727
                                        LOCK(AS.inputslock);
90✔
1728
                                  }
1729
                                  SeekFile(fi->handle,&(fi->POposition),SEEK_SET);
158✔
1730
                                  if ( ( RetCode = WriteFile(fi->handle,(UBYTE *)(fi->PObuffer),fi->POsize) ) != fi->POsize ) {
158✔
1731
                                        if ( fi == AR.hidefile ) {
×
1732
                                                UNLOCK(AS.inputslock);
×
1733
                                        }
1734
#ifdef ALLLOCK
1735
                                        UNLOCK(fi->pthreadslock);
1736
#endif
1737
                                        MLOCK(ErrorMessageLock);
×
1738
                                        MesPrint("Write error during sort. Disk full?");
×
1739
                                        MesPrint("Attempt to write %l bytes on file %d at position %15p",
×
1740
                                                                fi->POsize,fi->handle,&(fi->POposition));
1741
                                        MesPrint("RetCode = %l, Buffer address = %l",RetCode,(LONG)(fi->PObuffer));
×
1742
                                        MUNLOCK(ErrorMessageLock);
×
1743
                                        return(-1);
×
1744
                                  }
1745
                                  ADDPOS(fi->filesize,fi->POsize);
158✔
1746
                                  p = fi->PObuffer;
158✔
1747
                                  ADDPOS(fi->POposition,fi->POsize);
158✔
1748
                                  if ( fi == AR.hidefile ) {
158✔
1749
                                        UNLOCK(AS.inputslock);
194,685,834✔
1750
                                  }
1751
#ifdef ALLLOCK
1752
                                  UNLOCK(fi->pthreadslock);
1753
#endif
1754
#ifdef WITHPTHREADS
1755
                                  if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
68✔
1756
                                        if ( fi->handle >= 0 ) SynchFile(fi->handle);
1757
                                  }
1758
#endif
1759
                                }
1760
                          }
1761
                        } 
1762
                        if ( first ) {
570,461,701✔
1763
                                if ( first == 2 ) *p++ = k;
31,381,538✔
1764
                                else *p++ = j;
15,690,769✔
1765
                                first--;
31,381,538✔
1766
                        }
1767
                        else *p++ = *term++;
539,080,163✔
1768
/*
1769
                        if ( AP.DebugFlag ) {
1770
                                TalToLine((UWORD)(p[-1])); TokenToLine((UBYTE *)"  ");
1771
                        }
1772
*/
1773
                } while ( --i > 0 );
570,461,701✔
1774
                fi->POfull = fi->POfill = p;
30,977,310✔
1775
        }
1776
/*
1777
        if ( AP.DebugFlag ) {
1778
                AO.OutSkip = 0;
1779
                FiniLine();
1780
        }
1781
*/
1782
        return(ret);
1783
}
1784

1785
/*
1786
                 #] PutOut : 
1787
                 #[ FlushOut :                                WORD FlushOut(position,file,compr)
1788
*/
1789
/**
1790
 *        Completes output to an output file and writes the trailing zero.
1791
 *
1792
 *        @param position The position in the file after writing
1793
 *        @param fi       The file (or its cache)
1794
 *        @param compr        Indicates whether there should be compression with gzip.
1795
 *        @return   Regular conventions (OK -> 0).
1796
 */
1797

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

1994
/*
1995
                 #] FlushOut : 
1996
                 #[ AddCoef :                                WORD AddCoef(pterm1,pterm2)
1997
*/
1998
/**
1999
 *                Adds the coefficients of the terms *ps1 and *ps2.
2000
 *                The problem comes when there is not enough space for a new
2001
 *                longer coefficient. First a local solution is tried.
2002
 *                If this is not successful we need to move terms around.
2003
 *                The possibility of a garbage collection should not be
2004
 *                ignored, as avoiding this costs very much extra space which
2005
 *                is nearly wasted otherwise.
2006
 *
2007
 *                If the return value is zero the terms cancelled.
2008
 *
2009
 *                The resulting term is left in *ps1.
2010
 */
2011

2012
WORD AddCoef(PHEAD WORD **ps1, WORD **ps2)
16,822,029✔
2013
{
2014
        GETBIDENTITY
2015
        SORTING *S = AT.SS;
16,822,029✔
2016
        WORD *s1, *s2;
16,822,029✔
2017
        WORD l1, l2, i;
16,822,029✔
2018
        WORD OutLen, *t, j;
16,822,029✔
2019
        UWORD *OutCoef;
16,822,029✔
2020
#ifdef WITHFLOAT
2021
        if ( AT.SortFloatMode ) return(AddWithFloat(BHEAD ps1,ps2));
16,822,029✔
2022
#endif
2023
        OutCoef = AN.SoScratC;
16,822,029✔
2024
        s1 = *ps1; s2 = *ps2;
16,822,029✔
2025
        GETCOEF(s1,l1);
16,822,029✔
2026
        GETCOEF(s2,l2);
16,822,029✔
2027
        if ( AddRat(BHEAD (UWORD *)s1,l1,(UWORD *)s2,l2,OutCoef,&OutLen) ) {
16,822,029✔
2028
                MLOCK(ErrorMessageLock);
×
2029
                MesCall("AddCoef");
×
2030
                MUNLOCK(ErrorMessageLock);
×
2031
                Terminate(-1);
×
2032
        }
2033
        if ( AN.ncmod != 0 ) {
16,822,029✔
2034
                if ( ( AC.modmode & POSNEG ) != 0 ) {
×
2035
                        NormalModulus(OutCoef,&OutLen);
×
2036
/*
2037
                        We had forgotten that this can also become smaller but the
2038
                        denominator isn't there. Correct in the other case
2039
                        17-may-2009 [JV]
2040
*/
2041
                        j = ABS(OutLen); OutCoef[j] = 1;
×
2042
                        for ( i = 1; i < j; i++ ) OutCoef[j+i] = 0;
×
2043
                }
2044
                else if ( BigLong(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod)) >= 0 ) {
×
2045
                        SubPLon(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod),OutCoef,&OutLen);
×
2046
                        OutCoef[OutLen] = 1;
×
2047
                        for ( i = 1; i < OutLen; i++ ) OutCoef[OutLen+i] = 0;
×
2048
                }
2049
        }
2050
        if ( !OutLen ) { *ps1 = *ps2 = 0; return(0); }
16,822,029✔
2051
        OutLen *= 2;
13,667,647✔
2052
        if ( OutLen < 0 ) i = - ( --OutLen );
13,667,647✔
2053
        else                          i = ++OutLen;
10,386,109✔
2054
        if ( l1 < 0 ) l1 = -l1;
13,667,647✔
2055
        l1 *= 2; l1++;
13,667,647✔
2056
        if ( i <= l1 ) {        /* Fits in 1 */
13,667,647✔
2057
                l1 -= i;
13,610,097✔
2058
                **ps1 -= l1;
13,610,097✔
2059
                s2 = (WORD *)OutCoef;
13,610,097✔
2060
                while ( --i > 0 ) *s1++ = *s2++;
41,316,125✔
2061
                *s1++ = OutLen;
13,610,097✔
2062
                while ( --l1 >= 0 ) *s1++ = 0;
13,610,491✔
2063
                goto RegEnd;
13,610,097✔
2064
        }
2065
        if ( l2 < 0 ) l2 = -l2;
57,550✔
2066
        l2 *= 2; l2++;
57,550✔
2067
        if ( i <= l2 ) {        /* Fits in 2 */
57,550✔
2068
                l2 -= i;
32,272✔
2069
                **ps2 -= l2;
32,272✔
2070
                s1 = (WORD *)OutCoef;
32,272✔
2071
                while ( --i > 0 ) *s2++ = *s1++;
270,610✔
2072
                *s2++ = OutLen;
32,272✔
2073
                while ( --l2 >= 0 ) *s2++ = 0;
32,464✔
2074
                *ps1 = *ps2;
32,272✔
2075
                goto RegEnd;
32,272✔
2076
        }
2077

2078
        /* Doesn't fit. Make a new term. */
2079

2080
        t = s1;
25,278✔
2081
        s1 = *ps1;
25,278✔
2082
        j = *s1++ + i - l1;                /* Space needed */
25,278✔
2083
        if ( (S->sFill + j) >= S->sTop2 ) {
25,278✔
2084
                GarbHand();
×
2085
                s1 = *ps1;
×
2086
                t = s1 + *s1 - 1;
×
2087
                j = *s1++ + i - l1;                /* Space needed */
×
2088
                l1 = *t;
×
2089
                if ( l1 < 0 ) l1  = - l1;
×
2090
                t -= l1-1;
×
2091
        }
2092
        s2 = S->sFill;
25,278✔
2093
        *s2++ = j;
25,278✔
2094
        while ( s1 < t ) *s2++ = *s1++;
189,240✔
2095
        s1 = (WORD *)OutCoef;
2096
        while ( --i > 0 ) *s2++ = *s1++;
253,892✔
2097
        *s2++ = OutLen;
25,278✔
2098
        *ps1 = S->sFill;
25,278✔
2099
        S->sFill = s2;
25,278✔
2100
RegEnd:
13,667,647✔
2101
        *ps2 = 0;
13,667,647✔
2102
        if ( **ps1 > AM.MaxTer/((LONG)(sizeof(WORD))) ) {
13,667,647✔
2103
                MLOCK(ErrorMessageLock);
×
2104
                MesPrint("Term too complex after addition in sort. MaxTermSize = %10l",
×
2105
                AM.MaxTer/sizeof(WORD));
×
2106
                MUNLOCK(ErrorMessageLock);
×
2107
                Terminate(-1);
×
2108
        }
2109
        return(1);
2110
}
2111

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

2141
WORD AddPoly(PHEAD WORD **ps1, WORD **ps2)
778,699✔
2142
{
2143
        GETBIDENTITY
2144
        SORTING *S = AT.SS;
778,699✔
2145
        WORD i;
778,699✔
2146
        WORD *s1, *s2, *m, *w, *t, oldpw = S->PolyWise;
778,699✔
2147
        s1 = *ps1 + S->PolyWise;
778,699✔
2148
        s2 = *ps2 + S->PolyWise;
778,699✔
2149
        w = AT.WorkPointer;
778,699✔
2150
/*
2151
        Add here the two arguments. Is a straight merge.
2152
*/
2153
        if ( S->PolyFlag == 2 && AR.PolyFunExp != 2 && AR.PolyFunExp != 3 ) {
778,699✔
2154
                WORD **oldSplitScratch = AN.SplitScratch;
778,681✔
2155
                LONG oldSplitScratchSize = AN.SplitScratchSize;
778,681✔
2156
                LONG oldInScratch = AN.InScratch;
778,681✔
2157
                WORD oldtype = AR.SortType;
778,681✔
2158
                if ( (WORD *)((UBYTE *)w + AM.MaxTer) >= AT.WorkTop ) {
778,681✔
2159
                        MLOCK(ErrorMessageLock);
×
2160
                        MesPrint("Program was adding polyratfun arguments");
×
2161
                        MesWork();
×
2162
                        MUNLOCK(ErrorMessageLock);
249,532✔
2163
                }
2164
                AR.SortType = SORTHIGHFIRST;
778,681✔
2165
                S->PolyWise = 0;
778,681✔
2166
                AN.SplitScratch = AN.SplitScratch1;
778,681✔
2167
                AN.SplitScratchSize = AN.SplitScratchSize1;
778,681✔
2168
                AN.InScratch = AN.InScratch1;
778,681✔
2169
                poly_ratfun_add(BHEAD s1,s2);
778,681✔
2170
                S->PolyWise = oldpw;
778,681✔
2171
                AN.SplitScratch1 = AN.SplitScratch;
778,681✔
2172
                AN.SplitScratchSize1 = AN.SplitScratchSize;
778,681✔
2173
                AN.InScratch1 = AN.InScratch;
778,681✔
2174
                AN.SplitScratch = oldSplitScratch;
778,681✔
2175
                AN.SplitScratchSize = oldSplitScratchSize;
778,681✔
2176
                AN.InScratch = oldInScratch;
778,681✔
2177
                AT.WorkPointer = w;
778,681✔
2178
                AR.SortType = oldtype;
778,681✔
2179
                if ( w[1] <= FUNHEAD ||
778,681✔
2180
                        ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) ) {
778,681✔
2181
                        *ps1 = *ps2 = 0; return(0);
3,602✔
2182
                }
2183
        }
2184
        else {
2185
                if ( w + s1[1] + s2[1] + 12 + ARGHEAD >= AT.WorkTop ) {
18✔
2186
                        MLOCK(ErrorMessageLock);
×
2187
                        MesPrint("Program was adding polyfun arguments");
×
2188
                        MesWork();
×
2189
                        MUNLOCK(ErrorMessageLock);
8✔
2190
                }
2191
                AddArgs(BHEAD s1,s2,w);
18✔
2192
        }
2193
/*
2194
        Now we need to store the result in a convenient place.
2195
*/
2196
        if ( w[1] <= FUNHEAD ) { *ps1 = *ps2 = 0; return(0); }
775,097✔
2197
        if ( w[1] <= s1[1] || w[1] <= s2[1] ) {   /* Fits in place. */
775,097✔
2198
                if ( w[1] > s1[1] ) {
13,003✔
2199
                        *ps1 = *ps2;
1,577✔
2200
                        s1 = s2;
1,577✔
2201
                }
2202
                t = s1 + s1[1];
13,003✔
2203
                m = *ps1 + **ps1;
13,003✔
2204
                i = w[1];
13,003✔
2205
                NCOPY(s1,w,i);
2,502,512✔
2206
                if ( s1 != t ) {
13,003✔
2207
                        while ( t < m ) *s1++ = *t++;
620✔
2208
                        **ps1 = WORDDIF(s1,(*ps1));
155✔
2209
                }
2210
                *ps2 = 0;
13,003✔
2211
        }
2212
        else {                /* Make new term */
2213
#ifdef TESTGARB
2214
                s2 = *ps2;
2215
#endif
2216
                *ps2 = 0;
762,094✔
2217
                if ( (S->sFill + (**ps1 + w[1] - s1[1])) >= S->sTop2 ) {
762,094✔
2218
#ifdef TESTGARB
2219
                        MesPrint("------Garbage collection-------");
2220
#endif
2221
                        AT.WorkPointer += w[1];
782✔
2222
                        GarbHand();
782✔
2223
                        AT.WorkPointer = w;
774✔
2224
                        s1 = *ps1;
774✔
2225
                        if ( (S->sFill + (**ps1 + w[1] - s1[1])) >= S->sTop2 ) {
774✔
2226
#ifdef TESTGARB
2227
                                UBYTE OutBuf[140];
2228
                                MLOCK(ErrorMessageLock);
2229
                                AO.OutFill = AO.OutputLine = OutBuf;
2230
                                AO.OutSkip = 3;
2231
                                FiniLine();
2232
                                i = *s2;
2233
                                while ( --i >= 0 ) {
2234
                                        TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)"  ");
2235
                                }
2236
                                FiniLine();
2237
                                AO.OutFill = AO.OutputLine = OutBuf;
2238
                                AO.OutSkip = 3;
2239
                                FiniLine();
2240
                                s2 = *ps1;
2241
                                i = *s2;
2242
                                while ( --i >= 0 ) {
2243
                                        TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)"  ");
2244
                                }
2245
                                FiniLine();
2246
                                AO.OutFill = AO.OutputLine = OutBuf;
2247
                                AO.OutSkip = 3;
2248
                                FiniLine();
2249
                                s2 = w;
2250
                                i = w[1];
2251
                                while ( --i >= 0 ) {
2252
                                        TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)"  ");
2253
                                }
2254
                                FiniLine();
2255
                                if ( AR.sLevel > 0 ) {
2256
                                        MesPrint("Please increase SubSmallExtension setup parameter.");
2257
                                }
2258
                                else {
2259
                                        MesPrint("Please increase SmallExtension setup parameter.");
2260
                                }
2261
                                MUNLOCK(ErrorMessageLock);
2262
#else
2263
                                MLOCK(ErrorMessageLock);
12✔
2264
                                if ( AR.sLevel > 0 ) {
12✔
2265
                                        MesPrint("Please increase SubSmallExtension setup parameter.");
6✔
2266
                                }
2267
                                else {
2268
                                        MesPrint("Please increase SmallExtension setup parameter.");
6✔
2269
                                }
2270
                                MUNLOCK(ErrorMessageLock);
12✔
2271
#endif
2272
                                Terminate(-1);
12✔
2273
                        }
2274
                }
2275
                t = *ps1;
762,074✔
2276
                s2 = S->sFill;
762,074✔
2277
                m = s2;
762,074✔
2278
                i = S->PolyWise;
762,074✔
2279
                NCOPY(s2,t,i);
5,154,816✔
2280
                i = w[1];
762,074✔
2281
                NCOPY(s2,w,i);
243,541,076✔
2282
                t = t + t[1];
762,074✔
2283
                w = *ps1 + **ps1;
762,074✔
2284
                while ( t < w ) *s2++ = *t++;
3,048,296✔
2285
                *m = WORDDIF(s2,m);
762,074✔
2286
                *ps1 = m;
762,074✔
2287
                S->sFill = s2;
762,074✔
2288
                if ( *m > AM.MaxTer/((LONG)sizeof(WORD)) ) {
762,074✔
2289
                        MLOCK(ErrorMessageLock);
×
2290
                        MesPrint("Term too complex after polynomial addition. MaxTermSize = %10l",
×
2291
                        AM.MaxTer/sizeof(WORD));
×
2292
                        MUNLOCK(ErrorMessageLock);
×
2293
                        Terminate(-1);
×
2294
                }
2295
        }
2296
        return(1);
2297
}
2298

2299
/*
2300
                 #] AddPoly : 
2301
                 #[ AddArgs :                                void AddArgs(arg1,arg2,to)
2302
*/
2303
 
2304
#define INSLENGTH(x)  w[1] = FUNHEAD+ARGHEAD+x; w[FUNHEAD] = ARGHEAD+x;
2305

2306
/**
2307
 *        Adds the arguments of two occurrences of the PolyFun.
2308
 *        @param s1 Pointer to the first occurrence.
2309
 *        @param s2 Pointer to the second occurrence.
2310
 *        @param m  Pointer to where the answer should be.
2311
 */
2312

2313
void AddArgs(PHEAD WORD *s1, WORD *s2, WORD *m)
24✔
2314
{
2315
        GETBIDENTITY
2316
        WORD i1, i2;
24✔
2317
        WORD *w = m, *mm, *t, *t1, *t2, *tstop1, *tstop2;
24✔
2318
        WORD tempterm[8+FUNHEAD];
24✔
2319

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

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

2606
WORD Compare1(PHEAD WORD *term1, WORD *term2, WORD level)
163,383,984✔
2607
{
2608
        SORTING *S = AT.SS;
163,383,984✔
2609
        WORD *stopper1, *stopper2, *t2;
163,383,984✔
2610
        WORD *s1, *s2, *t1;
163,383,984✔
2611
        WORD *stopex1, *stopex2;
163,383,984✔
2612
        WORD c1, c2;
163,383,984✔
2613
        WORD prevorder;
163,383,984✔
2614
        WORD count = -1, localPoly, polyhit = -1;
163,383,984✔
2615

2616
        if ( AR.sLevel == 0 ) {
163,383,984✔
2617
                numcompares++;
96,213,003✔
2618
        }
2619

2620
        if ( S->PolyFlag ) {
163,383,984✔
2621
/*
2622
                if ( S->PolyWise != 0 ) {
2623
                        MLOCK(ErrorMessageLock);
2624
                        MesPrint("S->PolyWise is not zero!!!!!");
2625
                        MUNLOCK(ErrorMessageLock);
2626
                }
2627
*/
2628
                count = 0; localPoly = 1; S->PolyWise = polyhit = 0;
914,462✔
2629
                S->PolyFlag = AR.PolyFunType;
914,462✔
2630
                if ( AR.PolyFunType == 2 &&
914,462✔
2631
                         ( AR.PolyFunExp == 2 || AR.PolyFunExp == 3 ) ) S->PolyFlag = 1;
914,410✔
2632
        }
2633
        else { localPoly = 0; }
2634
#ifdef WITHFLOAT
2635
        AT.SortFloatMode = 0;
163,383,984✔
2636
#endif
2637
        prevorder = 0;
163,383,984✔
2638
        GETSTOP(term1,s1);
163,383,984✔
2639
        stopper1 = s1;
163,383,984✔
2640
        GETSTOP(term2,stopper2);
163,383,984✔
2641
        t1 = term1 + 1;
163,383,984✔
2642
        t2 = term2 + 1;
163,383,984✔
2643
        while ( t1 < stopper1 && t2 < stopper2 ) {
203,390,873✔
2644
                if ( *t1 != *t2 ) {
177,592,300✔
2645
                        if ( *t1 == HAAKJE ) return(PREV(-1));
56,090✔
2646
                        if ( *t2 == HAAKJE ) return(PREV(1));
37,406✔
2647
                        if ( *t1 >= (FUNCTION-1) ) {
35,678✔
2648
                                if ( *t2 < (FUNCTION-1) ) return(PREV(-1));
31,472✔
2649
                                if ( *t1 < FUNCTION && *t2 < FUNCTION ) return(PREV(*t2-*t1));
28,599✔
2650
                                if ( *t1 < FUNCTION ) return(PREV(1));
28,599✔
2651
                                if ( *t2 < FUNCTION ) return(PREV(-1));
28,599✔
2652
                                c1 = functions[*t1-FUNCTION].commute;
28,599✔
2653
                                c2 = functions[*t2-FUNCTION].commute;
28,599✔
2654
                                if ( !c1 ) {
28,599✔
2655
                                        if ( c2 ) return(PREV(1));
28,533✔
2656
                                        else return(PREV(*t2-*t1));
28,533✔
2657
                                }
2658
                                else {
2659
                                        if ( !c2 ) return(PREV(-1));
66✔
2660
                                        else return(PREV(*t2-*t1));
66✔
2661
                                }
2662
                        }
2663
                        else return(PREV(*t2-*t1));
4,206✔
2664
                }
2665
                s1 = t1 + 2;
177,536,210✔
2666
                s2 = t2 + 2;
177,536,210✔
2667
                c1 = *t1;
177,536,210✔
2668
                t1 += t1[1];
177,536,210✔
2669
                t2 += t2[1];
177,536,210✔
2670
                if ( localPoly && c1 < FUNCTION ) {
177,536,210✔
2671
                        polyhit = 1;
2672
                }
2673
                if ( c1 <= (FUNCTION-1)
177,536,168✔
2674
                || ( c1 >= FUNCTION && functions[c1-FUNCTION].spec > 0 ) ) {
51,260,846✔
2675
                        if ( c1 == SYMBOL ) {
126,634,830✔
2676
                                if ( *s1 == FACTORSYMBOL && *s2 == FACTORSYMBOL
103,304,822✔
2677
                                 && s1[-1] == 4 && s2[-1] == 4
5,194✔
2678
                                 && ( ( t1 < stopper1 && *t1 == HAAKJE )
5,194✔
2679
                                 || ( t1 == stopper1 && AT.fromindex ) ) ) {
×
2680
/*
2681
                                        We have to be very careful with the criteria here, because
2682
                                        Compare1 is called both in the regular sorting and by the
2683
                                        routine that makes the bracket index. In the last case
2684
                                        there is no HAAKJE subterm.
2685
*/
2686
                                        if ( s1[1] != s2[1] ) return(s2[1]-s1[1]);
5,194✔
2687
                                        s1 += 2; s2 += 2;
3,105✔
2688
                                }
2689
                                else if ( AR.SortType >= SORTPOWERFIRST ) {
103,299,628✔
2690
                                        WORD i1 = 0, *r1;
2691
                                        r1 = s1;
2692
                                        while ( s1 < t1 ) { i1 += s1[1]; s1 += 2; }
×
2693
                                        s1 = r1; r1 = s2;
×
2694
                                        while ( s2 < t2 ) { i1 -= s2[1]; s2 += 2; }
×
2695
                                        s2 = r1;
×
2696
                                        if ( i1 ) {
×
2697
                                                if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
×
2698
                                                return(PREV(i1));
×
2699
                                        }
2700
                                }
2701
                                while ( s1 < t1 ) {
180,382,752✔
2702
                                        if ( s2 >= t2 ) {
168,961,266✔
2703
/*                                                return(PREV(1));  */
2704
                                                if ( AR.SortType==SORTLOWFIRST ) {
262,367✔
2705
                                                        return(PREV((s1[1]>0?-1:1)));
251,686✔
2706
                                                }
2707
                                                else {
2708
                                                        return(PREV((s1[1]<0?-1:1)));
31,488✔
2709
                                                }
2710
                                        }
2711
                                        if ( *s1 != *s2 ) {
168,698,899✔
2712
/*                                                return(PREV(*s2-*s1)); */
2713
                                                if ( AR.SortType==SORTLOWFIRST ) {
2,764,819✔
2714
                                                        if ( *s1 < *s2 ) {
2,734,033✔
2715
                                                                return(PREV((s1[1]<0?1:-1)));
3,678,328✔
2716
                                                        }
2717
                                                        else {
2718
                                                                return(PREV((s2[1]<0?-1:1)));
1,734,590✔
2719
                                                        }
2720
                                                }
2721
                                                else {
2722
                                                        if ( *s1 < *s2 ) {
30,786✔
2723
                                                                return(PREV((s1[1]<0?-1:1)));
28,272✔
2724
                                                        }
2725
                                                        else {
2726
                                                                return(PREV((s2[1]<0?1:-1)));
33,300✔
2727
                                                        }
2728
                                                }
2729
                                        }
2730
                                        s1++; s2++;
165,934,080✔
2731
                                        if ( *s1 != *s2 ) return(
165,934,080✔
2732
                                                PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
88,854,061✔
2733
                                        s1++; s2++;
77,080,019✔
2734
                                }
2735
                                if ( s2 < t2 ) {
11,421,486✔
2736
/*                                        return(PREV(-1));  */
2737
                                        if ( AR.SortType==SORTLOWFIRST ) {
305,685✔
2738
                                                return(PREV((s2[1]<0?-1:1)));
585,560✔
2739
                                        }
2740
                                        else {
2741
                                                return(PREV((s2[1]<0?1:-1)));
22,848✔
2742
                                        }
2743
                                }
2744
                        }
2745
                        else if ( c1 == DOTPRODUCT ) {
23,330,008✔
2746
                                if ( AR.SortType >= SORTPOWERFIRST ) {
1,860✔
2747
                                        WORD i1 = 0, *r1;
2748
                                        r1 = s1;
2749
                                        while ( s1 < t1 ) { i1 += s1[2]; s1 += 3; }
×
2750
                                        s1 = r1; r1 = s2;
×
2751
                                        while ( s2 < t2 ) { i1 -= s2[2]; s2 += 3; }
×
2752
                                        s2 = r1;
×
2753
                                        if ( i1 ) {
×
2754
                                                if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
×
2755
                                                return(PREV(i1));
×
2756
                                        }
2757
                                }
2758
                                while ( s1 < t1 ) {
3,588✔
2759
                                        if ( s2 >= t2 ) return(PREV(1));
1,860✔
2760
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
1,860✔
2761
                                        s1++; s2++;
1,860✔
2762
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
1,860✔
2763
                                        s1++; s2++;
1,848✔
2764
                                        if ( *s1 != *s2 ) return(
1,848✔
2765
                                                PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
120✔
2766
                                        s1++; s2++;
1,728✔
2767
                                }
2768
                                if ( s2 < t2 ) return(PREV(-1));
1,728✔
2769
                        }
2770
                        else {
2771
                                while ( s1 < t1 ) {
186,332,360✔
2772
                                        if ( s2 >= t2 ) return(PREV(1));
185,753,178✔
2773
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
185,753,178✔
2774
                                        s1++; s2++;
163,004,212✔
2775
                                }
2776
                                if ( s2 < t2 ) return(PREV(-1));
579,182✔
2777
                        }
2778
                }
2779
                else {
2780
#if FUNHEAD != 2
2781
                        s1 += FUNHEAD-2;
50,901,380✔
2782
                        s2 += FUNHEAD-2;
50,901,380✔
2783
#endif
2784
                        if ( localPoly && c1 == AR.PolyFun ) {
50,901,380✔
2785
                                if ( count == 0 ) {
782,535✔
2786
                                  if ( S->PolyFlag == 1 ) {
782,535✔
2787
                                        WORD i1, i2;
24✔
2788
                                        if ( *s1 > 0 ) i1 = *s1;
24✔
2789
                                        else if ( *s1 <= -FUNCTION ) i1 = 1;
×
2790
                                        else i1 = 2;
×
2791
                                        if ( *s2 > 0 ) i2 = *s2;
24✔
2792
                                        else if ( *s2 <= -FUNCTION ) i2 = 1;
×
2793
                                        else i2 = 2;
×
2794
                                        if ( s1+i1 == t1 && s2+i2 == t2 ) {        /* This is the stuff */
24✔
2795
/*
2796
                                                Test for scalar nature
2797
*/
2798
                                                if ( !polyhit ) {
24✔
2799
                                                        WORD *u1, *u2, *ustop;
18✔
2800
                                                        if ( *s1 < 0 ) {
18✔
2801
                                                                if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
×
2802
                                                                        goto NoPoly;
×
2803
                                                        }
2804
                                                        else {
2805
                                                                u1 = s1 + ARGHEAD;
18✔
2806
                                                                while ( u1 < t1 ) {
61✔
2807
                                                                        u2 = u1 + *u1;
43✔
2808
                                                                        ustop = u2 - ABS(u2[-1]);
43✔
2809
                                                                        u1++;
43✔
2810
                                                                        while ( u1 < ustop ) {
80✔
2811
                                                                                if ( *u1 == INDEX ) goto NoPoly;
37✔
2812
                                                                                u1 += u1[1];
37✔
2813
                                                                        }
2814
                                                                        u1 = u2;
2815
                                                                }
2816
                                                        }
2817
                                                        if ( *s2 < 0 ) {
18✔
2818
                                                                if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
×
2819
                                                                        goto NoPoly;
×
2820
                                                        }
2821
                                                        else {
2822
                                                                u1 = s2 + ARGHEAD;
18✔
2823
                                                                while ( u1 < t2 ) {
50✔
2824
                                                                        u2 = u1 + *u1;
32✔
2825
                                                                        ustop = u2 - ABS(u2[-1]);
32✔
2826
                                                                        u1++;
32✔
2827
                                                                        while ( u1 < ustop ) {
58✔
2828
                                                                                if ( *u1 == INDEX ) goto NoPoly;
26✔
2829
                                                                                u1 += u1[1];
26✔
2830
                                                                        }
2831
                                                                        u1 = u2;
2832
                                                                }
2833
                                                        }
2834
                                                }
2835
                                                S->PolyWise = WORDDIF(s1,term1);
24✔
2836
                                                S->PolyWise -= FUNHEAD;
24✔
2837
                                                count = 1;
24✔
2838
                                                continue;
24✔
2839
                                        }
2840
                                        else {
2841
NoPoly:
×
2842
                                                S->PolyWise = localPoly = 0;
×
2843
                                        }
2844
                                  }
2845
                                  else if ( AR.PolyFunType == 2 ) {
782,511✔
2846
                                        WORD i1, i2, i1a, i2a;
782,511✔
2847
                                        if ( *s1 > 0 ) i1 = *s1;
782,511✔
2848
                                        else if ( *s1 <= -FUNCTION ) i1 = 1;
20,770✔
2849
                                        else i1 = 2;
20,770✔
2850
                                        if ( *s2 > 0 ) i2 = *s2;
782,511✔
2851
                                        else if ( *s2 <= -FUNCTION ) i2 = 1;
29,102✔
2852
                                        else i2 = 2;
29,102✔
2853
                                        if ( s1[i1] > 0 ) i1a = s1[i1];
782,511✔
2854
                                        else if ( s1[i1] <= -FUNCTION ) i1a = 1;
29,154✔
2855
                                        else i1a = 2;
29,154✔
2856
                                        if ( s2[i2] > 0 ) i2a = s2[i2];
782,511✔
2857
                                        else if ( s2[i2] <= -FUNCTION ) i2a = 1;
20,958✔
2858
                                        else i2a = 2;
20,958✔
2859
                                        if ( s1+i1+i1a == t1 && s2+i2+i2a == t2 ) {        /* This is the stuff */
782,511✔
2860
/*
2861
                                                Test for scalar nature
2862
*/
2863
                                                if ( !polyhit ) {
782,511✔
2864
                                                        WORD *u1, *u2, *ustop;
782,493✔
2865
                                                        if ( *s1 < 0 ) {
782,493✔
2866
                                                                if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
20,764✔
2867
                                                                        goto NoPoly;
×
2868
                                                        }
2869
                                                        else {
2870
                                                                u1 = s1 + ARGHEAD;
761,729✔
2871
                                                                while ( u1 < s1+i1 ) {
4,636,834✔
2872
                                                                        u2 = u1 + *u1;
3,875,105✔
2873
                                                                        ustop = u2 - ABS(u2[-1]);
3,875,105✔
2874
                                                                        u1++;
3,875,105✔
2875
                                                                        while ( u1 < ustop ) {
7,015,027✔
2876
                                                                                if ( *u1 == INDEX ) goto NoPoly;
3,139,922✔
2877
                                                                                u1 += u1[1];
3,139,922✔
2878
                                                                        }
2879
                                                                        u1 = u2;
2880
                                                                }
2881
                                                        }
2882
                                                        if ( s1[i1] < 0 ) {
782,493✔
2883
                                                                if ( s1[i1] != -SNUMBER && s1[i1] != -SYMBOL && s1[i1] > -FUNCTION )
29,154✔
2884
                                                                        goto NoPoly;
×
2885
                                                        }
2886
                                                        else {
2887
                                                                u1 = s1 +i1 + ARGHEAD;
753,339✔
2888
                                                                while ( u1 < t1 ) {
4,483,925✔
2889
                                                                        u2 = u1 + *u1;
3,730,586✔
2890
                                                                        ustop = u2 - ABS(u2[-1]);
3,730,586✔
2891
                                                                        u1++;
3,730,586✔
2892
                                                                        while ( u1 < ustop ) {
6,726,637✔
2893
                                                                                if ( *u1 == INDEX ) goto NoPoly;
2,996,051✔
2894
                                                                                u1 += u1[1];
2,996,051✔
2895
                                                                        }
2896
                                                                        u1 = u2;
2897
                                                                }
2898
                                                        }
2899
                                                        if ( *s2 < 0 ) {
782,493✔
2900
                                                                if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
29,096✔
2901
                                                                        goto NoPoly;
×
2902
                                                        }
2903
                                                        else {
2904
                                                                u1 = s2 + ARGHEAD;
753,397✔
2905
                                                                while ( u1 < s2+i2 ) {
4,442,782✔
2906
                                                                        u2 = u1 + *u1;
3,689,385✔
2907
                                                                        ustop = u2 - ABS(u2[-1]);
3,689,385✔
2908
                                                                        u1++;
3,689,385✔
2909
                                                                        while ( u1 < ustop ) {
6,644,235✔
2910
                                                                                if ( *u1 == INDEX ) goto NoPoly;
2,954,850✔
2911
                                                                                u1 += u1[1];
2,954,850✔
2912
                                                                        }
2913
                                                                        u1 = u2;
2914
                                                                }
2915
                                                        }
2916
                                                        if ( s2[i2] < 0 ) {
782,493✔
2917
                                                                if ( s2[i2] != -SNUMBER && s2[i2] != -SYMBOL && s2[i2] > -FUNCTION )
20,958✔
2918
                                                                        goto NoPoly;
×
2919
                                                        }
2920
                                                        else {
2921
                                                                u1 = s2 + i2 + ARGHEAD;
761,535✔
2922
                                                                while ( u1 < t2 ) {
5,044,990✔
2923
                                                                        u2 = u1 + *u1;
4,283,455✔
2924
                                                                        ustop = u2 - ABS(u2[-1]);
4,283,455✔
2925
                                                                        u1++;
4,283,455✔
2926
                                                                        while ( u1 < ustop ) {
7,831,727✔
2927
                                                                                if ( *u1 == INDEX ) goto NoPoly;
3,548,272✔
2928
                                                                                u1 += u1[1];
3,548,272✔
2929
                                                                        }
2930
                                                                        u1 = u2;
2931
                                                                }
2932
                                                        }
2933
                                                }
2934
                                                S->PolyWise = WORDDIF(s1,term1);
782,511✔
2935
                                                S->PolyWise -= FUNHEAD;
782,511✔
2936
                                                count = 1;
782,511✔
2937
                                                continue;
782,511✔
2938
                                        }
2939
                                        else {
2940
                                                S->PolyWise = localPoly = 0;
×
2941
                                        }
2942
                                  }
2943
                                  else {
2944
                                        S->PolyWise = localPoly = 0;
×
2945
                                  }
2946
                                }
2947
                                else {
2948
                                        t1 = term1 + S->PolyWise;
×
2949
                                        t2 = term2 + S->PolyWise;
×
2950
                                        S->PolyWise = 0;
×
2951
                                        localPoly = 0;
×
2952
                                        continue;
×
2953
                                }
2954
                        }
2955
#ifdef WITHFLOAT
2956
                        if ( c1 == FLOATFUN && t1 == stopper1 && t2 == stopper2 && AT.aux_ != 0 ) {
50,118,845✔
2957
/*
2958
                                We have two FLOATFUN's. Test whether they are 'legal'
2959
*/
2960
                                if ( TestFloat(s1-FUNHEAD) ) {
×
2961
                                        if ( TestFloat(s2-FUNHEAD) ) { AT.SortFloatMode = 3; return(0); }
×
2962
                                        else { return(1); }
2963
                                }
2964
                                else if ( TestFloat(s2-FUNHEAD) ) { return(-1); }
×
2965
                        }
2966
#endif
2967
                        while ( s1 < t1 ) {
78,028,456✔
2968
/*
2969
                                The next statement was added 9-nov-2001. It repaired a bad error
2970
*/
2971
                                if ( s2 >= t2 ) return(PREV(-1));
50,500,807✔
2972
/*
2973
                                There is a little problem here with fast arguments
2974
                                We don't want to sacrifice speed, but we like to
2975
                                keep a rational ordering. This last one suffers in
2976
                                the solution that has been chosen here.
2977
*/
2978
                                if ( AC.properorderflag ) {
50,500,807✔
2979
                                        WORD oldpolyflag;
×
2980
                                        oldpolyflag = S->PolyFlag;
×
2981
                                        S->PolyFlag = 0;
×
2982
                                        if ( ( c2 = -CompArg(s1,s2) ) != 0 ) {
×
2983
                                                S->PolyFlag = oldpolyflag; return(PREV(c2));
×
2984
                                        }
2985
                                        S->PolyFlag = oldpolyflag;
×
2986
                                        NEXTARG(s1)
×
2987
                                        NEXTARG(s2)
×
2988
                                }
2989
                                else {
2990
                                        if ( *s1 > 0 ) {
50,500,807✔
2991
                                                if ( *s2 > 0 ) {
379,252✔
2992
                                                        WORD oldpolyflag;
376,581✔
2993
                                                        stopex1 = s1 + *s1;
376,581✔
2994
                                                        if ( s2 >= t2 ) return(PREV(-1));
376,581✔
2995
                                                        stopex2 = s2 + *s2;
376,581✔
2996
                                                        s1 += ARGHEAD; s2 += ARGHEAD;
376,581✔
2997
                                                        oldpolyflag = S->PolyFlag;
376,581✔
2998
                                                        S->PolyFlag = 0;
376,581✔
2999
                                                        while ( s1 < stopex1 ) {
3,009,141✔
3000
                                                                if ( s2 >= stopex2 ) {
2,818,911✔
3001
                                                                        S->PolyFlag = oldpolyflag; return(PREV(-1));
3,151✔
3002
                                                                }
3003
                                                                if ( ( c2 = CompareTerms(BHEAD s1,s2,(WORD)1) ) != 0 ) {
2,815,760✔
3004
                                                                        S->PolyFlag = oldpolyflag; return(PREV(c2));
183,200✔
3005
                                                                }
3006
                                                                s1 += *s1;
2,632,560✔
3007
                                                                s2 += *s2;
2,632,560✔
3008
                                                        }
3009
                                                        S->PolyFlag = oldpolyflag;
190,230✔
3010
                                                        if ( s2 < stopex2 ) return(PREV(1));
190,230✔
3011
                                                }
3012
                                                else return(PREV(1));
3013
                                        }
3014
                                        else {
3015
                                                if ( *s2 > 0 ) return(PREV(-1));
50,121,555✔
3016
                                                if ( *s1 != *s2 ) { return(PREV(*s1-*s2)); }
50,118,341✔
3017
                                                if ( *s1 > -FUNCTION ) {
50,097,636✔
3018
                                                        if ( *++s1 != *++s2 ) { return(PREV(*s2-*s1)); }
50,075,064✔
3019
                                                }
3020
                                                s1++; s2++;
27,737,835✔
3021
                                        }
3022
                                }
3023
                        }
3024
                        if ( s2 < t2 ) return(PREV(1));
27,527,649✔
3025
                }
3026
        }
3027
#ifdef WITHFLOAT
3028
        if ( t1 < stopper1 && *t1 == FLOATFUN && t1+t1[1] == stopper1
25,798,573✔
3029
                        && TestFloat(t1) ) {
×
3030
                AT.SortFloatMode = 1; return(0);
×
3031
        }
3032
        else if ( t2 < stopper2 && *t2 == FLOATFUN && t2+t2[1] == stopper2
25,798,573✔
3033
                        && TestFloat(t2) ) {
×
3034
                AT.SortFloatMode = 2; return(0);
×
3035
        }
3036
#endif
3037
        {
3038
                if ( AR.SortType != SORTLOWFIRST ) {
25,798,573✔
3039
                        if ( t1 < stopper1 ) return(PREV(1));
4,569,576✔
3040
                        if ( t2 < stopper2 ) return(PREV(-1));
785,676✔
3041
                }
3042
                else {
3043
                        if ( t1 < stopper1 ) return(PREV(-1));
21,228,997✔
3044
                        if ( t2 < stopper2 ) return(PREV(1));
20,416,063✔
3045
                }
3046
        }
3047
        if ( level == 3 ) return(CompCoef(term1,term2));
19,913,200✔
3048
        if ( level >= 1 )
19,913,200✔
3049
                return(CompCoef(term2,term1));
2,651,934✔
3050
        return(0);
3051
}
3052

3053
/*
3054
                 #] Compare1 : 
3055
                 #[ CompareSymbols :                        WORD CompareSymbols(term1,term2,par)
3056
*/
3057
/**
3058
 *        Compares the terms, based on the value of AN.polysortflag.
3059
 *        If term1 < term2 the return value is -1
3060
 *        If term1 > term2 the return value is  1
3061
 *        If term1 = term2 the return value is  0
3062
 *        The coefficients may differ.
3063
 *        The terms contain only a single subterm of type SYMBOL.
3064
 *        If AN.polysortflag = 0 it is a 'regular' compare.
3065
 *        If AN.polysortflag = 1 the sum of the powers is more important
3066
 *        par is a dummy parameter to make the parameter field identical
3067
 *        to that of Compare1 which is the regular compare routine in sort.c
3068
 */
3069

3070
WORD CompareSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
33,706,583✔
3071
{
3072
        int sum1, sum2;
33,706,583✔
3073
        WORD *t1, *t2, *tt1, *tt2;
33,706,583✔
3074
        int low, high;
33,706,583✔
3075
        DUMMYUSE(par);
33,706,583✔
3076
        if ( AR.SortType == SORTLOWFIRST ) { low = 1; high = -1; }
33,706,583✔
3077
        else { low = -1; high = 1; }
32,949,601✔
3078
        t1 = term1 + 1; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); t1 += 2;
33,706,583✔
3079
        t2 = term2 + 1; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); t2 += 2;
33,706,583✔
3080
        if ( AN.polysortflag > 0 ) {
33,706,583✔
3081
                sum1 = 0; sum2 = 0;
×
3082
                while ( t1 < tt1 ) { sum1 += t1[1]; t1 += 2; }
×
3083
                while ( t2 < tt2 ) { sum2 += t2[1]; t2 += 2; }
×
3084
                if ( sum1 < sum2 ) return(low);
×
3085
                if ( sum1 > sum2 ) return(high);
×
3086
                t1 = term1+3; t2 = term2 + 3;
3087
        }
3088
        while ( t1 < tt1 && t2 < tt2 ) {
48,581,935✔
3089
                if ( *t1 > *t2 ) return(low);
43,677,232✔
3090
                if ( *t1 < *t2 ) return(high);
42,864,123✔
3091
                if ( t1[1] < t2[1] ) return(low);
42,621,413✔
3092
                if ( t1[1] > t2[1] ) return(high);
25,452,868✔
3093
                t1 += 2; t2 += 2;
14,875,352✔
3094
        }
3095
        if ( t1 < tt1 ) return(high);
4,904,703✔
3096
        if ( t2 < tt2 ) return(low);
1,383,504✔
3097
        return(0);
3098
}
3099

3100
/*
3101
                 #] CompareSymbols : 
3102
                 #[ CompareHSymbols :                WORD CompareHSymbols(term1,term2,par)
3103
*/
3104
/**
3105
 *        Compares terms that can have only SYMBOL and HAAKJE subterms.
3106
 *        If term1 < term2 the return value is -1
3107
 *        If term1 > term2 the return value is  1
3108
 *        If term1 = term2 the return value is  0
3109
 *        par is a dummy parameter to make the parameter field identical
3110
 *        to that of Compare1 which is the regular compare routine in sort.c
3111
 */
3112

3113
WORD CompareHSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
×
3114
{
3115
        WORD *t1, *t2, *tt1, *tt2, *ttt1, *ttt2;
×
3116
        DUMMYUSE(par);
×
3117
        DUMMYUSE(AT.WorkPointer);
×
3118
        t1 = term1 + 1; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); t1 += 2;
×
3119
        t2 = term2 + 1; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); t2 += 2;
×
3120
        while ( t1 < tt1 && t2 < tt2 ) {
×
3121
                if ( *t1 != *t2 ) {
×
3122
                        if ( t1[0] < t2[0] ) return(-1);
×
3123
                        return(1);
×
3124
                }
3125
                else if ( *t1 == HAAKJE ) {
×
3126
                        t1 += 3; t2 += 3; continue;
×
3127
                }
3128
                ttt1 = t1+t1[1]; ttt2 = t2+t2[1];
×
3129
                while ( t1 < ttt1 && t2 < ttt2 ) {
×
3130
                        if ( *t1 > *t2 ) return(-1);
×
3131
                        if ( *t1 < *t2 ) return(1);
×
3132
                        if ( t1[1] < t2[1] ) return(-1);
×
3133
                        if ( t1[1] > t2[1] ) return(1);
×
3134
                        t1 += 2; t2 += 2;
×
3135
                }
3136
                if ( t1 < ttt1 ) return(1);
×
3137
                if ( t2 < ttt2 ) return(-1);
×
3138
        }
3139
        if ( t1 < tt1 ) return(1);
×
3140
        if ( t2 < tt2 ) return(-1);
×
3141
        return(0);
3142
}
3143

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

3166
LONG ComPress(WORD **ss, LONG *n)
7,291✔
3167
{
3168
        GETIDENTITY
4,807✔
3169
        WORD *t, *s, j, k;
7,291✔
3170
        LONG size = 0;
7,291✔
3171
        int newsize, i;
7,291✔
3172
/*
3173
                        #[ debug :
3174

3175
        WORD **sss = ss;
3176

3177
        if ( AP.DebugFlag ) {
3178
                UBYTE OutBuf[140];
3179
                MLOCK(ErrorMessageLock);
3180
                MesPrint("ComPress:");
3181
                AO.OutFill = AO.OutputLine = OutBuf;
3182
                AO.OutSkip = 3;
3183
                FiniLine();
3184
                ss = sss;
3185
                while ( *ss ) {
3186
                        s = *ss++;
3187
                        j = *s;
3188
                        if ( j < 0 ) {
3189
                                j = s[1] + 2;
3190
                        }
3191
                        while ( --j >= 0 ) {
3192
                                TalToLine((UWORD)(*s++)); TokenToLine((UBYTE *)"  ");
3193
                        }
3194
                        FiniLine();
3195
                }
3196
                AO.OutSkip = 0;
3197
                FiniLine();
3198
                MUNLOCK(ErrorMessageLock);
3199
                ss = sss;
3200
        }
3201

3202
                        #] debug : 
3203
*/
3204
        *n = 0;
7,291✔
3205
        if ( AT.SS == AT.S0 && !AR.NoCompress ) {
7,291✔
3206
                if ( AN.compressSize == 0 ) {
6,113✔
3207
                        if ( *ss ) { AN.compressSize = **ss + 64; }
34✔
3208
                        else       { AN.compressSize = AM.MaxTer/sizeof(WORD) + 2; }
×
3209
                        AN.compressSpace = (WORD *)Malloc1(AN.compressSize*sizeof(WORD),"Compression");
34✔
3210
                }
3211
                AN.compressSpace[0] = 0;
6,113✔
3212
                while ( *ss ) {
1,471,511✔
3213
                        k = 0;
1,465,398✔
3214
                        s = *ss;
1,465,398✔
3215
                        j = *s++;
1,465,398✔
3216
                        if ( j > AN.compressSize ) {
1,465,398✔
3217
                                newsize = j + 64;
×
3218
                                t = (WORD *)Malloc1(newsize*sizeof(WORD),"Compression");
×
3219
                                t[0] = 0;
×
3220
                                if ( AN.compressSpace ) {
×
3221
                                        for ( i = 0; i < *AN.compressSpace; i++ ) t[i] = AN.compressSpace[i];
×
3222
                                        M_free(AN.compressSpace,"Compression");
×
3223
                                }
3224
                                AN.compressSpace = t;
×
3225
                                AN.compressSize = newsize;
×
3226
                        }
3227
                        t = AN.compressSpace;
1,465,398✔
3228
                        i = *t - 1;
1,465,398✔
3229
                        *t++ = j; j--;
1,465,398✔
3230
                        if ( AR.PolyFun ) {
1,465,398✔
3231
                                WORD *polystop, *sa;
×
3232
                                sa = s + j;
×
3233
                                sa -= ABS(sa[-1]);
×
3234
                                polystop = s;
×
3235
                                while ( polystop < sa && *polystop != AR.PolyFun ) {
×
3236
                                        polystop += polystop[1];
×
3237
                                }
3238
                                while ( i > 0 && j > 0 && *s == *t && s < polystop ) {
×
3239
                                        i--; j--; s++; t++; k--;
×
3240
                                }
3241
                        }
3242
                        else {
3243
                                WORD *sa;
1,465,398✔
3244
                                sa = s + j;
1,465,398✔
3245
                                sa -= ABS(sa[-1]);
1,465,398✔
3246
                                while ( i > 0 && j > 0 && *s == *t && s < sa ) { i--; j--; s++; t++; k--; }
7,809,932✔
3247
                        }
3248
                        if ( k < -1 ) {
1,465,398✔
3249
                                s[-1] = j;
1,459,283✔
3250
                                s[-2] = k;
1,459,283✔
3251
                                *ss = s-2;
1,459,283✔
3252
                                size += j + 2;
1,459,283✔
3253
                        }
3254
                        else {
3255
                                size += *AN.compressSpace;
6,115✔
3256
                                if ( k == -1 ) { t--; s--; j++; }
6,115✔
3257
                        }
3258
                        while ( --j >= 0 ) *t++ = *s++;
7,356,808✔
3259
/*                                        Sabotage getting into the coefficient next time */
3260
                        t = AN.compressSpace + *AN.compressSpace;
1,465,398✔
3261
                        t[-(ABS(t[-1]))] = 0;
1,465,398✔
3262
                        ss++;
1,465,398✔
3263
                        (*n)++;
1,465,398✔
3264
                }
3265
        }
3266
        else {
3267
                while ( *ss ) {
12,876,317✔
3268
                        size += *(*ss++);
12,875,139✔
3269
                        (*n)++;
12,875,139✔
3270
                }
3271
        }
3272
/*
3273
                        #[ debug :
3274

3275
        if ( AP.DebugFlag ) {
3276
                UBYTE OutBuf[140];
3277
                AO.OutFill = AO.OutputLine = OutBuf;
3278
                AO.OutSkip = 3;
3279
                FiniLine();
3280
                ss = sss;
3281
                while ( *ss ) {
3282
                        s = *ss++;
3283
                        j = *s;
3284
                        if ( j < 0 ) {
3285
                                j = s[1] + 2;
3286
                        }
3287
                        while ( --j >= 0 ) {
3288
                                TalToLine((UWORD)(*s++)); TokenToLine((UBYTE *)"  ");
3289
                        }
3290
                        FiniLine();
3291
                }
3292
                AO.OutSkip = 0;
3293
                FiniLine();
3294
        }
3295

3296
                        #] debug : 
3297
*/
3298
        return(size);
7,291✔
3299
}
3300

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

3330
#ifdef NEWSPLITMERGE
3331

3332
LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
95,601,446✔
3333
{
3334
        GETBIDENTITY
3335
        SORTING *S = AT.SS;
95,601,446✔
3336
        WORD **pp3, **pp1, **pp2, **pptop;
95,601,446✔
3337
        LONG i, newleft, newright, split;
95,601,446✔
3338

3339
#ifdef SPLITMERGEDEBUG
3340
        /* Print current array state on entry. */
3341
        printf("%4ld: ", number);
3342
        for (int ii = 0; ii < S->sTerms; ii++) {
3343
                if ( (S->sPointer)[ii] ) {
3344
                        printf("%4d ", (unsigned)(S->sPointer[ii]-S->sBuffer));
3345
                }
3346
                else {
3347
                        printf(".... ");
3348
                }
3349
        }
3350
        printf("\n");
3351
        fflush(stdout);
3352
#endif
3353

3354
        if ( number < 2 ) return(number);
95,601,446✔
3355
        if ( number == 2 ) {
81,741,561✔
3356
                pp1 = Pointer; pp2 = pp1 + 1;
39,313,963✔
3357
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
39,313,963✔
3358
                        pp3 = (WORD **)(*pp1); *pp1 = *pp2; *pp2 = (WORD *)pp3;
5,962,186✔
3359
                }
3360
                else if ( i == 0 ) {
33,351,777✔
3361
                        number--;
1,251,340✔
3362
                        if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) == 0 ) number = 0; }
1,251,340✔
3363
                        else               { if ( AddCoef(BHEAD pp1,pp2) == 0 ) number = 0; }
924,480✔
3364
                }
3365
                return(number);
39,313,962✔
3366
        }
3367
        pptop = Pointer + number;
42,427,598✔
3368
        split = number/2;
42,427,598✔
3369
        newleft  = SplitMerge(BHEAD Pointer,split);
42,427,598✔
3370
        newright = SplitMerge(BHEAD Pointer+split,number-split);
42,427,541✔
3371
        if ( newright == 0 ) return(newleft);
42,427,460✔
3372
/*
3373
        We compare the last of the left with the first of the right
3374
        If they are already in order, we will be done quickly.
3375
        We may have to compactify the buffer because the recursion may
3376
        have created holes. Also this compare may result in equal terms.
3377
        Addition of 23-jul-1999. It makes things a bit faster.
3378
*/
3379
        if ( newleft > 0 && newright > 0 &&
42,426,537✔
3380
        ( i = CompareTerms(BHEAD Pointer[newleft-1],Pointer[split],(WORD)0) ) >= 0 ) {
42,422,036✔
3381
                pp2 = Pointer+split; pp1 = Pointer+newleft-1;
32,930,723✔
3382
                if ( i == 0 ) {
32,930,723✔
3383
                        if ( S->PolyWise ) {
1,170,737✔
3384
                                if ( AddPoly(BHEAD pp1,pp2) > 0 ) pp1++;
438,957✔
3385
                                else newleft--;
×
3386
                        }
3387
                        else {
3388
                                if ( AddCoef(BHEAD pp1,pp2) > 0 ) pp1++;
731,780✔
3389
                                else newleft--;
2,037✔
3390
                        }
3391
                        *pp2++ = 0; newright--;
1,170,718✔
3392
                }
3393
                else pp1++;
31,759,986✔
3394
                newleft += newright;
32,930,704✔
3395
                if ( pp1 < pp2 ) {
32,930,704✔
3396
                        while ( --newright >= 0 ) *pp1++ = *pp2++;
1,355,703✔
3397
                        while ( pp1 < pptop ) *pp1++ = 0;
23,527,725✔
3398
                }
3399
                return(newleft);
32,930,704✔
3400
        }
3401

3402
        if ( split >= AN.SplitScratchSize ) {
9,495,814✔
3403
                AN.SplitScratchSize = (split*3)/2+100;
1,964✔
3404
                if ( AN.SplitScratchSize > S->Terms2InSmall/2 )
1,964✔
3405
                        AN.SplitScratchSize = S->Terms2InSmall/2;
6✔
3406
                if ( AN.SplitScratch ) M_free(AN.SplitScratch,"AN.SplitScratch");
1,964✔
3407
                AN.SplitScratch = (WORD **)Malloc1(AN.SplitScratchSize*sizeof(WORD *),"AN.SplitScratch");
1,964✔
3408
        }
3409

3410
        pp3 = AN.SplitScratch; pp1 = Pointer;
9,495,814✔
3411
        /* Move rather than copy, so GarbHand can't double-count. */
3412
        for ( i = 0; i < newleft; i++ ) { *pp3++ = *pp1; *pp1++ = 0; }
82,016,176✔
3413
        AN.InScratch = newleft;
9,495,814✔
3414
        pp1 = AN.SplitScratch; pp2 = Pointer + split; pp3 = Pointer;
9,495,814✔
3415

3416
#ifdef NEWSPLITMERGETIMSORT
3417
/*
3418
                An improvement in the style of Timsort
3419
*/
3420
        while ( newleft > 8 ) {
9,587,482✔
3421
                /* Check the middle of the LHS terms */
3422
                LONG nnleft = newleft/2;
1,706,785✔
3423
                if ( ( i = CompareTerms(BHEAD pp1[nnleft],*pp2,(WORD)0) ) < 0 ) {
1,706,785✔
3424
                        /* The terms are not in order. Break out and continue as normal. */
3425
                        break;
3426
                }
3427
                /* The terms merge or are in order. Copy pointers up to this point. */
3428
                /* In the copy, zero the skipped pointers so GarbHand can't double-count. */
3429
                for (int iii = 0; iii < nnleft; iii++) {
1,442,062✔
3430
                        *pp3++ = *pp1;
1,334,725✔
3431
                        *pp1++ = 0;
1,334,725✔
3432
                }
3433
                newleft -= nnleft;
107,337✔
3434
                if ( i == 0 ) {
107,337✔
3435
                        if ( S->PolyWise ) { i = AddPoly(BHEAD pp1,pp2); }
15,669✔
3436
                        else               { i = AddCoef(BHEAD pp1,pp2); }
15,507✔
3437
                        if ( i == 0 ) {
15,669✔
3438
                                /* The terms cancelled. The next term goes in *pp3. Don't move. */
3439
                        }
3440
                        else {
3441
                                /* The terms added. Advance pp3. */
3442
                                *pp3++ = *pp1;
15,669✔
3443
                        }
3444
                        /* We have taken a LHS (copy) and RHS term. */
3445
                        *pp2++ = 0;
15,669✔
3446
                        newright--;
15,669✔
3447
                        *pp1++ = 0;
15,669✔
3448
                        newleft--;
15,669✔
3449
                        break;
15,669✔
3450
                }
3451
        }
3452
#endif
3453

3454
        while ( newleft > 0 && newright > 0 ) {
103,196,415✔
3455
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
93,700,601✔
3456
                        *pp3++ = *pp2;
54,754,401✔
3457
                        *pp2++ = 0;
54,754,401✔
3458
                        newright--;
54,754,401✔
3459
                }
3460
                else if ( i > 0 ) {
38,946,200✔
3461
                        *pp3++ = *pp1;
23,783,218✔
3462
                        *pp1++ = 0;
23,783,218✔
3463
                        newleft--;
23,783,218✔
3464
                }
3465
                else {
3466
                        if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
15,162,982✔
3467
                        else {               if ( AddCoef(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
15,150,262✔
3468
                        *pp1++ = 0; *pp2++ = 0; newleft--; newright--;
15,162,982✔
3469
                }
3470
        }
3471
        for ( i = 0; i < newleft; i++ ) { *pp3++ = *pp1; *pp1++ = 0; }
41,719,582✔
3472
        if ( pp3 == pp2 ) {
9,495,814✔
3473
                pp3 += newright;
8,102,724✔
3474
        } else {
3475
                for ( i = 0; i < newright; i++ ) { *pp3++ = *pp2++; }
5,410,969✔
3476
        }
3477
        newleft = pp3 - Pointer;
9,495,814✔
3478
        while ( pp3 < pptop ) *pp3++ = 0;
94,631,628✔
3479
        AN.InScratch = 0;
9,495,814✔
3480
        return(newleft);
9,495,814✔
3481
}
3482

3483
#else
3484

3485
LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
3486
{
3487
        GETBIDENTITY
3488
        SORTING *S = AT.SS;
3489
        WORD **pp3, **pp1, **pp2;
3490
        LONG nleft, nright, i, newleft, newright;
3491
        WORD **pptop;
3492

3493
#ifdef SPLITMERGEDEBUG
3494
        /* Print current array state on entry. */
3495
        printf("%4ld: ", number);
3496
        for (int ii = 0; ii < S->sTerms; ii++) {
3497
                if ( (S->sPointer)[ii] ) {
3498
                        printf("%4d ", (unsigned)(S->sPointer[ii]-S->sBuffer));
3499
                }
3500
                else {
3501
                        printf(".... ");
3502
                }
3503
        }
3504
        printf("\n");
3505
        fflush(stdout);
3506
#endif
3507

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

3591
#endif
3592

3593
/*
3594
                 #] SplitMerge : 
3595
                 #[ GarbHand :                                void GarbHand()
3596
*/
3597
/**
3598
 *                Garbage collection that takes place when the small extension is full
3599
 *                and we need to place more terms there.
3600
 *                When this is the case there are many holes in the small buffer and
3601
 *                the whole can be compactified.
3602
 *                The major complication is the buffer for SplitMerge.
3603
 *                There are to options for temporary memory:
3604
 *                1: find some buffer that has enough space (maybe in the large
3605
 *                   buffer).
3606
 *                2: allocate a buffer. Give it back afterwards of course.
3607
 *                If the small extension is properly dimensioned this routine should
3608
 *                be called very rarely. Most of the time it will be called when the
3609
 *                polyfun or polyratfun is active.
3610
 */
3611

3612
void GarbHand(void)
782✔
3613
{
3614
        GETIDENTITY
608✔
3615
        SORTING *S = AT.SS;
782✔
3616
        WORD **Point, *s2, *t, *garbuf, i;
782✔
3617
        LONG k, total = 0;
782✔
3618
        int tobereturned = 0;
782✔
3619
/*
3620
        Compute the size needed. Put it in total.
3621
*/
3622
#ifdef TESTGARB
3623
        MLOCK(ErrorMessageLock);
3624
        MesPrint("in:  S->sFill = %l, S->sTop2 = %l",S->sFill-S->sBuffer,S->sTop2-S->sBuffer);
3625
#endif
3626
        Point = S->sPointer;
782✔
3627
        k = S->sTerms;
782✔
3628
        while ( --k >= 0 ) {
15,954,889✔
3629
                if ( ( s2 = *Point++ ) != 0 ) { total += *s2; }
15,954,107✔
3630
        }
3631
        Point = AN.SplitScratch;
782✔
3632
        k = AN.InScratch;
782✔
3633
        while ( --k >= 0 ) {
782✔
3634
                if ( ( s2 = *Point++ ) != 0 ) { total += *s2; }
×
3635
        }
3636
#ifdef TESTGARB
3637
        MesPrint("total = %l, nterms = %l",total,AN.InScratch);
3638
        MUNLOCK(ErrorMessageLock);
3639
#endif
3640
/*
3641
        Test now whether it fits. If so deal with the problem inside
3642
        the memory at the tail of the large buffer.
3643
*/
3644
        if ( S->lBuffer != 0 && S->lFill + total <= S->lTop ) {
782✔
3645
                garbuf = S->lFill;
3646
        }
3647
        else {
3648
                garbuf = (WORD *)Malloc1(total*sizeof(WORD),"Garbage buffer");
×
3649
                tobereturned = 1;
×
3650
        }
3651
        t = garbuf;
782✔
3652
        Point = S->sPointer;
782✔
3653
        k = S->sTerms;
782✔
3654
        while ( --k >= 0 ) {
15,915,537✔
3655
                if ( *Point ) {
15,914,755✔
3656
                        s2 = *Point++;
5,580,326✔
3657
                        i = *s2;
5,580,326✔
3658
                        NCOPY(t,s2,i);
1,049,245,217✔
3659
                }
3660
                else { Point++; }
10,334,429✔
3661
        }
3662
        Point = AN.SplitScratch;
782✔
3663
        k = AN.InScratch;
782✔
3664
        while ( --k >= 0 ) {
782✔
3665
                if ( *Point ) {
×
3666
                        s2 = *Point++;
×
3667
                        i = *s2;
×
3668
                        NCOPY(t,s2,i);
×
3669
                }
3670
                else Point++;
×
3671
        }
3672
        s2 = S->sBuffer;
782✔
3673
        t = garbuf;
782✔
3674
        Point = S->sPointer;
782✔
3675
        k = S->sTerms;
782✔
3676
        while ( --k >= 0 ) {
15,846,548✔
3677
                if ( *Point ) {
15,845,766✔
3678
                        *Point++ = s2;
5,574,498✔
3679
                        i = *t;
5,574,498✔
3680
                        NCOPY(s2,t,i);
1,045,709,806✔
3681
                }
3682
                else { Point++; }
10,271,268✔
3683
        }
3684
        Point = AN.SplitScratch;
782✔
3685
        k = AN.InScratch;
782✔
3686
        while ( --k >= 0 ) {
782✔
3687
                if ( *Point ) {
×
3688
                        *Point++ = s2;
×
3689
                        i = *t;
×
3690
                        NCOPY(s2,t,i);
×
3691
                }
3692
                else Point++;
×
3693
        }
3694
        S->sFill = s2;
782✔
3695
#ifdef TESTGARB
3696
        MLOCK(ErrorMessageLock);
3697
        MesPrint("out: S->sFill = %l, S->sTop2 = %l",S->sFill-S->sBuffer,S->sTop2-S->sBuffer);
3698
        if ( S->sFill >= S->sTop2 ) {
3699
                MesPrint("We are in deep trouble");
3700
        }
3701
        MUNLOCK(ErrorMessageLock);
3702
#endif
3703
        if ( tobereturned ) M_free(garbuf,"Garbage buffer");
782✔
3704
        return;
782✔
3705
}
3706

3707
/*
3708
                 #] GarbHand : 
3709
                 #[ MergePatches :                        WORD MergePatches(par)
3710
*/
3711
/**
3712
 *        The general merge routine. Can be used for the large buffer
3713
 *        and the file merging. The array S->Patches tells where the patches
3714
 *        start S->pStop tells where they end (has to be computed first).
3715
 *        The end of a 'line to be merged' is indicated by a zero. If
3716
 *        the end is reached without running into a zero or a term
3717
 *        runs over the boundary of a patch it is a file merging operation
3718
 *        and a new piece from the file is read in.
3719
 *
3720
 *        @param par
3721
 *        If par == 0 the sort is for file -> outputfile.
3722
 *        If par == 1 the sort is for large buffer -> sortfile.
3723
 *        If par == 2 the sort is for large buffer -> outputfile.
3724
 *
3725
 */
3726

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

3912
        The old code had to be replaced because all output needs to go
3913
        through PutOut. For this we have to go term by term and keep
3914
        track of the compression.
3915
*/
3916
        if ( S->lPatch == 1 ) {        /* Single patch --> direct copy. Very rare. */
834✔
3917
                LONG length;
10✔
3918

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

4056
                /* More than one patch. Construct the tree. */
4057

4058
                lpat = 1;
4059
                do { lpat *= 2; } while ( lpat < S->lPatch );
2,331✔
4060
                mpat = ( lpat >> 1 ) - 1;
824✔
4061
                k = lpat - S->lPatch;
824✔
4062

4063
                /* k is the number of empty places in the tree. they will
4064
                   be at the even positions from 2 to 2*k */
4065

4066
                for ( i = 1; i < lpat; i++ ) {
8,230✔
4067
                        S->tree[i] = -1;
7,406✔
4068
                }
4069
                for ( i = 1; i <= k; i++ ) {
1,278✔
4070
                        im = ( i * 2 ) - 1;
454✔
4071
                        poin[im] = S->Patches[i-1];
454✔
4072
                        poin2[im] = poin[im] + *(poin[im]);
454✔
4073
                        S->used[i] = im;
454✔
4074
                        S->ktoi[im] = i-1;
454✔
4075
                        S->tree[mpat+i] = 0;
454✔
4076
                        poin[im-1] = poin2[im-1] = 0;
454✔
4077
                }
4078
                for ( i = (k*2)+1; i <= lpat; i++ ) {
8,146✔
4079
                        S->used[i-k] = i;
7,322✔
4080
                        S->ktoi[i] = i-k-1;
7,322✔
4081
                        poin[i] = S->Patches[i-k-1];
7,322✔
4082
                        poin2[i] = poin[i] + *(poin[i]);
7,322✔
4083
                }
4084
/*
4085
                the array poin tells the position of the i-th element of the S->tree
4086
                'S->used' is a stack with the S->tree elements that need to be entered
4087
                into the S->tree. at the beginning this is S->lPatch. during the
4088
                sort there will be only very few elements.
4089
                poin2 is the next value of poin. it has to be determined
4090
                before the comparisons as the position or the size of the
4091
                term indicated by poin may change.
4092
                S->ktoi translates a S->tree element back to its stream number.
4093

4094
                start the sort
4095
*/
4096
                level = S->lPatch;
824✔
4097

4098
                /* introduce one term */
4099
OneTerm:
16,718,801✔
4100
                k = S->used[level];
16,719,625✔
4101
                i = k + lpat - 1;
16,719,625✔
4102
                if ( !*(poin[k]) ) {
16,719,625✔
4103
                        do { if ( !( i >>= 1 ) ) goto EndOfMerge; } while ( !S->tree[i] );
15,182✔
4104
                        if ( S->tree[i] == -1 ) {
6,952✔
4105
                                S->tree[i] = 0;
51✔
4106
                                level--;
51✔
4107
                                goto OneTerm;
51✔
4108
                        }
4109
                        k = S->tree[i];
6,901✔
4110
                        S->used[level] = k;
6,901✔
4111
                        S->tree[i] = 0;
6,901✔
4112
                }
4113
/*
4114
                move terms down the tree
4115
*/
4116
                while ( i >>= 1 ) {
42,821,346✔
4117
                        if ( S->tree[i] > 0 ) {
26,432,995✔
4118
                                if ( ( c = CompareTerms(BHEAD poin[S->tree[i]],poin[k],(WORD)0) ) > 0 ) {
16,343,215✔
4119
/*
4120
                                        S->tree[i] is the smaller. Exchange and go on.
4121
*/
4122
                                        S->used[level] = S->tree[i];
52,340✔
4123
                                        S->tree[i] = k;
52,340✔
4124
                                        k = S->used[level];
52,340✔
4125
                                }
4126
                                else if ( !c ) {        /* Terms are equal */
16,290,875✔
4127
                                        S->TermsLeft--;
175,872✔
4128
/*
4129
                                                Here the terms are equal and their coefficients
4130
                                                have to be added.
4131
*/
4132
                                        l1 = *( m1 = poin[S->tree[i]] );
175,872✔
4133
                                        l2 = *( m2 = poin[k] );
175,872✔
4134
                                        if ( S->PolyWise ) {  /* Here we work with PolyFun */
175,872✔
4135
                                                WORD *tt1, *w;
×
4136
                                                tt1 = m1;
×
4137
                                                m1 += S->PolyWise;
×
4138
                                                m2 += S->PolyWise;
×
4139
                                                if ( S->PolyFlag == 2 ) {
×
4140
                                                        w = poly_ratfun_add(BHEAD m1,m2);
×
4141
                                                        if ( *tt1 + w[1] - m1[1] > AM.MaxTer/((LONG)sizeof(WORD)) ) {
×
4142
                                                                MLOCK(ErrorMessageLock);
×
4143
                                                                MesPrint("Term too complex in PolyRatFun addition. MaxTermSize of %10l is too small",AM.MaxTer);
×
4144
                                                                MUNLOCK(ErrorMessageLock);
×
4145
                                                                Terminate(-1);
×
4146
                                                        }
4147
                                                        AT.WorkPointer = w;
×
4148
                                                }
4149
                                                else {
4150
                                                        w = AT.WorkPointer;
×
4151
                                                        if ( w + m1[1] + m2[1] > AT.WorkTop ) {
×
4152
                                                                MLOCK(ErrorMessageLock);
×
4153
                                                                MesPrint("A WorkSpace of %10l is too small",AM.WorkSize);
×
4154
                                                                MUNLOCK(ErrorMessageLock);
×
4155
                                                                Terminate(-1);
×
4156
                                                        }
4157
                                                        AddArgs(BHEAD m1,m2,w);
×
4158
                                                }
4159
                                                r1 = w[1];
×
4160
                                                if ( r1 <= FUNHEAD
×
4161
                                                        || ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) )
×
4162
                                                                 { goto cancelled; }
×
4163
                                                if ( r1 == m1[1] ) {
×
4164
                                                        NCOPY(m1,w,r1);
×
4165
                                                }
4166
                                                else if ( r1 < m1[1] ) {
×
4167
                                                        r2 = m1[1] - r1;
×
4168
                                                        m2 = w + r1;
×
4169
                                                        m1 += m1[1];
×
4170
                                                        while ( --r1 >= 0 ) *--m1 = *--m2;
×
4171
                                                        m2 = m1 - r2;
×
4172
                                                        r1 = S->PolyWise;
×
4173
                                                        while ( --r1 >= 0 ) *--m1 = *--m2;
×
4174
                                                        *m1 -= r2;
×
4175
                                                        poin[S->tree[i]] = m1;
×
4176
                                                }
4177
                                                else {
4178
                                                        r2 = r1 - m1[1];
×
4179
                                                        m2 = tt1 - r2;
×
4180
                                                        r1 = S->PolyWise;
×
4181
                                                        m1 = tt1;
×
4182
                                                        *m1 += r2;
×
4183
                                                        poin[S->tree[i]] = m2;
×
4184
                                                        NCOPY(m2,m1,r1);
×
4185
                                                        r1 = w[1];
×
4186
                                                        NCOPY(m2,w,r1);
×
4187
                                                }
4188
                                        }
4189
#ifdef WITHFLOAT
4190
                                        else if ( AT.SortFloatMode ) {
175,872✔
4191
                                                WORD *term1, *term2;
×
4192
                                                term1 = poin[S->tree[i]];
×
4193
                                                term2 = poin[k];
×
4194
                                                if ( MergeWithFloat(BHEAD &term1,&term2) == 0 )
×
4195
                                                        goto cancelled;
×
4196
                                                poin[S->tree[i]] = term1;
×
4197
                                        }
4198
#endif
4199
                                        else {
4200
                                          r1 = *( m1 += l1 - 1 );
175,872✔
4201
                                          m1 -= ABS(r1) - 1;
175,872✔
4202
                                          r1 = ( ( r1 > 0 ) ? (r1-1) : (r1+1) ) >> 1;
175,872✔
4203
                                          r2 = *( m2 += l2 - 1 );
175,872✔
4204
                                          m2 -= ABS(r2) - 1;
175,872✔
4205
                                          r2 = ( ( r2 > 0 ) ? (r2-1) : (r2+1) ) >> 1;
175,872✔
4206

4207
                                          if ( AddRat(BHEAD (UWORD *)m1,r1,(UWORD *)m2,r2,coef,&r3) ) {
175,872✔
4208
                                                MLOCK(ErrorMessageLock);
×
4209
                                                MesCall("MergePatches");
×
4210
                                                MUNLOCK(ErrorMessageLock);
×
4211
                                                SETERROR(-1)
×
4212
                                          }
4213

4214
                                          if ( AN.ncmod != 0 ) {
175,872✔
4215
                                                if ( ( AC.modmode & POSNEG ) != 0 ) {
×
4216
                                                        NormalModulus(coef,&r3);
×
4217
                                                }
4218
                                                else if ( BigLong(coef,r3,(UWORD *)AC.cmod,ABS(AN.ncmod)) >= 0 ) {
×
4219
                                                        WORD ii;
×
4220
                                                        SubPLon(coef,r3,(UWORD *)AC.cmod,ABS(AN.ncmod),coef,&r3);
×
4221
                                                        coef[r3] = 1;
×
4222
                                                        for ( ii = 1; ii < r3; ii++ ) coef[r3+ii] = 0;
×
4223
                                                }
4224
                                          }
4225
                                          r3 *= 2;
175,872✔
4226
                                          r33 = ( r3 > 0 ) ? ( r3 + 1 ) : ( r3 - 1 );
175,872✔
4227
                                          if ( r3 < 0 ) r3 = -r3;
175,872✔
4228
                                          if ( r1 < 0 ) r1 = -r1;
175,872✔
4229
                                          r1 *= 2;
175,872✔
4230
                                          r31 = r3 - r1;
175,872✔
4231
                                          if ( !r3 ) {                /* Terms cancel */
175,872✔
4232
cancelled:
147,626✔
4233
                                                ul = S->used[level] = S->tree[i];
147,626✔
4234
                                                S->tree[i] = -1;
147,626✔
4235
/*
4236
                                                We skip to the next term in stream ul
4237
*/
4238
                                                im = *poin2[ul];
147,626✔
4239
                                                if ( im < 0 ) {
147,626✔
4240
                                                        r1 = poin2[ul][1] - im + 1;
147,434✔
4241
                                                        m1 = poin2[ul] + 2;
147,434✔
4242
                                                        m2 = poin[ul] - im + 1;
147,434✔
4243
                                                        while ( ++im <= 0 ) *--m1 = *--m2;
737,170✔
4244
                                                        *--m1 = r1;
147,434✔
4245
                                                        poin2[ul] = m1;
147,434✔
4246
                                                        im = r1;
147,434✔
4247
                                                }
4248
                                                poin[ul] = poin2[ul];
147,626✔
4249
                                                ki = S->ktoi[ul];
147,626✔
4250
                                                if ( !par && (poin[ul] + im + COMPINC) >= S->pStop[ki]
147,626✔
4251
                                                && im > 0 ) {
×
4252
#ifdef WITHZLIB
4253
                                                        PutIn(fin,&(S->iPatches[ki]),S->Patches[ki],&(poin[ul]),ki);
×
4254
#else
4255
                                                        ADDPOS(S->iPatches[ki],PutIn(fin,&(S->iPatches[ki]),
4256
                                                        S->Patches[ki],&(poin[ul]),ki));
4257
#endif
4258
                                                        poin2[ul] = poin[ul] + im;
×
4259
                                                }
4260
                                                else {
4261
                                                        poin2[ul] += im;
147,626✔
4262
                                                }
4263
                                                S->used[++level] = k;
147,626✔
4264
                                                S->TermsLeft--;
147,626✔
4265
                                          }
4266
                                          else if ( !r31 ) {                /* copy coef into term1 */
28,246✔
4267
                                                goto CopCof2;
28,230✔
4268
                                          }
4269
                                          else if ( r31 < 0 ) {                /* copy coef into term1
16✔
4270
                                                                                        and adjust the length of term1 */
4271
                                                goto CopCoef;
×
4272
                                          }
4273
                                          else {
4274
/*
4275
                                                        this is the dreaded calamity.
4276
                                                        is there enough space?
4277
*/
4278
                                                if( (poin[S->tree[i]]+l1+r31) >= poin2[S->tree[i]] ) {
16✔
4279
/*
4280
                                                                no space! now the special trick for which
4281
                                                                we left 2*maxlng spaces open at the beginning
4282
                                                                of each patch.
4283
*/
4284
                                                        if ( (l1 + r31) > AM.MaxTer/((LONG)sizeof(WORD)) ) {
16✔
4285
                                                                MLOCK(ErrorMessageLock);
×
4286
                                                                MesPrint("Coefficient overflow during sort");
×
4287
                                                                MUNLOCK(ErrorMessageLock);
×
4288
                                                                goto ReturnError;
×
4289
                                                        }
4290
                                                        m2 = poin[S->tree[i]];
16✔
4291
                                                        m3 = ( poin[S->tree[i]] -= r31 );
16✔
4292
                                                        do { *m3++ = *m2++; } while ( m2 < m1 );
16✔
4293
                                                        m1 = m3;
4294
                                                }
4295
CopCoef:
×
4296
                                                *(poin[S->tree[i]]) += r31;
16✔
4297
CopCof2:
28,246✔
4298
                                                m2 = (WORD *)coef; im = r3;
28,246✔
4299
                                                NCOPY(m1,m2,im);
84,790✔
4300
                                                *m1 = r33;
28,246✔
4301
                                          }
4302
                                        }
4303
/*
4304
                                        Now skip to the next term in stream k.
4305
*/
4306
NextTerm:
16,564,223✔
4307
                                        im = poin2[k][0];
16,564,223✔
4308
                                        if ( im < 0 ) {
16,564,223✔
4309
                                                r1 = poin2[k][1] - im + 1;
3,662,112✔
4310
                                                m1 = poin2[k] + 2;
3,662,112✔
4311
                                                m2 = poin[k] - im + 1;
3,662,112✔
4312
                                                while ( ++im <= 0 ) *--m1 = *--m2;
18,282,242✔
4313
                                                *--m1 = r1;
3,662,112✔
4314
                                                poin2[k] = m1;
3,662,112✔
4315
                                                im = r1;
3,662,112✔
4316
                                        }
4317
                                        poin[k] = poin2[k];
16,564,223✔
4318
                                        ki = S->ktoi[k];
16,564,223✔
4319
                                        if ( !par && ( (poin[k] + im + COMPINC) >= S->pStop[ki] )
16,564,223✔
4320
                                        && im > 0 ) {
46✔
4321
#ifdef WITHZLIB
4322
                                                PutIn(fin,&(S->iPatches[ki]),S->Patches[ki],&(poin[k]),ki);
46✔
4323
#else
4324
                                                ADDPOS(S->iPatches[ki],PutIn(fin,&(S->iPatches[ki]),
4325
                                                S->Patches[ki],&(poin[k]),ki));
4326
#endif
4327
                                                poin2[k] = poin[k] + im;
46✔
4328
                                        }
4329
                                        else {
4330
                                                poin2[k] += im;
16,564,177✔
4331
                                        }
4332
                                        goto OneTerm;
16,564,223✔
4333
                                }
4334
                        }
4335
                        else if ( S->tree[i] < 0 ) {
10,089,780✔
4336
                                S->tree[i] = k;
154,527✔
4337
                                level--;
154,527✔
4338
                                goto OneTerm;
154,527✔
4339
                        }
4340
                }
4341
/*
4342
                        found the smallest in the set. indicated by k.
4343
                        write to its destination.
4344
*/
4345
#ifdef WITHPTHREADS
4346
                if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
10,290,956✔
4347
                        im = PutToMaster(BHEAD poin[k]);
8,663,876✔
4348
                }
4349
                else
4350
#endif
4351
                if ( ( im = PutOut(BHEAD poin[k],&position,fout,1) ) < 0 ) {
7,724,475✔
4352
                        MLOCK(ErrorMessageLock);
×
4353
                        MesPrint("Called from MergePatches with k = %d (stream %d)",k,S->ktoi[k]);
×
4354
                        MUNLOCK(ErrorMessageLock);
×
4355
                        goto ReturnError;
×
4356
                }
4357
                ADDPOS(S->SizeInFile[par],im);
16,388,351✔
4358
                goto NextTerm;
16,388,351✔
4359
        }
4360
        else {
4361
                goto NormalReturn;
×
4362
        }
4363
EndOfMerge:
824✔
4364
#ifdef WITHPTHREADS
4365
                if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
549✔
4366
                        PutToMaster(BHEAD 0);
44✔
4367
                }
4368
                else
4369
#endif
4370
        if ( FlushOut(&position,fout,1) ) goto ReturnError;
780✔
4371
        ADDPOS(S->SizeInFile[par],1);
824✔
4372
EndOfAll:
834✔
4373
        if ( par == 1 ) {        /* Set the fpatch pointers */
834✔
4374
#ifdef WITHZLIB
4375
                SeekFile(fout->handle,&position,SEEK_CUR);
453✔
4376
#endif
4377
                (S->fPatchN)++;
453✔
4378
                S->fPatches[S->fPatchN] = position;
453✔
4379
        }
4380
        if ( par == 0 && fout != AR.outfile ) {
834✔
4381
/*
4382
                        Output went to sortfile. We have two possibilities:
4383
                        1:        We are not finished with the current in-out cycle
4384
                                In that case we should pop to the next set of patches
4385
                        2:        We finished a cycle and should clean up the in file
4386
                                Then we restart the sort.
4387
*/
4388
                (S->fPatchN)++;
120✔
4389
                S->fPatches[S->fPatchN] = position;
120✔
4390
                if ( ISNOTZEROPOS(AN.OldPosIn) ) {                /* We are not done */
120✔
4391

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

4497
/*
4498
                 #] MergePatches : 
4499
                 #[ StoreTerm :                                WORD StoreTerm(term)
4500
*/
4501
/**
4502
 *        The central routine to accept terms, store them and keep things
4503
 *        at least partially sorted. A call to EndSort will then complete
4504
 *        storing and sorting.
4505
 *
4506
 *        @param term The term to be stored
4507
 *        @return  Regular return conventions (OK -> 0)
4508
 */
4509

4510
WORD StoreTerm(PHEAD WORD *term)
92,529,865✔
4511
{
4512
        GETBIDENTITY
4513
        SORTING *S = AT.SS;
92,529,865✔
4514
        WORD **ss, *lfill, j, *t;
92,529,865✔
4515
        POSITION pp;
92,529,865✔
4516
        LONG lSpace, sSpace, RetCode, over, tover;
92,529,865✔
4517

4518
        if ( ( ( AP.PreDebug & DUMPTOSORT ) == DUMPTOSORT ) && AR.sLevel == 0 ) {
92,529,865✔
4519
#ifdef WITHPTHREADS
4520
                snprintf((char *)(THRbuf),100,"StoreTerm(%d)",AT.identity);
4521
                PrintTerm(term,(char *)(THRbuf));
4522
#else
4523
                PrintTerm(term,"StoreTerm");
4524
#endif
4525
        }
4526
        if ( AM.exitflag && AR.sLevel == 0 ) return(0);
92,529,865✔
4527
        S->sFill = *(S->PoinFill);
92,529,865✔
4528
        if ( S->sTerms >= S->TermsInSmall || ( S->sFill + *term ) >= S->sTop ) {
92,529,865✔
4529
/*
4530
        The small buffer is full. It has to be sorted and written.
4531
*/
4532
                tover = over = S->sTerms;
7,030✔
4533
                ss = S->sPointer;
7,030✔
4534
                ss[over] = 0;
7,030✔
4535
#ifdef SPLITTIME
4536
                PrintTime((UBYTE *)"Before SplitMerge");
4537
#endif
4538
                ss[SplitMerge(BHEAD ss,over)] = 0;
7,030✔
4539
#ifdef SPLITTIME
4540
                PrintTime((UBYTE *)"After SplitMerge");
4541
#endif
4542
                sSpace = 0;
7,030✔
4543
                if ( over > 0 ) {
7,030✔
4544
                        sSpace = ComPress(ss,&RetCode);
7,030✔
4545
                        S->TermsLeft -= over - RetCode;
7,030✔
4546
                }
4547
                sSpace++;
7,030✔
4548

4549
                lSpace = sSpace + (S->lFill - S->lBuffer)
7,030✔
4550
                                 - (AM.MaxTer/sizeof(WORD))*((LONG)S->lPatch);
7,030✔
4551
                SETBASEPOSITION(pp,lSpace);
7,030✔
4552
                MULPOS(pp,sizeof(WORD));
7,030✔
4553
                if ( S->file.handle >= 0 ) {
7,030✔
4554
                        ADD2POS(pp,S->fPatches[S->fPatchN]);
5,733✔
4555
                }
4556
                if ( S == AT.S0 ) {        /* Only statistics at ground level */
7,030✔
4557
                        WriteStats(&pp,STATSSPLITMERGE,CHECKLOGTYPE);
6,067✔
4558
                }
4559
                if ( ( S->lPatch >= S->MaxPatches ) ||
7,030✔
4560
                        ( ( (WORD *)(((UBYTE *)(S->lFill + sSpace)) + 2*AM.MaxTer ) ) >= S->lTop ) ) {
6,621✔
4561
/*
4562
                        The large buffer is too full. Merge and write it
4563
*/
4564
                        if ( MergePatches(1) ) goto StoreCall;
411✔
4565
/*
4566
                        pp = S->SizeInFile[1];
4567
                        ADDPOS(pp,sSpace);
4568
                        MULPOS(pp,sizeof(WORD));
4569
*/
4570
                        SETBASEPOSITION(pp,sSpace);
405✔
4571
                        MULPOS(pp,sizeof(WORD));
405✔
4572
                        ADD2POS(pp,S->fPatches[S->fPatchN]);
405✔
4573

4574
                        if ( S == AT.S0 ) {        /* Only statistics at ground level */
405✔
4575
                                WriteStats(&pp,STATSMERGETOFILE,CHECKLOGTYPE);
345✔
4576
                        }
4577
                        S->lPatch = 0;
405✔
4578
                        S->lFill = S->lBuffer;
405✔
4579
                }
4580
                S->Patches[S->lPatch++] = S->lFill;
7,024✔
4581
            lfill = (WORD *)(((UBYTE *)(S->lFill)) + AM.MaxTer);
7,024✔
4582
                if ( tover > 0 ) {
7,024✔
4583
                        ss = S->sPointer;
7,024✔
4584
                        while ( ( t = *ss++ ) != 0 ) {
12,322,160✔
4585
                                j = *t;
12,315,136✔
4586
                                if ( j < 0 ) j = t[1] + 2;
12,315,136✔
4587
                                while ( --j >= 0 ){
255,479,047✔
4588
                                  *lfill++ = *t++;
243,163,911✔
4589
                                }
4590
                        }
4591
                }
4592
                *lfill++ = 0;
7,024✔
4593
                S->lFill = lfill;
7,024✔
4594
                S->sTerms = 0;
7,024✔
4595
                S->PoinFill = S->sPointer;
7,024✔
4596
                *(S->PoinFill) = S->sFill = S->sBuffer;
7,024✔
4597
        }
4598
        j = *term;
92,529,859✔
4599
        while ( --j >= 0 ) *S->sFill++ = *term++;
1,290,592,735✔
4600
        S->sTerms++;
92,529,859✔
4601
        S->GenTerms++;
92,529,859✔
4602
        S->TermsLeft++;
92,529,859✔
4603
        *++S->PoinFill = S->sFill;
92,529,859✔
4604

4605
        return(0);
92,529,859✔
4606

4607
StoreCall:
×
4608
        MLOCK(ErrorMessageLock);
×
4609
        MesCall("StoreTerm");
×
4610
        MUNLOCK(ErrorMessageLock);
×
4611
        SETERROR(-1)
×
4612
}
4613

4614
/*
4615
                 #] StoreTerm : 
4616
                 #[ StageSort :                                void StageSort(FILEHANDLE *fout)
4617
*/
4618
/**
4619
 *                Prepares a stage 4 or higher sort.
4620
 *                Stage 4 sorts occur when the sort file contains more patches than
4621
 *                can be merged in one pass.
4622
 */
4623

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

4682
                if ( AR.FoStage4[0].PObuffer == 0 ) {
88✔
4683
                        AR.FoStage4[0].PObuffer = (WORD *)Malloc1(AR.FoStage4[0].POsize*sizeof(WORD)
14✔
4684
                                                                                                ,"Stage 4 buffer");
4685
                        AR.FoStage4[0].POfill   = AR.FoStage4[0].PObuffer;
14✔
4686
                        AR.FoStage4[0].POstop   = AR.FoStage4[0].PObuffer
14✔
4687
                                                 + AR.FoStage4[0].POsize/sizeof(WORD);
14✔
4688
#ifdef WITHPTHREADS
4689
                        AR.FoStage4[0].pthreadslock = dummylock;
12✔
4690
#endif
4691
                }
4692
                if ( AR.FoStage4[1].PObuffer == 0 ) {
88✔
4693
                        AR.FoStage4[1].PObuffer = (WORD *)Malloc1(AR.FoStage4[1].POsize*sizeof(WORD)
14✔
4694
                                                                                                ,"Stage 4 buffer");
4695
                        AR.FoStage4[1].POfill   = AR.FoStage4[1].PObuffer;
14✔
4696
                        AR.FoStage4[1].POstop   = AR.FoStage4[1].PObuffer
14✔
4697
                                                 + AR.FoStage4[1].POsize/sizeof(WORD);
14✔
4698
#ifdef WITHPTHREADS
4699
                        AR.FoStage4[1].pthreadslock = dummylock;
12✔
4700
#endif
4701
                }
4702
                S->stage4 = 1;
88✔
4703
        }
4704
}
588✔
4705

4706
/*
4707
                 #] StageSort : 
4708
                 #[ SortWild :                                WORD SortWild(w,nw)
4709
*/
4710
/**
4711
 *        Sorts the wildcard entries in the parameter w. Double entries
4712
 *        are removed. Full space taken is nw words.
4713
 *        Routine serves for the reading of wildcards in the compiler.
4714
 *        The entries come in the format:
4715
 *        (type,4,number,0) in which the zero is reserved for the
4716
 *        future replacement of 'number'.
4717
 *
4718
 *        @param w  buffer with wildcard entries.
4719
 *        @param nw number of wildcard entries.
4720
 *        @return  Normal conventions (OK -> 0)
4721
 */
4722

4723
WORD SortWild(WORD *w, WORD nw)
5,012✔
4724
{
4725
        GETIDENTITY
3,340✔
4726
        WORD *v, *s, *m, k, i;
5,012✔
4727
        WORD *pScrat, *stop, *sv, error = 0;
5,012✔
4728
        pScrat = AT.WorkPointer;
5,012✔
4729
        if ( ( AT.WorkPointer + 8 * AM.MaxWildcards ) >= AT.WorkTop ) {
5,012✔
4730
                MLOCK(ErrorMessageLock);
×
4731
                MesWork();
×
4732
                MUNLOCK(ErrorMessageLock);
×
4733
                return(-1);
×
4734
        }
4735
        stop = w + nw;
5,012✔
4736
        i = 0;
5,012✔
4737
        while ( i < nw ) {
19,612✔
4738
                m = w + i;
14,600✔
4739
                v = m + m[1];
14,600✔
4740
                while ( v < stop && (
25,270✔
4741
                         *v == FROMSET || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
20,366✔
4742
                while ( v < stop ) {
34,934✔
4743
                        if ( *v >= 0 ) {
20,334✔
4744
                                if ( AM.Ordering[*v] < AM.Ordering[*m] ) {
19,440✔
4745
                                        m = v;
4746
                                }
4747
                                else if ( *v == *m ) {
18,978✔
4748
                                        if ( v[2] < m[2] ) {
17,970✔
4749
                                                m = v;
4750
                                        }
4751
                                        else if ( v[2] == m[2] ) {
17,952✔
4752
                                                s = m + m[1];
96✔
4753
                                                sv = v + v[1];
96✔
4754
                                                if ( s < stop && ( *s == FROMSET
96✔
4755
                                                 || *s == SETTONUM || *s == LOADDOLLAR ) ) {
96✔
4756
                                                        if ( sv < stop && ( *sv == FROMSET
×
4757
                                                        || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
×
4758
                                                                if ( s[2] != sv[2] ) {
×
4759
                                                                        error = -1;
×
4760
                                                                        MLOCK(ErrorMessageLock);
×
4761
                                                                        MesPrint("&Wildcard set conflict");
×
4762
                                                                        MUNLOCK(ErrorMessageLock);
×
4763
                                                                }
4764
                                                        }
4765
                                                        *v = -1;
×
4766
                                                }
4767
                                                else {
4768
                                                        if ( sv < stop && ( *sv == FROMSET
96✔
4769
                                                        || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
48✔
4770
                                                                *m = -1;
×
4771
                                                                m = v;
×
4772
                                                        }
4773
                                                        else {
4774
                                                                *v = -1;
96✔
4775
                                                        }
4776
                                                }
4777
                                        }
4778
                                }
4779
                        }
4780
                        v += v[1];
20,334✔
4781
                        while ( v < stop && ( *v == FROMSET
36,516✔
4782
                         || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
26,820✔
4783
                }
4784
                s = pScrat;
14,600✔
4785
                v = m;
14,600✔
4786
                k = m[1];
14,600✔
4787
                NCOPY(s,m,k);
73,000✔
4788
                while ( m < stop && ( *m == FROMSET
45,672✔
4789
                 || *m == SETTONUM || *m == LOADDOLLAR ) ) {
20,354✔
4790
                        k = m[1];
10,718✔
4791
                        NCOPY(s,m,k);
68,190✔
4792
                }
4793
                *v = -1;
14,600✔
4794
                pScrat = s;
14,600✔
4795
                i = 0;
14,600✔
4796
                while ( i < nw && ( w[i] < 0 || w[i] == FROMSET
74,958✔
4797
                || w[i] == SETTONUM || w[i] == LOADDOLLAR ) ) i += w[i+1];
69,946✔
4798
        }
4799
        AC.NwildC = k = WORDDIF(pScrat,AT.WorkPointer);
5,012✔
4800
        s = AT.WorkPointer;
5,012✔
4801
        m = w;
5,012✔
4802
        NCOPY(m,s,k);
106,284✔
4803
        AC.WildC = m;
5,012✔
4804
        return(error);
5,012✔
4805
}
4806

4807
/*
4808
                 #] SortWild : 
4809
                 #[ CleanUpSort :                        void CleanUpSort(num)
4810
*/
4811
/**
4812
 *                Partially or completely frees function sort buffers.
4813
 */
4814

4815
void CleanUpSort(int num)
5,628✔
4816
{
4817
        GETIDENTITY
3,744✔
4818
        SORTING *S;
5,628✔
4819
        int minnum = num, i;
5,628✔
4820
        if ( AN.FunSorts ) {
5,628✔
4821
                if ( num == -1 ) {
5,400✔
4822
                        if ( AN.MaxFunSorts > 3 ) {
3,586✔
4823
                                minnum = (AN.MaxFunSorts+4)/2;
1,900✔
4824
                        }
4825
                        else minnum = 4;
4826
                }
4827
                else if ( minnum == 0 ) minnum = 1;
1,814✔
4828
                for ( i = minnum; i < AN.NumFunSorts; i++ ) {
529,242✔
4829
                        S = AN.FunSorts[i];
523,842✔
4830
                        if ( S ) {
523,842✔
4831
                                if ( S->file.handle >= 0 ) {
1,462✔
4832
/*                                        TruncateFile(S->file.handle); */
4833
                                        UpdateMaxSize();
6✔
4834
#ifdef WITHZLIB
4835
                                        ClearSortGZIP(&(S->file));
6✔
4836
#endif
4837
                                        CloseFile(S->file.handle);
6✔
4838
                                        S->file.handle = -1;
6✔
4839
                                        remove(S->file.name);
6✔
4840
#ifdef GZIPDEBUG
4841
                                        MLOCK(ErrorMessageLock);
4842
                                        MesPrint("%w CleanUpSort removed file %s",S->file.name);
4843
                                        MUNLOCK(ErrorMessageLock);
4844
#endif
4845
                                }
4846
                                M_free(S->sPointer, "CleanUpSort: sPointer");
1,462✔
4847
                                M_free(S->Patches, "CleanUpSort: Patches");
1,462✔
4848
                                M_free(S->pStop, "CleanUpSort: pStop");
1,462✔
4849
                                M_free(S->poina, "CleanUpSort: poina");
1,462✔
4850
                                M_free(S->poin2a, "CleanUpSort: poin2a");
1,462✔
4851
                                M_free(S->fPatches, "CleanUpSort: fPatches");
1,462✔
4852
                                M_free(S->fPatchesStop, "CleanUpSort: fPatchesStop");
1,462✔
4853
                                M_free(S->inPatches, "CleanUpSort: inPatches");
1,462✔
4854
                                M_free(S->tree, "CleanUpSort: tree");
1,462✔
4855
                                M_free(S->used, "CleanUpSort: used");
1,462✔
4856
#ifdef WITHZLIB
4857
                                M_free(S->fpcompressed, "CleanUpSort: fpcompressed");
1,462✔
4858
                                M_free(S->fpincompressed, "CleanUpSort: fpincompressed");
1,462✔
4859
#endif
4860
                                M_free(S->ktoi, "CleanUpSort: ktoi");
1,462✔
4861
                                M_free(S->lBuffer, "CleanUpSort: lBuffer+sBuffer");
1,462✔
4862
                                M_free(S->file.PObuffer, "CleanUpSort: PObuffer");
1,462✔
4863
                                M_free(S, "CleanUpSort: sorting struct");
1,462✔
4864
                        }
4865
                        AN.FunSorts[i] = 0;
523,842✔
4866
                }
4867
                AN.MaxFunSorts = minnum;
5,400✔
4868
                if ( num == 0 ) {
5,400✔
4869
                        S = AN.FunSorts[0];
1,814✔
4870
                        if ( S ) {
1,814✔
4871
                                if ( S->file.handle >= 0 ) {
1,814✔
4872
/*                                        TruncateFile(S->file.handle); */
4873
                                        UpdateMaxSize();
×
4874
#ifdef WITHZLIB
4875
                                        ClearSortGZIP(&(S->file));
×
4876
#endif
4877
                                        CloseFile(S->file.handle);
×
4878
                                        S->file.handle = -1;
×
4879
                                        remove(S->file.name);
×
4880
#ifdef GZIPDEBUG
4881
                                        MLOCK(ErrorMessageLock);
4882
                                        MesPrint("%w CleanUpSort removed file %s",S->file.name);
4883
                                        MUNLOCK(ErrorMessageLock);
4884
#endif
4885
                                }
4886
                        }
4887
                }
4888
        }
4889
        for ( i = 0; i < 2; i++ ) {
16,884✔
4890
                if ( AR.FoStage4[i].handle >= 0 ) {
11,256✔
4891
                        UpdateMaxSize();
×
4892
#ifdef WITHZLIB
4893
                        ClearSortGZIP(&(AR.FoStage4[i]));
×
4894
#endif
4895
                        CloseFile(AR.FoStage4[i].handle);
×
4896
                        remove(AR.FoStage4[i].name);
×
4897
                        AR.FoStage4[i].handle = -1;
×
4898
#ifdef GZIPDEBUG
4899
                        MLOCK(ErrorMessageLock);
4900
                        MesPrint("%w CleanUpSort removed stage4 file %s",AR.FoStage4[i].name);
4901
                        MUNLOCK(ErrorMessageLock);
4902
#endif
4903
                }
4904
        }
4905
}
5,628✔
4906

4907
/*
4908
                 #] CleanUpSort : 
4909
                 #[ LowerSortLevel :         void LowerSortLevel()
4910
*/
4911
/**
4912
 *                Lowers the level in the sort system.
4913
 */
4914

4915
void LowerSortLevel(void)
24,500✔
4916
{
4917
        GETIDENTITY
16,332✔
4918
        if ( AR.sLevel >= 0 ) {
24,500✔
4919
                AR.sLevel--;
24,500✔
4920
                if ( AR.sLevel >= 0 ) AT.SS = AN.FunSorts[AR.sLevel];
24,500✔
4921
        }
4922
}
24,500✔
4923

4924
/*
4925
                 #] LowerSortLevel : 
4926
                 #[ PolyRatFunSpecial :
4927

4928
                Keeps only the most divergent term in AR.PolyFunVar
4929
                We assume that the terms are already in that notation.
4930
*/
4931

4932
WORD *PolyRatFunSpecial(PHEAD WORD *t1, WORD *t2)
×
4933
{
4934
        WORD *oldworkpointer = AT.WorkPointer, *t, *r;
×
4935
        WORD exp1, exp2;
×
4936
        int i;
×
4937
        t = t1+FUNHEAD;
×
4938
        if ( *t == -SYMBOL ) {
×
4939
                if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
4940
                exp1 = 1;
×
4941
                if ( t[2] != -SNUMBER ) goto Illegal;
×
4942
                t[3] = 1;
×
4943
        }
4944
        else if ( *t == -SNUMBER ) {
×
4945
                t[1] = 1;
×
4946
                t += 2;
×
4947
                if ( *t == -SYMBOL ) {
×
4948
                        if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
4949
                        exp1 = -1;
4950
                }
4951
                else if ( *t == -SNUMBER ) {
×
4952
                        t[1] = 1;
×
4953
                        exp1 = 0;
×
4954
                }
4955
                else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
4956
                        && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
4957
                        t[ARGHEAD+5] = 1;
×
4958
                        t[ARGHEAD+6] = 1;
×
4959
                        t[ARGHEAD+7] = 3;
×
4960
                        exp1 = -t[ARGHEAD+4];
×
4961
                }
4962
                else goto Illegal;
×
4963
        }
4964
        else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
4965
                && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
4966
                t[ARGHEAD+5] = 1;
×
4967
                t[ARGHEAD+6] = 1;
×
4968
                t[ARGHEAD+7] = 3;
×
4969
                exp1 = t[ARGHEAD+4];
×
4970
                t += *t;
×
4971
                if ( *t != -SNUMBER ) goto Illegal;
×
4972
                t[1] = 1;
×
4973
        }
4974
        else goto Illegal;
×
4975

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

5015
        if ( exp1 <= exp2 ) { i = t1[1]; r = t1; }
×
5016
        else                { i = t2[1]; r = t2; }
×
5017
        t = oldworkpointer;
5018
        NCOPY(t,r,i)
×
5019

5020
        return(oldworkpointer);
5021
Illegal:
×
5022
        MesPrint("Illegal occurrence of PolyRatFun with divergent option");
×
5023
        Terminate(-1);
×
5024
        return(0);
×
5025
}
5026

5027
/*
5028
                 #] PolyRatFunSpecial : 
5029
                 #[ SimpleSplitMerge :
5030

5031
                Sorts an array of WORDs. No adding of equal objects.
5032
*/
5033

NEW
5034
void SimpleSplitMergeRec(WORD *array,WORD num,WORD *auxarray)
×
5035
{
5036
        WORD n1,n2,i,j,k,*t1,*t2;
×
5037
        if ( num < 2 ) return;
×
5038
        if ( num == 2 ) {
×
5039
                if ( array[0] > array[1] ) {
×
5040
                        EXCH(array[0],array[1])
×
5041
                }
5042
                return;
×
5043
        }
5044
        n1 = num/2;
×
5045
        n2 = num - n1;
×
5046
        SimpleSplitMergeRec(array,n1,auxarray);
×
5047
        SimpleSplitMergeRec(array+n1,n2,auxarray);
×
5048
        if ( array[n1-1] <= array[n1] ) return;
×
5049

5050
        t1 = array; t2 = auxarray; i = n1; NCOPY(t2,t1,i);
×
5051
        i = 0; j = n1; k = 0;
5052
        while ( i < n1 && j < num ) {
×
5053
                if ( auxarray[i] <= array[j] ) { array[k++] = auxarray[i++]; }
×
5054
                else { array[k++] = array[j++]; }
×
5055
        }
5056
        while ( i < n1 ) array[k++] = auxarray[i++];
×
5057
/*
5058
        Remember: remnants of j are still in place!
5059
*/
5060
}
5061

NEW
5062
void SimpleSplitMerge(WORD *array,WORD num)
×
5063
{
5064
        WORD *auxarray = Malloc1(sizeof(WORD)*num/2,"SimpleSplitMerge");
×
5065
        SimpleSplitMergeRec(array,num,auxarray);
×
5066
        M_free(auxarray,"SimpleSplitMerge");
×
5067
}
×
5068

5069
/*
5070
                 #] SimpleSplitMerge : 
5071
                 #[ BinarySearch :
5072

5073
                Searches in the sorted array with length num for the object x.
5074
                If x is in the list, it returns the number of the array element
5075
                that matched. If it is not in the list, it returns -1.
5076
                If there are identical objects in the list, which one will
5077
                match is quasi random.
5078
*/
5079

5080
WORD BinarySearch(WORD *array,WORD num,WORD x)
×
5081
{
5082
        WORD i, bot, top, med;
×
5083
        if ( num < 8 ) {
×
5084
                for ( i = 0; i < num; i++ ) if ( array[i] == x ) return(i);
×
5085
                return(-1);
5086
        }
5087
        if ( array[0] > x || array[num-1] < x ) return(-1);
×
5088
        bot = 0; top = num-1; med = (top+bot)/2;
×
5089
        do {
×
5090
                if ( array[med] == x ) return(med);
×
5091
                if ( array[med] < x ) { bot = med+1; }
×
5092
                else { top = med-1; }
×
5093
                med = (top+bot)/2;
×
5094
        } while ( med >= bot && med <= top );
×
5095
        return(-1);
5096
}
5097

5098
/*
5099
                 #] BinarySearch : 
5100
        #] SortUtilities :
5101
*/
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