File: float16.go

package info (click to toggle)
golang-github-aws-smithy-go 1.23.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,520 kB
  • sloc: java: 21,276; sh: 131; makefile: 90; xml: 9
file content (45 lines) | stat: -rw-r--r-- 1,496 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package cbor

func float16to32(f uint16) uint32 {
	sign, exp, mant := splitf16(f)
	if exp == 0x1f {
		return sign | 0xff<<23 | mant // infinity/NaN
	}

	if exp == 0 { // subnormal
		if mant == 0 {
			return sign
		}
		return normalize(sign, mant)
	}

	return sign | (exp+127-15)<<23 | mant // rebias exp by the difference between the two
}

func splitf16(f uint16) (sign, exp, mantissa uint32) {
	const smask = 0x1 << 15  // put sign in float32 position
	const emask = 0x1f << 10 // pull exponent as a number (for bias shift)
	const mmask = 0x3ff      // put mantissa in float32 position

	return uint32(f&smask) << 16, uint32(f&emask) >> 10, uint32(f&mmask) << 13
}

// moves a float16 normal into normal float32 space
// to do this we must re-express the float16 mantissa in terms of a normal
// float32 where the hidden bit is 1, e.g.
//
// f16: 0    00000              0001010000 = 0.000101 * 2^(-14), which is equal to
// f32: 0 01101101 01000000000000000000000 =     1.01 * 2^(-18)
//
// this is achieved by shifting the mantissa to the right until the leading bit
// that == 1 reaches position 24, then the number of positions shifted over is
// equal to the offset from the subnormal exponent
func normalize(sign, mant uint32) uint32 {
	exp := uint32(-14 + 127) // f16 subnormal exp, with f32 bias
	for mant&0x800000 == 0 { // repeat until bit 24 ("hidden" mantissa) is 1
		mant <<= 1
		exp-- // tracking the offset
	}
	mant &= 0x7fffff // remask to 23bit
	return sign | exp<<23 | mant
}