1353358Sdim//===-- multc3.c - Implement __multc3 -------------------------------------===//
2353358Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6353358Sdim//
7353358Sdim//===----------------------------------------------------------------------===//
8353358Sdim//
9353358Sdim// This file implements __multc3 for the compiler_rt library.
10353358Sdim//
11353358Sdim//===----------------------------------------------------------------------===//
12281221Semaste
13281221Semaste#include "int_lib.h"
14281221Semaste#include "int_math.h"
15281221Semaste
16353358Sdim// Returns: the product of a + ib and c + id
17281221Semaste
18353358SdimCOMPILER_RT_ABI long double _Complex __multc3(long double a, long double b,
19353358Sdim                                              long double c, long double d) {
20353358Sdim  long double ac = a * c;
21353358Sdim  long double bd = b * d;
22353358Sdim  long double ad = a * d;
23353358Sdim  long double bc = b * c;
24353358Sdim  long double _Complex z;
25353358Sdim  __real__ z = ac - bd;
26353358Sdim  __imag__ z = ad + bc;
27353358Sdim  if (crt_isnan(__real__ z) && crt_isnan(__imag__ z)) {
28353358Sdim    int recalc = 0;
29353358Sdim    if (crt_isinf(a) || crt_isinf(b)) {
30353358Sdim      a = crt_copysignl(crt_isinf(a) ? 1 : 0, a);
31353358Sdim      b = crt_copysignl(crt_isinf(b) ? 1 : 0, b);
32353358Sdim      if (crt_isnan(c))
33353358Sdim        c = crt_copysignl(0, c);
34353358Sdim      if (crt_isnan(d))
35353358Sdim        d = crt_copysignl(0, d);
36353358Sdim      recalc = 1;
37281221Semaste    }
38353358Sdim    if (crt_isinf(c) || crt_isinf(d)) {
39353358Sdim      c = crt_copysignl(crt_isinf(c) ? 1 : 0, c);
40353358Sdim      d = crt_copysignl(crt_isinf(d) ? 1 : 0, d);
41353358Sdim      if (crt_isnan(a))
42353358Sdim        a = crt_copysignl(0, a);
43353358Sdim      if (crt_isnan(b))
44353358Sdim        b = crt_copysignl(0, b);
45353358Sdim      recalc = 1;
46353358Sdim    }
47353358Sdim    if (!recalc &&
48353358Sdim        (crt_isinf(ac) || crt_isinf(bd) || crt_isinf(ad) || crt_isinf(bc))) {
49353358Sdim      if (crt_isnan(a))
50353358Sdim        a = crt_copysignl(0, a);
51353358Sdim      if (crt_isnan(b))
52353358Sdim        b = crt_copysignl(0, b);
53353358Sdim      if (crt_isnan(c))
54353358Sdim        c = crt_copysignl(0, c);
55353358Sdim      if (crt_isnan(d))
56353358Sdim        d = crt_copysignl(0, d);
57353358Sdim      recalc = 1;
58353358Sdim    }
59353358Sdim    if (recalc) {
60353358Sdim      __real__ z = CRT_INFINITY * (a * c - b * d);
61353358Sdim      __imag__ z = CRT_INFINITY * (a * d + b * c);
62353358Sdim    }
63353358Sdim  }
64353358Sdim  return z;
65281221Semaste}
66