go math 源码

  • 2022-07-15
  • 浏览 (923)

golang math 代码

文件路径:/test/codegen/math.go

// asmcheck

// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package codegen

import "math"

var sink64 [8]float64

func approx(x float64) {
	// amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41"
	// amd64:"ROUNDSD\t[$]2"
	// s390x:"FIDBR\t[$]6"
	// arm64:"FRINTPD"
	// ppc64:"FRIP"
	// ppc64le:"FRIP"
	// wasm:"F64Ceil"
	sink64[0] = math.Ceil(x)

	// amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41"
	// amd64:"ROUNDSD\t[$]1"
	// s390x:"FIDBR\t[$]7"
	// arm64:"FRINTMD"
	// ppc64:"FRIM"
	// ppc64le:"FRIM"
	// wasm:"F64Floor"
	sink64[1] = math.Floor(x)

	// s390x:"FIDBR\t[$]1"
	// arm64:"FRINTAD"
	// ppc64:"FRIN"
	// ppc64le:"FRIN"
	sink64[2] = math.Round(x)

	// amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41"
	// amd64:"ROUNDSD\t[$]3"
	// s390x:"FIDBR\t[$]5"
	// arm64:"FRINTZD"
	// ppc64:"FRIZ"
	// ppc64le:"FRIZ"
	// wasm:"F64Trunc"
	sink64[3] = math.Trunc(x)

	// amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41"
	// amd64:"ROUNDSD\t[$]0"
	// s390x:"FIDBR\t[$]4"
	// arm64:"FRINTND"
	// wasm:"F64Nearest"
	sink64[4] = math.RoundToEven(x)
}

func sqrt(x float64) float64 {
	// amd64:"SQRTSD"
	// 386/sse2:"SQRTSD" 386/softfloat:-"SQRTD"
	// arm64:"FSQRTD"
	// arm/7:"SQRTD"
	// mips/hardfloat:"SQRTD" mips/softfloat:-"SQRTD"
	// mips64/hardfloat:"SQRTD" mips64/softfloat:-"SQRTD"
	// wasm:"F64Sqrt"
	return math.Sqrt(x)
}

func sqrt32(x float32) float32 {
	// amd64:"SQRTSS"
	// 386/sse2:"SQRTSS" 386/softfloat:-"SQRTS"
	// arm64:"FSQRTS"
	// arm/7:"SQRTF"
	// mips/hardfloat:"SQRTF" mips/softfloat:-"SQRTF"
	// mips64/hardfloat:"SQRTF" mips64/softfloat:-"SQRTF"
	// wasm:"F32Sqrt"
	return float32(math.Sqrt(float64(x)))
}

// Check that it's using integer registers
func abs(x, y float64) {
	// amd64:"BTRQ\t[$]63"
	// arm64:"FABSD\t"
	// s390x:"LPDFR\t",-"MOVD\t"     (no integer load/store)
	// ppc64:"FABS\t"
	// ppc64le:"FABS\t"
	// riscv64:"FABSD\t"
	// wasm:"F64Abs"
	// arm/6:"ABSD\t"
	sink64[0] = math.Abs(x)

	// amd64:"BTRQ\t[$]63","PXOR"    (TODO: this should be BTSQ)
	// s390x:"LNDFR\t",-"MOVD\t"     (no integer load/store)
	// ppc64:"FNABS\t"
	// ppc64le:"FNABS\t"
	sink64[1] = -math.Abs(y)
}

// Check that it's using integer registers
func abs32(x float32) float32 {
	// s390x:"LPDFR",-"LDEBR",-"LEDBR"     (no float64 conversion)
	return float32(math.Abs(float64(x)))
}

// Check that it's using integer registers
func copysign(a, b, c float64) {
	// amd64:"BTRQ\t[$]63","ANDQ","ORQ"
	// s390x:"CPSDR",-"MOVD"         (no integer load/store)
	// ppc64:"FCPSGN"
	// ppc64le:"FCPSGN"
	// riscv64:"FSGNJD"
	// wasm:"F64Copysign"
	sink64[0] = math.Copysign(a, b)

	// amd64:"BTSQ\t[$]63"
	// s390x:"LNDFR\t",-"MOVD\t"     (no integer load/store)
	// ppc64:"FCPSGN"
	// ppc64le:"FCPSGN"
	// riscv64:"FSGNJD"
	// arm64:"ORR", -"AND"
	sink64[1] = math.Copysign(c, -1)

	// Like math.Copysign(c, -1), but with integer operations. Useful
	// for platforms that have a copysign opcode to see if it's detected.
	// s390x:"LNDFR\t",-"MOVD\t"     (no integer load/store)
	sink64[2] = math.Float64frombits(math.Float64bits(a) | 1<<63)

	// amd64:"ANDQ","ORQ"
	// s390x:"CPSDR\t",-"MOVD\t"     (no integer load/store)
	// ppc64:"FCPSGN"
	// ppc64le:"FCPSGN"
	// riscv64:"FSGNJD"
	sink64[3] = math.Copysign(-1, c)
}

