1#!/usr/bin/env python 2from __future__ import generators 3import config.base 4 5class Configure(config.base.Configure): 6 def __init__(self, framework): 7 config.base.Configure.__init__(self, framework) 8 self.headerPrefix = '' 9 self.substPrefix = '' 10 self.have__float128 = 0 11 return 12 13 def __str1__(self): 14 output = ' Scalar type: ' + self.scalartype + '\n' 15 output += ' Precision: ' + self.precision + '\n' 16 if self.have__float128 and not self.precision == '__float128': output += ' Support for __float128\n' 17 return output 18 19 def setupHelp(self, help): 20 import nargs 21 # Dec 2016, the __fp16 type is only available with GNU compilers on ARM systems 22 help.addArgument('PETSc', '-with-precision=<__fp16,single,double,__float128>', nargs.Arg(None, 'double', 'Specify numerical precision')) 23 help.addArgument('PETSc', '-with-scalar-type=<real or complex>', nargs.Arg(None, 'real', 'Specify real or complex numbers')) 24 return 25 26 def setupDependencies(self, framework): 27 config.base.Configure.setupDependencies(self, framework) 28 self.types = framework.require('config.types', self) 29 self.languages = framework.require('PETSc.options.languages', self) 30 self.compilers = framework.require('config.compilers', self) 31 self.libraries = framework.require('config.libraries',self) 32 self.setCompilers = framework.require('config.setCompilers', self) 33 self.compilerFlags = framework.require('config.compilerFlags', self) 34 self.types = framework.require('config.types', self) 35 self.headers = framework.require('config.headers', self) 36 self.libraries = framework.require('config.libraries', self) 37 return 38 39 40 def configureScalarType(self): 41 '''Choose between real and complex numbers''' 42 self.scalartype = self.framework.argDB['with-scalar-type'].lower() 43 if self.scalartype == 'complex': 44 self.addDefine('USE_COMPLEX', '1') 45 if self.languages.clanguage == 'C' and not self.types.c99_complex: 46 raise RuntimeError('C Compiler provided doest not support C99 complex') 47 if self.languages.clanguage == 'Cxx' and not self.types.cxx_complex: 48 raise RuntimeError('Cxx compiler provided does not support std::complex') 49 if self.languages.clanguage == 'Cxx': 50 self.addDefine('USE_CXXCOMPLEX',1) 51 elif not self.scalartype == 'real': 52 raise RuntimeError('--with-scalar-type must be real or complex') 53 self.addDefine('USE_SCALAR_'+self.scalartype.upper(), '1') 54 self.logPrint('Scalar type is '+str(self.scalartype)) 55 # On apple isinf() and isnan() do not work when <complex> is included 56 self.pushLanguage(self.languages.clanguage) 57 if self.scalartype == 'complex' and self.languages.clanguage == 'Cxx': 58 if self.checkLink('#include <math.h>\n#include <complex>\n','double b = 2.0;int a = isnormal(b);\n'): 59 self.addDefine('HAVE_ISNORMAL',1) 60 if self.checkLink('#include <math.h>\n#include <complex>\n','double b = 2.0;int a = isnan(b);\n'): 61 self.addDefine('HAVE_ISNAN',1) 62 if self.checkLink('#include <math.h>\n#include <complex>\n','double b = 2.0;int a = isinf(b);\n'): 63 self.addDefine('HAVE_ISINF',1) 64 if self.checkLink('#include <float.h>\n#include <complex>\n','double b = 2.0;int a = _isnan(b);\n'): 65 self.addDefine('HAVE__ISNAN',1) 66 if self.checkLink('#include <float.h>\n#include <complex>\n','double b = 2.0;int a = _finite(b);\n'): 67 self.addDefine('HAVE__FINITE',1) 68 else: 69 if self.checkLink('#include <math.h>\n','double b = 2.0; int a = isnormal(b);\n'): 70 self.addDefine('HAVE_ISNORMAL',1) 71 if self.checkLink('#include <math.h>\n','double b = 2.0; int a = isnan(b);\n'): 72 self.addDefine('HAVE_ISNAN',1) 73 if self.checkLink('#include <math.h>\n','double b = 2.0; int a = isinf(b);\n'): 74 self.addDefine('HAVE_ISINF',1) 75 if self.checkLink('#include <float.h>\n','double b = 2.0;int a = _isnan(b);\n'): 76 self.addDefine('HAVE__ISNAN',1) 77 if self.checkLink('#include <float.h>\n','double b = 2.0;int a = _finite(b);\n'): 78 self.addDefine('HAVE__FINITE',1) 79 self.popLanguage() 80 return 81 82 def configurePrecision(self): 83 '''Set the default real number precision for PETSc objects''' 84 self.log.write('Checking C compiler works with __float128\n') 85 self.have__float128 = 0 86 if self.libraries.check('quadmath','logq',prototype='#include <quadmath.h>',call='__float128 f; logq(f);'): 87 self.log.write('C compiler with quadmath library\n') 88 self.have__float128 = 1 89 if hasattr(self.compilers, 'FC'): 90 self.libraries.pushLanguage('FC') 91 self.log.write('Checking Fortran works with quadmath library\n') 92 if self.libraries.check('quadmath',' ',call = ' real*16 s,w; w = 2.0 ;s = cos(w)'): 93 self.log.write('Fortran works with quadmath library\n') 94 else: 95 self.have__float128 = 0 96 self.log.write('Fortran fails with quadmath library\n') 97 self.libraries.popLanguage() 98 if self.have__float128: 99 self.libraries.add('quadmath','logq',prototype='#include <quadmath.h>',call='__float128 f; logq(f);') 100 self.addDefine('HAVE_REAL___FLOAT128', '1') 101 102 self.precision = self.framework.argDB['with-precision'].lower() 103 if self.precision == '__fp16': # supported by gcc trunk 104 if self.scalartype == 'complex': 105 raise RuntimeError('__fp16 can only be used with real numbers, not complex') 106 if hasattr(self.compilers, 'FC'): 107 raise RuntimeError('__fp16 can only be used with C compiler, not Fortran') 108 self.addDefine('USE_REAL___FP16', '1') 109 self.addMakeMacro('PETSC_SCALAR_SIZE', '16') 110 elif self.precision == 'single': 111 self.addDefine('USE_REAL_SINGLE', '1') 112 self.addMakeMacro('PETSC_SCALAR_SIZE', '32') 113 elif self.precision == 'double': 114 self.addDefine('USE_REAL_DOUBLE', '1') 115 self.addMakeMacro('PETSC_SCALAR_SIZE', '64') 116 elif self.precision == '__float128': # supported by gcc 4.6/gfortran and later 117 if self.have__float128: 118 self.addDefine('USE_REAL___FLOAT128', '1') 119 self.addMakeMacro('PETSC_SCALAR_SIZE', '128') 120 else: 121 raise RuntimeError('__float128 support not found. --with-precision=__float128 works with gcc-4.6 and newer compilers.') 122 else: 123 raise RuntimeError('--with-precision must be __fp16, single, double, or __float128') 124 self.logPrint('Precision is '+str(self.precision)) 125 if self.precision == '__float128' and self.scalartype == 'complex' and self.languages.clanguage == 'Cxx': 126 raise RuntimeError('Cannot use --with-precision=__float128 --with-scalar-type=complex and --with-clanguage=cxx because C++ std:complex class has no support for __float128, use --with-clanguage=c') 127 return 128 129 def configure(self): 130 self.executeTest(self.configureScalarType) 131 self.executeTest(self.configurePrecision) 132 return 133