make same performance improvements to all sieve commands

This commit is contained in:
filifa 2025-10-01 23:44:56 -04:00
parent 5f65b35b9c
commit 51ae15cedc
6 changed files with 30 additions and 18 deletions

View File

@ -17,7 +17,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package cmd package cmd
import ( import (
"bufio"
"fmt" "fmt"
"os"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"scm.dairydemon.net/filifa/mathtools/internal/lib" "scm.dairydemon.net/filifa/mathtools/internal/lib"
@ -27,7 +29,10 @@ var divisorsN uint
var divisorsE uint var divisorsE uint
func divisors(cmd *cobra.Command, args []string) { func divisors(cmd *cobra.Command, args []string) {
ch := lib.DivisorsSieve(divisorsN, divisorsE) bufStdout := bufio.NewWriter(os.Stdout)
defer bufStdout.Flush()
ch := lib.DivisorsSieve(divisorsN, divisorsE, 1000)
for i := 0; ; i++ { for i := 0; ; i++ {
v, ok := <-ch v, ok := <-ch
if !ok { if !ok {
@ -38,7 +43,7 @@ func divisors(cmd *cobra.Command, args []string) {
continue continue
} }
fmt.Println(v) fmt.Fprintln(bufStdout, v)
} }
} }

View File

@ -17,7 +17,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package cmd package cmd
import ( import (
"bufio"
"fmt" "fmt"
"os"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"scm.dairydemon.net/filifa/mathtools/internal/lib" "scm.dairydemon.net/filifa/mathtools/internal/lib"
@ -26,7 +28,10 @@ import (
var mobiusN uint var mobiusN uint
func mobius(cmd *cobra.Command, args []string) { func mobius(cmd *cobra.Command, args []string) {
ch := lib.MobiusSieve(mobiusN) bufStdout := bufio.NewWriter(os.Stdout)
defer bufStdout.Flush()
ch := lib.MobiusSieve(mobiusN, 1000)
for i := 0; ; i++ { for i := 0; ; i++ {
v, ok := <-ch v, ok := <-ch
if !ok { if !ok {
@ -37,7 +42,7 @@ func mobius(cmd *cobra.Command, args []string) {
continue continue
} }
fmt.Println(v) fmt.Fprintln(bufStdout, v)
} }
} }

View File

@ -17,7 +17,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package cmd package cmd
import ( import (
"bufio"
"fmt" "fmt"
"os"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"scm.dairydemon.net/filifa/mathtools/internal/lib" "scm.dairydemon.net/filifa/mathtools/internal/lib"
@ -27,7 +29,10 @@ var primeOmegaN uint
var primeOmegaMul bool var primeOmegaMul bool
func primeOmega(cmd *cobra.Command, args []string) { func primeOmega(cmd *cobra.Command, args []string) {
ch := lib.PrimeOmegaSieve(primeOmegaN, primeOmegaMul) bufStdout := bufio.NewWriter(os.Stdout)
defer bufStdout.Flush()
ch := lib.PrimeOmegaSieve(primeOmegaN, primeOmegaMul, 1000)
for i := 0; ; i++ { for i := 0; ; i++ {
v, ok := <-ch v, ok := <-ch
if !ok { if !ok {
@ -38,7 +43,7 @@ func primeOmega(cmd *cobra.Command, args []string) {
continue continue
} }
fmt.Println(v) fmt.Fprintln(bufStdout, v)
} }
} }

View File

@ -51,15 +51,16 @@ 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. 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 { func DivisorsSieve(n uint, x uint, buflen uint) chan uint {
sieve := make([]uint, n) sieve := make([]uint, n)
sieve[0] = 0 sieve[0] = 0
for i := uint(1); i < n; i++ { for i := uint(1); i < n; i++ {
sieve[i] = 1 sieve[i] = 1
} }
ch := make(chan uint) ch := make(chan uint, buflen)
go func() { go func() {
defer close(ch)
for i := uint(0); i < n; i++ { for i := uint(0); i < n; i++ {
if i == 0 || i == 1 || sieve[i] != 1 { if i == 0 || i == 1 || sieve[i] != 1 {
ch <- sieve[i] ch <- sieve[i]
@ -70,8 +71,6 @@ func DivisorsSieve(n uint, x uint) chan uint {
updateMultiples(sieve, x, i, n) updateMultiples(sieve, x, i, n)
ch <- sieve[i] ch <- sieve[i]
} }
close(ch)
}() }()
return ch return ch

View File

@ -19,14 +19,15 @@ package lib
/* /*
MobiusSieve computes mobius(k) for k=1 to n, where mobius is the Mobius function. MobiusSieve computes mobius(k) for k=1 to n, where mobius is the Mobius function.
*/ */
func MobiusSieve(n uint) chan int { func MobiusSieve(n uint, buflen uint) chan int {
sieve := make([]int, n) sieve := make([]int, n)
for i := 0; i < int(n); i++ { for i := 0; i < int(n); i++ {
sieve[i] = i sieve[i] = i
} }
ch := make(chan int) ch := make(chan int, buflen)
go func() { go func() {
defer close(ch)
for i := 0; i < int(n); i++ { for i := 0; i < int(n); i++ {
if i == 0 || i == 1 || sieve[i] != i { if i == 0 || i == 1 || sieve[i] != i {
ch <- sieve[i] ch <- sieve[i]
@ -43,8 +44,6 @@ func MobiusSieve(n uint) chan int {
sieve[j] /= -i sieve[j] /= -i
} }
} }
close(ch)
}() }()
return ch return ch

View File

@ -38,14 +38,15 @@ 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. 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 { func PrimeOmegaSieve(n uint, multiplicity bool, buflen uint) chan uint {
sieve := make([]uint, n) sieve := make([]uint, n)
for i := uint(0); i < n; i++ { for i := uint(0); i < n; i++ {
sieve[i] = 0 sieve[i] = 0
} }
ch := make(chan uint) ch := make(chan uint, buflen)
go func() { go func() {
defer close(ch)
for i := uint(0); i < n; i++ { for i := uint(0); i < n; i++ {
if i == 0 || i == 1 || sieve[i] != 0 { if i == 0 || i == 1 || sieve[i] != 0 {
ch <- sieve[i] ch <- sieve[i]
@ -56,8 +57,6 @@ func PrimeOmegaSieve(n uint, multiplicity bool) chan uint {
primeOmegaUpdateMultiples(sieve, i, n, multiplicity) primeOmegaUpdateMultiples(sieve, i, n, multiplicity)
ch <- sieve[i] ch <- sieve[i]
} }
close(ch)
}() }()
return ch return ch