gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

helper_internal.go (3805B)


      1 // Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved.
      2 // Use of this source code is governed by a MIT license found in the LICENSE file.
      3 
      4 package codec
      5 
      6 // maxArrayLen is the size of uint, which determines
      7 // the maximum length of any array.
      8 const maxArrayLen = 1<<((32<<(^uint(0)>>63))-1) - 1
      9 
     10 // All non-std package dependencies live in this file,
     11 // so porting to different environment is easy (just update functions).
     12 
     13 func pruneSignExt(v []byte, pos bool) (n int) {
     14 	if len(v) < 2 {
     15 	} else if pos && v[0] == 0 {
     16 		for ; v[n] == 0 && n+1 < len(v) && (v[n+1]&(1<<7) == 0); n++ {
     17 		}
     18 	} else if !pos && v[0] == 0xff {
     19 		for ; v[n] == 0xff && n+1 < len(v) && (v[n+1]&(1<<7) != 0); n++ {
     20 		}
     21 	}
     22 	return
     23 }
     24 
     25 func halfFloatToFloatBits(h uint16) (f uint32) {
     26 	// retrofitted from:
     27 	// - OGRE (Object-Oriented Graphics Rendering Engine)
     28 	//   function: halfToFloatI https://www.ogre3d.org/docs/api/1.9/_ogre_bitwise_8h_source.html
     29 
     30 	s := uint32(h >> 15)
     31 	m := uint32(h & 0x03ff)
     32 	e := int32((h >> 10) & 0x1f)
     33 
     34 	if e == 0 {
     35 		if m == 0 { // plus or minus 0
     36 			return s << 31
     37 		}
     38 		// Denormalized number -- renormalize it
     39 		for (m & 0x0400) == 0 {
     40 			m <<= 1
     41 			e -= 1
     42 		}
     43 		e += 1
     44 		m &= ^uint32(0x0400)
     45 	} else if e == 31 {
     46 		if m == 0 { // Inf
     47 			return (s << 31) | 0x7f800000
     48 		}
     49 		return (s << 31) | 0x7f800000 | (m << 13) // NaN
     50 	}
     51 	e = e + (127 - 15)
     52 	m = m << 13
     53 	return (s << 31) | (uint32(e) << 23) | m
     54 }
     55 
     56 func floatToHalfFloatBits(i uint32) (h uint16) {
     57 	// retrofitted from:
     58 	// - OGRE (Object-Oriented Graphics Rendering Engine)
     59 	//   function: halfToFloatI https://www.ogre3d.org/docs/api/1.9/_ogre_bitwise_8h_source.html
     60 	// - http://www.java2s.com/example/java-utility-method/float-to/floattohalf-float-f-fae00.html
     61 	s := (i >> 16) & 0x8000
     62 	e := int32(((i >> 23) & 0xff) - (127 - 15))
     63 	m := i & 0x7fffff
     64 
     65 	var h32 uint32
     66 
     67 	if e <= 0 {
     68 		if e < -10 { // zero
     69 			h32 = s // track -0 vs +0
     70 		} else {
     71 			m = (m | 0x800000) >> uint32(1-e)
     72 			h32 = s | (m >> 13)
     73 		}
     74 	} else if e == 0xff-(127-15) {
     75 		if m == 0 { // Inf
     76 			h32 = s | 0x7c00
     77 		} else { // NAN
     78 			m >>= 13
     79 			var me uint32
     80 			if m == 0 {
     81 				me = 1
     82 			}
     83 			h32 = s | 0x7c00 | m | me
     84 		}
     85 	} else {
     86 		if e > 30 { // Overflow
     87 			h32 = s | 0x7c00
     88 		} else {
     89 			h32 = s | (uint32(e) << 10) | (m >> 13)
     90 		}
     91 	}
     92 	h = uint16(h32)
     93 	return
     94 }
     95 
     96 // growCap will return a new capacity for a slice, given the following:
     97 //   - oldCap: current capacity
     98 //   - unit: in-memory size of an element
     99 //   - num: number of elements to add
    100 func growCap(oldCap, unit, num uint) (newCap uint) {
    101 	// appendslice logic (if cap < 1024, *2, else *1.25):
    102 	//   leads to many copy calls, especially when copying bytes.
    103 	//   bytes.Buffer model (2*cap + n): much better for bytes.
    104 	// smarter way is to take the byte-size of the appended element(type) into account
    105 
    106 	// maintain 1 thresholds:
    107 	// t1: if cap <= t1, newcap = 2x
    108 	//     else          newcap = 1.5x
    109 	//
    110 	// t1 is always >= 1024.
    111 	// This means that, if unit size >= 16, then always do 2x or 1.5x (ie t1, t2, t3 are all same)
    112 	//
    113 	// With this, appending for bytes increase by:
    114 	//    100% up to 4K
    115 	//     50% beyond that
    116 
    117 	// unit can be 0 e.g. for struct{}{}; handle that appropriately
    118 	maxCap := num + (oldCap * 3 / 2)
    119 	if unit == 0 || maxCap > maxArrayLen || maxCap < oldCap { // handle wraparound, etc
    120 		return maxArrayLen
    121 	}
    122 
    123 	var t1 uint = 1024 // default thresholds for large values
    124 	if unit <= 4 {
    125 		t1 = 8 * 1024
    126 	} else if unit <= 16 {
    127 		t1 = 2 * 1024
    128 	}
    129 
    130 	newCap = 2 + num
    131 	if oldCap > 0 {
    132 		if oldCap <= t1 { // [0,t1]
    133 			newCap = num + (oldCap * 2)
    134 		} else { // (t1,infinity]
    135 			newCap = maxCap
    136 		}
    137 	}
    138 
    139 	// ensure newCap takes multiples of a cache line (size is a multiple of 64)
    140 	t1 = newCap * unit
    141 	if t2 := t1 % 64; t2 != 0 {
    142 		t1 += 64 - t2
    143 		newCap = t1 / unit
    144 	}
    145 
    146 	return
    147 }