summaryrefslogtreecommitdiff
path: root/src/pkg/math/exp_amd64.s
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/math/exp_amd64.s')
-rw-r--r--src/pkg/math/exp_amd64.s92
1 files changed, 50 insertions, 42 deletions
diff --git a/src/pkg/math/exp_amd64.s b/src/pkg/math/exp_amd64.s
index 844b5c923..74c9c876a 100644
--- a/src/pkg/math/exp_amd64.s
+++ b/src/pkg/math/exp_amd64.s
@@ -19,20 +19,32 @@
#define LOG2E 1.4426950408889634073599246810018920 // 1/LN2
#define LN2U 0.69314718055966295651160180568695068359375 // upper half LN2
#define LN2L 0.28235290563031577122588448175013436025525412068e-12 // lower half LN2
+#define T0 1.0
+#define T1 0.5
+#define T2 1.6666666666666666667e-1
+#define T3 4.1666666666666666667e-2
+#define T4 8.3333333333333333333e-3
+#define T5 1.3888888888888888889e-3
+#define T6 1.9841269841269841270e-4
+#define T7 2.4801587301587301587e-5
+#define PosInf 0x7FF0000000000000
+#define NegInf 0xFFF0000000000000
// func Exp(x float64) float64
TEXT ·Exp(SB),7,$0
// test bits for not-finite
- MOVQ x+0(FP), AX
- MOVQ $0x7ff0000000000000, BX
- ANDQ BX, AX
- CMPQ BX, AX
- JEQ not_finite
- MOVSD x+0(FP), X0
+ MOVQ x+0(FP), BX
+ MOVQ $~(1<<63), AX // sign bit mask
+ MOVQ BX, DX
+ ANDQ AX, DX
+ MOVQ $PosInf, AX
+ CMPQ AX, DX
+ JLE notFinite
+ MOVQ BX, X0
MOVSD $LOG2E, X1
MULSD X0, X1
- CVTTSD2SQ X1, BX // BX = exponent
- CVTSQ2SD BX, X1
+ CVTSD2SL X1, BX // BX = exponent
+ CVTSL2SD BX, X1
MOVSD $LN2U, X2
MULSD X1, X2
SUBSD X2, X0
@@ -40,31 +52,23 @@ TEXT ·Exp(SB),7,$0
MULSD X1, X2
SUBSD X2, X0
// reduce argument
- MOVSD $0.0625, X1
- MULSD X1, X0
+ MULSD $0.0625, X0
// Taylor series evaluation
- MOVSD $2.4801587301587301587e-5, X1
+ MOVSD $T7, X1
MULSD X0, X1
- MOVSD $1.9841269841269841270e-4, X2
- ADDSD X2, X1
+ ADDSD $T6, X1
MULSD X0, X1
- MOVSD $1.3888888888888888889e-3, X2
- ADDSD X2, X1
+ ADDSD $T5, X1
MULSD X0, X1
- MOVSD $8.3333333333333333333e-3, X2
- ADDSD X2, X1
+ ADDSD $T4, X1
MULSD X0, X1
- MOVSD $4.1666666666666666667e-2, X2
- ADDSD X2, X1
+ ADDSD $T3, X1
MULSD X0, X1
- MOVSD $1.6666666666666666667e-1, X2
- ADDSD X2, X1
+ ADDSD $T2, X1
MULSD X0, X1
- MOVSD $0.5, X2
- ADDSD X2, X1
+ ADDSD $T1, X1
MULSD X0, X1
- MOVSD $1.0, X2
- ADDSD X2, X1
+ ADDSD $T0, X1
MULSD X1, X0
MOVSD $2.0, X1
ADDSD X0, X1
@@ -78,27 +82,31 @@ TEXT ·Exp(SB),7,$0
MOVSD $2.0, X1
ADDSD X0, X1
MULSD X1, X0
- MOVSD $1.0, X1
- ADDSD X1, X0
- // return ldexp(fr, exp)
- MOVQ $0x3ff, AX // bias + 1
- ADDQ AX, BX
+ ADDSD $1.0, X0
+ // return fr * 2**exponent
+ MOVL $0x3FF, AX // bias
+ ADDL AX, BX
+ JLE underflow
+ CMPL BX, $0x7FF
+ JGE overflow
+ MOVL $52, CX
+ SHLQ CX, BX
MOVQ BX, X1
- MOVQ $52, AX // shift
- MOVQ AX, X2
- PSLLQ X2, X1
MULSD X1, X0
MOVSD X0, r+8(FP)
RET
-not_finite:
-// test bits for -Inf
- MOVQ x+0(FP), AX
- MOVQ $0xfff0000000000000, BX
- CMPQ BX, AX
- JNE not_neginf
- XORQ AX, AX
+notFinite:
+ // test bits for -Inf
+ MOVQ $NegInf, AX
+ CMPQ AX, BX
+ JNE notNegInf
+ // -Inf, return 0
+underflow: // return 0
+ MOVQ $0, AX
MOVQ AX, r+8(FP)
RET
-not_neginf:
- MOVQ AX, r+8(FP)
+overflow: // return +Inf
+ MOVQ $PosInf, BX
+notNegInf: // NaN or +Inf, return x
+ MOVQ BX, r+8(FP)
RET