Imported Upstream version 3.2.2
[debian/gnuradio] / gnuradio-core / src / lib / general / gr_math.h
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2003,2005,2008 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 /*
24  * mathematical odds and ends.
25  */
26
27 #ifndef _GR_MATH_H_
28 #define _GR_MATH_H_
29
30 #include <gr_complex.h>
31
32 static inline bool
33 gr_is_power_of_2(long x)
34 {
35   return x != 0 && (x & (x-1)) == 0;
36 }
37
38 long gr_gcd (long m, long n);
39
40 // returns a non-zero value if value is "not-a-number" (NaN), and 0 otherwise
41 int gr_isnan (double value);
42
43 // returns a non-zero value if the value of x has its sign bit set.
44 //
45 // This  is  not  the  same  as `x < 0.0', because IEEE 754 floating point
46 // allows zero to be signed.  The comparison `-0.0 < 0.0'  is  false,  but
47 // `gr_signbit (-0.0)' will return a nonzero value.
48
49 int gr_signbit (double x);
50   
51 /*!
52  * \brief Fast arc tangent using table lookup and linear interpolation
53  * \ingroup misc
54  *
55  * \param y component of input vector
56  * \param x component of input vector
57  * \returns float angle angle of vector (x, y) in radians
58  *
59  * This function calculates the angle of the vector (x,y) based on a
60  * table lookup and linear interpolation. The table uses a 256 point
61  * table covering -45 to +45 degrees and uses symetry to determine the
62  * final angle value in the range of -180 to 180 degrees. Note that
63  * this function uses the small angle approximation for values close
64  * to zero. This routine calculates the arc tangent with an average
65  * error of +/- 0.045 degrees.
66  */
67 float gr_fast_atan2f(float y, float x);
68
69 static inline float gr_fast_atan2f(gr_complex z) 
70
71   return gr_fast_atan2f(z.imag(), z.real()); 
72 }
73
74 /* This bounds x by +/- clip without a branch */
75 static inline float gr_branchless_clip(float x, float clip)
76 {
77   float x1 = fabsf(x+clip);
78   float x2 = fabsf(x-clip);
79   x1 -= x2;
80   return 0.5*x1;
81 }
82
83 static inline float gr_clip(float x, float clip)
84 {
85   float y = x;
86   if(x > clip)
87     y = clip;
88   else if(x < -clip)
89     y = -clip;
90   return y;
91 }
92
93 // Slicer Functions
94 static inline unsigned int gr_binary_slicer(float x)
95 {
96   if(x >= 0)
97     return 1;
98   else
99     return 0;
100 }
101
102 static inline unsigned int gr_quad_45deg_slicer(float r, float i)
103 {
104   unsigned int ret = 0;
105   if((r >= 0) && (i >= 0))
106     ret = 0;
107   else if((r < 0) && (i >= 0))
108     ret = 1;
109   else if((r < 0) && (i < 0))
110     ret = 2;
111   else 
112     ret = 3;
113   return ret;
114 }
115
116 static inline unsigned int gr_quad_0deg_slicer(float r, float i)
117 {
118   unsigned int ret = 0;
119   if(fabsf(r) > fabsf(i)) {
120     if(r > 0)
121       ret = 0;
122     else
123       ret = 2;
124   }
125   else {
126     if(i > 0)
127       ret = 1;
128     else
129       ret = 3;
130   }
131
132   return ret;
133 }
134
135 static inline unsigned int gr_quad_45deg_slicer(gr_complex x)
136 {
137   return gr_quad_45deg_slicer(x.real(), x.imag());
138 }
139
140 static inline unsigned int gr_quad_0deg_slicer(gr_complex x)
141 {
142   return gr_quad_0deg_slicer(x.real(), x.imag());
143 }
144
145 // Branchless Slicer Functions
146 static inline unsigned int gr_branchless_binary_slicer(float x)
147 {
148   return (x >= 0);
149 }
150
151 static inline unsigned int gr_branchless_quad_0deg_slicer(float r, float i)
152 {
153   unsigned int ret = 0;
154   ret =  (fabsf(r) > fabsf(i)) * (((r < 0) << 0x1));       // either 0 (00) or 2 (10)
155   ret |= (fabsf(i) > fabsf(r)) * (((i < 0) << 0x1) | 0x1); // either 1 (01) or 3 (11)
156
157   return ret;
158 }
159
160 static inline unsigned int gr_branchless_quad_0deg_slicer(gr_complex x)
161 {
162   return gr_branchless_quad_0deg_slicer(x.real(), x.imag());
163 }
164
165 static inline unsigned int gr_branchless_quad_45deg_slicer(float r, float i)
166 {
167   char ret = (r <= 0);
168   ret |= ((i <= 0) << 1);
169   return (ret ^ ((ret & 0x2) >> 0x1));
170 }
171
172 static inline unsigned int gr_branchless_quad_45deg_slicer(gr_complex x)
173 {
174   return gr_branchless_quad_45deg_slicer(x.real(), x.imag());
175 }
176
177 /*!
178  * \param x any value
179  * \param pow2 must be a power of 2
180  * \returns \p x rounded down to a multiple of \p pow2.
181  */
182 static inline size_t
183 gr_p2_round_down(size_t x, size_t pow2)
184 {
185   return x & -pow2;
186 }
187
188 /*!
189  * \param x any value
190  * \param pow2 must be a power of 2
191  * \returns \p x rounded up to a multiple of \p pow2.
192  */
193 static inline size_t
194 gr_p2_round_up(size_t x, size_t pow2)
195 {
196   return gr_p2_round_down(x + pow2 - 1, pow2);
197 }
198
199 /*!
200  * \param x any value
201  * \param pow2 must be a power of 2
202  * \returns \p x modulo \p pow2.
203  */
204 static inline size_t
205 gr_p2_modulo(size_t x, size_t pow2)
206 {
207   return x & (pow2 - 1);
208 }
209
210 /*!
211  * \param x any value
212  * \param pow2 must be a power of 2
213  * \returns \p pow2 - (\p x modulo \p pow2).
214  */
215 static inline size_t
216 gr_p2_modulo_neg(size_t x, size_t pow2)
217 {
218   return pow2 - gr_p2_modulo(x, pow2);
219 }
220
221 #endif /* _GR_MATH_H_ */