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

vermaseren / form / 9364948935

04 Jun 2024 09:49AM UTC coverage: 49.979% (-0.02%) from 49.999%
9364948935

Pull #526

github

web-flow
Merge 7062bd769 into 83e3d4185
Pull Request #526: RFC: better debugging

52 of 415 new or added lines in 46 files covered. (12.53%)

32 existing lines in 2 files now uncovered.

41391 of 82816 relevant lines covered (49.98%)

878690.77 hits per line

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

58.44
/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

55
#include "form3.h"
56

57
#ifdef WITHPTHREADS
58
UBYTE THRbuf[100];
59
#endif
60

61
#ifdef WITHSTATS
62
extern LONG numwrites;
63
extern LONG numreads;
64
extern LONG numseeks;
65
extern LONG nummallocs;
66
extern LONG numfrees;
67
#endif
68

69
LONG numcompares;
70

71
/*
72
          #] Includes : 
73
        #[ SortUtilities :
74
                #[ WriteStats :                                VOID WriteStats(lspace,par,checkLogType)
75
*/
76
 
77
char *toterms[] = { "   ", " >>", "-->" };
78

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

95
VOID WriteStats(POSITION *plspace, WORD par, WORD checkLogType)
11,539✔
96
{
97
        GETIDENTITY
6,284✔
98
        LONG millitime, y = 0x7FFFFFFFL >> 1;
11,539✔
99
        WORD timepart;
11,539✔
100
        SORTING *S;
11,539✔
101
        POSITION pp;
11,539✔
102
        int use_wtime;
11,539✔
103
        if ( AT.SS == AT.S0 && AC.StatsFlag ) {
11,539✔
104
#ifdef WITHPTHREADS
105
                if ( AC.ThreadStats == 0 && identity > 0 ) return;
3,670✔
106
#elif defined(WITHMPI)
107
                if ( AC.OldParallelStats ) return;
800✔
108
                if ( ! AC.ProcessStats && PF.me != MASTER ) return;
800✔
109
#endif
110
                if ( Expressions == 0 ) return;
6,317✔
111

112
                if ( par == STATSSPLITMERGE ) {
6,317✔
113
                        if ( AC.ShortStatsMax == 0 ) return;
2,826✔
114
                        AR.ShortSortCount++;
×
115
                        if ( AR.ShortSortCount < AC.ShortStatsMax ) return;
×
116
                }
117
                AR.ShortSortCount = 0;
3,491✔
118

119
                S = AT.SS;
3,491✔
120

121
                MLOCK(ErrorMessageLock);
3,491✔
122

123
                /* If the statistics should not go to the log file, temporarily hide the
124
                 * LogHandle. This must be done within the ErrorMessageLock region to
125
                 * avoid a data race between threads. */
126
                const WORD oldLogHandle = AC.LogHandle;
3,491✔
127
                if ( checkLogType && AM.LogType ) {
3,491✔
128
                        AC.LogHandle = -1;
181✔
129
                }
130

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

590
                MUNLOCK(ErrorMessageLock);
6,099✔
591
        }
592
}
593

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

608
WORD NewSort(PHEAD0)
3,462,898✔
609
{
610
        GETBIDENTITY
611
        SORTING *S, **newFS;
3,462,898✔
612
        int i, newsize;
3,462,898✔
613
        if ( AN.SoScratC == 0 )
3,462,898✔
614
                AN.SoScratC = (UWORD *)Malloc1(2*(AM.MaxTal+2)*sizeof(UWORD),"NewSort");
2,585✔
615
        AR.sLevel++;
3,462,898✔
616
        if ( AR.sLevel >= AN.NumFunSorts ) {
3,462,898✔
617
                if ( AN.NumFunSorts == 0 ) newsize = 100;
3,079✔
618
                else newsize = 2*AN.NumFunSorts;
×
619
                newFS = (SORTING **)Malloc1((newsize+1)*sizeof(SORTING *),"FunSort pointers");
3,079✔
620
                for ( i = 0; i < AN.NumFunSorts; i++ ) newFS[i] = AN.FunSorts[i];
6,158✔
621
                for ( ; i <= newsize; i++ ) newFS[i] = 0;
314,058✔
622
                if ( AN.FunSorts ) M_free(AN.FunSorts,"FunSort pointers");
3,079✔
623
                AN.FunSorts = newFS; AN.NumFunSorts = newsize;
3,079✔
624
        }
625
        if ( AR.sLevel == 0 ) {
3,462,898✔
626

627
                numcompares = 0;
36,277✔
628

629
                AN.FunSorts[0] = AT.S0;
36,277✔
630
                if ( AR.PolyFun == 0 ) { AT.S0->PolyFlag = 0; }
36,277✔
631
                else if ( AR.PolyFunType == 1 ) { AT.S0->PolyFlag = 1; }
13,559✔
632
                else if ( AR.PolyFunType == 2 ) {
13,481✔
633
                        if ( AR.PolyFunExp == 2
13,481✔
634
                          || AR.PolyFunExp == 3 ) AT.S0->PolyFlag = 1;
13,481✔
635
                        else                      AT.S0->PolyFlag = 2;
13,227✔
636
                }
637
                AR.ShortSortCount = 0;
36,277✔
638
        }
639
        else {
640
                if ( AN.FunSorts[AR.sLevel] == 0 ) {
3,426,621✔
641
                        AN.FunSorts[AR.sLevel] = AllocSort(
1,414✔
642
                                AM.SLargeSize,AM.SSmallSize,AM.SSmallEsize,AM.STermsInSmall
643
                                        ,AM.SMaxPatches,AM.SMaxFpatches,AM.SIOsize);
644
                }
645
                AN.FunSorts[AR.sLevel]->PolyFlag = 0;
3,426,621✔
646
        }
647
        AT.SS = S = AN.FunSorts[AR.sLevel];
3,462,898✔
648
        S->sFill = S->sBuffer;
3,462,898✔
649
        S->lFill = S->lBuffer;
3,462,898✔
650
        S->lPatch = 0;
3,462,898✔
651
        S->fPatchN = 0;
3,462,898✔
652
        S->GenTerms = S->TermsLeft = S->GenSpace = S->SpaceLeft = 0;
3,462,898✔
653
        S->PoinFill = S->sPointer;
3,462,898✔
654
        *S->PoinFill = S->sFill;
3,462,898✔
655
        if ( AR.sLevel > 0 ) { S->PolyWise = 0; }
3,462,898✔
656
        PUTZERO(S->SizeInFile[0]); PUTZERO(S->SizeInFile[1]); PUTZERO(S->SizeInFile[2]);
3,462,898✔
657
        S->sTerms = 0;
3,462,898✔
658
        PUTZERO(S->file.POposition);
3,462,898✔
659
        S->stage4 = 0;
3,462,898✔
660
        if ( AR.sLevel > AN.MaxFunSorts ) AN.MaxFunSorts = AR.sLevel;
3,462,898✔
661
/*
662
        The next variable is for the staged sort only.
663
        It should be treated differently
664

665
        PUTZERO(AN.OldPosOut);
666
*/
667
        return(0);
3,462,898✔
668
}
669

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

698
LONG EndSort(PHEAD WORD *buffer, int par)
3,449,696✔
699
{
700
  GETBIDENTITY
701
  SORTING *S = AT.SS;
3,449,696✔
702
  WORD j, **ss, *to, *t;
3,449,696✔
703
  LONG sSpace, over, tover, spare, retval = 0, jj;
3,449,696✔
704
  POSITION position, pp;
3,449,696✔
705
  off_t lSpace;
3,449,696✔
706
  FILEHANDLE *fout = 0, *oldoutfile = 0, *newout = 0;
3,449,696✔
707

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

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

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

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

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

1321
/*
1322
                 #] PutIn : 
1323
                 #[ Sflush :                                        WORD Sflush(file)
1324
*/
1325
/**
1326
 *        Puts the contents of a buffer to output
1327
 *        Only to be used when there is a single patch in the large buffer.
1328
 *
1329
 *        @param fi  The filesystem (or its cache) to which the patch should be written
1330
 */
1331

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

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

1418
WORD PutOut(PHEAD WORD *term, POSITION *position, FILEHANDLE *fi, WORD ncomp)
12,200,460✔
1419
{
1420
        GETBIDENTITY
1421
        WORD i, *p, ret, *r, *rr, j, k, first;
12,200,460✔
1422
        int dobracketindex = 0;
12,200,460✔
1423
        LONG RetCode;
12,200,460✔
1424

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

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

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

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

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

1994
WORD AddCoef(PHEAD WORD **ps1, WORD **ps2)
3,611,130✔
1995
{
1996
        GETBIDENTITY
1997
        SORTING *S = AT.SS;
3,611,130✔
1998
        WORD *s1, *s2;
3,611,130✔
1999
        WORD l1, l2, i;
3,611,130✔
2000
        WORD OutLen, *t, j;
3,611,130✔
2001
        UWORD *OutCoef;
3,611,130✔
2002
#ifdef WITHFLOAT
2003
        if ( AT.SortFloatMode ) return(AddWithFloat(BHEAD ps1,ps2));
3,611,130✔
2004
#endif
2005
        OutCoef = AN.SoScratC;
3,611,130✔
2006
        s1 = *ps1; s2 = *ps2;
3,611,130✔
2007
        GETCOEF(s1,l1);
3,611,130✔
2008
        GETCOEF(s2,l2);
3,611,130✔
2009
        if ( AddRat(BHEAD (UWORD *)s1,l1,(UWORD *)s2,l2,OutCoef,&OutLen) ) {
3,611,130✔
2010
                MLOCK(ErrorMessageLock);
×
2011
                MesCall("AddCoef");
×
2012
                MUNLOCK(ErrorMessageLock);
×
NEW
2013
                TERMINATE(-1);
×
2014
        }
2015
        if ( AN.ncmod != 0 ) {
3,611,130✔
2016
                if ( ( AC.modmode & POSNEG ) != 0 ) {
×
2017
                        NormalModulus(OutCoef,&OutLen);
×
2018
/*
2019
                        We had forgotten that this can also become smaller but the
2020
                        denominator isn't there. Correct in the other case
2021
                        17-may-2009 [JV]
2022
*/
2023
                        j = ABS(OutLen); OutCoef[j] = 1;
×
2024
                        for ( i = 1; i < j; i++ ) OutCoef[j+i] = 0;
×
2025
                }
2026
                else if ( BigLong(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod)) >= 0 ) {
×
2027
                        SubPLon(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod),OutCoef,&OutLen);
×
2028
                        OutCoef[OutLen] = 1;
×
2029
                        for ( i = 1; i < OutLen; i++ ) OutCoef[OutLen+i] = 0;
×
2030
                }
2031
        }
2032
        if ( !OutLen ) { *ps1 = *ps2 = 0; return(0); }
3,611,130✔
2033
        OutLen *= 2;
3,587,728✔
2034
        if ( OutLen < 0 ) i = - ( --OutLen );
3,587,728✔
2035
        else                          i = ++OutLen;
3,401,176✔
2036
        if ( l1 < 0 ) l1 = -l1;
3,587,728✔
2037
        l1 *= 2; l1++;
3,587,728✔
2038
        if ( i <= l1 ) {        /* Fits in 1 */
3,587,728✔
2039
                l1 -= i;
3,549,437✔
2040
                **ps1 -= l1;
3,549,437✔
2041
                s2 = (WORD *)OutCoef;
3,549,437✔
2042
                while ( --i > 0 ) *s1++ = *s2++;
10,970,771✔
2043
                *s1++ = OutLen;
3,549,437✔
2044
                while ( --l1 >= 0 ) *s1++ = 0;
3,549,677✔
2045
                goto RegEnd;
3,549,437✔
2046
        }
2047
        if ( l2 < 0 ) l2 = -l2;
38,297✔
2048
        l2 *= 2; l2++;
38,297✔
2049
        if ( i <= l2 ) {        /* Fits in 2 */
38,297✔
2050
                l2 -= i;
21,451✔
2051
                **ps2 -= l2;
21,451✔
2052
                s1 = (WORD *)OutCoef;
21,451✔
2053
                while ( --i > 0 ) *s2++ = *s1++;
179,967✔
2054
                *s2++ = OutLen;
21,451✔
2055
                while ( --l2 >= 0 ) *s2++ = 0;
21,579✔
2056
                *ps1 = *ps2;
21,451✔
2057
                goto RegEnd;
21,451✔
2058
        }
2059

2060
        /* Doesn't fit. Make a new term. */
2061

2062
        t = s1;
16,846✔
2063
        s1 = *ps1;
16,846✔
2064
        j = *s1++ + i - l1;                /* Space needed */
16,846✔
2065
        if ( (S->sFill + j) >= S->sTop2 ) {
16,846✔
2066
                GarbHand();
×
2067
                s1 = *ps1;
×
2068
                t = s1 + *s1 - 1;
×
2069
                j = *s1++ + i - l1;                /* Space needed */
×
2070
                l1 = *t;
×
2071
                if ( l1 < 0 ) l1  = - l1;
×
2072
                t -= l1-1;
×
2073
        }
2074
        s2 = S->sFill;
16,846✔
2075
        *s2++ = j;
16,846✔
2076
        while ( s1 < t ) *s2++ = *s1++;
126,154✔
2077
        s1 = (WORD *)OutCoef;
2078
        while ( --i > 0 ) *s2++ = *s1++;
169,204✔
2079
        *s2++ = OutLen;
16,846✔
2080
        *ps1 = S->sFill;
16,846✔
2081
        S->sFill = s2;
16,846✔
2082
RegEnd:
3,587,728✔
2083
        *ps2 = 0;
3,587,728✔
2084
        if ( **ps1 > AM.MaxTer/((LONG)(sizeof(WORD))) ) {
3,587,728✔
2085
                MLOCK(ErrorMessageLock);
×
2086
                MesPrint("Term too complex after addition in sort. MaxTermSize = %10l",
×
2087
                AM.MaxTer/sizeof(WORD));
×
2088
                MUNLOCK(ErrorMessageLock);
×
NEW
2089
                TERMINATE(-1);
×
2090
        }
2091
        return(1);
2092
}
2093

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

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

2271
/*
2272
                 #] AddPoly : 
2273
                 #[ AddArgs :                                VOID AddArgs(arg1,arg2,to)
2274
*/
2275
 
2276
#define INSLENGTH(x)  w[1] = FUNHEAD+ARGHEAD+x; w[FUNHEAD] = ARGHEAD+x;
2277

2278
/**
2279
 *        Adds the arguments of two occurrences of the PolyFun.
2280
 *        @param s1 Pointer to the first occurrence.
2281
 *        @param s2 Pointer to the second occurrence.
2282
 *        @param m  Pointer to where the answer should be.
2283
 */
2284

