_divkc3.c revision 1.1.1.4
175584Sru/* Copyright (C) 1989-2017 Free Software Foundation, Inc.
275584Sru
375584SruThis file is part of GCC.
475584Sru
575584SruGCC is free software; you can redistribute it and/or modify it under
675584Sruthe terms of the GNU General Public License as published by the Free
775584SruSoftware Foundation; either version 3, or (at your option) any later
875584Sruversion.
975584Sru
1075584SruGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1175584SruWARRANTY; without even the implied warranty of MERCHANTABILITY or
1275584SruFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1375584Srufor more details.
1475584Sru
1575584SruUnder Section 7 of GPL version 3, you are granted additional
1675584Srupermissions described in the GCC Runtime Library Exception, version
1775584Sru3.1, as published by the Free Software Foundation.
1875584Sru
1975584SruYou should have received a copy of the GNU General Public License and
2075584Srua copy of the GCC Runtime Library Exception along with this program;
2175584Srusee the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2275584Sru<http://www.gnu.org/licenses/>.  */
2375584Sru
2475584Sru/* This is a temporary specialization of code from libgcc/libgcc2.c.  */
2575584Sru
2675584Srutypedef float KFtype __attribute__ ((mode (KF)));
2775584Srutypedef __complex float KCtype __attribute__ ((mode (KC)));
2875584Sru
2975584Sru#define COPYSIGN(x,y) __builtin_copysignq (x, y)
3075584Sru#define INFINITY __builtin_infq ()
3175584Sru#define FABS __builtin_fabsq
3275584Sru#define isnan __builtin_isnan
3375584Sru#define isinf __builtin_isinf
3475584Sru#define isfinite __builtin_isfinite
3575584Sru
3675584SruKCtype
3775584Sru__divkc3 (KFtype a, KFtype b, KFtype c, KFtype d)
3875584Sru{
3975584Sru  KFtype denom, ratio, x, y;
4075584Sru  KCtype res;
4175584Sru
4275584Sru  /* ??? We can get better behavior from logarithmic scaling instead of
4375584Sru     the division.  But that would mean starting to link libgcc against
4475584Sru     libm.  We could implement something akin to ldexp/frexp as gcc builtins
4575584Sru     fairly easily...  */
4675584Sru  if (FABS (c) < FABS (d))
4775584Sru    {
4875584Sru      ratio = c / d;
4975584Sru      denom = (c * ratio) + d;
5075584Sru      x = ((a * ratio) + b) / denom;
5175584Sru      y = ((b * ratio) - a) / denom;
5275584Sru    }
5375584Sru  else
5475584Sru    {
5575584Sru      ratio = d / c;
5675584Sru      denom = (d * ratio) + c;
5775584Sru      x = ((b * ratio) + a) / denom;
5875584Sru      y = (b - (a * ratio)) / denom;
5975584Sru    }
6075584Sru
6175584Sru  /* Recover infinities and zeros that computed as NaN+iNaN; the only cases
6275584Sru     are nonzero/zero, infinite/finite, and finite/infinite.  */
6375584Sru  if (isnan (x) && isnan (y))
6475584Sru    {
6575584Sru      if (c == 0.0 && d == 0.0 && (!isnan (a) || !isnan (b)))
6675584Sru	{
6775584Sru	  x = COPYSIGN (INFINITY, c) * a;
6875584Sru	  y = COPYSIGN (INFINITY, c) * b;
6975584Sru	}
7075584Sru      else if ((isinf (a) || isinf (b)) && isfinite (c) && isfinite (d))
7175584Sru	{
7275584Sru	  a = COPYSIGN (isinf (a) ? 1 : 0, a);
7375584Sru	  b = COPYSIGN (isinf (b) ? 1 : 0, b);
7475584Sru	  x = INFINITY * (a * c + b * d);
7575584Sru	  y = INFINITY * (b * c - a * d);
7675584Sru	}
7775584Sru      else if ((isinf (c) || isinf (d)) && isfinite (a) && isfinite (b))
7875584Sru	{
7975584Sru	  c = COPYSIGN (isinf (c) ? 1 : 0, c);
8075584Sru	  d = COPYSIGN (isinf (d) ? 1 : 0, d);
8175584Sru	  x = 0.0 * (a * c + b * d);
8275584Sru	  y = 0.0 * (b * c - a * d);
8375584Sru	}
8475584Sru    }
8575584Sru
8675584Sru  __real__ res = x;
8775584Sru  __imag__ res = y;
8875584Sru  return res;
8975584Sru}
9075584Sru