GNU Radio Manual and C++ API Reference  3.10.9.1
The Free & Open Software Radio Ecosystem
math.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2003,2005,2008,2013,2018 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * SPDX-License-Identifier: GPL-3.0-or-later
8  *
9  */
10 
11 /*
12  * mathematical odds and ends.
13  */
14 
15 #ifndef _GR_MATH_H_
16 #define _GR_MATH_H_
17 
18 #include <gnuradio/api.h>
19 #include <gnuradio/gr_complex.h>
20 #include <cmath>
21 
22 /*
23  * \brief Define commonly used mathematical constants
24  * \ingroup misc
25  *
26  * Mathematical constants are neither defined in the C standard
27  * nor the C++ standard. For -std=c{++}11 M_LOG2E and M_SQRT2 won't
28  * compile. GR_M_PI actually works with C++ but is defined here for the sake
29  * of consistency.
30  */
31 
32 #define GR_M_PI 3.14159265358979323846 /* pi */
33 #define GR_M_SQRT2 1.41421356237309504880 /* sqrt(2) */
34 
35 
36 namespace gr {
37 
38 static inline void
39 fast_cc_multiply(gr_complex& out, const gr_complex cc1, const gr_complex cc2)
40 {
41  // The built-in complex.h multiply has significant NaN/INF checking that
42  // considerably slows down performance. While on some compilers the
43  // -fcx-limit-range flag can be used, this fast function makes the math consistent
44  // in terms of performance for the Costas loop.
45  float o_r, o_i;
46 
47  o_r = (cc1.real() * cc2.real()) - (cc1.imag() * cc2.imag());
48  o_i = (cc1.real() * cc2.imag()) + (cc1.imag() * cc2.real());
49 
50  out.real(o_r);
51  out.imag(o_i);
52 }
53 
54 static inline bool is_power_of_2(long x) { return x != 0 && (x & (x - 1)) == 0; }
55 
56 /*!
57  * \brief Fast arc tangent using table lookup and linear interpolation
58  * \ingroup misc
59  *
60  * \param y component of input vector
61  * \param x component of input vector
62  * \returns float angle angle of vector (x, y) in radians
63  *
64  * This function calculates the angle of the vector (x,y) based on a
65  * table lookup and linear interpolation. The table uses a 256 point
66  * table covering -45 to +45 degrees and uses symmetry to determine
67  * the final angle value in the range of -180 to 180 degrees. Note
68  * that this function uses the small angle approximation for values
69  * close to zero. This routine calculates the arc tangent with an
70  * average error of +/- 0.045 degrees.
71  */
72 GR_RUNTIME_API float fast_atan2f(float y, float x);
73 
74 static inline float fast_atan2f(gr_complex z) { return fast_atan2f(z.imag(), z.real()); }
75 
76 /* This bounds x by +/- clip without a branch */
77 static inline float branchless_clip(float x, float clip)
78 {
79  return 0.5 * (std::abs(x + clip) - std::abs(x - clip));
80 }
81 
82 static inline float clip(float x, float clip)
83 {
84  float y = x;
85  if (x > clip)
86  y = clip;
87  else if (x < -clip)
88  y = -clip;
89  return y;
90 }
91 
92 // Slicer Functions
93 static inline unsigned int binary_slicer(float x)
94 {
95  if (x >= 0)
96  return 1;
97  else
98  return 0;
99 }
100 
101 static inline unsigned int quad_45deg_slicer(float r, float i)
102 {
103  unsigned int ret = 0;
104  if ((r >= 0) && (i >= 0))
105  ret = 0;
106  else if ((r < 0) && (i >= 0))
107  ret = 1;
108  else if ((r < 0) && (i < 0))
109  ret = 2;
110  else
111  ret = 3;
112  return ret;
113 }
114 
115 static inline unsigned int quad_0deg_slicer(float r, float i)
116 {
117  unsigned int ret = 0;
118  if (fabsf(r) > fabsf(i)) {
119  if (r > 0)
120  ret = 0;
121  else
122  ret = 2;
123  } else {
124  if (i > 0)
125  ret = 1;
126  else
127  ret = 3;
128  }
129 
130  return ret;
131 }
132 
133 static inline unsigned int quad_45deg_slicer(gr_complex x)
134 {
135  return quad_45deg_slicer(x.real(), x.imag());
136 }
137 
138 static inline unsigned int quad_0deg_slicer(gr_complex x)
139 {
140  return quad_0deg_slicer(x.real(), x.imag());
141 }
142 
143 // Branchless Slicer Functions
144 static inline unsigned int branchless_binary_slicer(float x) { return (x >= 0); }
145 
146 static inline unsigned int branchless_quad_0deg_slicer(float r, float i)
147 {
148  unsigned int ret = 0;
149  ret = (fabsf(r) > fabsf(i)) * (((r < 0) << 0x1)); // either 0 (00) or 2 (10)
150  ret |= (fabsf(i) > fabsf(r)) * (((i < 0) << 0x1) | 0x1); // either 1 (01) or 3 (11)
151 
152  return ret;
153 }
154 
155 static inline unsigned int branchless_quad_0deg_slicer(gr_complex x)
156 {
157  return branchless_quad_0deg_slicer(x.real(), x.imag());
158 }
159 
160 static inline unsigned int branchless_quad_45deg_slicer(float r, float i)
161 {
162  char ret = (r <= 0);
163  ret |= ((i <= 0) << 1);
164  return (ret ^ ((ret & 0x2) >> 0x1));
165 }
166 
167 static inline unsigned int branchless_quad_45deg_slicer(gr_complex x)
168 {
169  return branchless_quad_45deg_slicer(x.real(), x.imag());
170 }
171 
172 /*!
173  * \param x any value
174  * \param pow2 must be a power of 2
175  * \returns \p x rounded down to a multiple of \p pow2.
176  */
177 static inline size_t p2_round_down(size_t x, size_t pow2) { return x & -pow2; }
178 
179 /*!
180  * \param x any value
181  * \param pow2 must be a power of 2
182  * \returns \p x rounded up to a multiple of \p pow2.
183  */
184 static inline size_t p2_round_up(size_t x, size_t pow2)
185 {
186  return p2_round_down(x + pow2 - 1, pow2);
187 }
188 
189 /*!
190  * \param x any value
191  * \param pow2 must be a power of 2
192  * \returns \p x modulo \p pow2.
193  */
194 static inline size_t p2_modulo(size_t x, size_t pow2) { return x & (pow2 - 1); }
195 
196 /*!
197  * \param x any value
198  * \param pow2 must be a power of 2
199  * \returns \p pow2 - (\p x modulo \p pow2).
200  */
201 static inline size_t p2_modulo_neg(size_t x, size_t pow2)
202 {
203  return pow2 - p2_modulo(x, pow2);
204 }
205 
206 } /* namespace gr */
207 
208 #endif /* _GR_MATH_H_ */
#define GR_RUNTIME_API
Definition: gnuradio-runtime/include/gnuradio/api.h:18
std::complex< float > gr_complex
Definition: gr_complex.h:15
GR_RUNTIME_API float fast_atan2f(float y, float x)
Fast arc tangent using table lookup and linear interpolation.
GNU Radio logging wrapper.
Definition: basic_block.h:29
static unsigned int binary_slicer(float x)
Definition: math.h:93
static unsigned int branchless_quad_45deg_slicer(float r, float i)
Definition: math.h:160
static unsigned int quad_0deg_slicer(float r, float i)
Definition: math.h:115
static size_t p2_round_up(size_t x, size_t pow2)
Definition: math.h:184
static unsigned int quad_45deg_slicer(float r, float i)
Definition: math.h:101
static float clip(float x, float clip)
Definition: math.h:82
static size_t p2_round_down(size_t x, size_t pow2)
Definition: math.h:177
static void fast_cc_multiply(gr_complex &out, const gr_complex cc1, const gr_complex cc2)
Definition: math.h:39
static unsigned int branchless_quad_0deg_slicer(float r, float i)
Definition: math.h:146
static size_t p2_modulo_neg(size_t x, size_t pow2)
Definition: math.h:201
static float branchless_clip(float x, float clip)
Definition: math.h:77
static unsigned int branchless_binary_slicer(float x)
Definition: math.h:144
static bool is_power_of_2(long x)
Definition: math.h:54
static size_t p2_modulo(size_t x, size_t pow2)
Definition: math.h:194