2285
VOID AddArgs(PHEAD WORD *s1, WORD *s2, WORD *m)
16✔
2286
{
2287
        GETBIDENTITY
2288
        WORD i1, i2;
16✔
2289
        WORD *w = m, *mm, *t, *t1, *t2, *tstop1, *tstop2;
16✔
2290
        WORD tempterm[8+FUNHEAD];
16✔
2291

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

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

2578
WORD Compare1(PHEAD WORD *term1, WORD *term2, WORD level)
35,136,770✔
2579
{
2580
        SORTING *S = AT.SS;
35,136,770✔
2581
        WORD *stopper1, *stopper2, *t2;
35,136,770✔
2582
        WORD *s1, *s2, *t1;
35,136,770✔
2583
        WORD *stopex1, *stopex2;
35,136,770✔
2584
        WORD c1, c2;
35,136,770✔
2585
        WORD prevorder;
35,136,770✔
2586
        WORD count = -1, localPoly, polyhit = -1;
35,136,770✔
2587

2588
        if ( AR.sLevel == 0 ) {
35,136,770✔
2589
                numcompares++;
30,058,860✔
2590
        }
2591

2592
        if ( S->PolyFlag ) {
35,136,770✔
2593
/*
2594
                if ( S->PolyWise != 0 ) {
2595
                        MLOCK(ErrorMessageLock);
2596
                        MesPrint("S->PolyWise is not zero!!!!!");
2597
                        MUNLOCK(ErrorMessageLock);
2598
                }
2599
*/
2600
                count = 0; localPoly = 1; S->PolyWise = polyhit = 0;
101,963✔
2601
                S->PolyFlag = AR.PolyFunType;
101,963✔
2602
                if ( AR.PolyFunType == 2 &&
101,963✔
2603
                         ( AR.PolyFunExp == 2 || AR.PolyFunExp == 3 ) ) S->PolyFlag = 1;
101,927✔
2604
        }
2605
        else { localPoly = 0; }
2606
#ifdef WITHFLOAT
2607
        AT.SortFloatMode = 0;
35,136,770✔
2608
#endif
2609
        prevorder = 0;
35,136,770✔
2610
        GETSTOP(term1,s1);
35,136,770✔
2611
        stopper1 = s1;
35,136,770✔
2612
        GETSTOP(term2,stopper2);
35,136,770✔
2613
        t1 = term1 + 1;
35,136,770✔
2614
        t2 = term2 + 1;
35,136,770✔
2615
        while ( t1 < stopper1 && t2 < stopper2 ) {
49,068,810✔
2616
                if ( *t1 != *t2 ) {
42,066,960✔
2617
                        if ( *t1 == HAAKJE ) return(PREV(-1));
50,696✔
2618
                        if ( *t2 == HAAKJE ) return(PREV(1));
44,591✔
2619
                        if ( *t1 >= (FUNCTION-1) ) {
43,638✔
2620
                                if ( *t2 < (FUNCTION-1) ) return(PREV(-1));
21,347✔
2621
                                if ( *t1 < FUNCTION && *t2 < FUNCTION ) return(PREV(*t2-*t1));
10,360✔
2622
                                if ( *t1 < FUNCTION ) return(PREV(1));
10,360✔
2623
                                if ( *t2 < FUNCTION ) return(PREV(-1));
10,360✔
2624
                                c1 = functions[*t1-FUNCTION].commute;
10,360✔
2625
                                c2 = functions[*t2-FUNCTION].commute;
10,360✔
2626
                                if ( !c1 ) {
10,360✔
2627
                                        if ( c2 ) return(PREV(1));
10,360✔
2628
                                        else return(PREV(*t2-*t1));
10,360✔
2629
                                }
2630
                                else {
2631
                                        if ( !c2 ) return(PREV(-1));
×
2632
                                        else return(PREV(*t2-*t1));
×
2633
                                }
2634
                        }
2635
                        else return(PREV(*t2-*t1));
22,291✔
2636
                }
2637
                s1 = t1 + 2;
42,016,230✔
2638
                s2 = t2 + 2;
42,016,230✔
2639
                c1 = *t1;
42,016,230✔
2640
                t1 += t1[1];
42,016,230✔
2641
                t2 += t2[1];
42,016,230✔
2642
                if ( localPoly && c1 < FUNCTION ) {
42,016,230✔
2643
                        polyhit = 1;
13,308✔
2644
                }
2645
                if ( c1 <= (FUNCTION-1)
42,016,230✔
2646
                || ( c1 >= FUNCTION && functions[c1-FUNCTION].spec > 0 ) ) {
24,307,705✔
2647
                        if ( c1 == SYMBOL ) {
17,948,130✔
2648
                                if ( *s1 == FACTORSYMBOL && *s2 == FACTORSYMBOL
2,461,254✔
2649
                                 && s1[-1] == 4 && s2[-1] == 4
3,421✔
2650
                                 && ( ( t1 < stopper1 && *t1 == HAAKJE )
3,421✔
2651
                                 || ( t1 == stopper1 && AT.fromindex ) ) ) {
×
2652
/*
2653
                                        We have to be very careful with the criteria here, because
2654
                                        Compare1 is called both in the regular sorting and by the
2655
                                        routine that makes the bracket index. In the last case
2656
                                        there is no HAAKJE subterm.
2657
*/
2658
                                        if ( s1[1] != s2[1] ) return(s2[1]-s1[1]);
3,421✔
2659
                                        s1 += 2; s2 += 2;
2,059✔
2660
                                }
2661
                                else if ( AR.SortType >= SORTPOWERFIRST ) {
2,457,833✔
2662
                                        WORD i1 = 0, *r1;
2663
                                        r1 = s1;
×
2664
                                        while ( s1 < t1 ) { i1 += s1[1]; s1 += 2; }
×
2665
                                        s1 = r1; r1 = s2;
×
2666
                                        while ( s2 < t2 ) { i1 -= s2[1]; s2 += 2; }
×
2667
                                        s2 = r1;
×
2668
                                        if ( i1 ) {
×
2669
                                                if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
×
2670
                                                return(PREV(i1));
×
2671
                                        }
2672
                                }
2673
                                while ( s1 < t1 ) {
5,146,020✔
2674
                                        if ( s2 >= t2 ) {
4,765,060✔
2675
/*                                                return(PREV(1));  */
2676
                                                if ( AR.SortType==SORTLOWFIRST ) {
8,119✔
2677
                                                        return(PREV((s1[1]>0?-1:1)));
7,782✔
2678
                                                }
2679
                                                else {
2680
                                                        return(PREV((s1[1]<0?-1:1)));
337✔
2681
                                                }
2682
                                        }
2683
                                        if ( *s1 != *s2 ) {
4,756,930✔
2684
/*                                                return(PREV(*s2-*s1)); */
2685
                                                if ( AR.SortType==SORTLOWFIRST ) {
785,000✔
2686
                                                        if ( *s1 < *s2 ) {
714,281✔
2687
                                                                return(PREV((s1[1]<0?1:-1)));
445,685✔
2688
                                                        }
2689
                                                        else {
2690
                                                                return(PREV((s2[1]<0?-1:1)));
268,596✔
2691
                                                        }
2692
                                                }
2693
                                                else {
2694
                                                        if ( *s1 < *s2 ) {
70,719✔
2695
                                                                return(PREV((s1[1]<0?-1:1)));
51,965✔
2696
                                                        }
2697
                                                        else {
2698
                                                                return(PREV((s2[1]<0?1:-1)));
18,754✔
2699
                                                        }
2700
                                                }
2701
                                        }
2702
                                        s1++; s2++;
3,971,932✔
2703
                                        if ( *s1 != *s2 ) return(
3,971,932✔
2704
                                                PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
1,285,799✔
2705
                                        s1++; s2++;
2,686,132✔
2706
                                }
2707
                                if ( s2 < t2 ) {
380,974✔
2708
/*                                        return(PREV(-1));  */
2709
                                        if ( AR.SortType==SORTLOWFIRST ) {
10,936✔
2710
                                                return(PREV((s2[1]<0?-1:1)));
10,922✔
2711
                                        }
2712
                                        else {
2713
                                                return(PREV((s2[1]<0?1:-1)));
14✔
2714
                                        }
2715
                                }
2716
                        }
2717
                        else if ( c1 == DOTPRODUCT ) {
15,486,870✔
2718
                                if ( AR.SortType >= SORTPOWERFIRST ) {
88✔
2719
                                        WORD i1 = 0, *r1;
2720
                                        r1 = s1;
×
2721
                                        while ( s1 < t1 ) { i1 += s1[2]; s1 += 3; }
×
2722
                                        s1 = r1; r1 = s2;
×
2723
                                        while ( s2 < t2 ) { i1 -= s2[2]; s2 += 3; }
×
2724
                                        s2 = r1;
×
2725
                                        if ( i1 ) {
×
2726
                                                if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
×
2727
                                                return(PREV(i1));
×
2728
                                        }
2729
                                }
2730
                                while ( s1 < t1 ) {
88✔
2731
                                        if ( s2 >= t2 ) return(PREV(1));
88✔
2732
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
88✔
2733
                                        s1++; s2++;
88✔
2734
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
88✔
2735
                                        s1++; s2++;
80✔
2736
                                        if ( *s1 != *s2 ) return(
80✔
2737
                                                PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
80✔
2738
                                        s1++; s2++;
×
2739
                                }
2740
                                if ( s2 < t2 ) return(PREV(-1));
×
2741
                        }
2742
                        else {
2743
                                while ( s1 < t1 ) {
124,055,400✔
2744
                                        if ( s2 >= t2 ) return(PREV(1));
123,734,600✔
2745
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
123,734,600✔
2746
                                        s1++; s2++;
108,568,600✔
2747
                                }
2748
                                if ( s2 < t2 ) return(PREV(-1));
320,884✔
2749
                        }
2750
                }
2751
                else {
2752
#if FUNHEAD != 2
2753
                        s1 += FUNHEAD-2;
24,068,143✔
2754
                        s2 += FUNHEAD-2;
24,068,143✔
2755
#endif
2756
                        if ( localPoly && c1 == AR.PolyFun ) {
24,068,143✔
2757
                                if ( count == 0 ) {
13,932✔
2758
                                  if ( S->PolyFlag == 1 ) {
13,932✔
2759
                                        WORD i1, i2;
16✔
2760
                                        if ( *s1 > 0 ) i1 = *s1;
16✔
2761
                                        else if ( *s1 <= -FUNCTION ) i1 = 1;
×
2762
                                        else i1 = 2;
×
2763
                                        if ( *s2 > 0 ) i2 = *s2;
16✔
2764
                                        else if ( *s2 <= -FUNCTION ) i2 = 1;
×
2765
                                        else i2 = 2;
×
2766
                                        if ( s1+i1 == t1 && s2+i2 == t2 ) {        /* This is the stuff */
16✔
2767
/*
2768
                                                Test for scalar nature
2769
*/
2770
                                                if ( !polyhit ) {
16✔
2771
                                                        WORD *u1, *u2, *ustop;
12✔
2772
                                                        if ( *s1 < 0 ) {
12✔
2773
                                                                if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
×
2774
                                                                        goto NoPoly;
×
2775
                                                        }
2776
                                                        else {
2777
                                                                u1 = s1 + ARGHEAD;
12✔
2778
                                                                while ( u1 < t1 ) {
43✔
2779
                                                                        u2 = u1 + *u1;
31✔
2780
                                                                        ustop = u2 - ABS(u2[-1]);
31✔
2781
                                                                        u1++;
31✔
2782
                                                                        while ( u1 < ustop ) {
58✔
2783
                                                                                if ( *u1 == INDEX ) goto NoPoly;
27✔
2784
                                                                                u1 += u1[1];
27✔
2785
                                                                        }
2786
                                                                        u1 = u2;
2787
                                                                }
2788
                                                        }
2789
                                                        if ( *s2 < 0 ) {
12✔
2790
                                                                if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
×
2791
                                                                        goto NoPoly;
×
2792
                                                        }
2793
                                                        else {
2794
                                                                u1 = s2 + ARGHEAD;
12✔
2795
                                                                while ( u1 < t2 ) {
32✔
2796
                                                                        u2 = u1 + *u1;
20✔
2797
                                                                        ustop = u2 - ABS(u2[-1]);
20✔
2798
                                                                        u1++;
20✔
2799
                                                                        while ( u1 < ustop ) {
36✔
2800
                                                                                if ( *u1 == INDEX ) goto NoPoly;
16✔
2801
                                                                                u1 += u1[1];
16✔
2802
                                                                        }
2803
                                                                        u1 = u2;
2804
                                                                }
2805
                                                        }
2806
                                                }
2807
                                                S->PolyWise = WORDDIF(s1,term1);
16✔
2808
                                                S->PolyWise -= FUNHEAD;
16✔
2809
                                                count = 1;
16✔
2810
                                                continue;
16✔
2811
                                        }
2812
                                        else {
2813
NoPoly:
×
2814
                                                S->PolyWise = localPoly = 0;
×
2815
                                        }
2816
                                  }
2817
                                  else if ( AR.PolyFunType == 2 ) {
13,916✔
2818
                                        WORD i1, i2, i1a, i2a;
13,916✔
2819
                                        if ( *s1 > 0 ) i1 = *s1;
13,916✔
2820
                                        else if ( *s1 <= -FUNCTION ) i1 = 1;
1,457✔
2821
                                        else i1 = 2;
1,457✔
2822
                                        if ( *s2 > 0 ) i2 = *s2;
13,916✔
2823
                                        else if ( *s2 <= -FUNCTION ) i2 = 1;
927✔
2824
                                        else i2 = 2;
927✔
2825
                                        if ( s1[i1] > 0 ) i1a = s1[i1];
13,916✔
2826
                                        else if ( s1[i1] <= -FUNCTION ) i1a = 1;
1,244✔
2827
                                        else i1a = 2;
1,244✔
2828
                                        if ( s2[i2] > 0 ) i2a = s2[i2];
13,916✔
2829
                                        else if ( s2[i2] <= -FUNCTION ) i2a = 1;
1,152✔
2830
                                        else i2a = 2;
1,152✔
2831
                                        if ( s1+i1+i1a == t1 && s2+i2+i2a == t2 ) {        /* This is the stuff */
13,916✔
2832
/*
2833
                                                Test for scalar nature
2834
*/
2835
                                                if ( !polyhit ) {
13,916✔
2836
                                                        WORD *u1, *u2, *ustop;
9,748✔
2837
                                                        if ( *s1 < 0 ) {
9,748✔
2838
                                                                if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
745✔
2839
                                                                        goto NoPoly;
×
2840
                                                        }
2841
                                                        else {
2842
                                                                u1 = s1 + ARGHEAD;
9,003✔
2843
                                                                while ( u1 < s1+i1 ) {
133,004✔
2844
                                                                        u2 = u1 + *u1;
124,001✔
2845
                                                                        ustop = u2 - ABS(u2[-1]);
124,001✔
2846
                                                                        u1++;
124,001✔
2847
                                                                        while ( u1 < ustop ) {
240,866✔
2848
                                                                                if ( *u1 == INDEX ) goto NoPoly;
116,865✔
2849
                                                                                u1 += u1[1];
116,865✔
2850
                                                                        }
2851
                                                                        u1 = u2;
2852
                                                                }
2853
                                                        }
2854
                                                        if ( s1[i1] < 0 ) {
9,748✔
2855
                                                                if ( s1[i1] != -SNUMBER && s1[i1] != -SYMBOL && s1[i1] > -FUNCTION )
476✔
2856
                                                                        goto NoPoly;
×
2857
                                                        }
2858
                                                        else {
2859
                                                                u1 = s1 +i1 + ARGHEAD;
9,272✔
2860
                                                                while ( u1 < t1 ) {
138,694✔
2861
                                                                        u2 = u1 + *u1;
129,422✔
2862
                                                                        ustop = u2 - ABS(u2[-1]);
129,422✔
2863
                                                                        u1++;
129,422✔
2864
                                                                        while ( u1 < ustop ) {
251,724✔
2865
                                                                                if ( *u1 == INDEX ) goto NoPoly;
122,302✔
2866
                                                                                u1 += u1[1];
122,302✔
2867
                                                                        }
2868
                                                                        u1 = u2;
2869
                                                                }
2870
                                                        }
2871
                                                        if ( *s2 < 0 ) {
9,748✔
2872
                                                                if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
643✔
2873
                                                                        goto NoPoly;
×
2874
                                                        }
2875
                                                        else {
2876
                                                                u1 = s2 + ARGHEAD;
9,105✔
2877
                                                                while ( u1 < s2+i2 ) {
134,502✔
2878
                                                                        u2 = u1 + *u1;
125,397✔
2879
                                                                        ustop = u2 - ABS(u2[-1]);
125,397✔
2880
                                                                        u1++;
125,397✔
2881
                                                                        while ( u1 < ustop ) {
243,658✔
2882
                                                                                if ( *u1 == INDEX ) goto NoPoly;
118,261✔
2883
                                                                                u1 += u1[1];
118,261✔
2884
                                                                        }
2885
                                                                        u1 = u2;
2886
                                                                }
2887
                                                        }
2888
                                                        if ( s2[i2] < 0 ) {
9,748✔
2889
                                                                if ( s2[i2] != -SNUMBER && s2[i2] != -SYMBOL && s2[i2] > -FUNCTION )
484✔
2890
                                                                        goto NoPoly;
×
2891
                                                        }
2892
                                                        else {
2893
                                                                u1 = s2 + i2 + ARGHEAD;
9,264✔
2894
                                                                while ( u1 < t2 ) {
139,881✔
2895
                                                                        u2 = u1 + *u1;
130,617✔
2896
                                                                        ustop = u2 - ABS(u2[-1]);
130,617✔
2897
                                                                        u1++;
130,617✔
2898
                                                                        while ( u1 < ustop ) {
254,114✔
2899
                                                                                if ( *u1 == INDEX ) goto NoPoly;
123,497✔
2900
                                                                                u1 += u1[1];
123,497✔
2901
                                                                        }
2902
                                                                        u1 = u2;
2903
                                                                }
2904
                                                        }
2905
                                                }
2906
                                                S->PolyWise = WORDDIF(s1,term1);
13,916✔
2907
                                                S->PolyWise -= FUNHEAD;
13,916✔
2908
                                                count = 1;
13,916✔
2909
                                                continue;
13,916✔
2910
                                        }
2911
                                        else {
2912
                                                S->PolyWise = localPoly = 0;
×
2913
                                        }
2914
                                  }
2915
                                  else {
2916
                                        S->PolyWise = localPoly = 0;
×
2917
                                  }
2918
                                }
2919
                                else {
2920
                                        t1 = term1 + S->PolyWise;
×
2921
                                        t2 = term2 + S->PolyWise;
×
2922
                                        S->PolyWise = 0;
×
2923
                                        localPoly = 0;
×
2924
                                        continue;
×
2925
                                }
2926
                        }
2927
#ifdef WITHFLOAT
2928
                        if ( c1 == FLOATFUN && t1 == stopper1 && t2 == stopper2 && AT.aux_ != 0 ) {
24,054,190✔
2929
/*
2930
                                We have two FLOATFUN's. Test whether they are 'legal'
2931
*/
2932
                                if ( TestFloat(s1-FUNHEAD) ) {
×
2933
                                        if ( TestFloat(s2-FUNHEAD) ) { AT.SortFloatMode = 3; return(0); }
×
2934
                                        else { return(1); }
2935
                                }
2936
                                else if ( TestFloat(s2-FUNHEAD) ) { return(-1); }
×
2937
                        }
2938
#endif
2939
                        while ( s1 < t1 ) {
37,456,734✔
2940
/*
2941
                                The next statement was added 9-nov-2001. It repaired a bad error
2942
*/
2943
                                if ( s2 >= t2 ) return(PREV(-1));
24,229,558✔
2944
/*
2945
                                There is a little problem here with fast arguments
2946
                                We don't want to sacrifice speed, but we like to
2947
                                keep a rational ordering. This last one suffers in
2948
                                the solution that has been chosen here.
2949
*/
2950
                                if ( AC.properorderflag ) {
24,229,558✔
2951
                                        WORD oldpolyflag;
×
2952
                                        oldpolyflag = S->PolyFlag;
×
2953
                                        S->PolyFlag = 0;
×
2954
                                        if ( ( c2 = -CompArg(s1,s2) ) != 0 ) {
×
2955
                                                S->PolyFlag = oldpolyflag; return(PREV(c2));
×
2956
                                        }
2957
                                        S->PolyFlag = oldpolyflag;
×
2958
                                        NEXTARG(s1)
×
2959
                                        NEXTARG(s2)
×
2960
                                }
2961
                                else {
2962
                                        if ( *s1 > 0 ) {
24,229,558✔
2963
                                                if ( *s2 > 0 ) {
172,830✔
2964
                                                        WORD oldpolyflag;
172,026✔
2965
                                                        stopex1 = s1 + *s1;
172,026✔
2966
                                                        if ( s2 >= t2 ) return(PREV(-1));
172,026✔
2967
                                                        stopex2 = s2 + *s2;
172,026✔
2968
                                                        s1 += ARGHEAD; s2 += ARGHEAD;
172,026✔
2969
                                                        oldpolyflag = S->PolyFlag;
172,026✔
2970
                                                        S->PolyFlag = 0;
172,026✔
2971
                                                        while ( s1 < stopex1 ) {
426,800✔
2972
                                                                if ( s2 >= stopex2 ) {
329,084✔
2973
                                                                        S->PolyFlag = oldpolyflag; return(PREV(-1));
1,692✔
2974
                                                                }
2975
                                                                if ( ( c2 = CompareTerms(BHEAD s1,s2,(WORD)1) ) != 0 ) {
327,392✔
2976
                                                                        S->PolyFlag = oldpolyflag; return(PREV(c2));
72,618✔
2977
                                                                }
2978
                                                                s1 += *s1;
254,774✔
2979
                                                                s2 += *s2;
254,774✔
2980
                                                        }
2981
                                                        S->PolyFlag = oldpolyflag;
97,716✔
2982
                                                        if ( s2 < stopex2 ) return(PREV(1));
97,716✔
2983
                                                }
2984
                                                else return(PREV(1));
2985
                                        }
2986
                                        else {
2987
                                                if ( *s2 > 0 ) return(PREV(-1));
24,056,740✔
2988
                                                if ( *s1 != *s2 ) { return(PREV(*s1-*s2)); }
24,054,910✔
2989
                                                if ( *s1 > -FUNCTION ) {
24,054,899✔
2990
                                                        if ( *++s1 != *++s2 ) { return(PREV(*s2-*s1)); }
24,054,899✔
2991
                                                }
2992
                                                s1++; s2++;
13,309,934✔
2993
                                        }
2994
                                }
2995
                        }
2996
                        if ( s2 < t2 ) return(PREV(1));
13,227,186✔
2997
                }
2998
        }
2999
#ifdef WITHFLOAT
3000
        if ( t1 < stopper1 && *t1 == FLOATFUN && t1+t1[1] == stopper1
7,001,829✔
3001
                        && TestFloat(t1) ) {
×
3002
                AT.SortFloatMode = 1; return(0);
×
3003
        }
3004
        else if ( t2 < stopper2 && *t2 == FLOATFUN && t2+t2[1] == stopper2
7,001,829✔
3005
                        && TestFloat(t2) ) {
×
3006
                AT.SortFloatMode = 2; return(0);
×
3007
        }
3008
#endif
3009
        {
3010
                if ( AR.SortType != SORTLOWFIRST ) {
7,001,829✔
3011
                        if ( t1 < stopper1 ) return(PREV(1));
3,169,924✔
3012
                        if ( t2 < stopper2 ) return(PREV(-1));
669,154✔
3013
                }
3014
                else {
3015
                        if ( t1 < stopper1 ) return(PREV(-1));
3,831,910✔
3016
                        if ( t2 < stopper2 ) return(PREV(1));
3,826,038✔
3017
                }
3018
        }
3019
        if ( level == 3 ) return(CompCoef(term1,term2));
3,963,599✔
3020
        if ( level >= 1 )
3,963,599✔
3021
                return(CompCoef(term2,term1));
256,505✔
3022
        return(0);
3023
}
3024

3025
/*
3026
                 #] Compare1 : 
3027
                 #[ CompareSymbols :                        WORD CompareSymbols(term1,term2,par)
3028
*/
3029
/**
3030
 *        Compares the terms, based on the value of AN.polysortflag.
3031
 *        If term1 < term2 the return value is -1
3032
 *        If term1 > term2 the return value is  1
3033
 *        If term1 = term2 the return value is  0
3034
 *        The coefficients may differ.
3035
 *        The terms contain only a single subterm of type SYMBOL.
3036
 *        If AN.polysortflag = 0 it is a 'regular' compare.
3037
 *        If AN.polysortflag = 1 the sum of the powers is more important
3038
 *        par is a dummy parameter to make the parameter field identical
3039
 *        to that of Compare1 which is the regular compare routine in sort.c
3040
 */
3041

3042
WORD CompareSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
2,173,474✔
3043
{
3044
        int sum1, sum2;
2,173,474✔
3045
        WORD *t1, *t2, *tt1, *tt2;
2,173,474✔
3046
        int low, high;
2,173,474✔
3047
        DUMMYUSE(par);
2,173,474✔
3048
        if ( AR.SortType == SORTLOWFIRST ) { low = 1; high = -1; }
2,173,474✔
3049
        else { low = -1; high = 1; }
2,050,816✔
3050
        t1 = term1 + 1; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); t1 += 2;
2,173,474✔
3051
        t2 = term2 + 1; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); t2 += 2;
2,173,474✔
3052
        if ( AN.polysortflag > 0 ) {
2,173,474✔
3053
                sum1 = 0; sum2 = 0;
×
3054
                while ( t1 < tt1 ) { sum1 += t1[1]; t1 += 2; }
×
3055
                while ( t2 < tt2 ) { sum2 += t2[1]; t2 += 2; }
×
3056
                if ( sum1 < sum2 ) return(low);
×
3057
                if ( sum1 > sum2 ) return(high);
×
3058
                t1 = term1+3; t2 = term2 + 3;
×
3059
        }
3060
        while ( t1 < tt1 && t2 < tt2 ) {
3,692,574✔
3061
                if ( *t1 > *t2 ) return(low);
3,370,557✔
3062
                if ( *t1 < *t2 ) return(high);
2,986,362✔
3063
                if ( t1[1] < t2[1] ) return(low);
2,861,853✔
3064
                if ( t1[1] > t2[1] ) return(high);
2,036,878✔
3065
                t1 += 2; t2 += 2;
1,519,100✔
3066
        }
3067
        if ( t1 < tt1 ) return(high);
322,017✔
3068
        if ( t2 < tt2 ) return(low);
282,736✔
3069
        return(0);
3070
}
3071

3072
/*
3073
                 #] CompareSymbols : 
3074
                 #[ CompareHSymbols :                WORD CompareHSymbols(term1,term2,par)
3075
*/
3076
/**
3077
 *        Compares terms that can have only SYMBOL and HAAKJE subterms.
3078
 *        If term1 < term2 the return value is -1
3079
 *        If term1 > term2 the return value is  1
3080
 *        If term1 = term2 the return value is  0
3081
 *        par is a dummy parameter to make the parameter field identical
3082
 *        to that of Compare1 which is the regular compare routine in sort.c
3083
 */
3084

3085
WORD CompareHSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
×
3086
{
3087
        WORD *t1, *t2, *tt1, *tt2, *ttt1, *ttt2;
×
3088
        DUMMYUSE(par);
×
3089
        DUMMYUSE(AT.WorkPointer);
×
3090
        t1 = term1 + 1; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); t1 += 2;
×
3091
        t2 = term2 + 1; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); t2 += 2;
