xref: /petsc/src/sys/utils/memc.c (revision e93bc3c11e430217b93e6c0883a78d39bef6c101)
1 #define PETSC_DLL
2 
3 /*
4     We define the memory operations here. The reason we just do not use
5   the standard memory routines in the PETSc code is that on some machines
6   they are broken.
7 
8 */
9 #include "petsc.h"        /*I  "petsc.h"   I*/
10 #include "src/inline/axpy.h"
11 
12 /*
13     On the IBM Rs6000 using the Gnu G++ compiler you may have to include
14   <string.h> instead of <memory.h>
15 */
16 #include <memory.h>
17 #if defined(PETSC_HAVE_STRINGS_H)
18 #include <strings.h>
19 #endif
20 #if defined(PETSC_HAVE_STRING_H)
21 #include <string.h>
22 #endif
23 #if defined(PETSC_HAVE_STDLIB_H)
24 #include <stdlib.h>
25 #endif
26 #include "petscfix.h"
27 #include "petscbt.h"
28 #if defined(PETSC_PREFER_DCOPY_FOR_MEMCPY)
29 #include "petscblaslapack.h"
30 #endif
31 
32 #undef __FUNCT__
33 #define __FUNCT__ "PetscMemcpy"
34 /*@
35    PetscMemcpy - Copies n bytes, beginning at location b, to the space
36    beginning at location a. The two memory regions CANNOT overlap, use
37    PetscMemmove() in that case.
38 
39    Not Collective
40 
41    Input Parameters:
42 +  b - pointer to initial memory space
43 -  n - length (in bytes) of space to copy
44 
45    Output Parameter:
46 .  a - pointer to copy space
47 
48    Level: intermediate
49 
50    Compile Option:
51     PETSC_PREFER_DCOPY_FOR_MEMCPY will cause the BLAS dcopy() routine to be used
52                                   for memory copies on double precision values.
53     PETSC_PREFER_COPY_FOR_MEMCPY will cause C code to be used
54                                   for memory copies on double precision values.
55     PETSC_PREFER_FORTRAN_FORMEMCPY will cause Fortran code to be used
56                                   for memory copies on double precision values.
57 
58    Note:
59    This routine is analogous to memcpy().
60 
61   Concepts: memory^copying
62   Concepts: copying^memory
63 
64 .seealso: PetscMemmove()
65 
66 @*/
67 PetscErrorCode PETSC_DLLEXPORT PetscMemcpy(void *a,const void *b,size_t n)
68 {
69   unsigned long al = (unsigned long) a,bl = (unsigned long) b;
70   unsigned long nl = (unsigned long) n;
71 
72   PetscFunctionBegin;
73   if (n > 0 && !b) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy from a null pointer");
74   if (n > 0 && !a) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy to a null pointer");
75   if (a != b) {
76 #if !defined(PETSC_HAVE_CRAY90_POINTER)
77     if ((al > bl && (al - bl) < nl) || (bl - al) < nl) {
78       SETERRQ3(PETSC_ERR_ARG_INCOMP,"Memory regions overlap: either use PetscMemmov()\n\
79               or make sure your copy regions and lengths are correct. \n\
80               Length (bytes) %ld first address %ld second address %ld",nl,al,bl);
81     }
82 #endif
83 #if (defined(PETSC_PREFER_DCOPY_FOR_MEMCPY) || defined(PETSC_PREFER_COPY_FOR_MEMCPY) || defined(PETSC_PREFER_FORTRAN_FORMEMCPY))
84    if (!(((long) a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
85       size_t len = n/sizeof(PetscScalar);
86 #if defined(PETSC_PREFER_DCOPY_FOR_MEMCPY)
87       PetscBLASInt blen = (PetscBLASInt) len,one = 1;
88       BLAScopy_(&blen,(PetscScalar *)b,&one,(PetscScalar *)a,&one);
89 #elif defined(PETSC_PREFER_FORTRAN_FORMEMCPY)
90       fortrancopy_(&len,(PetscScalar*)b,(PetscScalar*)a);
91 #else
92       size_t      i;
93       PetscScalar *x = (PetscScalar*)b, *y = (PetscScalar*)a;
94       for (i=0; i<len; i++) y[i] = x[i];
95 #endif
96     } else {
97       memcpy((char*)(a),(char*)(b),n);
98     }
99 #elif defined(PETSC_HAVE__INTEL_FAST_MEMCPY)
100     _intel_fast_memcpy((char*)(a),(char*)(b),n);
101 #else
102     memcpy((char*)(a),(char*)(b),n);
103 #endif
104   }
105   PetscFunctionReturn(0);
106 }
107 
108 #undef __FUNCT__
109 #define __FUNCT__ "PetscBitMemcpy"
110 /*@C
111    PetscBitMemcpy - Copies an amount of data. This can include bit data.
112 
113    Not Collective
114 
115    Input Parameters:
116 +  b - pointer to initial memory space
117 .  bi - offset of initial memory space (in elementary chunk sizes)
118 .  bs - length (in elementary chunk sizes) of space to copy
119 -  dtype - datatype, for example, PETSC_INT, PETSC_DOUBLE, PETSC_LOGICAL
120 
121    Output Parameters:
122 +  a - pointer to result memory space
123 -  ai - offset of result memory space (in elementary chunk sizes)
124 
125    Level: intermediate
126 
127    Note:
128    This routine is analogous to PetscMemcpy(), except when the data type is
129    PETSC_LOGICAL.
130 
131    Concepts: memory^comparing
132    Concepts: comparing^memory
133 
134 .seealso: PetscMemmove(), PetscMemcpy()
135 
136 @*/
137 PetscErrorCode PETSC_DLLEXPORT PetscBitMemcpy(void *a,PetscInt ai,const void *b,PetscInt bi,PetscInt bs,PetscDataType dtype)
138 {
139   char           *aa = (char *)a,*bb = (char *)b;
140   PetscInt       dsize;
141   PetscErrorCode ierr;
142 
143   PetscFunctionBegin;
144   if (bs > 0 && !b) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy from a null pointer");
145   if (bs > 0 && !a) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy to a null pointer");
146   if (dtype != PETSC_LOGICAL) {
147     ierr = PetscDataTypeGetSize(dtype,&dsize);CHKERRQ(ierr);
148     ierr = PetscMemcpy(aa+ai*dsize,bb+bi*dsize,bs*dsize);CHKERRQ(ierr);
149   } else {
150     PetscBT  at = (PetscBT) a;
151     PetscBT  bt = (PetscBT) b;
152     PetscInt i;
153     for (i=0; i<bs; i++) {
154       if (PetscBTLookup(bt,bi+i)) {ierr = PetscBTSet(at,ai+i);CHKERRQ(ierr);}
155       else                        {ierr = PetscBTClear(at,ai+i);CHKERRQ(ierr);}
156     }
157   }
158   PetscFunctionReturn(0);
159 }
160 
161 #undef __FUNCT__
162 #define __FUNCT__ "PetscMemzero"
163 /*@
164    PetscMemzero - Zeros the specified memory.
165 
166    Not Collective
167 
168    Input Parameters:
169 +  a - pointer to beginning memory location
170 -  n - length (in bytes) of memory to initialize
171 
172    Level: intermediate
173 
174    Compile Option:
175    PETSC_PREFER_BZERO - on certain machines (the IBM RS6000) the bzero() routine happens
176   to be faster than the memset() routine. This flag causes the bzero() routine to be used.
177 
178    Concepts: memory^zeroing
179    Concepts: zeroing^memory
180 
181 .seealso: PetscMemcpy()
182 @*/
183 PetscErrorCode PETSC_DLLEXPORT PetscMemzero(void *a,size_t n)
184 {
185   PetscFunctionBegin;
186   if (n > 0) {
187     if (!a) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to zero at a null pointer");
188 #if defined(PETSC_PREFER_ZERO_FOR_MEMZERO)
189     if (!(((long) a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
190       size_t      i,len = n/sizeof(PetscScalar);
191       PetscScalar *x = (PetscScalar*)a;
192       for (i=0; i<len; i++) x[i] = 0.0;
193     } else {
194 #elif defined(PETSC_PREFER_FORTRAN_FOR_MEMZERO)
195     if (!(((long) a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
196       PetscInt len = n/sizeof(PetscScalar);
197       fortranzero_(&len,(PetscScalar*)a);
198     } else {
199 #endif
200 #if defined(PETSC_PREFER_BZERO)
201       bzero((char *)a,n);
202 #elif defined (PETSC_HAVE__INTEL_FAST_MEMSET)
203       _intel_fast_memset((char*)a,0,n);
204 #else
205       memset((char*)a,0,n);
206 #endif
207 #if defined(PETSC_PREFER_ZERO_FOR_MEMZERO) || defined(PETSC_PREFER_FORTRAN_FOR_MEMZERO)
208     }
209 #endif
210   }
211   PetscFunctionReturn(0);
212 }
213 
214 #undef __FUNCT__
215 #define __FUNCT__ "PetscMemcmp"
216 /*@C
217    PetscMemcmp - Compares two byte streams in memory.
218 
219    Not Collective
220 
221    Input Parameters:
222 +  str1 - Pointer to the first byte stream
223 .  str2 - Pointer to the second byte stream
224 -  len  - The length of the byte stream
225          (both str1 and str2 are assumed to be of length len)
226 
227    Output Parameters:
228 .   e - PETSC_TRUE if equal else PETSC_FALSE.
229 
230    Level: intermediate
231 
232    Note:
233    This routine is anologous to memcmp()
234 @*/
235 PetscErrorCode PETSC_DLLEXPORT PetscMemcmp(const void *str1,const void *str2,size_t len,PetscTruth *e)
236 {
237   int r;
238 
239   PetscFunctionBegin;
240   if (len > 0 && !str1) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to compare at a null pointer");
241   if (len > 0 && !str2) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to compare at a null pointer");
242   r = memcmp((char *)str1,(char *)str2,len);
243   if (!r) *e = PETSC_TRUE;
244   else    *e = PETSC_FALSE;
245   PetscFunctionReturn(0);
246 }
247 
248 #undef __FUNCT__
249 #define __FUNCT__ "PetscMemmove"
250 /*@C
251    PetscMemmove - Copies n bytes, beginning at location b, to the space
252    beginning at location a. Copying  between regions that overlap will
253    take place correctly.
254 
255    Not Collective
256 
257    Input Parameters:
258 +  b - pointer to initial memory space
259 -  n - length (in bytes) of space to copy
260 
261    Output Parameter:
262 .  a - pointer to copy space
263 
264    Level: intermediate
265 
266    Note:
267    This routine is analogous to memmove().
268 
269    Concepts: memory^copying with overlap
270    Concepts: copying^memory with overlap
271 
272 .seealso: PetscMemcpy()
273 @*/
274 PetscErrorCode PETSC_DLLEXPORT PetscMemmove(void *a,void *b,size_t n)
275 {
276   PetscFunctionBegin;
277   if (n > 0 && !a) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy to null pointer");
278   if (n > 0 && !b) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy from a null pointer");
279 #if !defined(PETSC_HAVE_MEMMOVE)
280   if (a < b) {
281     if (a <= b - n) {
282       memcpy(a,b,n);
283     } else {
284       memcpy(a,b,(int)(b - a));
285       PetscMemmove(b,b + (int)(b - a),n - (int)(b - a));
286     }
287   }  else {
288     if (b <= a - n) {
289       memcpy(a,b,n);
290     } else {
291       memcpy(b + n,b + (n - (int)(a - b)),(int)(a - b));
292       PetscMemmove(a,b,n - (int)(a - b));
293     }
294   }
295 #else
296   memmove((char*)(a),(char*)(b),n);
297 #endif
298   PetscFunctionReturn(0);
299 }
300 
301 
302 
303 
304