package utils import ( "fmt" "math" "testing" "github.com/badu/bus" ) 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) } } } 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} }