×
3092
        while ( t1 < tt1 && t2 < tt2 ) {
×
3093
                if ( *t1 != *t2 ) {
×
3094
                        if ( t1[0] < t2[0] ) return(-1);
×
3095
                        return(1);
×
3096
                }
3097
                else if ( *t1 == HAAKJE ) {
×
3098
                        t1 += 3; t2 += 3; continue;
×
3099
                }
3100
                ttt1 = t1+t1[1]; ttt2 = t2+t2[1];
×
3101
                while ( t1 < ttt1 && t2 < ttt2 ) {
×
3102
                        if ( *t1 > *t2 ) return(-1);
×
3103
                        if ( *t1 < *t2 ) return(1);
×
3104
                        if ( t1[1] < t2[1] ) return(-1);
×
3105
                        if ( t1[1] > t2[1] ) return(1);
×
3106
                        t1 += 2; t2 += 2;
×
3107
                }
3108
                if ( t1 < ttt1 ) return(1);
×
3109
                if ( t2 < ttt2 ) return(-1);
×
3110
        }
3111
        if ( t1 < tt1 ) return(1);
×
3112
        if ( t2 < tt2 ) return(-1);
×
3113
        return(0);
3114
}
3115

3116
/*
3117
                 #] CompareHSymbols : 
3118
                 #[ ComPress :                                LONG ComPress(ss,n)
3119
*/
3120
/**
3121
 *                Gets a list of pointers to terms and compresses the terms.
3122
 *                In n it collects the number of terms and the return value
3123
 *                of the function is the space that is occupied.
3124
 *
3125
 *                We have to pay some special attention to the compression of
3126
 *                terms with a PolyFun. This PolyFun should occur only straight
3127
 *                before the coefficient, so we can use the same trick as for
3128
 *                the coefficient to sabotage compression of this object
3129
 *                (Replace in the history the function pointer by zero. This
3130
 *                is safe, because terms that would be identical otherwise would
3131
 *                have been added).
3132
 *
3133
 *                @param ss Array of pointers to terms to be compressed.
3134
 *                @param n  Number of pointers in ss.
3135
 *                @return   Total number of words needed for the compressed result.
3136
 */
3137

3138
LONG ComPress(WORD **ss, LONG *n)
3,395✔
3139
{
3140
        GETIDENTITY
2,223✔
3141
        WORD *t, *s, j, k;
3,395✔
3142
        LONG size = 0;
3,395✔
3143
        int newsize, i;
3,395✔
3144
/*
3145
                        #[ debug :
3146

3147
        WORD **sss = ss;
3148

3149
        if ( AP.DebugFlag ) {
3150
                UBYTE OutBuf[140];
3151
                MLOCK(ErrorMessageLock);
3152
                MesPrint("ComPress:");
3153
                AO.OutFill = AO.OutputLine = OutBuf;
3154
                AO.OutSkip = 3;
3155
                FiniLine();
3156
                ss = sss;
3157
                while ( *ss ) {
3158
                        s = *ss++;
3159
                        j = *s;
3160
                        if ( j < 0 ) {
3161
                                j = s[1] + 2;
3162
                        }
3163
                        while ( --j >= 0 ) {
3164
                                TalToLine((UWORD)(*s++)); TokenToLine((UBYTE *)"  ");
3165
                        }
3166
                        FiniLine();
3167
                }
3168
                AO.OutSkip = 0;
3169
                FiniLine();
3170
                MUNLOCK(ErrorMessageLock);
3171
                ss = sss;
3172
        }
3173

3174
                        #] debug : 
3175
*/
3176
        *n = 0;
3,395✔
3177
        if ( AT.SS == AT.S0 && !AR.NoCompress ) {
3,395✔
3178
                if ( AN.compressSize == 0 ) {
2,817✔
3179
                        if ( *ss ) { AN.compressSize = **ss + 64; }
7✔
3180
                        else       { AN.compressSize = AM.MaxTer/sizeof(WORD) + 2; }
×
3181
                        AN.compressSpace = (WORD *)Malloc1(AN.compressSize*sizeof(WORD),"Compression");
7✔
3182
                }
3183
                AN.compressSpace[0] = 0;
2,817✔
3184
                while ( *ss ) {
362,492✔
3185
                        k = 0;
359,675✔
3186
                        s = *ss;
359,675✔
3187
                        j = *s++;
359,675✔
3188
                        if ( j > AN.compressSize ) {
359,675✔
3189
                                newsize = j + 64;
×
3190
                                t = (WORD *)Malloc1(newsize*sizeof(WORD),"Compression");
×
3191
                                t[0] = 0;
×
3192
                                if ( AN.compressSpace ) {
×
3193
                                        for ( i = 0; i < *AN.compressSpace; i++ ) t[i] = AN.compressSpace[i];
×
3194
                                        M_free(AN.compressSpace,"Compression");
×
3195
                                }
3196
                                AN.compressSpace = t;
×
3197
                                AN.compressSize = newsize;
×
3198
                        }
3199
                        t = AN.compressSpace;
359,675✔
3200
                        i = *t - 1;
359,675✔
3201
                        *t++ = j; j--;
359,675✔
3202
                        if ( AR.PolyFun ) {
359,675✔
3203
                                WORD *polystop, *sa;
×
3204
                                sa = s + j;
×
3205
                                sa -= ABS(sa[-1]);
×
3206
                                polystop = s;
×
3207
                                while ( polystop < sa && *polystop != AR.PolyFun ) {
×
3208
                                        polystop += polystop[1];
×
3209
                                }
3210
                                while ( i > 0 && j > 0 && *s == *t && s < polystop ) {
×
3211
                                        i--; j--; s++; t++; k--;
×
3212
                                }
3213
                        }
3214
                        else {
3215
                                WORD *sa;
359,675✔
3216
                                sa = s + j;
359,675✔
3217
                                sa -= ABS(sa[-1]);
359,675✔
3218
                                while ( i > 0 && j > 0 && *s == *t && s < sa ) { i--; j--; s++; t++; k--; }
1,787,107✔
3219
                        }
3220
                        if ( k < -1 ) {
359,675✔
3221
                                s[-1] = j;
356,858✔
3222
                                s[-2] = k;
356,858✔
3223
                                *ss = s-2;
356,858✔
3224
                                size += j + 2;
356,858✔
3225
                        }
3226
                        else {
3227
                                size += *AN.compressSpace;
2,817✔
3228
                                if ( k == -1 ) { t--; s--; j++; }
2,817✔
3229
                        }
3230
                        while ( --j >= 0 ) *t++ = *s++;
1,809,643✔
3231
/*                                        Sabotage getting into the coefficient next time */
3232
                        t = AN.compressSpace + *AN.compressSpace;
359,675✔
3233
                        t[-(ABS(t[-1]))] = 0;
359,675✔
3234
                        ss++;
359,675✔
3235
                        (*n)++;
359,675✔
3236
                }
3237
        }
3238
        else {
3239
                while ( *ss ) {
8,572,590✔
3240
                        size += *(*ss++);
8,571,990✔
3241
                        (*n)++;
8,571,990✔
3242
                }
3243
        }
3244
/*
3245
                        #[ debug :
3246

3247
        if ( AP.DebugFlag ) {
3248
                UBYTE OutBuf[140];
3249
                AO.OutFill = AO.OutputLine = OutBuf;
3250
                AO.OutSkip = 3;
3251
                FiniLine();
3252
                ss = sss;
3253
                while ( *ss ) {
3254
                        s = *ss++;
3255
                        j = *s;
3256
                        if ( j < 0 ) {
3257
                                j = s[1] + 2;
3258
                        }
3259
                        while ( --j >= 0 ) {
3260
                                TalToLine((UWORD)(*s++)); TokenToLine((UBYTE *)"  ");
3261
                        }
3262
                        FiniLine();
3263
                }
3264
                AO.OutSkip = 0;
3265
                FiniLine();
3266
        }
3267

3268
                        #] debug : 
3269
*/
3270
        return(size);
3,395✔
3271
}
3272

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

