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