summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--args.go13
-rw-r--r--factor_info.go28
-rw-r--r--factors/totative.go14
-rw-r--r--radix_info.go2
4 files changed, 45 insertions, 12 deletions
diff --git a/args.go b/args.go
index a211435..d0f5da9 100644
--- a/args.go
+++ b/args.go
@@ -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 {