[PATCH] Fir<> IPP cleanup

Nathan (Jasper) Myers ncm at codesourcery.com
Wed Oct 26 00:05:27 UTC 2005


I have checked in the patch below.

Fir<> now uses IPP for types and modes it supports, and native C++
code otherwise.  Before, if IPP was turned on it would only support
types IPP supports -- e.g., not long double, or int.   It also 
avoids exposing user code to Intel-header definitions.

Nathan Myers
ncm

Index: ChangeLog
===================================================================
RCS file: /home/cvs/Repository/vpp/ChangeLog,v
retrieving revision 1.296
diff -u -p -r1.296 ChangeLog
--- ChangeLog	24 Oct 2005 13:25:30 -0000	1.296
+++ ChangeLog	25 Oct 2005 23:50:18 -0000
@@ -1,3 +1,10 @@
+2005-10-25  Nathan Myers  <ncm at codesourcery.com>
+
+	* src/vsip/impl/ipp.cpp, src/vsip/impl/signal-fir.hpp:
+	  Use native C++ FIR code for all types and modes not supported 
+	  by IPP FIR.  Confine Intel ipp*.h includes to ipp.cpp where
+	  users' code will not be exposed to them.
+
 2005-10-24  Nathan Myers  <ncm at codesourcery.com>
 
 	* configure.ac: fix help for "--enable-profile-timer".
Index: src/vsip/impl/ipp.cpp
===================================================================
RCS file: /home/cvs/Repository/vpp/src/vsip/impl/ipp.cpp,v
retrieving revision 1.5
diff -u -p -r1.5 ipp.cpp
--- src/vsip/impl/ipp.cpp	21 Sep 2005 09:38:59 -0000	1.5
+++ src/vsip/impl/ipp.cpp	25 Oct 2005 23:50:18 -0000
@@ -10,7 +10,13 @@
   Included Files
 ***********************************************************************/
 
-#include "ipp.hpp"
+#include <vsip/impl/acconfig.hpp>
+
+#if defined(VSIP_IMPL_HAVE_IPP)
+
+#include <vsip/math.hpp>
+#include <vsip/signal.hpp>
+#include <vsip/impl/ipp.hpp>
 #include <ipps.h>
 
 /***********************************************************************
@@ -192,7 +198,74 @@ void conv(double* coeff, length_type coe
   ippsConv_64f(coeff, coeff_size, in, in_size, out);
 }
 
+//
+// FIR support
+//
+
+template
+<
+  typename T, typename IppT,
+  IppStatus (&ippFirF)(IppT const*,IppT*,int,IppT const*,int,IppT*,int*),
+  IppStatus (&ippFirDecF)(
+    IppT const*,IppT*,int,IppT const*,int,int,int,int,int,IppT*)
+>
+struct Ipp_fir_base
+{
+  typedef Ipp_fir_base  base_type;
+
+  inline static void
+  run(
+    T const* xin, T* xout, vsip::length_type outsize,
+    T const* xkernel, vsip::length_type ksize,  
+    T* xstate, vsip::length_type* xstate_ix, vsip::length_type dec)
+  {
+    IppT const* const  in = reinterpret_cast<IppT const*>(xin);
+    IppT* const  out = reinterpret_cast<IppT*>(xout);
+    IppT const* const  kernel = reinterpret_cast<IppT const*>(xkernel);
+    IppT* const  state = reinterpret_cast<IppT*>(xstate);
+    int state_ix = *xstate_ix;
+    IppStatus stat = (dec == 1) ?
+      ippFirF(in, out, outsize, kernel, ksize, state, &state_ix) :
+      ippFirDecF(in, out, outsize, kernel, ksize, 1, 0, dec, 0, state);
+    assert(stat == ippStsNoErr);
+    *xstate_ix = state_ix;
+  }
+};
+
+template <typename T> struct Ipp_fir;
+
+template<> struct Ipp_fir<float> : Ipp_fir_base<
+  float,Ipp32f,ippsFIR_Direct_32f,ippsFIRMR_Direct_32f> { };
+
+template<> struct Ipp_fir<double> : Ipp_fir_base<
+  double,Ipp64f,ippsFIR_Direct_64f,ippsFIRMR_Direct_64f> {};
+
+template<> struct Ipp_fir<std::complex<float> > : Ipp_fir_base<
+  std::complex<float>,Ipp32fc,ippsFIR_Direct_32fc,ippsFIRMR_Direct_32fc> {};
+
+template<> struct Ipp_fir<std::complex<double> > : Ipp_fir_base<
+  std::complex<double>,Ipp64fc,ippsFIR_Direct_64fc,ippsFIRMR_Direct_64fc> {};
+
+template <typename T>
+void
+Ipp_fir_driver<T>::run_fir(
+      T const* xin, T* xout, vsip::length_type outsize,
+      T const* xkernel, vsip::length_type ksize,  
+      T* xstate, vsip::length_type* xstate_ix, vsip::length_type dec)
+{
+  Ipp_fir<T>::run(
+    xin, xout, outsize, xkernel, ksize, xstate, xstate_ix, dec);   
+}
+
+// instantiate the specialized IPP FIR drivers here, along with what they use.
+
+template struct Ipp_fir_driver<float>;
+template struct Ipp_fir_driver<double>;
+template struct Ipp_fir_driver<std::complex<float> >;
+template struct Ipp_fir_driver<std::complex<double> >;
+
 } // namespace vsip::impl::ipp
 } // namespace vsip::impl
 } // namespace vsip
 
+#endif /* VSIP_IMPL_HAVE_IPP */
Index: src/vsip/impl/signal-fir.hpp
===================================================================
RCS file: /home/cvs/Repository/vpp/src/vsip/impl/signal-fir.hpp,v
retrieving revision 1.4
diff -u -p -r1.4 signal-fir.hpp
--- src/vsip/impl/signal-fir.hpp	24 Oct 2005 13:25:30 -0000	1.4
+++ src/vsip/impl/signal-fir.hpp	25 Oct 2005 23:50:18 -0000
@@ -19,13 +19,6 @@
 #include <vsip/impl/global_map.hpp>
 #include <vsip/impl/profile.hpp>
 