3302
#ifdef NEWSPLITMERGE
3303

3304
LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
18,951,590✔
3305
{
3306
        GETBIDENTITY
3307
        SORTING *S = AT.SS;
18,951,590✔
3308
        WORD **pp3, **pp1, **pp2;
18,951,590✔
3309
        LONG i, newleft, newright, split;
18,951,590✔
3310

3311
        if ( number < 2 ) return(number);
18,951,590✔
3312
        if ( number == 2 ) {
16,460,490✔
3313
                pp1 = Pointer; pp2 = pp1 + 1;
8,710,180✔
3314
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
8,710,180✔
3315
                        pp3 = (WORD **)(*pp1); *pp1 = *pp2; *pp2 = (WORD *)pp3;
767,541✔
3316
                }
3317
                else if ( i == 0 ) {
7,942,620✔
3318
                  number--;
242,264✔
3319
                  if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) == 0 ) number = 0; }
242,264✔
3320
                  else               { if ( AddCoef(BHEAD pp1,pp2) == 0 ) number = 0; }
241,233✔
3321
                }
3322
                return(number);
8,710,180✔
3323
        }
3324
        split = number/2;
7,750,340✔
3325
        newleft  = SplitMerge(BHEAD Pointer,split);
7,750,340✔
3326
        newright = SplitMerge(BHEAD Pointer+split,number-split);
7,750,340✔
3327
        if ( newright == 0 ) return(newleft);
7,750,340✔
3328
/*
3329
        We compare the last of the left with the first of the right
3330
        If they are already in order, we will be done quickly.
3331
        We may have to compactify the buffer because the recursion may
3332
        have created holes. Also this compare may result in equal terms.
3333
        Addition of 23-jul-1999. It makes things a bit faster.
3334
*/
3335
        if ( newleft > 0 && newright > 0 &&
7,750,130✔
3336
        ( i = CompareTerms(BHEAD Pointer[newleft-1],Pointer[split],(WORD)0) ) >= 0 ) {
7,747,360✔
3337
                pp2 = Pointer+split; pp1 = Pointer+newleft-1;
7,092,160✔
3338
                if ( i == 0 ) {
7,092,160✔
3339
                  if ( S->PolyWise ) {
188,094✔
3340
                        if ( AddPoly(BHEAD pp1,pp2) > 0 ) pp1++;
1,305✔
3341
                        else newleft--;
13✔
3342
                  }
3343
                  else {               
3344
                        if ( AddCoef(BHEAD pp1,pp2) > 0 ) pp1++;
186,789✔
3345
                        else newleft--;
545✔
3346
                  }
3347
                  pp2++; newright--;
188,094✔
3348
                }
3349
                else pp1++;
6,904,060✔
3350
                newleft += newright;
7,092,160✔
3351
                if ( pp1 < pp2 ) {
7,092,160✔
3352
                        while ( --newright >= 0 ) *pp1++ = *pp2++;
207,104✔
3353
                }
3354
                return(newleft);
7,092,160✔
3355
        }
3356

3357
        if ( split >= AN.SplitScratchSize ) {
657,967✔
3358
                AN.SplitScratchSize = (split*3)/2+100;
779✔
3359
                if ( AN.SplitScratchSize > S->Terms2InSmall/2 )
779✔
3360
                         AN.SplitScratchSize = S->Terms2InSmall/2;
×
3361
                if ( AN.SplitScratch ) M_free(AN.SplitScratch,"AN.SplitScratch");
779✔
3362
                AN.SplitScratch = (WORD **)Malloc1(AN.SplitScratchSize*sizeof(WORD *),"AN.SplitScratch");
779✔
3363
        }
3364
        pp3 = AN.SplitScratch; pp1 = Pointer;
657,967✔
3365
        for ( i = 0; i < newleft; i++ ) *pp3++ = *pp1++;
9,357,686✔
3366
        AN.InScratch = newleft;
657,967✔
3367
        pp1 = AN.SplitScratch; pp2 = Pointer + split; pp3 = Pointer;
657,967✔
3368
/*
3369
                An improvement in the style of Timsort
3370
*/
3371
        while ( newleft > 8 ) {
680,569✔
3372
                LONG nnleft = newleft/2;
174,534✔
3373
                if ( ( i = CompareTerms(BHEAD pp1[nnleft],*pp2,(WORD)0) ) < 0 ) break;
174,534✔
3374
                pp3 += nnleft+1;
23,583✔
3375
                pp1 += nnleft+1;
23,583✔
3376
                newleft -= nnleft+1;
23,583✔
3377
                if ( i == 0 ) {
23,583✔
3378
                        if ( S->PolyWise ) { i = AddPoly(BHEAD pp3-1,pp2); }
981✔
3379
                        else               { i = AddCoef(BHEAD pp3-1,pp2); }
881✔
3380
                        if ( i == 0 ) pp3--;
981✔
3381
                        pp2++;
981✔
3382
                        newright--;
981✔
3383
                        break;
981✔
3384
                }
3385
        }
3386

3387
        while ( newleft > 0 && newright > 0 ) {
11,443,621✔
3388
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
10,785,649✔
3389
                        *pp3++ = *pp2++;
4,681,709✔
3390
                        newright--;
4,681,709✔
3391
                }
3392
                else if ( i > 0 ) {
6,103,940✔
3393
                        *pp3++ = *pp1++;
2,911,696✔
3394
                        newleft--;
2,911,696✔
3395
                }
3396
                else {
3397
                  if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3,192,254✔
3398
                  else {               if ( AddCoef(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3,182,223✔
3399
                  pp1++; pp2++; newleft--; newright--;
3,192,254✔
3400
                }
3401
        }
3402
        for ( i = 0; i < newleft; i++ ) *pp3++ = *pp1++;
2,798,299✔
3403
        if ( pp3 == pp2 ) {
657,967✔
3404
                pp3 += newright;
518,929✔
3405
        } else {
3406
                for ( i = 0; i < newright; i++ ) *pp3++ = *pp2++;
576,722✔
3407
        }
3408
        AN.InScratch = 0;
657,967✔
3409
        return(pp3 - Pointer);
657,967✔
3410
}
3411

3412
#else
3413

3414
LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
3415
{
3416
        GETBIDENTITY
3417
        SORTING *S = AT.SS;
3418
        WORD **pp3, **pp1, **pp2;
3419
        LONG nleft, nright, i, newleft, newright;
3420
        WORD **pptop;
3421

3422
        if ( number < 2 ) return(number);
3423
        if ( number == 2 ) {
3424
                pp1 = Pointer; pp2 = pp1 + 1;
3425
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
3426
                        pp3 = (WORD **)(*pp1); *pp1 = *pp2; *pp2 = (WORD *)pp3;
3427
                }
3428
                else if ( i == 0 ) {
3429
                  number--;
3430
                  if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) == 0 ) { number = 0; } }
3431
                  else {               if ( AddCoef(BHEAD pp1,pp2) == 0 ) { number = 0; } }
3432
                }
3433
                return(number);
3434
        }
3435
        pptop = Pointer + number;
3436
        nleft = number >> 1; nright = number - nleft;
3437
        newleft  = SplitMerge(BHEAD Pointer,nleft);
3438
        newright = SplitMerge(BHEAD Pointer+nleft,nright);
3439
/*
3440
        We compare the last of the left with the first of the right
3441
        If they are already in order, we will be done quickly.
3442
        We may have to compactify the buffer because the recursion may
3443
        have created holes. Also this compare may result in equal terms.
3444
        Addition of 23-jul-1999. It makes things a bit faster.
3445
*/
3446
        if ( newleft > 0 && newright > 0 &&
3447
        ( i = CompareTerms(BHEAD Pointer[newleft-1],Pointer[nleft],(WORD)0) ) >= 0 ) {
3448
                pp2 = Pointer+nleft; pp1 = Pointer+newleft-1;
3449
                if ( i == 0 ) {
3450
                  if ( S->PolyWise ) {
3451
                        if ( AddPoly(BHEAD pp1,pp2) > 0 ) pp1++;
3452
                        else newleft--;
3453
                  }
3454
                  else {               
3455
                        if ( AddCoef(BHEAD pp1,pp2) > 0 ) pp1++;
3456
                        else newleft--;
3457
                  }
3458
                  *pp2++ = 0; newright--;
3459
                }
3460
                else pp1++;
3461
                newleft += newright;
3462
                if ( pp1 < pp2 ) {
3463
                        while ( --newright >= 0 ) *pp1++ = *pp2++;
3464
                        while ( pp1 < pptop ) *pp1++ = 0;
3465
                }
3466
                return(newleft);
3467
        }
3468
        if ( nleft > AN.SplitScratchSize ) {
3469
                AN.SplitScratchSize = (nleft*3)/2+100;
3470
                if ( AN.SplitScratchSize > S->Terms2InSmall/2 )
3471
                         AN.SplitScratchSize = S->Terms2InSmall/2;
3472
                if ( AN.SplitScratch ) M_free(AN.SplitScratch,"AN.SplitScratch");
3473
                AN.SplitScratch = (WORD **)Malloc1(AN.SplitScratchSize*sizeof(WORD *),"AN.SplitScratch");
3474
        }
3475
        pp3 = AN.SplitScratch; pp1 = Pointer; i = nleft;
3476
        do { *pp3++ = *pp1; *pp1++ = 0; } while ( *pp1 && --i > 0 );
3477
        if ( i > 0 ) { *pp3 = 0; i--; }
3478
        AN.InScratch = nleft - i;
3479
        pp1 = AN.SplitScratch; pp2 = Pointer + nleft; pp3 = Pointer;
3480
        while ( nleft > 0 && nright > 0 && *pp1 && *pp2 ) {
3481
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
3482
                        *pp3++ = *pp2;
3483
                        *pp2++ = 0;
3484
                        nright--;
3485
                }
3486
                else if ( i > 0 ) {
3487
                        *pp3++ = *pp1;
3488
                        *pp1++ = 0;
3489
                        nleft--;
3490
                }
