diff --git a/internal/lib/continuedFrac.go b/internal/lib/continuedFrac.go index 5b819cd..bd7a8f0 100644 --- a/internal/lib/continuedFrac.go +++ b/internal/lib/continuedFrac.go @@ -21,6 +21,9 @@ import ( "math/big" ) +/* +SqrtRepetend returns the repetend of the continued fraction of sqrt(x). It returns an error if x is a perfect square. +*/ func SqrtRepetend(x *big.Int) ([]*big.Int, error) { m := big.NewInt(0) d := big.NewInt(1) @@ -65,6 +68,9 @@ func cycle(seq []*big.Int) <-chan *big.Int { return ch } +/* +GaussianBrackets returns a channel that outputs the sequence [], [a1], [a1, a2], ... where each value comes from the input channel and [] denotes Gaussian brackets. +*/ func GaussianBrackets(ch <-chan *big.Int) <-chan *big.Int { out := make(chan *big.Int) @@ -87,6 +93,9 @@ func GaussianBrackets(ch <-chan *big.Int) <-chan *big.Int { return out } +/* +CFracConvergents returns a channel that outputs convergents of a periodic continued fraction with initial term a0 and repetend stored in denoms. +*/ func CFracConvergents(a0 *big.Int, denoms []*big.Int) <-chan *big.Rat { hc := cycle(denoms) _ = <-hc diff --git a/internal/lib/crt.go b/internal/lib/crt.go index 8314702..7375f6d 100644 --- a/internal/lib/crt.go +++ b/internal/lib/crt.go @@ -46,6 +46,9 @@ func solveCRT(a1, n1, a2, n2 *big.Int) (*big.Int, *big.Int) { return x, N } +/* +Given a system of congruences - defined by slices of remainders and moduli such that x = remainders[i] (mod moduli[i]) for each index i - CRTSolution outputs a solution to the system. +*/ func CRTSolution(remainders, moduli []*big.Int) (*big.Int, *big.Int) { n1 := new(big.Int) a1 := new(big.Int) @@ -63,6 +66,9 @@ func CRTSolution(remainders, moduli []*big.Int) (*big.Int, *big.Int) { return a1, n1 } +/* +ArePairwiseCoprime returns true if each pair of values in the input slice are coprime. +*/ func ArePairwiseCoprime(moduli []*big.Int) bool { z := new(big.Int) for i, a := range moduli { diff --git a/internal/lib/discreteLog.go b/internal/lib/discreteLog.go index 9452e7a..3b48361 100644 --- a/internal/lib/discreteLog.go +++ b/internal/lib/discreteLog.go @@ -33,9 +33,13 @@ func ceilSqrt(x *big.Int) *big.Int { return z } -// TODO: this can be extended to work with n, b not coprime -// https://cp-algorithms.com/algebra/discrete-log.html +/* +BabyStepGiantStep computes i such that b^i = x (mod n). For more efficient computation, provide the order of the group (i.e. totient(n)). +*/ func BabyStepGiantStep(n, b, x, order *big.Int) (*big.Int, error) { + // TODO: this function be extended to work with n, b not coprime + // https://cp-algorithms.com/algebra/discrete-log.html + z := new(big.Int).GCD(nil, nil, b, n) if z.Cmp(big.NewInt(1)) != 0 { return nil, fmt.Errorf("base %v and modulus %v are not coprime", b, n) diff --git a/internal/lib/divisor.go b/internal/lib/divisor.go index 7a4967c..dd21e42 100644 --- a/internal/lib/divisor.go +++ b/internal/lib/divisor.go @@ -20,8 +20,12 @@ import ( "math/big" ) -// TODO: expand to work for different sigmas +/* +DivisorSummatory computes the sum of sigma(k) for k=1 to n, where sigma is the divisor sum function. +*/ func DivisorSummatory(n *big.Int) *big.Int { + // TODO: expand to work for different sigmas + // employing Dirichlet's hyperbola method sqrt := new(big.Int).Sqrt(n) diff --git a/internal/lib/divisors.go b/internal/lib/divisors.go index 074f120..e9e7267 100644 --- a/internal/lib/divisors.go +++ b/internal/lib/divisors.go @@ -48,6 +48,9 @@ func updateMultiples(sieve []uint, x uint, p uint, n uint) { } } +/* +DivisorSieve computes sigma_x(k) for k=1 to n, where sigma_x is the divisor sum function. x sets the power each divisor is raised to. +*/ func DivisorsSieve(n uint, x uint) chan uint { sieve := make([]uint, n) sieve[0] = 0 diff --git a/internal/lib/mobius.go b/internal/lib/mobius.go index 6425fbf..b3e7bb3 100644 --- a/internal/lib/mobius.go +++ b/internal/lib/mobius.go @@ -16,6 +16,9 @@ along with this program. If not, see . */ package lib +/* +MobiusSieve computes mobius(k) for k=1 to n, where mobius is the Mobius function. +*/ func MobiusSieve(n uint) chan int { sieve := make([]int, n) for i := 0; i < int(n); i++ { diff --git a/internal/lib/partitions.go b/internal/lib/partitions.go index 3063f9a..c3b7df1 100644 --- a/internal/lib/partitions.go +++ b/internal/lib/partitions.go @@ -29,6 +29,9 @@ func nextPartition(k int, vals []*big.Int) { } } +/* +Partitions computes the number of ways to add to n with k or fewer terms. +*/ func Partitions(n, k int) *big.Int { if n < 0 { return big.NewInt(0) diff --git a/internal/lib/primeOmega.go b/internal/lib/primeOmega.go index 4ab53bd..d22ca76 100644 --- a/internal/lib/primeOmega.go +++ b/internal/lib/primeOmega.go @@ -35,6 +35,9 @@ func primeOmegaUpdateMultiples(sieve []uint, p uint, n uint, multiplicity bool) } } +/* +PrimeOmegaSieve computes omega(k) for k=1 to n, where omega is the prime omega function. If multiplicity is true, factors are counted with multiplicity. +*/ func PrimeOmegaSieve(n uint, multiplicity bool) chan uint { sieve := make([]uint, n) for i := uint(0); i < n; i++ { diff --git a/internal/lib/primitiveRoot.go b/internal/lib/primitiveRoot.go index 099687c..e84c604 100644 --- a/internal/lib/primitiveRoot.go +++ b/internal/lib/primitiveRoot.go @@ -21,6 +21,9 @@ import ( "math/big" ) +/* +Totient is a naive implementation of Euler's totient function. +*/ func Totient(n *big.Int) *big.Int { N := new(big.Int).Set(n) @@ -52,6 +55,9 @@ func Totient(n *big.Int) *big.Int { return phi } +/* +MultiplicativeOrder computes the smallest integer k such that g^k = 1 (mod modulus). +*/ func MultiplicativeOrder(g *big.Int, modulus *big.Int) *big.Int { e := new(big.Int).Set(g) var k *big.Int @@ -63,6 +69,9 @@ func MultiplicativeOrder(g *big.Int, modulus *big.Int) *big.Int { return k } +/* +PrimitiveRoot computes a primitive root modulo modulus. +*/ func PrimitiveRoot(modulus *big.Int) (*big.Int, error) { if modulus.Cmp(big.NewInt(1)) == 0 { return big.NewInt(0), nil @@ -85,6 +94,9 @@ func PrimitiveRoot(modulus *big.Int) (*big.Int, error) { return nil, errors.New("no primitive root") } +/* +PrimitiveRootFast computes a primitive root modulo modulus, utilizing the prime factorization of the totient of the modulus to find a solution more efficiently. +*/ func PrimitiveRootFast(modulus *big.Int, tpf map[string]*big.Int) (*big.Int, error) { phi := big.NewInt(1) for p, exp := range tpf { diff --git a/internal/lib/shoelace.go b/internal/lib/shoelace.go index 2b943bf..7c6dfdd 100644 --- a/internal/lib/shoelace.go +++ b/internal/lib/shoelace.go @@ -21,6 +21,9 @@ type Point struct { Y float64 } +/* +Area computes the area of a polygon given its vertices using the shoelace formula. +*/ func Area(points []Point) float64 { total := float64(0) n := len(points) diff --git a/internal/lib/stirling.go b/internal/lib/stirling.go index 55ced30..ad80425 100644 --- a/internal/lib/stirling.go +++ b/internal/lib/stirling.go @@ -30,6 +30,9 @@ func nextStirling1(k int, vals []*big.Int) { } } +/* +Stirling1 computes Stirling numbers of the first kind. +*/ func Stirling1(n, k int) *big.Int { if k > n { return big.NewInt(0) @@ -57,6 +60,9 @@ func nextStirling2(k int64, vals []*big.Int) { } } +/* +Stirling2 computes Stirling numbers of the second kind. +*/ func Stirling2(n, k int) *big.Int { if k > n { return big.NewInt(0) diff --git a/internal/lib/totient.go b/internal/lib/totient.go index fd97f24..85629da 100644 --- a/internal/lib/totient.go +++ b/internal/lib/totient.go @@ -16,6 +16,9 @@ along with this program. If not, see . */ package lib +/* +TotientSieve computes totient(k) for k=1 to n, where totient is Euler's totient function. +*/ func TotientSieve(n uint) chan uint { totients := make([]uint, n) totients[0] = 0