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