3491
                else {
3492
                  if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3493
                  else {               if ( AddCoef(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3494
                  *pp1++ = 0; *pp2++ = 0; nleft--; nright--;
3495
                }
3496
        }
3497
        while ( --nleft  >= 0 && *pp1 ) { *pp3++ = *pp1; *pp1++ = 0; }
3498
        while ( --nright >= 0 && *pp2 ) { *pp3++ = *pp2++; }
3499
        nleft = pp3 - Pointer;
3500
        while ( pp3 < pptop ) *pp3++ = 0;
3501
        AN.InScratch = 0;
3502
        return(nleft);
3503
}
3504

3505
#endif
3506

3507
/*
3508
                 #] SplitMerge : 
3509
                 #[ GarbHand :                                VOID GarbHand()
3510
*/
3511
/**
3512
 *                Garbage collection that takes place when the small extension is full
3513
 *                and we need to place more terms there.
3514
 *                When this is the case there are many holes in the small buffer and
3515
 *                the whole can be compactified.
3516
 *                The major complication is the buffer for SplitMerge.
3517
 *                There are to options for temporary memory:
3518
 *                1: find some buffer that has enough space (maybe in the large
3519
 *                   buffer).
3520
 *                2: allocate a buffer. Give it back afterwards of course.
3521
 *                If the small extension is properly dimensioned this routine should
3522
 *                be called very rarely. Most of the time it will be called when the
3523
 *                polyfun or polyratfun is active.
3524
 */
3525

3526
VOID GarbHand(VOID)
×
3527
{
3528
        GETIDENTITY
3529
        SORTING *S = AT.SS;
×
3530
        WORD **Point, *s2, *t, *garbuf, i;
×
3531
        LONG k, total = 0;
×
3532
        int tobereturned = 0;
×
3533
/*
3534
        Compute the size needed. Put it in total.
3535
*/
3536
#ifdef TESTGARB
3537
        MLOCK(ErrorMessageLock);
3538
        MesPrint("in:  S->sFill = %x, S->sTop2 = %x",S->sFill,S->sTop2);
3539
#endif
3540
        Point = S->sPointer;
×
3541
        k = S->sTerms;
×
3542
        while ( --k >= 0 ) {
×
3543
                if ( ( s2 = *Point++ ) != 0 ) { total += *s2; }
×
3544
        }
3545
        Point = AN.SplitScratch;
×
3546
        k = AN.InScratch;
×
3547
        while ( --k >= 0 ) {
×
3548
                if ( ( s2 = *Point++ ) != 0 ) { total += *s2; }
×
3549
        }
3550
#ifdef TESTGARB
3551
        MesPrint("total = %l, nterms = %l",2*total,AN.InScratch);
3552
        MUNLOCK(ErrorMessageLock);
3553
#endif
3554
/*
3555
        Test now whether it fits. If so deal with the problem inside
3556
        the memory at the tail of the large buffer.
3557
*/
3558
        if ( S->lBuffer != 0 && S->lFill + total <= S->lTop ) {
×
3559
                garbuf = S->lFill;
3560
        }
3561
        else {
3562
                garbuf = (WORD *)Malloc1(total*sizeof(WORD),"Garbage buffer");
×
3563
                tobereturned = 1;
×
3564
        }
3565
        t = garbuf;
×
3566
        Point = S->sPointer;
×
3567
        k = S->sTerms;
×
3568
        while ( --k >= 0 ) {
×
3569
                if ( *Point ) {
×
3570
                        s2 = *Point++;
×
3571
                        i = *s2;
×
3572
                        NCOPY(t,s2,i);
×
3573
                }
3574
                else { Point++; }
×
3575
        }
3576
        Point = AN.SplitScratch;
×
3577
        k = AN.InScratch;
×
3578
        while ( --k >= 0 ) {
×
3579
                if ( *Point ) {
×
3580
                        s2 = *Point++;
×
3581
                        i = *s2;
×
3582
                        NCOPY(t,s2,i);
×
3583
                }
3584
                else Point++;
×
3585
        }
3586
        s2 = S->sBuffer;
×
3587
        t = garbuf;
×
3588
        Point = S->sPointer;
×
3589
        k = S->sTerms;
×
3590
        while ( --k >= 0 ) {
×
3591
                if ( *Point ) {
×
3592
                        *Point++ = s2;
×
3593
                        i = *t;
×
3594
                        NCOPY(s2,t,i);
×
3595
                }
3596
                else { Point++; }
×
3597
        }
3598
        Point = AN.SplitScratch;
×
3599
        k = AN.InScratch;
×
3600
        while ( --k >= 0 ) {
×
3601
                if ( *Point ) {
×
3602
                        *Point++ = s2;
×
3603
                        i = *t;
×
3604
                        NCOPY(s2,t,i);
×
3605
                }
3606
                else Point++;
×
3607
        }
3608
        S->sFill = s2;
×
3609
#ifdef TESTGARB
3610
        MLOCK(ErrorMessageLock);
3611
        MesPrint("out: S->sFill = %x, S->sTop2 = %x",S->sFill,S->sTop2);
3612
        if ( S->sFill >= S->sTop2 ) {
3613
                MesPrint("We are in deep trouble");
3614
        }
3615
        MUNLOCK(ErrorMessageLock);
3616
#endif
3617
        if ( tobereturned ) M_free(garbuf,"Garbage buffer");
×
3618
        return;
×
3619
}
3620

3621
/*
3622
                 #] GarbHand : 
3623
                 #[ MergePatches :                        WORD MergePatches(par)
3624
*/
3625
/**
3626
 *        The general merge routine. Can be used for the large buffer
3627
 *        and the file merging. The array S->Patches tells where the patches
3628
 *        start S->pStop tells where they end (has to be computed first).
3629
 *        The end of a 'line to be merged' is indicated by a zero. If
3630
 *        the end is reached without running into a zero or a term
3631
 *        runs over the boundary of a patch it is a file merging operation
3632
 *        and a new piece from the file is read in.
3633
 *
3634
 *        @param par
3635
 *        If par == 0 the sort is for file -> outputfile.
3636
 *        If par == 1 the sort is for large buffer -> sortfile.
3637
 *        If par == 2 the sort is for large buffer -> outputfile.
3638
 *
3639
 */
3640

3641
WORD MergePatches(WORD par)
327✔
3642
{
3643
        GETIDENTITY
205✔
3644
        SORTING *S = AT.SS;
327✔
3645
        WORD **poin, **poin2, ul, k, i, im, *m1;
327✔
3646
        WORD *p, lpat, mpat, level, l1, l2, r1, r2, r3, c;
327✔
3647
        WORD *m2, *m3, r31, r33, ki, *rr;
327✔
3648
        UWORD *coef;
327✔
3649
        POSITION position;
327✔
3650
        FILEHANDLE *fin, *fout;
327✔
3651
        int fhandle;
327✔
3652
/*
3653
        UBYTE *s;
3654
*/
3655
#ifdef WITHZLIB
3656
        POSITION position2;
327✔
3657
        int oldgzipCompress = AR.gzipCompress;
327✔
3658
        if ( par == 2 ) {
327✔
3659
                AR.gzipCompress = 0;
91✔
3660
        }
3661
#endif
3662
        fin = &S->file;
327✔
3663
        fout = &(AR.FoStage4[0]);
327✔
3664
NewMerge:
343✔
3665
        coef = AN.SoScratC;
343✔
3666
        poin = S->poina; poin2 = S->poin2a;
343✔
3667
        rr = AR.CompressPointer;
343✔
3668
        *rr = 0;
343✔
3669
/*
3670
                 #[ Setup :
3671
*/
3672
        if ( par == 1 ) {
343✔
3673
                fout = &(S->file);
220✔
3674
                if ( fout->handle < 0 ) {
220✔
3675
FileMake:
19✔
3676
                        PUTZERO(AN.OldPosOut);
35✔
3677
                        if ( ( fhandle = CreateFile(fout->name) ) < 0 ) {
35✔
3678
                                MLOCK(ErrorMessageLock);
×
3679
                                MesPrint("Cannot create file %s",fout->name);
×
3680
                                MUNLOCK(ErrorMessageLock);
×
3681
                                goto ReturnError;
×
3682
                        }
3683
#ifdef GZIPDEBUG
3684
                        MLOCK(ErrorMessageLock);
3685
                        MesPrint("%w MergePatches created output file %s",fout->name);
3686
                        MUNLOCK(ErrorMessageLock);
3687
#endif
3688
                        fout->handle = fhandle;
35✔
3689
                        PUTZERO(fout->filesize);
35✔
3690
                        PUTZERO(fout->POposition);
35✔
3691
/*
3692
                        Should not be here?
3693
#ifdef WITHZLIB
3694
                        fout->ziobuffer = 0;
3695
#endif
3696
*/
3697
#ifdef ALLLOCK
3698
                        LOCK(fout->pthreadslock);
3699
#endif
3700
                        SeekFile(fout->handle,&(fout->filesize),SEEK_SET);
35✔
3701
#ifdef ALLLOCK
3702
                        UNLOCK(fout->pthreadslock);
3703
#endif
3704
                        S->fPatchN = 0;
35✔
3705
                        PUTZERO(S->fPatches[0]);
35✔
3706
                        fout->POfill = fout->PObuffer;        
35✔
3707
                        PUTZERO(fout->POposition);
35✔
3708
                }
3709
ConMer:
201✔
3710
                StageSort(fout);
280✔
3711
#ifdef WITHZLIB
3712
                if ( S == AT.S0 && AR.NoCompress == 0 && AR.gzipCompress > 0 )
277✔
3713
                        S->fpcompressed[S->fPatchN] = 1;
241✔
3714
                else
3715
                        S->fpcompressed[S->fPatchN] = 0;
36✔
3716
                SetupOutputGZIP(fout);
277✔
3717
#endif
3718
        }
3719
        else if ( par == 0 && S->stage4 > 0 ) {
123✔
3720
/*
3721
                We will have to do our job more than once.
3722
                Input is from S->file and output will go to AR.FoStage4.
3723
                The file corresponding to this last one must be made now.
3724
*/
3725
                AR.Stage4Name ^= 1;
16✔
3726
/*
3727
                s = (UBYTE *)(fout->name); while ( *s ) s++;
3728
                if ( AR.Stage4Name ) s[-1] += 1;
3729
                else                s[-1] -= 1;
3730
*/
3731
                S->iPatches = S->fPatches;
16✔
3732
                S->fPatches = S->inPatches;
16✔
3733
                S->inPatches = S->iPatches;
16✔
3734
                (S->inNum) = S->fPatchN;
16✔
3735
                AN.OldPosIn = AN.OldPosOut;
16✔
3736
#ifdef WITHZLIB
3737
                m1 = S->fpincompressed;
16✔
3738
                S->fpincompressed = S->fpcompressed;
16✔
3739
                S->fpcompressed = m1;
16✔
3740
                for ( i = 0; i < S->inNum; i++ ) {
56✔
3741
                        S->fPatchesStop[i] = S->iPatches[i+1];
40✔
3742
#ifdef GZIPDEBUG
3743
                        MLOCK(ErrorMessageLock);
3744
                        MesPrint("%w fPatchesStop[%d] = %10p",i,&(S->fPatchesStop[i]));
3745
                        MUNLOCK(ErrorMessageLock);
3746
#endif
3747
                }
3748
#endif
3749
                S->stage4 = 0;
16✔
3750
                goto FileMake;
16✔
3751
        }
3752
        else {
3753
#ifdef WITHZLIB
3754
/*
3755
                The next statement is just for now
3756
*/
3757
                AR.gzipCompress = 0;
107✔
3758
#endif
3759
                if ( par == 0 ) {
107✔
3760
                        S->iPatches = S->fPatches;
16✔
3761
                        S->inNum = S->fPatchN;
16✔
3762
#ifdef WITHZLIB
3763
                        m1 = S->fpincompressed;
16✔
3764
                        S->fpincompressed = S->fpcompressed;
16✔
3765
                        S->fpcompressed = m1;
16✔
3766
                        for ( i = 0; i < S->inNum; i++ ) {
65✔
3767
                                S->fPatchesStop[i] = S->fPatches[i+1];
49✔
3768
#ifdef GZIPDEBUG
3769
                                MLOCK(ErrorMessageLock);
3770
                                MesPrint("%w fPatchesStop[%d] = %10p",i,&(S->fPatchesStop[i]));
3771
                                MUNLOCK(ErrorMessageLock);
3772
#endif
3773
                        }
3774
#endif
3775
                }
3776
                fout = AR.outfile;
107✔
3777
        }
3778
        if ( par ) {                                /* Mark end of patches */
384✔
3779
                S->Patches[S->lPatch] = S->lFill;
308✔
3780
                for ( i = 0; i < S->lPatch; i++ ) {
3,676✔
3781
                        S->pStop[i] = S->Patches[i+1]-1;
3,368✔
3782
                    S->Patches[i] = (WORD *)(((UBYTE *)(S->Patches[i])) + AM.MaxTer);
3,368✔
3783
                }
3784
        }
3785
        else {        /* Load the patches */
3786
                S->lPatch = (S->inNum);
76✔
3787
#ifdef WITHMPI
3788
                if ( S->lPatch > 1 || ( (PF.exprtodo <0) && (fout == AR.outfile || fout == AR.hidefile ) ) ) {
3789
#else
3790
                if ( S->lPatch > 1 ) {
76✔
3791
#endif
3792
#ifdef WITHZLIB
3793
                        SetupAllInputGZIP(S);
71✔
3794
#endif
3795
                        p = S->lBuffer;
71✔
3796
                        for ( i = 0; i < S->lPatch; i++ ) {
331✔
3797
                                p = (WORD *)(((UBYTE *)p)+2*AM.MaxTer+COMPINC*sizeof(WORD));
260✔
3798
                                S->Patches[i] = p;
260✔
3799
                                p = (WORD *)(((UBYTE *)p) + fin->POsize);
260✔
3800
                                S->pStop[i] = m2 = p;
260✔
3801
#ifdef WITHZLIB
3802
                                PutIn(fin,&(S->iPatches[i]),S->Patches[i],&m2,i);
260✔
3803
#else
3804
                                ADDPOS(S->iPatches[i],PutIn(fin,&(S->iPatches[i]),S->Patches[i],&m2,i));
3805
#endif
3806
                        }
3807
                }
3808
        }
3809
        if ( fout->handle >= 0 ) {
384✔
3810
                PUTZERO(position);
277✔
3811
#ifdef ALLLOCK
3812
                LOCK(fout->pthreadslock);
3813
#endif
3814
                SeekFile(fout->handle,&position,SEEK_END);
277✔
3815
                ADDPOS(position,((fout->POfill-fout->PObuffer)*sizeof(WORD)));
277✔
3816
#ifdef ALLLOCK
3817
                UNLOCK(fout->pthreadslock);
3818
#endif
3819
        }
3820
        else {
3821
                SETBASEPOSITION(position,(fout->POfill-fout->PObuffer)*sizeof(WORD));
107✔
3822
        }
3823
/*
3824
                 #] Setup : 
3825

3826
        The old code had to be replaced because all output needs to go
3827
        through PutOut. For this we have to go term by term and keep
3828
        track of the compression.
3829
*/
3830
        if ( S->lPatch == 1 ) {        /* Single patch --> direct copy. Very rare. */
384✔
3831
                LONG length;
5✔
3832

3833
                if ( fout->handle < 0 ) if ( Sflush(fout) ) goto PatCall;
5✔
3834
                if ( par ) {                /* Memory to file */
5✔
3835
#ifdef WITHZLIB
3836
/*
3837
                        We fix here the problem that the thing needs to go through PutOut
3838
*/
3839
                        m2 = m1 = *S->Patches; /* The m2 is to keep the compiler from complaining */
×
3840
                        while ( *m1 ) {
×
3841
                                if ( *m1 < 0 ) { /* Need to uncompress */
×
3842
                                        i = -(*m1++); m2 += i; im = *m1+i+1;
×
3843
                                        while ( i > 0 ) { *m1-- = *m2--; i--; }
×
3844
                                        *m1 = im;
×
3845
                                }
3846
#ifdef WITHPTHREADS
3847
                                /* Check here (and in the following) that we are at ground level
3848
                                   (so S == AT.S0) to use PutToMaster. Control can reach here,
3849
                                   with AS.MasterSort, but with S != AT.S0, when the SortBots are
3850
                                   adding PolyRatFun and the sorting of their arguments requires
3851
                                   large buffer patches to be merged. In this case, terms escape
3852
                                   the PolyRatFun argument and end up at ground level, if we use
3853
                                   PutToMaster. */
3854
                                if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
3855
                                        im = PutToMaster(BHEAD m1);
3856
                                }
3857
                                else
3858
#endif
3859
                                if ( ( im = PutOut(BHEAD m1,&position,fout,1) ) < 0 ) goto ReturnError;
×
3860
                                ADDPOS(S->SizeInFile[par],im);
×
3861
                                m2 = m1;
×
3862
                                m1 += *m1;
×
3863
                        }
3864
#ifdef WITHPTHREADS
3865
                        if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
3866
                                PutToMaster(BHEAD 0);
3867
                        }
3868
                        else
3869
#endif
3870
                        if ( FlushOut(&position,fout,1) ) goto ReturnError;
×
3871
                        ADDPOS(S->SizeInFile[par],1);
×
3872
#else
3873
/* old code */
3874
                        length = (LONG)(*S->pStop)-(LONG)(*S->Patches)+sizeof(WORD);
3875
                        if ( WriteFile(fout->handle,(UBYTE *)(*S->Patches),length) != length )
3876
                                goto PatwCall;
3877
                        ADDPOS(position,length);
3878
                        ADDPOS(fout->POposition,length);
3879
                        ADDPOS(fout->filesize,length);
3880
                        ADDPOS(S->SizeInFile[par],length/sizeof(WORD));
3881
#endif
3882
                }
3883
                else {                                /* File to file */
3884
#ifdef WITHZLIB
3885
/*
3886
                        Note: if we change FRONTSIZE we need to make the minimum value
3887
                        of SmallEsize in AllocSort correspondingly larger or smaller.
3888
                        Theoretically we could get close to 2*AM.MaxTer!
3889
*/
3890
                        #define FRONTSIZE (2*AM.MaxTer)
3891
                        WORD *copybuf = (WORD *)(((UBYTE *)(S->sBuffer)) + FRONTSIZE);
5✔
3892
                        WORD *copytop;
5✔
3893
                        SetupAllInputGZIP(S);
5✔
3894
                        m1 = m2 = copybuf;
5✔
3895
                        position2 = S->iPatches[0];
5✔
3896
                        while ( ( length = FillInputGZIP(fin,&position2,
10✔
3897
                                        (UBYTE *)copybuf,
3898
                                        (S->SmallEsize*sizeof(WORD)-FRONTSIZE),0) ) > 0 ) {
5✔
3899
                                copytop = (WORD *)(((UBYTE *)copybuf)+length);
5✔
3900
                                while ( *m1 && ( ( *m1 > 0 && m1+*m1 < copytop ) ||
40,965✔
3901
                                ( *m1 < 0 && ( m1+1 < copytop ) && ( m1+m1[1]+1 < copytop ) ) ) )
40,955✔
3902
/*
3903
        22-jun-2013 JV  Extremely nasty bug that has been around for a while.
3904
                        What if the end is in the remaining part? We will loose terms!
3905
                                while ( *m1 && ( (WORD *)(((UBYTE *)(m1)) + AM.MaxTer ) < S->sTop2 ) )
3906
*/
3907
                                {
3908
                                        if ( *m1 < 0 ) { /* Need to uncompress */
40,960✔
3909
                                                i = -(*m1++); m2 += i; im = *m1+i+1;
40,955✔
3910
                                                while ( i > 0 ) { *m1-- = *m2--; i--; }
204,775✔
3911
                                                *m1 = im;
40,955✔
3912
                                        }
3913
#ifdef WITHPTHREADS
3914
                                        if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
32,768✔
3915
                                                im = PutToMaster(BHEAD m1);
3916
                                        }
3917
                                        else
3918
#endif
3919
                                        if ( ( im = PutOut(BHEAD m1,&position,fout,1) ) < 0 ) goto ReturnError;
40,960✔
3920
                                        ADDPOS(S->SizeInFile[par],im);
40,960✔
3921
                                        m2 = m1;
40,960✔
3922
                                        m1 += *m1;
40,960✔
3923
                                }
3924
                                if ( m1 < copytop && *m1 == 0 ) break;
5✔
3925
/*
3926
                                Now move the remaining part 'back'
3927
*/
3928
                            m3 = copybuf;
3929
                                m1 = copytop;
3930
                                while ( m1 > m2 ) *--m3 = *--m1;
×
3931
                                m2 = m3;
×
3932
                                m1 = m2 + *m2;
×
3933
                        }
3934
                        if ( length < 0 ) {
5✔
3935
                                MLOCK(ErrorMessageLock);
×
3936
                                MesPrint("Readerror");
×
3937
                                goto PatCall2;
×
3938
                        }
3939
#ifdef WITHPTHREADS
3940
                        if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
4✔
3941
                                PutToMaster(BHEAD 0);
3942
                        }
3943
                        else
3944
#endif
3945
                        if ( FlushOut(&position,fout,1) ) goto ReturnError;
5✔
3946
                        ADDPOS(S->SizeInFile[par],1);
5✔
3947
#else
3948
/* old code */
3949
                        SeekFile(fin->handle,&(S->iPatches[0]),SEEK_SET); /* needed for stage4 */
3950
                        while ( ( length = ReadFile(fin->handle,
3951
                                        (UBYTE *)(S->sBuffer),S->SmallEsize*sizeof(WORD)) ) > 0 ) {
3952
                                if ( WriteFile(fout->handle,(UBYTE *)(S->sBuffer),length) != length )
3953
                                        goto PatwCall;
3954
                                ADDPOS(position,length);
3955
                                ADDPOS(fout->POposition,length);
3956
                                ADDPOS(fout->filesize,length);
3957
                                ADDPOS(S->SizeInFile[par],length/sizeof(WORD));
3958
                        }
3959
                        if ( length < 0 ) {
3960
                                MLOCK(ErrorMessageLock);
3961
                                MesPrint("Readerror");
3962
                                goto PatCall2;
3963
                        }
3964
#endif
3965
                }
3966
                goto EndOfAll;
5✔
3967
        }
