1// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package math
6
7// Ldexp is the inverse of Frexp.
8// It returns frac × 2**exp.
9//
10// Special cases are:
11//	Ldexp(±0, exp) = ±0
12//	Ldexp(±Inf, exp) = ±Inf
13//	Ldexp(NaN, exp) = NaN
14
15//extern ldexp
16func libc_ldexp(float64, int) float64
17
18func Ldexp(frac float64, exp int) float64 {
19	r := libc_ldexp(frac, exp)
20
21	// Work around a bug in the implementation of ldexp on Solaris
22	// 9.  If multiplying a negative number by 2 raised to a
23	// negative exponent underflows, we want to return negative
24	// zero, but the Solaris 9 implementation returns positive
25	// zero.  This workaround can be removed when and if we no
26	// longer care about Solaris 9.
27	if r == 0 && frac < 0 && exp < 0 {
28		r = Copysign(0, frac)
29	}
30	return r
31}
32
33func ldexp(frac float64, exp int) float64 {
34	// special cases
35	switch {
36	case frac == 0:
37		return frac // correctly return -0
38	case IsInf(frac, 0) || IsNaN(frac):
39		return frac
40	}
41	frac, e := normalize(frac)
42	exp += e
43	x := Float64bits(frac)
44	exp += int(x>>shift)&mask - bias
45	if exp < -1074 {
46		return Copysign(0, frac) // underflow
47	}
48	if exp > 1023 { // overflow
49		if frac < 0 {
50			return Inf(-1)
51		}
52		return Inf(1)
53	}
54	var m float64 = 1
55	if exp < -1022 { // denormal
56		exp += 52
57		m = 1.0 / (1 << 52) // 2**-52
58	}
59	x &^= mask << shift
60	x |= uint64(exp+bias) << shift
61	return m * Float64frombits(x)
62}
63