package fastimportconst ( diyFpKSignificandSize = 64 kSignificandSize = 53 kUint64MSB uint64 = 1 << 63 kSignificandMask = 0x000FFFFFFFFFFFFF kHiddenBit = 0x0010000000000000 kExponentMask = 0x7FF0000000000000 kPhysicalSignificandSize = 52// Excludes the hidden bit. kExponentBias = 0x3FF + kPhysicalSignificandSize kDenormalExponent = -kExponentBias + 1)type double float64type diyfp struct { f uint64 e int}// f =- o.// The exponents of both numbers must be the same and the significand of this// must be bigger than the significand of other.// The result will not be normalized.func ( *diyfp) ( diyfp) {_DCHECK(.e == .e)_DCHECK(.f >= .f) .f -= .f}// Returns f - o// The exponents of both numbers must be the same and this must be bigger// than other. The result will not be normalized.func ( diyfp) ( diyfp) diyfp { := .subtract()return}// f *= ofunc ( *diyfp) ( diyfp) {// Simply "emulates" a 128 bit multiplication. // However: the resulting number only contains 64 bits. The least // significant 64 bits are only used for rounding the most significant 64 // bits.constuint64 = 0xFFFFFFFF := .f >> 32 := .f & := .f >> 32 := .f & := * := * := * := * := ( >> 32) + ( & ) + ( & )// By adding 1U << 31 to tmp we round the final result. // Halfway cases will be round up. += 1 << 31 := + ( >> 32) + ( >> 32) + ( >> 32) .e += .e + 64 .f = }// Returns f * ofunc ( diyfp) ( diyfp) diyfp { := .mul()return}func ( *diyfp) () { , := .f, .e// This method is mainly called for normalizing boundaries. In general // boundaries need to be shifted by 10 bits. We thus optimize for this case.constuint64 = 0x3FF << 54for & == 0 { <<= 10 -= 10 }for &kUint64MSB == 0 { <<= 1 -- } .f, .e = , }func normalizeDiyfp( diyfp) diyfp { := ._normalize()return}// f must be strictly greater than 0.func ( double) () diyfp { , := .sigExp()// The current float could be a denormal.for ( & kHiddenBit) == 0 { <<= 1 -- }// Do the final shifts in one go. <<= diyFpKSignificandSize - kSignificandSize -= diyFpKSignificandSize - kSignificandSizereturndiyfp{, }}// Returns the two boundaries of this.// The bigger boundary (m_plus) is normalized. The lower boundary has the same// exponent as m_plus.// Precondition: the value encoded by this Double must be greater than 0.func ( double) () (, diyfp) { := .toDiyFp() := .f == kHiddenBit = normalizeDiyfp(diyfp{f: (.f << 1) + 1, e: .e - 1})if && .e != kDenormalExponent {// The boundary is closer. Think of v = 1000e10 and v- = 9999e9. // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but // at a distance of 1e8. // The only exception is for the smallest normal: the largest denormal is // at the same distance as its successor. // Note: denormals have the same exponent as the smallest normals. = diyfp{f: (.f << 2) - 1, e: .e - 2} } else { = diyfp{f: (.f << 1) - 1, e: .e - 1} } .f <<= .e - .e .e = .ereturn}func ( double) () diyfp { , := .sigExp()returndiyfp{f: , e: }}func ( double) () ( uint64, int) { := math.Float64bits(float64()) = & kSignificandMaskif &kExponentMask != 0 { // not denormal += kHiddenBit = int((&kExponentMask)>>kPhysicalSignificandSize) - kExponentBias } else { = kDenormalExponent }return}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.