3968
        else if ( S->lPatch > 0 ) {
379✔
3969

3970
                /* More than one patch. Construct the tree. */
3971

3972
                lpat = 1;
3973
                do { lpat *= 2; } while ( lpat < S->lPatch );
1,073✔
3974
                mpat = ( lpat >> 1 ) - 1;
379✔
3975
                k = lpat - S->lPatch;
379✔
3976

3977
                /* k is the number of empty places in the tree. they will
3978
                   be at the even positions from 2 to 2*k */
3979

3980
                for ( i = 1; i < lpat; i++ ) {
3,738✔
3981
                        S->tree[i] = -1;
3,359✔
3982
                }
3983
                for ( i = 1; i <= k; i++ ) {
489✔
3984
                        im = ( i * 2 ) - 1;
110✔
3985
                        poin[im] = S->Patches[i-1];
110✔
3986
                        poin2[im] = poin[im] + *(poin[im]);
110✔
3987
                        S->used[i] = im;
110✔
3988
                        S->ktoi[im] = i-1;
110✔
3989
                        S->tree[mpat+i] = 0;
110✔
3990
                        poin[im-1] = poin2[im-1] = 0;
110✔
3991
                }
3992
                for ( i = (k*2)+1; i <= lpat; i++ ) {
3,897✔
3993
                        S->used[i-k] = i;
3,518✔
3994
                        S->ktoi[i] = i-k-1;
3,518✔
3995
                        poin[i] = S->Patches[i-k-1];
3,518✔
3996
                        poin2[i] = poin[i] + *(poin[i]);
3,518✔
3997
                }
3998
/*
3999
                the array poin tells the position of the i-th element of the S->tree
4000
                'S->used' is a stack with the S->tree elements that need to be entered
4001
                into the S->tree. at the beginning this is S->lPatch. during the
4002
                sort there will be only very few elements.
4003
                poin2 is the next value of poin. it has to be determined
4004
                before the comparisons as the position or the size of the
4005
                term indicated by poin may change.
4006
                S->ktoi translates a S->tree element back to its stream number.
4007

4008
                start the sort
4009
*/
4010
                level = S->lPatch;
379✔
4011

4012
                /* introduce one term */
4013
OneTerm:
9,876,170✔
4014
                k = S->used[level];
9,876,550✔
4015
                i = k + lpat - 1;
9,876,550✔
4016
                if ( !*(poin[k]) ) {
9,876,550✔
4017
                        do { if ( !( i >>= 1 ) ) goto EndOfMerge; } while ( !S->tree[i] );
6,987✔
4018
                        if ( S->tree[i] == -1 ) {
3,249✔
4019
                                S->tree[i] = 0;
12✔
4020
                                level--;
12✔
4021
                                goto OneTerm;
12✔
4022
                        }
4023
                        k = S->tree[i];
3,237✔
4024
                        S->used[level] = k;
3,237✔
4025
                        S->tree[i] = 0;
3,237✔
4026
                }
4027
/*
4028
                move terms down the tree
4029
*/
4030
                while ( i >>= 1 ) {
23,497,860✔
4031
                        if ( S->tree[i] > 0 ) {
13,743,550✔
4032
                                if ( ( c = CompareTerms(BHEAD poin[S->tree[i]],poin[k],(WORD)0) ) > 0 ) {
9,132,100✔
4033
/*
4034
                                        S->tree[i] is the smaller. Exchange and go on.
4035
*/
4036
                                        S->used[level] = S->tree[i];
31,381✔
4037
                                        S->tree[i] = k;
31,381✔
4038
                                        k = S->used[level];
31,381✔
4039
                                }
4040
                                else if ( !c ) {        /* Terms are equal */
9,100,720✔
4041
                                        S->TermsLeft--;
68,382✔
4042
/*
4043
                                                Here the terms are equal and their coefficients
4044
                                                have to be added.
4045
*/
4046
                                        l1 = *( m1 = poin[S->tree[i]] );
68,382✔
4047
                                        l2 = *( m2 = poin[k] );
68,382✔
4048
                                        if ( S->PolyWise ) {  /* Here we work with PolyFun */
68,382✔
4049
                                                WORD *tt1, *w;
×
4050
                                                tt1 = m1;
×
4051
                                                m1 += S->PolyWise;
×
4052
                                                m2 += S->PolyWise;
×
4053
                                                if ( S->PolyFlag == 2 ) {
×
4054
                                                        w = poly_ratfun_add(BHEAD m1,m2);
×
4055
                                                        if ( *tt1 + w[1] - m1[1] > AM.MaxTer/((LONG)sizeof(WORD)) ) {
×
4056
                                                                MLOCK(ErrorMessageLock);
×
4057
                                                                MesPrint("Term too complex in PolyRatFun addition. MaxTermSize of %10l is too small",AM.MaxTer);
×
4058
                                                                MUNLOCK(ErrorMessageLock);
×
NEW
4059
                                                                TERMINATE(-1);
×
4060
                                                        }
4061
                                                        AT.WorkPointer = w;
×
4062
                                                }
4063
                                                else {
4064
                                                        w = AT.WorkPointer;
×
4065
                                                        if ( w + m1[1] + m2[1] > AT.WorkTop ) {
×
4066
                                                                MLOCK(ErrorMessageLock);
×
4067
                                                                MesPrint("A WorkSpace of %10l is too small",AM.WorkSize);
×
4068
                                                                MUNLOCK(ErrorMessageLock);
×
NEW
4069
                                                                TERMINATE(-1);
×
4070
                                                        }
4071
                                                        AddArgs(BHEAD m1,m2,w);
×
4072
                                                }
4073
                                                r1 = w[1];
×
4074
                                                if ( r1 <= FUNHEAD
×
4075
                                                        || ( w[FUNHEAD] == -SNUMBER && w[FUNHEAD+1] == 0 ) )
×
4076
                                                                 { goto cancelled; }
×
4077
                                                if ( r1 == m1[1] ) {
×
4078
                                                        NCOPY(m1,w,r1);
×
4079
                                                }
4080
                                                else if ( r1 < m1[1] ) {
×
4081
                                                        r2 = m1[1] - r1;
×
4082
                                                        m2 = w + r1;
×
4083
                                                        m1 += m1[1];
×
4084
                                                        while ( --r1 >= 0 ) *--m1 = *--m2;
×
4085
                                                        m2 = m1 - r2;
×
4086
                                                        r1 = S->PolyWise;
×
4087
                                                        while ( --r1 >= 0 ) *--m1 = *--m2;
×
4088
                                                        *m1 -= r2;
×
4089
                                                        poin[S->tree[i]] = m1;
×
4090
                                                }
4091
                                                else {
4092
                                                        r2 = r1 - m1[1];
×
4093
                                                        m2 = tt1 - r2;
×
4094
                                                        r1 = S->PolyWise;
×
4095
                                                        m1 = tt1;
×
4096
                                                        *m1 += r2;
×
4097
                                                        poin[S->tree[i]] = m2;
×
4098
                                                        NCOPY(m2,m1,r1);
×
4099
                                                        r1 = w[1];
×
4100
                                                        NCOPY(m2,w,r1);
×
4101
                                                }
4102
                                        }
4103
#ifdef WITHFLOAT
4104
                                        else if ( AT.SortFloatMode ) {
68,382✔
4105
                                                WORD *term1, *term2;
×
4106
                                                term1 = poin[S->tree[i]];
×
4107
                                                term2 = poin[k];
×
4108
                                                if ( MergeWithFloat(BHEAD &term1,&term2) == 0 )
×
4109
                                                        goto cancelled;
×
4110
                                                poin[S->tree[i]] = term1;
×
4111
                                        }
4112
#endif
4113
                                        else {
4114
                                          r1 = *( m1 += l1 - 1 );
68,382✔
4115
                                          m1 -= ABS(r1) - 1;
68,382✔
4116
                                          r1 = ( ( r1 > 0 ) ? (r1-1) : (r1+1) ) >> 1;
68,382✔
4117
                                          r2 = *( m2 += l2 - 1 );
68,382✔
4118
                                          m2 -= ABS(r2) - 1;
68,382✔
4119
                                          r2 = ( ( r2 > 0 ) ? (r2-1) : (r2+1) ) >> 1;
68,382✔
4120

4121
                                          if ( AddRat(BHEAD (UWORD *)m1,r1,(UWORD *)m2,r2,coef,&r3) ) {
68,382✔
4122
                                                MLOCK(ErrorMessageLock);
×
4123
                                                MesCall("MergePatches");
×
4124
                                                MUNLOCK(ErrorMessageLock);
×
4125
                                                SETERROR(-1)
×
4126
                                          }
4127

4128
                                          if ( AN.ncmod != 0 ) {
68,382✔
4129
                                                if ( ( AC.modmode & POSNEG ) != 0 ) {
×
4130
                                                        NormalModulus(coef,&r3);
×
4131
                                                }
4132
                                                else if ( BigLong(coef,r3,(UWORD *)AC.cmod,ABS(AN.ncmod)) >= 0 ) {
×
4133
                                                        WORD ii;
×
4134
                                                        SubPLon(coef,r3,(UWORD *)AC.cmod,ABS(AN.ncmod),coef,&r3);
×
4135
                                                        coef[r3] = 1;
×
4136
                                                        for ( ii = 1; ii < r3; ii++ ) coef[r3+ii] = 0;
×
4137
                                                }
4138
                                          }
4139
                                          r3 *= 2;
68,382✔
4140
                                          r33 = ( r3 > 0 ) ? ( r3 + 1 ) : ( r3 - 1 );
68,382✔
4141
                                          if ( r3 < 0 ) r3 = -r3;
68,382✔
4142
                                          if ( r1 < 0 ) r1 = -r1;
68,382✔
4143
                                          r1 *= 2;
68,382✔
4144
                                          r31 = r3 - r1;
68,382✔
4145
                                          if ( !r3 ) {                /* Terms cancel */
68,382✔
4146
cancelled:
50,230✔
4147
                                                ul = S->used[level] = S->tree[i];
50,230✔
4148
                                                S->tree[i] = -1;
50,230✔
4149
/*
4150
                                                We skip to the next term in stream ul
4151
*/
4152
                                                im = *poin2[ul];
50,230✔
4153
                                                if ( im < 0 ) {
50,230✔
4154
                                                        r1 = poin2[ul][1] - im + 1;
50,137✔
4155
                                                        m1 = poin2[ul] + 2;
50,137✔
4156
                                                        m2 = poin[ul] - im + 1;
50,137✔
4157
                                                        while ( ++im <= 0 ) *--m1 = *--m2;
250,685✔
4158
                                                        *--m1 = r1;
50,137✔
4159
                                                        poin2[ul] = m1;
50,137✔
4160
                                                        im = r1;
50,137✔
4161
                                                }
4162
                                                poin[ul] = poin2[ul];
50,230✔
4163
                                                ki = S->ktoi[ul];
50,230✔
4164
                                                if ( !par && (poin[ul] + im + COMPINC) >= S->pStop[ki]
50,230✔
4165
                                                && im > 0 ) {
×
4166
#ifdef WITHZLIB
4167
                                                        PutIn(fin,&(S->iPatches[ki]),S->Patches[ki],&(poin[ul]),ki);
×
4168
#else
4169
                                                        ADDPOS(S->iPatches[ki],PutIn(fin,&(S->iPatches[ki]),
4170
                                                        S->Patches[ki],&(poin[ul]),ki));
4171
#endif
4172
                                                        poin2[ul] = poin[ul] + im;
×
4173
                                                }
4174
                                                else {
4175
                                                        poin2[ul] += im;
50,230✔
4176
                                                }
4177
                                                S->used[++level] = k;
50,230✔
4178
                                                S->TermsLeft--;
50,230✔
4179
                                          }
4180
                                          else if ( !r31 ) {                /* copy coef into term1 */
18,152✔
4181
                                                goto CopCof2;
18,152✔
4182
                                          }
4183
                                          else if ( r31 < 0 ) {                /* copy coef into term1
×
4184
                                                                                        and adjust the length of term1 */
4185
                                                goto CopCoef;
×
4186
                                          }
4187
                                          else {
4188
/*
4189
                                                        this is the dreaded calamity.
4190
                                                        is there enough space?
4191
*/
4192
                                                if( (poin[S->tree[i]]+l1+r31) >= poin2[S->tree[i]] ) {
×
4193
/*
4194
                                                                no space! now the special trick for which
4195
                                                                we left 2*maxlng spaces open at the beginning
4196
                                                                of each patch.
4197
*/
4198
                                                        if ( (l1 + r31) > AM.MaxTer/((LONG)sizeof(WORD)) ) {
×
4199
                                                                MLOCK(ErrorMessageLock);
×
4200
                                                                MesPrint("Coefficient overflow during sort");
×
4201
                                                                MUNLOCK(ErrorMessageLock);
×
4202
                                                                goto ReturnError;
×
4203
                                                        }
4204
                                                        m2 = poin[S->tree[i]];
×
4205
                                                        m3 = ( poin[S->tree[i]] -= r31 );
×
4206
                                                        do { *m3++ = *m2++; } while ( m2 < m1 );
×
4207
                                                        m1 = m3;
4208
                                                }
4209
CopCoef:
×
4210
                                                *(poin[S->tree[i]]) += r31;
×
4211
CopCof2:
18,152✔
4212
                                                m2 = (WORD *)coef; im = r3;
18,152✔
4213
                                                NCOPY(m1,m2,im);
54,456✔
4214
                                                *m1 = r33;
18,152✔
4215
                                          }
4216
                                        }
4217
/*
4218
                                        Now skip to the next term in stream k.
4219
*/
4220
NextTerm:
9,822,700✔
4221
                                        im = poin2[k][0];
9,822,700✔
4222
                                        if ( im < 0 ) {
9,822,700✔
4223
                                                r1 = poin2[k][1] - im + 1;
1,237,450✔
4224
                                                m1 = poin2[k] + 2;
1,237,450✔
4225
                                                m2 = poin[k] - im + 1;
1,237,450✔
4226
                                                while ( ++im <= 0 ) *--m1 = *--m2;
6,187,240✔
4227
                                                *--m1 = r1;
1,237,450✔
4228
                                                poin2[k] = m1;
1,237,450✔
4229
                                                im = r1;
1,237,450✔
4230
                                        }
4231
                                        poin[k] = poin2[k];
9,822,700✔
4232
                                        ki = S->ktoi[k];
9,822,700✔
4233
                                        if ( !par && ( (poin[k] + im + COMPINC) >= S->pStop[ki] )
9,822,700✔
4234
                                        && im > 0 ) {
×
4235
#ifdef WITHZLIB
4236
                                                PutIn(fin,&(S->iPatches[ki]),S->Patches[ki],&(poin[k]),ki);
×
4237
#else
4238
                                                ADDPOS(S->iPatches[ki],PutIn(fin,&(S->iPatches[ki]),
4239
                                                S->Patches[ki],&(poin[k]),ki));
4240
#endif
4241
                                                poin2[k] = poin[k] + im;
×
4242
                                        }
4243
                                        else {
4244
                                                poin2[k] += im;
9,822,700✔
4245
                                        }
4246
                                        goto OneTerm;
9,822,700✔
4247
                                }
4248
                        }
4249
                        else if ( S->tree[i] < 0 ) {
4,611,452✔
4250
                                S->tree[i] = k;
53,467✔
4251
                                level--;
53,467✔
4252
                                goto OneTerm;
53,467✔
4253
                        }
4254
                }
4255
/*
4256
                        found the smallest in the set. indicated by k.
4257
                        write to its destination.
4258
*/
4259
#ifdef WITHPTHREADS
4260
                if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
5,108,180✔
4261
                        im = PutToMaster(BHEAD poin[k]);
4,273,440✔
4262
                }
4263
                else
4264
#endif
4265
                if ( ( im = PutOut(BHEAD poin[k],&position,fout,1) ) < 0 ) {
5,480,866✔
4266
                        MLOCK(ErrorMessageLock);
×
4267
                        MesPrint("Called from MergePatches with k = %d (stream %d)",k,S->ktoi[k]);
×
4268
                        MUNLOCK(ErrorMessageLock);
×
4269
                        goto ReturnError;
×
4270
                }
4271
                ADDPOS(S->SizeInFile[par],im);
9,754,310✔
4272
                goto NextTerm;
9,754,310✔
4273
        }
4274
        else {
4275
                goto NormalReturn;
×
4276
        }
4277
EndOfMerge:
379✔
4278
#ifdef WITHPTHREADS
4279
                if ( AS.MasterSort && ( fout == AR.outfile ) && S == AT.S0 ) {
239✔
4280
                        PutToMaster(BHEAD 0);
10✔
4281
                }
4282
                else
4283
#endif
4284
        if ( FlushOut(&position,fout,1) ) goto ReturnError;
369✔
4285
        ADDPOS(S->SizeInFile[par],1);
379✔
4286
EndOfAll:
384✔
4287
        if ( par == 1 ) {        /* Set the fpatch pointers */
384✔
4288
#ifdef WITHZLIB
4289
                SeekFile(fout->handle,&position,SEEK_CUR);
217✔
4290
#endif
4291
                (S->fPatchN)++;
217✔
4292
                S->fPatches[S->fPatchN] = position;
217✔
4293
        }
