Skip to content

Commit 0c6d27b

Browse files
committed
Add -group and -groups-file flags
1 parent 43b7aef commit 0c6d27b

1 file changed

Lines changed: 125 additions & 24 deletions

File tree

find_arctan_formulae.go

Lines changed: 125 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package main
55

66
import (
7+
"bufio"
78
"encoding/binary"
89
"flag"
910
"fmt"
@@ -15,6 +16,7 @@ import (
1516
"runtime"
1617
"runtime/debug"
1718
"runtime/pprof"
19+
"strconv"
1820
"strings"
1921
"sync"
2022
"time"
@@ -25,29 +27,32 @@ import (
2527

2628
var (
2729
// Flags
28-
cpuprofile string // write CPU profile to this file
29-
pslqVerbose bool // verbose flag for PSLQ
30-
pslqIterations int // iterations for PSLQ
31-
pslqPrecision uint // precision to do PSLQ in
32-
pslqLogMaxCoeff uint // log(max coefficient size) for PSLQ
33-
pslqTargetPrecision float64 // PSLQ target precision of the result as a fraction of prec
34-
workers int // Number of workers for PSLQ and search
35-
pslqAlgorithm int // PSLQ algorithm
36-
pslqMaxItems int // output no more than this many entries per PSLQ file
37-
alpha uint32 // Don't output arctan terms bigger than 1/alpha
38-
maxPrime uint32 // maximum prime factor to consider for groups
39-
pslqMinItems int // minimum number of items required for a PSLQ file
40-
minGroupLength int // only find groups with this many members, min
41-
maxGroupLength int // only find groups with this many members, max
42-
maxX uint32 // max value of x when in arctan 1/x term
43-
arctanCacheSize int // cache this many arctan values
44-
groupCacheSize int // cache this many group values
45-
pslqMaxFails int // stop PSLQ with this many failures in a row
46-
pslqMaxNoNew int // stop PSLQ if no new formulae for this long
47-
pslqTrimStart bool // if set, trim PSLQ norms from the start (larger fractions)
48-
maxLehmerMeasure float64 // don't print if worse than this
49-
searchX uint32 // if set, linear search formulae from 1/searchX up
50-
pslqSkipZeros bool // if set skip PSLQ on any relations which contain zero relations
30+
cpuprofile string // write CPU profile to this file
31+
pslqVerbose bool // verbose flag for PSLQ
32+
pslqIterations int // iterations for PSLQ
33+
pslqPrecision uint // precision to do PSLQ in
34+
pslqLogMaxCoeff uint // log(max coefficient size) for PSLQ
35+
pslqTargetPrecision float64 // PSLQ target precision of the result as a fraction of prec
36+
workers int // Number of workers for PSLQ and search
37+
pslqAlgorithm int // PSLQ algorithm
38+
pslqMaxItems int // output no more than this many entries per PSLQ file
39+
alpha uint32 // Don't output arctan terms bigger than 1/alpha
40+
maxPrime uint32 // maximum prime factor to consider for groups
41+
pslqMinItems int // minimum number of items required for a PSLQ file
42+
minGroupLength int // only find groups with this many members, min
43+
maxGroupLength int // only find groups with this many members, max
44+
maxX uint32 // max value of x when in arctan 1/x term
45+
arctanCacheSize int // cache this many arctan values
46+
groupCacheSize int // cache this many group values
47+
pslqMaxFails int // stop PSLQ with this many failures in a row
48+
pslqMaxNoNew int // stop PSLQ if no new formulae for this long
49+
pslqTrimStart bool // if set, trim PSLQ norms from the start (larger fractions)
50+
maxLehmerMeasure float64 // don't print if worse than this
51+
searchX uint32 // if set, linear search formulae from 1/searchX up
52+
pslqSkipZeros bool // if set skip PSLQ on any relations which contain zero relations
53+
fixedGroupString string // a comma or space separated string for a prime group to use
54+
groupsFile string // a file of comma or spare seperated groups, one per line
55+
fixedGroups [][]uint32 // parsed version of the above
5156

5257
// Globals
5358
arctanCache *lru.Cache[uint32, *big.Float]
@@ -94,6 +99,8 @@ func init() {
9499
flag.BoolVar(&pslqSkipZeros, "skip-zeros", false, "if set skip PSLQ on any relations which contain previously found zero relations")
95100
flag.Float64Var(&maxLehmerMeasure, "max-lehmer-measure", 0.0, "Don't print formulae with a Lehmer measure greater than this")
96101
Uint32Var(&searchX, "search-x", 0, "If set do a linear search of terms from this value up")
102+
flag.StringVar(&fixedGroupString, "group", "", "A comma or space separated list of primes to use as the prime group")
103+
flag.StringVar(&groupsFile, "groups-file", "", "a file of comma or spare seperated groups, one per line")
97104
}
98105

99106
func showParameters() {
@@ -575,7 +582,15 @@ func processPrimeGroups(norms []*Norm, primeMap map[uint32][]*Norm, primesToProc
575582
go processPrimeGroupsWorker(primeMap, ch, &wg)
576583
}
577584

578-
if searchX == 0 {
585+
if len(fixedGroups) != 0 {
586+
for _, group := range fixedGroups {
587+
statsMu.Lock()
588+
currentGroup = group
589+
groupsChecked++
590+
statsMu.Unlock()
591+
ch <- group
592+
}
593+
} else if searchX == 0 {
579594
for length := minGroupLength; length <= maxGroupLength; length++ {
580595
Printf("\n--- Processing groups of length %d ---\n", length)
581596
for group := range Combinations(primesToProcess, length) {
@@ -638,13 +653,99 @@ func run() error {
638653
return processPrimeGroups(norms, primeMap, primesToProcess)
639654
}
640655

656+
// parseUint32List parses a string containing space or comma or both
657+
// separated integers into a slice of uint32.
658+
// It returns the slice of parsed integers and any error encountered during parsing.
659+
func parseUint32List(input string) ([]uint32, error) {
660+
// Replace commas with spaces to handle both delimiters consistently.
661+
replaced := strings.ReplaceAll(input, ",", " ")
662+
663+
// Split the string by spaces.
664+
parts := strings.Fields(replaced)
665+
666+
result := make([]uint32, 0, len(parts))
667+
668+
for _, part := range parts {
669+
if part == "" {
670+
continue // Skip empty strings resulting from multiple spaces or commas.
671+
}
672+
val, err := strconv.ParseUint(part, 10, 32)
673+
if err != nil {
674+
return nil, err
675+
}
676+
result = append(result, uint32(val))
677+
}
678+
679+
return result, nil
680+
}
681+
682+
// loadGroups reads a file of prime groups, parses each line as a space or comma
683+
// separated list of integers, and returns a slice of slices of uint32.
684+
func loadGroups(fileName string) ([][]uint32, error) {
685+
file, err := os.Open(fileName)
686+
if err != nil {
687+
return nil, fmt.Errorf("failed to open file %q: %w", fileName, err)
688+
}
689+
defer file.Close()
690+
691+
var groups [][]uint32
692+
scanner := bufio.NewScanner(file)
693+
for scanner.Scan() {
694+
line := scanner.Text()
695+
if line == "" {
696+
continue // Skip empty lines
697+
}
698+
group, err := parseUint32List(line)
699+
if err != nil {
700+
return nil, fmt.Errorf("failed to parse line %q: %w", line, err)
701+
}
702+
groups = append(groups, group)
703+
}
704+
705+
if err := scanner.Err(); err != nil {
706+
return nil, fmt.Errorf("failed to read file %q: %w", fileName, err)
707+
}
708+
709+
return groups, nil
710+
}
711+
641712
func main() {
642713
var err error
643714
flag.Parse()
644715

645716
Printf("Starting %s with parameters %v\n\n", os.Args[0], os.Args[1:])
646717
showParameters()
647718

719+
if fixedGroupString != "" {
720+
fixedGroup, err := parseUint32List(fixedGroupString)
721+
if err != nil {
722+
log.Fatalf("Failed to parse -group %q: %v", fixedGroupString, err)
723+
}
724+
fixedGroups = [][]uint32{fixedGroup}
725+
Printf("Using fixed prime group %v\n", fixedGroup)
726+
} else if groupsFile != "" {
727+
fixedGroups, err = loadGroups(groupsFile)
728+
if err != nil {
729+
log.Fatalf("Failed to parse -groups-file %q: %v", groupsFile, err)
730+
}
731+
Printf("Using %d fixed prime groups from file %q\n", len(fixedGroups), groupsFile)
732+
}
733+
// Filter out lines bigger than maxPrime
734+
if len(fixedGroups) != 0 {
735+
newFixedGroups := fixedGroups[:0]
736+
GROUPS:
737+
for _, group := range fixedGroups {
738+
for _, p := range group {
739+
if p > maxPrime {
740+
Printf("Warning: dropping %v from fixed group as %d > %d (-max-prime)\n", group, p, maxPrime)
741+
continue GROUPS
742+
}
743+
}
744+
newFixedGroups = append(newFixedGroups, group)
745+
}
746+
fixedGroups = newFixedGroups
747+
}
748+
648749
// Do CPU profiling if requested
649750
if cpuprofile != "" {
650751
f, err := os.Create(cpuprofile)

0 commit comments

Comments
 (0)