File: scalarTypes.py

package info (click to toggle)
petsc 3.22.5%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 516,740 kB
  • sloc: ansic: 814,333; cpp: 50,948; python: 37,416; f90: 17,187; javascript: 3,493; makefile: 3,198; sh: 1,502; xml: 619; objc: 445; java: 13; csh: 1
file content (166 lines) | stat: -rwxr-xr-x 8,885 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
from __future__ import generators
import config.base

class Configure(config.base.Configure):
  def __init__(self, framework):
    config.base.Configure.__init__(self, framework)
    self.headerPrefix   = ''
    self.substPrefix    = ''
    self.have__fp16     = 0
    self.have__float128 = 0
    return

  def __str1__(self):
    output  = '  Scalar type: ' + self.scalartype + '\n'
    output += '  Precision: ' + self.precision + '\n'
    support = []
    if self.have__fp16 and not self.precision == '__fp16': support.append('__fp16')
    if self.have__float128 and not self.precision == '__float128': support.append('__float128')
    if not len(support) == 0: output += '  Support for ' + ' and '.join(support) + '\n'
    return output

  def setupHelp(self, help):
    import nargs
    #  Dec 2016, the __fp16 type is only available with GNU compilers on ARM systems
    help.addArgument('PETSc', '-with-precision=<__fp16,single,double,__float128>', nargs.Arg(None, 'double', 'Specify numerical precision'))
    help.addArgument('PETSc', '-with-scalar-type=<real or complex>', nargs.Arg(None, 'real', 'Specify real or complex numbers'))
    return

  def setupDependencies(self, framework):
    config.base.Configure.setupDependencies(self, framework)
    self.types         = framework.require('config.types', self)
    self.languages     = framework.require('PETSc.options.languages', self)
    self.compilers     = framework.require('config.compilers', self)
    self.libraries     = framework.require('config.libraries',self)
    self.setCompilers  = framework.require('config.setCompilers', self)
    self.compilerFlags = framework.require('config.compilerFlags', self)
    self.types         = framework.require('config.types', self)
    self.headers       = framework.require('config.headers', self)
    self.libraries     = framework.require('config.libraries', self)
    return

  def configureScalarType(self):
    '''Choose between real and complex numbers'''
    self.scalartype = self.framework.argDB['with-scalar-type'].lower()
    if self.scalartype == 'complex':
      self.addDefine('USE_COMPLEX', '1')
      if self.languages.clanguage == 'C' and not self.types.c99_complex:
        raise RuntimeError('C Compiler provided does not support C99 complex')
      if self.languages.clanguage == 'Cxx' and not self.types.cxx_complex:
        raise RuntimeError('Cxx compiler provided does not support std::complex')
      if self.languages.clanguage == 'Cxx':
        self.addDefine('USE_CXXCOMPLEX',1)
    elif not self.scalartype == 'real':
      raise RuntimeError('--with-scalar-type must be real or complex')
    self.logPrint('Scalar type is '+str(self.scalartype))
    # On apple isinf() and isnan() do not work when <complex> is included
    self.pushLanguage(self.languages.clanguage)
    if self.scalartype == 'complex' and self.languages.clanguage == 'Cxx':
      if self.checkLink('#include <math.h>\n#include <complex>\n','double b = 2.0;int a = isnormal(b);(void)a'):
        self.addDefine('HAVE_ISNORMAL',1)
      if self.checkLink('#include <math.h>\n#include <complex>\n','double b = 2.0;int a = isnan(b);(void)a'):
        self.addDefine('HAVE_ISNAN',1)
      elif self.checkLink('#include <float.h>\n#include <complex>\n','double b = 2.0;int a = _isnan(b);(void)a'):
        self.addDefine('HAVE__ISNAN',1)
      if self.checkLink('#include <math.h>\n#include <complex>\n','double b = 2.0;int a = isinf(b);(void)a'):
        self.addDefine('HAVE_ISINF',1)
      elif self.checkLink('#include <float.h>\n#include <complex>\n','double b = 2.0;int a = _finite(b);(void)a'):
        self.addDefine('HAVE__FINITE',1)
    else:
      if self.checkLink('#include <math.h>\n','double b = 2.0; int a = isnormal(b);(void)a'):
        self.addDefine('HAVE_ISNORMAL',1)
      if self.checkLink('#include <math.h>\n','double b = 2.0; int a = isnan(b);(void)a'):
        self.addDefine('HAVE_ISNAN',1)
      elif self.checkLink('#include <float.h>\n','double b = 2.0;int a = _isnan(b);(void)a'):
        self.addDefine('HAVE__ISNAN',1)
      if self.checkLink('#include <math.h>\n','double b = 2.0; int a = isinf(b);(void)a'):
        self.addDefine('HAVE_ISINF',1)
      elif self.checkLink('#include <float.h>\n','double b = 2.0;int a = _finite(b);(void)a'):
        self.addDefine('HAVE__FINITE',1)
    self.popLanguage()
    return

  def checkNoFiniteMathOnly(self):
    '''Check if attribute for ignoring finite-math-only optimization is valid, for isnan() and isinf()'''
    if self.checkCompile('','__attribute__((optimize ("no-finite-math-only"))) int foo(void);'):
      self.addDefine('HAVE_NO_FINITE_MATH_ONLY',1)

  def configurePrecision(self):
    '''Set the default real number precision for PETSc objects'''
    self.log.write('Checking C compiler works with __float128\n')
    self.have__float128 = 0
    if self.libraries.check('quadmath','logq',prototype='#include <quadmath.h>',call='__float128 f = 0.0; logq(f)'):
      self.log.write('C compiler works with quadmath library\n')
      self.have__float128 = 1
      if hasattr(self.compilers, 'FC'):
        self.libraries.pushLanguage('FC')
        self.log.write('Checking Fortran compiler works with quadmath library\n')
        if self.libraries.check('quadmath','     ',call = '      real*16 s,w; w = 2.0; s = cos(w)'):
          self.log.write('Fortran compiler works with quadmath library\n')
        else:
          self.have__float128 = 0
          self.log.write('Fortran compiler fails with quadmath library\n')
        self.libraries.popLanguage()
      if hasattr(self.compilers, 'CXX'):
        self.libraries.pushLanguage('Cxx')
        isGNU = self.setCompilers.isGNU(self.getCompiler(lang='Cxx'), self.log)
        # need to bypass g++ error: non-standard suffix on floating constant [-Werror=pedantic]
        # this warning can't be disabled but is actually never triggered by PETSc
        if isGNU:
          self.setCompilers.pushLanguage('Cxx')
          preprocessorFlagsArg = self.setCompilers.getPreprocessorFlagsArg()
          oldPreprocessorFlags = getattr(self.setCompilers, preprocessorFlagsArg)
          setattr(self.setCompilers, preprocessorFlagsArg, oldPreprocessorFlags+' -Wno-error')
        self.log.write('Checking C++ compiler works with quadmath library\n')
        if self.libraries.check('quadmath','logq',prototype='#include <quadmath.h>',call='__float128 f = FLT128_EPSILON; logq(f)'):
          self.log.write('C++ compiler works with quadmath library\n')
        else:
          self.have__float128 = 0
          self.log.write('C++ compiler fails with quadmath library\n')
        if isGNU:
          setattr(self.setCompilers, preprocessorFlagsArg, oldPreprocessorFlags)
          self.setCompilers.popLanguage()
        self.libraries.popLanguage()
      if self.have__float128:
          self.libraries.add('quadmath','logq',prototype='#include <quadmath.h>',call='__float128 f = 0.0; logq(f)')
          self.addDefine('HAVE_REAL___FLOAT128', '1')

    self.log.write('Checking C compiler works with __fp16\n')
    self.have__fp16 = 0
    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; }'):
      self.have__fp16 = 1
      self.addDefine('HAVE_REAL___FP16', '1')

    self.precision = self.framework.argDB['with-precision'].lower()
    if self.precision == '__fp16':  # supported by gcc trunk
      if self.scalartype == 'complex':
        raise RuntimeError('__fp16 can only be used with real numbers, not complex')
      if hasattr(self.compilers, 'FC'):
        raise RuntimeError('__fp16 can only be used with C compiler, not Fortran')
      if self.have__fp16:
        self.addDefine('USE_REAL___FP16', '1')
        self.addMakeMacro('PETSC_SCALAR_SIZE', '16')
      else:
        raise RuntimeError('__fp16 support not found, cannot proceed --with-precision=__fp16')
    elif self.precision == 'single':
      self.addDefine('USE_REAL_SINGLE', '1')
      self.addMakeMacro('PETSC_SCALAR_SIZE', '32')
    elif self.precision == 'double':
      self.addDefine('USE_REAL_DOUBLE', '1')
      self.addMakeMacro('PETSC_SCALAR_SIZE', '64')
    elif self.precision == '__float128':  # supported by gcc 4.6/gfortran and later
      if self.have__float128:
        self.addDefine('USE_REAL___FLOAT128', '1')
        self.addMakeMacro('PETSC_SCALAR_SIZE', '128')
      else:
        raise RuntimeError('__float128 support not found. --with-precision=__float128 works with gcc-4.6 and newer compilers.')
    else:
      raise RuntimeError('--with-precision must be __fp16, single, double, or __float128')
    self.logPrint('Precision is '+str(self.precision))
    return

  def configure(self):
    self.executeTest(self.configureScalarType)
    self.executeTest(self.configurePrecision)
    self.executeTest(self.checkNoFiniteMathOnly)
    return