ivl 679
|
00001 /* This file is part of the ivl C++ library <http://image.ntua.gr/ivl>. 00002 A C++ template library extending syntax towards mathematical notation. 00003 00004 Copyright (C) 2012 Yannis Avrithis <iavr@image.ntua.gr> 00005 Copyright (C) 2012 Kimon Kontosis <kimonas@image.ntua.gr> 00006 00007 ivl is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU Lesser General Public License 00009 version 3 as published by the Free Software Foundation. 00010 00011 Alternatively, you can redistribute it and/or modify it under the terms 00012 of the GNU General Public License version 2 as published by the Free 00013 Software Foundation. 00014 00015 ivl is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00018 See the GNU General Public License for more details. 00019 00020 You should have received a copy of the GNU General Public License 00021 and a copy of the GNU Lesser General Public License along 00022 with ivl. If not, see <http://www.gnu.org/licenses/>. */ 00023 00024 #ifndef IVL_ARRAY_ND_SPECIALIZATION_DETAILS_SUBARRAY_ND_TOOLS_HPP 00025 #define IVL_ARRAY_ND_SPECIALIZATION_DETAILS_SUBARRAY_ND_TOOLS_HPP 00026 00027 namespace ivl { 00028 00029 namespace array_nd_details { 00030 00031 template <class REF_ITER_IS_ND> 00032 struct subarray_tools 00033 { 00034 }; 00035 00036 template <> 00037 struct subarray_tools<types::t_true> 00038 { 00039 template <class IT, class SIT> 00040 static inline void inc_along(IT& it, const SIT& sit) 00041 { 00042 it.ptr.move_along(sit.ptr, sit.step); 00043 } 00044 00045 template <class IT, class SIT> 00046 static inline void dec_along(IT& it, const SIT& sit) 00047 { 00048 it.ptr.move_along(sit.ptr, sit.step); 00049 } 00050 00051 template <class IT, class SIT> 00052 static inline void move_along(IT& it, const SIT& sit, ptrdiff_t dist) 00053 { 00054 it.ptr.move_along(sit.ptr, sit.step * dist); 00055 } 00056 00057 template <class PTR, class S_PTR> 00058 static inline void move_ref_along(PTR& it, const S_PTR& sit, ptrdiff_t step, ptrdiff_t dist) 00059 { 00060 it.move_along(sit, step * dist); 00061 } 00062 00063 template <class IT> 00064 struct iter_nd_border_walker 00065 { 00066 ptrdiff_t step; 00067 ptrdiff_t len; 00068 ptrdiff_t cur_pos; 00069 IT it; 00070 00071 iter_nd_border_walker() {} 00072 iter_nd_border_walker(ptrdiff_t x) : len(0), cur_pos(-1), step(0) { } 00073 template<class SIT> 00074 iter_nd_border_walker(const SIT& it, 00075 size_t step, size_t len = 0, ptrdiff_t cur_pos = -1 00076 ) : step(step), len(len), cur_pos(cur_pos), it(it) { } 00077 }; 00078 00079 }; 00080 00081 template <> 00082 struct subarray_tools<types::t_false> 00083 { 00084 template <class IT, class SIT> 00085 static inline void inc_along(IT& it, const SIT& sit) 00086 { 00087 it.ptr += sit.step; 00088 } 00089 00090 template <class IT, class SIT> 00091 static inline void dec_along(IT& it, const SIT& sit) 00092 { 00093 it.ptr -= sit.step; 00094 } 00095 00096 template <class IT, class SIT> 00097 static inline void move_along(IT& it, const SIT& sit, ptrdiff_t dist) 00098 { 00099 it.ptr += sit.step * dist; 00100 } 00101 00102 template <class PTR, class S_PTR> 00103 static inline void move_ref_along(PTR& it, const S_PTR& sit, ptrdiff_t step, 00104 ptrdiff_t dist) 00105 { 00106 it += step * dist; 00107 } 00108 00109 template <class IT> 00110 struct iter_nd_border_walker 00111 { 00112 ptrdiff_t len; 00113 ptrdiff_t cur_pos; 00114 ptrdiff_t step; 00115 types::code_word<> it; 00116 00117 iter_nd_border_walker() {} 00118 iter_nd_border_walker(ptrdiff_t x) : len(0), cur_pos(-1), step(0) { } 00119 template<class SIT> 00120 iter_nd_border_walker(const SIT& it, 00121 size_t step, size_t len = 0, ptrdiff_t cur_pos = -1 00122 ) : len(len), cur_pos(cur_pos), step(step) { } 00123 }; 00124 00125 }; 00126 00127 struct subarray_common_tools 00128 { 00129 struct add_op 00130 { 00131 template<class X, class Y> 00132 static inline void operate(X& a, const Y& b) { a += b; } 00133 }; 00134 struct sub_op 00135 { 00136 template<class X, class Y> 00137 static inline void operate(X& a, const Y& b) { a -= b; } 00138 }; 00139 00140 template<class OP, class IT> 00141 static inline void inc_along(IT& ir, const IT& d, 00142 const ptrdiff_t* diff, size_t pos, size_t str) 00143 { 00144 if(diff) 00145 ir.inc_along(d, diff[pos]); 00146 else 00147 ir.inc_along(d, str); 00148 }; 00149 00150 template<class OP, class IT> 00151 static inline void dec_along(IT& ir, const IT& d, 00152 const ptrdiff_t* diff, size_t pos, size_t str) 00153 { 00154 if(diff) 00155 ir.dec_along(d, diff[pos]); 00156 else 00157 ir.dec_along(d, str); 00158 }; 00159 00160 // TODO:: possible speed improvement is: 00161 // do not use pos0 at all in the array specialized case, and 00162 // use a ptrdiff_t + length as barrier. 00163 // make also a specialized function that controls the pos0++ and 00164 // the ending condition. 00165 // However, when copying from an iterator<2> to an iterator<0> 00166 // it will be needed to generate pos0 from diff0 - start_diff0_border 00167 // and to reset diff0 = start_diff0_border, and 00168 // when copying from an iterator<0> to an iterator<2> do: 00169 // diff0 += pos 00170 00171 template<int SP = 0> // generic case operator. slower 00172 struct inner_dim_adder 00173 { 00174 template<class OP, class IT> 00175 static inline void operate(IT& ir, const ptrdiff_t* diff0, 00176 size_t pos, size_t str) 00177 { 00178 if(diff0) 00179 OP::operate(ir, diff0[pos]); 00180 else 00181 OP::operate(ir, str); 00182 } 00183 }; 00184 00185 // iterator_nd type 00186 enum sub_type 00187 { 00188 step_it = 0, 00189 array_it = 1 00190 }; 00191 00192 // get iterator_nd type from index_array indtype 00193 static inline sub_type type_from_indtype(ivl::index_array:: 00194 index_array_type y) 00195 { 00196 return (y == ivl::index_array::ARRAY ? array_it : step_it); 00197 } 00198 00199 }; 00200 00201 template<> 00202 struct subarray_common_tools::inner_dim_adder<1> // special case 1: index 0 is all or range. 00203 { 00204 template<class OP, class IT> 00205 static inline void operate(IT& ir, const ptrdiff_t* diff0, 00206 size_t pos, size_t str) 00207 { 00208 OP::operate(ir, str); 00209 } 00210 }; 00211 template<> 00212 struct subarray_common_tools::inner_dim_adder<2> // special case 2: index 0 is array. 00213 { 00214 template<class OP, class IT> 00215 static inline void operate(IT& ir, const ptrdiff_t* diff0, 00216 size_t pos, size_t str) 00217 { 00218 OP::operate(ir, diff0[pos]); 00219 } 00220 }; 00221 00222 }; /*namespace array_nd_details*/ 00223 00224 }; /*namespace ivl*/ 00225 00226 00227 #endif // IVL_ARRAY_ND_SPECIALIZATION_DETAILS_SUBARRAY_ND_TOOLS_HPP