diff options
Diffstat (limited to 'factors/digit_map.go')
| -rw-r--r-- | factors/digit_map.go | 140 |
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 +} |
