12116Sjkh/* e_hypotf.c -- float version of e_hypot.c.
22116Sjkh * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
32116Sjkh */
42116Sjkh
52116Sjkh/*
62116Sjkh * ====================================================
72116Sjkh * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
82116Sjkh *
92116Sjkh * Developed at SunPro, a Sun Microsystems, Inc. business.
102116Sjkh * Permission to use, copy, modify, and distribute this
118870Srgrimes * software is freely granted, provided that this notice
122116Sjkh * is preserved.
132116Sjkh * ====================================================
142116Sjkh */
152116Sjkh
16176277Sbde#include <sys/cdefs.h>
17176277Sbde__FBSDID("$FreeBSD$");
182116Sjkh
192116Sjkh#include "math.h"
202116Sjkh#include "math_private.h"
212116Sjkh
2297413Salfredfloat
2397413Salfred__ieee754_hypotf(float x, float y)
242116Sjkh{
25226380Sdas	float a,b,t1,t2,y1,y2,w;
262116Sjkh	int32_t j,k,ha,hb;
272116Sjkh
282116Sjkh	GET_FLOAT_WORD(ha,x);
292116Sjkh	ha &= 0x7fffffff;
302116Sjkh	GET_FLOAT_WORD(hb,y);
312116Sjkh	hb &= 0x7fffffff;
322116Sjkh	if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
33177751Sbde	a = fabsf(a);
34177751Sbde	b = fabsf(b);
352116Sjkh	if((ha-hb)>0xf000000) {return a+b;} /* x/y > 2**30 */
362116Sjkh	k=0;
372116Sjkh	if(ha > 0x58800000) {	/* a>2**50 */
382116Sjkh	   if(ha >= 0x7f800000) {	/* Inf or NaN */
39176277Sbde	       /* Use original arg order iff result is NaN; quieten sNaNs. */
40177749Sbde	       w = fabsf(x+0.0F)-fabsf(y+0.0F);
412116Sjkh	       if(ha == 0x7f800000) w = a;
422116Sjkh	       if(hb == 0x7f800000) w = b;
432116Sjkh	       return w;
442116Sjkh	   }
4523397Sbde	   /* scale a and b by 2**-68 */
4623397Sbde	   ha -= 0x22000000; hb -= 0x22000000;	k += 68;
472116Sjkh	   SET_FLOAT_WORD(a,ha);
482116Sjkh	   SET_FLOAT_WORD(b,hb);
492116Sjkh	}
502116Sjkh	if(hb < 0x26800000) {	/* b < 2**-50 */
518870Srgrimes	    if(hb <= 0x007fffff) {	/* subnormal b or 0 */
522116Sjkh	        if(hb==0) return a;
5323397Sbde		SET_FLOAT_WORD(t1,0x7e800000);	/* t1=2^126 */
542116Sjkh		b *= t1;
552116Sjkh		a *= t1;
562116Sjkh		k -= 126;
5723397Sbde	    } else {		/* scale a and b by 2^68 */
5823397Sbde	        ha += 0x22000000; 	/* a *= 2^68 */
5923397Sbde		hb += 0x22000000;	/* b *= 2^68 */
6023397Sbde		k -= 68;
612116Sjkh		SET_FLOAT_WORD(a,ha);
622116Sjkh		SET_FLOAT_WORD(b,hb);
632116Sjkh	    }
642116Sjkh	}
652116Sjkh    /* medium size a and b */
662116Sjkh	w = a-b;
672116Sjkh	if (w>b) {
682116Sjkh	    SET_FLOAT_WORD(t1,ha&0xfffff000);
692116Sjkh	    t2 = a-t1;
7023579Sbde	    w  = __ieee754_sqrtf(t1*t1-(b*(-b)-t2*(a+t1)));
712116Sjkh	} else {
722116Sjkh	    a  = a+a;
732116Sjkh	    SET_FLOAT_WORD(y1,hb&0xfffff000);
742116Sjkh	    y2 = b - y1;
75177746Sbde	    SET_FLOAT_WORD(t1,(ha+0x00800000)&0xfffff000);
762116Sjkh	    t2 = a - t1;
7723579Sbde	    w  = __ieee754_sqrtf(t1*y1-(w*(-w)-(t1*y2+t2*b)));
782116Sjkh	}
792116Sjkh	if(k!=0) {
802116Sjkh	    SET_FLOAT_WORD(t1,0x3f800000+(k<<23));
812116Sjkh	    return t1*w;
822116Sjkh	} else return w;
832116Sjkh}
84