Skip to content

Commit ec4399c

Browse files
author
Thomas Maeder
committed
Merge branch 'release/v4.95'
2 parents 47d6b89 + 8ab1184 commit ec4399c

File tree

108 files changed

+6674
-3971
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+6674
-3971
lines changed

BEISPIEL/pieces.inp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,5 +378,15 @@ steine Weiss Kd6 Tc4 Le7 Be6 ZRa3a8b7h6 AEd2d3h1
378378
forderung #2
379379
option vari
380380

381+
weiteresproblem
382+
383+
autor S\'ebastien Luce
384+
quelle Julia's Fairies 2016
385+
steine Weiss Sre3
386+
Schwarz Kf1 Tf4 Ld2h2 Sf5g3 Be2f2g2
387+
forderung ser-#19
388+
bedingung platzwechselcirce
389+
option ohnewk
390+
381391
end
382392

DHT/dhtbcmem.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@
2323
#include "dhtbcmem.h"
2424
#include "dht.h"
2525

26-
enum {
27-
ENSURE_SIZE_OF_ELEMENT_IS_ONE = 1/(1 == sizeof ((BCMemValue const *)NULL)->Data[0])
28-
};
26+
STATIC_ASSERT(1 == sizeof ((BCMemValue const *)NULL)->Data[0], "sizeof BCMemValue element must be 1.");
2927

