From: Nick Bowler Date: Sat, 5 Mar 2022 20:51:40 +0000 (-0500) Subject: Fix distribution. X-Git-Url: http://git.draconx.ca/gitweb/rrace.git/commitdiff_plain/30f49b9152dcf5ce7baefa9287b0ec627155fba9?hp=e9ab90141032c23a97fa82a723a7a751658bce66 Fix distribution. --- diff --git a/.gitignore b/.gitignore index 92acc78..fc36602 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ /testsuite /testsuite.deps /testsuite.dir +/testsuite.log diff --git a/Makefile.am b/Makefile.am index 48a0b4e..0ce64bc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,7 @@ AM_CFLAGS = $(MOTIF_CFLAGS) bin_PROGRAMS = rrace-motif -rrace_motif_SOURCES = src/game.c src/x11.c +rrace_motif_SOURCES = src/game.c src/x11.c src/game.h src/motif.h rrace_motif_LDADD = $(libmotifmain_a_OBJECTS) $(libmotifui_a_OBJECTS) \ $(libglohelp_a_OBJECTS) libgnu.a $(MOTIF_LIBS) $(rrace_motif_OBJECTS): $(gnulib_headers) @@ -35,7 +35,7 @@ $(libmotifui_a_OBJECTS): $(gnulib_headers) $(libmotifui_a_OBJECTS): src/motifgui.h src/motifstr.h EXTRA_LIBRARIES += libglohelp.a -libglohelp_a_SOURCES = common/src/help.c +libglohelp_a_SOURCES = common/src/help.c common/src/help.h libglohelp_a_CFLAGS = -DHELP_GETOPT_LONG_ONLY $(libglohelp_a_OBJECTS): $(gnulib_headers) libglohelp_a_SHORTNAME = glo @@ -54,7 +54,7 @@ STRFILES = src/motifstr.str $(AM_V_at) mv -f $@.tmp $@ $(STRFILES:.str=.h): $(DX_BASEDIR)/scripts/gen-strtab.awk DISTCLEANFILES += $(STRFILES:.str=.h) -EXTRA_DIST += $(DX_BASEDIR)/scripts/gen-strtab.awk $(GUIFILES) +EXTRA_DIST += $(DX_BASEDIR)/scripts/gen-strtab.awk $(STRFILES) GUIFILES = src/motifgui.dat .dat.h: @@ -65,6 +65,7 @@ DISTCLEANFILES += $(GUIFILES:.dat=.h) EXTRA_DIST += $(DX_BASEDIR)/scripts/gen-tree.awk $(GUIFILES) check_PROGRAMS = t/boardmove t/rng-test +EXTRA_DIST += t/xos256ss.c t_boardmove_LDADD = src/game.$(OBJEXT) libgnu.a $(t_boardmove_OBJECTS): $(gnulib_headers) diff --git a/t/.gitignore b/t/.gitignore new file mode 100644 index 0000000..46a482f --- /dev/null +++ b/t/.gitignore @@ -0,0 +1,2 @@ +/boardmove +/rng-test diff --git a/t/rng-test.c b/t/rng-test.c new file mode 100644 index 0000000..78797ab --- /dev/null +++ b/t/rng-test.c @@ -0,0 +1,81 @@ +/* + * Test case for xoshiro256** implementation. + * Copyright © 2022 Nick Bowler + * + * Directly compare the game RNG against the reference implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "game.c" +#include "xos256ss.c" + +int main(void) +{ + unsigned long long seed_state = 0xdeadbeeff00dcafe; + unsigned long long test_result, ref_result; + unsigned long long ref_state[4], test_state[4]; + int i, ret = 0; + + printf("1..200\n"); + for (i = 0; i < 100; i++) { + s[0] = ref_state[0] = test_state[0] = splitmix64(&seed_state); + s[1] = ref_state[1] = test_state[1] = splitmix64(&seed_state); + s[2] = ref_state[2] = test_state[2] = splitmix64(&seed_state); + s[3] = ref_state[3] = test_state[3] = splitmix64(&seed_state); + + ref_result = next(); + test_result = xoshiro256ss(test_state); + + if (ref_result != test_result) { + printf("not ok %d rng output\n", 2*i+1); + printf("# Failed, unexpected result\n"); + printf("# with initial state %llx %llx %llx %llx\n", + ref_state[0], ref_state[1], + ref_state[2], ref_state[3]); + printf("# received: %llx\n", test_result); + printf("# expected: %llx\n", ref_result); + ret = EXIT_FAILURE; + } else { + printf("ok %d rng output\n", 2*i+1); + } + + if (s[0] != test_state[0] || s[1] != test_state[1] + || s[2] != test_state[2] || s[3] != test_state[3]) + { + printf("not ok %d rng state update\n", 2*i+2); + printf("# Failed, state update differed\n"); + printf("# with initial state %llx %llx %llx %llx\n", + ref_state[0], ref_state[1], + ref_state[2], ref_state[3]); + printf("# received: %llx %llx %llx %llx\n", + test_state[0], test_state[1], + test_state[2], test_state[3]); + printf("# expected: %llx %llx %llx %llx\n", + (unsigned long long)s[0], + (unsigned long long)s[1], + (unsigned long long)s[2], + (unsigned long long)s[3]); + ret = EXIT_FAILURE; + } else { + printf("ok %d rng state update\n", 2*i+2); + } + } + + return ret; +} diff --git a/t/xos256ss.c b/t/xos256ss.c new file mode 100644 index 0000000..d0b83a2 --- /dev/null +++ b/t/xos256ss.c @@ -0,0 +1,104 @@ +/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ + +#include + +/* This is xoshiro256** 1.0, one of our all-purpose, rock-solid + generators. It has excellent (sub-ns) speed, a state (256 bits) that is + large enough for any parallel application, and it passes all tests we + are aware of. + + For generating just floating-point numbers, xoshiro256+ is even faster. + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. */ + +static inline uint64_t rotl(const uint64_t x, int k) { + return (x << k) | (x >> (64 - k)); +} + + +static uint64_t s[4]; + +uint64_t next(void) { + const uint64_t result = rotl(s[1] * 5, 7) * 9; + + const uint64_t t = s[1] << 17; + + s[2] ^= s[0]; + s[3] ^= s[1]; + s[1] ^= s[2]; + s[0] ^= s[3]; + + s[2] ^= t; + + s[3] = rotl(s[3], 45); + + return result; +} + + +/* This is the jump function for the generator. It is equivalent + to 2^128 calls to next(); it can be used to generate 2^128 + non-overlapping subsequences for parallel computations. */ + +void jump(void) { + static const uint64_t JUMP[] = { 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c }; + + uint64_t s0 = 0; + uint64_t s1 = 0; + uint64_t s2 = 0; + uint64_t s3 = 0; + for(int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) + for(int b = 0; b < 64; b++) { + if (JUMP[i] & UINT64_C(1) << b) { + s0 ^= s[0]; + s1 ^= s[1]; + s2 ^= s[2]; + s3 ^= s[3]; + } + next(); + } + + s[0] = s0; + s[1] = s1; + s[2] = s2; + s[3] = s3; +} + + + +/* This is the long-jump function for the generator. It is equivalent to + 2^192 calls to next(); it can be used to generate 2^64 starting points, + from each of which jump() will generate 2^64 non-overlapping + subsequences for parallel distributed computations. */ + +void long_jump(void) { + static const uint64_t LONG_JUMP[] = { 0x76e15d3efefdcbbf, 0xc5004e441c522fb3, 0x77710069854ee241, 0x39109bb02acbe635 }; + + uint64_t s0 = 0; + uint64_t s1 = 0; + uint64_t s2 = 0; + uint64_t s3 = 0; + for(int i = 0; i < sizeof LONG_JUMP / sizeof *LONG_JUMP; i++) + for(int b = 0; b < 64; b++) { + if (LONG_JUMP[i] & UINT64_C(1) << b) { + s0 ^= s[0]; + s1 ^= s[1]; + s2 ^= s[2]; + s3 ^= s[3]; + } + next(); + } + + s[0] = s0; + s[1] = s1; + s[2] = s2; + s[3] = s3; +} diff --git a/tests/game.at b/tests/game.at index c90ff87..9cfc7af 100644 --- a/tests/game.at +++ b/tests/game.at @@ -540,3 +540,11 @@ AT_CHECK([boardmove m4_do( ]]) AT_CLEANUP + +AT_SETUP([xoshiro256** sanity]) + +AT_CHECK([rng-test >out +grep -v '^ok' out], [0], [1..200 +]) + +AT_CLEANUP