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