summaryrefslogtreecommitdiff
path: root/factors/digit_map.go
diff options
context:
space:
mode:
Diffstat (limited to 'factors/digit_map.go')
-rw-r--r--factors/digit_map.go140
1 files changed, 140 insertions, 0 deletions
diff --git a/factors/digit_map.go b/factors/digit_map.go
new file mode 100644
index 0000000..e78cce0
--- /dev/null
+++ b/factors/digit_map.go
@@ -0,0 +1,140 @@
+package factors
+
+import "fmt"
+
+type DigitType struct {
+ regularity uint8
+ totativeType TotativeType
+}
+
+type TotativeType uint8
+
+const (
+ // This number does not have any totative factors
+ Regular TotativeType = iota
+ // This number's totative part is divisible by (r^2 - 1)
+ // - this makes it easier to work with
+ Neighbour
+ // This number's totative part is not divisible by (r^2 - 1)
+ // - it will not be nice to work with
+ Opaque
+ // This number is zero, and doesn't have a true totative type.
+ Zero
+)
+
+// Zero and one will always have these types.
+var (
+ zeroType = DigitType{regularity: 0, totativeType: Zero}
+ oneType = DigitType{regularity: 0, totativeType: Regular}
+)
+
+// Above this number, regularity indices will be shown as '+'
+// instead of the number; this is to keep the code 2 characters long
+const maxDisplayRegularity = 7
+
+// The regularity index of a number in a radix, the smallest power of the
+// radix that is divisible by the number's regular part.
+func (dt DigitType) Regularity() uint8 { return dt.regularity }
+
+// The type of a number's totative part in a radix
+func (dt DigitType) TotativeType() TotativeType { return dt.totativeType }
+
+// String returns a string representation of the digit type
+// as a two-character code - the first representing regularity,
+// the second totative type
+func (dt DigitType) String() string {
+ var rString string
+ if dt.regularity > maxDisplayRegularity {
+ rString = "+"
+ } else {
+ rString = fmt.Sprint(dt.regularity)
+ }
+
+ var tString string
+ switch dt.totativeType {
+ case Zero:
+ tString = "0"
+ case Regular:
+ tString = "R"
+ case Neighbour:
+ tString = "N"
+ case Opaque:
+ tString = "P"
+ }
+
+ return rString + tString
+}
+
+// Splits a digit in a radix into its regular and totative parts
+func splitPF(digit, radix PrimeFactorization) (regular, totative uint) {
+ regular, totative = 1, 1
+ for p, e := range digit.exponents {
+ if radix.exponents[p] != 0 {
+ regular *= uintpow(p, e)
+ } else {
+ totative *= uintpow(p, e)
+ }
+ }
+ return regular, totative
+}
+
+// Splits a digit in a radix into its regular and totative parts
+func Split(digit, radix uint) (regular, totative uint) {
+ return splitPF(PrimeFactorize(digit), PrimeFactorize(radix))
+}
+
+// Calculates the regularity index of a number's regular part
+func calcRegularity(regular, radix uint) uint8 {
+ regularity, radixPower := uint8(0), uint(1)
+ for radixPower%regular != 0 {
+ regularity++
+ radixPower *= radix
+ }
+ return regularity
+}
+
+// Calculates the totative type of a number's totative part
+func calcTotativeType(totative, radix uint) TotativeType {
+ switch true {
+ case totative == 0:
+ return Zero
+ case totative == 1:
+ return Regular
+ case (radix*radix-1)%totative == 0:
+ return Neighbour
+ default:
+ return Opaque
+ }
+}
+
+// Gets the regularity and totative type of one digit in a radix
+func GetDigitType(digit, radix uint) DigitType {
+ if radix < 2 {
+ panic("Radices cannot be less than 2!")
+ }
+ radixPF := PrimeFactorize(radix)
+ digitPF := PrimeFactorize(digit)
+ regular, totative := splitPF(digitPF, radixPF)
+ regularity := calcRegularity(regular, radix)
+ totativeType := calcTotativeType(totative, radix)
+ return DigitType{regularity, totativeType}
+}
+
+// Gets the regularity and totative type of each digit in a radix
+func DigitMap(radix uint) []DigitType {
+ if radix < 2 {
+ panic("Radices cannot be less than 2!")
+ }
+ radixPF := PrimeFactorize(radix)
+ types := make([]DigitType, radix, radix)
+ types[0] = zeroType
+ types[1] = oneType
+ for d := uint(2); d < radix; d++ {
+ digitPF := PrimeFactorize(d)
+ regular, totative := splitPF(digitPF, radixPF)
+ regularity := calcRegularity(regular, radix)
+ totativeType := calcTotativeType(totative, radix)
+ types[d] = DigitType{regularity, totativeType}
+ }
+ return types
+}