LDMX Software
ap_int_special.h
1/*
2 * Copyright 2011-2019 Xilinx, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef __AP_INT_SPECIAL_H__
18#define __AP_INT_SPECIAL_H__
19
20#ifndef __AP_INT_H__
21#error "Only ap_fixed.h and ap_int.h can be included directly in user code."
22#endif
23
24#ifndef __SYNTHESIS__
25#include <cstdio>
26#include <cstdlib>
27#endif
28// FIXME AP_AUTOCC cannot handle many standard headers, so declare instead of
29// include.
30// #include <complex>
31namespace std {
32template <typename _Tp>
33class complex;
34}
35
36/*
37 TODO: Modernize the code using C++11/C++14
38 1. constexpr
39 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0415r0.html
40 2. move constructor
41*/
42
43namespace std {
44/*
45 Specialize std::complex<ap_int> to zero initialization ap_int.
46
47 To reduce the area cost, ap_int is not zero initialized, just like basic
48 types float or double. However, libstdc++ provides specialization for float,
49 double and long double, initializing image part to 0 when not specified.
50
51 This has become a difficulty in switching legacy code from these C types to
52 ap_int. To ease the tranform of legacy code, we have to implement
53 specialization of std::complex<> for our type.
54
55 As ap_int is a template, it is impossible to specialize only the methods
56 that causes default initialization of value type in std::complex<>. An
57 explicit full specialization of the template class has to be done, covering
58 all the member functions and operators of std::complex<> as specified
59 in standard 26.2.4 and 26.2.5.
60*/
61template <int _AP_W>
62class complex<ap_int<_AP_W> > {
63 public:
64 typedef ap_int<_AP_W> _Tp;
65 typedef _Tp value_type;
66
67 // 26.2.4/1
68 // Constructor without argument
69 // Default initialize, so that in dataflow, the variable is only written once.
70 complex() : _M_real(_Tp()), _M_imag(_Tp()) {}
71 // Constructor with ap_int.
72 // Zero initialize image part when not specified, so that `C(1) == C(1,0)`
73 complex(const _Tp &__r, const _Tp &__i = _Tp(0))
74 : _M_real(__r), _M_imag(__i) {}
75
76 // Constructor with another complex number
77 template <typename _Up>
78 complex(const complex<_Up> &__z) : _M_real(__z.real()), _M_imag(__z.imag()) {}
79
80#if __cplusplus >= 201103L
81 const _Tp &real() const { return _M_real; }
82 const _Tp &imag() const { return _M_imag; }
83#else
84 _Tp &real() { return _M_real; }
85 const _Tp &real() const { return _M_real; }
86 _Tp &imag() { return _M_imag; }
87 const _Tp &imag() const { return _M_imag; }
88#endif
89
90 void real(_Tp __val) { _M_real = __val; }
91
92 void imag(_Tp __val) { _M_imag = __val; }
93
94 // Assign this complex number with ap_int.
95 // Zero initialize image poarrt, so that `C c; c = 1; c == C(1,0);`
96 complex<_Tp> &operator=(const _Tp __t) {
97 _M_real = __t;
98 _M_imag = _Tp(0);
99 return *this;
100 }
101
102 // 26.2.5/1
103 // Add ap_int to this complex number.
104 complex<_Tp> &operator+=(const _Tp &__t) {
105 _M_real += __t;
106 return *this;
107 }
108
109 // 26.2.5/3
110 // Subtract ap_int from this complex number.
111 complex<_Tp> &operator-=(const _Tp &__t) {
112 _M_real -= __t;
113 return *this;
114 }
115
116 // 26.2.5/5
117 // Multiply this complex number by ap_int.
118 complex<_Tp> &operator*=(const _Tp &__t) {
119 _M_real *= __t;
120 _M_imag *= __t;
121 return *this;
122 }
123
124 // 26.2.5/7
125 // Divide this complex number by ap_int.
126 complex<_Tp> &operator/=(const _Tp &__t) {
127 _M_real /= __t;
128 _M_imag /= __t;
129 return *this;
130 }
131
132 // Assign complex number to this complex number.
133 template <typename _Up>
134 complex<_Tp> &operator=(const complex<_Up> &__z) {
135 _M_real = __z.real();
136 _M_imag = __z.imag();
137 return *this;
138 }
139
140 // 26.2.5/9
141 // Add complex number to this.
142 template <typename _Up>
143 complex<_Tp> &operator+=(const complex<_Up> &__z) {
144 _M_real += __z.real();
145 _M_imag += __z.imag();
146 return *this;
147 }
148
149 // 26.2.5/11
150 // Subtract complex number from this.
151 template <typename _Up>
152 complex<_Tp> &operator-=(const complex<_Up> &__z) {
153 _M_real -= __z.real();
154 _M_imag -= __z.imag();
155 return *this;
156 }
157
158 // 26.2.5/13
159 // Multiply this by complex number.
160 template <typename _Up>
161 complex<_Tp> &operator*=(const complex<_Up> &__z) {
162 const _Tp __r = _M_real * __z.real() - _M_imag * __z.imag();
163 _M_imag = _M_real * __z.imag() + _M_imag * __z.real();
164 _M_real = __r;
165 return *this;
166 }
167
168 // 26.2.5/15
169 // Divide this by complex number.
170 template <typename _Up>
171 complex<_Tp> &operator/=(const complex<_Up> &__z) {
172 complex<_Tp> cj(__z.real(), -__z.imag());
173 complex<_Tp> a = (*this) * cj;
174 complex<_Tp> b = cj * __z;
175 _M_real = a.real() / b.real();
176 _M_imag = a.imag() / b.real();
177 return *this;
178 }
179
180 private:
181 _Tp _M_real;
182 _Tp _M_imag;
183
184}; // class complex<ap_int<_AP_W> >
185
186/*
187 Non-member operations
188 These operations are not required by standard in 26.2.6, but libstdc++
189 defines them for
190 float, double or long double's specialization.
191*/
192// Compare complex number with ap_int.
193template <int _AP_W>
194inline bool operator==(const complex<ap_int<_AP_W> > &__x,
195 const ap_int<_AP_W> &__y) {
196 return __x.real() == __y && __x.imag() == 0;
197}
198
199// Compare ap_int with complex number.
200template <int _AP_W>
201inline bool operator==(const ap_int<_AP_W> &__x,
202 const complex<ap_int<_AP_W> > &__y) {
203 return __x == __y.real() && 0 == __y.imag();
204}
205
206// Compare complex number with ap_int.
207template <int _AP_W>
208inline bool operator!=(const complex<ap_int<_AP_W> > &__x,
209 const ap_int<_AP_W> &__y) {
210 return __x.real() != __y || __x.imag() != 0;
211}
212
213// Compare ap_int with complex number.
214template <int _AP_W>
215inline bool operator!=(const ap_int<_AP_W> &__x,
216 const complex<ap_int<_AP_W> > &__y) {
217 return __x != __y.real() || 0 != __y.imag();
218}
219
220} // namespace std
221
222#endif // ifndef __AP_INT_SPECIAL_H__
223
224// -*- cpp -*-
Sign Arbitrary Precision Type.
Definition ap_int.h:28