package gnarlring import ( "math" "testing" ) func TestGaussSampleZCDT(t *testing.T) { sigma := math.Sqrt(float64(N)) * 2.0 // ≈ 10.39 gs := NewGaussSampler(sigma) // Sample many values, check mean is near 0 and variance is near sigma^2. const samples = 50000 var sum int64 var sumSq float64 for i := 0; i < samples; i++ { z := gs.SampleZ(0) sum += z sumSq += float64(z) * float64(z) } mean := float64(sum) / float64(samples) variance := sumSq / float64(samples) // Standard error for mean: σ/√n ≈ 10.4/223 ≈ 0.05. // 3σ interval: [-0.15, +0.15]. if mean < -0.15 || mean > 0.15 { t.Fatalf("mean %f outside [-0.15, 0.15]", mean) } // Variance target: σ²/(2π) ≈ 108/(2π) ≈ 17.2 for discrete Gaussian. // For 50k samples, std err ≈ 17.2×√(2/n) ≈ 17.2×√(2/50000) ≈ 0.11. // 5σ interval: [17.2-0.55, 17.2+0.55] ≈ [16.65, 17.75]. if variance < 16.5 || variance > 18.0 { t.Fatalf("variance %f outside [106, 110]", variance) } } func TestGaussSampleZBounds(t *testing.T) { sigma := math.Sqrt(float64(N)) * 2.0 gs := NewGaussSampler(sigma) for i := 0; i < 10000; i++ { z := gs.SampleZ(0) // Should never exceed 13*sigma ≈ 135. if z < -140 || z > 140 { t.Fatalf("sample %d outside bounds", z) } } } func TestGaussSamplePoly(t *testing.T) { sigma := math.Sqrt(float64(N)) * 2.0 gs := NewGaussSampler(sigma) p := gs.SamplePoly() // Should be non-zero with high probability. if IsZero(p) { t.Fatal("SamplePoly returned zero polynomial (astronomically unlikely)") } // All coefficients should be small (< 135). for i, v := range p.Coeffs { // Convert to centered. half := uint16(Q / 2) var absV uint16 if v > half { absV = Q - v } else { absV = v } if absV > 140 { t.Fatalf("coefficient %d too large: %d", i, absV) } } } func TestGaussSamplePolyReproducible(t *testing.T) { sigma := math.Sqrt(float64(N)) * 2.0 // Two samplers with different RNG should produce different outputs. gs1 := NewGaussSampler(sigma) gs2 := NewGaussSampler(sigma) p1 := gs1.SamplePoly() p2 := gs2.SamplePoly() if Equal(p1, p2) { t.Log("two SamplePoly outputs identical (possible but unlikely — retry)") // Not a hard failure — genuinely possible at 1/2^243 probability. } } func TestGaussSampleZWithCenter(t *testing.T) { sigma := math.Sqrt(float64(N)) * 2.0 gs := NewGaussSampler(sigma) const samples = 20000 var sum int64 for i := 0; i < samples; i++ { z := gs.SampleZ(5.0) sum += z } mean := float64(sum) / float64(samples) if mean < 4.5 || mean > 5.5 { t.Fatalf("centered mean %f outside [4.5, 5.5]", mean) } }