summaryrefslogtreecommitdiff
path: root/factors/factors_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'factors/factors_test.go')
-rw-r--r--factors/factors_test.go404
1 files changed, 0 insertions, 404 deletions
diff --git a/factors/factors_test.go b/factors/factors_test.go
deleted file mode 100644
index ab06aba..0000000
--- a/factors/factors_test.go
+++ /dev/null
@@ -1,404 +0,0 @@
-package factors
-
-import (
- "fmt"
- "maps"
- "slices"
- "testing"
-)
-
-// Run a test with a table of cases
-func tableTest[IN comparable, OUT any](t *testing.T, toTest func(IN) OUT,
- cases map[IN]OUT, equal func(OUT, OUT) bool, name string) {
- for input, expected := range cases {
- t.Run(fmt.Sprintf("%v", input), func(t *testing.T) {
- actual := toTest(input)
- if !equal(expected, actual) {
- t.Errorf("%s(%v) = %v, expect %v", name, input, actual, expected)
- }
- })
- }
-}
-
-type uintPair struct{ a, b uint }
-
-var primeFactorCases = map[uint]PrimeFactorization{
- 0: PrimeFactorization{map[uint]uint{0: 1}},
- 1: PrimeFactorization{map[uint]uint{}},
- 2: PrimeFactorization{map[uint]uint{2: 1}},
- 3: PrimeFactorization{map[uint]uint{3: 1}},
- 4: PrimeFactorization{map[uint]uint{2: 2}},
- 6: PrimeFactorization{map[uint]uint{2: 1, 3: 1}},
- 9: PrimeFactorization{map[uint]uint{3: 2}},
- 10: PrimeFactorization{map[uint]uint{2: 1, 5: 1}},
- 12: PrimeFactorization{map[uint]uint{2: 2, 3: 1}},
- 33: PrimeFactorization{map[uint]uint{3: 1, 11: 1}},
- 60: PrimeFactorization{map[uint]uint{2: 2, 3: 1, 5: 1}},
- 71: PrimeFactorization{map[uint]uint{71: 1}},
- 1024: PrimeFactorization{map[uint]uint{2: 10}},
- 86400: PrimeFactorization{map[uint]uint{2: 7, 3: 3, 5: 2}},
-}
-
-func TestPrimeFactorize(t *testing.T) {
- equal := func(a, b PrimeFactorization) bool {
- return maps.Equal(a.exponents, b.exponents)
- }
- tableTest(t, PrimeFactorize, primeFactorCases, equal, "PrimeFactorize")
-}
-
-var factorCases = map[uint][]uint{
- 1: []uint{1},
- 2: []uint{1, 2},
- 4: []uint{1, 2, 4},
- 6: []uint{1, 2, 3, 6},
- 9: []uint{1, 3, 9},
- 10: []uint{1, 2, 5, 10},
- 12: []uint{1, 2, 3, 4, 6, 12},
- 13: []uint{1, 13},
- 15: []uint{1, 3, 5, 15},
- 16: []uint{1, 2, 4, 8, 16},
- 18: []uint{1, 2, 3, 6, 9, 18},
- 30: []uint{1, 2, 3, 5, 6, 10, 15, 30},
- 32: []uint{1, 2, 4, 8, 16, 32},
- 33: []uint{1, 3, 11, 33},
- 60: []uint{1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60},
- 71: []uint{1, 71},
-}
-
-func TestFactors(t *testing.T) {
- tableTest(t, Factors, factorCases, setEquals, "Factors")
-}
-
-var totativeRatioCases = map[uint]float64{
- 1: 1.0, 2: 0.5, 3: 2.0 / 3.0, 4: 0.5, 6: 1.0 / 3.0, 7: 6.0 / 7.0, 8: 0.5,
- 10: 0.4, 12: 1.0 / 3.0, 14: 3.0 / 7.0, 15: 8.0 / 15.0, 16: 0.5, 20: 0.4,
- 24: 1.0 / 3.0, 30: 4.0 / 15.0, 60: 4.0 / 15.0, 71: 70.0 / 71.0,
- 120: 4.0 / 15.0,
-}
-
-func totativeRatio(n uint) float64 {
- return float64(Totient(n)) / float64(n)
-}
-
-func TestTotativeRatio(t *testing.T) {
- tableTest(t, totativeRatio, totativeRatioCases, stdEquals, "TotativeRatio")
-}
-
-var totientCases = map[uint]uint{
- 0: 0, 1: 1, 2: 1, 3: 2, 4: 2, 6: 2, 7: 6, 8: 4, 10: 4, 12: 4,
- 14: 6, 15: 8, 16: 8, 20: 8, 24: 8, 30: 8, 60: 16, 71: 70, 120: 32,
-}
-
-func TestTotativeCount(t *testing.T) {
- tableTest(t, Totient, totientCases, stdEquals, "Totient")
-}
-
-var totativeDigitCases = map[uint32][]uint32{
- 0: []uint32{},
- 1: []uint32{1},
- 2: []uint32{1},
- 3: []uint32{1, 2},
- 4: []uint32{1, 3},
- 6: []uint32{1, 5},
- 7: []uint32{1, 2, 3, 4, 5, 6},
- 8: []uint32{1, 3, 5, 7},
- 10: []uint32{1, 3, 7, 9},
- 12: []uint32{1, 5, 7, 11},
- 14: []uint32{1, 3, 5, 9, 11, 13},
- 15: []uint32{1, 2, 4, 7, 8, 11, 13, 14},
- 16: []uint32{1, 3, 5, 7, 9, 11, 13, 15},
- 20: []uint32{1, 3, 7, 9, 11, 13, 17, 19},
- 24: []uint32{1, 5, 7, 11, 13, 17, 19, 23},
- 30: []uint32{1, 7, 11, 13, 17, 19, 23, 29},
- 60: []uint32{1, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 49, 53, 59},
- 71: []uint32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
- 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
- 61, 62, 63, 64, 65, 66, 67, 68, 69, 70},
- 120: []uint32{1, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 49, 53, 59,
- 61, 67, 71, 73, 77, 79, 83, 89, 91, 97, 101, 103, 107, 109, 113, 119},
-}
-
-func TestTotativeDigits(t *testing.T) {
- tableTest(t, TotativeDigits, totativeDigitCases, slices.Equal,
- "TotativeDigits")
-}
-
-var factorScoreCases = map[uint]float64{
- 1: 1.0,
- 2: 1.5,
- 3: 4.0 / 3.0,
- 4: 1.75,
- 6: 2.0,
- 8: 1.875,
- 10: 1.8,
- 12: 7.0 / 3.0,
- 71: 72.0 / 71.0,
- 120: 3.0,
- // number that will use bigScore
- 367567200: 62496.0 / 12155.0,
-}
-
-func TestFactorScore(t *testing.T) {
- // factors.Score is accurate enough that we can test for exact floats!
- tableTest(t, Score, factorScoreCases, stdEquals, "Score")
-}
-
-var basicRankCases = map[uint]string{
- // one test per rank, plus three extra (22, 25, 44) to test that
- // n%3 = 1 vs n%3 = 2 doesn't matter
- 2: "D-", 3: "E-", 4: "C~", 5: "F+", 6: "B~", 7: "F-", 8: "C-",
- 9: "E~", 10: "D+", 11: "F~", 12: "A-", 14: "D~", 15: "E+", 18: "B-",
- 20: "C+", 22: "D-", 24: "A~", 25: "F+", 30: "B+", 44: "C~", 60: "A+",
- // test that it only depends on n%60
- 62: "D-", 63: "E-", 64: "C~", 65: "F+", 66: "B~", 67: "F-", 68: "C-",
- 69: "E~", 70: "D+", 71: "F~", 72: "A-", 74: "D~", 75: "E+", 78: "B-",
- 80: "C+", 82: "D-", 84: "A~", 85: "F+", 90: "B+", 104: "C~", 120: "A+",
- // test that it can extend to 0 and 1 as well
- 0: "A+", 1: "F~",
-}
-
-func TestBasicRank(t *testing.T) {
- tableTest(t, BasicRank, basicRankCases, stdEquals, "BasicRank")
-}
-
-var gcdCases = map[struct{ a, b uint32 }]uint32{
- {0, 0}: 0, {1, 1}: 1,
- {0, 1}: 1, {1, 0}: 1,
- {0, 12}: 12, {12, 0}: 12,
- {1, 12}: 1, {12, 1}: 1,
- {6, 10}: 2, {10, 6}: 2,
- {12, 20}: 4, {20, 12}: 4,
- {20, 55}: 5, {55, 20}: 5,
- {60, 120}: 60, {120, 60}: 60,
- {120, 180}: 60, {180, 120}: 60,
-}
-
-// a version of gcd() for testing purposes
-func gcdTest(c struct{ a, b uint32 }) uint32 {
- return gcd(c.a, c.b)
-}
-
-func TestGCD(t *testing.T) {
- tableTest(t, gcdTest, gcdCases, stdEquals, "gcd")
-}
-
-var mtcCases = map[uint32]uint64{
- 2: 0, 3: 0, 4: 2, 5: 10, 6: 8,
- 7: 28, 8: 26, 9: 42, 10: 42, 11: 88, 12: 52,
- 13: 130, 14: 100, 15: 116, 16: 138, 18: 146,
- 20: 190, 24: 252, 28: 416, 30: 380, 32: 618, 36: 598,
- 48: 1100, 60: 1496, 64: 2602, 90: 3662, 120: 6080,
- 210: 18542, 360: 54362, 840: 270122, 2520: 2363528, 5040: 9409112,
-}
-
-func TestMTC(t *testing.T) {
- tableTest(t, MTC, mtcCases, stdEquals, "MTC")
-}
-
-var sanCases = map[uint]bool{
- 1: true, 2: true, 4: true, 6: true, 12: true, 24: true, 36: true,
- 48: true, 60: true, 120: true, 180: true, 240: true, 360: true,
- 720: true, 840: true, 1260: true, 1680: true, 2520: true, 5040: true,
- 10080: true, 15120: true, 25200: true, 27720: true, 55440: true,
- 3: false, 8: false, 13: false, 18: false, 20: false, 30: false,
- 31: false, 72: false, 107: false, 135: false, 144: false, 300: false,
- 1728: false, 4000: false, 6912: false, 7560: false,
-}
-
-func isSAN(n uint) bool {
- return Type(n) >= Superabundant
-}
-
-func TestSAN(t *testing.T) {
- tableTest(t, isSAN, sanCases, stdEquals, "isSAN")
-}
-
-var expOrdCases = map[uint]bool{
- 0: true, 1: true, 2: true, 4: true, 5: false, 6: true, 8: true, 12: true,
- 16: true, 18: false, 20: false, 27: false, 30: true, 36: true, 44: false,
- 60: true, 70: false, 90: false, 96: true, 101: false, 120: true, 144: true,
- 180: true, 770: false, 900: true, 6912: true, 10010: false,
-}
-
-func TestExponentsOrdered(t *testing.T) {
- tableTest(t, exponentsOrdered, expOrdCases, stdEquals, "exponentsOrdered")
-}
-
-var practicalCases = map[uint]bool{
- 1: true, 2: true, 4: true, 6: true, 8: true, 12: true, 16: true,
- 18: true, 20: true, 24: true, 28: true, 30: true, 32: true, 36: true,
- 48: true, 60: true, 120: true, 180: true, 240: true, 360: true,
- 720: true, 840: true, 1260: true, 1680: true, 2520: true, 5040: true,
- 10080: true, 15120: true, 25200: true, 27720: true, 55440: true,
- 3: false, 10: false, 27: false, 44: false, 45: false, 68: false,
- 70: false, 114: false, 121: false, 770: false, 1729: false, 10010: false,
-}
-
-func TestPractical(t *testing.T) {
- tableTest(t, practical, practicalCases, stdEquals, "practical")
-}
-
-var typeCases = map[uint]NumberType{
- 2: ColossallyAbundant, 3: NotPractical, 4: Superabundant,
- 6: ColossallyAbundant, 8: OrderedExponent, 10: NotPractical,
- 12: ColossallyAbundant, 18: Practical, 20: Practical, 24: Superabundant,
- 28: Practical, 30: OrderedExponent, 31: NotPractical, 34: NotPractical,
- 60: ColossallyAbundant, 70: NotPractical, 90: Practical, 100: Practical,
- 120: ColossallyAbundant, 144: OrderedExponent, 180: Superabundant,
- 240: Superabundant, 360: ColossallyAbundant, 720: Superabundant,
- 770: NotPractical, 900: OrderedExponent, 1680: Superabundant,
- 1729: NotPractical, 6912: OrderedExponent, 10010: NotPractical,
- 10080: Superabundant, 15120: Superabundant, 25200: Superabundant,
- 27720: Superabundant, 55440: ColossallyAbundant,
-}
-
-func TestType(t *testing.T) {
- tableTest(t, Type, typeCases, stdEquals, "Type")
-}
-
-// ====== DIGIT MAP TESTS ======
-var (
- zt = zeroType // 00 - zero
- ot = oneType // 0R - one
- ft = DigitType{1, Regular} // 1R - factors
- rt = DigitType{2, Regular} // 2R - regulars (index 2)
- wt = DigitType{0, Omega} // 0ω - omega neighbours
- at = DigitType{0, Alpha} // 0α - alpha neighbours
- nt = DigitType{0, Pseudoneighbour} // 0N - neighbour-like
- pt = DigitType{0, Opaque} // 0P - opaque totatives
-)
-var digitMapCases = map[uint][]DigitType{
- 0: []DigitType{},
- 1: []DigitType{zt},
- 2: []DigitType{zt, ot},
- 3: []DigitType{zt, ot, wt},
- 4: []DigitType{zt, ot, ft, wt},
- 5: []DigitType{zt, ot, wt, at, wt},
- 6: []DigitType{zt, ot, ft, ft, rt, wt},
- 8: []DigitType{zt, ot, ft, at, ft, pt, DigitType{1, Alpha}, wt},
- 10: []DigitType{zt, ot, ft, wt, rt, ft, DigitType{1, Omega}, pt,
- DigitType{3, Regular}, wt},
- 11: []DigitType{zt, ot, wt, at, at, wt, at, pt, nt, pt, wt},
- 12: []DigitType{zt, ot, ft, ft, ft, pt, ft, pt, rt, rt,
- DigitType{1, Opaque}, wt},
- 16: []DigitType{zt, ot, ft, wt, ft, wt, DigitType{1, Omega}, pt,
- ft, pt, DigitType{1, Omega}, pt, DigitType{1, Omega},
- pt, DigitType{1, Opaque}, wt},
- 17: []DigitType{zt, ot, wt, at, wt, pt, at, pt, wt, at,
- pt, pt, nt, pt, pt, pt, wt},
- 19: []DigitType{zt, ot, wt, wt, at, at, wt, pt, nt, wt,
- at, pt, nt, pt, pt, nt, pt, pt, wt},
- 22: []DigitType{zt, ot, ft, wt, rt, pt, DigitType{1, Omega}, wt,
- DigitType{3, Regular}, pt, DigitType{1, Opaque}, ft,
- DigitType{2, Omega}, pt, DigitType{1, Omega}, pt,
- DigitType{4, Regular}, pt, DigitType{1, Opaque}, pt,
- DigitType{2, Opaque}, wt},
- 24: []DigitType{zt, ot, ft, ft, ft, at, ft, pt, ft, rt,
- DigitType{1, Alpha}, pt, ft, pt, DigitType{1, Opaque},
- DigitType{1, Alpha}, rt, pt, rt, pt, DigitType{1, Alpha},
- DigitType{1, Opaque}, DigitType{1, Opaque}, wt},
-}
-
-func TestDigitMap(t *testing.T) {
- tableTest(t, DigitMap, digitMapCases, slices.Equal, "DigitMap")
-}
-
-// ensures GetDigitType(d, r) == DigitMap(r)[d];
-// does not ensure it has the correct value (that's TestDigitMap's job)
-func TestGetDigitType(t *testing.T) {
- for radix := range digitMapCases {
- digitMap := DigitMap(radix)
- for digit := range digitMap {
- actual := GetDigitType(uint(digit), radix)
- if actual != digitMap[digit] {
- t.Logf("GetDigitType(%d, %d) = %d", digit, radix, actual)
- t.Errorf("GetDigitType(%d, %d) != DigitMap(%d)[%d]",
- digit, radix, radix, digit)
- }
- }
- }
-}
-
-// A few test cases related to radix zero
-func TestGetDigitTypeMisc(t *testing.T) {
- t.Run("GetDigitType(0, 0)", func(t *testing.T) {
- if GetDigitType(0, 0) != ft {
- t.Errorf("GetDigitType(0, 0) = %s, expected 1R", GetDigitType(0, 0))
- }
- })
- t.Run("GetDigitType(1, 0)", func(t *testing.T) {
- if GetDigitType(1, 0) != ot {
- t.Errorf("GetDigitType(1, 0) = %s, expected 0R", GetDigitType(1, 0))
- }
- })
- t.Run("GetDigitType(2, 0)", func(t *testing.T) {
- if GetDigitType(2, 0) != pt {
- t.Errorf("GetDigitType(2, 0) = %s, expected 0P", GetDigitType(2, 0))
- }
- })
-}
-
-var splitCases = map[uintPair]uintPair{
- // digit, radix, regular part, totative part
- uintPair{0, 0}: uintPair{0, 1},
- uintPair{0, 1}: uintPair{1, 0},
- uintPair{0, 2}: uintPair{1, 0},
- uintPair{0, 12}: uintPair{1, 0},
- uintPair{1, 0}: uintPair{1, 1},
- uintPair{20, 0}: uintPair{1, 20},
- uintPair{360, 0}: uintPair{1, 360},
- uintPair{1, 1}: uintPair{1, 1},
- uintPair{12, 1}: uintPair{1, 12},
- uintPair{87, 1}: uintPair{1, 87},
- uintPair{120, 1}: uintPair{1, 120},
- uintPair{1, 2}: uintPair{1, 1},
- uintPair{1, 3}: uintPair{1, 1},
- uintPair{1, 7}: uintPair{1, 1},
- uintPair{1, 12}: uintPair{1, 1},
- uintPair{1, 39}: uintPair{1, 1},
- uintPair{1, 2948}: uintPair{1, 1},
- uintPair{5, 6}: uintPair{1, 5},
- uintPair{10, 6}: uintPair{2, 5},
- uintPair{12, 6}: uintPair{12, 1},
- uintPair{15, 6}: uintPair{3, 5},
- uintPair{35, 6}: uintPair{1, 35},
- uintPair{56, 6}: uintPair{8, 7},
- uintPair{5, 12}: uintPair{1, 5},
- uintPair{10, 12}: uintPair{2, 5},
- uintPair{12, 12}: uintPair{12, 1},
- uintPair{15, 12}: uintPair{3, 5},
- uintPair{35, 12}: uintPair{1, 35},
- uintPair{56, 12}: uintPair{8, 7},
- uintPair{12, 7}: uintPair{1, 12},
- uintPair{56, 7}: uintPair{7, 8},
- uintPair{70, 10}: uintPair{10, 7},
-}
-
-// testing version of Split
-func splitTest(a uintPair) uintPair {
- regular, totative := Split(a.a, a.b)
- return uintPair{regular, totative}
-}
-
-func TestSplit(t *testing.T) {
- tableTest(t, splitTest, splitCases, stdEquals, "Split")
-}
-
-// to be used as the equal paramater for tableTest
-func stdEquals[T comparable](a, b T) bool { return a == b }
-
-func setEquals[E comparable](a, b []E) bool {
- // use maps to simulate sets
- // aSet[a] == true means set contains a, false means not
- aSet := make(map[E]bool)
- bSet := make(map[E]bool)
- for _, i := range a {
- aSet[i] = true
- }
- for _, j := range b {
- bSet[j] = true
- }
- return maps.Equal(aSet, bSet)
-}