GNU Radio 3.6.3 C++ API
gr_math.h
Go to the documentation of this file.
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_core_api.h>
31 #include <gr_complex.h>
32 
33 static inline bool
35 {
36  return x != 0 && (x & (x-1)) == 0;
37 }
38 
39 /*!
40  * \brief Fast arc tangent using table lookup and linear interpolation
41  * \ingroup misc
42  *
43  * \param y component of input vector
44  * \param x component of input vector
45  * \returns float angle angle of vector (x, y) in radians
46  *
47  * This function calculates the angle of the vector (x,y) based on a
48  * table lookup and linear interpolation. The table uses a 256 point
49  * table covering -45 to +45 degrees and uses symetry to determine the
50  * final angle value in the range of -180 to 180 degrees. Note that
51  * this function uses the small angle approximation for values close
52  * to zero. This routine calculates the arc tangent with an average
53  * error of +/- 0.045 degrees.
54  */
55 GR_CORE_API float gr_fast_atan2f(float y, float x);
56 
57 static inline float gr_fast_atan2f(gr_complex z)
58 {
59  return gr_fast_atan2f(z.imag(), z.real());
60 }
61 
62 /* This bounds x by +/- clip without a branch */
63 static inline float gr_branchless_clip(float x, float clip)
64 {
65  float x1 = fabsf(x+clip);
66  float x2 = fabsf(x-clip);
67  x1 -= x2;
68  return 0.5*x1;
69 }
70 
71 static inline float gr_clip(float x, float clip)
72 {
73  float y = x;
74  if(x > clip)
75  y = clip;
76  else if(x < -clip)
77  y = -clip;
78  return y;
79 }
80 
81 // Slicer Functions
82 static inline unsigned int gr_binary_slicer(float x)
83 {
84  if(x >= 0)
85  return 1;
86  else
87  return 0;
88 }
89 
90 static inline unsigned int gr_quad_45deg_slicer(float r, float i)
91 {
92  unsigned int ret = 0;
93  if((r >= 0) && (i >= 0))
94  ret = 0;
95  else if((r < 0) && (i >= 0))
96  ret = 1;
97  else if((r < 0) && (i < 0))
98  ret = 2;
99  else
100  ret = 3;
101  return ret;
102 }
103 
104 static inline unsigned int gr_quad_0deg_slicer(float r, float i)
105 {
106  unsigned int ret = 0;
107  if(fabsf(r) > fabsf(i)) {
108  if(r > 0)
109  ret = 0;
110  else
111  ret = 2;
112  }
113  else {
114  if(i > 0)
115  ret = 1;
116  else
117  ret = 3;
118  }
119 
120  return ret;
121 }
122 
123 static inline unsigned int gr_quad_45deg_slicer(gr_complex x)
124 {
125  return gr_quad_45deg_slicer(x.real(), x.imag());
126 }
127 
128 static inline unsigned int gr_quad_0deg_slicer(gr_complex x)
129 {
130  return gr_quad_0deg_slicer(x.real(), x.imag());
131 }
132 
133 // Branchless Slicer Functions
134 static inline unsigned int gr_branchless_binary_slicer(float x)
135 {
136  return (x >= 0);
137 }
138 
139 static inline unsigned int gr_branchless_quad_0deg_slicer(float r, float i)
140 {
141  unsigned int ret = 0;
142  ret = (fabsf(r) > fabsf(i)) * (((r < 0) << 0x1)); // either 0 (00) or 2 (10)
143  ret |= (fabsf(i) > fabsf(r)) * (((i < 0) << 0x1) | 0x1); // either 1 (01) or 3 (11)
144 
145  return ret;
146 }
147 
148 static inline unsigned int gr_branchless_quad_0deg_slicer(gr_complex x)
149 {
150  return gr_branchless_quad_0deg_slicer(x.real(), x.imag());
151 }
152 
153 static inline unsigned int gr_branchless_quad_45deg_slicer(float r, float i)
154 {
155  char ret = (r <= 0);
156  ret |= ((i <= 0) << 1);
157  return (ret ^ ((ret & 0x2) >> 0x1));
158 }
159 
160 static inline unsigned int gr_branchless_quad_45deg_slicer(gr_complex x)
161 {
162  return gr_branchless_quad_45deg_slicer(x.real(), x.imag());
163 }
164 
165 /*!
166  * \param x any value
167  * \param pow2 must be a power of 2
168  * \returns \p x rounded down to a multiple of \p pow2.
169  */
170 static inline size_t
171 gr_p2_round_down(size_t x, size_t pow2)
172 {
173  return x & -pow2;
174 }
175 
176 /*!
177  * \param x any value
178  * \param pow2 must be a power of 2
179  * \returns \p x rounded up to a multiple of \p pow2.
180  */
181 static inline size_t
182 gr_p2_round_up(size_t x, size_t pow2)
183 {
184  return gr_p2_round_down(x + pow2 - 1, pow2);
185 }
186 
187 /*!
188  * \param x any value
189  * \param pow2 must be a power of 2
190  * \returns \p x modulo \p pow2.
191  */
192 static inline size_t
193 gr_p2_modulo(size_t x, size_t pow2)
194 {
195  return x & (pow2 - 1);
196 }
197 
198 /*!
199  * \param x any value
200  * \param pow2 must be a power of 2
201  * \returns \p pow2 - (\p x modulo \p pow2).
202  */
203 static inline size_t
204 gr_p2_modulo_neg(size_t x, size_t pow2)
205 {
206  return pow2 - gr_p2_modulo(x, pow2);
207 }
208 
209 #endif /* _GR_MATH_H_ */