diff options
| -rw-r--r-- | args.go | 13 | ||||
| -rw-r--r-- | factor_info.go | 28 | ||||
| -rw-r--r-- | factors/totative.go | 14 | ||||
| -rw-r--r-- | radix_info.go | 2 |
4 files changed, 45 insertions, 12 deletions
@@ -11,10 +11,11 @@ const ProgramVersion = "1.0.0-alpha+dev" // The arguments to this program type args struct { - Radix uint - Compact bool - FullMap bool - ExactMTCLarge bool + Radix uint + Compact bool + FullMap bool + ExactMTCLarge bool + TotativeDigits bool // If true, exit the program immediately after parsing args. Exit bool } @@ -28,6 +29,8 @@ func parseArgs() (args, error) { flag.BoolVar(&a.ExactMTCLarge, "m", false, fmt.Sprintf("Calculate exact MTC for very large radices (up to %d instead of %d), which may take a while.", maxExtended, maxNormal)) + flag.BoolVar(&a.TotativeDigits, "t", false, + "Calculate the radix's totative digits instead of just how many there are; incompatible with -c.") help := flag.Bool("?", false, "Get information about program usage then exit") version := flag.Bool("V", false, @@ -40,6 +43,8 @@ func parseArgs() (args, error) { } else if *version { fmt.Println("Radix Info version", ProgramVersion) return args{Exit: true}, nil + } else if a.Compact && a.TotativeDigits { + return args{}, errors.New("You cannot use both -t and -c at the same time.") } else { if flag.NArg() == 1 { if radix, err := strconv.ParseUint(flag.Arg(0), 0, 0); err == nil { diff --git a/factor_info.go b/factor_info.go index 03c81f3..bcfc3b1 100644 --- a/factor_info.go +++ b/factor_info.go @@ -26,6 +26,8 @@ type factorInfo struct { // The fraction of digits that are totatives (numbers that share no // factors with the radix - they are the worst kind of digits) TotativeRatio float64 + // The totative digits of this radix. May be nil if this was not requested. + TotativeDigits []uint32 // A rank measuring how well the radix works with the most elementary // numbers and ratios BasicRank string @@ -58,18 +60,25 @@ const ( maxExtended = 1 << 32 ) -func getFactorInfo(radix uint, fullMap bool, exactMTCLarge bool) *factorInfo { +func getFactorInfo(a args) *factorInfo { + radix := a.Radix + r_factors := factors.Factors(radix) slices.Sort(r_factors) + var totativeDigits []uint32 = nil + if a.TotativeDigits && radix < maxExtended { + totativeDigits = factors.TotativeDigits(uint32(radix)) + } + var mtc_ptr *uint64 = nil - if radix < maxNormal || (exactMTCLarge && radix < maxExtended) { + if radix < maxNormal || (a.ExactMTCLarge && radix < maxExtended) { mtc := factors.MTC(uint32(radix)) mtc_ptr = &mtc } var digitMap []factors.DigitType - if fullMap { + if a.FullMap { digitMap = make([]factors.DigitType, maxSmallRadix) for d := 0; d < maxSmallRadix; d++ { digitMap[d] = factors.GetDigitType(uint(d), radix) @@ -85,16 +94,21 @@ func getFactorInfo(radix uint, fullMap bool, exactMTCLarge bool) *factorInfo { return &factorInfo{radix, factors.PrimeFactorize(radix), r_factors, factors.Score(radix), totativeCount, totativeRatio, - factors.BasicRank(radix), factors.Type(radix), mtc_ptr, - math.Log(float64(radix)), digitMap} + totativeDigits, factors.BasicRank(radix), factors.Type(radix), + mtc_ptr, math.Log(float64(radix)), digitMap} } func (fi *factorInfo) writeTo(w io.Writer) { fmt.Fprintln(w, fi.Radix, "=", fi.PrimeFactorization) fmt.Fprintf(w, "Factors: %v (Score: %.4f)\n", fi.Factors, fi.Score) fmt.Fprintln(w, "2345 Rank:", fi.BasicRank) - fmt.Fprintf(w, "Totative Digit Count: %d (%.3f%%)\n", - fi.Totient, fi.TotativeRatio*100.0) + if fi.TotativeDigits != nil { + fmt.Fprintf(w, "Totative Digits: %v (%.3f%%)\n", + fi.TotativeDigits, fi.TotativeRatio*100.0) + } else { + fmt.Fprintf(w, "Totative Digit Count: %d (%.3f%%)\n", + fi.Totient, fi.TotativeRatio*100.0) + } writeTypeMessage(w, fi.Type) if fi.MTC != nil { fmt.Fprintln(w, "Multiplication Table Complexity:", *fi.MTC) diff --git a/factors/totative.go b/factors/totative.go index 680cc26..abbbe89 100644 --- a/factors/totative.go +++ b/factors/totative.go @@ -17,3 +17,17 @@ func Totient(n uint) uint { return num * (n / denom) } + +// TotativeDigits returns a slice containing every number less than r +// that is a totative of r (shares no factors with r). +func TotativeDigits(r uint32) []uint32 { + digits := make([]uint32, Totient(uint(r))) + totativesFound := 0 + for d := uint32(0); d < r; d++ { + if gcd(d, r) == 1 { + digits[totativesFound] = d + totativesFound++ + } + } + return digits +} diff --git a/radix_info.go b/radix_info.go index 9845572..f495905 100644 --- a/radix_info.go +++ b/radix_info.go @@ -12,7 +12,7 @@ func main() { } if err == nil { - factorInfo := getFactorInfo(args.Radix, args.FullMap, args.ExactMTCLarge) + factorInfo := getFactorInfo(args) if args.Compact { factorInfo.writeToCompact(os.Stdout) } else { |
