casacore
Loading...
Searching...
No Matches
Copy.h
Go to the documentation of this file.
1// # Copy.h: Copy objects from one C-style array to another.
2// # Copyright (C) 1994-1997,1999-2002,2005,2015
3// # Associated Universities, Inc. Washington DC, USA.
4// # National Astronomical Observatory of Japan
5// # 2-21-1, Osawa, Mitaka, Tokyo, 181-8588, Japan.
6// #
7// # This library is free software; you can redistribute it and/or modify it
8// # under the terms of the GNU Library General Public License as published by
9// # the Free Software Foundation; either version 2 of the License, or (at your
10// # option) any later version.
11// #
12// # This library is distributed in the hope that it will be useful, but WITHOUT
13// # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14// # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
15// # License for more details.
16// #
17// # You should have received a copy of the GNU Library General Public License
18// # along with this library; if not, write to the Free Software Foundation,
19// # Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
20// #
21// # Correspondence concerning AIPS++ should be addressed as follows:
22// # Internet email: casa-feedback@nrao.edu.
23// # Postal address: AIPS++ Project Office
24// # National Radio Astronomy Observatory
25// # 520 Edgemont Road
26// # Charlottesville, VA 22903-2475 USA
27
28#ifndef CASA_COPY_H
29#define CASA_COPY_H
30
31// # Includes
32#include <casacore/casa/aips.h>
33#include <casacore/casa/BasicSL/Complex.h>
34#include <algorithm>
35
36namespace casacore { // # NAMESPACE CASACORE - BEGIN
37
38// <summary>
39// Copy objects from one C-style array to another.
40// </summary>
41
42// <use visibility=export>
43// <reviewed reviewer="Friso Olnon" date="1995/03/14" tests="tCopy" demos="">
44// </reviewed>
45
46// <synopsis>
47// Objset is used to fill a C-style array of objects.
48//
49// Objcopy and objmove are used to copy objects from one place to
50// another. Optionally a stride can be supplied.
51//
52// The functions are equivalent to C's <src>memcpy</src> and
53// <src>memmove</src>.
54// When possible C++ standard library functions are used to implement them
55//
56// Similar to memcpy and memmove, the difference between objcopy
57// and objmove is that objmove takes account of an overlap of source and
58// destination. In general, objcopy is slighty (but only slighty) faster.
59// </synopsis>
60
61// <example>
62// Setting and copying arrays of built-in types:
63// <srcblock>
64// // Create int array of 4 elements
65// size_t size=4;
66// int* ia = new int[size];
67// // Initialize all elements to value 99
68// objset(ia, 99, size);
69// // Change all odd elements to 66 -> [99 66 99 66]
70// objset(ia+1, 66, 5, 2);
71//
72// // Create another 4-element int array
73// int* ia2 = new int[size];
74// // Copy array ia into array ia2 -> [99 66 99 66]
75// objmove(ia2, ia, size);
76// // Copy the even elements of ia to the odd elements of ia2
77// // -> [99 99 99 99]
78// objcopy(ia2+1, ia, size/2, 2, 2);
79// </srcblock>
80//
81// Setting and copying arrays of a randomly chosen type:
82// <srcblock>
83// // Create 4-element array of 3-element Block<int> objects
84// size_t size=4;
85// Block<int>* ta = new Block<int>[size];
86// Block<int> set(3);
87// // Initialize the array -> [[123][123][123][123]]
88// set[0] = 1; set[1] = 2; set[2] = 3;
89// objset(ta, set, size);
90// // Change odd Blocks to [777]-> [[123][777][123][777]]
91// set[0] = set[1] = set[2] = 7;
92// objset(ta + 1, set, size/2, 2);
93//
94// // Create another Block<int> array
95// Block<int>* ta2 = new Block<int>[size];
96// // Copy the even elements of ta to the first elements of ta2
97// // -> [[123][123]...]
98// objcopy(ta2, ta, size/2, 1, 2);
99// </srcblock>
100// </example>
101
102// <group name=throw>
103// Throw the various AipsErrors when incorrect arguments used
104void objthrowmv1(const void* to, const void* from, const size_t n);
105void objthrowmv2(const void* to, const void* from, const size_t n, const size_t toStride,
106 const size_t fromStride);
107void objthrowcp1(const void* to, const void* from, const size_t n);
108void objthrowcp2(const void* to, const void* from, const size_t n, const size_t toStride,
109 const size_t fromStride);
110void objthrowfl1(const void* to, const size_t n);
111void objthrowfl2(const void* to, const size_t n, const size_t toStride);
112// </group>
113
114// <summary> Test routines </summary>
115// <group name=test>
116// Test on how to handle the overlap in move
117void objtestmv(size_t& nLeft, size_t& startLeft, size_t& startRight, const void* to,
118 const void* from, const size_t n, const size_t toStride, const size_t fromStride,
119 const void* toPn, const void* fromPn, const size_t fromMto, const size_t toMfrom);
120// </group>
121
122// <summary> Copy methods </summary>
123// <group name=copy>
124// The general function to copy <src>n</src> objects from one place
125// to another if overlap between <src>to</src> and <src>from</src> fields
126// is possible. Strides may be specified, i.e. you may copy from every
127// <src>fromStride</src>-th position into every <src>toStride</src>-th
128// one.
129//
130// The function will call <src>std::copy()</src> when possible.
131// Objmove works correctly if the source and destination overlap in any way.
132//
133// An exception will be thrown if the source or the destination does not
134// exist (and <em>n</em> is non-zero) or if the strides are non-positive.
135// <thrown>
136// <li> AipsError
137// </thrown>
138//
139// <group>
140template <class T>
141void objmove(T* to, const T* from, size_t n) {
142 objthrowmv1(to, from, n);
143 (to < from || to >= from + n) ? std::copy(from, from + n, to)
144 : std::copy_backward(from, from + n, to + n);
145}
146template <class T>
147void objmove(T* to, const T* from, size_t n, size_t toStride, size_t fromStride) {
148 if (!n) return;
149 objthrowmv2(to, from, n, toStride, fromStride);
150 if (toStride * fromStride == 1) {
151 objmove(to, from, n);
152 return;
153 }
154 size_t nLeft, startLeft, startRight;
155 size_t fromMto = 0;
156 size_t toMfrom = 0;
157 if (toStride > fromStride && from > to)
158 fromMto = (from - to) / (toStride - fromStride);
159 else if (toStride < fromStride && from < to)
160 toMfrom = (to - from) / (fromStride - toStride);
161 objtestmv(nLeft, startLeft, startRight, to, from, n, toStride, fromStride, to + n * toStride,
162 from + n * fromStride, fromMto, toMfrom);
163 n -= nLeft;
164 if (nLeft) {
165 const T* fromPtr = from + startLeft * fromStride;
166 T* toPtr = to + startLeft * toStride;
167 while (nLeft--) {
168 *toPtr = *fromPtr;
169 fromPtr += fromStride;
170 toPtr += toStride;
171 };
172 };
173 // Do the moves from the right.
174 if (n) {
175 const T* fromPtr = from + startRight * fromStride;
176 T* toPtr = to + startRight * toStride;
177 while (n--) {
178 fromPtr -= fromStride;
179 toPtr -= toStride;
180 *toPtr = *fromPtr;
181 };
182 };
183}
184// </group>
185
186// The non-general function to copy <src>n</src> objects from one place
187// to another. Strides may be specified, i.e. you may copy from every
188// <src>fromStride</src>-th position into every <src>toStride</src>-th
189// one.
190//
191// Objcopy/objcopyctor does not take an overlap of source and destination into account.
192// Objmove should be used if that is an issue.
193//
194// Objcopyctor copy objects from <src>from</src> by calling copy constructor
195// on each element in <src>to</src>.
196//
197// An exception will be thrown if the source or the destination does not
198// exist or if the strides are non-positive.
199// <thrown>
200// <li> AipsError
201// </thrown>
202//
203// <group>
204template <class T>
205void objcopy(T* to, const T* from, size_t n) {
206 objthrowcp1(to, from, n);
207 std::copy(from, from + n, to);
208}
209template <class T>
210void objcopy(T* to, const T* from, size_t n, size_t toStride, size_t fromStride) {
211 objthrowcp2(to, from, n, toStride, fromStride);
212 while (n--) {
213 *to = *from;
214 to += toStride;
215 from += fromStride;
216 }
217}
218
219template <class T>
220void objcopyctor(T* to, const T* from, size_t n) {
221 objthrowcp1(to, from, n);
222 size_t i;
223 try {
224 for (i = 0; i < n; ++i) {
225 ::new (&to[i]) T(from[i]);
226 }
227 } catch (...) {
228 while (i > 0) { // roll back
229 to[--i].~T();
230 }
231 throw;
232 }
233}
234template <class T>
235void objcopyctor(T* to, const T* from, size_t n, size_t toStride, size_t fromStride) {
236 objthrowcp2(to, from, n, toStride, fromStride);
237 size_t i = 0;
238 try {
239 for (i = 0; i < n; ++i) {
240 ::new (to) T(*from);
241 to += toStride;
242 from += fromStride;
243 }
244 } catch (...) {
245 while (i > 0) { // roll back
246 --i;
247 to -= toStride;
248 to->~T();
249 }
250 throw;
251 }
252}
253// </group>
254
255// Fill <src>n</src> elements of an array of objects with the given
256// value, optionally with a stride. Note that the fillValue is passed
257// by value.
258//
259// An exception will be thrown if the destination array does not exist
260// or if the stride is non-positive.
261//
262// <thrown>
263// <li> AipsError
264// </thrown>
265//
266// <group>
267template <class T>
268void objset(T* to, const T fillValue, size_t n) {
269 objthrowfl1(to, n);
270 std::fill_n(to, n, fillValue);
271}
272
273template <class T>
274void objset(T* to, const T fillValue, size_t n, size_t toStride) {
275 objthrowfl2(to, n, toStride);
276 while (n--) {
277 *to = fillValue;
278 to += toStride;
279 };
280}
281
282// </group>
283
284// </group>
285
286} // namespace casacore
287
288#ifndef CASACORE_NO_AUTO_TEMPLATES
289#include <casacore/casa/Utilities/Copy.tcc>
290#endif // # CASACORE_NO_AUTO_TEMPLATES
291#endif
For temporary backward namespace compatibility, use casa as alias for casacore.
Definition mainpage.dox:28
void objcopyctor(T *to, const T *from, size_t n)
Definition Copy.h:220
void objcopy(T *to, const T *from, size_t n)
The non-general function to copy n objects from one place to another.
Definition Copy.h:205
void objset(T *to, const T fillValue, size_t n, size_t toStride)
Definition Copy.h:274
void objcopyctor(T *to, const T *from, size_t n, size_t toStride, size_t fromStride)
Definition Copy.h:235
void objmove(T *to, const T *from, size_t n)
The general function to copy n objects from one place to another if overlap between to and from field...
Definition Copy.h:141
void objset(T *to, const T fillValue, size_t n)
Fill n elements of an array of objects with the given value, optionally with a stride.
Definition Copy.h:268
void objcopy(T *to, const T *from, size_t n, size_t toStride, size_t fromStride)
Definition Copy.h:210
void objmove(T *to, const T *from, size_t n, size_t toStride, size_t fromStride)
Definition Copy.h:147
void objtestmv(size_t &nLeft, size_t &startLeft, size_t &startRight, const void *to, const void *from, const size_t n, const size_t toStride, const size_t fromStride, const void *toPn, const void *fromPn, const size_t fromMto, const size_t toMfrom)
Test on how to handle the overlap in move.
void objthrowmv1(const void *to, const void *from, const size_t n)
Throw the various AipsErrors when incorrect arguments used.
void objthrowcp1(const void *to, const void *from, const size_t n)
void objthrowfl1(const void *to, const size_t n)
void objthrowmv2(const void *to, const void *from, const size_t n, const size_t toStride, const size_t fromStride)
void objthrowfl2(const void *to, const size_t n, const size_t toStride)
void objthrowcp2(const void *to, const void *from, const size_t n, const size_t toStride, const size_t fromStride)