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

     1  /*
     2  Package ftoa provides ECMAScript-compliant floating point number conversion to string.
     3  
     4  It contains code ported from Rhino (https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/DToA.java)
     5  as well as from the original code by David M. Gay.
     6  
     7  See LICENSE_LUCENE for the original copyright message and disclaimer.
     8  */
     9  package ftoa
    10  
    11  import (
    12  	"math"
    13  )
    14  
    15  const (
    16  	frac_mask = 0xfffff
    17  	exp_shift = 20
    18  	exp_msk1  = 0x100000
    19  
    20  	exp_shiftL       = 52
    21  	exp_mask_shifted = 0x7ff
    22  	frac_maskL       = 0xfffffffffffff
    23  	exp_msk1L        = 0x10000000000000
    24  	exp_shift1       = 20
    25  	exp_mask         = 0x7ff00000
    26  	bias             = 1023
    27  	p                = 53
    28  	bndry_mask       = 0xfffff
    29  	log2P            = 1
    30  )
    31  
    32  func lo0bits(x uint32) (k int) {
    33  
    34  	if (x & 7) != 0 {
    35  		if (x & 1) != 0 {
    36  			return 0
    37  		}
    38  		if (x & 2) != 0 {
    39  			return 1
    40  		}
    41  		return 2
    42  	}
    43  	if (x & 0xffff) == 0 {
    44  		k = 16
    45  		x >>= 16
    46  	}
    47  	if (x & 0xff) == 0 {
    48  		k += 8
    49  		x >>= 8
    50  	}
    51  	if (x & 0xf) == 0 {
    52  		k += 4
    53  		x >>= 4
    54  	}
    55  	if (x & 0x3) == 0 {
    56  		k += 2
    57  		x >>= 2
    58  	}
    59  	if (x & 1) == 0 {
    60  		k++
    61  		x >>= 1
    62  		if (x & 1) == 0 {
    63  			return 32
    64  		}
    65  	}
    66  	return
    67  }
    68  
    69  func hi0bits(x uint32) (k int) {
    70  
    71  	if (x & 0xffff0000) == 0 {
    72  		k = 16
    73  		x <<= 16
    74  	}
    75  	if (x & 0xff000000) == 0 {
    76  		k += 8
    77  		x <<= 8
    78  	}
    79  	if (x & 0xf0000000) == 0 {
    80  		k += 4
    81  		x <<= 4
    82  	}
    83  	if (x & 0xc0000000) == 0 {
    84  		k += 2
    85  		x <<= 2
    86  	}
    87  	if (x & 0x80000000) == 0 {
    88  		k++
    89  		if (x & 0x40000000) == 0 {
    90  			return 32
    91  		}
    92  	}
    93  	return
    94  }
    95  
    96  func stuffBits(bits []byte, offset int, val uint32) {
    97  	bits[offset] = byte(val >> 24)
    98  	bits[offset+1] = byte(val >> 16)
    99  	bits[offset+2] = byte(val >> 8)
   100  	bits[offset+3] = byte(val)
   101  }
   102  
   103  func d2b(d float64, b []byte) (e, bits int, dblBits []byte) {
   104  	dBits := math.Float64bits(d)
   105  	d0 := uint32(dBits >> 32)
   106  	d1 := uint32(dBits)
   107  
   108  	z := d0 & frac_mask
   109  	d0 &= 0x7fffffff /* clear sign bit, which we ignore */
   110  
   111  	var de, k, i int
   112  	if de = int(d0 >> exp_shift); de != 0 {
   113  		z |= exp_msk1
   114  	}
   115  
   116  	y := d1
   117  	if y != 0 {
   118  		dblBits = b[:8]
   119  		k = lo0bits(y)
   120  		y >>= k
   121  		if k != 0 {
   122  			stuffBits(dblBits, 4, y|z<<(32-k))
   123  			z >>= k
   124  		} else {
   125  			stuffBits(dblBits, 4, y)
   126  		}
   127  		stuffBits(dblBits, 0, z)
   128  		if z != 0 {
   129  			i = 2
   130  		} else {
   131  			i = 1
   132  		}
   133  	} else {
   134  		dblBits = b[:4]
   135  		k = lo0bits(z)
   136  		z >>= k
   137  		stuffBits(dblBits, 0, z)
   138  		k += 32
   139  		i = 1
   140  	}
   141  
   142  	if de != 0 {
   143  		e = de - bias - (p - 1) + k
   144  		bits = p - k
   145  	} else {
   146  		e = de - bias - (p - 1) + 1 + k
   147  		bits = 32*i - hi0bits(z)
   148  	}
   149  	return
   150  }