-#if VSIP_IMPL_HAVE_IPP
-#include <vsip/impl/ipp.hpp>
-#include <ipps.h>
-#endif
-
-#include <new>
-
 namespace vsip
 {
 
@@ -48,49 +41,54 @@ struct Fir_aligned
     block_type;
 };
 
-#if VSIP_IMPL_HAVE_IPP
-
-template
-<
-  typename T, typename IppT,
-  IppStatus (&ippFirF)(IppT const*,IppT*,int,IppT const*,int,IppT*,int*),
-  IppStatus (&ippFirDecF)(
-    IppT const*,IppT*,int,IppT const*,int,int,int,int,int,IppT*)
->
-struct Ipp_fir_driver_base
+template <typename T>
+struct Fir_driver
 {
+  static const bool  reverse_kernel = true;
+  static const bool  use_native = true;
+  static const bool  mismatch_ok = true;
+
+  // code that calls this should be elided by the optimizer.
   static void
   run_fir(
-    T const* xin, T* xout, vsip::length_type outsize,
-    T const* xkernel, vsip::length_type ksize,  
-    T* xstate, vsip::length_type* xstate_ix, vsip::length_type dec)
-  {
-    IppT const* const  in = reinterpret_cast<IppT const*>(xin);
-    IppT* const  out = reinterpret_cast<IppT*>(xout);
-    IppT const* const  kernel = reinterpret_cast<IppT const*>(xkernel);
-    IppT* const  state = reinterpret_cast<IppT*>(xstate);
-    int state_ix = *xstate_ix;
-    IppStatus stat = (dec == 1) ?
-      ippFirF(in, out, outsize, kernel, ksize, state, &state_ix) :
-      ippFirDecF(in, out, outsize, kernel, ksize, 1, 0, dec, 0, state);
-    assert(stat == ippStsNoErr);
-    *xstate_ix = state_ix;
-  }
+      T const* xin, T* xout, vsip::length_type outsize,
+      T const* xkernel, vsip::length_type ksize,  
+      T* xstate, vsip::length_type* xstate_ix, vsip::length_type dec)
+    { assert(false); }
 };
 
-template<typename T> struct Ipp_fir_driver;
+#if VSIP_IMPL_HAVE_IPP
 
