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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
/* This script is part of radix_info.
Copyright (C) 2023, 2025 Adrien Hopkins
This program is free software: you can redistribute it and/or modify
it under the terms of version 3 of the GNU General Public License
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package main
import (
"errors"
"flag"
"fmt"
"strconv"
)
const ProgramVersion = "1.0.0"
// The arguments to this program
type args struct {
Radix uint
Compact bool
FullMap bool
ExactMTCLarge bool
TotativeDigits bool
DigitMapOnly bool
LogRegularComplexities bool
// If true, exit the program immediately after parsing args.
Exit bool
}
func parseArgs() (args, error) {
var a args
flag.BoolVar(&a.Compact, "c", false, "Compact the output display")
flag.BoolVar(&a.DigitMapOnly, "d", false,
"Show only the digit map; incompatible with -m and -t")
flag.BoolVar(&a.FullMap, "f", false,
fmt.Sprintf("Show full digit map (up to %d) for every radix",
maxSmallRadix))
flag.BoolVar(&a.LogRegularComplexities, "l", false,
"Show the base-2 logarithm of the regular complexities")
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,
"Print program version then exit")
flag.Parse()
if *help {
printHelp()
return args{Exit: true}, nil
} 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 a.DigitMapOnly && (a.TotativeDigits || a.ExactMTCLarge) {
return args{}, errors.New("You cannot use both -d and -t or -m at the same time.")
} else if flag.NArg() < 1 {
return args{}, errors.New("Please provide an argument (radix to study).")
} else if flag.NArg() > 1 {
return args{}, errors.New("Too many arguments provided.")
}
radix, err := strconv.ParseUint(flag.Arg(0), 0, 0)
if err != nil {
return args{}, uintParsingError(flag.Arg(0), err)
} else if radix < 2 {
return args{}, errors.New("Cannot use 0 or 1 as radices.")
} else if radix > maxSmallRadix && a.DigitMapOnly && !a.FullMap {
return args{}, errors.New("Used -d option, but digit map cannot be shown.")
}
a.Radix = uint(radix)
return a, nil
}
// uintParsingError determines what error to show the user if radix parsing fails.
// parsed is the radix string that was parsed and uintErr is the resulting error.
func uintParsingError(parsed string, uintErr error) error {
_, floatErr := strconv.ParseFloat(parsed, 64)
if floatErr != nil {
return fmt.Errorf("Error parsing radix: %w", uintErr)
}
var parsingErr *strconv.NumError
if !errors.As(uintErr, &parsingErr) {
return fmt.Errorf("Error parsing radix: %w", uintErr)
} else if errors.Is(parsingErr.Err, strconv.ErrRange) {
return fmt.Errorf("Radix is too large. Please use something smaller.")
} else {
return fmt.Errorf("Radix must be an unsigned integer.")
}
}
func printHelp() {
fmt.Println("Get important information about a radix.")
fmt.Println("You must provide one argument, which is the radix to get information about.")
fmt.Println("The radix must be an unsigned integer above 1.")
fmt.Println("Usage: radix_info [flags...] <radix>")
fmt.Println("Options:")
flag.PrintDefaults()
}
|