GNU Radio 3.5.1 C++ API
|
00001 /* -*- c++ -*- */ 00002 /* 00003 * Copyright 2003,2005,2008 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 <gr_core_api.h> 00031 #include <gr_complex.h> 00032 00033 static inline bool 00034 gr_is_power_of_2(long x) 00035 { 00036 return x != 0 && (x & (x-1)) == 0; 00037 } 00038 00039 /*! 00040 * \brief Fast arc tangent using table lookup and linear interpolation 00041 * \ingroup misc 00042 * 00043 * \param y component of input vector 00044 * \param x component of input vector 00045 * \returns float angle angle of vector (x, y) in radians 00046 * 00047 * This function calculates the angle of the vector (x,y) based on a 00048 * table lookup and linear interpolation. The table uses a 256 point 00049 * table covering -45 to +45 degrees and uses symetry to determine the 00050 * final angle value in the range of -180 to 180 degrees. Note that 00051 * this function uses the small angle approximation for values close 00052 * to zero. This routine calculates the arc tangent with an average 00053 * error of +/- 0.045 degrees. 00054 */ 00055 GR_CORE_API float gr_fast_atan2f(float y, float x); 00056 00057 static inline float gr_fast_atan2f(gr_complex z) 00058 { 00059 return gr_fast_atan2f(z.imag(), z.real()); 00060 } 00061 00062 /* This bounds x by +/- clip without a branch */ 00063 static inline float gr_branchless_clip(float x, float clip) 00064 { 00065 float x1 = fabsf(x+clip); 00066 float x2 = fabsf(x-clip); 00067 x1 -= x2; 00068 return 0.5*x1; 00069 } 00070 00071 static inline float gr_clip(float x, float clip) 00072 { 00073 float y = x; 00074 if(x > clip) 00075 y = clip; 00076 else if(x < -clip) 00077 y = -clip; 00078 return y; 00079 } 00080 00081 // Slicer Functions 00082 static inline unsigned int gr_binary_slicer(float x) 00083 { 00084 if(x >= 0) 00085 return 1; 00086 else 00087 return 0; 00088 } 00089 00090 static inline unsigned int gr_quad_45deg_slicer(float r, float i) 00091 { 00092 unsigned int ret = 0; 00093 if((r >= 0) && (i >= 0)) 00094 ret = 0; 00095 else if((r < 0) && (i >= 0)) 00096 ret = 1; 00097 else if((r < 0) && (i < 0)) 00098 ret = 2; 00099 else 00100 ret = 3; 00101 return ret; 00102 } 00103 00104 static inline unsigned int gr_quad_0deg_slicer(float r, float i) 00105 { 00106 unsigned int ret = 0; 00107 if(fabsf(r) > fabsf(i)) { 00108 if(r > 0) 00109 ret = 0; 00110 else 00111 ret = 2; 00112 } 00113 else { 00114 if(i > 0) 00115 ret = 1; 00116 else 00117 ret = 3; 00118 } 00119 00120 return ret; 00121 } 00122 00123 static inline unsigned int gr_quad_45deg_slicer(gr_complex x) 00124 { 00125 return gr_quad_45deg_slicer(x.real(), x.imag()); 00126 } 00127 00128 static inline unsigned int gr_quad_0deg_slicer(gr_complex x) 00129 { 00130 return gr_quad_0deg_slicer(x.real(), x.imag()); 00131 } 00132 00133 // Branchless Slicer Functions 00134 static inline unsigned int gr_branchless_binary_slicer(float x) 00135 { 00136 return (x >= 0); 00137 } 00138 00139 static inline unsigned int gr_branchless_quad_0deg_slicer(float r, float i) 00140 { 00141 unsigned int ret = 0; 00142 ret = (fabsf(r) > fabsf(i)) * (((r < 0) << 0x1)); // either 0 (00) or 2 (10) 00143 ret |= (fabsf(i) > fabsf(r)) * (((i < 0) << 0x1) | 0x1); // either 1 (01) or 3 (11) 00144 00145 return ret; 00146 } 00147 00148 static inline unsigned int gr_branchless_quad_0deg_slicer(gr_complex x) 00149 { 00150 return gr_branchless_quad_0deg_slicer(x.real(), x.imag()); 00151 } 00152 00153 static inline unsigned int gr_branchless_quad_45deg_slicer(float r, float i) 00154 { 00155 char ret = (r <= 0); 00156 ret |= ((i <= 0) << 1); 00157 return (ret ^ ((ret & 0x2) >> 0x1)); 00158 } 00159 00160 static inline unsigned int gr_branchless_quad_45deg_slicer(gr_complex x) 00161 { 00162 return gr_branchless_quad_45deg_slicer(x.real(), x.imag()); 00163 } 00164 00165 /*! 00166 * \param x any value 00167 * \param pow2 must be a power of 2 00168 * \returns \p x rounded down to a multiple of \p pow2. 00169 */ 00170 static inline size_t 00171 gr_p2_round_down(size_t x, size_t pow2) 00172 { 00173 return x & -pow2; 00174 } 00175 00176 /*! 00177 * \param x any value 00178 * \param pow2 must be a power of 2 00179 * \returns \p x rounded up to a multiple of \p pow2. 00180 */ 00181 static inline size_t 00182 gr_p2_round_up(size_t x, size_t pow2) 00183 { 00184 return gr_p2_round_down(x + pow2 - 1, pow2); 00185 } 00186 00187 /*! 00188 * \param x any value 00189 * \param pow2 must be a power of 2 00190 * \returns \p x modulo \p pow2. 00191 */ 00192 static inline size_t 00193 gr_p2_modulo(size_t x, size_t pow2) 00194 { 00195 return x & (pow2 - 1); 00196 } 00197 00198 /*! 00199 * \param x any value 00200 * \param pow2 must be a power of 2 00201 * \returns \p pow2 - (\p x modulo \p pow2). 00202 */ 00203 static inline size_t 00204 gr_p2_modulo_neg(size_t x, size_t pow2) 00205 { 00206 return pow2 - gr_p2_modulo(x, pow2); 00207 } 00208 00209 #endif /* _GR_MATH_H_ */