1 /***************************************************************************
2 * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *
3 * Martin Renou                                                             *
4 * Copyright (c) QuantStack                                                 *
5 * Copyright (c) Serge Guelton                                              *
6 *                                                                          *
7 * Distributed under the terms of the BSD 3-Clause License.                 *
8 *                                                                          *
9 * The full license is in the file LICENSE, distributed with this software. *
10 ****************************************************************************/
11 
12 #ifndef XSIMD_GENERIC_COMPLEX_HPP
13 #define XSIMD_GENERIC_COMPLEX_HPP
14 
15 #include <complex>
16 
17 #include "./xsimd_generic_details.hpp"
18 
19 namespace xsimd {
20 
21   namespace kernel {
22 
23     using namespace types;
24 
25     // real
26     template <class A, class T>
real(batch<T,A> const & self,requires_arch<generic>)27     batch<T, A> real(batch<T, A> const& self, requires_arch<generic>) {
28       return self;
29     }
30 
31     template <class A, class T>
real(batch<std::complex<T>,A> const & self,requires_arch<generic>)32     batch<T, A> real(batch<std::complex<T>, A> const& self, requires_arch<generic>) {
33       return self.real();
34     }
35 
36     // imag
37     template <class A, class T>
imag(batch<T,A> const &,requires_arch<generic>)38     batch<T, A> imag(batch<T, A> const& /*self*/, requires_arch<generic>) {
39       return batch<T, A>(T(0));
40     }
41 
42     template <class A, class T>
imag(batch<std::complex<T>,A> const & self,requires_arch<generic>)43     batch<T, A> imag(batch<std::complex<T>, A> const& self, requires_arch<generic>) {
44       return self.imag();
45     }
46 
47     // arg
48     template<class A, class T>
arg(batch<T,A> const & self,requires_arch<generic>)49     real_batch_type_t<batch<T, A>> arg(batch<T, A> const& self, requires_arch<generic>) {
50       return atan2(imag(self), real(self));
51     }
52 
53     // conj
54     template<class A, class T>
conj(batch<T,A> const & self,requires_arch<generic>)55     complex_batch_type_t<batch<T, A>> conj(batch<T, A> const& self, requires_arch<generic>) {
56       return {real(self), - imag(self)};
57     }
58 
59     // norm
60     template<class A, class T>
norm(batch<T,A> const & self,requires_arch<generic>)61     real_batch_type_t<batch<T, A>> norm(batch<T, A> const& self, requires_arch<generic>) {
62       return {fma(real(self), real(self), imag(self) * imag(self))};
63     }
64 
65     // proj
66     template<class A, class T>
proj(batch<T,A> const & self,requires_arch<generic>)67     complex_batch_type_t<batch<T, A>> proj(batch<T, A> const& self, requires_arch<generic>) {
68       using batch_type = complex_batch_type_t<batch<T, A>>;
69       using real_batch = typename batch_type::real_batch;
70       using real_value_type = typename real_batch::value_type;
71       auto cond = xsimd::isinf(real(self)) || xsimd::isinf(imag(self));
72       return select(cond,
73                     batch_type(constants::infinity<real_batch>(),
74                                copysign(real_batch(real_value_type(0)), imag(self))),
75                     batch_type(self));
76     }
77 
78     template <class A, class T>
isnan(batch<std::complex<T>,A> const & self,requires_arch<generic>)79     batch_bool<T, A> isnan(batch<std::complex<T>, A> const& self, requires_arch<generic>) {
80       return batch_bool<T, A>(isnan(self.real()) || isnan(self.imag()));
81     }
82   }
83 }
84 
85 #endif
86 
87