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_SPECIALIZATION_DETAILS_SUBARRAY_TOOLS_HPP 00025 #define IVL_ARRAY_SPECIALIZATION_DETAILS_SUBARRAY_TOOLS_HPP 00026 00027 namespace ivl { 00028 00029 namespace array_details { 00030 00031 template <class REF_ITER_IS_ND, class IT> 00032 struct subarray_tools 00033 { 00034 }; 00035 00036 template <class IT> 00037 struct subarray_tools<types::t_true, IT> 00038 { 00039 template <class A, class IDX> 00040 static IT begin(A& a, size_t dim, const IDX& i) 00041 { return a._iter(dim, i); } 00042 00043 template <class A> 00044 static IT rend_base(A& a, size_t dim) { return a._rend(dim).base(); } 00045 00046 template <class A> 00047 static IT end(A& a, size_t dim) { return a._end(dim); } 00048 00049 template <class A> 00050 static IT last(A& a, size_t dim) { return a._last(dim); } 00051 00052 template <class A> 00053 static IT //todo names.. 00054 iter(A& a, size_t dim, const IT& x) 00055 { return a._begin(dim, x); } 00056 00057 template <class A> 00058 static inline size_t stride(A& a, size_t dim) { return 1; } 00059 00060 }; 00061 00062 template <class IT> 00063 struct subarray_tools<types::t_false, IT> 00064 { 00065 template <class A, class IDX> 00066 static IT begin(A& a, size_t dim, const IDX& i) 00067 { return a.begin() + sub2ind(a, i); } 00068 00069 template <class A> 00070 static IT rend_base(A& a, size_t dim) { return a.rend().base(); } 00071 00072 template <class A> 00073 static IT end(A& a, size_t dim) { return a.end(); } 00074 00075 template <class A> 00076 static IT iter(A& a, size_t dim, const IT& x) { return x; } 00077 00078 template <class A> 00079 static inline size_t stride(A& a, size_t dim) { return a.stride(dim); } 00080 00081 }; 00082 00083 struct subarray_common_tools 00084 { 00085 struct add_op 00086 { 00087 template<class X, class Y> 00088 static inline void operate(X& a, const Y& b) { a += b; } 00089 }; 00090 struct sub_op 00091 { 00092 template<class X, class Y> 00093 static inline void operate(X& a, const Y& b) { a -= b; } 00094 }; 00095 00096 template<class OP, class IT> 00097 static inline void inc_along(IT& ir, const IT& d, 00098 const ptrdiff_t* diff, size_t pos, size_t str) 00099 { 00100 if(diff) 00101 ir.inc_along(d, diff[pos]); 00102 else 00103 ir.inc_along(d, str); 00104 }; 00105 00106 template<class OP, class IT> 00107 static inline void dec_along(IT& ir, const IT& d, 00108 const ptrdiff_t* diff, size_t pos, size_t str) 00109 { 00110 if(diff) 00111 ir.dec_along(d, diff[pos]); 00112 else 00113 ir.dec_along(d, str); 00114 }; 00115 00116 // TODO:: possible speed improvement is: 00117 // do not use pos0 at all in the array specialized case, and 00118 // use a ptrdiff_t + length as barrier. 00119 // make also a specialized function that controls the pos0++ and 00120 // the ending condition. 00121 // However, when copying from an iterator<2> to an iterator<0> 00122 // it will be needed to generate pos0 from diff0 - start_diff0_border 00123 // and to reset diff0 = start_diff0_border, and 00124 // when copying from an iterator<0> to an iterator<2> do: 00125 // diff0 += pos 00126 00127 template<int SP = 0> // generic case operator. slower 00128 struct inner_dim_adder 00129 { 00130 template<class OP, class IT> 00131 static inline void operate(IT& ir, const ptrdiff_t* diff0, 00132 size_t pos, size_t str) 00133 { 00134 if(diff0) 00135 OP::operate(ir, diff0[pos]); 00136 else 00137 OP::operate(ir, str); 00138 } 00139 }; 00140 }; 00141 00142 template<> 00143 struct subarray_common_tools::inner_dim_adder<1> // special case 1: index 0 is all or range. 00144 { 00145 template<class OP, class IT> 00146 static inline void operate(IT& ir, const ptrdiff_t* diff0, 00147 size_t pos, size_t str) 00148 { 00149 OP::operate(ir, str); 00150 } 00151 }; 00152 template<> 00153 struct subarray_common_tools::inner_dim_adder<2> // special case 2: index 0 is array. 00154 { 00155 template<class OP, class IT> 00156 static inline void operate(IT& ir, const ptrdiff_t* diff0, 00157 size_t pos, size_t str) 00158 { 00159 OP::operate(ir, diff0[pos]); 00160 } 00161 }; 00162 00163 }; /*namespace array_details*/ 00164 00165 }; /*namespace ivl*/ 00166 00167 00168 #endif // IVL_ARRAY_SPECIALIZATION_DETAILS_SUBARRAY_TOOLS_HPP