42 lines
1.6 KiB
C++
42 lines
1.6 KiB
C++
#pragma once
|
|
#include "../full_search_feasibility/interval_solver.hpp"
|
|
#if defined(__CUDACC__)
|
|
#define NS_HD __host__ __device__ __forceinline__
|
|
#else
|
|
#define NS_HD inline
|
|
#endif
|
|
namespace normal_search {
|
|
namespace sr=slime_research;
|
|
struct Prepared { uint32_t h[25], b[25]; };
|
|
NS_HD void prepare(uint32_t root,const sr::CellTerm* cells,Prepared& out){
|
|
for(int i=0;i<25;++i){
|
|
const uint64_t a=root+cells[i].term;
|
|
out.h[i]=uint32_t(a>>18);
|
|
const uint64_t lo=(a^sr::kCombinedXor)&((1U<<18)-1);
|
|
out.b[i]=uint32_t((lo*sr::kJavaMultiplier+11)>>17);
|
|
}
|
|
}
|
|
NS_HD uint32_t preparedQ(const Prepared& p,int i,uint32_t m){
|
|
const uint32_t u=(m+p.h[i])^uint32_t(sr::kCombinedXor>>18);
|
|
return (p.b[i]+2U*uint32_t(sr::kJavaMultiplier)*u)&0x7fffffffU;
|
|
}
|
|
|
|
// Bits 4..7 of kCombinedXor >> 18 are zero. For m=base+16*j,
|
|
// j in [0,16), m XOR C is affine. Each shifted input crosses at
|
|
// most one 256 boundary, so each output difference has at most two values.
|
|
// base bits 4..7 must be zero; cells[0].term must be zero (normalized anchor).
|
|
NS_HD uint32_t groupMask(const Prepared& p,uint32_t base,int count=25){
|
|
uint32_t mask=65535;
|
|
const uint32_t q0=preparedQ(p,0,base),qend=preparedQ(p,0,base+240);
|
|
for(int i=1;i<count&&mask;++i){
|
|
const uint32_t n=(256-((base+p.h[i])&255)+15)>>4;
|
|
const uint32_t before=(1U<<n)-1;
|
|
const uint32_t r0=((preparedQ(p,i,base)-q0)&0x7fffffffU)%10;
|
|
const uint32_t r1=((preparedQ(p,i,base+240)-qend)&0x7fffffffU)%10;
|
|
const uint32_t allowed=((r0==0||r0==8)?before:0U)|((r1==0||r1==8)?(65535U^before):0U);
|
|
mask &= allowed;
|
|
}
|
|
return mask;
|
|
}
|
|
}
|
|
#undef NS_HD
|