4294
        if ( par == 0 && fout != AR.outfile ) {
384✔
4295
/*
4296
                        Output went to sortfile. We have two possibilities:
4297
                        1:        We are not finished with the current in-out cycle
4298
                                In that case we should pop to the next set of patches
4299
                        2:        We finished a cycle and should clean up the in file
4300
                                Then we restart the sort.
4301
*/
4302
                (S->fPatchN)++;
60✔
4303
                S->fPatches[S->fPatchN] = position;
60✔
4304
                if ( ISNOTZEROPOS(AN.OldPosIn) ) {                /* We are not done */
60✔
4305

4306
                        SeekFile(fin->handle,&(AN.OldPosIn),SEEK_SET);
44✔
4307
/*
4308
                        We don't need extra provisions for the zlib compression here.
4309
                        If part of an expression has been sorted, the whole has been so.
4310
                        This means that S->fpincompressed[] will remain the same
4311
*/
4312
                        if ( (ULONG)ReadFile(fin->handle,(UBYTE *)(&(S->inNum)),(LONG)sizeof(WORD)) !=
44✔
4313
                                sizeof(WORD)
4314
                          || (ULONG)ReadFile(fin->handle,(UBYTE *)(&AN.OldPosIn),(LONG)sizeof(POSITION)) !=
44✔
4315
                                sizeof(POSITION)
4316
                          || (ULONG)ReadFile(fin->handle,(UBYTE *)S->iPatches,(LONG)((S->inNum)+1)
88✔
4317
                                        *sizeof(POSITION)) != ((S->inNum)+1)*sizeof(POSITION) ) {
44✔
4318
                                MLOCK(ErrorMessageLock);
×
4319
                                MesPrint("Read error fourth stage sorting");
×
4320
                                MUNLOCK(ErrorMessageLock);
×
4321
                                goto ReturnError;
×
4322
                        }
4323
                        *rr = 0;
44✔
4324
#ifdef WITHZLIB
4325
                        for ( i = 0; i < S->inNum; i++ ) {
220✔
4326
                                S->fPatchesStop[i] = S->iPatches[i+1];
176✔
4327
#ifdef GZIPDEBUG
4328
                                MLOCK(ErrorMessageLock);
4329
                                MesPrint("%w fPatchesStop[%d] = %10p",i,&(S->fPatchesStop[i]));
4330
                                MUNLOCK(ErrorMessageLock);
4331
#endif
4332
                        }
4333
#endif
4334
                        goto ConMer;
44✔
4335
                }
4336
                else {
4337
/*
4338
                        if ( fin == &(AR.FoStage4[0]) ) {
4339
                                s = (UBYTE *)(fin->name); while ( *s ) s++;
4340
                                if ( AR.Stage4Name == 1 ) s[-1] -= 1;
4341
                                else                      s[-1] += 1;
4342
                        }
4343
*/
4344
/*                        TruncateFile(fin->handle); */
4345
                        UpdateMaxSize();
16✔
4346
#ifdef WITHZLIB
4347
                        ClearSortGZIP(fin);
16✔
4348
#endif
4349
                        CloseFile(fin->handle);
16✔
4350
                        remove(fin->name);                /* Gives diskspace free again. */
16✔
4351
#ifdef GZIPDEBUG
4352
                        MLOCK(ErrorMessageLock);
4353
                        MesPrint("%w MergePatches removed in file %s",fin->name);
4354
                        MUNLOCK(ErrorMessageLock);
4355
#endif
4356
/*
4357
                        if ( fin == &(AR.FoStage4[0]) ) {
4358
                                s = (UBYTE *)(fin->name); while ( *s ) s++;
4359
                                if ( AR.Stage4Name == 1 ) s[-1] += 1;
4360
                                else                      s[-1] -= 1;
4361
                        }
4362
*/
4363
                        fin->handle = -1;
16✔
4364
                        { FILEHANDLE *ff = fin; fin = fout; fout = ff; }
16✔
4365
                        PUTZERO(S->SizeInFile[0]);
16✔
4366
                        goto NewMerge;
16✔
4367
                }
4368
        }
4369
        if ( par == 0 ) {
324✔
4370
/*                TruncateFile(fin->handle); */
4371
                UpdateMaxSize();
16✔
4372
#ifdef WITHZLIB
4373
                ClearSortGZIP(fin);
16✔
4374
#endif
4375
                CloseFile(fin->handle);
16✔
4376
                remove(fin->name);
16✔
4377
                fin->handle = -1;
16✔
4378
#ifdef GZIPDEBUG
4379
                MLOCK(ErrorMessageLock);
4380
                MesPrint("%w MergePatches removed in file %s",fin->name);
4381
                MUNLOCK(ErrorMessageLock);
4382
#endif
4383
        }
4384
NormalReturn:
308✔
4385
#ifdef WITHZLIB
4386
        AR.gzipCompress = oldgzipCompress;
324✔
4387
#endif
4388
        return(0);
324✔
4389
ReturnError:
×
4390
#ifdef WITHZLIB
4391
        AR.gzipCompress = oldgzipCompress;
×
4392
#endif
4393
        return(-1);
×
4394
#ifndef WITHZLIB
4395
PatwCall:
4396
        MLOCK(ErrorMessageLock);
4397
        MesPrint("Error while writing to file.");
4398
        goto PatCall2;
4399
#endif
4400
PatCall:;
×
4401
        MLOCK(ErrorMessageLock);
×
4402
PatCall2:;
×
4403
        MesCall("MergePatches");
×
4404
        MUNLOCK(ErrorMessageLock);
×
4405
#ifdef WITHZLIB
4406
        AR.gzipCompress = oldgzipCompress;
×
4407
#endif
4408
        SETERROR(-1)
×
4409
}
4410

4411
/*
4412
                 #] MergePatches : 
4413
                 #[ StoreTerm :                                WORD StoreTerm(term)
4414
*/
4415
/**
4416
 *        The central routine to accept terms, store them and keep things
4417
 *        at least partially sorted. A call to EndSort will then complete
4418
 *        storing and sorting.
4419
 *
4420
 *        @param term The term to be stored
4421
 *        @return  Regular return conventions (OK -> 0)
4422
 */
4423

4424
WORD StoreTerm(PHEAD WORD *term)
19,898,030✔
4425
{
4426
        GETBIDENTITY
4427
        SORTING *S = AT.SS;
19,898,030✔
4428
        WORD **ss, *lfill, j, *t;
19,898,030✔
4429
        POSITION pp;
19,898,030✔
4430
        LONG lSpace, sSpace, RetCode, over, tover;
19,898,030✔
4431

4432
        if ( ( ( AP.PreDebug & DUMPTOSORT ) == DUMPTOSORT ) && AR.sLevel == 0 ) {
19,898,030✔
4433
#ifdef WITHPTHREADS
4434
                snprintf((char *)(THRbuf),100,"StoreTerm(%d)",AT.identity);
4435
                PrintTerm(term,(char *)(THRbuf));
4436
#else
4437
                PrintTerm(term,"StoreTerm");
4438
#endif
4439
        }
4440
        if ( AM.exitflag && AR.sLevel == 0 ) return(0);
19,898,030✔
4441
        S->sFill = *(S->PoinFill);
19,898,030✔
4442
        if ( S->sTerms >= S->TermsInSmall || ( S->sFill + *term ) >= S->sTop ) {
19,898,030✔
4443
/*
4444
        The small buffer is full. It has to be sorted and written.
4445
*/
4446
                tover = over = S->sTerms;
3,288✔
4447
                ss = S->sPointer;
3,288✔
4448
                ss[over] = 0;
3,288✔
4449
#ifdef SPLITTIME
4450
                PrintTime((UBYTE *)"Before SplitMerge");
4451
#endif
4452
                ss[SplitMerge(BHEAD ss,over)] = 0;
3,288✔
4453
#ifdef SPLITTIME
4454
                PrintTime((UBYTE *)"After SplitMerge");
4455
#endif
4456
                sSpace = 0;
3,288✔
4457
                if ( over > 0 ) {
3,288✔
4458
                        sSpace = ComPress(ss,&RetCode);
3,288✔
4459
                        S->TermsLeft -= over - RetCode;
3,288✔
4460
                }
4461
                sSpace++;
3,288✔
4462

4463
                lSpace = sSpace + (S->lFill - S->lBuffer)
3,288✔
4464
                                 - (AM.MaxTer/sizeof(WORD))*((LONG)S->lPatch);
3,288✔
4465
                SETBASEPOSITION(pp,lSpace);
3,288✔
4466
                MULPOS(pp,sizeof(WORD));
3,288✔
4467
                if ( S->file.handle >= 0 ) {
3,288✔
4468
                        ADD2POS(pp,S->fPatches[S->fPatchN]);
2,865✔
4469
                }
4470
                if ( S == AT.S0 ) {        /* Only statistics at ground level */
3,288✔
4471
                        WriteStats(&pp,STATSSPLITMERGE,CHECKLOGTYPE);
2,812✔
4472
                }
4473
                if ( ( S->lPatch >= S->MaxPatches ) ||
3,288✔
4474
                        ( ( (WORD *)(((UBYTE *)(S->lFill + sSpace)) + 2*AM.MaxTer ) ) >= S->lTop ) ) {
3,084✔
4475
/*
4476
                        The large buffer is too full. Merge and write it
4477
*/
4478
                        if ( MergePatches(1) ) goto StoreCall;
204✔
4479
/*
4480
                        pp = S->SizeInFile[1];
4481
                        ADDPOS(pp,sSpace);
4482
                        MULPOS(pp,sizeof(WORD));
4483
*/
4484
                        SETBASEPOSITION(pp,sSpace);
201✔
4485
                        MULPOS(pp,sizeof(WORD));
201✔
4486
                        ADD2POS(pp,S->fPatches[S->fPatchN]);
201✔
4487

4488
                        if ( S == AT.S0 ) {        /* Only statistics at ground level */
201✔
4489
                                WriteStats(&pp,STATSMERGETOFILE,CHECKLOGTYPE);
171✔
4490
                        }
4491
                        S->lPatch = 0;
201✔
4492
                        S->lFill = S->lBuffer;
201✔
4493
                }
4494
                S->Patches[S->lPatch++] = S->lFill;
3,285✔
4495
            lfill = (WORD *)(((UBYTE *)(S->lFill)) + AM.MaxTer);
3,285✔
4496
                if ( tover > 0 ) {
3,285✔
4497
                        ss = S->sPointer;
3,285✔
4498
                        while ( ( t = *ss++ ) != 0 ) {
7,608,530✔
4499
                                j = *t;
7,605,240✔
4500
                                if ( j < 0 ) j = t[1] + 2;
7,605,240✔
4501
                                while ( --j >= 0 ){
166,025,600✔
4502
                                  *lfill++ = *t++;
158,420,300✔
4503
                                }
4504
                        }
4505
                }
4506
                *lfill++ = 0;
3,285✔
4507
                S->lFill = lfill;
3,285✔
4508
                S->sTerms = 0;
3,285✔
4509
                S->PoinFill = S->sPointer;
3,285✔
4510
                *(S->PoinFill) = S->sFill = S->sBuffer;
3,285✔
4511
        }
4512
        j = *term;
19,898,030✔
4513
        while ( --j >= 0 ) *S->sFill++ = *term++;
338,019,500✔
4514
        S->sTerms++;
19,898,030✔
4515
        S->GenTerms++;
19,898,030✔
4516
        S->TermsLeft++;
19,898,030✔
4517
        *++S->PoinFill = S->sFill;
19,898,030✔
4518

4519
        return(0);
19,898,030✔
4520

4521
StoreCall:
×
4522
        MLOCK(ErrorMessageLock);
×
4523
        MesCall("StoreTerm");
×
4524
        MUNLOCK(ErrorMessageLock);
×
4525
        SETERROR(-1)
×
4526
}
4527

4528
/*
4529
                 #] StoreTerm : 
4530
                 #[ StageSort :                                VOID StageSort(FILEHANDLE *fout)
4531
*/
4532
/**
4533
 *                Prepares a stage 4 or higher sort.
4534
 *                Stage 4 sorts occur when the sort file contains more patches than
4535
 *                can be merged in one pass.
4536
 */
4537

4538
VOID StageSort(FILEHANDLE *fout)
280✔
4539
{
4540
        GETIDENTITY
187✔
4541
        SORTING *S = AT.SS;
280✔
4542
        if ( S->fPatchN >= S->MaxFpatches ) {
280✔
4543
                POSITION position;
47✔
4544
                if ( S != AT.S0 ) {
47✔
4545
/*
4546
                        There are no proper provisions for stage 4 or higher sorts
4547
                        for function arguments and $ variables. The reason:
4548
                        The current code maps out the patches, based on the size of
4549
                        the buffers in the FoStage4 structs, while they are used
4550
                        inside the S->file struct that may have far smaller buffers.
4551
                        By itself that might still be repairable, but it goes completely
4552
                        wrong when during the sort polyRatFuns have to be added and they
4553
                        would go into stage4 (very rare but possible).
4554
                        The only really correct solution would be to put FoStage4 structs
4555
                        in all sort levels. Messy. (JV 8-oct-2018).
4556
*/
4557
                        MLOCK(ErrorMessageLock);
3✔
4558
                        MesPrint("Currently Stage 4 sorts are not allowed for function arguments or $ variables.");
3✔
4559
                        MesPrint("Please increase correspondingsorting parameters (sub-) in the setup.");
3✔
4560
                        MUNLOCK(ErrorMessageLock);
3✔
4561
                        TERMINATE(-1);
3✔
4562
                }
4563
                PUTZERO(position);
44✔
4564
                MLOCK(ErrorMessageLock);
44✔
4565
#ifdef WITHPTHREADS
4566
                MesPrint("StageSort in thread %d",identity);
28✔
4567
#elif defined(WITHMPI)
4568
                MesPrint("StageSort in process %d",PF.me);
4569
#else
4570
                MesPrint("StageSort");
16✔
4571
#endif
4572
                MUNLOCK(ErrorMessageLock);
44✔
4573
                SeekFile(fout->handle,&position,SEEK_END);
44✔
4574
/*
4575
                No extra compression data has to be written.
4576
                S->fpincompressed should remain valid.
4577
*/
4578
                if ( (ULONG)WriteFile(fout->handle,(UBYTE *)(&(S->fPatchN)),(LONG)sizeof(WORD)) !=
44✔
4579
                        sizeof(WORD)
4580
                  || (ULONG)WriteFile(fout->handle,(UBYTE *)(&(AN.OldPosOut)),(LONG)sizeof(POSITION)) !=
44✔
4581
                        sizeof(POSITION)
4582
                  || (ULONG)WriteFile(fout->handle,(UBYTE *)(S->fPatches),(LONG)(S->fPatchN+1)
88✔
4583
                                        *sizeof(POSITION)) != (S->fPatchN+1)*sizeof(POSITION) ) {
44✔
4584
                        MLOCK(ErrorMessageLock);
×
4585
                        MesPrint("Write error while staging sort. Disk full?");
×
4586
                        MUNLOCK(ErrorMessageLock);
×
NEW
4587
                        TERMINATE(-1);
×
4588
                }
4589
                AN.OldPosOut = position;
44✔
4590
                fout->filesize = position;
44✔
4591
                ADDPOS(fout->filesize,(S->fPatchN+2)*sizeof(POSITION) + sizeof(WORD));
44✔
4592
                fout->POposition = fout->filesize;
44✔
4593
                S->fPatches[0] = fout->filesize;
44✔
4594
                S->fPatchN = 0;
44✔
4595

4596
                if ( AR.FoStage4[0].PObuffer == 0 ) {
44✔
4597
                        AR.FoStage4[0].PObuffer = (WORD *)Malloc1(AR.FoStage4[0].POsize*sizeof(WORD)
7✔
4598
                                                                                                ,"Stage 4 buffer");
4599
                        AR.FoStage4[0].POfill   = AR.FoStage4[0].PObuffer;
7✔
4600
                        AR.FoStage4[0].POstop   = AR.FoStage4[0].PObuffer
7✔
4601
                                                 + AR.FoStage4[0].POsize/sizeof(WORD);
7✔
4602
#ifdef WITHPTHREADS
4603
                        AR.FoStage4[0].pthreadslock = dummylock;
6✔
4604
#endif
4605
                }
4606
                if ( AR.FoStage4[1].PObuffer == 0 ) {
44✔
4607
                        AR.FoStage4[1].PObuffer = (WORD *)Malloc1(AR.FoStage4[1].POsize*sizeof(WORD)
7✔
4608
                                                                                                ,"Stage 4 buffer");
4609
                        AR.FoStage4[1].POfill   = AR.FoStage4[1].PObuffer;
7✔
4610
                        AR.FoStage4[1].POstop   = AR.FoStage4[1].PObuffer
7✔
4611
                                                 + AR.FoStage4[1].POsize/sizeof(WORD);
7✔
4612
#ifdef WITHPTHREADS
4613
                        AR.FoStage4[1].pthreadslock = dummylock;
6✔
4614
#endif
4615
                }
4616
                S->stage4 = 1;
44✔
4617
        }
4618
}
277✔
4619

