move to lib
This commit is contained in:
parent
d2275cd69f
commit
b55fe61820
|
|
@ -17,11 +17,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"scm.dairydemon.net/filifa/mathtools/internal/lib"
|
||||
)
|
||||
|
||||
var discreteLogModulus string
|
||||
|
|
@ -29,62 +29,6 @@ var discreteLogBase string
|
|||
var discreteLogElement string
|
||||
var discreteLogOrder string
|
||||
|
||||
// whyyyy doesn't math/big have a ceil functionnnn
|
||||
func ceilSqrt(x *big.Int) *big.Int {
|
||||
z := new(big.Int).Sqrt(x)
|
||||
s := new(big.Int).Exp(z, big.NewInt(2), nil)
|
||||
if s.Cmp(x) != 0 {
|
||||
z.Add(z, big.NewInt(1))
|
||||
}
|
||||
|
||||
return z
|
||||
}
|
||||
|
||||
// TODO: this can be extended to work with n, b not coprime
|
||||
// https://cp-algorithms.com/algebra/discrete-log.html
|
||||
func babyStepGiantStep(n, b, x, order *big.Int) (*big.Int, error) {
|
||||
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)
|
||||
}
|
||||
|
||||
var m *big.Int
|
||||
if order == nil {
|
||||
// m = ceil(sqrt(n - 1))
|
||||
z := big.NewInt(1)
|
||||
z.Sub(n, z)
|
||||
m = ceilSqrt(z)
|
||||
} else {
|
||||
m = ceilSqrt(order)
|
||||
}
|
||||
|
||||
table := make(map[string]*big.Int)
|
||||
for j := big.NewInt(1); j.Cmp(m) <= 0; j.Add(j, big.NewInt(1)) {
|
||||
a := new(big.Int).Exp(b, j, n)
|
||||
table[a.String()] = new(big.Int).Set(j)
|
||||
}
|
||||
|
||||
// p = b^-m modulo n
|
||||
p := new(big.Int).Neg(m)
|
||||
p.Exp(b, p, n)
|
||||
|
||||
gamma := new(big.Int).Set(x)
|
||||
|
||||
for i := big.NewInt(0); i.Cmp(m) == -1; i.Add(i, big.NewInt(1)) {
|
||||
j, ok := table[gamma.String()]
|
||||
if ok {
|
||||
i.Mul(i, m)
|
||||
i.Add(i, j)
|
||||
return i, nil
|
||||
}
|
||||
|
||||
gamma.Mul(gamma, p)
|
||||
gamma.Mod(gamma, n)
|
||||
}
|
||||
|
||||
return nil, errors.New("no solution")
|
||||
}
|
||||
|
||||
func discreteLog(cmd *cobra.Command, args []string) {
|
||||
m, ok := new(big.Int).SetString(discreteLogModulus, 10)
|
||||
if !ok {
|
||||
|
|
@ -109,7 +53,7 @@ func discreteLog(cmd *cobra.Command, args []string) {
|
|||
}
|
||||
}
|
||||
|
||||
k, err := babyStepGiantStep(m, b, x, order)
|
||||
k, err := lib.BabyStepGiantStep(m, b, x, order)
|
||||
if err != nil {
|
||||
cobra.CheckErr(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,27 +21,9 @@ import (
|
|||
"math/big"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"scm.dairydemon.net/filifa/mathtools/internal/lib"
|
||||
)
|
||||
|
||||
// TODO: expand to work for different sigmas
|
||||
func divisorSummatory(n *big.Int) *big.Int {
|
||||
// employing Dirichlet's hyperbola method
|
||||
sqrt := new(big.Int).Sqrt(n)
|
||||
|
||||
total := big.NewInt(0)
|
||||
for x := big.NewInt(1); x.Cmp(sqrt) <= 0; x.Add(x, big.NewInt(1)) {
|
||||
z := new(big.Int).Div(n, x)
|
||||
total.Add(total, z)
|
||||
}
|
||||
|
||||
total.Mul(total, big.NewInt(2))
|
||||
|
||||
sqrt.Exp(sqrt, big.NewInt(2), nil)
|
||||
total.Sub(total, sqrt)
|
||||
|
||||
return total
|
||||
}
|
||||
|
||||
func divisorSum(cmd *cobra.Command, args []string) {
|
||||
for _, arg := range args {
|
||||
n, ok := new(big.Int).SetString(arg, 10)
|
||||
|
|
@ -50,7 +32,7 @@ func divisorSum(cmd *cobra.Command, args []string) {
|
|||
continue
|
||||
}
|
||||
|
||||
d := divisorSummatory(n)
|
||||
d := lib.DivisorSummatory(n)
|
||||
fmt.Println(d)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,71 +20,14 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"scm.dairydemon.net/filifa/mathtools/internal/lib"
|
||||
)
|
||||
|
||||
var divisorsN uint
|
||||
var divisorsE uint
|
||||
|
||||
func pow(base uint, exp uint) uint {
|
||||
result := uint(1)
|
||||
for exp > 0 {
|
||||
if exp%2 == 1 {
|
||||
result *= base
|
||||
}
|
||||
|
||||
exp >>= 1
|
||||
base *= base
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func updateMultiples(sieve []uint, x uint, p uint, n uint) {
|
||||
for q := p; ; q *= p {
|
||||
// sigma_x(a*b) = sigma_x(a) * sigma_x(b) if gcd(a,b) = 1
|
||||
for i := 2 * q; i < n; i += q {
|
||||
if i%(p*q) != 0 {
|
||||
sieve[i] *= sieve[q]
|
||||
}
|
||||
}
|
||||
|
||||
if p*q >= n {
|
||||
break
|
||||
}
|
||||
|
||||
// sigma_x(p^k) = p^(kx) + sigma_x(p^(k-1))
|
||||
sieve[p*q] = pow(p*q, x) + sieve[q]
|
||||
}
|
||||
}
|
||||
|
||||
func divisorsSieve(n uint, x uint) chan uint {
|
||||
sieve := make([]uint, n)
|
||||
sieve[0] = 0
|
||||
for i := uint(1); i < n; i++ {
|
||||
sieve[i] = 1
|
||||
}
|
||||
|
||||
ch := make(chan uint)
|
||||
go func() {
|
||||
for i := uint(0); i < n; i++ {
|
||||
if i == 0 || i == 1 || sieve[i] != 1 {
|
||||
ch <- sieve[i]
|
||||
continue
|
||||
}
|
||||
|
||||
sieve[i] = pow(i, x) + 1
|
||||
updateMultiples(sieve, x, i, n)
|
||||
ch <- sieve[i]
|
||||
}
|
||||
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
func divisors(cmd *cobra.Command, args []string) {
|
||||
ch := divisorsSieve(divisorsN, divisorsE)
|
||||
ch := lib.DivisorsSieve(divisorsN, divisorsE)
|
||||
for i := 0; ; i++ {
|
||||
v, ok := <-ch
|
||||
if !ok {
|
||||
|
|
|
|||
|
|
@ -20,43 +20,13 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"scm.dairydemon.net/filifa/mathtools/internal/lib"
|
||||
)
|
||||
|
||||
var mobiusN uint
|
||||
|
||||
func mobiusSieve(n uint) chan int {
|
||||
sieve := make([]int, n)
|
||||
for i := 0; i < int(n); i++ {
|
||||
sieve[i] = i
|
||||
}
|
||||
|
||||
ch := make(chan int)
|
||||
go func() {
|
||||
for i := 0; i < int(n); i++ {
|
||||
if i == 0 || i == 1 || sieve[i] != i {
|
||||
ch <- sieve[i]
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- -1
|
||||
|
||||
for j := 2 * i; j < int(n); j += i {
|
||||
if j%(i*i) == 0 {
|
||||
sieve[j] = 0
|
||||
}
|
||||
|
||||
sieve[j] /= -i
|
||||
}
|
||||
}
|
||||
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
func mobius(cmd *cobra.Command, args []string) {
|
||||
ch := mobiusSieve(mobiusN)
|
||||
ch := lib.MobiusSieve(mobiusN)
|
||||
for i := 0; ; i++ {
|
||||
v, ok := <-ch
|
||||
if !ok {
|
||||
|
|
|
|||
|
|
@ -18,46 +18,15 @@ package cmd
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"scm.dairydemon.net/filifa/mathtools/internal/lib"
|
||||
)
|
||||
|
||||
var partitionsN string
|
||||
var partitionsK string
|
||||
|
||||
// given a slice where vals[i] = p_{k-1}(i) for a given k, nextPartition updates the slice so vals[i] = p_k(i) using the property that p_k(n) = p_k(n-k) + p_{k-1}(n)
|
||||
func nextPartition(k int, vals []*big.Int) {
|
||||
for i := 1; i < len(vals); i++ {
|
||||
if i-k >= 0 {
|
||||
vals[i].Add(vals[i], vals[i-k])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func p(n, k int) *big.Int {
|
||||
if n < 0 {
|
||||
return big.NewInt(0)
|
||||
}
|
||||
|
||||
if k > n {
|
||||
k = n
|
||||
}
|
||||
|
||||
vals := make([]*big.Int, n+1)
|
||||
for i := range vals {
|
||||
vals[i] = big.NewInt(0)
|
||||
}
|
||||
vals[0] = big.NewInt(1)
|
||||
|
||||
for i := 1; i <= k; i++ {
|
||||
nextPartition(i, vals)
|
||||
}
|
||||
|
||||
return vals[n]
|
||||
}
|
||||
|
||||
func partitions(cmd *cobra.Command, args []string) {
|
||||
n, err := strconv.Atoi(partitionsN)
|
||||
if err != nil {
|
||||
|
|
@ -83,7 +52,7 @@ func partitions(cmd *cobra.Command, args []string) {
|
|||
cobra.CheckErr("k must be nonnegative")
|
||||
}
|
||||
|
||||
z := p(n, k)
|
||||
z := lib.Partitions(n, k)
|
||||
fmt.Println(z)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,57 +20,14 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"scm.dairydemon.net/filifa/mathtools/internal/lib"
|
||||
)
|
||||
|
||||
var primeOmegaN uint
|
||||
var primeOmegaMul bool
|
||||
|
||||
func primeOmegaUpdateMultiples(sieve []uint, p uint, n uint, multiplicity bool) {
|
||||
for q := p; ; q *= p {
|
||||
// omega(a*b) = omega(a) + omega(b) if gcd(a,b) = 1
|
||||
for i := 2 * q; i < n; i += q {
|
||||
if i%(p*q) != 0 {
|
||||
sieve[i] += sieve[q]
|
||||
}
|
||||
}
|
||||
|
||||
if p*q >= n {
|
||||
break
|
||||
}
|
||||
|
||||
if multiplicity {
|
||||
sieve[p*q] = 1 + sieve[q]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func primeOmegaSieve(n uint) chan uint {
|
||||
sieve := make([]uint, n)
|
||||
for i := uint(0); i < n; i++ {
|
||||
sieve[i] = 0
|
||||
}
|
||||
|
||||
ch := make(chan uint)
|
||||
go func() {
|
||||
for i := uint(0); i < n; i++ {
|
||||
if i == 0 || i == 1 || sieve[i] != 0 {
|
||||
ch <- sieve[i]
|
||||
continue
|
||||
}
|
||||
|
||||
sieve[i] = 1
|
||||
primeOmegaUpdateMultiples(sieve, i, n, primeOmegaMul)
|
||||
ch <- sieve[i]
|
||||
}
|
||||
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
func primeOmega(cmd *cobra.Command, args []string) {
|
||||
ch := primeOmegaSieve(primeOmegaN)
|
||||
ch := lib.PrimeOmegaSieve(primeOmegaN, primeOmegaMul)
|
||||
for i := 0; ; i++ {
|
||||
v, ok := <-ch
|
||||
if !ok {
|
||||
|
|
|
|||
|
|
@ -24,15 +24,11 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"scm.dairydemon.net/filifa/mathtools/internal/lib"
|
||||
)
|
||||
|
||||
var shoelaceFile string
|
||||
|
||||
type point struct {
|
||||
x float64
|
||||
y float64
|
||||
}
|
||||
|
||||
func splitLines(file *os.File) []string {
|
||||
slice := make([]string, 0)
|
||||
scanner := bufio.NewScanner(file)
|
||||
|
|
@ -43,8 +39,8 @@ func splitLines(file *os.File) []string {
|
|||
return slice
|
||||
}
|
||||
|
||||
func readFromFile(filepath string) ([]point, error) {
|
||||
points := make([]point, 0)
|
||||
func readFromFile(filepath string) ([]lib.Point, error) {
|
||||
points := make([]lib.Point, 0)
|
||||
file, err := os.Open(filepath)
|
||||
if err != nil {
|
||||
return points, err
|
||||
|
|
@ -65,25 +61,14 @@ func readFromFile(filepath string) ([]point, error) {
|
|||
return points, err
|
||||
}
|
||||
|
||||
points = append(points, point{x, y})
|
||||
points = append(points, lib.Point{x, y})
|
||||
}
|
||||
|
||||
return points, nil
|
||||
}
|
||||
|
||||
func area(points []point) float64 {
|
||||
total := float64(0)
|
||||
n := len(points)
|
||||
for i, p := range points {
|
||||
q := points[(i+1)%n]
|
||||
total += (p.y + q.y) * (p.x - q.x)
|
||||
}
|
||||
|
||||
return total / 2
|
||||
}
|
||||
|
||||
func shoelace(cmd *cobra.Command, args []string) {
|
||||
var coordinates []point
|
||||
var coordinates []lib.Point
|
||||
var err error
|
||||
if shoelaceFile != "" {
|
||||
coordinates, err = readFromFile(shoelaceFile)
|
||||
|
|
@ -94,7 +79,7 @@ func shoelace(cmd *cobra.Command, args []string) {
|
|||
cobra.CheckErr("filename required")
|
||||
}
|
||||
|
||||
fmt.Println(area(coordinates))
|
||||
fmt.Println(lib.Area(coordinates))
|
||||
}
|
||||
|
||||
// shoelaceCmd represents the shoelace command
|
||||
|
|
|
|||
|
|
@ -20,39 +20,13 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"scm.dairydemon.net/filifa/mathtools/internal/lib"
|
||||
)
|
||||
|
||||
var totientN uint
|
||||
|
||||
func totientSieve(n uint) chan uint {
|
||||
totients := make([]uint, n)
|
||||
totients[0] = 0
|
||||
totients[1] = 1
|
||||
for i := uint(2); i < n; i++ {
|
||||
totients[i] = i - 1
|
||||
}
|
||||
|
||||
ch := make(chan uint)
|
||||
go func() {
|
||||
for i := uint(0); i < n; i++ {
|
||||
ch <- totients[i]
|
||||
if i == 0 || i == 1 || totients[i] != i-1 {
|
||||
continue
|
||||
}
|
||||
|
||||
for j := uint(2 * i); j < n; j += i {
|
||||
totients[j] -= totients[j] / i
|
||||
}
|
||||
}
|
||||
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
func totient(cmd *cobra.Command, args []string) {
|
||||
for v := range totientSieve(totientN) {
|
||||
for v := range lib.TotientSieve(totientN) {
|
||||
if v == 0 {
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
Copyright © 2025 filifa
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package lib
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// whyyyy doesn't math/big have a ceil functionnnn
|
||||
func ceilSqrt(x *big.Int) *big.Int {
|
||||
z := new(big.Int).Sqrt(x)
|
||||
s := new(big.Int).Exp(z, big.NewInt(2), nil)
|
||||
if s.Cmp(x) != 0 {
|
||||
z.Add(z, big.NewInt(1))
|
||||
}
|
||||
|
||||
return z
|
||||
}
|
||||
|
||||
// TODO: this can be extended to work with n, b not coprime
|
||||
// https://cp-algorithms.com/algebra/discrete-log.html
|
||||
func BabyStepGiantStep(n, b, x, order *big.Int) (*big.Int, error) {
|
||||
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)
|
||||
}
|
||||
|
||||
var m *big.Int
|
||||
if order == nil {
|
||||
// m = ceil(sqrt(n - 1))
|
||||
z := big.NewInt(1)
|
||||
z.Sub(n, z)
|
||||
m = ceilSqrt(z)
|
||||
} else {
|
||||
m = ceilSqrt(order)
|
||||
}
|
||||
|
||||
table := make(map[string]*big.Int)
|
||||
for j := big.NewInt(1); j.Cmp(m) <= 0; j.Add(j, big.NewInt(1)) {
|
||||
a := new(big.Int).Exp(b, j, n)
|
||||
table[a.String()] = new(big.Int).Set(j)
|
||||
}
|
||||
|
||||
// p = b^-m modulo n
|
||||
p := new(big.Int).Neg(m)
|
||||
p.Exp(b, p, n)
|
||||
|
||||
gamma := new(big.Int).Set(x)
|
||||
|
||||
for i := big.NewInt(0); i.Cmp(m) == -1; i.Add(i, big.NewInt(1)) {
|
||||
j, ok := table[gamma.String()]
|
||||
if ok {
|
||||
i.Mul(i, m)
|
||||
i.Add(i, j)
|
||||
return i, nil
|
||||
}
|
||||
|
||||
gamma.Mul(gamma, p)
|
||||
gamma.Mod(gamma, n)
|
||||
}
|
||||
|
||||
return nil, errors.New("no solution")
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright © 2025 filifa
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package lib
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// TODO: expand to work for different sigmas
|
||||
func DivisorSummatory(n *big.Int) *big.Int {
|
||||
// employing Dirichlet's hyperbola method
|
||||
sqrt := new(big.Int).Sqrt(n)
|
||||
|
||||
total := big.NewInt(0)
|
||||
for x := big.NewInt(1); x.Cmp(sqrt) <= 0; x.Add(x, big.NewInt(1)) {
|
||||
z := new(big.Int).Div(n, x)
|
||||
total.Add(total, z)
|
||||
}
|
||||
|
||||
total.Mul(total, big.NewInt(2))
|
||||
|
||||
sqrt.Exp(sqrt, big.NewInt(2), nil)
|
||||
total.Sub(total, sqrt)
|
||||
|
||||
return total
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
Copyright © 2025 filifa
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package lib
|
||||
|
||||
func pow(base uint, exp uint) uint {
|
||||
result := uint(1)
|
||||
for exp > 0 {
|
||||
if exp%2 == 1 {
|
||||
result *= base
|
||||
}
|
||||
|
||||
exp >>= 1
|
||||
base *= base
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func updateMultiples(sieve []uint, x uint, p uint, n uint) {
|
||||
for q := p; ; q *= p {
|
||||
// sigma_x(a*b) = sigma_x(a) * sigma_x(b) if gcd(a,b) = 1
|
||||
for i := 2 * q; i < n; i += q {
|
||||
if i%(p*q) != 0 {
|
||||
sieve[i] *= sieve[q]
|
||||
}
|
||||
}
|
||||
|
||||
if p*q >= n {
|
||||
break
|
||||
}
|
||||
|
||||
// sigma_x(p^k) = p^(kx) + sigma_x(p^(k-1))
|
||||
sieve[p*q] = pow(p*q, x) + sieve[q]
|
||||
}
|
||||
}
|
||||
|
||||
func DivisorsSieve(n uint, x uint) chan uint {
|
||||
sieve := make([]uint, n)
|
||||
sieve[0] = 0
|
||||
for i := uint(1); i < n; i++ {
|
||||
sieve[i] = 1
|
||||
}
|
||||
|
||||
ch := make(chan uint)
|
||||
go func() {
|
||||
for i := uint(0); i < n; i++ {
|
||||
if i == 0 || i == 1 || sieve[i] != 1 {
|
||||
ch <- sieve[i]
|
||||
continue
|
||||
}
|
||||
|
||||
sieve[i] = pow(i, x) + 1
|
||||
updateMultiples(sieve, x, i, n)
|
||||
ch <- sieve[i]
|
||||
}
|
||||
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
Copyright © 2025 filifa
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package lib
|
||||
|
||||
func MobiusSieve(n uint) chan int {
|
||||
sieve := make([]int, n)
|
||||
for i := 0; i < int(n); i++ {
|
||||
sieve[i] = i
|
||||
}
|
||||
|
||||
ch := make(chan int)
|
||||
go func() {
|
||||
for i := 0; i < int(n); i++ {
|
||||
if i == 0 || i == 1 || sieve[i] != i {
|
||||
ch <- sieve[i]
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- -1
|
||||
|
||||
for j := 2 * i; j < int(n); j += i {
|
||||
if j%(i*i) == 0 {
|
||||
sieve[j] = 0
|
||||
}
|
||||
|
||||
sieve[j] /= -i
|
||||
}
|
||||
}
|
||||
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Copyright © 2025 filifa
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package lib
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// given a slice where vals[i] = p_{k-1}(i) for a given k, nextPartition updates the slice so vals[i] = p_k(i) using the property that p_k(n) = p_k(n-k) + p_{k-1}(n)
|
||||
func nextPartition(k int, vals []*big.Int) {
|
||||
for i := 1; i < len(vals); i++ {
|
||||
if i-k >= 0 {
|
||||
vals[i].Add(vals[i], vals[i-k])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Partitions(n, k int) *big.Int {
|
||||
if n < 0 {
|
||||
return big.NewInt(0)
|
||||
}
|
||||
|
||||
if k > n {
|
||||
k = n
|
||||
}
|
||||
|
||||
vals := make([]*big.Int, n+1)
|
||||
for i := range vals {
|
||||
vals[i] = big.NewInt(0)
|
||||
}
|
||||
vals[0] = big.NewInt(1)
|
||||
|
||||
for i := 1; i <= k; i++ {
|
||||
nextPartition(i, vals)
|
||||
}
|
||||
|
||||
return vals[n]
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
Copyright © 2025 filifa
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package lib
|
||||
|
||||
func primeOmegaUpdateMultiples(sieve []uint, p uint, n uint, multiplicity bool) {
|
||||
for q := p; ; q *= p {
|
||||
// omega(a*b) = omega(a) + omega(b) if gcd(a,b) = 1
|
||||
for i := 2 * q; i < n; i += q {
|
||||
if i%(p*q) != 0 {
|
||||
sieve[i] += sieve[q]
|
||||
}
|
||||
}
|
||||
|
||||
if p*q >= n {
|
||||
break
|
||||
}
|
||||
|
||||
if multiplicity {
|
||||
sieve[p*q] = 1 + sieve[q]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func PrimeOmegaSieve(n uint, multiplicity bool) chan uint {
|
||||
sieve := make([]uint, n)
|
||||
for i := uint(0); i < n; i++ {
|
||||
sieve[i] = 0
|
||||
}
|
||||
|
||||
ch := make(chan uint)
|
||||
go func() {
|
||||
for i := uint(0); i < n; i++ {
|
||||
if i == 0 || i == 1 || sieve[i] != 0 {
|
||||
ch <- sieve[i]
|
||||
continue
|
||||
}
|
||||
|
||||
sieve[i] = 1
|
||||
primeOmegaUpdateMultiples(sieve, i, n, multiplicity)
|
||||
ch <- sieve[i]
|
||||
}
|
||||
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
Copyright © 2025 filifa
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package lib
|
||||
|
||||
type Point struct {
|
||||
X float64
|
||||
Y float64
|
||||
}
|
||||
|
||||
func Area(points []Point) float64 {
|
||||
total := float64(0)
|
||||
n := len(points)
|
||||
for i, p := range points {
|
||||
q := points[(i+1)%n]
|
||||
total += (p.Y + q.Y) * (p.X - q.X)
|
||||
}
|
||||
|
||||
return total / 2
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
Copyright © 2025 filifa
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package lib
|
||||
|
||||
func TotientSieve(n uint) chan uint {
|
||||
totients := make([]uint, n)
|
||||
totients[0] = 0
|
||||
totients[1] = 1
|
||||
for i := uint(2); i < n; i++ {
|
||||
totients[i] = i - 1
|
||||
}
|
||||
|
||||
ch := make(chan uint)
|
||||
go func() {
|
||||
for i := uint(0); i < n; i++ {
|
||||
ch <- totients[i]
|
||||
if i == 0 || i == 1 || totients[i] != i-1 {
|
||||
continue
|
||||
}
|
||||
|
||||
for j := uint(2 * i); j < n; j += i {
|
||||
totients[j] -= totients[j] / i
|
||||
}
|
||||
}
|
||||
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
Loading…
Reference in New Issue