73 lines
3.7 KiB
C++
73 lines
3.7 KiB
C++
#include "interval_solver.hpp"
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <iostream>
|
|
#include <random>
|
|
#include <stdexcept>
|
|
#include <vector>
|
|
|
|
namespace sr=slime_research;
|
|
namespace fs=full_search_experiment;
|
|
struct Emit {std::vector<uint64_t>& result;void operator()(uint64_t s){result.push_back(s);}};
|
|
void require(bool b,const char*message){if(!b)throw std::runtime_error(message);}
|
|
|
|
// Separate Java arithmetic oracle. Every conversion is explicit to avoid signed overflow.
|
|
uint64_t term(int32_t x,int32_t z){
|
|
auto sx=[](uint32_t n){return uint64_t(int64_t(int32_t(n)));};
|
|
uint32_t a=uint32_t(x),b=uint32_t(z);
|
|
return sx(a*a*4987142U)+sx(a*5947611U)+sx(b*b)*4392871ULL+sx(b*389711U);
|
|
}
|
|
bool exact(uint64_t seed,uint64_t coordinate){
|
|
uint64_t s=((seed+coordinate)^987234911ULL^0x5DEECE66DULL)&((1ULL<<48)-1);
|
|
for(;;){s=(s*0x5DEECE66DULL+11)&((1ULL<<48)-1);uint32_t q=s>>17;
|
|
if(q<2147483640U)return q%10==0;}
|
|
}
|
|
int main(){
|
|
std::mt19937_64 rng(2026101102);
|
|
uint64_t checked=0;
|
|
for(int test=0;test<4096;++test){
|
|
int32_t x=int32_t(rng()%3750000)-1875000,z=int32_t(rng()%3750000)-1875000;
|
|
if(test<24){x=51069;z=419124;}
|
|
std::array<sr::CellTerm,25> cells;
|
|
for(int j=0;j<5;j++)for(int i=0;i<5;i++)cells[j*5+i]={term(x+i,z+j),sr::kSlime};
|
|
int count=test<24?25:1+test%25;
|
|
uint64_t low=rng()&((1ULL<<35)-1);
|
|
if(test<24)low=(test%2?15959335054446ULL:61692151016558ULL)&((1ULL<<35)-1);
|
|
std::vector<uint64_t> direct,old,interval,filtered;Emit a{old},b{interval},c{filtered};
|
|
sr::solveUpper13(low,cells.data(),count,a);fs::solveIntervals(low,cells.data(),count,b);
|
|
if(fs::differenceFilter(low,cells.data(),count))fs::solveIntervals(low,cells.data(),count,c);
|
|
for(uint64_t h=0;h<8192;++h){
|
|
uint64_t s=low+(h<<35);bool ok=true;
|
|
for(int i=0;i<count;++i){
|
|
uint64_t v=(((s+cells[i].term)^0x5E434E432ULL)*0x5DEECE66DULL+11)&((1ULL<<48)-1);
|
|
if((v>>17)%10!=0||!exact(s,cells[i].term)){ok=false;break;}
|
|
}
|
|
if(ok)direct.push_back(s);
|
|
}
|
|
std::sort(old.begin(),old.end());std::sort(interval.begin(),interval.end());std::sort(filtered.begin(),filtered.end());
|
|
require(old==direct&&interval==direct&&filtered==direct,"upper enumeration mismatch");checked+=8192;
|
|
}
|
|
uint64_t rejectedSlime=0,oddRejectedSlime=0;
|
|
for(uint64_t v=uint64_t(2147483640U)<<17;v<(1ULL<<48);++v){
|
|
const uint64_t t=term(-1875000,1874999);
|
|
const uint64_t u=((v-11)*0xDFE05BCB1365ULL)&((1ULL<<48)-1);
|
|
const uint64_t seed=((u^0x5E434E432ULL)-t)&((1ULL<<48)-1);
|
|
const uint64_t recovered=(((seed+t)^0x5E434E432ULL)*0x5DEECE66DULL+11)&((1ULL<<48)-1);
|
|
require(v==recovered,"tail inversion mismatch");
|
|
bool a=exact(seed,t),b=sr::exactIsSlimeFromTerm(seed,t);require(a==b,"Java oracle mismatch");
|
|
rejectedSlime+=a;oddRejectedSlime+=a&&((v>>17)&1);
|
|
}
|
|
require(oddRejectedSlime>0,"missing rejection regression example");
|
|
for(int n=0;n<10000;++n){
|
|
int32_t x=int32_t(rng()%3750000)-1875000,z=int32_t(rng()%3750000)-1875000;
|
|
for(int j=0;j<5;++j)for(int i=0;i<5;++i){
|
|
uint64_t d=(term(x+i,z+j)-term(x,z))&((1U<<18)-1);
|
|
require(d==((term(x+65536+i,z+j)-term(x+65536,z))&((1U<<18)-1)),"X periodicity mismatch");
|
|
require(d==((term(x+i,z+131072+j)-term(x,z+131072))&((1U<<18)-1)),"Z periodicity mismatch");
|
|
}
|
|
}
|
|
std::cout<<"{\"upper_planes\":4096,\"direct_seeds\":"<<checked
|
|
<<",\"tail_states\":1048576,\"tail_slime\":"<<rejectedSlime
|
|
<<",\"odd_tail_slime\":"<<oddRejectedSlime
|
|
<<",\"periodicity_cells\":250000,\"passed\":true}\n";
|
|
}
|