4620
/*
4621
                 #] StageSort : 
4622
                 #[ SortWild :                                WORD SortWild(w,nw)
4623
*/
4624
/**
4625
 *        Sorts the wildcard entries in the parameter w. Double entries
4626
 *        are removed. Full space taken is nw words.
4627
 *        Routine serves for the reading of wildcards in the compiler.
4628
 *        The entries come in the format:
4629
 *        (type,4,number,0) in which the zero is reserved for the
4630
 *        future replacement of 'number'.
4631
 *
4632
 *        @param w  buffer with wildcard entries.
4633
 *        @param nw number of wildcard entries.
4634
 *        @return  Normal conventions (OK -> 0)
4635
 */
4636

4637
WORD SortWild(WORD *w, WORD nw)
5,895✔
4638
{
4639
        GETIDENTITY
1,690✔
4640
        WORD *v, *s, *m, k, i;
5,895✔
4641
        WORD *pScrat, *stop, *sv, error = 0;
5,895✔
4642
        pScrat = AT.WorkPointer;
5,895✔
4643
        if ( ( AT.WorkPointer + 8 * AM.MaxWildcards ) >= AT.WorkTop ) {
5,895✔
4644
                MLOCK(ErrorMessageLock);
×
4645
                MesWork();
×
4646
                MUNLOCK(ErrorMessageLock);
×
4647
                return(-1);
×
4648
        }
4649
        stop = w + nw;
5,895✔
4650
        i = 0;
5,895✔
4651
        while ( i < nw ) {
22,892✔
4652
                m = w + i;
16,997✔
4653
                v = m + m[1];
16,997✔
4654
                while ( v < stop && (
29,450✔
4655
                         *v == FROMSET || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
23,681✔
4656
                while ( v < stop ) {
40,524✔
4657
                        if ( *v >= 0 ) {
23,527✔
4658
                                if ( AM.Ordering[*v] < AM.Ordering[*m] ) {
22,512✔
4659
                                        m = v;
4660
                                }
4661
                                else if ( *v == *m ) {
22,001✔
4662
                                        if ( v[2] < m[2] ) {
20,965✔
4663
                                                m = v;
4664
                                        }
4665
                                        else if ( v[2] == m[2] ) {
20,944✔
4666
                                                s = m + m[1];
112✔
4667
                                                sv = v + v[1];
112✔
4668
                                                if ( s < stop && ( *s == FROMSET
112✔
4669
                                                 || *s == SETTONUM || *s == LOADDOLLAR ) ) {
112✔
4670
                                                        if ( sv < stop && ( *sv == FROMSET
×
4671
                                                        || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
×
4672
                                                                if ( s[2] != sv[2] ) {
×
4673
                                                                        error = -1;
×
4674
                                                                        MLOCK(ErrorMessageLock);
×
4675
                                                                        MesPrint("&Wildcard set conflict");
×
4676
                                                                        MUNLOCK(ErrorMessageLock);
×
4677
                                                                }
4678
                                                        }
4679
                                                        *v = -1;
×
4680
                                                }
4681
                                                else {
4682
                                                        if ( sv < stop && ( *sv == FROMSET
112✔
4683
                                                        || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
56✔
4684
                                                                *m = -1;
×
4685
                                                                m = v;
×
4686
                                                        }
4687
                                                        else {
4688
                                                                *v = -1;
112✔
4689
                                                        }
4690
                                                }
4691
                                        }
4692
                                }
4693
                        }
4694
                        v += v[1];
23,527✔
4695
                        while ( v < stop && ( *v == FROMSET
42,350✔
4696
                         || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
31,122✔
4697
                }
4698
                s = pScrat;
16,997✔
4699
                v = m;
16,997✔
4700
                k = m[1];
16,997✔
4701
                NCOPY(s,m,k);
84,985✔
4702
                while ( m < stop && ( *m == FROMSET
53,117✔
4703
                 || *m == SETTONUM || *m == LOADDOLLAR ) ) {
23,639✔
4704
                        k = m[1];
12,481✔
4705
                        NCOPY(s,m,k);
79,402✔
4706
                }
4707
                *v = -1;
16,997✔
4708
                pScrat = s;
16,997✔
4709
                i = 0;
16,997✔
4710
                while ( i < nw && ( w[i] < 0 || w[i] == FROMSET
87,145✔
4711
                || w[i] == SETTONUM || w[i] == LOADDOLLAR ) ) i += w[i+1];
81,250✔
4712
        }
4713
        AC.NwildC = k = WORDDIF(pScrat,AT.WorkPointer);
5,895✔
4714
        s = AT.WorkPointer;
5,895✔
4715
        m = w;
5,895✔
4716
        NCOPY(m,s,k);
123,807✔
4717
        AC.WildC = m;
5,895✔
4718
        return(error);
5,895✔
4719
}
4720

4721
/*
4722
                 #] SortWild : 
4723
                 #[ CleanUpSort :                        VOID CleanUpSort(num)
4724
*/
4725
/**
4726
 *                Partially or completely frees function sort buffers.
4727
 */
4728

4729
void CleanUpSort(int num)
5,153✔
4730
{
4731
        GETIDENTITY
1,506✔
4732
        SORTING *S;
5,153✔
4733
        int minnum = num, i;
5,153✔
4734
        if ( AN.FunSorts ) {
5,153✔
4735
                if ( num == -1 ) {
4,936✔
4736
                        if ( AN.MaxFunSorts > 3 ) {
3,273✔
4737
                                minnum = (AN.MaxFunSorts+4)/2;
1,669✔
4738
                        }
4739
                        else minnum = 4;
4740
                }
4741
                else if ( minnum == 0 ) minnum = 1;
1,663✔
4742
                for ( i = minnum; i < AN.NumFunSorts; i++ ) {
483,781✔
4743
                        S = AN.FunSorts[i];
478,845✔
4744
                        if ( S ) {
478,845✔
4745
                                if ( S->file.handle >= 0 ) {
1,043✔
4746
/*                                        TruncateFile(S->file.handle); */
4747
                                        UpdateMaxSize();
3✔
4748
#ifdef WITHZLIB
4749
                                        ClearSortGZIP(&(S->file));
3✔
4750
#endif
4751
                                        CloseFile(S->file.handle);
3✔
4752
                                        S->file.handle = -1;
3✔
4753
                                        remove(S->file.name);
3✔
4754
#ifdef GZIPDEBUG
4755
                                        MLOCK(ErrorMessageLock);
4756
                                        MesPrint("%w CleanUpSort removed file %s",S->file.name);
4757
                                        MUNLOCK(ErrorMessageLock);
4758
#endif
4759
                                }
4760
                                M_free(S,"sorting struct");
1,043✔
4761
                        }
4762
                        AN.FunSorts[i] = 0;
478,845✔
4763
                }
4764
                AN.MaxFunSorts = minnum;
4,936✔
4765
                if ( num == 0 ) {
4,936✔
4766
                        S = AN.FunSorts[0];
1,663✔
4767
                        if ( S ) {
1,663✔
4768
                                if ( S->file.handle >= 0 ) {
1,663✔
4769
/*                                        TruncateFile(S->file.handle); */
4770
                                        UpdateMaxSize();
×
4771
#ifdef WITHZLIB
4772
                                        ClearSortGZIP(&(S->file));
×
4773
#endif
4774
                                        CloseFile(S->file.handle);
×
4775
                                        S->file.handle = -1;
×
4776
                                        remove(S->file.name);
×
4777
#ifdef GZIPDEBUG
4778
                                        MLOCK(ErrorMessageLock);
4779
                                        MesPrint("%w CleanUpSort removed file %s",S->file.name);
4780
                                        MUNLOCK(ErrorMessageLock);
4781
#endif
4782
                                }
4783
                        }
4784
                }
4785
        }
4786
        for ( i = 0; i < 2; i++ ) {
15,459✔
4787
                if ( AR.FoStage4[i].handle >= 0 ) {
10,306✔
4788
                        UpdateMaxSize();
×
4789
#ifdef WITHZLIB
4790
                        ClearSortGZIP(&(AR.FoStage4[i]));
×
4791
#endif
4792
                        CloseFile(AR.FoStage4[i].handle);
×
4793
                        remove(AR.FoStage4[i].name);
×
4794
                        AR.FoStage4[i].handle = -1;
×
4795
#ifdef GZIPDEBUG
4796
                        MLOCK(ErrorMessageLock);
4797
                        MesPrint("%w CleanUpSort removed stage4 file %s",AR.FoStage4[i].name);
4798
                        MUNLOCK(ErrorMessageLock);
4799
#endif
4800
                }
4801
        }
4802
}
5,153✔
4803

4804
/*
4805
                 #] CleanUpSort : 
4806
                 #[ LowerSortLevel :         VOID LowerSortLevel()
4807
*/
4808
/**
4809
 *                Lowers the level in the sort system.
4810
 */
4811

4812
VOID LowerSortLevel(VOID)
8,917✔
4813
{
4814
        GETIDENTITY
2,580✔
4815
        if ( AR.sLevel >= 0 ) {
8,917✔
4816
                AR.sLevel--;
8,917✔
4817
                if ( AR.sLevel >= 0 ) AT.SS = AN.FunSorts[AR.sLevel];
8,917✔
4818
        }
4819
}
8,917✔
4820

4821
/*
4822
                 #] LowerSortLevel : 
4823
                 #[ PolyRatFunSpecial :
4824

4825
                Keeps only the most divergent term in AR.PolyFunVar
4826
                We assume that the terms are already in that notation.
4827
*/
4828

4829
WORD *PolyRatFunSpecial(PHEAD WORD *t1, WORD *t2)
×
4830
{
4831
        WORD *oldworkpointer = AT.WorkPointer, *t, *r;
×
4832
        WORD exp1, exp2;
×
4833
        int i;
×
4834
        t = t1+FUNHEAD;
×
4835
        if ( *t == -SYMBOL ) {
×
4836
                if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
4837
                exp1 = 1;
×
4838
                if ( t[2] != -SNUMBER ) goto Illegal;
×
4839
                t[3] = 1;
×
4840
        }
4841
        else if ( *t == -SNUMBER ) {
×
4842
                t[1] = 1;
×
4843
                t += 2;
×
4844
                if ( *t == -SYMBOL ) {
×
4845
                        if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
4846
                        exp1 = -1;
4847
                }
4848
                else if ( *t == -SNUMBER ) {
×
4849
                        t[1] = 1;
×
4850
                        exp1 = 0;
×
4851
                }
4852
                else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
4853
                        && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
4854
                        t[ARGHEAD+5] = 1;
×
4855
                        t[ARGHEAD+6] = 1;
×
4856
                        t[ARGHEAD+7] = 3;
×
4857
                        exp1 = -t[ARGHEAD+4];
×
4858
                }
4859
                else goto Illegal;
×
4860
        }
4861
        else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
4862
                && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
4863
                t[ARGHEAD+5] = 1;
×
4864
                t[ARGHEAD+6] = 1;
×
4865
                t[ARGHEAD+7] = 3;
×
4866
                exp1 = t[ARGHEAD+4];
×
4867
                t += *t;
×
4868
                if ( *t != -SNUMBER ) goto Illegal;
×
4869
                t[1] = 1;
×
4870
        }
4871
        else goto Illegal;
×
4872

4873
        t = t2+FUNHEAD;
×
4874
        if ( *t == -SYMBOL ) {
×
4875
                if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
4876
                exp2 = 1;
×
4877
                if ( t[2] != -SNUMBER ) goto Illegal;
×
4878
                t[3] = 1;
×
4879
        }
4880
        else if ( *t == -SNUMBER ) {
×
4881
                t[1] = 1;
×
4882
                t += 2;
×
4883
                if ( *t == -SYMBOL ) {
×
4884
                        if ( t[1] != AR.PolyFunVar ) goto Illegal;
×
4885
                        exp2 = -1;
4886
                }
4887
                else if ( *t == -SNUMBER ) {
×
4888
                        t[1] = 1;
×
4889
                        exp2 = 0;
×
4890
                }
4891
                else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
4892
                        && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
4893
                        t[ARGHEAD+5] = 1;
×
4894
                        t[ARGHEAD+6] = 1;
×
4895
                        t[ARGHEAD+7] = 3;
×
4896
                        exp2 = -t[ARGHEAD+4];
×
4897
                }
4898
                else goto Illegal;
×
4899
        }
4900
        else if ( *t == ARGHEAD+8 && t[ARGHEAD] == 8 && t[ARGHEAD+1] == SYMBOL
×
4901
                && t[ARGHEAD+3] == AR.PolyFunVar ) {
×
4902
                t[ARGHEAD+5] = 1;
×
4903
                t[ARGHEAD+6] = 1;
×
4904
                t[ARGHEAD+7] = 3;
×
4905
                exp2 = t[ARGHEAD+4];
×
4906
                t += *t;
×
4907
                if ( *t != -SNUMBER ) goto Illegal;
×
4908
                t[1] = 1;
×
4909
        }
4910
        else goto Illegal;
×
4911

4912
        if ( exp1 <= exp2 ) { i = t1[1]; r = t1; }
×
4913
        else                { i = t2[1]; r = t2; }
×
4914
        t = oldworkpointer;
4915
        NCOPY(t,r,i)
×
4916

4917
        return(oldworkpointer);
4918
Illegal:
×
4919
        MesPrint("Illegal occurrence of PolyRatFun with divergent option");
×
NEW
4920
        TERMINATE(-1);
×
4921
        return(0);
×
4922
}
4923

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

4928
                Sorts an array of WORDs. No adding of equal objects.
4929
*/
4930

4931
VOID SimpleSplitMergeRec(WORD *array,WORD num,WORD *auxarray)
×
4932
{
4933
        WORD n1,n2,i,j,k,*t1,*t2;
×
4934
        if ( num < 2 ) return;
×
4935
        if ( num == 2 ) {
×
4936
                if ( array[0] > array[1] ) {
×
4937
                        EXCH(array[0],array[1])
×
4938
                }
4939
                return;
×
4940
        }
4941
        n1 = num/2;
×
4942
        n2 = num - n1;
×
4943
        SimpleSplitMergeRec(array,n1,auxarray);
×
4944
        SimpleSplitMergeRec(array+n1,n2,auxarray);
×
4945
        if ( array[n1-1] <= array[n1] ) return;
×
4946

4947
        t1 = array; t2 = auxarray; i = n1; NCOPY(t2,t1,i);
×
4948
        i = 0; j = n1; k = 0;
4949
        while ( i < n1 && j < num ) {
×
4950
                if ( auxarray[i] <= array[j] ) { array[k++] = auxarray[i++]; }
×
4951
                else { array[k++] = array[j++]; }
×
4952
        }
4953
        while ( i < n1 ) array[k++] = auxarray[i++];
×
4954
/*
4955
        Remember: remnants of j are still in place!
4956
*/
4957
}
4958

4959
VOID SimpleSplitMerge(WORD *array,WORD num)
×
4960
{
4961
        WORD *auxarray = Malloc1(sizeof(WORD)*num/2,"SimpleSplitMerge");
×
4962
        SimpleSplitMergeRec(array,num,auxarray);
×
4963
        M_free(auxarray,"SimpleSplitMerge");
×
4964
}
×
4965

4966
/*
4967
                 #] SimpleSplitMerge : 
4968
                 #[ BinarySearch :
4969

4970
                Searches in the sorted array with length num for the object x.
4971
                If x is in the list, it returns the number of the array element
4972
                that matched. If it is not in the list, it returns -1.
4973
                If there are identical objects in the list, which one will
4974
                match is quasi random.
4975
*/
4976

4977
WORD BinarySearch(WORD *array,WORD num,WORD x)
×
4978
{
4979
        WORD i, bot, top, med;
×
4980
        if ( num < 8 ) {
×
4981
                for ( i = 0; i < num; i++ ) if ( array[i] == x ) return(i);
×
4982
                return(-1);
4983
        }
4984
        if ( array[0] > x || array[num-1] < x ) return(-1);
×
4985
        bot = 0; top = num-1; med = (top+bot)/2;
×
4986
        do {
×
4987
                if ( array[med] == x ) return(med);
×
4988
                if ( array[med] < x ) { bot = med+1; }
×
4989
                else { top = med-1; }
×
4990
                med = (top+bot)/2;
×
4991
        } while ( med >= bot && med <= top );
×
4992
        return(-1);
4993
}
4994

4995
/*
4996
                 #] BinarySearch : 
4997
        #] SortUtilities :
4998
*/
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