-template < > struct Ipp_fir_driver<float> : Ipp_fir_driver_base<
-  float,Ipp32f,ippsFIR_Direct_32f,ippsFIRMR_Direct_32f> { };
+namespace ipp
+{
+
+template <typename T>
+struct Ipp_fir_driver
+{
+  static const bool  reverse_kernel = false;
+  static const bool  use_native = false;
+  static const bool  mismatch_ok = false;
+
+  // same API as in Fir_driver, but implemented in src/vsip/impl/ipp.cpp
+  static void
+  run_fir(
+      T const* xin, T* xout, vsip::length_type outsize,
+      T const* xkernel, vsip::length_type ksize,  
+      T* xstate, vsip::length_type* xstate_ix, vsip::length_type dec);
+};
 
-template<> struct Ipp_fir_driver<double> : Ipp_fir_driver_base<
-  double,Ipp64f,ippsFIR_Direct_64f,ippsFIRMR_Direct_64f> {};
+} // namespace vsip::impl::ipp
 
-template<> struct Ipp_fir_driver<std::complex<float> > : Ipp_fir_driver_base<
-  std::complex<float>,Ipp32fc,ippsFIR_Direct_32fc,ippsFIRMR_Direct_32fc> {};
+// use IPP specialization for certain T:
 
-template<> struct Ipp_fir_driver<std::complex<double> > : Ipp_fir_driver_base<
-  std::complex<double>,Ipp64fc,ippsFIR_Direct_64fc,ippsFIRMR_Direct_64fc> {};
+template<> struct Fir_driver<float>
+  : ipp::Ipp_fir_driver<float> {};
+template<> struct Fir_driver<double>
+  : ipp::Ipp_fir_driver<double> {};
+template<> struct Fir_driver<std::complex<float> >
+  : ipp::Ipp_fir_driver<std::complex<float> > {};
+template<> struct Fir_driver<std::complex<double> >
+  : ipp::Ipp_fir_driver<std::complex<double> > {};
 
 #endif // VSIP_IMPL_HAVE_IPP
 
@@ -147,18 +145,10 @@ public:
     // must be after asserts because of division
     this->output_size_ = (input_size + decimation - 1) / decimation;
 
-#if VSIP_IMPL_HAVE_IPP
     // use IPP only if decimation is a factor of input size.
-    if (this->output_size_ * decimation == this->input_size_)
-    {
-      // IPP doesn't want it reversed.
-      this->kernel_(vsip::Domain<1>(kernel.size())) = kernel;
-      if (symV != vsip::nonsym)
-	this->kernel_(vsip::Domain<1>(
-	   this->kernel_.size() - 1, -1, kernel.size())) = kernel;
-    }
-    else
-#endif
+    if (impl::Fir_driver<T>::reverse_kernel || 
+        (!impl::Fir_driver<T>::mismatch_ok && 
+          this->output_size_ * decimation != this->input_size_))
     {
       // mirror the kernel
       unsigned const ksz = kernel.size();
@@ -167,6 +157,14 @@ public:
       if (symV != vsip::nonsym)
 	this->kernel_(vsip::Domain<1>(ksz)) = kernel;
     }
+    else
+    {
+      // e.g. IPP doesn't want it reversed.
+      this->kernel_(vsip::Domain<1>(kernel.size())) = kernel;
+      if (symV != vsip::nonsym)
+	this->kernel_(vsip::Domain<1>(
+	   this->kernel_.size() - 1, -1, kernel.size())) = kernel;
+    }
   }
 
   // FIXME: spec says this should be nothrow, but it has to allocate
@@ -240,7 +238,9 @@ public:
 #if VSIP_IMPL_HAVE_IPP
     
     // use IPP only if decimation is a factor of input size.
-    if (this->input_size_ == this->output_size_ * dec)
+    if (!impl::Fir_driver<T>::use_native &&
+        (impl::Fir_driver<T>::mismatch_ok ||
+          this->input_size_ == this->output_size_ * dec))
     {
       typedef impl::Layout<1,vsip::tuple<0,1,2>,
 	  impl::Stride_unit,impl::Cmplx_inter_fmt>  layout_type;
@@ -254,7 +254,7 @@ public:
       impl::Ext_data<block_type,layout_type>  raw_state(this->state_.block());
       oix = (this->input_size_ - skip + dec - 1) / dec;
       
-      impl::Ipp_fir_driver<T>::run_fir(raw_in.data(), raw_out.data(), oix,
+      impl::Fir_driver<T>::run_fir(raw_in.data(), raw_out.data(), oix,
 	raw_kernel.data(), m + 1, raw_state.data(), &this->state_saved_, dec);
 
       if (useOldState != state_save)
@@ -304,7 +304,7 @@ public:
 
   void reset()  VSIP_NOTHROW
     { this->state_saved_ = this->skip_ = 0;
-      this->state_ = T(0.0); }
+      this->state_ = T(0); }
 
 public:
 



More information about the vsipl++ mailing list