algebramix_doc 0.3
|
00001 00002 /****************************************************************************** 00003 * MODULE : vector_unrolled.hpp 00004 * DESCRIPTION: loop unrolling within vectorial operations 00005 * COPYRIGHT : (C) 2007 Joris van der Hoeven and Gregoire Lecerf 00006 ******************************************************************************* 00007 * This software falls under the GNU general public license and comes WITHOUT 00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details. 00009 * If you don't have this file, write to the Free Software Foundation, Inc., 00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00011 ******************************************************************************/ 00012 00013 #ifndef __MMX__VECTOR_UNROLLED__HPP 00014 #define __MMX__VECTOR_UNROLLED__HPP 00015 #include <basix/basix.hpp> 00016 #include <algebramix/vector_fixed.hpp> 00017 00018 namespace mmx { 00019 #define TMPL template<typename C> 00020 00021 /****************************************************************************** 00022 * Variant for loop unrolled routines on vectors 00023 ******************************************************************************/ 00024 00025 template<nat len, typename V= vector_naive> 00026 struct vector_unrolled: public V { 00027 typedef typename V::Naive Naive; 00028 typedef vector_unrolled<len,typename V::Aligned> Aligned; 00029 typedef vector_unrolled<len,typename V::No_simd> No_simd; 00030 typedef vector_unrolled<len,typename V::No_thread> No_thread; 00031 }; 00032 00033 template<typename F, typename V, nat len, typename W> 00034 struct implementation<F,V,vector_unrolled<len,W> >: 00035 public implementation<F,V,W> {}; 00036 00037 /****************************************************************************** 00038 * Abstract low level vector routines on vectors in memory 00039 ******************************************************************************/ 00040 00041 template<typename V, nat len, typename W> 00042 struct implementation<vector_abstractions,V,vector_unrolled<len,W> >: 00043 public implementation<vector_allocate,V> 00044 { 00045 typedef implementation<vector_abstractions,W> Vec; 00046 00047 template<typename Op, typename T> static inline void 00048 vec_nullary (T* dest, nat n) { 00049 _loop: 00050 if (n<len) Vec::template vec_nullary<Op> (dest, n); 00051 else { 00052 vec_nullary_helper<Op, T, len>::op (dest); 00053 dest += len; n -= len; 00054 goto _loop; 00055 } 00056 } 00057 00058 template<typename Op, typename T, typename C> static inline void 00059 vec_unary (T* dest, const C* s, nat n) { 00060 _loop: 00061 if (n<len) Vec::template vec_unary<Op> (dest, s, n); 00062 else { 00063 vec_unary_helper<Op, T, C, len>::op (dest, s); 00064 dest += len; s += len; n -= len; 00065 goto _loop; 00066 } 00067 } 00068 00069 template<typename Op, typename T, typename C1, typename C2> static inline void 00070 vec_binary (T* dest, const C1* s1, const C2* s2, nat n) { 00071 _loop: 00072 if (n<len) Vec::template vec_binary<Op, T, C1, C2> (dest, s1, s2, n); 00073 else { 00074 vec_binary_helper<Op, T, C1, C2, len>::op (dest, s1, s2); 00075 dest += len; s1 += len; s2 += len; n -= len; 00076 goto _loop; 00077 } 00078 } 00079 00080 template<typename Op, typename T, typename X> static inline void 00081 vec_unary_scalar (T* dest, const X& x, nat n) { 00082 _loop: 00083 if (n<len) Vec::template vec_unary_scalar<Op, T, X> (dest, x, n); 00084 else { 00085 vec_unary_scalar_helper<Op, T, X, len>::op (dest, x); 00086 dest += len; n -= len; 00087 goto _loop; 00088 } 00089 } 00090 00091 template<typename Op, typename T, typename C, typename X> static inline void 00092 vec_binary_scalar (T* dest, const C* s, const X& x, nat n) { 00093 _loop: 00094 if (n<len) Vec::template vec_binary_scalar<Op, T, C, X> (dest, s, x, n); 00095 else { 00096 vec_binary_scalar_helper<Op, T, C, X, len>::op (dest, s, x); 00097 dest += len; s += len; n -= len; 00098 goto _loop; 00099 } 00100 } 00101 00102 template<typename Op, typename C> static inline bool 00103 vec_unary_test (const C* s, nat n) { 00104 _loop: 00105 if (n<len) 00106 return Vec::template vec_unary_test<Op, C> (s, n); 00107 else { 00108 if (! vec_unary_test_helper<Op, C, len>::op (s)) 00109 return false; 00110 s += len; n -= len; 00111 goto _loop; 00112 } 00113 return true; 00114 } 00115 00116 template<typename Op, typename C1, typename C2> static inline bool 00117 vec_binary_test (const C1* s1, const C2* s2, nat n) { 00118 _loop: 00119 if (n<len) 00120 return Vec::template vec_binary_test<Op, C1, C2> (s1, s2, n); 00121 else { 00122 if (! vec_binary_test_helper<Op, C1, C2, len>::op (s1, s2)) 00123 return false; 00124 s1 += len; s2 += len; n -= len; 00125 goto _loop; 00126 } 00127 return true; 00128 } 00129 00130 template<typename Op, typename C, typename X> static inline bool 00131 vec_binary_test_scalar (const C* s, const X& x, nat n) { 00132 _loop: 00133 if (n<len) 00134 return Vec::template vec_binary_test_scalar<Op, C, X> (s, x, n); 00135 else { 00136 if (! vec_binary_test_scalar_helper<Op, C, X, len>::op (s, x)) 00137 return false; 00138 s += len; n -= len; 00139 goto _loop; 00140 } 00141 return true; 00142 } 00143 00144 template<typename Op, typename C> static inline Unary_return_type(Op,C) 00145 vec_unary_big (const C* s, nat n) { 00146 typedef Unary_return_type(Op,C) R; 00147 if (n == 0) return Op::template neutral<C> (); 00148 R r= Op::template neutral<R> (); 00149 Op::set_op (r, Vec::template vec_unary_big<Op, C> (s, n)); 00150 s++; n--; 00151 _loop: 00152 if (n < len) 00153 Op::set_op (r, Vec::template vec_unary_big<Op, C> (s, n)); 00154 else { 00155 vec_unary_big_helper<Op, R, C, len>::set_op (r, s); 00156 s += len; n -= len; 00157 goto _loop; 00158 } 00159 return r; 00160 } 00161 00162 template<typename Op, typename C> static inline Unary_return_type(Op,C) 00163 vec_unary_big (const C* s, nat n, const format<C>& fm) { 00164 typedef Unary_return_type(Op,C) R; 00165 R r= get_sample (unary_map<Op> (fm)); 00166 Op::set_neutral (r); 00167 if (n == 0) return r; 00168 Op::set_op (r, Vec::template vec_unary_big<Op, C> (s, n, fm)); 00169 s++; n--; 00170 _loop: 00171 if (n < len) 00172 Op::set_op (r, Vec::template vec_unary_big<Op, C> (s, n, fm)); 00173 else { 00174 vec_unary_big_helper<Op, R, C, len>::set_op (r, s, fm); 00175 s += len; n -= len; 00176 goto _loop; 00177 } 00178 return r; 00179 } 00180 00181 template<typename Op, typename C> static inline C 00182 vec_unary_big_dicho (const C* s, nat n) { 00183 return vec_unary_big<Op, C> (s, n); 00184 } 00185 00186 template<typename Op, typename C> static inline C 00187 vec_unary_big_dicho (const C* s, nat n, const format<C>& fm) { 00188 return vec_unary_big<Op, C> (s, n, fm); 00189 } 00190 00191 template<typename Op, typename C1, typename C2> static inline C1 00192 vec_binary_big (const C1* s1, const C2* s2, nat n) { 00193 C1 r= Op::template neutral<C1> (); 00194 _loop: 00195 if (n<len) 00196 for (; n != 0; s1++, s2++, n--) 00197 Op::set_op (r, *s1, *s2); 00198 else { 00199 vec_binary_big_helper<Op, C1, C2, len>::_op (r, s1, s2); 00200 s1 += len; s2 += len; n -= len; 00201 goto _loop; 00202 } 00203 return r; 00204 } 00205 00206 template<typename Op, typename C1, typename C2> static inline C1 00207 vec_binary_big (const C1* s1, const C2* s2, nat n, 00208 const format<C1>& fm1, const format<C2>& fm2) { 00209 C1 r= get_sample (binary_map<Op> (fm1, fm2)); 00210 Op::set_neutral (r); 00211 _loop: 00212 if (n<len) 00213 for (; n != 0; s1++, s2++, n--) 00214 Op::set_op (r, *s1, *s2); 00215 else { 00216 vec_binary_big_helper<Op, C1, C2, len>::_op (r, s1, s2, fm1, fm2); 00217 s1 += len; s2 += len; n -= len; 00218 goto _loop; 00219 } 00220 return r; 00221 } 00222 00223 }; // implementation<vector_abstractions,V,vector_unrolled<len1,W> > 00224 00225 #undef TMPL 00226 } // namespace mmx 00227 #endif //__MMX__VECTOR_UNROLLED__HPP