Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 108 additions & 3 deletions check/fixes.frm
Original file line number Diff line number Diff line change
Expand Up @@ -2725,9 +2725,10 @@ EOF
#: SortIOSize 200K
#: SubSortIOSize 200K

#: SubSmallSize 100K
#: SubSmallExtension 200K
#: SubTermsInSmall 5K
#: SubLargeSize 134400480
#: SubSmallSize 12800016
#: SubSmallExtension 19200032
#: SubTermsInSmall 5008

#define N "30"

Expand Down Expand Up @@ -2841,6 +2842,110 @@ print;
assert succeeded?
assert result("F") =~ expr("5000")
*--#] Issue508 :
*--#[ Issue512_1 :
#-
* Sort which fills SmallExtension:

* These are the smallest buffer sizes that are OK for -w4 tform workers
#: SmallSize 10240064
#: SmallExtension 15360096
#: TermsInSmall 100K

Symbol x,n;
CFunction g,f,prf;

Local test = (<f(1)>+...+<f(150)>)*(<g(1)>+...+<g(350)>);
.sort

PolyRatFun prf;

Identify f(x?) = prf(n-x,n+x);

.end
# Fails due to polynomial size on 32bit builds
#require wordsize >= 4
# Runtime errors may freeze ParFORM.
#pend_if mpi?
assert runtime_error?("Please increase SmallExtension setup parameter.")
*--#] Issue512_1 :
*--#[ Issue512_2 :
#-

* Sort which fills SubSmallExtension:
* These are the default sizes at the time of writing:
#: SubSmallSize 2560016
#: SubSmallExtension 3840032
* These are not default:
#: SubTermsInSmall 100K

Symbol x,n;
CFunction f,g,prf;

Local test = 1;
.sort

PolyRatFun prf;
Term;
Multiply (<f(1)>+...+<f(150)>)*(<g(1)>+...+<g(100)>);
Identify f(x?) = prf(n-x,n+x);
EndTerm;

.end
# Fails due to polynomial size on 32bit builds
#require wordsize >= 4
# Runtime errors may freeze ParFORM.
#pend_if mpi?
assert runtime_error?("Please increase SubSmallExtension setup parameter.")
*--#] Issue512_2 :
*--#[ Issue512_3 :
#-

* Sort which fits in SmallExtension, but needs GarbHand
#: SmallSize 10240064
#: SmallExtension 20360K
#: TermsInSmall 100K

Symbol x,n;
CFunction g,f,prf;

Local test = (<f(1)>+...+<f(150)>)*(<g(1)>+...+<g(350)>);
.sort

PolyRatFun prf;
Identify f(x?) = prf(n-x,n+x);

.end
# Fails due to polynomial size on 32bit builds
#require wordsize >= 4
assert succeeded?
*--#] Issue512_3 :
*--#[ Issue512_4 :
#-

* Sort which fits in SubSmallExtension, but needs GarbHand
* These are the default sizes at the time of writing:
#: SubSmallSize 2560016
* These are not default:
#: SubSmallExtension 5090K
#: SubTermsInSmall 100K

Symbol x,n;
CFunction f,g,prf;

Local test = 1;
.sort

PolyRatFun prf;
Term;
Multiply (<f(1)>+...+<f(150)>)*(<g(1)>+...+<g(100)>);
Identify f(x?) = prf(n-x,n+x);
EndTerm;

.end
# Fails due to polynomial size on 32bit builds
#require wordsize >= 4
assert succeeded?
*--#] Issue512_4 :
*--#[ Issue525 :
#:threadbucketsize 5
#:processbucketsize 5
Expand Down
148 changes: 111 additions & 37 deletions sources/sort.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@
#define GZIPDEBUG
*/
#define NEWSPLITMERGE
/* Comment to turn off Timsort in SplitMerge for debugging: */
#define NEWSPLITMERGETIMSORT
/* During SplitMerge, print pointer array state on entry. Very spammy, for debugging. */
/* #define SPLITMERGEDEBUG */
/* Debug printing for GarbHand */
/* #define TESTGARB */

#include "form3.h"

