Actual source code: petscmath.h
petsc-3.10.5 2019-03-28
Report Typos and Errors

      1: /*

      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.

      7:     This file is included by petscsys.h and should not be used directly.

      9: */

     13: #include <math.h>

     15: /*

     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.

     22: */

     24: #if defined(PETSC_USE_REAL_SINGLE)
     25: #define MPIU_REAL   MPI_FLOAT
     26: typedef float PetscReal;
     27: #define PetscRoundReal(a)   roundf(a)
     28: #define PetscSqrtReal(a)    sqrtf(a)
     29: #define PetscExpReal(a)     expf(a)
     30: #define PetscLogReal(a)     logf(a)
     31: #define PetscLog10Real(a)   log10f(a)
     32: #ifdef PETSC_HAVE_LOG2
     33: #define PetscLog2Real(a)    log2f(a)
     34: #endif
     35: #define PetscSinReal(a)     sinf(a)
     36: #define PetscCosReal(a)     cosf(a)
     37: #define PetscTanReal(a)     tanf(a)
     38: #define PetscAsinReal(a)    asinf(a)
     39: #define PetscAcosReal(a)    acosf(a)
     40: #define PetscAtanReal(a)    atanf(a)
     41: #define PetscAtan2Real(a,b) atan2f(a,b)
     42: #define PetscSinhReal(a)    sinhf(a)
     43: #define PetscCoshReal(a)    coshf(a)
     44: #define PetscTanhReal(a)    tanhf(a)
     45: #define PetscPowReal(a,b)   powf(a,b)
     46: #define PetscCeilReal(a)    ceilf(a)
     47: #define PetscFloorReal(a)   floorf(a)
     48: #define PetscFmodReal(a,b)  fmodf(a,b)
     49: #define PetscTGamma(a)      tgammaf(a)
     50: #elif defined(PETSC_USE_REAL_DOUBLE)
     51: #define MPIU_REAL   MPI_DOUBLE
     52: typedef double PetscReal;
     53: #define PetscRoundReal(a)   round(a)
     54: #define PetscSqrtReal(a)    sqrt(a)
     55: #define PetscExpReal(a)     exp(a)
     56: #define PetscLogReal(a)     log(a)
     57: #define PetscLog10Real(a)   log10(a)
     58: #ifdef PETSC_HAVE_LOG2
     59: #define PetscLog2Real(a)    log2(a)
     60: #endif
     61: #define PetscSinReal(a)     sin(a)
     62: #define PetscCosReal(a)     cos(a)
     63: #define PetscTanReal(a)     tan(a)
     64: #define PetscAsinReal(a)    asin(a)
     65: #define PetscAcosReal(a)    acos(a)
     66: #define PetscAtanReal(a)    atan(a)
     67: #define PetscAtan2Real(a,b) atan2(a,b)
     68: #define PetscSinhReal(a)    sinh(a)
     69: #define PetscCoshReal(a)    cosh(a)
     70: #define PetscTanhReal(a)    tanh(a)
     71: #define PetscPowReal(a,b)   pow(a,b)
     72: #define PetscCeilReal(a)    ceil(a)
     73: #define PetscFloorReal(a)   floor(a)
     74: #define PetscFmodReal(a,b)  fmod(a,b)
     75: #define PetscTGamma(a)      tgamma(a)
     76: #elif defined(PETSC_USE_REAL___FLOAT128)
     77: #if defined(__cplusplus)
     78: extern "C" {
     79: #endif
     80: #include <quadmath.h>
     81: #if defined(__cplusplus)
     82: }
     83: #endif
     84: PETSC_EXTERN MPI_Datatype MPIU___FLOAT128 PetscAttrMPITypeTag(__float128);
     85: #define MPIU_REAL MPIU___FLOAT128
     86: typedef __float128 PetscReal;
     87: #define PetscRoundReal(a)   roundq(a)
     88: #define PetscSqrtReal(a)    sqrtq(a)
     89: #define PetscExpReal(a)     expq(a)
     90: #define PetscLogReal(a)     logq(a)
     91: #define PetscLog10Real(a)   log10q(a)
     92: #ifdef PETSC_HAVE_LOG2
     93: #define PetscLog2Real(a)    log2q(a)
     94: #endif
     95: #define PetscSinReal(a)     sinq(a)
     96: #define PetscCosReal(a)     cosq(a)
     97: #define PetscTanReal(a)     tanq(a)
     98: #define PetscAsinReal(a)    asinq(a)
     99: #define PetscAcosReal(a)    acosq(a)
    100: #define PetscAtanReal(a)    atanq(a)
    101: #define PetscAtan2Real(a,b) atan2q(a,b)
    102: #define PetscSinhReal(a)    sinhq(a)
    103: #define PetscCoshReal(a)    coshq(a)
    104: #define PetscTanhReal(a)    tanhq(a)
    105: #define PetscPowReal(a,b)   powq(a,b)
    106: #define PetscCeilReal(a)    ceilq(a)
    107: #define PetscFloorReal(a)   floorq(a)
    108: #define PetscFmodReal(a,b)  fmodq(a,b)
    109: #define PetscTGamma(a)      tgammaq(a)
    110: #elif defined(PETSC_USE_REAL___FP16)
    111: PETSC_EXTERN MPI_Datatype MPIU___FP16 PetscAttrMPITypeTag(__fp16);
    112: #define MPIU_REAL MPIU___FP16
    113: typedef __fp16 PetscReal;
    114: #define PetscRoundReal(a)   roundf(a)
    115: #define PetscSqrtReal(a)    sqrtf(a)
    116: #define PetscExpReal(a)     expf(a)
    117: #define PetscLogReal(a)     logf(a)
    118: #define PetscLog10Real(a)   log10f(a)
    119: #ifdef PETSC_HAVE_LOG2
    120: #define PetscLog2Real(a)    log2f(a)
    121: #endif
    122: #define PetscSinReal(a)     sinf(a)
    123: #define PetscCosReal(a)     cosf(a)
    124: #define PetscTanReal(a)     tanf(a)
    125: #define PetscAsinReal(a)    asinf(a)
    126: #define PetscAcosReal(a)    acosf(a)
    127: #define PetscAtanReal(a)    atanf(a)
    128: #define PetscAtan2Real(a,b) atan2f(a,b)
    129: #define PetscSinhReal(a)    sinhf(a)
    130: #define PetscCoshReal(a)    coshf(a)
    131: #define PetscTanhReal(a)    tanhf(a)
    132: #define PetscPowReal(a,b)   powf(a,b)
    133: #define PetscCeilReal(a)    ceilf(a)
    134: #define PetscFloorReal(a)   floorf(a)
    135: #define PetscFmodReal(a,b)  fmodf(a,b)
    136: #define PetscTGamma(a)      tgammaf(a)
    137: #endif /* PETSC_USE_REAL_* */

    139: /*
    140:     Complex number definitions
    141:  */
    142: #if defined(__cplusplus) && defined(PETSC_HAVE_CXX_COMPLEX) && !defined(PETSC_USE_REAL___FLOAT128)
    143: #if !defined(PETSC_SKIP_COMPLEX)
    144: #define PETSC_HAVE_COMPLEX 1
    145: /* C++ support of complex number */
    146: #if defined(PETSC_HAVE_VECCUDA) && __CUDACC_VER_MAJOR__ > 6
    147: /* complex headers in thrust only available in CUDA 7.0 and above */
    148: #define complexlib thrust
    149: #include <thrust/complex.h>
    150: #else
    151: #define complexlib std
    152: #include <complex>
    153: #endif

    155: #define PetscRealPartComplex(a)      (a).real()
    156: #define PetscImaginaryPartComplex(a) (a).imag()
    157: #define PetscAbsComplex(a)           complexlib::abs(a)
    158: #define PetscConjComplex(a)          complexlib::conj(a)
    159: #define PetscSqrtComplex(a)          complexlib::sqrt(a)
    160: #define PetscPowComplex(a,b)         complexlib::pow(a,b)
    161: #define PetscExpComplex(a)           complexlib::exp(a)
    162: #define PetscLogComplex(a)           complexlib::log(a)
    163: #define PetscSinComplex(a)           complexlib::sin(a)
    164: #define PetscCosComplex(a)           complexlib::cos(a)
    165: #define PetscAsinComplex(a)          complexlib::asin(a)
    166: #define PetscAcosComplex(a)          complexlib::acos(a)
    167: #if defined(PETSC_HAVE_TANCOMPLEX)
    168: #define PetscTanComplex(a)           complexlib::tan(a)
    169: #else
    170: #define PetscTanComplex(a)           PetscSinComplex(a)/PetscCosComplex(a)
    171: #endif
    172: #define PetscSinhComplex(a)          complexlib::sinh(a)
    173: #define PetscCoshComplex(a)          complexlib::cosh(a)
    174: #if defined(PETSC_HAVE_TANHCOMPLEX)
    175: #define PetscTanhComplex(a)          complexlib::tanh(a)
    176: #else
    177: #define PetscTanhComplex(a)          PetscSinhComplex(a)/PetscCoshComplex(a)
    178: #endif

    180: #if defined(PETSC_USE_REAL_SINGLE)
    181: typedef complexlib::complex<float> PetscComplex;
    182: #if defined(PETSC_USE_CXX_COMPLEX_FLOAT_WORKAROUND)
    183: static inline PetscComplex operator+(const PetscComplex& lhs, const double& rhs) { return lhs + float(rhs); }
    184: static inline PetscComplex operator+(const double& lhs, const PetscComplex& rhs) { return float(lhs) + rhs; }
    185: static inline PetscComplex operator-(const PetscComplex& lhs, const double& rhs) { return lhs - float(rhs); }
    186: static inline PetscComplex operator-(const double& lhs, const PetscComplex& rhs) { return float(lhs) - rhs; }
    187: static inline PetscComplex operator*(const PetscComplex& lhs, const double& rhs) { return lhs * float(rhs); }
    188: static inline PetscComplex operator*(const double& lhs, const PetscComplex& rhs) { return float(lhs) * rhs; }
    189: static inline PetscComplex operator/(const PetscComplex& lhs, const double& rhs) { return lhs / float(rhs); }
    190: static inline PetscComplex operator/(const double& lhs, const PetscComplex& rhs) { return float(lhs) / rhs; }
    191: static inline bool operator==(const PetscComplex& lhs, const double& rhs) { return lhs.imag() == float(0) && lhs.real() == float(rhs); }
    192: static inline bool operator==(const double& lhs, const PetscComplex& rhs) { return rhs.imag() == float(0) && rhs.real() == float(lhs); }
    193: static inline bool operator!=(const PetscComplex& lhs, const double& rhs) { return lhs.imag() != float(0) || lhs.real() != float(rhs); }
    194: static inline bool operator!=(const double& lhs, const PetscComplex& rhs) { return rhs.imag() != float(0) || rhs.real() != float(lhs); }
    195: #endif  /* PETSC_USE_CXX_COMPLEX_FLOAT_WORKAROUND */
    196: #elif defined(PETSC_USE_REAL_DOUBLE)
    197: typedef complexlib::complex<double> PetscComplex;
    198: #if defined(PETSC_USE_CXX_COMPLEX_FLOAT_WORKAROUND)
    199: static inline PetscComplex operator+(const PetscComplex& lhs, const PetscInt& rhs) { return lhs + double(rhs); }
    200: static inline PetscComplex operator+(const PetscInt& lhs, const PetscComplex& rhs) { return double(lhs) + rhs; }
    201: static inline PetscComplex operator-(const PetscComplex& lhs, const PetscInt& rhs) { return lhs - double(rhs); }
    202: static inline PetscComplex operator-(const PetscInt& lhs, const PetscComplex& rhs) { return double(lhs) - rhs; }
    203: static inline PetscComplex operator*(const PetscComplex& lhs, const PetscInt& rhs) { return lhs * double(rhs); }
    204: static inline PetscComplex operator*(const PetscInt& lhs, const PetscComplex& rhs) { return double(lhs) * rhs; }
    205: static inline PetscComplex operator/(const PetscComplex& lhs, const PetscInt& rhs) { return lhs / double(rhs); }
    206: static inline PetscComplex operator/(const PetscInt& lhs, const PetscComplex& rhs) { return double(lhs) / rhs; }
    207: static inline bool operator==(const PetscComplex& lhs, const PetscInt& rhs) { return lhs.imag() == double(0) && lhs.real() == double(rhs); }
    208: static inline bool operator==(const PetscInt& lhs, const PetscComplex& rhs) { return rhs.imag() == double(0) && rhs.real() == double(lhs); }
    209: static inline bool operator!=(const PetscComplex& lhs, const PetscInt& rhs) { return lhs.imag() != double(0) || lhs.real() != double(rhs); }
    210: static inline bool operator!=(const PetscInt& lhs, const PetscComplex& rhs) { return rhs.imag() != double(0) || rhs.real() != double(lhs); }
    211: #endif  /* PETSC_USE_CXX_COMPLEX_FLOAT_WORKAROUND */
    212: #elif defined(PETSC_USE_REAL___FLOAT128)
    213: typedef complexlib::complex<__float128> PetscComplex; /* Notstandard and not expected to work, use __complex128 */
    214: PETSC_EXTERN MPI_Datatype MPIU___COMPLEX128;
    215: #endif  /* PETSC_USE_REAL_ */
    216: #endif  /* ! PETSC_SKIP_COMPLEX */

    218: #elif defined(PETSC_HAVE_C99_COMPLEX) && !defined(PETSC_USE_REAL___FP16)
    219: #if !defined(PETSC_SKIP_COMPLEX)
    220: #define PETSC_HAVE_COMPLEX 1
    221: #include <complex.h>

    223: #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL___FP16)
    224: typedef float _Complex PetscComplex;

    226: #define PetscRealPartComplex(a)      crealf(a)
    227: #define PetscImaginaryPartComplex(a) cimagf(a)
    228: #define PetscAbsComplex(a)           cabsf(a)
    229: #define PetscConjComplex(a)          conjf(a)
    230: #define PetscSqrtComplex(a)          csqrtf(a)
    231: #define PetscPowComplex(a,b)         cpowf(a,b)
    232: #define PetscExpComplex(a)           cexpf(a)
    233: #define PetscLogComplex(a)           clogf(a)
    234: #define PetscSinComplex(a)           csinf(a)
    235: #define PetscCosComplex(a)           ccosf(a)
    236: #define PetscAsinComplex(a)          casinf(a)
    237: #define PetscAcosComplex(a)          cacosf(a)
    238: #define PetscTanComplex(a)           ctanf(a)
    239: #define PetscSinhComplex(a)          csinhf(a)
    240: #define PetscCoshComplex(a)          ccoshf(a)
    241: #define PetscTanhComplex(a)          ctanhf(a)

    243: #elif defined(PETSC_USE_REAL_DOUBLE)
    244: typedef double _Complex PetscComplex;

    246: #define PetscRealPartComplex(a)      creal(a)
    247: #define PetscImaginaryPartComplex(a) cimag(a)
    248: #define PetscAbsComplex(a)           cabs(a)
    249: #define PetscConjComplex(a)          conj(a)
    250: #define PetscSqrtComplex(a)          csqrt(a)
    251: #define PetscPowComplex(a,b)         cpow(a,b)
    252: #define PetscExpComplex(a)           cexp(a)
    253: #define PetscLogComplex(a)           clog(a)
    254: #define PetscSinComplex(a)           csin(a)
    255: #define PetscCosComplex(a)           ccos(a)
    256: #define PetscAsinComplex(a)          casin(a)
    257: #define PetscAcosComplex(a)          cacos(a)
    258: #define PetscTanComplex(a)           ctan(a)
    259: #define PetscSinhComplex(a)          csinh(a)
    260: #define PetscCoshComplex(a)          ccosh(a)
    261: #define PetscTanhComplex(a)          ctanh(a)

    263: #elif defined(PETSC_USE_REAL___FLOAT128)
    264: typedef __complex128 PetscComplex;
    265: PETSC_EXTERN MPI_Datatype MPIU___COMPLEX128 PetscAttrMPITypeTag(__complex128);

    267: #define PetscRealPartComplex(a)      crealq(a)
    268: #define PetscImaginaryPartComplex(a) cimagq(a)
    269: #define PetscAbsComplex(a)           cabsq(a)
    270: #define PetscConjComplex(a)          conjq(a)
    271: #define PetscSqrtComplex(a)          csqrtq(a)
    272: #define PetscPowComplex(a,b)         cpowq(a,b)
    273: #define PetscExpComplex(a)           cexpq(a)
    274: #define PetscLogComplex(a)           clogq(a)
    275: #define PetscSinComplex(a)           csinq(a)
    276: #define PetscCosComplex(a)           ccosq(a)
    277: #define PetscAsinComplex(a)          casinq(a)
    278: #define PetscAcosComplex(a)          cacosq(a)
    279: #define PetscTanComplex(a)           ctanq(a)
    280: #define PetscSinhComplex(a)          csinhq(a)
    281: #define PetscCoshComplex(a)          ccoshq(a)
    282: #define PetscTanhComplex(a)          ctanhq(a)

    284: #endif /* PETSC_USE_REAL_* */
    285: #elif (defined(PETSC_USE_COMPLEX) && !defined(PETSC_SKIP_COMPLEX))
    286: #error "PETSc was configured --with-scalar-type=complex, but a language-appropriate complex library is not available"
    287: #endif /* !PETSC_SKIP_COMPLEX */
    288: #endif /* (__cplusplus && PETSC_HAVE_CXX_COMPLEX) else-if (!__cplusplus && PETSC_HAVE_C99_COMPLEX) */

    290: #if defined(PETSC_HAVE_COMPLEX)
    291: #if defined(PETSC_HAVE_MPI_C_DOUBLE_COMPLEX)
    292: #define MPIU_C_DOUBLE_COMPLEX MPI_C_DOUBLE_COMPLEX
    293: #define MPIU_C_COMPLEX MPI_C_COMPLEX
    294: #else
    295: # if defined(__cplusplus) && defined(PETSC_HAVE_CXX_COMPLEX) && !defined(PETSC_USE_REAL___FLOAT128)
    296:   typedef complexlib::complex<double> petsc_mpiu_c_double_complex;
    297:   typedef complexlib::complex<float> petsc_mpiu_c_complex;
    298: # elif !defined(__cplusplus) && defined(PETSC_HAVE_C99_COMPLEX)
    299:   typedef double _Complex petsc_mpiu_c_double_complex;
    300:   typedef float _Complex petsc_mpiu_c_complex;
    301: # else
    302:   typedef struct {double real,imag;} petsc_mpiu_c_double_complex;
    303:   typedef struct {float real,imag;} petsc_mpiu_c_complex;
    304: # endif
    305: PETSC_EXTERN MPI_Datatype MPIU_C_DOUBLE_COMPLEX PetscAttrMPITypeTagLayoutCompatible(petsc_mpiu_c_double_complex);
    306: PETSC_EXTERN MPI_Datatype MPIU_C_COMPLEX PetscAttrMPITypeTagLayoutCompatible(petsc_mpiu_c_complex);
    307: #endif /* PETSC_HAVE_MPI_C_DOUBLE_COMPLEX */
    308: #endif /* PETSC_HAVE_COMPLEX */

    310: #if defined(PETSC_HAVE_COMPLEX)
    311: #  if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL___FP16)
    312: #    define MPIU_COMPLEX MPIU_C_COMPLEX
    313: #  elif defined(PETSC_USE_REAL_DOUBLE)
    314: #    define MPIU_COMPLEX MPIU_C_DOUBLE_COMPLEX
    315: #  elif defined(PETSC_USE_REAL___FLOAT128)
    316: #    define MPIU_COMPLEX MPIU___COMPLEX128
    317: #  endif /* PETSC_USE_REAL_* */
    318: #endif

    320: #if (defined(PETSC_USE_COMPLEX) && !defined(PETSC_SKIP_COMPLEX))
    321: typedef PetscComplex PetscScalar;

    323: /*MC
    324:    PetscRealPart - Returns the real part of a PetscScalar

    326:    Synopsis:
    327:    #include <petscmath.h>
    328:    PetscScalar PetscRealPart(PetscScalar v)

    330:    Not Collective

    332:    Input Parameter:
    333: .  v - value to find the real part of

    335:    Level: beginner

    337: .seealso: PetscScalar, PetscImaginaryPart(), PetscMax(), PetscClipInterval(), PetscAbsInt(), PetscAbsReal(), PetscSqr()

    339: M*/
    340: #define PetscRealPart(a)      PetscRealPartComplex(a)

    342: /*MC
    343:    PetscImaginaryPart - Returns the imaginary part of a PetscScalar

    345:    Synopsis:
    346:    #include <petscmath.h>
    347:    PetscScalar PetscImaginaryPart(PetscScalar v)

    349:    Not Collective

    351:    Input Parameter:
    352: .  v - value to find the imaginary part of

    354:    Level: beginner

    356:    Notes:
    357:        If PETSc was configured for real numbers then this always returns the value 0

    359: .seealso: PetscScalar, PetscRealPart(), PetscMax(), PetscClipInterval(), PetscAbsInt(), PetscAbsReal(), PetscSqr()

    361: M*/
    362: #define PetscImaginaryPart(a) PetscImaginaryPartComplex(a)

    364: #define PetscAbsScalar(a)     PetscAbsComplex(a)
    365: #define PetscConj(a)          PetscConjComplex(a)
    366: #define PetscSqrtScalar(a)    PetscSqrtComplex(a)
    367: #define PetscPowScalar(a,b)   PetscPowComplex(a,b)
    368: #define PetscExpScalar(a)     PetscExpComplex(a)
    369: #define PetscLogScalar(a)     PetscLogComplex(a)
    370: #define PetscSinScalar(a)     PetscSinComplex(a)
    371: #define PetscCosScalar(a)     PetscCosComplex(a)
    372: #define PetscAsinScalar(a)    PetscAsinComplex(a)
    373: #define PetscAcosScalar(a)    PetscAcosComplex(a)
    374: #define PetscTanScalar(a)     PetscTanComplex(a)
    375: #define PetscSinhScalar(a)    PetscSinhComplex(a)
    376: #define PetscCoshScalar(a)    PetscCoshComplex(a)
    377: #define PetscTanhScalar(a)    PetscTanhComplex(a)
    378: #define MPIU_SCALAR MPIU_COMPLEX

    380: /*
    381:     real number definitions
    382:  */
    383: #else /* PETSC_USE_COMPLEX */
    384: typedef PetscReal PetscScalar;
    385: #define MPIU_SCALAR MPIU_REAL

    387: #define PetscRealPart(a)      (a)
    388: #define PetscImaginaryPart(a) ((PetscReal)0.)
    389: PETSC_STATIC_INLINE PetscReal PetscAbsScalar(PetscScalar a) {return a < 0.0 ? -a : a;}
    390: #define PetscConj(a)          (a)
    391: #if !defined(PETSC_USE_REAL___FLOAT128)  && !defined(PETSC_USE_REAL___FP16)
    392: #define PetscSqrtScalar(a)    sqrt(a)
    393: #define PetscPowScalar(a,b)   pow(a,b)
    394: #define PetscExpScalar(a)     exp(a)
    395: #define PetscLogScalar(a)     log(a)
    396: #define PetscSinScalar(a)     sin(a)
    397: #define PetscCosScalar(a)     cos(a)
    398: #define PetscAsinScalar(a)    asin(a)
    399: #define PetscAcosScalar(a)    acos(a)
    400: #define PetscTanScalar(a)     tan(a)
    401: #define PetscSinhScalar(a)    sinh(a)
    402: #define PetscCoshScalar(a)    cosh(a)
    403: #define PetscTanhScalar(a)    tanh(a)
    404: #elif defined(PETSC_USE_REAL___FP16)
    405: #define PetscSqrtScalar(a)    sqrtf(a)
    406: #define PetscPowScalar(a,b)   powf(a,b)
    407: #define PetscExpScalar(a)     expf(a)
    408: #define PetscLogScalar(a)     logf(a)
    409: #define PetscSinScalar(a)     sinf(a)
    410: #define PetscCosScalar(a)     cosf(a)
    411: #define PetscAsinScalar(a)    asinf(a)
    412: #define PetscAcosScalar(a)    acosf(a)
    413: #define PetscTanScalar(a)     tanf(a)
    414: #define PetscSinhScalar(a)    sinhf(a)
    415: #define PetscCoshScalar(a)    coshf(a)
    416: #define PetscTanhScalar(a)    tanhf(a)
    417: #else /* PETSC_USE_REAL___FLOAT128 */
    418: #define PetscSqrtScalar(a)    sqrtq(a)
    419: #define PetscPowScalar(a,b)   powq(a,b)
    420: #define PetscExpScalar(a)     expq(a)
    421: #define PetscLogScalar(a)     logq(a)
    422: #define PetscSinScalar(a)     sinq(a)
    423: #define PetscCosScalar(a)     cosq(a)
    424: #define PetscAsinScalar(a)    asinq(a)
    425: #define PetscAcosScalar(a)    acosq(a)
    426: #define PetscTanScalar(a)     tanq(a)
    427: #define PetscSinhScalar(a)    sinhq(a)
    428: #define PetscCoshScalar(a)    coshq(a)
    429: #define PetscTanhScalar(a)    tanhq(a)
    430: #endif /* PETSC_USE_REAL___FLOAT128 */

    432: #endif /* PETSC_USE_COMPLEX */

    434: #define PetscSign(a) (((a) >= 0) ? ((a) == 0 ? 0 : 1) : -1)
    435: #define PetscSignReal(a) (((a) >= 0.0) ? ((a) == 0.0 ? 0.0 : 1.0) : -1.0)
    436: #define PetscAbs(a)  (((a) >= 0) ? (a) : (-(a)))

    438: /* --------------------------------------------------------------------------*/

    440: /*
    441:    Certain objects may be created using either single or double precision.
    442:    This is currently not used.
    443: */
    444: typedef enum { PETSC_SCALAR_DOUBLE,PETSC_SCALAR_SINGLE, PETSC_SCALAR_LONG_DOUBLE, PETSC_SCALAR_HALF } PetscScalarPrecision;

    446: #if defined(PETSC_HAVE_COMPLEX)
    447: /* PETSC_i is the imaginary number, i */
    448: PETSC_EXTERN PetscComplex PETSC_i;

    450: /* Try to do the right thing for complex number construction: see

    452:   http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1464.htm

    454:   for details
    455: */
    456: PETSC_STATIC_INLINE PetscComplex PetscCMPLX(PetscReal x, PetscReal y)
    457: {
    458: #if   defined(__cplusplus) && defined(PETSC_HAVE_CXX_COMPLEX) && !defined(PETSC_USE_REAL___FLOAT128)
    459:   return PetscComplex(x,y);
    460: #elif defined(_Imaginary_I)
    461:   return x + y * _Imaginary_I;
    462: #else
    463:   { /* In both C99 and C11 (ISO/IEC 9899, Section 6.2.5),

    465:        "For each floating type there is a corresponding real type, which is always a real floating
    466:        type. For real floating types, it is the same type. For complex types, it is the type given
    467:        by deleting the keyword _Complex from the type name."

    469:        So type punning should be portable. */
    470:     union { PetscComplex z; PetscReal f[2]; } uz;

    472:     uz.f[0] = x;
    473:     uz.f[1] = y;
    474:     return uz.z;
    475:   }
    476: #endif
    477: }
    478: #endif

    481: /*MC
    482:    PetscMin - Returns minimum of two numbers

    484:    Synopsis:
    485:    #include <petscmath.h>
    486:    type PetscMin(type v1,type v2)

    488:    Not Collective

    490:    Input Parameter:
    491: +  v1 - first value to find minimum of
    492: -  v2 - second value to find minimum of

    494:    Notes:
    495:     type can be integer or floating point value

    497:    Level: beginner

    499: .seealso: PetscMax(), PetscClipInterval(), PetscAbsInt(), PetscAbsReal(), PetscSqr()

    501: M*/
    502: #define PetscMin(a,b)   (((a)<(b)) ?  (a) : (b))

    504: /*MC
    505:    PetscMax - Returns maxium of two numbers

    507:    Synopsis:
    508:    #include <petscmath.h>
    509:    type max PetscMax(type v1,type v2)

    511:    Not Collective

    513:    Input Parameter:
    514: +  v1 - first value to find maximum of
    515: -  v2 - second value to find maximum of

    517:    Notes:
    518:     type can be integer or floating point value

    520:    Level: beginner

    522: .seealso: PetscMin(), PetscClipInterval(), PetscAbsInt(), PetscAbsReal(), PetscSqr()

    524: M*/
    525: #define PetscMax(a,b)   (((a)<(b)) ?  (b) : (a))

    527: /*MC
    528:    PetscClipInterval - Returns a number clipped to be within an interval

    530:    Synopsis:
    531:    #include <petscmath.h>
    532:    type clip PetscClipInterval(type x,type a,type b)

    534:    Not Collective

    536:    Input Parameter:
    537: +  x - value to use if within interval (a,b)
    538: .  a - lower end of interval
    539: -  b - upper end of interval

    541:    Notes:
    542:     type can be integer or floating point value

    544:    Level: beginner

    546: .seealso: PetscMin(), PetscMax(), PetscAbsInt(), PetscAbsReal(), PetscSqr()

    548: M*/
    549: #define PetscClipInterval(x,a,b)   (PetscMax((a),PetscMin((x),(b))))

    551: /*MC
    552:    PetscAbsInt - Returns the absolute value of an integer

    554:    Synopsis:
    555:    #include <petscmath.h>
    556:    int abs PetscAbsInt(int v1)

    558:    Not Collective

    560:    Input Parameter:
    561: .   v1 - the integer

    563:    Level: beginner

    565: .seealso: PetscMax(), PetscMin(), PetscAbsReal(), PetscSqr()

    567: M*/
    568: #define PetscAbsInt(a)  (((a)<0)   ? (-(a)) : (a))

    570: /*MC
    571:    PetscAbsReal - Returns the absolute value of an real number

    573:    Synopsis:
    574:    #include <petscmath.h>
    575:    Real abs PetscAbsReal(PetscReal v1)

    577:    Not Collective

    579:    Input Parameter:
    580: .   v1 - the double

    583:    Level: beginner

    585: .seealso: PetscMax(), PetscMin(), PetscAbsInt(), PetscSqr()

    587: M*/
    588: #if defined(PETSC_USE_REAL_SINGLE)
    589: #define PetscAbsReal(a) fabsf(a)
    590: #elif defined(PETSC_USE_REAL_DOUBLE)
    591: #define PetscAbsReal(a) fabs(a)
    592: #elif defined(PETSC_USE_REAL___FLOAT128)
    593: #define PetscAbsReal(a) fabsq(a)
    594: #elif defined(PETSC_USE_REAL___FP16)
    595: #define PetscAbsReal(a) fabsf(a)
    596: #endif

    598: /*MC
    599:    PetscSqr - Returns the square of a number

    601:    Synopsis:
    602:    #include <petscmath.h>
    603:    type sqr PetscSqr(type v1)

    605:    Not Collective

    607:    Input Parameter:
    608: .   v1 - the value

    610:    Notes:
    611:     type can be integer or floating point value

    613:    Level: beginner

    615: .seealso: PetscMax(), PetscMin(), PetscAbsInt(), PetscAbsReal()

    617: M*/
    618: #define PetscSqr(a)     ((a)*(a))

    620: /* ----------------------------------------------------------------------------*/

    622: #if defined(PETSC_USE_REAL_SINGLE)
    623: #define PetscRealConstant(constant) constant##F
    624: #elif defined(PETSC_USE_REAL___FLOAT128)
    625: #define PetscRealConstant(constant) constant##Q
    626: #else
    627: #define PetscRealConstant(constant) constant
    628: #endif

    630: /*
    631:      Basic constants
    632: */
    633: #define PETSC_PI   PetscRealConstant(3.1415926535897932384626433832795029)
    634: #define PETSC_PHI  PetscRealConstant(1.6180339887498948482045868343656381)

    636: #if !defined(PETSC_USE_64BIT_INDICES)
    637: #define PETSC_MAX_INT            2147483647
    638: #define PETSC_MIN_INT            (-PETSC_MAX_INT - 1)
    639: #else
    640: #define PETSC_MAX_INT            9223372036854775807L
    641: #define PETSC_MIN_INT            (-PETSC_MAX_INT - 1)
    642: #endif

    644: #if defined(PETSC_USE_REAL_SINGLE)
    645: #  define PETSC_MAX_REAL                3.40282346638528860e+38F
    646: #  define PETSC_MIN_REAL                (-PETSC_MAX_REAL)
    647: #  define PETSC_MACHINE_EPSILON         1.19209290e-07F
    648: #  define PETSC_SQRT_MACHINE_EPSILON    3.45266983e-04F
    649: #  define PETSC_SMALL                   1.e-5F
    650: #elif defined(PETSC_USE_REAL_DOUBLE)
    651: #  define PETSC_MAX_REAL                1.7976931348623157e+308
    652: #  define PETSC_MIN_REAL                (-PETSC_MAX_REAL)
    653: #  define PETSC_MACHINE_EPSILON         2.2204460492503131e-16
    654: #  define PETSC_SQRT_MACHINE_EPSILON    1.490116119384766e-08
    655: #  define PETSC_SMALL                   1.e-10
    656: #elif defined(PETSC_USE_REAL___FLOAT128)
    657: #  define PETSC_MAX_REAL                FLT128_MAX
    658: #  define PETSC_MIN_REAL                (-FLT128_MAX)
    659: #  define PETSC_MACHINE_EPSILON         FLT128_EPSILON
    660: #  define PETSC_SQRT_MACHINE_EPSILON    1.38777878078144567552953958511352539e-17Q
    661: #  define PETSC_SMALL                   1.e-20Q
    662: #elif defined(PETSC_USE_REAL___FP16)  /* maybe should use single precision values for these? */
    663: #  define PETSC_MAX_REAL                65504.
    664: #  define PETSC_MIN_REAL                (-PETSC_MAX_REAL)
    665: #  define PETSC_MACHINE_EPSILON         .00097656
    666: #  define PETSC_SQRT_MACHINE_EPSILON    .0312
    667: #  define PETSC_SMALL                   5.e-3
    668: #endif

    670: #define PETSC_INFINITY               (PETSC_MAX_REAL/4)
    671: #define PETSC_NINFINITY              (-PETSC_INFINITY)

    673: PETSC_EXTERN PetscBool PetscIsInfReal(PetscReal);
    674: PETSC_EXTERN PetscBool PetscIsNanReal(PetscReal);
    675: PETSC_EXTERN PetscBool PetscIsNormalReal(PetscReal);
    676: PETSC_STATIC_INLINE PetscBool PetscIsInfOrNanReal(PetscReal v) {return PetscIsInfReal(v) || PetscIsNanReal(v) ? PETSC_TRUE : PETSC_FALSE;}
    677: PETSC_STATIC_INLINE PetscBool PetscIsInfScalar(PetscScalar v) {return PetscIsInfReal(PetscAbsScalar(v));}
    678: PETSC_STATIC_INLINE PetscBool PetscIsNanScalar(PetscScalar v) {return PetscIsNanReal(PetscAbsScalar(v));}
    679: PETSC_STATIC_INLINE PetscBool PetscIsInfOrNanScalar(PetscScalar v) {return PetscIsInfOrNanReal(PetscAbsScalar(v));}
    680: PETSC_STATIC_INLINE PetscBool PetscIsNormalScalar(PetscScalar v) {return PetscIsNormalReal(PetscAbsScalar(v));}

    682: PETSC_EXTERN PetscBool PetscEqualReal(PetscReal,PetscReal);
    683: PETSC_EXTERN PetscBool PetscEqualScalar(PetscScalar,PetscScalar);

    685: /*
    686:     These macros are currently hardwired to match the regular data types, so there is no support for a different
    687:     MatScalar from PetscScalar. We left the MatScalar in the source just in case we use it again.
    688:  */
    689: #define MPIU_MATSCALAR MPIU_SCALAR
    690: typedef PetscScalar MatScalar;
    691: typedef PetscReal MatReal;

    693: struct petsc_mpiu_2scalar {PetscScalar a,b;};
    694: PETSC_EXTERN MPI_Datatype MPIU_2SCALAR PetscAttrMPITypeTagLayoutCompatible(struct petsc_mpiu_2scalar);
    695: #if defined(PETSC_USE_64BIT_INDICES) || !defined(MPI_2INT)
    696: struct petsc_mpiu_2int {PetscInt a,b;};
    697: PETSC_EXTERN MPI_Datatype MPIU_2INT PetscAttrMPITypeTagLayoutCompatible(struct petsc_mpiu_2int);
    698: #else
    699: #define MPIU_2INT MPI_2INT
    700: #endif

    702: PETSC_STATIC_INLINE PetscInt PetscPowInt(PetscInt base,PetscInt power)
    703: {
    704:   PetscInt result = 1;
    705:   while (power) {
    706:     if (power & 1) result *= base;
    707:     power >>= 1;
    708:     base *= base;
    709:   }
    710:   return result;
    711: }

    713: PETSC_STATIC_INLINE PetscReal PetscPowRealInt(PetscReal base,PetscInt power)
    714: {
    715:   PetscReal result = 1;
    716:   if (power < 0) {
    717:     power = -power;
    718:     base  = ((PetscReal)1)/base;
    719:   }
    720:   while (power) {
    721:     if (power & 1) result *= base;
    722:     power >>= 1;
    723:     base *= base;
    724:   }
    725:   return result;
    726: }

    728: PETSC_STATIC_INLINE PetscScalar PetscPowScalarInt(PetscScalar base,PetscInt power)
    729: {
    730:   PetscScalar result = 1;
    731:   if (power < 0) {
    732:     power = -power;
    733:     base  = ((PetscReal)1)/base;
    734:   }
    735:   while (power) {
    736:     if (power & 1) result *= base;
    737:     power >>= 1;
    738:     base *= base;
    739:   }
    740:   return result;
    741: }

    743: PETSC_STATIC_INLINE PetscScalar PetscPowScalarReal(PetscScalar base,PetscReal power)
    744: {
    745:   PetscScalar cpower = power;
    746:   return PetscPowScalar(base,cpower);
    747: }

    749: #ifndef PETSC_HAVE_LOG2
    750: PETSC_STATIC_INLINE PetscReal PetscLog2Real(PetscReal n)
    751: {
    752:   return PetscLogReal(n)/PetscLogReal(2.0);
    753: }
    754: #endif
    755: #endif