2025-07-30 02:27:58 +00:00
|
|
|
|
package utils
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"fmt"
|
|
|
|
|
|
"math"
|
|
|
|
|
|
"testing"
|
2025-08-05 16:10:18 +08:00
|
|
|
|
|
|
|
|
|
|
"github.com/badu/bus"
|
2025-07-30 02:27:58 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
func Test_fastSqrt(t *testing.T) {
|
|
|
|
|
|
// 测试用例
|
|
|
|
|
|
testCases := []float64{2, 4, 10, 16, 25, 100, 1000, 0.5, 0.01, 1e-20}
|
|
|
|
|
|
|
|
|
|
|
|
fmt.Println("测试卡马克快速平方根算法与标准库的对比:")
|
|
|
|
|
|
fmt.Println("数值\t快速算法结果\t标准库结果\t绝对误差")
|
|
|
|
|
|
fmt.Println("--------------------------------------------------------------")
|
|
|
|
|
|
|
|
|
|
|
|
for _, x := range testCases {
|
|
|
|
|
|
fastResult := fastSqrt(x)
|
|
|
|
|
|
stdResult := math.Sqrt(x)
|
|
|
|
|
|
error := math.Abs(fastResult - stdResult)
|
|
|
|
|
|
|
|
|
|
|
|
fmt.Printf("%.10g\t%.10g\t\t%.10g\t\t%.2e\n",
|
|
|
|
|
|
x, fastResult, stdResult, error)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 测试整数版本
|
|
|
|
|
|
fmt.Println("\n测试整数快速平方根算法:")
|
|
|
|
|
|
fmt.Println("数值\t快速算法结果\t标准库转换结果")
|
|
|
|
|
|
fmt.Println("--------------------------------------")
|
|
|
|
|
|
|
|
|
|
|
|
for _, x := range []int{2, 4, 10, 16, 25, 100, 1000} {
|
|
|
|
|
|
fastResult := fastSqrtInt(x)
|
|
|
|
|
|
stdResult := int(math.Sqrt(float64(x)))
|
|
|
|
|
|
|
|
|
|
|
|
fmt.Printf("%d\t%d\t\t%d\n", x, fastResult, stdResult)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
func BenchmarkMathSqrt(b *testing.B) {
|
|
|
|
|
|
testValues := []float64{2, 4, 10, 16, 25, 100, 1000, 0.5, 0.01, 1e-20}
|
|
|
|
|
|
b.ResetTimer()
|
|
|
|
|
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
|
|
for _, x := range testValues {
|
|
|
|
|
|
_ = math.Sqrt(x)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func BenchmarkFastSqrt(b *testing.B) {
|
|
|
|
|
|
testValues := []float64{2, 4, 10, 16, 25, 100, 1000, 0.5, 0.01, 1e-20}
|
|
|
|
|
|
b.ResetTimer()
|
|
|
|
|
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
|
|
for _, x := range testValues {
|
|
|
|
|
|
_ = fastSqrt(x)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func BenchmarkFastSqrtCarmack(b *testing.B) {
|
|
|
|
|
|
testValues := []float64{2, 4, 10, 16, 25, 100, 1000, 0.5, 0.01, 1e-20}
|
|
|
|
|
|
b.ResetTimer()
|
|
|
|
|
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
|
|
for _, x := range testValues {
|
|
|
|
|
|
_ = fastSqrtCarmack(x)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func BenchmarkMathSqrtInt(b *testing.B) {
|
|
|
|
|
|
testValues := []int{2, 4, 10, 16, 25, 100, 1000, 10000, 100000}
|
|
|
|
|
|
b.ResetTimer()
|
|
|
|
|
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
|
|
for _, x := range testValues {
|
|
|
|
|
|
_ = int(math.Sqrt(float64(x)))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func BenchmarkFastSqrtInt(b *testing.B) {
|
|
|
|
|
|
testValues := []int{2, 4, 10, 16, 25, 100, 1000, 10000, 100000}
|
|
|
|
|
|
b.ResetTimer()
|
|
|
|
|
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
|
|
for _, x := range testValues {
|
|
|
|
|
|
_ = fastSqrtInt(x)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-05 16:10:18 +08:00
|
|
|
|
|
|
|
|
|
|
func Test_fastSqr1(b *testing.T) {
|
|
|
|
|
|
// scenario : we have a large number of subscribers.
|
|
|
|
|
|
// we publish an event and while doing that,
|
|
|
|
|
|
// we register another one on a different goroutine
|
|
|
|
|
|
|
|
|
|
|
|
topic := bus.NewTopic[*Uint32AsyncEvent]()
|
|
|
|
|
|
for i := 0; i < 4096; i++ {
|
|
|
|
|
|
topic.Sub(func(v *Uint32AsyncEvent) {
|
|
|
|
|
|
print(v.u)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
topic.Pub(&Uint32AsyncEvent{u: 1})
|
|
|
|
|
|
// finishPubWait := make(chan struct{})
|
|
|
|
|
|
// finishSubWait := make(chan struct{})
|
|
|
|
|
|
// start := make(chan struct{})
|
|
|
|
|
|
|
|
|
|
|
|
// go func() {
|
|
|
|
|
|
// <-start
|
|
|
|
|
|
// topic.PubAsync(&Uint32AsyncEvent{u: 1})
|
|
|
|
|
|
// defer close(finishPubWait)
|
|
|
|
|
|
// }()
|
|
|
|
|
|
|
|
|
|
|
|
// newSubCalled := false
|
|
|
|
|
|
|
|
|
|
|
|
// go func() {
|
|
|
|
|
|
// <-start
|
|
|
|
|
|
// topic.Sub(func(v *Uint32AsyncEvent) {
|
|
|
|
|
|
// newSubCalled = true
|
|
|
|
|
|
// })
|
|
|
|
|
|
// close(finishSubWait)
|
|
|
|
|
|
// }()
|
|
|
|
|
|
|
|
|
|
|
|
// close(start) // start both goroutines
|
|
|
|
|
|
|
|
|
|
|
|
// <-finishPubWait // wait for pub to finish
|
|
|
|
|
|
|
|
|
|
|
|
// <-finishSubWait // wait for sub to finish
|
|
|
|
|
|
|
|
|
|
|
|
// if newSubCalled {
|
|
|
|
|
|
// print("new subscriber called")
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Various event types
|
|
|
|
|
|
const EventA = 0x01
|
|
|
|
|
|
|
|
|
|
|
|
type Uint32AsyncEvent struct {
|
|
|
|
|
|
u uint32
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Event type for testing purposes
|
|
|
|
|
|
type Event struct {
|
|
|
|
|
|
Data string
|
|
|
|
|
|
type1 uint32
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Type returns the event type
|
|
|
|
|
|
func (ev Event) Type() uint32 {
|
|
|
|
|
|
return ev.type1
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// newEventA creates a new instance of an event
|
|
|
|
|
|
func newEventA(data string) Event {
|
|
|
|
|
|
return Event{Data: data, type1: EventA}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Various event types
|
|
|
|
|
|
const EventB1 = 0x02
|
|
|
|
|
|
|
|
|
|
|
|
func newEventB(data string) Event {
|
|
|
|
|
|
return Event{Data: data, type1: EventB1}
|
|
|
|
|
|
}
|