github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/ipow.go (about)

     1  package goja
     2  
     3  // inspired by https://gist.github.com/orlp/3551590
     4  
     5  var overflows = [64]int64{
     6  	9223372036854775807, 9223372036854775807, 3037000499, 2097151,
     7  	55108, 6208, 1448, 511,
     8  	234, 127, 78, 52,
     9  	38, 28, 22, 18,
    10  	15, 13, 11, 9,
    11  	8, 7, 7, 6,
    12  	6, 5, 5, 5,
    13  	4, 4, 4, 4,
    14  	3, 3, 3, 3,
    15  	3, 3, 3, 3,
    16  	2, 2, 2, 2,
    17  	2, 2, 2, 2,
    18  	2, 2, 2, 2,
    19  	2, 2, 2, 2,
    20  	2, 2, 2, 2,
    21  	2, 2, 2, 2,
    22  }
    23  
    24  var highestBitSet = [63]byte{
    25  	0, 1, 2, 2, 3, 3, 3, 3,
    26  	4, 4, 4, 4, 4, 4, 4, 4,
    27  	5, 5, 5, 5, 5, 5, 5, 5,
    28  	5, 5, 5, 5, 5, 5, 5, 5,
    29  	6, 6, 6, 6, 6, 6, 6, 6,
    30  	6, 6, 6, 6, 6, 6, 6, 6,
    31  	6, 6, 6, 6, 6, 6, 6, 6,
    32  	6, 6, 6, 6, 6, 6, 6,
    33  }
    34  
    35  func ipow(base, exp int64) (result int64) {
    36  	if exp >= 63 {
    37  		if base == 1 {
    38  			return 1
    39  		}
    40  
    41  		if base == -1 {
    42  			return 1 - 2*(exp&1)
    43  		}
    44  
    45  		return 0
    46  	}
    47  
    48  	if base > overflows[exp] || -base > overflows[exp] {
    49  		return 0
    50  	}
    51  
    52  	result = 1
    53  
    54  	switch highestBitSet[byte(exp)] {
    55  	case 6:
    56  		if exp&1 != 0 {
    57  			result *= base
    58  		}
    59  		exp >>= 1
    60  		base *= base
    61  		fallthrough
    62  	case 5:
    63  		if exp&1 != 0 {
    64  			result *= base
    65  		}
    66  		exp >>= 1
    67  		base *= base
    68  		fallthrough
    69  	case 4:
    70  		if exp&1 != 0 {
    71  			result *= base
    72  		}
    73  		exp >>= 1
    74  		base *= base
    75  		fallthrough
    76  	case 3:
    77  		if exp&1 != 0 {
    78  			result *= base
    79  		}
    80  		exp >>= 1
    81  		base *= base
    82  		fallthrough
    83  	case 2:
    84  		if exp&1 != 0 {
    85  			result *= base
    86  		}
    87  		exp >>= 1
    88  		base *= base
    89  		fallthrough
    90  	case 1:
    91  		if exp&1 != 0 {
    92  			result *= base
    93  		}
    94  		fallthrough
    95  	default:
    96  		return result
    97  	}
    98  }