3028
static dhtHashValue ConvertBCMemValue(dhtKey m)
3129
{

DHT/dhtcmem.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@
2424
typedef unsigned long uLong;
2525
typedef unsigned char uChar;
2626

27-
enum {
28-
ENSURE_SIZE_OF_ELEMENT_IS_ONE = 1/(1 == sizeof NilCompactMemVal->Data[0])
29-
};
27+
STATIC_ASSERT(1 == sizeof NilCompactMemVal->Data[0], "sizeof CompactMemVal element must be 1.");
3028

3129
static dhtHashValue ConvertCompactMemoryValue(dhtKey m)
3230
{

DHT/dhtmem.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@
2424
typedef unsigned long uLong;
2525
typedef unsigned char uChar;
2626

27-
enum {
28-
ENSURE_SIZE_OF_ELEMENT_IS_ONE = 1/(1 == sizeof NilMemVal->Data[0])
29-
};
27+
STATIC_ASSERT(1 == sizeof NilMemVal->Data[0], "sizeof BCMemValue element must be 1.");
3028

3129
static dhtHashValue HashMemoryValue(dhtKey k)
3230
{

DHT/fxf.c

Lines changed: 124 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,22 @@ enum
5656

5757
#define BOTTOM_BIT(s) (((size_t) (s)) & -(size_t) (s))
5858

59+
/*
60+
We want to ensure that every block we hand out is properly aligned for the
61+
object it will be storing. Trying to honor all required alignments without
62+
wasting too much memory would complicate things dramatically, so we make some
63+
assumptions. We assume there is a MAX_ALIGNMENT and a NOT_MULTIPLE_ALIGNMENT.
64+
Any allocation with size that's a multiple of MAX_ALIGNMENT will be assumed
65+
to require no more than that alignment. Other sizes will be assumed to require
66+
no more than NOT_MULTIPLE_ALIGNMENT, though we'll consider that they may require
67+
less (if they're smaller than NOT_MULTIPLE_ALIGNMENT).
68+
*/
69+
70+
/*
71+
Determine MAX_ALIGNMENT and NOT_MULTIPLE_ALIGNMENT. If types
72+
were provided then use their alignments; otherwise try to infer the maximum
73+
values on the system.
74+
*/
5975
#if defined(FXF_MAX_ALIGNMENT_TYPE)
6076
# define MAX_ALIGNMENT ALIGNMENT_OF_TYPE(FXF_MAX_ALIGNMENT_TYPE)
6177
#else /*FXF_MAX_ALIGNMENT_TYPE*/
@@ -161,8 +177,19 @@ typedef struct {
161177
/* TODO: Is the above a good default, sufficiently large for all of our needs without being excessive? */
162178
#endif
163179

180+
/*
181+
Determine the maximum amount we'll allow one to allocate. We need to ensure that it's
182+
a multiple of its required alignment, and we're OK with it being overaligned, so we
183+
round it up to the next alignment multiple.
184+
*/
164185
#define DESIRED_MAX_ALLOC_ALIGNMENT ((FXF_DESIRED_MAX_ALLOC < MAX_ALIGNMENT) ? NOT_MULTIPLE_ALIGNMENT : MAX_ALIGNMENT)
165186
#define ROUNDED_DESIRED_MAXIMUM_ALLOC ROUND_UP_TO_ALIGNMENT(FXF_DESIRED_MAX_ALLOC, DESIRED_MAX_ALLOC_ALIGNMENT)
187+
188+
/*
189+
Now determine the actual minimum and maximum allocations. The minimum is new.
190+
We determined the maximum above, but of course we can't allocate more than
191+
a full segment. (Segment sizes should already be maximally aligned.)
192+
*/
166193
enum
167194
{
168195
fxfMINSIZE = sizeof(void *), /* Different size of fxfMINSIZE for 32-/64/Bit compilation */
@@ -173,26 +200,65 @@ enum
173200
#endif
174201
};
175202

176-
enum {
177-
ENSURE_FXFMINSIZE_GT_0 = 1/(fxfMINSIZE > 0),
178-
ENSURE_FXFMAXSIZE_GE_FXFMINSIZE = 1/(fxfMAXSIZE >= fxfMINSIZE),
203+
STATIC_ASSERT(fxfMINSIZE > 0, "fxfMINSIZE must be > 0.");
204+
STATIC_ASSERT(fxfMAXSIZE >= fxfMINSIZE, "fxfMAXSIZE must be >= fxfMINSIZE.");
179205
#if defined(SEGMENT)
180-
ENSURE_SEGMENTS_ALIGNED = 1/!((ARENA_SEG_SIZE & (((ARENA_SEG_SIZE < MAX_ALIGNMENT) ? NOT_MULTIPLE_ALIGNMENT : MAX_ALIGNMENT) - 1U)) &&
181-
(ARENA_SEG_SIZE & (ARENA_SEG_SIZE - 1U))),
206+
STATIC_ASSERT(!((ARENA_SEG_SIZE & (((ARENA_SEG_SIZE < MAX_ALIGNMENT) ? NOT_MULTIPLE_ALIGNMENT :
207+
MAX_ALIGNMENT)
208+
- 1U)) &&
209+
(ARENA_SEG_SIZE & (ARENA_SEG_SIZE - 1U))), "Segments must be aligned.");
182210
#endif
183-
ENSURE_FXFMAXSIZE_ALIGNED = 1/((!CLEAR_BOTTOM_BIT(fxfMAXSIZE)) ||
211+
STATIC_ASSERT((!CLEAR_BOTTOM_BIT(fxfMAXSIZE)) ||
184212
((fxfMAXSIZE < MAX_ALIGNMENT) && !(fxfMAXSIZE & (NOT_MULTIPLE_ALIGNMENT - 1U))) ||
185-
!(fxfMAXSIZE & (MAX_ALIGNMENT - 1U))),
186-
ENSURE_ALIGNMENT_ORDERED = 1/((NOT_MULTIPLE_ALIGNMENT > 0) && (NOT_MULTIPLE_ALIGNMENT <= MAX_ALIGNMENT)),
187-
ENSURE_ALIGNMENTS_POWERS_OF_2 = 1/!(CLEAR_BOTTOM_BIT(NOT_MULTIPLE_ALIGNMENT) || CLEAR_BOTTOM_BIT(MAX_ALIGNMENT))
188-
};
189-
213+
!(fxfMAXSIZE & (MAX_ALIGNMENT - 1U)), "fxfMAXSIZE must be aligned.");
214+
STATIC_ASSERT((NOT_MULTIPLE_ALIGNMENT > 0) && (NOT_MULTIPLE_ALIGNMENT <= MAX_ALIGNMENT), "Alignments must be properly ordered.");
215+
STATIC_ASSERT(!(CLEAR_BOTTOM_BIT(NOT_MULTIPLE_ALIGNMENT) || CLEAR_BOTTOM_BIT(MAX_ALIGNMENT)), "Alignments must be powers of 2.");
216+
217+
/*
218+
We'll be rounding allocation sizes to the next multiple of whatever the minimum
219+
alignment we will ever need is. We need to know that minimum alignment to
220+
create space for the free store. Unfortunately, it's hard to compute what we
221+
want under all circumstances at compile-time, espcially since this has to be
222+
correct after any rounding. For example, if NOT_MINIMUM_ALIGNMENT is 4 and
223+
fxfMINSIZE is 3 then
224+
1. We'd start by assuming that an allocation of size 3 can't require an alignment
225+
greater than 2.
226+
2. If we assume the minimum alignment is 2, then allocations will be rounded up
227+
to multiples of 2.
228+
3. Step (2) would round the allocation of size 3 up to 4 bytes.
229+
4. We'd then observe that an allocation of size 4 can require an alignment as large
230+
as 4.
231+
It seems that if fxfMINSIZE is < NOT_MINIMUM_ALIGNMENT then we want the largest
232+
power of 2 that is < 2 * fxfMINSIZE, but I don't see how to determine that at
233+
compile-time for an arbitrary fxfMINSIZE. What we compute here should be correct
234+
in many cases, and otherwise it should be <= that value; an underestimate here is OK.
235+
*/
190236
#define MIN_ALIGNMENT_UNDERESTIMATE (((NOT_MULTIPLE_ALIGNMENT>>1) < fxfMINSIZE) ? NOT_MULTIPLE_ALIGNMENT : \
191237
(CLEAR_BOTTOM_BIT(fxfMINSIZE) ? (BOTTOM_BIT(fxfMINSIZE)<<2) : \
192238
fxfMINSIZE))
239+
/*
240+
This will store the actual minimum alignment. We'll compute it at run-time.
241+
*/
193242
static size_t min_alignment= NOT_MULTIPLE_ALIGNMENT; /* for now */
194243

244+
245+
/*
246+
This rounds fxfMINSIZE up to a multiple of MIN_ALIGNMENT_UNDERESTIMATE. This should be <= whatever
247+
fxfMINSIZE gets rounded to at run-time, since MIN_ALIGNMENT_UNDERESTIMATE will be <= the computed
248+
min_alignment.
249+
*/
195250
#define ROUNDED_MIN_SIZE_UNDERESTIMATE ROUND_UP_TO_ALIGNMENT(fxfMINSIZE, MIN_ALIGNMENT_UNDERESTIMATE)
251+
252+
/*
253+
We can now create the array for the free store heads. We need to have a head for sizes between
254+
[whatever fxfMINSIZE gets rounded to, fxfMAXSIZE]
255+
that are multiples of min_alignment. Additional entries aren't a problem, so we'll create entries
256+
for every multiple of (the possible
257+
underestimate) MIN_ALIGNMENT_UNDERESTIMATE in the
258+
[ROUNDED_MIN_SIZE_UNDERESTIMATE, fxfMAXSIZE].
259+
SIZEDATA_SIZE_TO_INDEX maps these values into {0, 1, 2, ..., N}, and we use N to determine how many
260+
heads we need.
261+
*/
196262
#define SIZEDATA_SIZE_TO_INDEX(s) (((s) - ROUNDED_MIN_SIZE_UNDERESTIMATE)/MIN_ALIGNMENT_UNDERESTIMATE)
197263
#define SIZEDATA_INDEX_TO_SIZE(x) ((size_t)(((x) * MIN_ALIGNMENT_UNDERESTIMATE) + ROUNDED_MIN_SIZE_UNDERESTIMATE))
198264
static SizeHead SizeData[1 + SIZEDATA_SIZE_TO_INDEX(fxfMAXSIZE)];
@@ -383,7 +449,7 @@ size_t fxfInit(size_t Size) {
383449
}
384450
else
385451
{
386-
Size = ((Size+31)>>5);
452+
Size = ((Size+31)>>5);
387453
}
388454

389455
FreeMap= (FreeMapType *)nNewCallocUntyped(Size, FreeMapType);
@@ -645,16 +711,32 @@ void *fxfAllocRaw(size_t size, size_t desired_alignment) {
645711
#else
646712
(size_t)pointerDifference(BotFreePtr,Arena);
647713
#endif
714+
/*
715+
Determine what alignment this allocation actually requires.
716+
*/
648717
size_t needed_alignment_mask= (NOT_MULTIPLE_ALIGNMENT-1U);
649718
while (needed_alignment_mask >= size)
650719
needed_alignment_mask>>= 1;
720+
721+
/*
722+
We only care about our offset modulo the required alignment.
723+
*/
651724
curBottomIndex&= needed_alignment_mask;
652725
if (curBottomIndex) {
726+
/*
727+
We aren't aligned as strongly as we need to be for this allocation. Let's step until
728+
we are, and we'll add what we skip over to the free store. If we won't have a enough
729+
space left then move on to the next segment.
730+
*/
653731
if ((needed_alignment_mask - curBottomIndex) >= (sizeCurrentSeg - size))
654732
goto NEXT_SEGMENT;
655733
do {
656734
size_t const cur_alignment= BOTTOM_BIT(curBottomIndex);
657-
pushOntoFreeStore(BotFreePtr, cur_alignment);
735+
assert(cur_alignment >= min_alignment);
736+
if (cur_alignment >= ALIGN_TO_MINIMUM(fxfMINSIZE))
737+
pushOntoFreeStore(BotFreePtr, cur_alignment);
738+
else
739+
TMDBG(printf(" leaking %" SIZE_T_PRINTF_SPECIFIER " byte(s) instead of adding them to the free store\n", (size_t_printf_type)cur_alignment));
658740
BotFreePtr= stepPointer(BotFreePtr, (ptrdiff_t)cur_alignment);
659741
curBottomIndex+= cur_alignment;
660742
} while (curBottomIndex & needed_alignment_mask);
@@ -680,22 +762,40 @@ void *fxfAllocRaw(size_t size, size_t desired_alignment) {
680762
NEXT_SEGMENT:
681763
#if defined(SEGMENTED)
682764
if ((CurrentSeg+1) < ArenaSegCnt) {
765+
/*
766+
We're about to move to the next segment, but let's put whatever we can into the free store.
767+
*/
683768
size_t curBottomIndex= (size_t)pointerDifference(BotFreePtr,Arena[CurrentSeg]);
769+
/*
770+
Add small powers of two until we reach NOT_MULTIPLE_ALIGNMENT.
771+
*/
772+
size_t cur_alignment;
684773
while (curBottomIndex & (NOT_MULTIPLE_ALIGNMENT-1U))
685774
{
686-
size_t const cur_alignment= BOTTOM_BIT(curBottomIndex);
687-
pushOntoFreeStore(BotFreePtr, cur_alignment);
775+
cur_alignment= BOTTOM_BIT(curBottomIndex);
776+
assert(cur_alignment >= min_alignment);
777+
if (cur_alignment >= ALIGN_TO_MINIMUM(fxfMINSIZE))
778+
pushOntoFreeStore(BotFreePtr, cur_alignment);
779+
else
780+
TMDBG(printf(" leaking %" SIZE_T_PRINTF_SPECIFIER " byte(s) instead of adding them to the free store\n", (size_t_printf_type)cur_alignment));
688781
BotFreePtr= stepPointer(BotFreePtr, (ptrdiff_t)cur_alignment);
689782
curBottomIndex+= cur_alignment;
690783
}
691-
curBottomIndex= (size_t)pointerDifference(TopFreePtr,BotFreePtr);
692-
if (curBottomIndex >= fxfMINSIZE)
784+
/*
785+
If there's anything left, we can add it all. Here we take advantage of the fact that
786+
the whole segment is fully aligned, so if what's left requires full alignment then
787+
the pointer must be fully aligned when we get here.
788+
*/
789+
cur_alignment= (size_t)pointerDifference(TopFreePtr,BotFreePtr); /* Now stores the remaining space. */
790+
if (cur_alignment)
693791
{
694-
assert(!(curBottomIndex & (NOT_MULTIPLE_ALIGNMENT - 1U)));
695-
pushOntoFreeStore(BotFreePtr, curBottomIndex);
792+
assert(!((cur_alignment | curBottomIndex) & (NOT_MULTIPLE_ALIGNMENT-1U))); /* Must be divisible by and aligned for NOT_MULTIPLE_ALIGNMENT. */
793+
assert((cur_alignment & PTRMASK) || !(curBottomIndex & PTRMASK)); /* If we're divisible by MAX_ALIGNMENT then we must be properly aligned for that. */
794+
if (cur_alignment >= ALIGN_TO_MINIMUM(fxfMINSIZE))
795+
pushOntoFreeStore(BotFreePtr, cur_alignment);
796+
else
797+
TMDBG(printf(" leaking %" SIZE_T_PRINTF_SPECIFIER " byte(s) moving from segment %d to segment %d\n", (size_t_printf_type)cur_alignment, CurrentSeg, CurrentSeg+1));
696798
}
697-
else if (curBottomIndex)
698-
TMDBG(printf(" leaking %" SIZE_T_PRINTF_SPECIFIER " byte(s) moving from segment %d to segment %d\n", (size_t_printf_type)curBottomIndex, CurrentSeg, CurrentSeg+1));
699799
TMDBG(fputs(" next seg", stdout));
700800
++CurrentSeg;
701801
BotFreePtr= Arena[CurrentSeg];
@@ -842,7 +942,7 @@ void *fxfReAllocRaw(void *ptr, size_t OldSize, size_t NewSize, size_t desired_al
842942
ptrdiff_t const ptrIndex= pointerDifference(ptr,Arena);
843943
assert(GlobalSize > (size_t)ptrIndex);
844944
# endif
845-
assert(ptrIndex >= 0);
945+
assert(ptrIndex >= 0);
846946
if (ptrIndex > 0)
847947
{
848948
size_t allocatedSize= OldSize;
@@ -869,7 +969,7 @@ void *fxfReAllocRaw(void *ptr, size_t OldSize, size_t NewSize, size_t desired_al
869969
needed_alignment= MAX_ALIGNMENT;
870970
assert(!(((size_t)ptrIndex) & (needed_alignment - 1U)));
871971
}
872-
}
972+
}
873973
#endif
874974
assert(desired_alignment && !CLEAR_BOTTOM_BIT(desired_alignment));
875975
assert(desired_alignment <= OldSize);
@@ -889,7 +989,7 @@ void *fxfReAllocRaw(void *ptr, size_t OldSize, size_t NewSize, size_t desired_al
889989
if (needed_allocation < fxfMINSIZE)
890990
needed_allocation= fxfMINSIZE;
891991
needed_allocation= ALIGN_TO_MINIMUM(needed_allocation);
892-
if (needed_allocation == original_allocation)
992+
if (needed_allocation == original_allocation)
893993
return ptr;
894994
/* TODO: Should we try to break apart this chunk? */
895995
}

EXAMPLES/alice.inp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
begin
2+
3+
protocol alice.ref
4+
5+
author Joost Michielsen
6+
origin Andernach 2025, 2nd place
7+
Stipulation dia10.5
8+
Pieces
9+
white Rh1a8a1 Sg1 Bf1c1 Ke1 Qd1 Ph2g2f2e2d2c2b2
10+
white AliceB Sa3
11+
black Ph7g7f7e7d7c7 Rh8 Sg8 Bf8 Qd8
12+
black AliceB Bb7 Pb6a5 Ra4 Kb8 Sa6
13+
14+
next
15+
16+
author Thomas Maeder & Kjell Widlert
17+
origin Andernach 2025, 3rd place
18+
pieces white ke5 pc2d3e6 white AliceB qd7 bh4 sa8 pb5c3e3f4
19+
black kb8 ba2 sd5 pd4e7 black AliceB ra4 ba7 pb6e4g6
20+
stip #3
21+
option try vari
22+
23+
next
24+
25+
author Manfred Rittirsch & Franz Pachl
26+
origin Andernach 2025, 4th place
27+
pieces white kh1 rg2 pe6g3g6 white AliceB bf7
28+
black rd2e7 bd5g7 pd3g4 black AliceB kf8
29+
stip h#2
30+
twin move h1 h2
31+
32+
next
33+
34+
author Michel Caillaud
35+
origin Andernach 2025, 5th place
36+
pieces white ka1 qc5 white AliceB rc3 black AliceB ke5 pd2
37+
stip h#2
38+
39+
next
40+
41+
author Manfred Rittirsch & Franz Pachl
42+
origin Andernach 2025, 6th place
43+
pieces white AliceB kh5 rh4 bc8f4 sd7g4 black kd5 ra1 pc5f2g5g7 black AliceB bc7 se1 pa4c6d3g3
44+
stip h#2
45+
46+
next
47+
48+
author Ralf Kr\"atschmer & Franz Pachl & Manfred Rittirsch
49+
origin Andernach 2025, 7th place
50+
pieces white kd1 qd7 rh4 ba5 pa4d4d5d6e4f2 white AliceB sc6e6 pb3e2
51+
black kd3 ra3g8 ba7b1 pb7f6 black AliceB sd8h6 pa6h3
52+
stipulation #2
53+
option try vari
54+
55+
next
56+
57+
author Michel Caillaud
58+
origin Andernach 2025, 8th place
59+
pieces white kf8 pd4f3 white AliceB ra4 bh1
60+
black kd1 black AliceB rc1e1 ba3
61+
stip h#2.5
62+
63+
end
64+

EXAMPLES/bolero.inp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,13 @@ pieces white kf4 rc3g2 bh2h7 sc5h3 pb4d2d3d6f5f7h5 black pc6d7 kh6
4343
stipulation ser-h#14
4444
condition boleroinverse rexincl
4545

46+
next
47+
48+
author Geoff Foster
49+
origin Anda Fairy Planet 2020-21, 1st prize
50+
pieces white kd7 black kd5 neutral rc6 ba8
51+
stip h#2
52+
condition bolero rexincl
53+
4654
end
4755

REGRESSIONS/4_89_to_4_91.inp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ next
165165
title an intermediate version found 1...[+wRa1]0-0-0[d1=wR] 2.TI~*f2 TI~-~[f2=bK] 3.Ba5-e1 Rd1-d2 4.Kf2-g1 TI~*e1 #, but 2.-Sb4-c2 and no mate
166166
pieces white ke1 pf2 black ba5 totalinv 3
167167
stipulation h#3.5
168-
option movenum start 3:2:1:11:13:4:2:1 upto 3:2:1:11:13:4:2:40
168+
option movenum start 3:2:1:11:13:4:2 upto 3:2:1:11:13:4:2
169169

170170
next
171171

0 commit comments

Comments
 (0)