github.com/gopherd/gonum@v0.0.4/internal/asm/f64/l2norminc_amd64.s (about) 1 // Copyright ©2019 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build !noasm,!gccgo,!safe 6 7 #include "textflag.h" 8 9 #define SUMSQ X0 10 #define ABSX X1 11 #define SCALE X2 12 #define ZERO X3 13 #define TMP X4 14 #define ABSMASK X5 15 #define INF X7 16 #define INFMASK X11 17 #define NANMASK X12 18 #define IDX AX 19 #define LEN SI 20 #define INC BX 21 #define X_ DI 22 23 #define ABSMASK_DATA l2nrodata<>+0(SB) 24 #define INF_DATA l2nrodata<>+8(SB) 25 #define NAN_DATA l2nrodata<>+16(SB) 26 // AbsMask 27 DATA l2nrodata<>+0(SB)/8, $0x7FFFFFFFFFFFFFFF 28 // Inf 29 DATA l2nrodata<>+8(SB)/8, $0x7FF0000000000000 30 // NaN 31 DATA l2nrodata<>+16(SB)/8, $0xFFF8000000000000 32 GLOBL l2nrodata<>+0(SB), RODATA, $24 33 34 // func L2NormInc(x []float64, n, incX uintptr) (norm float64) 35 TEXT ·L2NormInc(SB), NOSPLIT, $0 36 MOVQ n+24(FP), LEN // LEN = len(x) 37 MOVQ incX+32(FP), INC 38 MOVQ x_base+0(FP), X_ 39 XORPS ZERO, ZERO 40 CMPQ LEN, $0 // if LEN == 0 { return 0 } 41 JZ retZero 42 43 XORPS INFMASK, INFMASK 44 XORPS NANMASK, NANMASK 45 MOVSD $1.0, SUMSQ // ssq = 1 46 XORPS SCALE, SCALE 47 MOVSD ABSMASK_DATA, ABSMASK 48 MOVSD INF_DATA, INF 49 SHLQ $3, INC // INC *= sizeof(float64) 50 51 initZero: // for ;x[i]==0; i++ {} 52 // Skip all leading zeros, to avoid divide by zero NaN 53 MOVSD (X_), ABSX // absxi = x[i] 54 UCOMISD ABSX, ZERO 55 JP retNaN // if isNaN(x[i]) { return NaN } 56 JNZ loop // if x[i] != 0 { goto loop } 57 ADDQ INC, X_ // i += INC 58 DECQ LEN // LEN-- 59 JZ retZero // if LEN == 0 { return 0 } 60 JMP initZero 61 62 loop: 63 MOVSD (X_), ABSX // absxi = x[i] 64 MOVUPS ABSX, TMP 65 CMPSD ABSX, TMP, $3 66 ORPD TMP, NANMASK // NANMASK = NANMASK | IsNaN(absxi) 67 MOVSD INF, TMP 68 ANDPD ABSMASK, ABSX // absxi == Abs(absxi) 69 CMPSD ABSX, TMP, $0 70 ORPD TMP, INFMASK // INFMASK = INFMASK | IsInf(absxi) 71 UCOMISD SCALE, ABSX 72 JA adjScale // IF SCALE > ABSXI { goto adjScale } 73 74 DIVSD SCALE, ABSX // absxi = scale / absxi 75 MULSD ABSX, ABSX // absxi *= absxi 76 ADDSD ABSX, SUMSQ // sumsq += absxi 77 ADDQ INC, X_ // i += INC 78 DECQ LEN // LEN-- 79 JNZ loop // if LEN > 0 { continue } 80 JMP retSum // if LEN == 0 { goto retSum } 81 82 adjScale: // Scale > Absxi 83 DIVSD ABSX, SCALE // tmp = absxi / scale 84 MULSD SCALE, SUMSQ // sumsq *= tmp 85 MULSD SCALE, SUMSQ // sumsq *= tmp 86 ADDSD $1.0, SUMSQ // sumsq += 1 87 MOVUPS ABSX, SCALE // scale = absxi 88 ADDQ INC, X_ // i += INC 89 DECQ LEN // LEN-- 90 JNZ loop // if LEN > 0 { continue } 91 92 retSum: // Calculate return value 93 SQRTSD SUMSQ, SUMSQ // sumsq = sqrt(sumsq) 94 MULSD SCALE, SUMSQ // sumsq += scale 95 MOVQ SUMSQ, R10 // tmp = sumsq 96 UCOMISD ZERO, INFMASK 97 CMOVQPS INF_DATA, R10 // if INFMASK { tmp = INF } 98 UCOMISD ZERO, NANMASK 99 CMOVQPS NAN_DATA, R10 // if NANMASK { tmp = NaN } 100 MOVQ R10, norm+40(FP) // return tmp 101 RET 102 103 retZero: 104 MOVSD ZERO, norm+40(FP) // return 0 105 RET 106 107 retNaN: 108 MOVSD NAN_DATA, TMP // return NaN 109 MOVSD TMP, norm+40(FP) 110 RET