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