Expand Down Expand Up @@ -2234,11 +2240,21 @@ WORD AddPoly(PHEAD WORD **ps1, WORD **ps2)
TalToLine((UWORD)(*s2++)); TokenToLine((UBYTE *)" ");
}
FiniLine();
MesPrint("Please increase SmallExtension in %s",setupfilename);
if ( AR.sLevel > 0 ) {
MesPrint("Please increase SubSmallExtension setup parameter.");
}
else {
MesPrint("Please increase SmallExtension setup parameter.");
}
MUNLOCK(ErrorMessageLock);
#else
MLOCK(ErrorMessageLock);
MesPrint("Please increase SmallExtension in %s",setupfilename);
if ( AR.sLevel > 0 ) {
MesPrint("Please increase SubSmallExtension setup parameter.");
}
else {
MesPrint("Please increase SmallExtension setup parameter.");
}
MUNLOCK(ErrorMessageLock);
#endif
Terminate(-1);
Expand Down Expand Up @@ -3305,22 +3321,38 @@ LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
{
GETBIDENTITY
SORTING *S = AT.SS;
WORD **pp3, **pp1, **pp2;
WORD **pp3, **pp1, **pp2, **pptop;
LONG i, newleft, newright, split;

#ifdef SPLITMERGEDEBUG
/* Print current array state on entry. */
printf("%4ld: ", number);
for (int ii = 0; ii < S->sTerms; ii++) {
if ( (S->sPointer)[ii] ) {
printf("%4d ", (unsigned)(S->sPointer[ii]-S->sBuffer));
}
else {
printf(".... ");
}
}
printf("\n");
fflush(stdout);
#endif

if ( number < 2 ) return(number);
if ( number == 2 ) {
pp1 = Pointer; pp2 = pp1 + 1;
if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
pp3 = (WORD **)(*pp1); *pp1 = *pp2; *pp2 = (WORD *)pp3;
}
else if ( i == 0 ) {
number--;
if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) == 0 ) number = 0; }
else { if ( AddCoef(BHEAD pp1,pp2) == 0 ) number = 0; }
number--;
if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) == 0 ) number = 0; }
else { if ( AddCoef(BHEAD pp1,pp2) == 0 ) number = 0; }
}
return(number);
}
pptop = Pointer + number;
split = number/2;
newleft = SplitMerge(BHEAD Pointer,split);
newright = SplitMerge(BHEAD Pointer+split,number-split);
Expand All @@ -3336,77 +3368,104 @@ LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
( i = CompareTerms(BHEAD Pointer[newleft-1],Pointer[split],(WORD)0) ) >= 0 ) {
pp2 = Pointer+split; pp1 = Pointer+newleft-1;
if ( i == 0 ) {
if ( S->PolyWise ) {
if ( AddPoly(BHEAD pp1,pp2) > 0 ) pp1++;
else newleft--;
}
else {
if ( AddCoef(BHEAD pp1,pp2) > 0 ) pp1++;
else newleft--;
}
pp2++; newright--;
if ( S->PolyWise ) {
if ( AddPoly(BHEAD pp1,pp2) > 0 ) pp1++;
else newleft--;
}
else {
if ( AddCoef(BHEAD pp1,pp2) > 0 ) pp1++;
else newleft--;
}
*pp2++ = 0; newright--;
}
else pp1++;
newleft += newright;
if ( pp1 < pp2 ) {
while ( --newright >= 0 ) *pp1++ = *pp2++;
while ( pp1 < pptop ) *pp1++ = 0;
}
return(newleft);
}

if ( split >= AN.SplitScratchSize ) {
AN.SplitScratchSize = (split*3)/2+100;
if ( AN.SplitScratchSize > S->Terms2InSmall/2 )
AN.SplitScratchSize = S->Terms2InSmall/2;
AN.SplitScratchSize = S->Terms2InSmall/2;
if ( AN.SplitScratch ) M_free(AN.SplitScratch,"AN.SplitScratch");
AN.SplitScratch = (WORD **)Malloc1(AN.SplitScratchSize*sizeof(WORD *),"AN.SplitScratch");
}

pp3 = AN.SplitScratch; pp1 = Pointer;
for ( i = 0; i < newleft; i++ ) *pp3++ = *pp1++;
/* Move rather than copy, so GarbHand can't double-count. */
for ( i = 0; i < newleft; i++ ) { *pp3++ = *pp1; *pp1++ = 0; }
AN.InScratch = newleft;
pp1 = AN.SplitScratch; pp2 = Pointer + split; pp3 = Pointer;

#ifdef NEWSPLITMERGETIMSORT
/*
An improvement in the style of Timsort
*/
while ( newleft > 8 ) {
/* Check the middle of the LHS terms */
LONG nnleft = newleft/2;
if ( ( i = CompareTerms(BHEAD pp1[nnleft],*pp2,(WORD)0) ) < 0 ) break;
pp3 += nnleft+1;
pp1 += nnleft+1;
newleft -= nnleft+1;
if ( ( i = CompareTerms(BHEAD pp1[nnleft],*pp2,(WORD)0) ) < 0 ) {
/* The terms are not in order. Break out and continue as normal. */
break;
}
/* The terms merge or are in order. Copy pointers up to this point. */
/* In the copy, zero the skipped pointers so GarbHand can't double-count. */
for (int iii = 0; iii < nnleft; iii++) {
*pp3++ = *pp1;
*pp1++ = 0;
}
newleft -= nnleft;
if ( i == 0 ) {
if ( S->PolyWise ) { i = AddPoly(BHEAD pp3-1,pp2); }
else { i = AddCoef(BHEAD pp3-1,pp2); }
if ( i == 0 ) pp3--;
pp2++;
if ( S->PolyWise ) { i = AddPoly(BHEAD pp1,pp2); }
else { i = AddCoef(BHEAD pp1,pp2); }
if ( i == 0 ) {
/* The terms cancelled. The next term goes in *pp3. Don't move. */
}
else {
/* The terms added. Advance pp3. */
*pp3++ = *pp1;
}
/* We have taken a LHS (copy) and RHS term. */
*pp2++ = 0;
newright--;
*pp1++ = 0;
newleft--;
break;
}
}
#endif

