GNU Radio 3.7.0 C++ API
math.h
Go to the documentation of this file.
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_ */