Actual source code: memc.c

  1: /*$Id: memc.c,v 1.69 2001/09/07 20:08:33 bsmith Exp $*/

  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.

  8: */
 9:  #include petsc.h
 10:  #include src/inline/axpy.h

 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

 34: /*@C
 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.

 39:    Not Collective

 41:    Input Parameters:
 42: +  b - pointer to initial memory space
 43: -  n - length (in bytes) of space to copy

 45:    Output Parameter:
 46: .  a - pointer to copy space

 48:    Level: intermediate

 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.

 54:    Note:
 55:    This routine is analogous to memcpy().

 57:   Concepts: memory^copying
 58:   Concepts: copying^memory
 59:   
 60: .seealso: PetscMemmove()

 62: @*/
 63: int PetscMemcpy(void *a,const void *b,int n)
 64: {
 65:   unsigned long al = (unsigned long) a,bl = (unsigned long) b;
 66:   unsigned long nl = (unsigned long) n;

 69:   if (a != b) {
 70: #if !defined(PETSC_HAVE_CRAY90_POINTER)
 71:     if ((al > bl && (al - bl) < nl) || (bl - al) < nl) {
 72:       SETERRQ3(PETSC_ERR_ARG_INCOMP,"Memory regions overlap: either use PetscMemmov()\n\
 73:               or make sure your copy regions and lengths are correct. \n\
 74:               Length (bytes) %ld first address %ld second address %ld",nl,al,bl);
 75:     }
 76: #endif
 77: #if (defined(PETSC_PREFER_DCOPY_FOR_MEMCPY) || defined(PETSC_PREFER_COPY_FOR_MEMCPY) || defined(PETSC_PREFER_FORTRAN_FORMEMCPY))
 78:    if (!(((long) a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
 79:       int len = n/sizeof(PetscScalar);
 80: #if defined(PETSC_PREFER_DCOPY_FOR_MEMCPY)
 81:       int one = 1;
 82:       BLcopy_(&len,(PetscScalar *)b,&one,(PetscScalar *)a,&one);
 83: #elif defined(PETSC_PREFER_FORTRAN_FORMEMCPY)
 84:       fortrancopy_(&len,(PetscScalar*)b,(PetscScalar*)a);
 85: #else
 86:       int         i;
 87:       PetscScalar *x = (PetscScalar*)b, *y = (PetscScalar*)a;
 88:       for (i=0; i<len; i++) y[i] = x[i];
 89: #endif
 90:     } else {
 91:       memcpy((char*)(a),(char*)(b),n);
 92:     }
 93: #else
 94:     memcpy((char*)(a),(char*)(b),n);
 95: #endif
 96:   }
 97:   return(0);
 98: }

102: /*@C
103:    PetscBitMemcpy - Copies an amount of data. This can include bit data.

105:    Not Collective

107:    Input Parameters:
108: +  b - pointer to initial memory space
109: .  bi - offset of initial memory space (in elementary chunk sizes)
110: .  bs - length (in elementary chunk sizes) of space to copy
111: -  dtype - datatype, for example, PETSC_INT, PETSC_DOUBLE, PETSC_LOGICAL

113:    Output Parameters:
114: +  a - pointer to result memory space
115: -  ai - offset of result memory space (in elementary chunk sizes)

117:    Level: intermediate

119:    Note:
120:    This routine is analogous to PetscMemcpy(), except when the data type is 
121:    PETSC_LOGICAL.

123:    Concepts: memory^comparing
124:    Concepts: comparing^memory

126: .seealso: PetscMemmove(), PetscMemcpy()

128: @*/
129: int PetscBitMemcpy(void *a,int ai,const void *b,int bi,int bs,PetscDataType dtype)
130: {
131:   char *aa = (char *)a,*bb = (char *)b;
132:   int  dsize,ierr;

135:   if (dtype != PETSC_LOGICAL) {
136:     PetscDataTypeGetSize(dtype,&dsize);
137:     PetscMemcpy(aa+ai*dsize,bb+bi*dsize,bs*dsize);
138:   } else {
139:     PetscBT at = (PetscBT) a;
140:     PetscBT bt = (PetscBT) b;
141:     int i;
142:     for (i=0; i<bs; i++) {
143:       if (PetscBTLookup(bt,bi+i)) PetscBTSet(at,ai+i);
144:       else                        PetscBTClear(at,ai+i);
145:     }
146:   }
147:   return(0);
148: }

152: /*@C
153:    PetscMemzero - Zeros the specified memory.

155:    Not Collective

157:    Input Parameters:
158: +  a - pointer to beginning memory location
159: -  n - length (in bytes) of memory to initialize

161:    Level: intermediate

163:    Compile Option:
164:    PETSC_PREFER_BZERO - on certain machines (the IBM RS6000) the bzero() routine happens
165:   to be faster than the memset() routine. This flag causes the bzero() routine to be used.

167:    Concepts: memory^zeroing
168:    Concepts: zeroing^memory

170: .seealso: PetscMemcpy()
171: @*/
172: int PetscMemzero(void *a,int n)
173: {
175:   if (n < 0) SETERRQ(1,"Memory length must be >= 0");
176:   if (n > 0) {
177: #if defined(PETSC_PREFER_ZERO_FOR_MEMZERO)
178:     if (!(((long) a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
179:       int         i,len = n/sizeof(PetscScalar);
180:       PetscScalar *x = (PetscScalar*)a;
181:       for (i=0; i<len; i++) x[i] = 0.0;
182:     } else {
183: #elif defined(PETSC_PREFER_FORTRAN_FOR_MEMZERO)
184:     if (!(((long) a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
185:       int len = n/sizeof(PetscScalar);
186:       fortranzero_(&len,(PetscScalar*)a);
187:     } else {
188: #endif
189: #if defined(PETSC_PREFER_BZERO)
190:       bzero((char *)a,n);
191: #else
192:       memset((char*)a,0,n);
193: #endif
194: #if defined(PETSC_PREFER_ZERO_FOR_MEMZERO) || defined(PETSC_PREFER_FORTRAN_FOR_MEMZERO)
195:     }
196: #endif
197:   }
198:   return(0);
199: }

203: /*@C
204:    PetscMemcmp - Compares two byte streams in memory.

206:    Not Collective

208:    Input Parameters:
209: +  str1 - Pointer to the first byte stream
210: .  str2 - Pointer to the second byte stream
211: -  len  - The length of the byte stream
212:          (both str1 and str2 are assumed to be of length len)

214:    Output Parameters:
215: .   e - PETSC_TRUE if equal else PETSC_FALSE.

217:    Level: intermediate

219:    Note: 
220:    This routine is anologous to memcmp()
221: @*/
222: int PetscMemcmp(const void *str1,const void *str2,int len,PetscTruth *e)
223: {
224:   int r;

227:   r = memcmp((char *)str1,(char *)str2,len);
228:   if (!r) *e = PETSC_TRUE;
229:   else    *e = PETSC_FALSE;
230:   return(0);
231: }

235: /*@C
236:    PetscMemmove - Copies n bytes, beginning at location b, to the space
237:    beginning at location a. Copying  between regions that overlap will
238:    take place correctly.

240:    Not Collective

242:    Input Parameters:
243: +  b - pointer to initial memory space
244: -  n - length (in bytes) of space to copy

246:    Output Parameter:
247: .  a - pointer to copy space

249:    Level: intermediate

251:    Note:
252:    This routine is analogous to memmove().

254:    Contributed by: Matthew Knepley

256:    Concepts: memory^copying with overlap
257:    Concepts: copying^memory with overlap

259: .seealso: PetscMemcpy()
260: @*/
261: int PetscMemmove(void *a,void *b,int n)
262: {
264: #if !defined(PETSC_HAVE_MEMMOVE)
265:   if (a < b) {
266:     if (a <= b - n) {
267:       memcpy(a,b,n);
268:     } else {
269:       memcpy(a,b,(int)(b - a));
270:       PetscMemmove(b,b + (int)(b - a),n - (int)(b - a));
271:     }
272:   }  else {
273:     if (b <= a - n) {
274:       memcpy(a,b,n);
275:     } else {
276:       memcpy(b + n,b + (n - (int)(a - b)),(int)(a - b));
277:       PetscMemmove(a,b,n - (int)(a - b));
278:     }
279:   }
280: #else
281:   memmove((char*)(a),(char*)(b),n);
282: #endif
283:   return(0);
284: }