1112158Sdas/* @(#)s_frexp.c 5.1 93/09/24 */
2112158Sdas/*
3112158Sdas * ====================================================
4112158Sdas * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5112158Sdas *
6112158Sdas * Developed at SunPro, a Sun Microsystems, Inc. business.
7112158Sdas * Permission to use, copy, modify, and distribute this
8112158Sdas * software is freely granted, provided that this notice
9112158Sdas * is preserved.
10112158Sdas * ====================================================
11112158Sdas */
12112158Sdas
13112158Sdas#include <sys/cdefs.h>
14112158Sdas#if defined(LIBM_SCCS) && !defined(lint)
15112158Sdas__RCSID("$NetBSD: s_frexp.c,v 1.14 2020/01/30 20:31:50 joerg Exp $");
16112158Sdas#endif
17112158Sdas
18112158Sdas/*
19112158Sdas * for non-zero x
20112158Sdas *	x = frexp(arg,&exp);
21112158Sdas * return a double fp quantity x such that 0.5 <= |x| <1.0
22112158Sdas * and the corresponding binary exponent "exp". That is
23112158Sdas *	arg = x*2^exp.
24112158Sdas * If arg is inf, 0.0, or NaN, then frexp(arg,&exp) returns arg
25112158Sdas * with *exp=0.
26112158Sdas */
27112158Sdas
28112158Sdas#include "math.h"
29165743Sdas#include "math_private.h"
30165743Sdas
31112158Sdas#ifndef __HAVE_LONG_DOUBLE
32112158Sdas__strong_alias(frexpl, frexp)
33112158Sdas#endif
34112158Sdas
35112158Sdasstatic const double
36112158Sdastwo54 =  1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */
37112158Sdas
38112158Sdasdouble
39112158Sdasfrexp(double x, int *eptr)
40112158Sdas{
41112158Sdas	int32_t hx, ix, lx;
42112158Sdas	EXTRACT_WORDS(hx,lx,x);
43112158Sdas	ix = 0x7fffffff&hx;
44112158Sdas	*eptr = 0;
45112158Sdas	if(ix>=0x7ff00000||((ix|lx)==0)) return x;	/* 0,inf,nan */
46112158Sdas	if (ix<0x00100000) {		/* subnormal */
47112158Sdas	    x *= two54;
48112158Sdas	    GET_HIGH_WORD(hx,x);
49112158Sdas	    ix = hx&0x7fffffff;
50112158Sdas	    *eptr = -54;
51112158Sdas	}
52112158Sdas	*eptr += ((uint32_t)ix>>20)-1022;
53112158Sdas	hx = (hx&0x800fffff)|0x3fe00000;
54112158Sdas	SET_HIGH_WORD(x,hx);
55112158Sdas	return x;
56112158Sdas}
57112158Sdas