GNU Radio 3.7.1 C++ API
|
00001 /* -*- c++ -*- */ 00002 /* 00003 * Copyright 2003,2005,2008,2013 Free Software Foundation, Inc. 00004 * 00005 * This file is part of GNU Radio 00006 * 00007 * GNU Radio is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 3, or (at your option) 00010 * any later version. 00011 * 00012 * GNU Radio is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with GNU Radio; see the file COPYING. If not, write to 00019 * the Free Software Foundation, Inc., 51 Franklin Street, 00020 * Boston, MA 02110-1301, USA. 00021 */ 00022 00023 /* 00024 * mathematical odds and ends. 00025 */ 00026 00027 #ifndef _GR_MATH_H_ 00028 #define _GR_MATH_H_ 00029 00030 #include <cmath> 00031 #include <gnuradio/api.h> 00032 #include <gnuradio/gr_complex.h> 00033 00034 namespace gr { 00035 00036 static inline bool 00037 is_power_of_2(long x) 00038 { 00039 return x != 0 && (x & (x-1)) == 0; 00040 } 00041 00042 /*! 00043 * \brief Fast arc tangent using table lookup and linear interpolation 00044 * \ingroup misc 00045 * 00046 * \param y component of input vector 00047 * \param x component of input vector 00048 * \returns float angle angle of vector (x, y) in radians 00049 * 00050 * This function calculates the angle of the vector (x,y) based on a 00051 * table lookup and linear interpolation. The table uses a 256 point 00052 * table covering -45 to +45 degrees and uses symetry to determine 00053 * the final angle value in the range of -180 to 180 degrees. Note 00054 * that this function uses the small angle approximation for values 00055 * close to zero. This routine calculates the arc tangent with an 00056 * average error of +/- 0.045 degrees. 00057 */ 00058 GR_RUNTIME_API float fast_atan2f(float y, float x); 00059 00060 static inline float 00061 fast_atan2f(gr_complex z) 00062 { 00063 return fast_atan2f(z.imag(), z.real()); 00064 } 00065 00066 /* This bounds x by +/- clip without a branch */ 00067 static inline float 00068 branchless_clip(float x, float clip) 00069 { 00070 float x1 = fabsf(x+clip); 00071 float x2 = fabsf(x-clip); 00072 x1 -= x2; 00073 return 0.5*x1; 00074 } 00075 00076 static inline float 00077 clip(float x, float clip) 00078 { 00079 float y = x; 00080 if(x > clip) 00081 y = clip; 00082 else if(x < -clip) 00083 y = -clip; 00084 return y; 00085 } 00086 00087 // Slicer Functions 00088 static inline unsigned int 00089 binary_slicer(float x) 00090 { 00091 if(x >= 0) 00092 return 1; 00093 else 00094 return 0; 00095 } 00096 00097 static inline unsigned int 00098 quad_45deg_slicer(float r, float i) 00099 { 00100 unsigned int ret = 0; 00101 if((r >= 0) && (i >= 0)) 00102 ret = 0; 00103 else if((r < 0) && (i >= 0)) 00104 ret = 1; 00105 else if((r < 0) && (i < 0)) 00106 ret = 2; 00107 else 00108 ret = 3; 00109 return ret; 00110 } 00111 00112 static inline unsigned int 00113 quad_0deg_slicer(float r, float i) 00114 { 00115 unsigned int ret = 0; 00116 if(fabsf(r) > fabsf(i)) { 00117 if(r > 0) 00118 ret = 0; 00119 else 00120 ret = 2; 00121 } 00122 else { 00123 if(i > 0) 00124 ret = 1; 00125 else 00126 ret = 3; 00127 } 00128 00129 return ret; 00130 } 00131 00132 static inline unsigned int 00133 quad_45deg_slicer(gr_complex x) 00134 { 00135 return quad_45deg_slicer(x.real(), x.imag()); 00136 } 00137 00138 static inline unsigned int 00139 quad_0deg_slicer(gr_complex x) 00140 { 00141 return quad_0deg_slicer(x.real(), x.imag()); 00142 } 00143 00144 // Branchless Slicer Functions 00145 static inline unsigned int 00146 branchless_binary_slicer(float x) 00147 { 00148 return (x >= 0); 00149 } 00150 00151 static inline unsigned int 00152 branchless_quad_0deg_slicer(float r, float i) 00153 { 00154 unsigned int ret = 0; 00155 ret = (fabsf(r) > fabsf(i)) * (((r < 0) << 0x1)); // either 0 (00) or 2 (10) 00156 ret |= (fabsf(i) > fabsf(r)) * (((i < 0) << 0x1) | 0x1); // either 1 (01) or 3 (11) 00157 00158 return ret; 00159 } 00160 00161 static inline unsigned int 00162 branchless_quad_0deg_slicer(gr_complex x) 00163 { 00164 return branchless_quad_0deg_slicer(x.real(), x.imag()); 00165 } 00166 00167 static inline unsigned int 00168 branchless_quad_45deg_slicer(float r, float i) 00169 { 00170 char ret = (r <= 0); 00171 ret |= ((i <= 0) << 1); 00172 return (ret ^ ((ret & 0x2) >> 0x1)); 00173 } 00174 00175 static inline unsigned int 00176 branchless_quad_45deg_slicer(gr_complex x) 00177 { 00178 return branchless_quad_45deg_slicer(x.real(), x.imag()); 00179 } 00180 00181 /*! 00182 * \param x any value 00183 * \param pow2 must be a power of 2 00184 * \returns \p x rounded down to a multiple of \p pow2. 00185 */ 00186 static inline size_t 00187 p2_round_down(size_t x, size_t pow2) 00188 { 00189 return x & -pow2; 00190 } 00191 00192 /*! 00193 * \param x any value 00194 * \param pow2 must be a power of 2 00195 * \returns \p x rounded up to a multiple of \p pow2. 00196 */ 00197 static inline size_t 00198 p2_round_up(size_t x, size_t pow2) 00199 { 00200 return p2_round_down(x + pow2 - 1, pow2); 00201 } 00202 00203 /*! 00204 * \param x any value 00205 * \param pow2 must be a power of 2 00206 * \returns \p x modulo \p pow2. 00207 */ 00208 static inline size_t 00209 p2_modulo(size_t x, size_t pow2) 00210 { 00211 return x & (pow2 - 1); 00212 } 00213 00214 /*! 00215 * \param x any value 00216 * \param pow2 must be a power of 2 00217 * \returns \p pow2 - (\p x modulo \p pow2). 00218 */ 00219 static inline size_t 00220 p2_modulo_neg(size_t x, size_t pow2) 00221 { 00222 return pow2 - p2_modulo(x, pow2); 00223 } 00224 00225 } /* namespace gr */ 00226 00227 #endif /* _GR_MATH_H_ */