blob: 2d4f7a3c61642ced6d4fef14222f8ff4d79a19ca [file] [log] [blame]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001/*
Elliott Hughes99ef4472022-01-12 17:51:20 -08002 * Copyright (c) 2005-2020 Rich Felker, et al.
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08003 *
Elliott Hughes99ef4472022-01-12 17:51:20 -08004 * SPDX-License-Identifier: MIT
5 *
6 * Please see https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
7 * for all contributors to musl.
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08008 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08009#include <float.h>
Elliott Hughes99ef4472022-01-12 17:51:20 -080010#include <math.h>
11#include <stdint.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080012
Elliott Hughes99ef4472022-01-12 17:51:20 -080013double scalbn(double x, int n)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080014{
Elliott Hughes99ef4472022-01-12 17:51:20 -080015 union {double f; uint64_t i;} u;
16 double_t y = x;
17
18 if (n > 1023) {
19 y *= 0x1p1023;
20 n -= 1023;
21 if (n > 1023) {
22 y *= 0x1p1023;
23 n -= 1023;
24 if (n > 1023)
25 n = 1023;
26 }
27 } else if (n < -1022) {
28 /* make sure final n < -53 to avoid double
29 rounding in the subnormal range */
30 y *= 0x1p-1022 * 0x1p53;
31 n += 1022 - 53;
32 if (n < -1022) {
33 y *= 0x1p-1022 * 0x1p53;
34 n += 1022 - 53;
35 if (n < -1022)
36 n = -1022;
37 }
Elliott Hughes8da8ca42018-05-08 13:35:33 -070038 }
Elliott Hughes99ef4472022-01-12 17:51:20 -080039 u.i = (uint64_t)(0x3ff+n)<<52;
40 x = y * u.f;
41 return x;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080042}
43
Elliott Hughes99ef4472022-01-12 17:51:20 -080044#if (LDBL_MANT_DIG == 53) && !defined(scalbn)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080045__weak_reference(scalbn, ldexpl);
46__weak_reference(scalbn, scalbnl);
47#endif