xref: /petsc/config/PETSc/options/scalarTypes.py (revision 226f8a8a5081bc6ad7227cd631662400f0d6e2a0)
19d310bb7SBarry Smithfrom __future__ import generators
29d310bb7SBarry Smithimport config.base
39d310bb7SBarry Smith
49d310bb7SBarry Smithclass Configure(config.base.Configure):
59d310bb7SBarry Smith  def __init__(self, framework):
69d310bb7SBarry Smith    config.base.Configure.__init__(self, framework)
79d310bb7SBarry Smith    self.headerPrefix   = ''
89d310bb7SBarry Smith    self.substPrefix    = ''
99e517322SPierre Jolivet    self.have__fp16     = 0
1092659a76SBarry Smith    self.have__float128 = 0
119d310bb7SBarry Smith    return
129d310bb7SBarry Smith
139d310bb7SBarry Smith  def __str1__(self):
1492659a76SBarry Smith    output  = '  Scalar type: ' + self.scalartype + '\n'
1592659a76SBarry Smith    output += '  Precision: ' + self.precision + '\n'
169e517322SPierre Jolivet    support = []
179e517322SPierre Jolivet    if self.have__fp16 and not self.precision == '__fp16': support.append('__fp16')
189e517322SPierre Jolivet    if self.have__float128 and not self.precision == '__float128': support.append('__float128')
199e517322SPierre Jolivet    if not len(support) == 0: output += '  Support for ' + ' and '.join(support) + '\n'
2092659a76SBarry Smith    return output
219d310bb7SBarry Smith
229d310bb7SBarry Smith  def setupHelp(self, help):
239d310bb7SBarry Smith    import nargs
24570b7f6dSBarry Smith    #  Dec 2016, the __fp16 type is only available with GNU compilers on ARM systems
25570b7f6dSBarry Smith    help.addArgument('PETSc', '-with-precision=<__fp16,single,double,__float128>', nargs.Arg(None, 'double', 'Specify numerical precision'))
269d310bb7SBarry Smith    help.addArgument('PETSc', '-with-scalar-type=<real or complex>', nargs.Arg(None, 'real', 'Specify real or complex numbers'))
279d310bb7SBarry Smith    return
289d310bb7SBarry Smith
299d310bb7SBarry Smith  def setupDependencies(self, framework):
309d310bb7SBarry Smith    config.base.Configure.setupDependencies(self, framework)
319d310bb7SBarry Smith    self.types         = framework.require('config.types', self)
329d310bb7SBarry Smith    self.languages     = framework.require('PETSc.options.languages', self)
339d310bb7SBarry Smith    self.compilers     = framework.require('config.compilers', self)
349d310bb7SBarry Smith    self.libraries     = framework.require('config.libraries',self)
3592659a76SBarry Smith    self.setCompilers  = framework.require('config.setCompilers', self)
3692659a76SBarry Smith    self.compilerFlags = framework.require('config.compilerFlags', self)
3792659a76SBarry Smith    self.types         = framework.require('config.types', self)
3892659a76SBarry Smith    self.headers       = framework.require('config.headers', self)
3992659a76SBarry Smith    self.libraries     = framework.require('config.libraries', self)
409d310bb7SBarry Smith    return
419d310bb7SBarry Smith
429d310bb7SBarry Smith  def configureScalarType(self):
439d310bb7SBarry Smith    '''Choose between real and complex numbers'''
449d310bb7SBarry Smith    self.scalartype = self.framework.argDB['with-scalar-type'].lower()
459d310bb7SBarry Smith    if self.scalartype == 'complex':
469d310bb7SBarry Smith      self.addDefine('USE_COMPLEX', '1')
479d310bb7SBarry Smith      if self.languages.clanguage == 'C' and not self.types.c99_complex:
48f51b456fSStefano Zampini        raise RuntimeError('C Compiler provided does not support C99 complex')
499d310bb7SBarry Smith      if self.languages.clanguage == 'Cxx' and not self.types.cxx_complex:
509d310bb7SBarry Smith        raise RuntimeError('Cxx compiler provided does not support std::complex')
51826b3ad7SBarry Smith      if self.languages.clanguage == 'Cxx':
52826b3ad7SBarry Smith        self.addDefine('USE_CXXCOMPLEX',1)
539d310bb7SBarry Smith    elif not self.scalartype == 'real':
549d310bb7SBarry Smith      raise RuntimeError('--with-scalar-type must be real or complex')
557ad10985SMatthew G. Knepley    self.logPrint('Scalar type is '+str(self.scalartype))
569d310bb7SBarry Smith    # On apple isinf() and isnan() do not work when <complex> is included
579d310bb7SBarry Smith    self.pushLanguage(self.languages.clanguage)
589d310bb7SBarry Smith    if self.scalartype == 'complex' and self.languages.clanguage == 'Cxx':
5922164b4cSPierre Jolivet      if self.checkLink('#include <math.h>\n#include <complex>\n','double b = 2.0;int a = isnormal(b);(void)a'):
609d310bb7SBarry Smith        self.addDefine('HAVE_ISNORMAL',1)
6122164b4cSPierre Jolivet      if self.checkLink('#include <math.h>\n#include <complex>\n','double b = 2.0;int a = isnan(b);(void)a'):
629d310bb7SBarry Smith        self.addDefine('HAVE_ISNAN',1)
6322164b4cSPierre Jolivet      elif self.checkLink('#include <float.h>\n#include <complex>\n','double b = 2.0;int a = _isnan(b);(void)a'):
640542e31aSBarry Smith        self.addDefine('HAVE__ISNAN',1)
6522164b4cSPierre Jolivet      if self.checkLink('#include <math.h>\n#include <complex>\n','double b = 2.0;int a = isinf(b);(void)a'):
669d310bb7SBarry Smith        self.addDefine('HAVE_ISINF',1)
6722164b4cSPierre Jolivet      elif self.checkLink('#include <float.h>\n#include <complex>\n','double b = 2.0;int a = _finite(b);(void)a'):
689d310bb7SBarry Smith        self.addDefine('HAVE__FINITE',1)
699d310bb7SBarry Smith    else:
7022164b4cSPierre Jolivet      if self.checkLink('#include <math.h>\n','double b = 2.0; int a = isnormal(b);(void)a'):
719d310bb7SBarry Smith        self.addDefine('HAVE_ISNORMAL',1)
7222164b4cSPierre Jolivet      if self.checkLink('#include <math.h>\n','double b = 2.0; int a = isnan(b);(void)a'):
739d310bb7SBarry Smith        self.addDefine('HAVE_ISNAN',1)
7422164b4cSPierre Jolivet      elif self.checkLink('#include <float.h>\n','double b = 2.0;int a = _isnan(b);(void)a'):
750542e31aSBarry Smith        self.addDefine('HAVE__ISNAN',1)
7622164b4cSPierre Jolivet      if self.checkLink('#include <math.h>\n','double b = 2.0; int a = isinf(b);(void)a'):
779d310bb7SBarry Smith        self.addDefine('HAVE_ISINF',1)
7822164b4cSPierre Jolivet      elif self.checkLink('#include <float.h>\n','double b = 2.0;int a = _finite(b);(void)a'):
799d310bb7SBarry Smith        self.addDefine('HAVE__FINITE',1)
809d310bb7SBarry Smith    self.popLanguage()
819d310bb7SBarry Smith    return
829d310bb7SBarry Smith
8360634426SJames Wright  def checkNoFiniteMathOnly(self):
8460634426SJames Wright    '''Check if attribute for ignoring finite-math-only optimization is valid, for isnan() and isinf()'''
8560634426SJames Wright    if self.checkCompile('','__attribute__((optimize ("no-finite-math-only"))) int foo(void);'):
8660634426SJames Wright      self.addDefine('HAVE_NO_FINITE_MATH_ONLY',1)
8760634426SJames Wright
889d310bb7SBarry Smith  def configurePrecision(self):
899d310bb7SBarry Smith    '''Set the default real number precision for PETSc objects'''
9092659a76SBarry Smith    self.log.write('Checking C compiler works with __float128\n')
9192659a76SBarry Smith    self.have__float128 = 0
9222164b4cSPierre Jolivet    if self.libraries.check('quadmath','logq',prototype='#include <quadmath.h>',call='__float128 f = 0.0; logq(f)'):
93bd6c2bcdSPierre Jolivet      self.log.write('C compiler works with quadmath library\n')
9492659a76SBarry Smith      self.have__float128 = 1
9592659a76SBarry Smith      if hasattr(self.compilers, 'FC'):
9692659a76SBarry Smith        self.libraries.pushLanguage('FC')
97bd6c2bcdSPierre Jolivet        self.log.write('Checking Fortran compiler works with quadmath library\n')
9892659a76SBarry Smith        if self.libraries.check('quadmath','     ',call = '      real*16 s,w; w = 2.0; s = cos(w)'):
99bd6c2bcdSPierre Jolivet          self.log.write('Fortran compiler works with quadmath library\n')
1000a5d3b00SBarry Smith        else:
10192659a76SBarry Smith          self.have__float128 = 0
102bd6c2bcdSPierre Jolivet          self.log.write('Fortran compiler fails with quadmath library\n')
103bd6c2bcdSPierre Jolivet        self.libraries.popLanguage()
104bd6c2bcdSPierre Jolivet      if hasattr(self.compilers, 'CXX'):
105bd6c2bcdSPierre Jolivet        self.libraries.pushLanguage('Cxx')
1063099708eSPierre Jolivet        isGNU = self.setCompilers.isGNU(self.getCompiler(lang='Cxx'), self.log)
1073099708eSPierre Jolivet        # need to bypass g++ error: non-standard suffix on floating constant [-Werror=pedantic]
1083099708eSPierre Jolivet        # this warning can't be disabled but is actually never triggered by PETSc
1093099708eSPierre Jolivet        if isGNU:
1103099708eSPierre Jolivet          self.setCompilers.pushLanguage('Cxx')
1113099708eSPierre Jolivet          preprocessorFlagsArg = self.setCompilers.getPreprocessorFlagsArg()
1123099708eSPierre Jolivet          oldPreprocessorFlags = getattr(self.setCompilers, preprocessorFlagsArg)
1133099708eSPierre Jolivet          setattr(self.setCompilers, preprocessorFlagsArg, oldPreprocessorFlags+' -Wno-error')
114bd6c2bcdSPierre Jolivet        self.log.write('Checking C++ compiler works with quadmath library\n')
115bd6c2bcdSPierre Jolivet        if self.libraries.check('quadmath','logq',prototype='#include <quadmath.h>',call='__float128 f = FLT128_EPSILON; logq(f)'):
116bd6c2bcdSPierre Jolivet          self.log.write('C++ compiler works with quadmath library\n')
117bd6c2bcdSPierre Jolivet        else:
118bd6c2bcdSPierre Jolivet          self.have__float128 = 0
119bd6c2bcdSPierre Jolivet          self.log.write('C++ compiler fails with quadmath library\n')
1203099708eSPierre Jolivet        if isGNU:
1213099708eSPierre Jolivet          setattr(self.setCompilers, preprocessorFlagsArg, oldPreprocessorFlags)
1223099708eSPierre Jolivet          self.setCompilers.popLanguage()
12392659a76SBarry Smith        self.libraries.popLanguage()
12492659a76SBarry Smith      if self.have__float128:
12522164b4cSPierre Jolivet          self.libraries.add('quadmath','logq',prototype='#include <quadmath.h>',call='__float128 f = 0.0; logq(f)')
12692659a76SBarry Smith          self.addDefine('HAVE_REAL___FLOAT128', '1')
12792659a76SBarry Smith
1289e517322SPierre Jolivet    self.log.write('Checking C compiler works with __fp16\n')
1299e517322SPierre Jolivet    self.have__fp16 = 0
13022164b4cSPierre Jolivet    if self.libraries.check('','',call='__fp16 f = 1.0, g; g = ret___fp16(f); (void)g',prototype='static __fp16 ret___fp16(__fp16 f) { return f; }'):
1319e517322SPierre Jolivet      self.have__fp16 = 1
1329e517322SPierre Jolivet      self.addDefine('HAVE_REAL___FP16', '1')
1339e517322SPierre Jolivet
1349d310bb7SBarry Smith    self.precision = self.framework.argDB['with-precision'].lower()
135570b7f6dSBarry Smith    if self.precision == '__fp16':  # supported by gcc trunk
136570b7f6dSBarry Smith      if self.scalartype == 'complex':
137570b7f6dSBarry Smith        raise RuntimeError('__fp16 can only be used with real numbers, not complex')
138570b7f6dSBarry Smith      if hasattr(self.compilers, 'FC'):
139570b7f6dSBarry Smith        raise RuntimeError('__fp16 can only be used with C compiler, not Fortran')
1409e517322SPierre Jolivet      if self.have__fp16:
141570b7f6dSBarry Smith        self.addDefine('USE_REAL___FP16', '1')
142570b7f6dSBarry Smith        self.addMakeMacro('PETSC_SCALAR_SIZE', '16')
1439e517322SPierre Jolivet      else:
1449e517322SPierre Jolivet        raise RuntimeError('__fp16 support not found, cannot proceed --with-precision=__fp16')
145570b7f6dSBarry Smith    elif self.precision == 'single':
1469d310bb7SBarry Smith      self.addDefine('USE_REAL_SINGLE', '1')
14769bf3e1aSBarry Smith      self.addMakeMacro('PETSC_SCALAR_SIZE', '32')
1489d310bb7SBarry Smith    elif self.precision == 'double':
1499d310bb7SBarry Smith      self.addDefine('USE_REAL_DOUBLE', '1')
15069bf3e1aSBarry Smith      self.addMakeMacro('PETSC_SCALAR_SIZE', '64')
15192659a76SBarry Smith    elif self.precision == '__float128':  # supported by gcc 4.6/gfortran and later
15292659a76SBarry Smith      if self.have__float128:
1539d310bb7SBarry Smith        self.addDefine('USE_REAL___FLOAT128', '1')
15469bf3e1aSBarry Smith        self.addMakeMacro('PETSC_SCALAR_SIZE', '128')
1559d310bb7SBarry Smith      else:
15692659a76SBarry Smith        raise RuntimeError('__float128 support not found. --with-precision=__float128 works with gcc-4.6 and newer compilers.')
1579d310bb7SBarry Smith    else:
1580a5d3b00SBarry Smith      raise RuntimeError('--with-precision must be __fp16, single, double, or __float128')
1597ad10985SMatthew G. Knepley    self.logPrint('Precision is '+str(self.precision))
1609d310bb7SBarry Smith    return
1619d310bb7SBarry Smith
1629d310bb7SBarry Smith  def configure(self):
1639d310bb7SBarry Smith    self.executeTest(self.configureScalarType)
1649d310bb7SBarry Smith    self.executeTest(self.configurePrecision)
16560634426SJames Wright    self.executeTest(self.checkNoFiniteMathOnly)
1669d310bb7SBarry Smith    return
167*2b2a1e23SStefano Zampini
168*2b2a1e23SStefano Zampini  def precisionToBytes(self):
169*2b2a1e23SStefano Zampini    d = {'__fp16' : 2, 'single' : 4, 'double' : 8, '__float128' : 16}
170*2b2a1e23SStefano Zampini    return d[self.precision]
171