00001 //# Copy.h: Copy objects from one C-style array to another. 00002 //# Copyright (C) 1994-1997,1999-2002,2005,2015 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# National Astronomical Observatory of Japan 00005 //# 2-21-1, Osawa, Mitaka, Tokyo, 181-8588, Japan. 00006 //# 00007 //# This library is free software; you can redistribute it and/or modify it 00008 //# under the terms of the GNU Library General Public License as published by 00009 //# the Free Software Foundation; either version 2 of the License, or (at your 00010 //# option) any later version. 00011 //# 00012 //# This library is distributed in the hope that it will be useful, but WITHOUT 00013 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00014 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00015 //# License for more details. 00016 //# 00017 //# You should have received a copy of the GNU Library General Public License 00018 //# along with this library; if not, write to the Free Software Foundation, 00019 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00020 //# 00021 //# Correspondence concerning AIPS++ should be addressed as follows: 00022 //# Internet email: aips2-request@nrao.edu. 00023 //# Postal address: AIPS++ Project Office 00024 //# National Radio Astronomy Observatory 00025 //# 520 Edgemont Road 00026 //# Charlottesville, VA 22903-2475 USA 00027 //# 00028 //# $Id$ 00029 00030 #ifndef CASA_COPY_H 00031 #define CASA_COPY_H 00032 00033 //# Includes 00034 #include <casacore/casa/aips.h> 00035 #include <casacore/casa/BasicSL/Complex.h> 00036 #include <algorithm> 00037 00038 namespace casacore { //# NAMESPACE CASACORE - BEGIN 00039 00040 // <summary> 00041 // Copy objects from one C-style array to another. 00042 // </summary> 00043 00044 // <use visibility=export> 00045 // <reviewed reviewer="Friso Olnon" date="1995/03/14" tests="tCopy" demos=""> 00046 // </reviewed> 00047 00048 // <synopsis> 00049 // Objset is used to fill a C-style array of objects. 00050 // 00051 // Objcopy and objmove are used to copy objects from one place to 00052 // another. Optionally a stride can be supplied. 00053 // 00054 // The functions are equivalent to C's <src>memcpy</src> and 00055 // <src>memmove</src>. 00056 // When possible C++ standard library functions are used to implement them 00057 // 00058 // Similar to memcpy and memmove, the difference between objcopy 00059 // and objmove is that objmove takes account of an overlap of source and 00060 // destination. In general, objcopy is slighty (but only slighty) faster. 00061 // </synopsis> 00062 00063 // <example> 00064 // Setting and copying arrays of built-in types: 00065 // <srcblock> 00066 // // Create int array of 4 elements 00067 // size_t size=4; 00068 // int* ia = new int[size]; 00069 // // Initialize all elements to value 99 00070 // objset(ia, 99, size); 00071 // // Change all odd elements to 66 -> [99 66 99 66] 00072 // objset(ia+1, 66, 5, 2); 00073 // 00074 // // Create another 4-element int array 00075 // int* ia2 = new int[size]; 00076 // // Copy array ia into array ia2 -> [99 66 99 66] 00077 // objmove(ia2, ia, size); 00078 // // Copy the even elements of ia to the odd elements of ia2 00079 // // -> [99 99 99 99] 00080 // objcopy(ia2+1, ia, size/2, 2, 2); 00081 // </srcblock> 00082 // 00083 // Setting and copying arrays of a randomly chosen type: 00084 // <srcblock> 00085 // // Create 4-element array of 3-element Block<int> objects 00086 // size_t size=4; 00087 // Block<int>* ta = new Block<int>[size]; 00088 // Block<int> set(3); 00089 // // Initialize the array -> [[123][123][123][123]] 00090 // set[0] = 1; set[1] = 2; set[2] = 3; 00091 // objset(ta, set, size); 00092 // // Change odd Blocks to [777]-> [[123][777][123][777]] 00093 // set[0] = set[1] = set[2] = 7; 00094 // objset(ta + 1, set, size/2, 2); 00095 // 00096 // // Create another Block<int> array 00097 // Block<int>* ta2 = new Block<int>[size]; 00098 // // Copy the even elements of ta to the first elements of ta2 00099 // // -> [[123][123]...] 00100 // objcopy(ta2, ta, size/2, 1, 2); 00101 // </srcblock> 00102 // </example> 00103 00104 // <group name=throw> 00105 // Throw the various AipsErrors when incorrect arguments used 00106 void objthrowmv1(const void *to, const void *from, const size_t n); 00107 void objthrowmv2(const void *to, const void *from, const size_t n, 00108 const size_t toStride, const size_t fromStride); 00109 void objthrowcp1(const void *to, const void *from, const size_t n); 00110 void objthrowcp2(const void *to, const void *from, const size_t n, 00111 const size_t toStride, const size_t fromStride); 00112 void objthrowfl1(const void *to, const size_t n); 00113 void objthrowfl2(const void *to, const size_t n, 00114 const size_t toStride); 00115 // </group> 00116 00117 // <summary> Test routines </summary> 00118 // <group name=test> 00119 // Test on how to handle the overlap in move 00120 void objtestmv(size_t &nLeft, size_t &startLeft, size_t &startRight, 00121 const void *to, const void *from, const size_t n, 00122 const size_t toStride, const size_t fromStride, 00123 const void *toPn, const void *fromPn, 00124 const size_t fromMto, const size_t toMfrom); 00125 // </group> 00126 00127 // <summary> Copy methods </summary> 00128 // <group name=copy> 00129 // The general function to copy <src>n</src> objects from one place 00130 // to another if overlap between <src>to</src> and <src>from</src> fields 00131 // is possible. Strides may be specified, i.e. you may copy from every 00132 // <src>fromStride</src>-th position into every <src>toStride</src>-th 00133 // one. 00134 // 00135 // The function will call <src>std::copy()</src> when possible. 00136 // Objmove works correctly if the source and destination overlap in any way. 00137 // 00138 // An exception will be thrown if the source or the destination does not 00139 // exist (and <em>n</em> is non-zero) or if the strides are non-positive. 00140 // <thrown> 00141 // <li> AipsError 00142 // </thrown> 00143 // 00144 // <group> 00145 template<class T> void objmove(T* to, const T* from, size_t n) { 00146 objthrowmv1(to,from,n); 00147 (to<from || to >= from+n) ? std::copy(from,from+n,to) 00148 : std::copy_backward(from,from+n,to+n); } 00149 template<class T> void objmove(T* to, const T* from, size_t n, 00150 size_t toStride, size_t fromStride) { 00151 if (!n) return; 00152 objthrowmv2(to,from,n,toStride,fromStride); 00153 if (toStride*fromStride == 1) { objmove(to, from, n); 00154 return; } 00155 size_t nLeft, startLeft, startRight; 00156 size_t fromMto=0; size_t toMfrom=0; 00157 if (toStride > fromStride && from > to) 00158 fromMto = (from-to)/(toStride-fromStride); 00159 else if (toStride < fromStride && from < to) 00160 toMfrom = (to-from)/(fromStride-toStride); 00161 objtestmv(nLeft, startLeft, startRight, to, from, n, 00162 toStride, fromStride, to+n*toStride, from+n*fromStride, 00163 fromMto, toMfrom); 00164 n -= nLeft; 00165 if (nLeft) { 00166 const T* fromPtr = from + startLeft*fromStride; 00167 T* toPtr = to + startLeft*toStride; 00168 while (nLeft--) { *toPtr = *fromPtr; 00169 fromPtr += fromStride; 00170 toPtr += toStride; }; }; 00171 // Do the moves from the right. 00172 if (n) { 00173 const T* fromPtr = from + startRight*fromStride; 00174 T* toPtr = to + startRight*toStride; 00175 while (n--) { fromPtr -= fromStride; toPtr -= toStride; 00176 *toPtr = *fromPtr; }; }; 00177 } 00178 // </group> 00179 00180 // The non-general function to copy <src>n</src> objects from one place 00181 // to another. Strides may be specified, i.e. you may copy from every 00182 // <src>fromStride</src>-th position into every <src>toStride</src>-th 00183 // one. 00184 // 00185 // Objcopy/objcopyctor does not take an overlap of source and destination into account. 00186 // Objmove should be used if that is an issue. 00187 // 00188 // Objcopyctor copy objects from <src>from</src> by calling copy constructor 00189 // on each element in <src>to</src>. 00190 // 00191 // An exception will be thrown if the source or the destination does not 00192 // exist or if the strides are non-positive. 00193 // <thrown> 00194 // <li> AipsError 00195 // </thrown> 00196 // 00197 // <group> 00198 template<class T> void objcopy(T* to, const T* from, size_t n) { 00199 objthrowcp1(to,from,n); std::copy(from, from+n, to); } 00200 template<class T> void objcopy(T* to, const T* from, size_t n, 00201 size_t toStride, size_t fromStride) { 00202 objthrowcp2(to,from,n,toStride,fromStride); while (n--) { 00203 *to = *from; to += toStride; from += fromStride; } } 00204 00205 template<class T> void objcopyctor(T* to, const T* from, size_t n) { 00206 objthrowcp1(to, from, n); 00207 size_t i; 00208 try { 00209 for (i = 0; i < n; ++i) { 00210 ::new (&to[i]) T(from[i]); 00211 } 00212 } catch (...) { 00213 while (i > 0) { // roll back 00214 to[--i].~T(); 00215 } 00216 throw; 00217 } 00218 } 00219 template<class T> void objcopyctor(T* to, const T* from, size_t n, 00220 size_t toStride, size_t fromStride) { 00221 objthrowcp2(to, from, n, toStride, fromStride); 00222 size_t i = 0; 00223 try { 00224 for (i = 0; i < n; ++i) { 00225 ::new (to) T(*from); 00226 to += toStride; 00227 from += fromStride; 00228 } 00229 } catch (...) { 00230 while (i > 0) { // roll back 00231 --i; 00232 to -= toStride; 00233 to->~T(); 00234 } 00235 throw; 00236 } 00237 } 00238 // </group> 00239 00240 // Fill <src>n</src> elements of an array of objects with the given 00241 // value, optionally with a stride. Note that the fillValue is passed 00242 // by value. 00243 // 00244 // An exception will be thrown if the destination array does not exist 00245 // or if the stride is non-positive. 00246 // 00247 // <thrown> 00248 // <li> AipsError 00249 // </thrown> 00250 // 00251 // <group> 00252 template<class T> void objset(T* to, const T fillValue, size_t n) { 00253 objthrowfl1(to,n); std::fill_n(to, n, fillValue); } 00254 00255 template<class T> void objset(T* to, const T fillValue, size_t n, 00256 size_t toStride) { 00257 objthrowfl2(to,n,toStride); 00258 while (n--){*to = fillValue; to += toStride; }; } 00259 00260 // </group> 00261 00262 // </group> 00263 00264 } //# NAMESPACE CASACORE - END 00265 00266 #ifndef CASACORE_NO_AUTO_TEMPLATES 00267 #include <casacore/casa/Utilities/Copy.tcc> 00268 #endif //# CASACORE_NO_AUTO_TEMPLATES 00269 #endif