Example #1
0
long double _Complex
_X_cplx_div_ix(long double b, long double _Complex w)
{
	long double _Complex	v;
	union {
		int		i[3];
		long double	e;
	} bb, cc, dd;
	long double	c, d, sc, sd, r;
	int		eb, ec, ed, ew, i, j;

	/*
	 * The following is equivalent to
	 *
	 *  c = creall(*w); d = cimagl(*w);
	 */
	c = ((long double *)&w)[0];
	d = ((long double *)&w)[1];

	/* extract exponents to estimate |z| and |w| */
	bb.e = b;
	eb = bb.i[2] & 0x7fff;

	cc.e = c;
	dd.e = d;
	ec = cc.i[2] & 0x7fff;
	ed = dd.i[2] & 0x7fff;
	ew = (ec > ed)? ec : ed;

	/* check for special cases */
	if (ew >= 0x7fff) { /* w is inf or nan */
		i = testinfl(c);
		j = testinfl(d);
		if (i | j) { /* w is infinite */
			c = ((cc.i[2] << 16) < 0)? -0.0f : 0.0f;
			d = ((dd.i[2] << 16) < 0)? -0.0f : 0.0f;
		} else /* w is nan */
			b += c + d;
		((long double *)&v)[0] = b * d;
		((long double *)&v)[1] = b * c;
		return (v);
	}

	if (ew == 0 && (cc.i[1] | cc.i[0] | dd.i[1] | dd.i[0]) == 0) {
		/* w is zero; multiply b by 1/Re(w) - I * Im(w) */
		c = 1.0f / c;
		j = testinfl(b);
		if (j) { /* b is infinite */
			b = j;
		}
		((long double *)&v)[0] = (b == 0.0f)? b * c : b * d;
		((long double *)&v)[1] = b * c;
		return (v);
	}

	if (eb >= 0x7fff) { /* a is inf or nan */
		((long double *)&v)[0] = b * d;
		((long double *)&v)[1] = b * c;
		return (v);
	}

	/*
	 * Compute the real and imaginary parts of the quotient,
	 * scaling to avoid overflow or underflow.
	 */
	ew = (ew - 0x3800) >> 12;
	sc = c * scl[ew + 4].e;
	sd = d * scl[ew + 4].e;
	r = sc * sc + sd * sd;

	eb = (eb - 0x3800) >> 12;
	b = (b * scl[eb + 4].e) / r;
	eb -= (ew + ew);

	ec = (ec - 0x3800) >> 12;
	c = (c * scl[ec + 4].e) * b;
	ec += eb;

	ed = (ed - 0x3800) >> 12;
	d = (d * scl[ed + 4].e) * b;
	ed += eb;

	/* compensate for scaling */
	sc = scl[3].e; /* 2^4080 */
	if (ec < 0) {
		ec = -ec;
		sc = scl[5].e; /* 2^-4080 */
	}
	while (ec--)
		c *= sc;

	sd = scl[3].e;
	if (ed < 0) {
		ed = -ed;
		sd = scl[5].e;
	}
	while (ed--)
		d *= sd;

	((long double *)&v)[0] = d;
	((long double *)&v)[1] = c;
	return (v);
}
Example #2
0
long double _Complex
_Q_cplx_div_rx(const long double *pa, const long double _Complex *w)
{
	long double _Complex	v;
#else
void
_Q_cplx_div_rx(long double _Complex *v, const long double *pa,
	const long double _Complex *w)
{
#endif
	union {
		int		i[4];
		long double	q;
	} aa, cc, dd;
	long double	a, c, d, sc, sd, r;
	int		ha, hc, hd, hw, i, j;

	a = *pa;

	/*
	 * The following is equivalent to
	 *
	 *  c = creall(*w); d = cimagl(*w);
	 */
	c = ((long double *)w)[0];
	d = ((long double *)w)[1];

	/* extract high-order words to estimate |a| and |w| */
	aa.q = a;
	ha = aa.i[0] & ~0x80000000;

	cc.q = c;
	dd.q = d;
	hc = cc.i[0] & ~0x80000000;
	hd = dd.i[0] & ~0x80000000;
	hw = (hc > hd)? hc : hd;

	/* check for special cases */
	if (hw >= 0x7fff0000) { /* w is inf or nan */
		i = testinfl(c);
		j = testinfl(d);
		if (i | j) { /* w is infinite */
			c = (cc.i[0] < 0)? -0.0l : 0.0l;
			d = (dd.i[0] < 0)? -0.0l : 0.0l;
		} else /* w is nan */
			a += c + d;
		c *= a;
		d *= -a;
		goto done;
	}

	if (hw == 0 && (cc.i[1] | cc.i[2] | cc.i[3] |
		dd.i[1] | dd.i[2] | dd.i[3]) == 0) {
		/* w is zero; multiply a by 1/Re(w) - I * Im(w) */
		c = 1.0l / c;
		i = testinfl(a);
		if (i) { /* a is infinite */
			a = i;
		}
		c *= a;
		d = (a == 0.0l)? c : -a * d;
		goto done;
	}

	if (ha >= 0x7fff0000) { /* a is inf or nan */
		c *= a;
		d *= -a;
		goto done;
	}

	/*
	 * Compute the real and imaginary parts of the quotient,
	 * scaling to avoid overflow or underflow.
	 */
	hw = (hw - 0x3fff0000) >> 16;
	sc = c;
	sd = d;
	_Q_scl(&sc, -hw);
	_Q_scl(&sd, -hw);
	r = sc * sc + sd * sd;

	ha = (ha - 0x3fff0000) >> 16;
	_Q_scl(&a, -ha);
	a /= r;
	ha -= (hw + hw);

	hc = (hc - 0x3fff0000) >> 16;
	_Q_scl(&c, -hc);
	c *= a;
	hc += ha;

	hd = (hd - 0x3fff0000) >> 16;
	_Q_scl(&d, -hd);
	d *= -a;
	hd += ha;

	/* compensate for scaling */
	_Q_scle(&c, hc);
	_Q_scle(&d, hd);

done:
#ifdef __sparcv9
	((long double *)&v)[0] = c;
	((long double *)&v)[1] = d;
	return (v);
#else
	((long double *)v)[0] = c;
	((long double *)v)[1] = d;
#endif
}