_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