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