mathtools/cmd/divisor.go

82 lines
2.2 KiB
Go

/*
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 cmd
import (
"fmt"
"math/big"
"github.com/spf13/cobra"
)
// 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)
if !ok {
cmd.PrintErrln("invalid input " + arg)
continue
}
d := divisorSummatory(n)
fmt.Println(d)
}
}
// divisorCmd represents the divisor command
var divisorCmd = &cobra.Command{
Use: "divisor N [N ...]",
Short: "Compute the divisor summatory function",
Long: `Compute the divisor summatory function.
For each argument n, compute D(n) = d(1) + d(2) + d(3) + ... + d(n), where d(n) is the number of divisors of n.`,
Args: cobra.MinimumNArgs(1),
Run: divisorSum,
}
func init() {
sumCmd.AddCommand(divisorCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// divisorCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// divisorCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}