while ( newleft > 0 && newright > 0 ) {
if ( ( i = CompareTerms(BHEAD *pp1,*pp2,(WORD)0) ) < 0 ) {
*pp3++ = *pp2++;
*pp3++ = *pp2;
*pp2++ = 0;
newright--;
}
else if ( i > 0 ) {
*pp3++ = *pp1++;
*pp3++ = *pp1;
*pp1++ = 0;
newleft--;
}
else {
if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
else { if ( AddCoef(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
pp1++; pp2++; newleft--; newright--;
if ( S->PolyWise ) { if ( AddPoly(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
else { if ( AddCoef(BHEAD pp1,pp2) > 0 ) *pp3++ = *pp1; }
*pp1++ = 0; *pp2++ = 0; newleft--; newright--;
}
}
for ( i = 0; i < newleft; i++ ) *pp3++ = *pp1++;
for ( i = 0; i < newleft; i++ ) { *pp3++ = *pp1; *pp1++ = 0; }
if ( pp3 == pp2 ) {
pp3 += newright;
} else {
for ( i = 0; i < newright; i++ ) *pp3++ = *pp2++;
for ( i = 0; i < newright; i++ ) { *pp3++ = *pp2++; }
}
newleft = pp3 - Pointer;
while ( pp3 < pptop ) *pp3++ = 0;
AN.InScratch = 0;
return(pp3 - Pointer);
return(newleft);
}

#else
Expand All @@ -3419,6 +3478,21 @@ LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
LONG nleft, nright, i, newleft, newright;
WORD **pptop;

#ifdef SPLITMERGEDEBUG
/* Print current array state on entry. */
printf("%4ld: ", number);
for (int ii = 0; ii < S->sTerms; ii++) {
if ( (S->sPointer)[ii] ) {
printf("%4d ", (unsigned)(S->sPointer[ii]-S->sBuffer));
}
else {
printf(".... ");
}
}
printf("\n");
fflush(stdout);
#endif

if ( number < 2 ) return(number);
if ( number == 2 ) {
pp1 = Pointer; pp2 = pp1 + 1;
Expand Down Expand Up @@ -3451,7 +3525,7 @@ LONG SplitMerge(PHEAD WORD **Pointer, LONG number)
if ( AddPoly(BHEAD pp1,pp2) > 0 ) pp1++;
else newleft--;
}
else {
else {
if ( AddCoef(BHEAD pp1,pp2) > 0 ) pp1++;
else newleft--;
}
Expand Down Expand Up @@ -3535,7 +3609,7 @@ VOID GarbHand(VOID)
*/
#ifdef TESTGARB
MLOCK(ErrorMessageLock);
MesPrint("in: S->sFill = %x, S->sTop2 = %x",S->sFill,S->sTop2);
MesPrint("in: S->sFill = %l, S->sTop2 = %l",S->sFill-S->sBuffer,S->sTop2-S->sBuffer);
#endif
Point = S->sPointer;
k = S->sTerms;
Expand All @@ -3548,7 +3622,7 @@ VOID GarbHand(VOID)
if ( ( s2 = *Point++ ) != 0 ) { total += *s2; }
}
#ifdef TESTGARB
MesPrint("total = %l, nterms = %l",2*total,AN.InScratch);
MesPrint("total = %l, nterms = %l",total,AN.InScratch);
MUNLOCK(ErrorMessageLock);
#endif
/*
Expand Down Expand Up @@ -3608,7 +3682,7 @@ VOID GarbHand(VOID)
S->sFill = s2;
#ifdef TESTGARB
MLOCK(ErrorMessageLock);
MesPrint("out: S->sFill = %x, S->sTop2 = %x",S->sFill,S->sTop2);
MesPrint("out: S->sFill = %l, S->sTop2 = %l",S->sFill-S->sBuffer,S->sTop2-S->sBuffer);
if ( S->sFill >= S->sTop2 ) {
MesPrint("We are in deep trouble");
}
Expand Down
Loading