<T>LAPACK 0.1.1
C++ Template Linear Algebra PACKage
Loading...
Searching...
No Matches
ladiv.hpp
Go to the documentation of this file.
1
3//
4// Copyright (c) 2021-2023, University of Colorado Denver. All rights reserved.
5//
6// This file is part of <T>LAPACK.
7// <T>LAPACK is free software: you can redistribute it and/or modify it under
8// the terms of the BSD 3-Clause license. See the accompanying LICENSE file.
9
10#ifndef TLAPACK_LADIV_HH
11#define TLAPACK_LADIV_HH
12
15
16namespace tlapack {
17
34template <TLAPACK_REAL real_t,
35 enable_if_t<(
36 /* Requires: */
37 is_real<real_t>),
38 int> = 0>
39void ladiv(const real_t& a,
40 const real_t& b,
41 const real_t& c,
42 const real_t& d,
43 real_t& p,
44 real_t& q)
45{
46 // internal function sladiv2
47 auto sladiv2 = [](const real_t& a, const real_t& b, const real_t& c,
48 const real_t& d, const real_t& r, const real_t& t) {
49 const real_t zero(0);
50 if (r != zero) {
51 const real_t br = b * r;
52 if (br != zero)
53 return (a + br) * t;
54 else
55 return a * t + (b * t) * r;
56 }
57 else
58 return (a + d * (b / c)) * t;
59 };
60
61 // internal function sladiv1
62 auto sladiv1 = [sladiv2](const real_t& a, const real_t& b, const real_t& c,
63 const real_t& d, real_t& p, real_t& q) {
64 const real_t r = d / c;
65 const real_t t = real_t(1) / (c + d * r);
66 p = sladiv2(a, b, c, d, r, t);
67 q = sladiv2(b, -a, c, d, r, t);
68 };
69
70 // constant to control the lower limit of the overflow threshold
71 const real_t bs(2);
72
73 // constants for safe computation
74 const real_t one(1);
75 const real_t two(2);
76 const real_t half(0.5);
77 const real_t ov = std::numeric_limits<real_t>::max();
79 const real_t u = uroundoff<real_t>();
80 const real_t be = bs / (u * u);
81
82 // constants
83 const real_t ab = max(abs(a), abs(b));
84 const real_t cd = max(abs(c), abs(d));
85
86 // local variables
87 real_t aa = a;
88 real_t bb = b;
89 real_t cc = c;
90 real_t dd = d;
91 real_t s(1); // scaling factor
92
93 // scale values to avoid overflow
94 if (ab >= half * ov) {
95 aa *= half;
96 bb *= half;
97 s *= two;
98 }
99 if (cd >= half * ov) {
100 cc *= half;
101 dd *= half;
102 s *= half;
103 }
104 if (ab <= safeMin * bs / u) {
105 aa *= be;
106 bb *= be;
107 s /= be;
108 }
109 if (cd <= safeMin * bs / u) {
110 cc *= be;
111 dd *= be;
112 s *= be;
113 }
114
115 // compute the quotient
116 if (abs(d) <= abs(c)) {
117 sladiv1(aa, bb, cc, dd, p, q);
118 }
119 else {
120 sladiv1(bb, aa, dd, cc, p, q);
121 q = -q;
122 }
123
124 // scale the result
125 if (s != one) {
126 p *= s;
127 q *= s;
128 }
129}
130
141template <TLAPACK_COMPLEX T, enable_if_t<is_complex<T>, int> = 0>
142T ladiv(const T& x, const T& y)
143{
145 ladiv(real(x), imag(x), real(y), imag(y), zr, zi);
146
147 return T(zr, zi);
148}
149
150} // namespace tlapack
151
152#endif // TLAPACK_LADIV_HH
constexpr real_type< T > real(const T &x) noexcept
Extends std::real() to real datatypes.
Definition utils.hpp:71
constexpr real_type< T > imag(const T &x) noexcept
Extends std::imag() to real datatypes.
Definition utils.hpp:86
#define TLAPACK_REAL
Macro for tlapack::concepts::Real compatible with C++17.
Definition concepts.hpp:918
void ladiv(const real_t &a, const real_t &b, const real_t &c, const real_t &d, real_t &p, real_t &q)
Performs complex division in real arithmetic.
Definition ladiv.hpp:39
typename traits::real_type_traits< Types..., int >::type real_type
The common real type of the list of types.
Definition scalar_type_traits.hpp:113