func fma(x, y, z float64) float64 {
	// amd64/v3:-".*x86HasFMA"
	// amd64:"VFMADD231SD"
	// arm/6:"FMULAD"
	// arm64:"FMADDD"
	// s390x:"FMADD"
	// ppc64:"FMADD"
	// ppc64le:"FMADD"
	// riscv64:"FMADDD"
	return math.FMA(x, y, z)
}

func fms(x, y, z float64) float64 {
	// riscv64:"FMSUBD"
	return math.FMA(x, y, -z)
}

func fnma(x, y, z float64) float64 {
	// riscv64:"FNMADDD"
	return math.FMA(-x, y, z)
}

func fnms(x, y, z float64) float64 {
	// riscv64:"FNMSUBD"
	return math.FMA(x, -y, -z)
}

func fromFloat64(f64 float64) uint64 {
	// amd64:"MOVQ\tX.*, [^X].*"
	// arm64:"FMOVD\tF.*, R.*"
	// ppc64:"MFVSRD"
	// ppc64le:"MFVSRD"
	return math.Float64bits(f64+1) + 1
}

func fromFloat32(f32 float32) uint32 {
	// amd64:"MOVL\tX.*, [^X].*"
	// arm64:"FMOVS\tF.*, R.*"
	return math.Float32bits(f32+1) + 1
}

func toFloat64(u64 uint64) float64 {
	// amd64:"MOVQ\t[^X].*, X.*"
	// arm64:"FMOVD\tR.*, F.*"
	// ppc64:"MTVSRD"
	// ppc64le:"MTVSRD"
	return math.Float64frombits(u64+1) + 1
}

func toFloat32(u32 uint32) float32 {
	// amd64:"MOVL\t[^X].*, X.*"
	// arm64:"FMOVS\tR.*, F.*"
	return math.Float32frombits(u32+1) + 1
}

// Test that comparisons with constants converted to float
// are evaluated at compile-time

func constantCheck64() bool {
	// amd64:"(MOVB\t[$]0)|(XORL\t[A-Z][A-Z0-9]+, [A-Z][A-Z0-9]+)",-"FCMP",-"MOVB\t[$]1"
	// s390x:"MOV(B|BZ|D)\t[$]0,",-"FCMPU",-"MOV(B|BZ|D)\t[$]1,"
	return 0.5 == float64(uint32(1)) || 1.5 > float64(uint64(1<<63))
}

func constantCheck32() bool {
	// amd64:"MOV(B|L)\t[$]1",-"FCMP",-"MOV(B|L)\t[$]0"
	// s390x:"MOV(B|BZ|D)\t[$]1,",-"FCMPU",-"MOV(B|BZ|D)\t[$]0,"
	return float32(0.5) <= float32(int64(1)) && float32(1.5) >= float32(int32(-1<<31))
}

// Test that integer constants are converted to floating point constants
// at compile-time

func constantConvert32(x float32) float32 {
	// amd64:"MOVSS\t[$]f32.3f800000\\(SB\\)"
	// s390x:"FMOVS\t[$]f32.3f800000\\(SB\\)"
	// ppc64:"FMOVS\t[$]f32.3f800000\\(SB\\)"
	// ppc64le:"FMOVS\t[$]f32.3f800000\\(SB\\)"
	// arm64:"FMOVS\t[$]\\(1.0\\)"
	if x > math.Float32frombits(0x3f800000) {
		return -x
	}
	return x
}

func constantConvertInt32(x uint32) uint32 {
	// amd64:-"MOVSS"
	// s390x:-"FMOVS"
	// ppc64:-"FMOVS"
	// ppc64le:-"FMOVS"
	// arm64:-"FMOVS"
	if x > math.Float32bits(1) {
		return -x
	}
	return x
}

func nanGenerate64() float64 {
	// Test to make sure we don't generate a NaN while constant propagating.
	// See issue 36400.
	zero := 0.0
	// amd64:-"DIVSD"
	inf := 1 / zero // +inf. We can constant propagate this one.
	negone := -1.0

	// amd64:"DIVSD"
	z0 := zero / zero
	// amd64:"MULSD"
	z1 := zero * inf
	// amd64:"SQRTSD"
	z2 := math.Sqrt(negone)
	return z0 + z1 + z2
}

func nanGenerate32() float32 {
	zero := float32(0.0)
	// amd64:-"DIVSS"
	inf := 1 / zero // +inf. We can constant propagate this one.

	// amd64:"DIVSS"
	z0 := zero / zero
	// amd64:"MULSS"
	z1 := zero * inf
	return z0 + z1
}

相关信息

go 源码目录

相关文章

go addrcalc 源码

go alloc 源码

go arithmetic 源码

go bitfield 源码

go bits 源码

go bmi 源码

go bool 源码

go clobberdead 源码

go clobberdeadreg 源码

go compare_and_branch 源码

0  赞