xref: /petsc/include/petscmath.h (revision 0646a658dcefdf4ee741d3bf5d8bdc3d39675ad7)
1 /*
2 
3       PETSc mathematics include file. Defines certain basic mathematical
4     constants and functions for working with single, double, and quad precision
5     floating point numbers as well as complex single and double.
6 
7     This file is included by petscsys.h and should not be used directly.
8 
9 */
10 
11 #if !defined(__PETSCMATH_H)
12 #define __PETSCMATH_H
13 #include <math.h>
14 
15 /*
16 
17      Defines operations that are different for complex and real numbers;
18    note that one cannot mix the use of complex and real in the same
19    PETSc program. All PETSc objects in one program are built around the object
20    PetscScalar which is either always a real or a complex.
21 
22 */
23 
24 #define PetscExpPassiveScalar(a) PetscExpScalar()
25 #if defined(PETSC_USE_REAL_SINGLE)
26 #define MPIU_REAL   MPI_FLOAT
27 typedef float PetscReal;
28 #define PetscSqrtReal(a)    sqrt(a)
29 #define PetscExpReal(a)     exp(a)
30 #define PetscLogReal(a)     log(a)
31 #define PetscSinReal(a)     sin(a)
32 #define PetscCosReal(a)     cos(a)
33 #define PetscASinReal(a)    asin(a)
34 #define PetscACosReal(a)    acos(a)
35 #define PetscPowReal(a,b)   pow(a,b)
36 #define PetscTGamma(a)      tgammaf(a)
37 #elif defined(PETSC_USE_REAL_DOUBLE)
38 #define MPIU_REAL   MPI_DOUBLE
39 typedef double PetscReal;
40 #define PetscSqrtReal(a)    sqrt(a)
41 #define PetscExpReal(a)     exp(a)
42 #define PetscLogReal(a)     log(a)
43 #define PetscSinReal(a)     sin(a)
44 #define PetscCosReal(a)     cos(a)
45 #define PetscASinReal(a)    asin(a)
46 #define PetscACosReal(a)    acos(a)
47 #define PetscPowReal(a,b)   pow(a,b)
48 #define PetscTGamma(a)      tgamma(a)
49 #elif defined(PETSC_USE_REAL___FLOAT128)
50 #if defined(__cplusplus)
51 extern "C" {
52 #endif
53 #include <quadmath.h>
54 #if defined(__cplusplus)
55 }
56 #endif
57 PETSC_EXTERN MPI_Datatype MPIU___FLOAT128 PetscAttrMPITypeTag(__float128);
58 #define MPIU_REAL MPIU___FLOAT128
59 typedef __float128 PetscReal;
60 #define PetscSqrtReal(a)    sqrtq(a)
61 #define PetscExpReal(a)     expq(a)
62 #define PetscLogReal(a)     logq(a)
63 #define PetscSinReal(a)     sinq(a)
64 #define PetscCosReal(a)     cosq(a)
65 #define PetscASinReal(a)    asinq(a)
66 #define PetscACosReal(a)    acosq(a)
67 #define PetscPowReal(a,b)   powq(a,b)
68 #define PetscTGamma(a)      tgammaq(a)
69 #endif /* PETSC_USE_REAL_* */
70 
71 /*
72     Complex number definitions
73  */
74 #if defined(PETSC_CLANGUAGE_CXX) && defined(PETSC_HAVE_CXX_COMPLEX) && !defined(PETSC_USE_REAL___FLOAT128)
75 #if defined(PETSC_USE_COMPLEX) || defined(PETSC_DESIRE_COMPLEX)
76 #define PETSC_HAVE_COMPLEX 1
77 /* C++ support of complex number */
78 #if defined(PETSC_HAVE_CUSP)
79 #define complexlib cusp
80 #include <cusp/complex.h>
81 #else
82 #define complexlib std
83 #include <complex>
84 #endif
85 
86 #define PetscRealPartComplex(a)      (a).real()
87 #define PetscImaginaryPartComplex(a) (a).imag()
88 #define PetscAbsComplex(a)           complexlib::abs(a)
89 #define PetscConjComplex(a)          complexlib::conj(a)
90 #define PetscSqrtComplex(a)          complexlib::sqrt(a)
91 #define PetscPowComplex(a,b)         complexlib::pow(a,b)
92 #define PetscExpComplex(a)           complexlib::exp(a)
93 #define PetscLogComplex(a)           complexlib::log(a)
94 #define PetscSinComplex(a)           complexlib::sin(a)
95 #define PetscCosComplex(a)           complexlib::cos(a)
96 #define PetscASinComplex(a)          complexlib::asin(a)
97 #define PetscACosComplex(a)          complexlib::acos(a)
98 
99 #if defined(PETSC_USE_REAL_SINGLE)
100 typedef complexlib::complex<float> PetscComplex;
101 #elif defined(PETSC_USE_REAL_DOUBLE)
102 typedef complexlib::complex<double> PetscComplex;
103 #elif defined(PETSC_USE_REAL___FLOAT128)
104 typedef complexlib::complex<__float128> PetscComplex; /* Notstandard and not expected to work, use __complex128 */
105 #endif  /* PETSC_USE_REAL_ */
106 #endif  /* PETSC_USE_COMPLEX || PETSC_DESIRE_COMPLEX */
107 
108 #elif defined(PETSC_CLANGUAGE_C) && defined(PETSC_HAVE_C99_COMPLEX)
109 /* Use C99 _Complex for the type. Do not include complex.h by default to define "complex" because of symbol conflicts in Hypre. */
110 /* Compilation units that can safely use complex should define PETSC_DESIRE_COMPLEX before including any headers */
111 #if defined(PETSC_USE_COMPLEX) || defined(PETSC_DESIRE_COMPLEX)
112 #define PETSC_HAVE_COMPLEX 1
113 #include <complex.h>
114 
115 #if defined(PETSC_USE_REAL_SINGLE)
116 typedef float _Complex PetscComplex;
117 
118 #define PetscRealPartComplex(a)      crealf(a)
119 #define PetscImaginaryPartComplex(a) cimagf(a)
120 #define PetscAbsComplex(a)           cabsf(a)
121 #define PetscConjComplex(a)          conjf(a)
122 #define PetscSqrtComplex(a)          csqrtf(a)
123 #define PetscPowComplex(a,b)         cpowf(a,b)
124 #define PetscExpComplex(a)           cexpf(a)
125 #define PetscLogComplex(a)           clogf(a)
126 #define PetscSinComplex(a)           csinf(a)
127 #define PetscCosComplex(a)           ccosf(a)
128 #define PetscASinComplex(a)          casinf(a)
129 #define PetscACosComplex(a)          cacosf(a)
130 
131 #elif defined(PETSC_USE_REAL_DOUBLE)
132 typedef double _Complex PetscComplex;
133 
134 #define PetscRealPartComplex(a)      creal(a)
135 #define PetscImaginaryPartComplex(a) cimag(a)
136 #define PetscAbsComplex(a)           cabs(a)
137 #define PetscConjComplex(a)          conj(a)
138 #define PetscSqrtComplex(a)          csqrt(a)
139 #define PetscPowComplex(a,b)         cpow(a,b)
140 #define PetscExpComplex(a)           cexp(a)
141 #define PetscLogComplex(a)           clog(a)
142 #define PetscSinComplex(a)           csin(a)
143 #define PetscCosComplex(a)           ccos(a)
144 #define PetscASinComplex(a)          casin(a)
145 #define PetscACosComplex(a)          cacos(a)
146 
147 #elif defined(PETSC_USE_REAL___FLOAT128)
148 typedef __complex128 PetscComplex;
149 PETSC_EXTERN MPI_Datatype MPIU___COMPLEX128 PetscAttrMPITypeTag(__complex128);
150 
151 #define PetscRealPartComplex(a)      crealq(a)
152 #define PetscImaginaryPartComplex(a) cimagq(a)
153 #define PetscAbsComplex(a)           cabsq(a)
154 #define PetscConjComplex(a)          conjq(a)
155 #define PetscSqrtComplex(a)          csqrtq(a)
156 #define PetscPowComplex(a,b)         cpowq(a,b)
157 #define PetscExpComplex(a)           cexpq(a)
158 #define PetscLogComplex(a)           clogq(a)
159 #define PetscSinComplex(a)           csinq(a)
160 #define PetscCosComplex(a)           ccosq(a)
161 #define PetscASinComplex(a)          casinq(a)
162 #define PetscACosComplex(a)          cacosq(a)
163 #endif /* PETSC_USE_REAL_* */
164 #elif defined(PETSC_USE_COMPLEX)
165 #error "PETSc was configured --with-scalar-type=complex, but a language-appropriate complex library is not available"
166 #endif /* PETSC_USE_COMPLEX || PETSC_DESIRE_COMPLEX */
167 #endif /* (PETSC_CLANGUAGE_CXX && PETSC_HAVE_CXX_COMPLEX) else-if (PETSC_CLANGUAGE_C && PETSC_HAVE_C99_COMPLEX) */
168 
169 #if defined(PETSC_HAVE_COMPLEX)
170 #if defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)
171 #define MPIU_C_DOUBLE_COMPLEX MPI_C_DOUBLE_COMPLEX
172 #define MPIU_C_COMPLEX MPI_C_COMPLEX
173 #else
174 # if defined(PETSC_CLANGUAGE_CXX) && defined(PETSC_HAVE_CXX_COMPLEX)
175   typedef complexlib::complex<double> petsc_mpiu_c_double_complex;
176   typedef complexlib::complex<float> petsc_mpiu_c_complex;
177 # elif defined(PETSC_CLANGUAGE_C) && defined(PETSC_HAVE_C99_COMPLEX)
178   typedef double _Complex petsc_mpiu_c_double_complex;
179   typedef float _Complex petsc_mpiu_c_complex;
180 # else
181   typedef struct {double real,imag;} petsc_mpiu_c_double_complex;
182   typedef struct {float real,imag;} petsc_mpiu_c_complex;
183 # endif
184 PETSC_EXTERN MPI_Datatype MPIU_C_DOUBLE_COMPLEX PetscAttrMPITypeTagLayoutCompatible(petsc_mpiu_c_double_complex);
185 PETSC_EXTERN MPI_Datatype MPIU_C_COMPLEX PetscAttrMPITypeTagLayoutCompatible(petsc_mpiu_c_complex);
186 #endif /* PETSC_HAVE_MPI_C_DOUBLE_COMPLEX */
187 #endif /* PETSC_HAVE_COMPLEX */
188 
189 #if defined(PETSC_HAVE_COMPLEX)
190 #  if defined(PETSC_USE_REAL_SINGLE)
191 #    define MPIU_COMPLEX MPIU_C_COMPLEX
192 #  elif defined(PETSC_USE_REAL_DOUBLE)
193 #    define MPIU_COMPLEX MPIU_C_DOUBLE_COMPLEX
194 #  elif defined(PETSC_USE_REAL___FLOAT128)
195 #    define MPIU_COMPLEX MPIU___COMPLEX128
196 #  endif /* PETSC_USE_REAL_* */
197 #endif
198 
199 #if defined(PETSC_USE_COMPLEX)
200 typedef PetscComplex PetscScalar;
201 #define PetscRealPart(a)      PetscRealPartComplex(a)
202 #define PetscImaginaryPart(a) PetscImaginaryPartComplex(a)
203 #define PetscAbsScalar(a)     PetscAbsComplex(a)
204 #define PetscConj(a)          PetscConjComplex(a)
205 #define PetscSqrtScalar(a)    PetscSqrtComplex(a)
206 #define PetscPowScalar(a,b)   PetscPowComplex(a,b)
207 #define PetscExpScalar(a)     PetscExpComplex(a)
208 #define PetscLogScalar(a)     PetscLogComplex(a)
209 #define PetscSinScalar(a)     PetscSinComplex(a)
210 #define PetscCosScalar(a)     PetscCosComplex(a)
211 #define PetscASinScalar(a)    PetscASinComplex(a)
212 #define PetscACosScalar(a)    PetscACosComplex(a)
213 
214 #define MPIU_SCALAR MPIU_COMPLEX
215 
216 /*
217     real number definitions
218  */
219 #else /* PETSC_USE_COMPLEX */
220 typedef PetscReal PetscScalar;
221 #define MPIU_SCALAR MPIU_REAL
222 
223 #define PetscRealPart(a)      (a)
224 #define PetscImaginaryPart(a) ((PetscReal)0.)
225 PETSC_STATIC_INLINE PetscReal PetscAbsScalar(PetscScalar a) {return a < 0.0 ? -a : a;}
226 #define PetscConj(a)          (a)
227 #if !defined(PETSC_USE_REAL___FLOAT128)
228 #define PetscSqrtScalar(a)    sqrt(a)
229 #define PetscPowScalar(a,b)   pow(a,b)
230 #define PetscExpScalar(a)     exp(a)
231 #define PetscLogScalar(a)     log(a)
232 #define PetscSinScalar(a)     sin(a)
233 #define PetscCosScalar(a)     cos(a)
234 #define PetscASinScalar(a)    asin(a)
235 #define PetscACosScalar(a)    acos(a)
236 #else /* PETSC_USE_REAL___FLOAT128 */
237 #define PetscSqrtScalar(a)    sqrtq(a)
238 #define PetscPowScalar(a,b)   powq(a,b)
239 #define PetscExpScalar(a)     expq(a)
240 #define PetscLogScalar(a)     logq(a)
241 #define PetscSinScalar(a)     sinq(a)
242 #define PetscCosScalar(a)     cosq(a)
243 #define PetscASinScalar(a)    asinq(a)
244 #define PetscACosScalar(a)    qcosq(a)
245 #endif /* PETSC_USE_REAL___FLOAT128 */
246 
247 #endif /* PETSC_USE_COMPLEX */
248 
249 #define PetscSign(a) (((a) >= 0) ? ((a) == 0 ? 0 : 1) : -1)
250 #define PetscAbs(a)  (((a) >= 0) ? (a) : -(a))
251 
252 /* --------------------------------------------------------------------------*/
253 
254 /*
255    Certain objects may be created using either single or double precision.
256    This is currently not used.
257 */
258 typedef enum { PETSC_SCALAR_DOUBLE,PETSC_SCALAR_SINGLE, PETSC_SCALAR_LONG_DOUBLE } PetscScalarPrecision;
259 
260 #if defined(PETSC_HAVE_COMPLEX)
261 /* PETSC_i is the imaginary number, i */
262 PETSC_EXTERN PetscComplex PETSC_i;
263 #endif
264 
265 /*MC
266    PetscMin - Returns minimum of two numbers
267 
268    Synopsis:
269    #include <petscmath.h>
270    type PetscMin(type v1,type v2)
271 
272    Not Collective
273 
274    Input Parameter:
275 +  v1 - first value to find minimum of
276 -  v2 - second value to find minimum of
277 
278 
279    Notes: type can be integer or floating point value
280 
281    Level: beginner
282 
283 
284 .seealso: PetscMin(), PetscClipInterval(), PetscAbsInt(), PetscAbsReal(), PetscSqr()
285 
286 M*/
287 #define PetscMin(a,b)   (((a)<(b)) ?  (a) : (b))
288 
289 /*MC
290    PetscMax - Returns maxium of two numbers
291 
292    Synopsis:
293    #include <petscmath.h>
294    type max PetscMax(type v1,type v2)
295 
296    Not Collective
297 
298    Input Parameter:
299 +  v1 - first value to find maximum of
300 -  v2 - second value to find maximum of
301 
302    Notes: type can be integer or floating point value
303 
304    Level: beginner
305 
306 .seealso: PetscMin(), PetscClipInterval(), PetscAbsInt(), PetscAbsReal(), PetscSqr()
307 
308 M*/
309 #define PetscMax(a,b)   (((a)<(b)) ?  (b) : (a))
310 
311 /*MC
312    PetscClipInterval - Returns a number clipped to be within an interval
313 
314    Synopsis:
315    #include <petscmath.h>
316    type clip PetscClipInterval(type x,type a,type b)
317 
318    Not Collective
319 
320    Input Parameter:
321 +  x - value to use if within interval (a,b)
322 .  a - lower end of interval
323 -  b - upper end of interval
324 
325    Notes: type can be integer or floating point value
326 
327    Level: beginner
328 
329 .seealso: PetscMin(), PetscMax(), PetscAbsInt(), PetscAbsReal(), PetscSqr()
330 
331 M*/
332 #define PetscClipInterval(x,a,b)   (PetscMax((a),PetscMin((x),(b))))
333 
334 /*MC
335    PetscAbsInt - Returns the absolute value of an integer
336 
337    Synopsis:
338    #include <petscmath.h>
339    int abs PetscAbsInt(int v1)
340 
341    Not Collective
342 
343    Input Parameter:
344 .   v1 - the integer
345 
346    Level: beginner
347 
348 .seealso: PetscMax(), PetscMin(), PetscAbsReal(), PetscSqr()
349 
350 M*/
351 #define PetscAbsInt(a)  (((a)<0)   ? -(a) : (a))
352 
353 /*MC
354    PetscAbsReal - Returns the absolute value of an real number
355 
356    Synopsis:
357    #include <petscmath.h>
358    Real abs PetscAbsReal(PetscReal v1)
359 
360    Not Collective
361 
362    Input Parameter:
363 .   v1 - the double
364 
365 
366    Level: beginner
367 
368 .seealso: PetscMax(), PetscMin(), PetscAbsInt(), PetscSqr()
369 
370 M*/
371 #define PetscAbsReal(a) (((a)<0)   ? -(a) : (a))
372 
373 /*MC
374    PetscSqr - Returns the square of a number
375 
376    Synopsis:
377    #include <petscmath.h>
378    type sqr PetscSqr(type v1)
379 
380    Not Collective
381 
382    Input Parameter:
383 .   v1 - the value
384 
385    Notes: type can be integer or floating point value
386 
387    Level: beginner
388 
389 .seealso: PetscMax(), PetscMin(), PetscAbsInt(), PetscAbsReal()
390 
391 M*/
392 #define PetscSqr(a)     ((a)*(a))
393 
394 /* ----------------------------------------------------------------------------*/
395 /*
396      Basic constants
397 */
398 #if defined(PETSC_USE_REAL___FLOAT128)
399 #define PETSC_PI                 M_PIq
400 #elif defined(M_PI)
401 #define PETSC_PI                 M_PI
402 #else
403 #define PETSC_PI                 3.14159265358979323846264338327950288419716939937510582
404 #endif
405 
406 #if !defined(PETSC_USE_64BIT_INDICES)
407 #define PETSC_MAX_INT            2147483647
408 #define PETSC_MIN_INT            (-PETSC_MAX_INT - 1)
409 #else
410 #define PETSC_MAX_INT            9223372036854775807L
411 #define PETSC_MIN_INT            (-PETSC_MAX_INT - 1)
412 #endif
413 
414 #if defined(PETSC_USE_REAL_SINGLE)
415 #  define PETSC_MAX_REAL                3.40282346638528860e+38F
416 #  define PETSC_MIN_REAL                -PETSC_MAX_REAL
417 #  define PETSC_MACHINE_EPSILON         1.19209290e-07F
418 #  define PETSC_SQRT_MACHINE_EPSILON    3.45266983e-04F
419 #  define PETSC_SMALL                   1.e-5
420 #elif defined(PETSC_USE_REAL_DOUBLE)
421 #  define PETSC_MAX_REAL                1.7976931348623157e+308
422 #  define PETSC_MIN_REAL                -PETSC_MAX_REAL
423 #  define PETSC_MACHINE_EPSILON         2.2204460492503131e-16
424 #  define PETSC_SQRT_MACHINE_EPSILON    1.490116119384766e-08
425 #  define PETSC_SMALL                   1.e-10
426 #elif defined(PETSC_USE_REAL___FLOAT128)
427 #  define PETSC_MAX_REAL                FLT128_MAX
428 #  define PETSC_MIN_REAL                -FLT128_MAX
429 #  define PETSC_MACHINE_EPSILON         FLT128_EPSILON
430 #  define PETSC_SQRT_MACHINE_EPSILON    1.38777878078e-17
431 #  define PETSC_SMALL                   1.e-20
432 #endif
433 
434 #define PETSC_INFINITY                PETSC_MAX_REAL/4.0
435 #define PETSC_NINFINITY              -PETSC_INFINITY
436 
437 PETSC_EXTERN PetscErrorCode PetscIsInfOrNanScalar(PetscScalar);
438 PETSC_EXTERN PetscErrorCode PetscIsInfOrNanReal(PetscReal);
439 PETSC_EXTERN PetscBool PetscIsNormalScalar(PetscScalar);
440 PETSC_EXTERN PetscBool PetscIsNormalReal(PetscReal);
441 
442 /* ----------------------------------------------------------------------------*/
443 #define PassiveReal   PetscReal
444 #define PassiveScalar PetscScalar
445 
446 /*
447     These macros are currently hardwired to match the regular data types, so there is no support for a different
448     MatScalar from PetscScalar. We left the MatScalar in the source just in case we use it again.
449  */
450 #define MPIU_MATSCALAR MPIU_SCALAR
451 typedef PetscScalar MatScalar;
452 typedef PetscReal MatReal;
453 
454 struct petsc_mpiu_2scalar {PetscScalar a,b;};
455 PETSC_EXTERN MPI_Datatype MPIU_2SCALAR PetscAttrMPITypeTagLayoutCompatible(struct petsc_mpiu_2scalar);
456 #if defined(PETSC_USE_64BIT_INDICES) || !defined(MPI_2INT)
457 struct petsc_mpiu_2int {PetscInt a,b;};
458 PETSC_EXTERN MPI_Datatype MPIU_2INT PetscAttrMPITypeTagLayoutCompatible(struct petsc_mpiu_2int);
459 #else
460 #define MPIU_2INT MPI_2INT
461 #endif
462 
463 PETSC_STATIC_INLINE PetscInt PetscPowInt(PetscInt base,PetscInt power) {
464   PetscInt result = 1;
465   while (power) {
466     if (power & 1) result *= base;
467     power >>= 1;
468     base *= base;
469   }
470   return result;
471 }
472 PETSC_STATIC_INLINE PetscReal PetscPowRealInt(PetscReal base,PetscInt power) {
473   PetscReal result = 1;
474   if (power < 0) {
475     power = -power;
476     if (base != 0.0) base  = 1./base;
477   }
478   while (power) {
479     if (power & 1) result *= base;
480     power >>= 1;
481     base *= base;
482   }
483   return result;
484 }
485 
486 PETSC_STATIC_INLINE PetscScalar PetscPowScalarInt(PetscScalar base,PetscInt power) {
487   PetscScalar result = 1;
488   if (power < 0) {
489     power = -power;
490     if (base != 0.0) base  = 1./base;
491   }
492   while (power) {
493     if (power & 1) result *= base;
494     power >>= 1;
495     base *= base;
496   }
497   return result;
498 }
499 
500 #endif
501