//go:build (amd64 || arm64) && !generic && !generic32 && !generic64
// +build amd64 arm64
// +build !generic
// +build !generic32
// +build !generic64

package ec256

import (
	"fmt"
	"math/big"
	"testing"
	"time"
)

func pointFromBig(x, y *big.Int) []uint64 {
	xyz := make([]uint64, 12)
	fromBig(xyz[0:4], maybeReduceModP(x))
	fromBig(xyz[4:8], maybeReduceModP(y))
	c256Mul(xyz[0:4], xyz[0:4], rr[:])
	c256Mul(xyz[4:8], xyz[4:8], rr[:])
	xyz[8] = montOne0
	xyz[9] = montOne1
	xyz[10] = montOne2
	xyz[11] = montOne3
	return xyz
}

// func TestC256AddSpeed(t *testing.T) {
// 	a := []uint64{0x715A4589334C74C7, 0x8FE30BBFF2660BE1, 0x5F9904466A39C994, 0x32C4AE2C1F198119}
// 	b := []uint64{0x715A4589334C74C7, 0x8FE30BBFF2660BE1, 0x5F9904466A39C994, 0x32C4AE2C1F198119}
// 	res := make([]uint64, 4)
// 	begin := time.Now()
// 	total := 1000000000
// 	for i := 0; i < total; i++ {
// 		c256Add(res, a, b)
// 	}
// 	elaspe := time.Since(begin)
// 	fmt.Println("time: ", elaspe.Milliseconds(), "ms")
// 	fmt.Println(int(float64(total) / float64(elaspe.Milliseconds()) * 1000))
// }

func TestC256SqrSpeed(t *testing.T) {
	a := []uint64{0x715A4589334C74C7, 0x8FE30BBFF2660BE1, 0x5F9904466A39C994, 0x32C4AE2C1F198119}
	res := make([]uint64, 4)
	begin := time.Now()
	total := 100000000
	for i := 0; i < total; i++ {
		c256Sqr(res, a, 1)
		// c256Sqr(res, res, 1)
		// c256Sqr(res, res, 1)
		// c256Sqr(res, res, 1)
	}
	elaspe := time.Since(begin)
	fmt.Println("time: ", elaspe.Milliseconds(), "ms")
	fmt.Println(int(float64(total) / float64(elaspe.Milliseconds()) * 1000))
}

func TestC256MulSpeed(t *testing.T) {
	a := []uint64{0x715A4589334C74C7, 0x8FE30BBFF2660BE1, 0x5F9904466A39C994, 0x32C4AE2C1F198119}
	b := []uint64{0x715A4589334C74C6, 0x8FE30BBFF2660BE1, 0x5F9904466A39C994, 0x32C4AE2C1F198119}
	res := make([]uint64, 4)
	total := 100000000
	begin := time.Now()
	for i := 0; i < total; i++ {
		c256Mul(res, a, b)
	}
	elaspe := time.Since(begin)
	fmt.Println("time: ", elaspe.Milliseconds(), "ms")
	fmt.Println(int(float64(total) / float64(elaspe.Milliseconds()) * 1000))
}

func TestC256PointAddAsmSpeed(t *testing.T) {
	p1 := pointFromBig(c256.Gx, c256.Gy)
	x2, y2 := c256.ScalarMult(c256.Gx, c256.Gy, (new(big.Int).SetInt64(2)).Bytes())
	p2 := pointFromBig(x2, y2)
	var res [12]uint64
	begin := time.Now()
	total := 10000000
	for i := 0; i < total; i++ {
		c256PointAddAsm(res[:], p1, p2)
	}
	elaspe := time.Since(begin)
	fmt.Println("time: ", elaspe.Milliseconds(), "ms")
	fmt.Println(int(float64(total) / float64(elaspe.Milliseconds()) * 1000))
}

func TestC256PointDoubleAsmSpeed(t *testing.T) {
	p1 := pointFromBig(c256.Gx, c256.Gy)
	var res [12]uint64
	begin := time.Now()
	total := 10000000
	for i := 0; i < total; i++ {
		c256PointDoubleAsm(res[:], p1)
	}
	elaspe := time.Since(begin)
	fmt.Println("time: ", elaspe.Milliseconds(), "ms")
	fmt.Println(int(float64(total) / float64(elaspe.Milliseconds()) * 1000))
}

func TestC256InvSpeed(t *testing.T) {
	in := []uint64{34235, 23341, 3444, 55555}
	out := make([]uint64, 4)
	begin := time.Now()
	total := 1000000
	for i := 0; i < total; i++ {
		c256Inverse(out, in)
	}
	elaspe := time.Since(begin)
	fmt.Println("time: ", elaspe.Milliseconds(), "ms")
	fmt.Println(float64(total) / float64(elaspe.Milliseconds()) * 1000)
}
