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

vermaseren / form / 9173760979

21 May 2024 11:16AM UTC coverage: 48.988% (+0.2%) from 48.764%
9173760979

push

github

tueda
ci: add test jobs for tform/tvorm -w2

Add a variable "nthreads" to the configurations of "check",
"valgrind-check", "coverage" and "check-i386" jobs.
This variable specifies the number of threads in tform/tvorm jobs.
Now "-w2" is tested in addition to the default "-w4".

40556 of 82788 relevant lines covered (48.99%)

821279.54 hits per line

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

58.4
/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)
6,436✔
96
{
97
        GETIDENTITY
3,733✔
98
        LONG millitime, y = 0x7FFFFFFFL >> 1;
6,436✔
99
        WORD timepart;
6,436✔
100
        SORTING *S;
6,436✔
101
        POSITION pp;
6,436✔
102
        int use_wtime;
6,436✔
103
        if ( AT.SS == AT.S0 && AC.StatsFlag ) {
6,436✔
104
#ifdef WITHPTHREADS
105
                if ( AC.ThreadStats == 0 && identity > 0 ) return;
3,657✔
106
#elif defined(WITHMPI)
107
                if ( AC.OldParallelStats ) return;
793✔
108
                if ( ! AC.ProcessStats && PF.me != MASTER ) return;
793✔
109
#endif
110
                if ( Expressions == 0 ) return;
6,290✔
111

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

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

121
                MLOCK(ErrorMessageLock);
3,463✔
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,463✔
127
                if ( checkLogType && AM.LogType ) {
3,463✔
128
                        AC.LogHandle = -1;
181✔
129
                }
130

131
                if ( AC.ShortStats ) {}
3,463✔
132
                else {
133
#ifdef WITHPTHREADS
134
                        if ( identity > 0 ) {
1,765✔
135
                                MesPrint("             Thread %d reporting",identity);
133✔
136
                        }
137
                        else {
138
                                MesPrint("");
1,632✔
139
                        }
140
#elif defined(WITHMPI)
141
                        if ( PF.me != MASTER ) {
787✔
142
                                MesPrint("             Process %d reporting",PF.me);
2✔
143
                        }
144
                        else {
145
                                MesPrint("");
785✔
146
                        }
147
#else
148
                        MesPrint("");
895✔
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,463✔
158
#if defined(WITHPTHREADS)
159
                if ( use_wtime && identity > 0 ) use_wtime = 0;
1,773✔
160
#elif defined(WITHMPI)
161
                if ( use_wtime && PF.me != MASTER ) use_wtime = 0;
791✔
162
#endif
163
                millitime = use_wtime ? TimeWallClock(1) * 10 : TimeCPU(1);
3,463✔
164
                timepart = (WORD)(millitime%1000);
3,463✔
165
                millitime /= 1000;
3,463✔
166
                timepart /= 10;
3,463✔
167
                if ( AC.ShortStats ) {
3,463✔
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,447✔
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,266✔
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,266✔
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,266✔
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,447✔
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,447✔
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,765✔
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 ) {
787✔
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,433✔
508
                                        EXPRNAME(AR.CurExpr),FG.swmes[par],S->TermsLeft);
3,433✔
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,447✔
537
                if ( ISLESSPOS(*plspace,pp) ) {
3,447✔
538
                        MesPrint("%24s Bytes used      = %10p",AC.Commercial,plspace);
3,447✔
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,463✔
589

590
                MUNLOCK(ErrorMessageLock);
3,533✔
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,233,487✔
609
{
610
        GETBIDENTITY
611
        SORTING *S, **newFS;
3,233,487✔
612
        int i, newsize;
3,233,487✔
613
        if ( AN.SoScratC == 0 )
3,233,487✔
614
                AN.SoScratC = (UWORD *)Malloc1(2*(AM.MaxTal+2)*sizeof(UWORD),"NewSort");
2,497✔
615
        AR.sLevel++;
3,233,487✔
616
        if ( AR.sLevel >= AN.NumFunSorts ) {
3,233,487✔
617
                if ( AN.NumFunSorts == 0 ) newsize = 100;
2,975✔
618
                else newsize = 2*AN.NumFunSorts;
×
619
                newFS = (SORTING **)Malloc1((newsize+1)*sizeof(SORTING *),"FunSort pointers");
2,975✔
620
                for ( i = 0; i < AN.NumFunSorts; i++ ) newFS[i] = AN.FunSorts[i];
5,950✔
621
                for ( ; i <= newsize; i++ ) newFS[i] = 0;
303,450✔
622
                if ( AN.FunSorts ) M_free(AN.FunSorts,"FunSort pointers");
2,975✔
623
                AN.FunSorts = newFS; AN.NumFunSorts = newsize;
2,975✔
624
        }
625
        if ( AR.sLevel == 0 ) {
3,233,487✔
626

627
                numcompares = 0;
12,997✔
628

629
                AN.FunSorts[0] = AT.S0;
12,997✔
630
                if ( AR.PolyFun == 0 ) { AT.S0->PolyFlag = 0; }
12,997✔
631
                else if ( AR.PolyFunType == 1 ) { AT.S0->PolyFlag = 1; }
945✔
632
                else if ( AR.PolyFunType == 2 ) {
867✔
633
                        if ( AR.PolyFunExp == 2
867✔
634
                          || AR.PolyFunExp == 3 ) AT.S0->PolyFlag = 1;
867✔
635
                        else                      AT.S0->PolyFlag = 2;
613✔
636
                }
637
                AR.ShortSortCount = 0;
12,997✔
638
        }
639
        else {
640
                if ( AN.FunSorts[AR.sLevel] == 0 ) {
3,220,490✔
641
                        AN.FunSorts[AR.sLevel] = AllocSort(
1,326✔
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,220,490✔
646
        }
647
        AT.SS = S = AN.FunSorts[AR.sLevel];
3,233,487✔
648
        S->sFill = S->sBuffer;
3,233,487✔
649
        S->lFill = S->lBuffer;
3,233,487✔
650
        S->lPatch = 0;
3,233,487✔
651
        S->fPatchN = 0;
3,233,487✔
652
        S->GenTerms = S->TermsLeft = S->GenSpace = S->SpaceLeft = 0;
3,233,487✔
653
        S->PoinFill = S->sPointer;
3,233,487✔
654
        *S->PoinFill = S->sFill;
3,233,487✔
655
        if ( AR.sLevel > 0 ) { S->PolyWise = 0; }
3,233,487✔
656
        PUTZERO(S->SizeInFile[0]); PUTZERO(S->SizeInFile[1]); PUTZERO(S->SizeInFile[2]);
3,233,487✔
657
        S->sTerms = 0;
3,233,487✔
658
        PUTZERO(S->file.POposition);
3,233,487✔
659
        S->stage4 = 0;
3,233,487✔
660
        if ( AR.sLevel > AN.MaxFunSorts ) AN.MaxFunSorts = AR.sLevel;
3,233,487✔
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,233,487✔
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,229,529✔
699
{
700
  GETBIDENTITY
701
  SORTING *S = AT.SS;
3,229,529✔
702
  WORD j, **ss, *to, *t;
3,229,529✔
703
  LONG sSpace, over, tover, spare, retval = 0, jj;
3,229,529✔
704
  POSITION position, pp;
3,229,529✔
705
  off_t lSpace;
3,229,529✔
706
  FILEHANDLE *fout = 0, *oldoutfile = 0, *newout = 0;
3,229,529✔
707

708
  if ( AM.exitflag && AR.sLevel == 0 ) return(0);
3,229,529✔
709
#ifdef WITHMPI 
710
  if( (retval = PF_EndSort()) > 0){
770,594✔
711
        oldoutfile = AR.outfile;
781✔
712
        retval = 0;
781✔
713
        goto RetRetval;
781✔
714
  } 
715
  else if(retval < 0){
769,813✔
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,228,748✔
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,228,748✔
738
        *(S->PoinFill) = 0;
3,228,748✔
739
#ifdef SPLITTIME
740
                PrintTime((UBYTE *)"EndSort, before SplitMerge");
741
#endif
742
        S->sPointer[SplitMerge(BHEAD S->sPointer,S->sTerms)] = 0;
3,228,748✔
743
#ifdef SPLITTIME
744
                PrintTime((UBYTE *)"Endsort,  after SplitMerge");
745
#endif
746
        sSpace = 0;
3,228,748✔
747
        tover = over = S->sTerms;
3,228,748✔
748
        ss = S->sPointer;
3,228,748✔
749
        if ( over >= 0 ) {
3,228,748✔
750
                if ( S->lPatch > 0 || S->file.handle >= 0 ) {
3,228,748✔
751
                        ss[over] = 0;
103✔
752
                        sSpace = ComPress(ss,&spare);
103✔
753
                        S->TermsLeft -= over - spare;
103✔
754
                        if ( par == 1 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
103✔
755
                }
756
                else if ( S != AT.S0 ) {
3,228,645✔
757
                        ss[over] = 0;
3,220,398✔
758
                        if ( par == 2 ) {
3,220,398✔
759
                                sSpace = 3;
760
                                while ( ( t = *ss++ ) != 0 ) { sSpace += *t; }
43,188✔
761
                                if ( AN.tryterm > 0 && ( (sSpace+1)*sizeof(WORD) < (size_t)(AM.MaxTer) ) ) {
12,982✔
762
                                        to = TermMalloc("$-sort space");
4✔
763
                                }
764
                                else {
765
                                        LONG allocsp = sSpace+1;
12,978✔
766
                                        if ( allocsp < MINALLOC ) allocsp = MINALLOC;
12,978✔
767
                                        allocsp = ((allocsp+7)/8)*8;
12,978✔
768
                                        to = (WORD *)Malloc1(allocsp*sizeof(WORD),"$-sort space");
12,978✔
769
                                        if ( AN.tryterm > 0 ) AN.tryterm = 0;
12,978✔
770
                                }
771
                                *((WORD **)buffer) = to;
12,982✔
772
                                ss = S->sPointer;
12,982✔
773
                                while ( ( t = *ss++ ) != 0 ) {
43,188✔
774
                                        j = *t; while ( --j >= 0 ) *to++ = *t++;
351,989✔
775
                                }
776
                                *to = 0;
12,982✔
777
                                retval = sSpace + 1;
12,982✔
778
                        }
779
                        else {
780
                                to = buffer;
781
                                sSpace = 0;
782
                                while ( ( t = *ss++ ) != 0 ) {
9,486,310✔
783
                                        j = *t;
6,278,890✔
784
                                        if ( ( sSpace += j ) > AM.MaxTer/((LONG)sizeof(WORD)) ) {
6,278,890✔
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++;
44,156,900✔
791
                                }
792
                                *to = 0;
3,207,416✔
793
                        }
794
                        goto RetRetval;
3,220,398✔
795
                }
796
                else {
797
                        POSITION oldpos;
8,247✔
798
                        if ( S == AT.S0 ) {
8,247✔
799
                                fout = AR.outfile;
8,247✔
800
                                *AR.CompressPointer = 0;
8,247✔
801
                                SeekScratch(AR.outfile,&position);
8,247✔
802
                        }
803
                        else {
804
                                fout = &(S->file);
805
                                PUTZERO(position);
806
                        }
807
                        oldpos = position;
8,247✔
808
                        S->TermsLeft = 0;
8,247✔
809
/*
810
                        Here we can go directly to the output.
811
*/
812
#ifdef WITHZLIB
813
                        { int oldgzipCompress = AR.gzipCompress;
8,247✔
814
                                AR.gzipCompress = 0;
8,247✔
815
#endif
816
                        if ( tover > 0 ) {
8,247✔
817
                                ss = S->sPointer;
3,679✔
818
                                while ( ( t = *ss++ ) != 0 ) {
388,942✔
819
                                        if ( *t ) S->TermsLeft++;
385,263✔
820
#ifdef WITHPTHREADS
821
                                        if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD t); }
205,905✔
822
                                        else
823
#endif
824
                                        if ( PutOut(BHEAD t,&position,fout,1) < 0 ) {
181,508✔
825
                                                retval = -1; goto RetRetval;
×
826
                                        }
827
                                }
828
                        }
829
#ifdef WITHPTHREADS
830
                        if ( AS.MasterSort && ( fout == AR.outfile ) ) { PutToMaster(BHEAD 0); }
4,992✔
831
                        else
832
#endif
833
                        if ( FlushOut(&position,fout,1) ) {
3,319✔
834
                                retval = -1; goto RetRetval;
×
835
                        }
836
#ifdef WITHZLIB
837
                                AR.gzipCompress = oldgzipCompress;
8,247✔
838
                        }
839
#endif
840
#ifdef WITHPTHREADS
841
                        if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
4,992✔
842
#endif
843
#ifdef WITHMPI
844
                        if ( PF.me != MASTER && PF.exprtodo < 0 ) goto RetRetval;
2,385✔
845
#endif
846
                        DIFPOS(oldpos,position,oldpos);
977✔
847
                        S->SpaceLeft = BASEPOSITION(oldpos);
977✔
848
                        WriteStats(&oldpos,STATSPOSTSORT,NOCHECKLOGTYPE);
977✔
849
                        pp = oldpos;
977✔
850
                        goto RetRetval;
977✔
851
                }
852
        }
853
        else if ( par == 1 && newout == 0 ) { AR.outfile = newout = AllocFileHandle(0,(char *)0); }
×
854
        sSpace++;
103✔
855
        lSpace = sSpace + (S->lFill - S->lBuffer) - (LONG)S->lPatch*(AM.MaxTer/sizeof(WORD));
103✔
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);
103✔
859
        MULPOS(pp,sizeof(WORD));
103✔
860
        if ( S->file.handle >= 0 ) {
103✔
861
                ADD2POS(pp,S->fPatches[S->fPatchN]);
16✔
862
        }
863
        if ( S == AT.S0 ) {
103✔
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); }
103✔
869
        if ( S->lPatch > 0 ) {
103✔
870
                if ( ( S->lPatch >= S->MaxPatches ) ||
103✔
871
                        ( ( (WORD *)(((UBYTE *)(S->lFill + sSpace)) + 2*AM.MaxTer) ) >= S->lTop ) ) {
103✔
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

882
                        if ( MergePatches(1) ) {
×
883
                                MLOCK(ErrorMessageLock);
×
884
                                MesCall("EndSort");
×
885
                                MUNLOCK(ErrorMessageLock);
×
886
                                retval = -1; goto RetRetval;
×
887
                        }
888
                        S->lPatch = 0;
×
889
                        pp = S->SizeInFile[1];
×
890
                        MULPOS(pp,sizeof(WORD));
×
891
#ifndef WITHPTHREADS
892
                        if ( S == AT.S0 )
893
#endif
894
                        {
895
                                POSITION pppp;
×
896
                                SETBASEPOSITION(pppp,0);
×
897
                                SeekFile(S->file.handle,&pppp,SEEK_CUR);
×
898
                                SeekFile(S->file.handle,&pp,SEEK_END);
×
899
                                SeekFile(S->file.handle,&pppp,SEEK_SET);
×
900
                                WriteStats(&pp,STATSMERGETOFILE,CHECKLOGTYPE);
×
901
                                UpdateMaxSize();
×
902
                        }
903
                }
904
                else {
905
                        S->Patches[S->lPatch++] = S->lFill;
103✔
906
                    to = (WORD *)(((UBYTE *)(S->lFill)) + AM.MaxTer);
103✔
907
                        if ( tover > 0 ) {
103✔
908
                                ss = S->sPointer;
103✔
909
                                while ( ( t = *ss++ ) != 0 ) {
1,325,415✔
910
                                        j = *t;
1,325,312✔
911
                                        if ( j < 0 ) j = t[1] + 2;
1,325,312✔
912
                                        while ( --j >= 0 ) *to++ = *t++;
30,164,370✔
913
                                }
914
                        }
915
                        *to++ = 0;
103✔
916
                        S->lFill = to;
103✔
917
                        if ( S->file.handle < 0 ) {
103✔
918
                                if ( MergePatches(2) ) {
87✔
919
                                        MLOCK(ErrorMessageLock);
×
920
                                        MesCall("EndSort");
×
921
                                        MUNLOCK(ErrorMessageLock);
×
922
                                        retval = -1; goto RetRetval;
×
923
                                }
924
                                if ( S == AT.S0 ) {
87✔
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 ) {
83✔
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 ) {        /* output too large */
83✔
961
TooLarge:
×
962
                                                MLOCK(ErrorMessageLock);
×
963
                                                MesPrint("(1)Output should fit inside a single term. Increase MaxTermSize?");
×
964
                                                MesCall("EndSort");
×
965
                                                MUNLOCK(ErrorMessageLock);
×
966
                                                retval = -1; goto RetRetval;
×
967
                                        }
968
                                        else {
969
                                                t = newout->PObuffer;
83✔
970
                                                if ( par == 2 ) {
83✔
971
                                                        jj = newout->POfill - t;
×
972
                                                        if ( AN.tryterm > 0 && ( (jj+2)*sizeof(WORD) < (size_t)(AM.MaxTer) ) ) {
×
973
                                                                to = TermMalloc("$-sort space");
×
974
                                                        }
975
                                                        else {
976
                                                                LONG allocsp = jj+2;
×
977
                                                                if ( allocsp < MINALLOC ) allocsp = MINALLOC;
×
978
                                                                allocsp = ((allocsp+7)/8)*8;
×
979
                                                                to = (WORD *)Malloc1(allocsp*sizeof(WORD),"$-sort space");
×
980
                                                                if ( AN.tryterm > 0 ) AN.tryterm = 0;
×
981
                                                        }
982
                                                        *((WORD **)buffer) = to;
×
983
                                                        NCOPY(to,t,jj);
×
984
                                                }
985
                                                else {
986
                                                        j = newout->POfill - t;
83✔
987
                                                        to = buffer;
83✔
988
                                                        if ( to >= AT.WorkSpace && to < AT.WorkTop && to+j > AT.WorkTop )
83✔
989
                                                                goto WorkSpaceError;
×
990
                                                        if ( j > AM.MaxTer ) goto TooLarge;
83✔
991
                                                        NCOPY(to,t,j);
6,263,580✔
992
                                                }
993
                                        }
994
                                }
995
                                goto RetRetval;
87✔
996
                        }
997
                        if ( MergePatches(1) ) { /* --> SortFile */
16✔
998
                                MLOCK(ErrorMessageLock);
×
999
                                MesCall("EndSort");
×
1000
                                MUNLOCK(ErrorMessageLock);
×
1001
                                retval = -1; goto RetRetval;
×
1002
                        }
1003
                        UpdateMaxSize();
16✔
1004
                        pp = S->SizeInFile[1];
16✔
1005
                        MULPOS(pp,sizeof(WORD));
16✔
1006
#ifndef WITHPTHREADS
1007
                        if ( S == AT.S0 )
4✔
1008
#endif
1009
                        {
1010
                                POSITION pppp;
14✔
1011
                                SETBASEPOSITION(pppp,0);
14✔
1012
                                SeekFile(S->file.handle,&pppp,SEEK_CUR);
14✔
1013
                                SeekFile(S->file.handle,&pp,SEEK_END);
14✔
1014
                                SeekFile(S->file.handle,&pppp,SEEK_SET);
14✔
1015
                                WriteStats(&pp,STATSMERGETOFILE,CHECKLOGTYPE);
14✔
1016
                        }
1017
#ifdef WITHERRORXXX
1018
                        if ( S != AT.S0 ) {
1019
/*
1020
                                This is wrong! We have sorted to the sort file.
1021
                                Things are not sitting in the output yet.
1022
*/
1023
                                if ( newout->handle >= 0 ) goto TooLarge;
1024
                                t = newout->PObuffer;
1025
                                j = newout->POfill - t;
1026
                                to = buffer;
1027
                                if ( to >= AT.WorkSpace && to < AT.WorkTop && to+j > AT.WorkTop )
1028
                                        goto WorkSpaceError;
1029
                                if ( j > AM.MaxTer ) goto TooLarge;
1030
                                NCOPY(to,t,j);
1031
                                goto RetRetval;
1032
                        }
1033
#endif
1034
                }
1035
        }
1036
        if ( S->file.handle >= 0 ) {
16✔
1037
#ifdef GZIPDEBUG
1038
                MLOCK(ErrorMessageLock);
1039
                MesPrint("%w EndSort: fPatchN = %d, lPatch = %d, position = %12p"
1040
                        ,S->fPatchN,S->lPatch,&(S->fPatches[S->fPatchN]));
1041
                MUNLOCK(ErrorMessageLock);
1042
#endif
1043
                if ( S->lPatch <= 0 ) {
16✔
1044
                        StageSort(&(S->file));
×
1045
                        position = S->fPatches[S->fPatchN];
×
1046
                        ss = S->sPointer;
×
1047
                        if ( *ss ) {
×
1048
#ifdef WITHZLIB
1049
                                *AR.CompressPointer = 0;
×
1050
                                if ( S == AT.S0 && AR.NoCompress == 0 && AR.gzipCompress > 0 )
×
1051
                                        S->fpcompressed[S->fPatchN] = 1;
×
1052
                                else
1053
                                        S->fpcompressed[S->fPatchN] = 0;
×
1054
                                SetupOutputGZIP(&(S->file));
×
1055
#endif
1056
                                while ( ( t = *ss++ ) != 0 ) {
×
1057
                                        if ( PutOut(BHEAD t,&position,&(S->file),1) < 0 ) {
×
1058
                                                retval = -1; goto RetRetval;
×
1059
                                        }
1060
                                }
1061
                                if ( FlushOut(&position,&(S->file),1) ) {
×
1062
                                        retval = -1; goto RetRetval;
×
1063
                                }
1064
                                ++(S->fPatchN);
×
1065
                                S->fPatches[S->fPatchN] = position;
×
1066
                                UpdateMaxSize();
×
1067
#ifdef GZIPDEBUG
1068
                                MLOCK(ErrorMessageLock);
1069
                                MesPrint("%w EndSort+: fPatchN = %d, lPatch = %d, position = %12p"
1070
                                        ,S->fPatchN,S->lPatch,&(S->fPatches[S->fPatchN]));
1071
                                MUNLOCK(ErrorMessageLock);
1072
#endif
1073
                        }
1074
                }
1075
                AR.Stage4Name = 0;
16✔
1076
#ifdef WITHPTHREADS
1077
                if ( AS.MasterSort && AC.ThreadSortFileSynch ) {
12✔
1078
                        if ( S->file.handle >= 0 ) {
1079
                                SynchFile(S->file.handle);
1080
                        }
1081
                }
1082
#endif
1083
                UpdateMaxSize();
16✔
1084
                if ( MergePatches(0) ) {
16✔
1085
                        MLOCK(ErrorMessageLock);
×
1086
                        MesCall("EndSort");
×
1087
                        MUNLOCK(ErrorMessageLock);
×
1088
                        retval = -1; goto RetRetval;
×
1089
                }
1090
                S->stage4 = 0;
16✔
1091
#ifdef WITHPTHREADS
1092
                if ( AS.MasterSort && ( fout == AR.outfile ) ) goto RetRetval;
12✔
1093
#endif
1094
                pp = S->SizeInFile[0];
16✔
1095
                MULPOS(pp,sizeof(WORD));
16✔
1096
                WriteStats(&pp,STATSPOSTSORT,NOCHECKLOGTYPE);
16✔
1097
                UpdateMaxSize();
16✔
1098
        }
1099
RetRetval:
×
1100

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

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

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

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

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

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

1413
WORD PutOut(PHEAD WORD *term, POSITION *position, FILEHANDLE *fi, WORD ncomp)
12,146,930✔
1414
{
1415
        GETBIDENTITY
1416
        WORD i, *p, ret, *r, *rr, j, k, first;
12,146,930✔
1417
        int dobracketindex = 0;
12,146,930✔
1418
        LONG RetCode;
12,146,930✔
1419

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

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

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

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

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

1989
WORD AddCoef(PHEAD WORD **ps1, WORD **ps2)
3,426,735✔
1990
{
1991
        GETBIDENTITY
1992
        SORTING *S = AT.SS;
3,426,735✔
1993
        WORD *s1, *s2;
3,426,735✔
1994
        WORD l1, l2, i;
3,426,735✔
1995
        WORD OutLen, *t, j;
3,426,735✔
1996
        UWORD *OutCoef;
3,426,735✔
1997
#ifdef WITHFLOAT
1998
        if ( AT.SortFloatMode ) return(AddWithFloat(BHEAD ps1,ps2));
3,426,735✔
1999
#endif
2000
        OutCoef = AN.SoScratC;
3,426,735✔
2001
        s1 = *ps1; s2 = *ps2;
3,426,735✔
2002
        GETCOEF(s1,l1);
3,426,735✔
2003
        GETCOEF(s2,l2);
3,426,735✔
2004
        if ( AddRat(BHEAD (UWORD *)s1,l1,(UWORD *)s2,l2,OutCoef,&OutLen) ) {
3,426,735✔
2005
                MLOCK(ErrorMessageLock);
×
2006
                MesCall("AddCoef");
×
2007
                MUNLOCK(ErrorMessageLock);
×
2008
                Terminate(-1);
×
2009
        }
2010
        if ( AN.ncmod != 0 ) {
3,426,735✔
2011
                if ( ( AC.modmode & POSNEG ) != 0 ) {
×
2012
                        NormalModulus(OutCoef,&OutLen);
×
2013
/*
2014
                        We had forgotten that this can also become smaller but the
2015
                        denominator isn't there. Correct in the other case
2016
                        17-may-2009 [JV]
2017
*/
2018
                        j = ABS(OutLen); OutCoef[j] = 1;
×
2019
                        for ( i = 1; i < j; i++ ) OutCoef[j+i] = 0;
×
2020
                }
2021
                else if ( BigLong(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod)) >= 0 ) {
×
2022
                        SubPLon(OutCoef,OutLen,(UWORD *)AC.cmod,ABS(AN.ncmod),OutCoef,&OutLen);
×
2023
                        OutCoef[OutLen] = 1;
×
2024
                        for ( i = 1; i < OutLen; i++ ) OutCoef[OutLen+i] = 0;
×
2025
                }
2026
        }
2027
        if ( !OutLen ) { *ps1 = *ps2 = 0; return(0); }
3,426,735✔
2028
        OutLen *= 2;
3,415,859✔
2029
        if ( OutLen < 0 ) i = - ( --OutLen );
3,415,859✔
2030
        else                          i = ++OutLen;
3,255,860✔
2031
        if ( l1 < 0 ) l1 = -l1;
3,415,859✔
2032
        l1 *= 2; l1++;
3,415,859✔
2033
        if ( i <= l1 ) {        /* Fits in 1 */
3,415,859✔
2034
                l1 -= i;
3,388,755✔
2035
                **ps1 -= l1;
3,388,755✔
2036
                s2 = (WORD *)OutCoef;
3,388,755✔
2037
                while ( --i > 0 ) *s1++ = *s2++;
10,403,535✔
2038
                *s1++ = OutLen;
3,388,755✔
2039
                while ( --l1 >= 0 ) *s1++ = 0;
3,388,979✔
2040
                goto RegEnd;
3,388,755✔
2041
        }
2042
        if ( l2 < 0 ) l2 = -l2;
27,096✔
2043
        l2 *= 2; l2++;
27,096✔
2044
        if ( i <= l2 ) {        /* Fits in 2 */
27,096✔
2045
                l2 -= i;
12,636✔
2046
                **ps2 -= l2;
12,636✔
2047
                s1 = (WORD *)OutCoef;
12,636✔
2048
                while ( --i > 0 ) *s2++ = *s1++;
116,644✔
2049
                *s2++ = OutLen;
12,636✔
2050
                while ( --l2 >= 0 ) *s2++ = 0;
12,764✔
2051
                *ps1 = *ps2;
12,636✔
2052
                goto RegEnd;
12,636✔
2053
        }
2054

2055
        /* Doesn't fit. Make a new term. */
2056

2057
        t = s1;
14,460✔
2058
        s1 = *ps1;
14,460✔
2059
        j = *s1++ + i - l1;                /* Space needed */
14,460✔
2060
        if ( (S->sFill + j) >= S->sTop2 ) {
14,460✔
2061
                GarbHand();
×
2062
                s1 = *ps1;
×
2063
                t = s1 + *s1 - 1;
×
2064
                j = *s1++ + i - l1;                /* Space needed */
×
2065
                l1 = *t;
×
2066
                if ( l1 < 0 ) l1  = - l1;
×
2067
                t -= l1-1;
×
2068
        }
2069
        s2 = S->sFill;
14,460✔
2070
        *s2++ = j;
14,460✔
2071
        while ( s1 < t ) *s2++ = *s1++;
123,768✔
2072
        s1 = (WORD *)OutCoef;
2073
        while ( --i > 0 ) *s2++ = *s1++;
151,588✔
2074
        *s2++ = OutLen;
14,460✔
2075
        *ps1 = S->sFill;
14,460✔
2076
        S->sFill = s2;
14,460✔
2077
RegEnd:
3,415,859✔
2078
        *ps2 = 0;
3,415,859✔
2079
        if ( **ps1 > AM.MaxTer/((LONG)(sizeof(WORD))) ) {
3,415,859✔
2080
                MLOCK(ErrorMessageLock);
×
2081
                MesPrint("Term too complex after addition in sort. MaxTermSize = %10l",
×
2082
                AM.MaxTer/sizeof(WORD));
×
2083
                MUNLOCK(ErrorMessageLock);
×
2084
                Terminate(-1);
×
2085
        }
2086
        return(1);
2087
}
2088

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

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

2266
/*
2267
                 #] AddPoly : 
2268
                 #[ AddArgs :                                VOID AddArgs(arg1,arg2,to)
2269
*/
2270
 
2271
#define INSLENGTH(x)  w[1] = FUNHEAD+ARGHEAD+x; w[FUNHEAD] = ARGHEAD+x;
2272

2273
/**
2274
 *        Adds the arguments of two occurrences of the PolyFun.
2275
 *        @param s1 Pointer to the first occurrence.
2276
 *        @param s2 Pointer to the second occurrence.
2277
 *        @param m  Pointer to where the answer should be.
2278
 */
2279

2280
VOID AddArgs(PHEAD WORD *s1, WORD *s2, WORD *m)
16✔
2281
{
2282
        GETBIDENTITY
2283
        WORD i1, i2;
16✔
2284
        WORD *w = m, *mm, *t, *t1, *t2, *tstop1, *tstop2;
16✔
2285
        WORD tempterm[8+FUNHEAD];
16✔
2286

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

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

2573
WORD Compare1(PHEAD WORD *term1, WORD *term2, WORD level)
34,609,210✔
2574
{
2575
        SORTING *S = AT.SS;
34,609,210✔
2576
        WORD *stopper1, *stopper2, *t2;
34,609,210✔
2577
        WORD *s1, *s2, *t1;
34,609,210✔
2578
        WORD *stopex1, *stopex2;
34,609,210✔
2579
        WORD c1, c2;
34,609,210✔
2580
        WORD prevorder;
34,609,210✔
2581
        WORD count = -1, localPoly, polyhit = -1;
34,609,210✔
2582

2583
        if ( AR.sLevel == 0 ) {
34,609,210✔
2584
                numcompares++;
29,788,120✔
2585
        }
2586

2587
        if ( S->PolyFlag ) {
34,609,210✔
2588
/*
2589
                if ( S->PolyWise != 0 ) {
2590
                        MLOCK(ErrorMessageLock);
2591
                        MesPrint("S->PolyWise is not zero!!!!!");
2592
                        MUNLOCK(ErrorMessageLock);
2593
                }
2594
*/
2595
                count = 0; localPoly = 1; S->PolyWise = polyhit = 0;
15,042✔
2596
                S->PolyFlag = AR.PolyFunType;
15,042✔
2597
                if ( AR.PolyFunType == 2 &&
15,042✔
2598
                         ( AR.PolyFunExp == 2 || AR.PolyFunExp == 3 ) ) S->PolyFlag = 1;
15,006✔
2599
        }
2600
        else { localPoly = 0; }
2601
#ifdef WITHFLOAT
2602
        AT.SortFloatMode = 0;
34,609,210✔
2603
#endif
2604
        prevorder = 0;
34,609,210✔
2605
        GETSTOP(term1,s1);
34,609,210✔
2606
        stopper1 = s1;
34,609,210✔
2607
        GETSTOP(term2,stopper2);
34,609,210✔
2608
        t1 = term1 + 1;
34,609,210✔
2609
        t2 = term2 + 1;
34,609,210✔
2610
        while ( t1 < stopper1 && t2 < stopper2 ) {
48,187,640✔
2611
                if ( *t1 != *t2 ) {
41,397,760✔
2612
                        if ( *t1 == HAAKJE ) return(PREV(-1));
17,085✔
2613
                        if ( *t2 == HAAKJE ) return(PREV(1));
10,972✔
2614
                        if ( *t1 >= (FUNCTION-1) ) {
10,027✔
2615
                                if ( *t2 < (FUNCTION-1) ) return(PREV(-1));
9,916✔
2616
                                if ( *t1 < FUNCTION && *t2 < FUNCTION ) return(PREV(*t2-*t1));
9,325✔
2617
                                if ( *t1 < FUNCTION ) return(PREV(1));
9,325✔
2618
                                if ( *t2 < FUNCTION ) return(PREV(-1));
9,325✔
2619
                                c1 = functions[*t1-FUNCTION].commute;
9,325✔
2620
                                c2 = functions[*t2-FUNCTION].commute;
9,325✔
2621
                                if ( !c1 ) {
9,325✔
2622
                                        if ( c2 ) return(PREV(1));
9,325✔
2623
                                        else return(PREV(*t2-*t1));
9,325✔
2624
                                }
2625
                                else {
2626
                                        if ( !c2 ) return(PREV(-1));
×
2627
                                        else return(PREV(*t2-*t1));
×
2628
                                }
2629
                        }
2630
                        else return(PREV(*t2-*t1));
111✔
2631
                }
2632
                s1 = t1 + 2;
41,380,610✔
2633
                s2 = t2 + 2;
41,380,610✔
2634
                c1 = *t1;
41,380,610✔
2635
                t1 += t1[1];
41,380,610✔
2636
                t2 += t2[1];
41,380,610✔
2637
                if ( localPoly && c1 < FUNCTION ) {
41,380,610✔
2638
                        polyhit = 1;
28✔
2639
                }
2640
                if ( c1 <= (FUNCTION-1)
41,380,610✔
2641
                || ( c1 >= FUNCTION && functions[c1-FUNCTION].spec > 0 ) ) {
24,010,141✔
2642
                        if ( c1 == SYMBOL ) {
17,610,070✔
2643
                                if ( *s1 == FACTORSYMBOL && *s2 == FACTORSYMBOL
2,123,628✔
2644
                                 && s1[-1] == 4 && s2[-1] == 4
3,426✔
2645
                                 && ( ( t1 < stopper1 && *t1 == HAAKJE )
3,426✔
2646
                                 || ( t1 == stopper1 && AT.fromindex ) ) ) {
×
2647
/*
2648
                                        We have to be very careful with the criteria here, because
2649
                                        Compare1 is called both in the regular sorting and by the
2650
                                        routine that makes the bracket index. In the last case
2651
                                        there is no HAAKJE subterm.
2652
*/
2653
                                        if ( s1[1] != s2[1] ) return(s2[1]-s1[1]);
3,426✔
2654
                                        s1 += 2; s2 += 2;
2,058✔
2655
                                }
2656
                                else if ( AR.SortType >= SORTPOWERFIRST ) {
2,120,202✔
2657
                                        WORD i1 = 0, *r1;
2658
                                        r1 = s1;
×
2659
                                        while ( s1 < t1 ) { i1 += s1[1]; s1 += 2; }
×
2660
                                        s1 = r1; r1 = s2;
×
2661
                                        while ( s2 < t2 ) { i1 -= s2[1]; s2 += 2; }
×
2662
                                        s2 = r1;
×
2663
                                        if ( i1 ) {
×
2664
                                                if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
×
2665
                                                return(PREV(i1));
×
2666
                                        }
2667
                                }
2668
                                while ( s1 < t1 ) {
4,542,490✔
2669
                                        if ( s2 >= t2 ) {
4,306,670✔
2670
/*                                                return(PREV(1));  */
2671
                                                if ( AR.SortType==SORTLOWFIRST ) {
8,116✔
2672
                                                        return(PREV((s1[1]>0?-1:1)));
7,779✔
2673
                                                }
2674
                                                else {
2675
                                                        return(PREV((s1[1]<0?-1:1)));
337✔
2676
                                                }
2677
                                        }
2678
                                        if ( *s1 != *s2 ) {
4,298,560✔
2679
/*                                                return(PREV(*s2-*s1)); */
2680
                                                if ( AR.SortType==SORTLOWFIRST ) {
670,341✔
2681
                                                        if ( *s1 < *s2 ) {
667,631✔
2682
                                                                return(PREV((s1[1]<0?1:-1)));
408,540✔
2683
                                                        }
2684
                                                        else {
2685
                                                                return(PREV((s2[1]<0?-1:1)));
259,091✔
2686
                                                        }
2687
                                                }
2688
                                                else {
2689
                                                        if ( *s1 < *s2 ) {
2,710✔
2690
                                                                return(PREV((s1[1]<0?-1:1)));
290✔
2691
                                                        }
2692
                                                        else {
2693
                                                                return(PREV((s2[1]<0?1:-1)));
2,420✔
2694
                                                        }
2695
                                                }
2696
                                        }
2697
                                        s1++; s2++;
3,628,217✔
2698
                                        if ( *s1 != *s2 ) return(
3,628,217✔
2699
                                                PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
1,207,981✔
2700
                                        s1++; s2++;
2,420,236✔
2701
                                }
2702
                                if ( s2 < t2 ) {
235,822✔
2703
/*                                        return(PREV(-1));  */
2704
                                        if ( AR.SortType==SORTLOWFIRST ) {
10,934✔
2705
                                                return(PREV((s2[1]<0?-1:1)));
10,920✔
2706
                                        }
2707
                                        else {
2708
                                                return(PREV((s2[1]<0?1:-1)));
14✔
2709
                                        }
2710
                                }
2711
                        }
2712
                        else if ( c1 == DOTPRODUCT ) {
15,486,430✔
2713
                                if ( AR.SortType >= SORTPOWERFIRST ) {
88✔
2714
                                        WORD i1 = 0, *r1;
2715
                                        r1 = s1;
×
2716
                                        while ( s1 < t1 ) { i1 += s1[2]; s1 += 3; }
×
2717
                                        s1 = r1; r1 = s2;
×
2718
                                        while ( s2 < t2 ) { i1 -= s2[2]; s2 += 3; }
×
2719
                                        s2 = r1;
×
2720
                                        if ( i1 ) {
×
2721
                                                if ( AR.SortType >= SORTANTIPOWER ) i1 = -i1;
×
2722
                                                return(PREV(i1));
×
2723
                                        }
2724
                                }
2725
                                while ( s1 < t1 ) {
88✔
2726
                                        if ( s2 >= t2 ) return(PREV(1));
88✔
2727
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
88✔
2728
                                        s1++; s2++;
88✔
2729
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
88✔
2730
                                        s1++; s2++;
80✔
2731
                                        if ( *s1 != *s2 ) return(
80✔
2732
                                                PREV((AR.SortType==SORTLOWFIRST?*s2-*s1:*s1-*s2)));
80✔
2733
                                        s1++; s2++;
×
2734
                                }
2735
                                if ( s2 < t2 ) return(PREV(-1));
×
2736
                        }
2737
                        else {
2738
                                while ( s1 < t1 ) {
124,054,600✔
2739
                                        if ( s2 >= t2 ) return(PREV(1));
123,734,200✔
2740
                                        if ( *s1 != *s2 ) return(PREV(*s2-*s1));
123,734,200✔
2741
                                        s1++; s2++;
108,568,200✔
2742
                                }
2743
                                if ( s2 < t2 ) return(PREV(-1));
320,445✔
2744
                        }
2745
                }
2746
                else {
2747
#if FUNHEAD != 2
2748
                        s1 += FUNHEAD-2;
23,770,579✔
2749
                        s2 += FUNHEAD-2;
23,770,579✔
2750
#endif
2751
                        if ( localPoly && c1 == AR.PolyFun ) {
23,770,579✔
2752
                                if ( count == 0 ) {
2,260✔
2753
                                  if ( S->PolyFlag == 1 ) {
2,260✔
2754
                                        WORD i1, i2;
16✔
2755
                                        if ( *s1 > 0 ) i1 = *s1;
16✔
2756
                                        else if ( *s1 <= -FUNCTION ) i1 = 1;
×
2757
                                        else i1 = 2;
×
2758
                                        if ( *s2 > 0 ) i2 = *s2;
16✔
2759
                                        else if ( *s2 <= -FUNCTION ) i2 = 1;
×
2760
                                        else i2 = 2;
×
2761
                                        if ( s1+i1 == t1 && s2+i2 == t2 ) {        /* This is the stuff */
16✔
2762
/*
2763
                                                Test for scalar nature
2764
*/
2765
                                                if ( !polyhit ) {
16✔
2766
                                                        WORD *u1, *u2, *ustop;
12✔
2767
                                                        if ( *s1 < 0 ) {
12✔
2768
                                                                if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
×
2769
                                                                        goto NoPoly;
×
2770
                                                        }
2771
                                                        else {
2772
                                                                u1 = s1 + ARGHEAD;
12✔
2773
                                                                while ( u1 < t1 ) {
42✔
2774
                                                                        u2 = u1 + *u1;
30✔
2775
                                                                        ustop = u2 - ABS(u2[-1]);
30✔
2776
                                                                        u1++;
30✔
2777
                                                                        while ( u1 < ustop ) {
56✔
2778
                                                                                if ( *u1 == INDEX ) goto NoPoly;
26✔
2779
                                                                                u1 += u1[1];
26✔
2780
                                                                        }
2781
                                                                        u1 = u2;
2782
                                                                }
2783
                                                        }
2784
                                                        if ( *s2 < 0 ) {
12✔
2785
                                                                if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
×
2786
                                                                        goto NoPoly;
×
2787
                                                        }
2788
                                                        else {
2789
                                                                u1 = s2 + ARGHEAD;
12✔
2790
                                                                while ( u1 < t2 ) {
32✔
2791
                                                                        u2 = u1 + *u1;
20✔
2792
                                                                        ustop = u2 - ABS(u2[-1]);
20✔
2793
                                                                        u1++;
20✔
2794
                                                                        while ( u1 < ustop ) {
36✔
2795
                                                                                if ( *u1 == INDEX ) goto NoPoly;
16✔
2796
                                                                                u1 += u1[1];
16✔
2797
                                                                        }
2798
                                                                        u1 = u2;
2799
                                                                }
2800
                                                        }
2801
                                                }
2802
                                                S->PolyWise = WORDDIF(s1,term1);
16✔
2803
                                                S->PolyWise -= FUNHEAD;
16✔
2804
                                                count = 1;
16✔
2805
                                                continue;
16✔
2806
                                        }
2807
                                        else {
2808
NoPoly:
×
2809
                                                S->PolyWise = localPoly = 0;
×
2810
                                        }
2811
                                  }
2812
                                  else if ( AR.PolyFunType == 2 ) {
2,244✔
2813
                                        WORD i1, i2, i1a, i2a;
2,244✔
2814
                                        if ( *s1 > 0 ) i1 = *s1;
2,244✔
2815
                                        else if ( *s1 <= -FUNCTION ) i1 = 1;
516✔
2816
                                        else i1 = 2;
516✔
2817
                                        if ( *s2 > 0 ) i2 = *s2;
2,244✔
2818
                                        else if ( *s2 <= -FUNCTION ) i2 = 1;
540✔
2819
                                        else i2 = 2;
540✔
2820
                                        if ( s1[i1] > 0 ) i1a = s1[i1];
2,244✔
2821
                                        else if ( s1[i1] <= -FUNCTION ) i1a = 1;
268✔
2822
                                        else i1a = 2;
268✔
2823
                                        if ( s2[i2] > 0 ) i2a = s2[i2];
2,244✔
2824
                                        else if ( s2[i2] <= -FUNCTION ) i2a = 1;
268✔
2825
                                        else i2a = 2;
268✔
2826
                                        if ( s1+i1+i1a == t1 && s2+i2+i2a == t2 ) {        /* This is the stuff */
2,244✔
2827
/*
2828
                                                Test for scalar nature
2829
*/
2830
                                                if ( !polyhit ) {
2,244✔
2831
                                                        WORD *u1, *u2, *ustop;
2,232✔
2832
                                                        if ( *s1 < 0 ) {
2,232✔
2833
                                                                if ( *s1 != -SNUMBER && *s1 != -SYMBOL && *s1 > -FUNCTION )
512✔
2834
                                                                        goto NoPoly;
×
2835
                                                        }
2836
                                                        else {
2837
                                                                u1 = s1 + ARGHEAD;
1,720✔
2838
                                                                while ( u1 < s1+i1 ) {
27,331✔
2839
                                                                        u2 = u1 + *u1;
25,611✔
2840
                                                                        ustop = u2 - ABS(u2[-1]);
25,611✔
2841
                                                                        u1++;
25,611✔
2842
                                                                        while ( u1 < ustop ) {
50,890✔
2843
                                                                                if ( *u1 == INDEX ) goto NoPoly;
25,279✔
2844
                                                                                u1 += u1[1];
25,279✔
2845
                                                                        }
2846
                                                                        u1 = u2;
2847
                                                                }
2848
                                                        }
2849
                                                        if ( s1[i1] < 0 ) {
2,232✔
2850
                                                                if ( s1[i1] != -SNUMBER && s1[i1] != -SYMBOL && s1[i1] > -FUNCTION )
268✔
2851
                                                                        goto NoPoly;
×
2852
                                                        }
2853
                                                        else {
2854
                                                                u1 = s1 +i1 + ARGHEAD;
1,964✔
2855
                                                                while ( u1 < t1 ) {
30,400✔
2856
                                                                        u2 = u1 + *u1;
28,436✔
2857
                                                                        ustop = u2 - ABS(u2[-1]);
28,436✔
2858
                                                                        u1++;
28,436✔
2859
                                                                        while ( u1 < ustop ) {
56,556✔
2860
                                                                                if ( *u1 == INDEX ) goto NoPoly;
28,120✔
2861
                                                                                u1 += u1[1];
28,120✔
2862
                                                                        }
2863
                                                                        u1 = u2;
2864
                                                                }
2865
                                                        }
2866
                                                        if ( *s2 < 0 ) {
2,232✔
2867
                                                                if ( *s2 != -SNUMBER && *s2 != -SYMBOL && *s2 > -FUNCTION )
536✔
2868
                                                                        goto NoPoly;
×
2869
                                                        }
2870
                                                        else {
2871
                                                                u1 = s2 + ARGHEAD;
1,696✔
2872
                                                                while ( u1 < s2+i2 ) {
27,283✔
2873
                                                                        u2 = u1 + *u1;
25,587✔
2874
                                                                        ustop = u2 - ABS(u2[-1]);
25,587✔
2875
                                                                        u1++;
25,587✔
2876
                                                                        while ( u1 < ustop ) {
50,842✔
2877
                                                                                if ( *u1 == INDEX ) goto NoPoly;
25,255✔
2878
                                                                                u1 += u1[1];
25,255✔
2879
                                                                        }
2880
                                                                        u1 = u2;
2881
                                                                }
2882
                                                        }
2883
                                                        if ( s2[i2] < 0 ) {
2,232✔
2884
                                                                if ( s2[i2] != -SNUMBER && s2[i2] != -SYMBOL && s2[i2] > -FUNCTION )
268✔
2885
                                                                        goto NoPoly;
×
2886
                                                        }
2887
                                                        else {
2888
                                                                u1 = s2 + i2 + ARGHEAD;
1,964✔
2889
                                                                while ( u1 < t2 ) {
30,396✔
2890
                                                                        u2 = u1 + *u1;
28,432✔
2891
                                                                        ustop = u2 - ABS(u2[-1]);
28,432✔
2892
                                                                        u1++;
28,432✔
2893
                                                                        while ( u1 < ustop ) {
56,548✔
2894
                                                                                if ( *u1 == INDEX ) goto NoPoly;
28,116✔
2895
                                                                                u1 += u1[1];
28,116✔
2896
                                                                        }
2897
                                                                        u1 = u2;
2898
                                                                }
2899
                                                        }
2900
                                                }
2901
                                                S->PolyWise = WORDDIF(s1,term1);
2,244✔
2902
                                                S->PolyWise -= FUNHEAD;
2,244✔
2903
                                                count = 1;
2,244✔
2904
                                                continue;
2,244✔
2905
                                        }
2906
                                        else {
2907
                                                S->PolyWise = localPoly = 0;
×
2908
                                        }
2909
                                  }
2910
                                  else {
2911
                                        S->PolyWise = localPoly = 0;
×
2912
                                  }
2913
                                }
2914
                                else {
2915
                                        t1 = term1 + S->PolyWise;
×
2916
                                        t2 = term2 + S->PolyWise;
×
2917
                                        S->PolyWise = 0;
×
2918
                                        localPoly = 0;
×
2919
                                        continue;
×
2920
                                }
2921
                        }
2922
#ifdef WITHFLOAT
2923
                        if ( c1 == FLOATFUN && t1 == stopper1 && t2 == stopper2 && AT.aux_ != 0 ) {
23,768,304✔
2924
/*
2925
                                We have two FLOATFUN's. Test whether they are 'legal'
2926
*/
2927
                                if ( TestFloat(s1-FUNHEAD) ) {
×
2928
                                        if ( TestFloat(s2-FUNHEAD) ) { AT.SortFloatMode = 3; return(0); }
×
2929
                                        else { return(1); }
2930
                                }
2931
                                else if ( TestFloat(s2-FUNHEAD) ) { return(-1); }
×
2932
                        }
2933
#endif
2934
                        while ( s1 < t1 ) {
36,825,095✔
2935
/*
2936
                                The next statement was added 9-nov-2001. It repaired a bad error
2937
*/
2938
                                if ( s2 >= t2 ) return(PREV(-1));
23,794,331✔
2939
/*
2940
                                There is a little problem here with fast arguments
2941
                                We don't want to sacrifice speed, but we like to
2942
                                keep a rational ordering. This last one suffers in
2943
                                the solution that has been chosen here.
2944
*/
2945
                                if ( AC.properorderflag ) {
23,794,331✔
2946
                                        WORD oldpolyflag;
×
2947
                                        oldpolyflag = S->PolyFlag;
×
2948
                                        S->PolyFlag = 0;
×
2949
                                        if ( ( c2 = -CompArg(s1,s2) ) != 0 ) {
×
2950
                                                S->PolyFlag = oldpolyflag; return(PREV(c2));
×
2951
                                        }
2952
                                        S->PolyFlag = oldpolyflag;
×
2953
                                        NEXTARG(s1)
×
2954
                                        NEXTARG(s2)
×
2955
                                }
2956
                                else {
2957
                                        if ( *s1 > 0 ) {
23,794,331✔
2958
                                                if ( *s2 > 0 ) {
106,862✔
2959
                                                        WORD oldpolyflag;
106,505✔
2960
                                                        stopex1 = s1 + *s1;
106,505✔
2961
                                                        if ( s2 >= t2 ) return(PREV(-1));
106,505✔
2962
                                                        stopex2 = s2 + *s2;
106,505✔
2963
                                                        s1 += ARGHEAD; s2 += ARGHEAD;
106,505✔
2964
                                                        oldpolyflag = S->PolyFlag;
106,505✔
2965
                                                        S->PolyFlag = 0;
106,505✔
2966
                                                        while ( s1 < stopex1 ) {
224,300✔
2967
                                                                if ( s2 >= stopex2 ) {
190,528✔
2968
                                                                        S->PolyFlag = oldpolyflag; return(PREV(-1));
889✔
2969
                                                                }
2970
                                                                if ( ( c2 = CompareTerms(BHEAD s1,s2,(WORD)1) ) != 0 ) {
189,639✔
2971
                                                                        S->PolyFlag = oldpolyflag; return(PREV(c2));
71,844✔
2972
                                                                }
2973
                                                                s1 += *s1;
117,795✔
2974
                                                                s2 += *s2;
117,795✔
2975
                                                        }
2976
                                                        S->PolyFlag = oldpolyflag;
33,772✔
2977
                                                        if ( s2 < stopex2 ) return(PREV(1));
33,772✔
2978
                                                }
2979
                                                else return(PREV(1));
2980
                                        }
2981
                                        else {
2982
                                                if ( *s2 > 0 ) return(PREV(-1));
23,687,465✔
2983
                                                if ( *s1 != *s2 ) { return(PREV(*s1-*s2)); }
23,686,839✔
2984
                                                if ( *s1 > -FUNCTION ) {
23,686,838✔
2985
                                                        if ( *++s1 != *++s2 ) { return(PREV(*s2-*s1)); }
23,686,838✔
2986
                                                }
2987
                                                s1++; s2++;
13,027,372✔
2988
                                        }
2989
                                }
2990
                        }
2991
                        if ( s2 < t2 ) return(PREV(1));
13,030,754✔
2992
                }
2993
        }
2994
#ifdef WITHFLOAT
2995
        if ( t1 < stopper1 && *t1 == FLOATFUN && t1+t1[1] == stopper1
6,789,842✔
2996
                        && TestFloat(t1) ) {
×
2997
                AT.SortFloatMode = 1; return(0);
×
2998
        }
2999
        else if ( t2 < stopper2 && *t2 == FLOATFUN && t2+t2[1] == stopper2
6,789,842✔
3000
                        && TestFloat(t2) ) {
×
3001
                AT.SortFloatMode = 2; return(0);
×
3002
        }
3003
#endif
3004
        {
3005
                if ( AR.SortType != SORTLOWFIRST ) {
6,789,842✔
3006
                        if ( t1 < stopper1 ) return(PREV(1));
3,020,131✔
3007
                        if ( t2 < stopper2 ) return(PREV(-1));
520,108✔
3008
                }
3009
                else {
3010
                        if ( t1 < stopper1 ) return(PREV(-1));
3,769,703✔
3011
                        if ( t2 < stopper2 ) return(PREV(1));
3,763,837✔
3012
                }
3013
        }
3014
        if ( level == 3 ) return(CompCoef(term1,term2));
3,753,162✔
3015
        if ( level >= 1 )
3,753,162✔
3016
                return(CompCoef(term2,term1));
119,526✔
3017
        return(0);
3018
}
3019

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

3037
WORD CompareSymbols(PHEAD WORD *term1, WORD *term2, WORD par)
1,026,315✔
3038
{
3039
        int sum1, sum2;
1,026,315✔
3040
        WORD *t1, *t2, *tt1, *tt2;
1,026,315✔
3041
        int low, high;
1,026,315✔
3042
        DUMMYUSE(par);
1,026,315✔
3043
        if ( AR.SortType == SORTLOWFIRST ) { low = 1; high = -1; }
1,026,315✔
3044
        else { low = -1; high = 1; }
911,320✔
3045
        t1 = term1 + 1; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); t1 += 2;
1,026,315✔
3046
        t2 = term2 + 1; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); t2 += 2;
1,026,315✔
3047
        if ( AN.polysortflag > 0 ) {
1,026,315✔
3048
                sum1 = 0; sum2 = 0;
×
3049
                while ( t1 < tt1 ) { sum1 += t1[1]; t1 += 2; }
×
3050
                while ( t2 < tt2 ) { sum2 += t2[1]; t2 += 2; }
×
3051
                if ( sum1 < sum2 ) return(low);
×
3052
                if ( sum1 > sum2 ) return(high);
×
3053
                t1 = term1+3; t2 = term2 + 3;
×
3054
        }
3055
        while ( t1 < tt1 && t2 < tt2 ) {
1,989,070✔
3056
                if ( *t1 > *t2 ) return(low);
1,978,041✔
3057
                if ( *t1 < *t2 ) return(high);
1,798,380✔
3058
                if ( t1[1] < t2[1] ) return(low);
1,771,339✔
3059
                if ( t1[1] > t2[1] ) return(high);
1,202,623✔
3060
                t1 += 2; t2 += 2;
962,755✔
3061
        }
3062
        if ( t1 < tt1 ) return(high);
11,029✔
3063
        if ( t2 < tt2 ) return(low);
3,796✔
3064
        return(0);
3065
}
3066

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

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

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

3133
LONG ComPress(WORD **ss, LONG *n)
3,388✔
3134
{
3135
        GETIDENTITY
2,220✔
3136
        WORD *t, *s, j, k;
3,388✔
3137
        LONG size = 0;
3,388✔
3138
        int newsize, i;
3,388✔
3139
/*
3140
                        #[ debug :
3141

3142
        WORD **sss = ss;
3143

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

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

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

3263
                        #] debug : 
3264
*/
3265
        return(size);
3,388✔
3266
}
3267

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

3297
#ifdef NEWSPLITMERGE
3298

3299
LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
18,167,230✔
3300
{
3301
        GETBIDENTITY
3302
        SORTING *S = AT.SS;
18,167,230✔
3303
        WORD **pp3, **pp1, **pp2;
18,167,230✔
3304
        LONG i, newleft, newright, split;
18,167,230✔
3305

3306
        if ( number < 2 ) return(number);
18,167,230✔
3307
        if ( number == 2 ) {
15,834,210✔
3308
                pp1 = Pointer; pp2 = pp1 + 1;
8,366,620✔
3309
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
8,366,620✔
3310
                        pp3 = (WORD **)(*pp1); *pp1 = *pp2; *pp2 = (WORD *)pp3;
687,079✔
3311
                }
3312
                else if ( i == 0 ) {
7,679,540✔
3313
                  number--;
161,189✔
3314
                  if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) == 0 ) number = 0; }
161,189✔
3315
                  else               { if ( AddCoef(BHEAD pp1,pp2) == 0 ) number = 0; }
161,164✔
3316
                }
3317
                return(number);
8,366,620✔
3318
        }
3319
        split = number/2;
7,467,600✔
3320
        newleft  = SplitMerge(BHEAD Pointer,split);
7,467,600✔
3321
        newright = SplitMerge(BHEAD Pointer+split,number-split);
7,467,600✔
3322
        if ( newright == 0 ) return(newleft);
7,467,600✔
3323
/*
3324
        We compare the last of the left with the first of the right
3325
        If they are already in order, we will be done quickly.
3326
        We may have to compactify the buffer because the recursion may
3327
        have created holes. Also this compare may result in equal terms.
3328
        Addition of 23-jul-1999. It makes things a bit faster.
3329
*/
3330
        if ( newleft > 0 && newright > 0 &&
7,467,540✔
3331
        ( i = CompareTerms(BHEAD Pointer[newleft-1],Pointer[split],(WORD)0) ) >= 0 ) {
7,467,530✔
3332
                pp2 = Pointer+split; pp1 = Pointer+newleft-1;
6,984,320✔
3333
                if ( i == 0 ) {
6,984,320✔
3334
                  if ( S->PolyWise ) {
157,405✔
3335
                        if ( AddPoly(BHEAD pp1,pp2) > 0 ) pp1++;
3✔
3336
                        else newleft--;
×
3337
                  }
3338
                  else {               
3339
                        if ( AddCoef(BHEAD pp1,pp2) > 0 ) pp1++;
157,402✔
3340
                        else newleft--;
21✔
3341
                  }
3342
                  pp2++; newright--;
157,405✔
3343
                }
3344
                else pp1++;
6,826,920✔
3345
                newleft += newright;
6,984,320✔
3346
                if ( pp1 < pp2 ) {
6,984,320✔
3347
                        while ( --newright >= 0 ) *pp1++ = *pp2++;
169,604✔
3348
                }
3349
                return(newleft);
6,984,320✔
3350
        }
3351

3352
        if ( split >= AN.SplitScratchSize ) {
483,219✔
3353
                AN.SplitScratchSize = (split*3)/2+100;
689✔
3354
                if ( AN.SplitScratchSize > S->Terms2InSmall/2 )
689✔
3355
                         AN.SplitScratchSize = S->Terms2InSmall/2;
×
3356
                if ( AN.SplitScratch ) M_free(AN.SplitScratch,"AN.SplitScratch");
689✔
3357
                AN.SplitScratch = (WORD **)Malloc1(AN.SplitScratchSize*sizeof(WORD *),"AN.SplitScratch");
689✔
3358
        }
3359
        pp3 = AN.SplitScratch; pp1 = Pointer;
483,219✔
3360
        for ( i = 0; i < newleft; i++ ) *pp3++ = *pp1++;
8,652,948✔
3361
        AN.InScratch = newleft;
483,219✔
3362
        pp1 = AN.SplitScratch; pp2 = Pointer + split; pp3 = Pointer;
483,219✔
3363
/*
3364
                An improvement in the style of Timsort
3365
*/
3366
        while ( newleft > 8 ) {
504,901✔
3367
                LONG nnleft = newleft/2;
162,927✔
3368
                if ( ( i = CompareTerms(BHEAD pp1[nnleft],*pp2,(WORD)0) ) < 0 ) break;
162,927✔
3369
                pp3 += nnleft+1;
22,526✔
3370
                pp1 += nnleft+1;
22,526✔
3371
                newleft -= nnleft+1;
22,526✔
3372
                if ( i == 0 ) {
22,526✔
3373
                        if ( S->PolyWise ) { i = AddPoly(BHEAD pp3-1,pp2); }
844✔
3374
                        else               { i = AddCoef(BHEAD pp3-1,pp2); }
842✔
3375
                        if ( i == 0 ) pp3--;
844✔
3376
                        pp2++;
844✔
3377
                        newright--;
844✔
3378
                        break;
844✔
3379
                }
3380
        }
3381

3382
        while ( newleft > 0 && newright > 0 ) {
10,403,960✔
3383
                if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
9,920,732✔
3384
                        *pp3++ = *pp2++;
4,219,300✔
3385
                        newright--;
4,219,300✔
3386
                }
3387
                else if ( i > 0 ) {
5,701,432✔
3388
                        *pp3++ = *pp1++;
2,593,272✔
3389
                        newleft--;
2,593,272✔
3390
                }
3391
                else {
3392
                  if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3,108,171✔
3393
                  else {               if ( AddCoef(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
3,107,323✔
3394
                  pp1++; pp2++; newleft--; newright--;
3,108,171✔
3395
                }
3396
        }
3397
        for ( i = 0; i < newleft; i++ ) *pp3++ = *pp1++;
2,512,389✔
3398
        if ( pp3 == pp2 ) {
483,219✔
3399
                pp3 += newright;
419,629✔
3400
        } else {
3401
                for ( i = 0; i < newright; i++ ) *pp3++ = *pp2++;
467,116✔
3402
        }
3403
        AN.InScratch = 0;
483,219✔
3404
        return(pp3 - Pointer);
483,219✔
3405
}
3406

3407
#else
3408

3409
LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
3410
{
3411
        GETBIDENTITY
3412
        SORTING *S = AT.SS;
3413
        WORD **pp3, **pp1, **pp2;
3414
        LONG nleft, nright, i, newleft, newright;
3415
        WORD **pptop;
3416

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

3500
#endif
3501

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

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

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

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

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

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

3965
                /* More than one patch. Construct the tree. */
3966

3967
                lpat = 1;
3968
                do { lpat *= 2; } while ( lpat < S->lPatch );
1,068✔
3969
                mpat = ( lpat >> 1 ) - 1;
375✔
3970
                k = lpat - S->lPatch;
375✔
3971

3972
                /* k is the number of empty places in the tree. they will
3973
                   be at the even positions from 2 to 2*k */
3974

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

4003
                start the sort
4004
*/
4005
                level = S->lPatch;
375✔
4006

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

4116
                                          if ( AddRat(BHEAD (UWORD *)m1,r1,(UWORD *)m2,r2,coef,&r3) ) {
74,548✔
4117
                                                MLOCK(ErrorMessageLock);
×
4118
                                                MesCall("MergePatches");
×
4119
                                                MUNLOCK(ErrorMessageLock);
×
4120
                                                SETERROR(-1)
×
4121
                                          }
4122

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

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

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

4419
WORD StoreTerm(PHEAD WORD *term)
19,061,450✔
4420
{
4421
        GETBIDENTITY
4422
        SORTING *S = AT.SS;
19,061,450✔
4423
        WORD **ss, *lfill, j, *t;
19,061,450✔
4424
        POSITION pp;
19,061,450✔
4425
        LONG lSpace, sSpace, RetCode, over, tover;
19,061,450✔
4426

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

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

4483
                        if ( S == AT.S0 ) {        /* Only statistics at ground level */
201✔
4484
                                WriteStats(&pp,STATSMERGETOFILE,CHECKLOGTYPE);
171✔
4485
                        }
4486
                        S->lPatch = 0;
201✔
4487
                        S->lFill = S->lBuffer;
201✔
4488
                }
4489
                S->Patches[S->lPatch++] = S->lFill;
3,282✔
4490
            lfill = (WORD *)(((UBYTE *)(S->lFill)) + AM.MaxTer);
3,282✔
4491
                if ( tover > 0 ) {
3,282✔
4492
                        ss = S->sPointer;
3,282✔
4493
                        while ( ( t = *ss++ ) != 0 ) {
7,605,540✔
4494
                                j = *t;
7,602,270✔
4495
                                if ( j < 0 ) j = t[1] + 2;
7,602,270✔
4496
                                while ( --j >= 0 ){
165,984,000✔
4497
                                  *lfill++ = *t++;
158,381,800✔
4498
                                }
4499
                        }
4500
                }
4501
                *lfill++ = 0;
3,282✔
4502
                S->lFill = lfill;
3,282✔
4503
                S->sTerms = 0;
3,282✔
4504
                S->PoinFill = S->sPointer;
3,282✔
4505
                *(S->PoinFill) = S->sFill = S->sBuffer;
3,282✔
4506
        }
4507
        j = *term;
19,061,450✔
4508
        while ( --j >= 0 ) *S->sFill++ = *term++;
320,340,500✔
4509
        S->sTerms++;
19,061,450✔
4510
        S->GenTerms++;
19,061,450✔
4511
        S->TermsLeft++;
19,061,450✔
4512
        *++S->PoinFill = S->sFill;
19,061,450✔
4513

4514
        return(0);
19,061,450✔
4515

4516
StoreCall:
×
4517
        MLOCK(ErrorMessageLock);
×
4518
        MesCall("StoreTerm");
×
4519
        MUNLOCK(ErrorMessageLock);
×
4520
        SETERROR(-1)
×
4521
}
4522

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

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

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

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

4632
WORD SortWild(WORD *w, WORD nw)
883✔
4633
{
4634
        GETIDENTITY
258✔
4635
        WORD *v, *s, *m, k, i;
883✔
4636
        WORD *pScrat, *stop, *sv, error = 0;
883✔
4637
        pScrat = AT.WorkPointer;
883✔
4638
        if ( ( AT.WorkPointer + 8 * AM.MaxWildcards ) >= AT.WorkTop ) {
883✔
4639
                MLOCK(ErrorMessageLock);
×
4640
                MesWork();
×
4641
                MUNLOCK(ErrorMessageLock);
×
4642
                return(-1);
×
4643
        }
4644
        stop = w + nw;
883✔
4645
        i = 0;
883✔
4646
        while ( i < nw ) {
2,592✔
4647
                m = w + i;
1,709✔
4648
                v = m + m[1];
1,709✔
4649
                while ( v < stop && (
1,926✔
4650
                         *v == FROMSET || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
1,162✔
4651
                while ( v < stop ) {
3,809✔
4652
                        if ( *v >= 0 ) {
2,100✔
4653
                                if ( AM.Ordering[*v] < AM.Ordering[*m] ) {
1,596✔
4654
                                        m = v;
4655
                                }
4656
                                else if ( *v == *m ) {
1,330✔
4657
                                        if ( v[2] < m[2] ) {
777✔
4658
                                                m = v;
4659
                                        }
4660
                                        else if ( v[2] == m[2] ) {
756✔
4661
                                                s = m + m[1];
91✔
4662
                                                sv = v + v[1];
91✔
4663
                                                if ( s < stop && ( *s == FROMSET
91✔
4664
                                                 || *s == SETTONUM || *s == LOADDOLLAR ) ) {
91✔
4665
                                                        if ( sv < stop && ( *sv == FROMSET
×
4666
                                                        || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
×
4667
                                                                if ( s[2] != sv[2] ) {
×
4668
                                                                        error = -1;
×
4669
                                                                        MLOCK(ErrorMessageLock);
×
4670
                                                                        MesPrint("&Wildcard set conflict");
×
4671
                                                                        MUNLOCK(ErrorMessageLock);
×
4672
                                                                }
4673
                                                        }
4674
                                                        *v = -1;
×
4675
                                                }
4676
                                                else {
4677
                                                        if ( sv < stop && ( *sv == FROMSET
91✔
4678
                                                        || *sv == SETTONUM || *sv == LOADDOLLAR ) ) {
42✔
4679
                                                                *m = -1;
×
4680
                                                                m = v;
×
4681
                                                        }
4682
                                                        else {
4683
                                                                *v = -1;
91✔
4684
                                                        }
4685
                                                }
4686
                                        }
4687
                                }
4688
                        }
4689
                        v += v[1];
2,100✔
4690
                        while ( v < stop && ( *v == FROMSET
2,191✔
4691
                         || *v == SETTONUM || *v == LOADDOLLAR ) ) v += v[1];
1,246✔
4692
                }
4693
                s = pScrat;
1,709✔
4694
                v = m;
1,709✔
4695
                k = m[1];
1,709✔
4696
                NCOPY(s,m,k);
8,545✔
4697
                while ( m < stop && ( *m == FROMSET
3,074✔
4698
                 || *m == SETTONUM || *m == LOADDOLLAR ) ) {
1,120✔
4699
                        k = m[1];
245✔
4700
                        NCOPY(s,m,k);
2,934✔
4701
                }
4702
                *v = -1;
1,709✔
4703
                pScrat = s;
1,709✔
4704
                i = 0;
1,709✔
4705
                while ( i < nw && ( w[i] < 0 || w[i] == FROMSET
5,028✔
4706
                || w[i] == SETTONUM || w[i] == LOADDOLLAR ) ) i += w[i+1];
4,145✔
4707
        }
4708
        AC.NwildC = k = WORDDIF(pScrat,AT.WorkPointer);
883✔
4709
        s = AT.WorkPointer;
883✔
4710
        m = w;
883✔
4711
        NCOPY(m,s,k);
8,699✔
4712
        AC.WildC = m;
883✔
4713
        return(error);
883✔
4714
}
4715

4716
/*
4717
                 #] SortWild : 
4718
                 #[ CleanUpSort :                        VOID CleanUpSort(num)
4719
*/
4720
/**
4721
 *                Partially or completely frees function sort buffers.
4722
 */
4723

4724
void CleanUpSort(int num)
4,670✔
4725
{
4726
        GETIDENTITY
1,368✔
4727
        SORTING *S;
4,670✔
4728
        int minnum = num, i;
4,670✔
4729
        if ( AN.FunSorts ) {
4,670✔
4730
                if ( num == -1 ) {
4,488✔
4731
                        if ( AN.MaxFunSorts > 3 ) {
2,881✔
4732
                                minnum = (AN.MaxFunSorts+4)/2;
1,333✔
4733
                        }
4734
                        else minnum = 4;
4735
                }
4736
                else if ( minnum == 0 ) minnum = 1;
1,607✔
4737
                for ( i = minnum; i < AN.NumFunSorts; i++ ) {
440,157✔
4738
                        S = AN.FunSorts[i];
435,669✔
4739
                        if ( S ) {
435,669✔
4740
                                if ( S->file.handle >= 0 ) {
984✔
4741
/*                                        TruncateFile(S->file.handle); */
4742
                                        UpdateMaxSize();
3✔
4743
#ifdef WITHZLIB
4744
                                        ClearSortGZIP(&(S->file));
3✔
4745
#endif
4746
                                        CloseFile(S->file.handle);
3✔
4747
                                        S->file.handle = -1;
3✔
4748
                                        remove(S->file.name);
3✔
4749
#ifdef GZIPDEBUG
4750
                                        MLOCK(ErrorMessageLock);
4751
                                        MesPrint("%w CleanUpSort removed file %s",S->file.name);
4752
                                        MUNLOCK(ErrorMessageLock);
4753
#endif
4754
                                }
4755
                                M_free(S,"sorting struct");
984✔
4756
                        }
4757
                        AN.FunSorts[i] = 0;
435,669✔
4758
                }
4759
                AN.MaxFunSorts = minnum;
4,488✔
4760
                if ( num == 0 ) {
4,488✔
4761
                        S = AN.FunSorts[0];
1,607✔
4762
                        if ( S ) {
1,607✔
4763
                                if ( S->file.handle >= 0 ) {
1,607✔
4764
/*                                        TruncateFile(S->file.handle); */
4765
                                        UpdateMaxSize();
×
4766
#ifdef WITHZLIB
4767
                                        ClearSortGZIP(&(S->file));
×
4768
#endif
4769
                                        CloseFile(S->file.handle);
×
4770
                                        S->file.handle = -1;
×
4771
                                        remove(S->file.name);
×
4772
#ifdef GZIPDEBUG
4773
                                        MLOCK(ErrorMessageLock);
4774
                                        MesPrint("%w CleanUpSort removed file %s",S->file.name);
4775
                                        MUNLOCK(ErrorMessageLock);
4776
#endif
4777
                                }
4778
                        }
4779
                }
4780
        }
4781
        for ( i = 0; i < 2; i++ ) {
14,010✔
4782
                if ( AR.FoStage4[i].handle >= 0 ) {
9,340✔
4783
                        UpdateMaxSize();
×
4784
#ifdef WITHZLIB
4785
                        ClearSortGZIP(&(AR.FoStage4[i]));
×
4786
#endif
4787
                        CloseFile(AR.FoStage4[i].handle);
×
4788
                        remove(AR.FoStage4[i].name);
×
4789
                        AR.FoStage4[i].handle = -1;
×
4790
#ifdef GZIPDEBUG
4791
                        MLOCK(ErrorMessageLock);
4792
                        MesPrint("%w CleanUpSort removed stage4 file %s",AR.FoStage4[i].name);
4793
                        MUNLOCK(ErrorMessageLock);
4794
#endif
4795
                }
4796
        }
4797
}
4,670✔
4798

4799
/*
4800
                 #] CleanUpSort : 
4801
                 #[ LowerSortLevel :         VOID LowerSortLevel()
4802
*/
4803
/**
4804
 *                Lowers the level in the sort system.
4805
 */
4806

4807
VOID LowerSortLevel(VOID)
2,225✔
4808
{
4809
        GETIDENTITY
668✔
4810
        if ( AR.sLevel >= 0 ) {
2,225✔
4811
                AR.sLevel--;
2,225✔
4812
                if ( AR.sLevel >= 0 ) AT.SS = AN.FunSorts[AR.sLevel];
2,225✔
4813
        }
4814
}
2,225✔
4815

4816
/*
4817
                 #] LowerSortLevel : 
4818
                 #[ PolyRatFunSpecial :
4819

4820
                Keeps only the most divergent term in AR.PolyFunVar
4821
                We assume that the terms are already in that notation.
4822
*/
4823

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

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

4907
        if ( exp1 <= exp2 ) { i = t1[1]; r = t1; }
×
4908
        else                { i = t2[1]; r = t2; }
×
4909
        t = oldworkpointer;
4910
        NCOPY(t,r,i)
×
4911

4912
        return(oldworkpointer);
4913
Illegal:
×
4914
        MesPrint("Illegal occurrence of PolyRatFun with divergent option");
×
4915
        Terminate(-1);
×
4916
        return(0);
×
4917
}
4918

4919
/*
4920
                 #] PolyRatFunSpecial : 
4921
                 #[ SimpleSplitMerge :
4922

4923
                Sorts an array of WORDs. No adding of equal objects.
4924
*/
4925

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

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

4954
VOID SimpleSplitMerge(WORD *array,WORD num)
×
4955
{
4956
        WORD *auxarray = Malloc1(sizeof(WORD)*num/2,"SimpleSplitMerge");
×
4957
        SimpleSplitMergeRec(array,num,auxarray);
×
4958
        M_free(auxarray,"SimpleSplitMerge");
×
4959
}
×
4960

4961
/*
4962
                 #] SimpleSplitMerge : 
4963
                 #[ BinarySearch :
4964

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

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

4990
/*
4991
                 #] BinarySearch : 
4992
        #] SortUtilities :
4993
*/
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