xref: /petsc/src/sys/utils/memc.c (revision 62903a643c6f3b806cfd2df6dfd11354dcefb6c2)
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 #else
100     memcpy((char*)(a),(char*)(b),n);
101 #endif
102   }
103   PetscFunctionReturn(0);
104 }
105 
106 #undef __FUNCT__
107 #define __FUNCT__ "PetscBitMemcpy"
108 /*@C
109    PetscBitMemcpy - Copies an amount of data. This can include bit data.
110 
111    Not Collective
112 
113    Input Parameters:
114 +  b - pointer to initial memory space
115 .  bi - offset of initial memory space (in elementary chunk sizes)
116 .  bs - length (in elementary chunk sizes) of space to copy
117 -  dtype - datatype, for example, PETSC_INT, PETSC_DOUBLE, PETSC_LOGICAL
118 
119    Output Parameters:
120 +  a - pointer to result memory space
121 -  ai - offset of result memory space (in elementary chunk sizes)
122 
123    Level: intermediate
124 
125    Note:
126    This routine is analogous to PetscMemcpy(), except when the data type is
127    PETSC_LOGICAL.
128 
129    Concepts: memory^comparing
130    Concepts: comparing^memory
131 
132 .seealso: PetscMemmove(), PetscMemcpy()
133 
134 @*/
135 PetscErrorCode PETSC_DLLEXPORT PetscBitMemcpy(void *a,PetscInt ai,const void *b,PetscInt bi,PetscInt bs,PetscDataType dtype)
136 {
137   char           *aa = (char *)a,*bb = (char *)b;
138   PetscInt       dsize;
139   PetscErrorCode ierr;
140 
141   PetscFunctionBegin;
142   if (bs > 0 && !b) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy from a null pointer");
143   if (bs > 0 && !a) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy to a null pointer");
144   if (dtype != PETSC_LOGICAL) {
145     ierr = PetscDataTypeGetSize(dtype,&dsize);CHKERRQ(ierr);
146     ierr = PetscMemcpy(aa+ai*dsize,bb+bi*dsize,bs*dsize);CHKERRQ(ierr);
147   } else {
148     PetscBT  at = (PetscBT) a;
149     PetscBT  bt = (PetscBT) b;
150     PetscInt i;
151     for (i=0; i<bs; i++) {
152       if (PetscBTLookup(bt,bi+i)) {ierr = PetscBTSet(at,ai+i);CHKERRQ(ierr);}
153       else                        {ierr = PetscBTClear(at,ai+i);CHKERRQ(ierr);}
154     }
155   }
156   PetscFunctionReturn(0);
157 }
158 
159 #undef __FUNCT__
160 #define __FUNCT__ "PetscMemzero"
161 /*@
162    PetscMemzero - Zeros the specified memory.
163 
164    Not Collective
165 
166    Input Parameters:
167 +  a - pointer to beginning memory location
168 -  n - length (in bytes) of memory to initialize
169 
170    Level: intermediate
171 
172    Compile Option:
173    PETSC_PREFER_BZERO - on certain machines (the IBM RS6000) the bzero() routine happens
174   to be faster than the memset() routine. This flag causes the bzero() routine to be used.
175 
176    Concepts: memory^zeroing
177    Concepts: zeroing^memory
178 
179 .seealso: PetscMemcpy()
180 @*/
181 PetscErrorCode PETSC_DLLEXPORT PetscMemzero(void *a,size_t n)
182 {
183   PetscFunctionBegin;
184   if (n > 0) {
185     if (!a) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to zero at a null pointer");
186 #if defined(PETSC_PREFER_ZERO_FOR_MEMZERO)
187     if (!(((long) a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
188       size_t      i,len = n/sizeof(PetscScalar);
189       PetscScalar *x = (PetscScalar*)a;
190       for (i=0; i<len; i++) x[i] = 0.0;
191     } else {
192 #elif defined(PETSC_PREFER_FORTRAN_FOR_MEMZERO)
193     if (!(((long) a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
194       PetscInt len = n/sizeof(PetscScalar);
195       fortranzero_(&len,(PetscScalar*)a);
196     } else {
197 #endif
198 #if defined(PETSC_PREFER_BZERO)
199       bzero((char *)a,n);
200 #else
201       memset((char*)a,0,n);
202 #endif
203 #if defined(PETSC_PREFER_ZERO_FOR_MEMZERO) || defined(PETSC_PREFER_FORTRAN_FOR_MEMZERO)
204     }
205 #endif
206   }
207   PetscFunctionReturn(0);
208 }
209 
210 #undef __FUNCT__
211 #define __FUNCT__ "PetscMemcmp"
212 /*@C
213    PetscMemcmp - Compares two byte streams in memory.
214 
215    Not Collective
216 
217    Input Parameters:
218 +  str1 - Pointer to the first byte stream
219 .  str2 - Pointer to the second byte stream
220 -  len  - The length of the byte stream
221          (both str1 and str2 are assumed to be of length len)
222 
223    Output Parameters:
224 .   e - PETSC_TRUE if equal else PETSC_FALSE.
225 
226    Level: intermediate
227 
228    Note:
229    This routine is anologous to memcmp()
230 @*/
231 PetscErrorCode PETSC_DLLEXPORT PetscMemcmp(const void *str1,const void *str2,size_t len,PetscTruth *e)
232 {
233   int r;
234 
235   PetscFunctionBegin;
236   if (len > 0 && !str1) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to compare at a null pointer");
237   if (len > 0 && !str2) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to compare at a null pointer");
238   r = memcmp((char *)str1,(char *)str2,len);
239   if (!r) *e = PETSC_TRUE;
240   else    *e = PETSC_FALSE;
241   PetscFunctionReturn(0);
242 }
243 
244 #undef __FUNCT__
245 #define __FUNCT__ "PetscMemmove"
246 /*@C
247    PetscMemmove - Copies n bytes, beginning at location b, to the space
248    beginning at location a. Copying  between regions that overlap will
249    take place correctly.
250 
251    Not Collective
252 
253    Input Parameters:
254 +  b - pointer to initial memory space
255 -  n - length (in bytes) of space to copy
256 
257    Output Parameter:
258 .  a - pointer to copy space
259 
260    Level: intermediate
261 
262    Note:
263    This routine is analogous to memmove().
264 
265    Concepts: memory^copying with overlap
266    Concepts: copying^memory with overlap
267 
268 .seealso: PetscMemcpy()
269 @*/
270 PetscErrorCode PETSC_DLLEXPORT PetscMemmove(void *a,void *b,size_t n)
271 {
272   PetscFunctionBegin;
273   if (n > 0 && !a) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy to null pointer");
274   if (n > 0 && !b) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy from a null pointer");
275 #if !defined(PETSC_HAVE_MEMMOVE)
276   if (a < b) {
277     if (a <= b - n) {
278       memcpy(a,b,n);
279     } else {
280       memcpy(a,b,(int)(b - a));
281       PetscMemmove(b,b + (int)(b - a),n - (int)(b - a));
282     }
283   }  else {
284     if (b <= a - n) {
285       memcpy(a,b,n);
286     } else {
287       memcpy(b + n,b + (n - (int)(a - b)),(int)(a - b));
288       PetscMemmove(a,b,n - (int)(a - b));
289     }
290   }
291 #else
292   memmove((char*)(a),(char*)(b),n);
293 #endif
294   PetscFunctionReturn(0);
295 }
296 
297 
298 
299 
300