#!/usr/bin/env python
|
#!/usr/bin/env python
|
#
|
#
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
# SLEPc - Scalable Library for Eigenvalue Problem Computations
|
# SLEPc - Scalable Library for Eigenvalue Problem Computations
|
# Copyright (c) 2002-2009, Universidad Politecnica de Valencia, Spain
|
# Copyright (c) 2002-2009, Universidad Politecnica de Valencia, Spain
|
#
|
#
|
# This file is part of SLEPc.
|
# This file is part of SLEPc.
|
#
|
#
|
# SLEPc is free software: you can redistribute it and/or modify it under the
|
# SLEPc is free software: you can redistribute it and/or modify it under the
|
# terms of version 3 of the GNU Lesser General Public License as published by
|
# terms of version 3 of the GNU Lesser General Public License as published by
|
# the Free Software Foundation.
|
# the Free Software Foundation.
|
#
|
#
|
# SLEPc is distributed in the hope that it will be useful, but WITHOUT ANY
|
# SLEPc is distributed in the hope that it will be useful, but WITHOUT ANY
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
# more details.
|
# more details.
|
#
|
#
|
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
# along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
|
# along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
#
|
#
|
|
|
import os
|
import os
|
import sys
|
import sys
|
import time
|
import time
|
|
|
import petscversion
|
import petscversion
|
import petscconf
|
import petscconf
|
import log
|
import log
|
import check
|
import check
|
import arpack
|
import arpack
|
import blzpack
|
import blzpack
|
import trlan
|
import trlan
|
import lapack
|
import lapack
|
import primme
|
import primme
|
|
|
if not hasattr(sys, 'version_info') or not sys.version_info[1] >= 2:
|
if not hasattr(sys, 'version_info') or not sys.version_info[1] >= 2:
|
print '**** You must have Python version 2.2 or higher to run config/configure.py ******'
|
print '**** You must have Python version 2.2 or higher to run config/configure.py ******'
|
print '* Python is easy to install for end users or sys-admin. *'
|
print '* Python is easy to install for end users or sys-admin. *'
|
print '* http://www.python.org/download/ *'
|
print '* http://www.python.org/download/ *'
|
print '* *'
|
print '* *'
|
print '* You CANNOT configure SLEPc without Python *'
|
print '* You CANNOT configure SLEPc without Python *'
|
print '*********************************************************************************'
|
print '*********************************************************************************'
|
sys.exit(4)
|
sys.exit(4)
|
|
|
# support a few standard configure option types
|
# support a few standard configure option types
|
for l in range(1,len(sys.argv)):
|
for l in range(1,len(sys.argv)):
|
name = sys.argv[l]
|
name = sys.argv[l]
|
if name.startswith('--enable'):
|
if name.startswith('--enable'):
|
sys.argv[l] = name.replace('--enable','--with')
|
sys.argv[l] = name.replace('--enable','--with')
|
if name.find('=') == -1: sys.argv[l] += '=1'
|
if name.find('=') == -1: sys.argv[l] += '=1'
|
if name.startswith('--disable'):
|
if name.startswith('--disable'):
|
sys.argv[l] = name.replace('--disable','--with')
|
sys.argv[l] = name.replace('--disable','--with')
|
if name.find('=') == -1: sys.argv[l] += '=0'
|
if name.find('=') == -1: sys.argv[l] += '=0'
|
elif name.endswith('=1'): sys.argv[l].replace('=1','=0')
|
elif name.endswith('=1'): sys.argv[l].replace('=1','=0')
|
if name.startswith('--without'):
|
if name.startswith('--without'):
|
sys.argv[l] = name.replace('--without','--with')
|
sys.argv[l] = name.replace('--without','--with')
|
if name.find('=') == -1: sys.argv[l] += '=0'
|
if name.find('=') == -1: sys.argv[l] += '=0'
|
elif name.endswith('=1'): sys.argv[l].replace('=1','=0')
|
elif name.endswith('=1'): sys.argv[l].replace('=1','=0')
|
|
|
# Check configure parameters
|
# Check configure parameters
|
havearpack = 0
|
havearpack = 0
|
arpackdir = ''
|
arpackdir = ''
|
arpacklibs = []
|
arpacklibs = []
|
haveblzpack = 0
|
haveblzpack = 0
|
blzpackdir = ''
|
blzpackdir = ''
|
blzpacklibs = []
|
blzpacklibs = []
|
havetrlan = 0
|
havetrlan = 0
|
trlandir = ''
|
trlandir = ''
|
trlanlibs = []
|
trlanlibs = []
|
haveprimme = 0
|
haveprimme = 0
|
primmedir = ''
|
primmedir = ''
|
primmelibs = []
|
primmelibs = []
|
prefixdir = ''
|
prefixdir = ''
|
|
|
for i in sys.argv[1:]:
|
for i in sys.argv[1:]:
|
if i.startswith('--with-arpack-dir='):
|
if i.startswith('--with-arpack-dir='):
|
arpackdir = i.split('=')[1]
|
arpackdir = i.split('=')[1]
|
havearpack = 1
|
havearpack = 1
|
elif i.startswith('--with-arpack-flags='):
|
elif i.startswith('--with-arpack-flags='):
|
arpacklibs = i.split('=')[1].split(',')
|
arpacklibs = i.split('=')[1].split(',')
|
havearpack = 1
|
havearpack = 1
|
elif i.startswith('--with-arpack'):
|
elif i.startswith('--with-arpack'):
|
havearpack = not i.endswith('=0')
|
havearpack = not i.endswith('=0')
|
elif i.startswith('--with-blzpack-dir='):
|
elif i.startswith('--with-blzpack-dir='):
|
blzpackdir = i.split('=')[1]
|
blzpackdir = i.split('=')[1]
|
haveblzpack = 1
|
haveblzpack = 1
|
elif i.startswith('--with-blzpack-flags='):
|
elif i.startswith('--with-blzpack-flags='):
|
blzpacklibs = i.split('=')[1].split(',')
|
blzpacklibs = i.split('=')[1].split(',')
|
haveblzpack = 1
|
haveblzpack = 1
|
elif i.startswith('--with-blzpack'):
|
elif i.startswith('--with-blzpack'):
|
haveblzpack = not i.endswith('=0')
|
haveblzpack = not i.endswith('=0')
|
elif i.startswith('--with-trlan-dir='):
|
elif i.startswith('--with-trlan-dir='):
|
trlandir = i.split('=')[1]
|
trlandir = i.split('=')[1]
|
havetrlan = 1
|
havetrlan = 1
|
elif i.startswith('--with-trlan-flags='):
|
elif i.startswith('--with-trlan-flags='):
|
trlanlibs = i.split('=')[1].split(',')
|
trlanlibs = i.split('=')[1].split(',')
|
havetrlan = 1
|
havetrlan = 1
|
elif i.startswith('--with-trlan'):
|
elif i.startswith('--with-trlan'):
|
havetrlan = not i.endswith('=0')
|
havetrlan = not i.endswith('=0')
|
elif i.startswith('--with-primme-dir'):
|
elif i.startswith('--with-primme-dir'):
|
primmedir = i.split('=')[1]
|
primmedir = i.split('=')[1]
|
haveprimme = 1
|
haveprimme = 1
|
elif i.startswith('--with-primme-flags='):
|
elif i.startswith('--with-primme-flags='):
|
primmelibs = i.split('=')[1].split(',')
|
primmelibs = i.split('=')[1].split(',')
|
haveprimme = 1
|
haveprimme = 1
|
elif i.startswith('--with-primme'):
|
elif i.startswith('--with-primme'):
|
haveprimme = not i.endswith('=0')
|
haveprimme = not i.endswith('=0')
|
elif i.startswith('--prefix='):
|
elif i.startswith('--prefix='):
|
prefixdir = i.split('=')[1]
|
prefixdir = i.split('=')[1]
|
elif i.startswith('--h') or i.startswith('-h') or i.startswith('-?'):
|
elif i.startswith('--h') or i.startswith('-h') or i.startswith('-?'):
|
print 'SLEPc Configure Help'
|
print 'SLEPc Configure Help'
|
print '-'*80
|
print '-'*80
|
print ' --prefix=<dir> : Specifiy location to install SLEPc (eg. /usr/local)'
|
print ' --prefix=<dir> : Specifiy location to install SLEPc (eg. /usr/local)'
|
print 'ARPACK:'
|
print 'ARPACK:'
|
print ' --with-arpack : Indicate if you wish to test for ARPACK (PARPACK)'
|
print ' --with-arpack : Indicate if you wish to test for ARPACK (PARPACK)'
|
print ' --with-arpack-dir=<dir> : Indicate the directory for ARPACK libraries'
|
print ' --with-arpack-dir=<dir> : Indicate the directory for ARPACK libraries'
|
print ' --with-arpack-flags=<flags> : Indicate comma-separated flags for linking ARPACK'
|
print ' --with-arpack-flags=<flags> : Indicate comma-separated flags for linking ARPACK'
|
print 'BLZPACK:'
|
print 'BLZPACK:'
|
print ' --with-blzpack : Indicate if you wish to test for BLZPACK'
|
print ' --with-blzpack : Indicate if you wish to test for BLZPACK'
|
print ' --with-blzpack-dir=<dir> : Indicate the directory for BLZPACK libraries'
|
print ' --with-blzpack-dir=<dir> : Indicate the directory for BLZPACK libraries'
|
print ' --with-blzpack-flags=<flags> : Indicate comma-separated flags for linking BLZPACK'
|
print ' --with-blzpack-flags=<flags> : Indicate comma-separated flags for linking BLZPACK'
|
print 'TRLAN:'
|
print 'TRLAN:'
|
print ' --with-trlan : Indicate if you wish to test for TRLAN'
|
print ' --with-trlan : Indicate if you wish to test for TRLAN'
|
print ' --with-trlan-dir=<dir> : Indicate the directory for TRLAN libraries'
|
print ' --with-trlan-dir=<dir> : Indicate the directory for TRLAN libraries'
|
print ' --with-trlan-flags=<flags> : Indicate comma-separated flags for linking TRLAN'
|
print ' --with-trlan-flags=<flags> : Indicate comma-separated flags for linking TRLAN'
|
print 'PRIMME:'
|
print 'PRIMME:'
|
print ' --with-primme : Indicate if you wish to test for PRIMME'
|
print ' --with-primme : Indicate if you wish to test for PRIMME'
|
print ' --with-primme-dir=<dir> : Indicate the directory for PRIMME libraries'
|
print ' --with-primme-dir=<dir> : Indicate the directory for PRIMME libraries'
|
print ' --with-primme-flags=<flags> : Indicate comma-separated flags for linking PRIMME'
|
print ' --with-primme-flags=<flags> : Indicate comma-separated flags for linking PRIMME'
|
sys.exit(0)
|
sys.exit(0)
|
else:
|
else:
|
sys.exit('ERROR: Invalid argument ' + i +' use -h for help')
|
sys.exit('ERROR: Invalid argument ' + i +' use -h for help')
|
|
|
# Check if enviroment is ok
|
# Check if enviroment is ok
|
print 'Checking environment...'
|
print 'Checking environment...'
|
if 'SLEPC_DIR' not in os.environ:
|
if 'SLEPC_DIR' not in os.environ:
|
sys.exit('ERROR: SLEPC_DIR enviroment variable is not set')
|
sys.exit('ERROR: SLEPC_DIR enviroment variable is not set')
|
slepcdir = os.environ['SLEPC_DIR']
|
slepcdir = os.environ['SLEPC_DIR']
|
if not os.path.exists(slepcdir) or not os.path.exists(os.sep.join([slepcdir,'config'])):
|
if not os.path.exists(slepcdir) or not os.path.exists(os.sep.join([slepcdir,'config'])):
|
sys.exit('ERROR: SLEPC_DIR enviroment variable is not valid')
|
sys.exit('ERROR: SLEPC_DIR enviroment variable is not valid')
|
if os.getcwd() != slepcdir:
|
if os.path.realpath(os.getcwd()) != os.path.realpath(slepcdir):
|
sys.exit('ERROR: SLEPC_DIR is not the current directory')
|
sys.exit('ERROR: SLEPC_DIR is not the current directory')
|
|
|
if 'PETSC_DIR' not in os.environ:
|
if 'PETSC_DIR' not in os.environ:
|
sys.exit('ERROR: PETSC_DIR enviroment variable is not set')
|
sys.exit('ERROR: PETSC_DIR enviroment variable is not set')
|
petscdir = os.environ['PETSC_DIR']
|
petscdir = os.environ['PETSC_DIR']
|
if not os.path.exists(petscdir):
|
if not os.path.exists(petscdir):
|
sys.exit('ERROR: PETSC_DIR enviroment variable is not valid')
|
sys.exit('ERROR: PETSC_DIR enviroment variable is not valid')
|
|
|
# Check PETSc version
|
# Check PETSc version
|
petscversion.Load(petscdir)
|
petscversion.Load(petscdir)
|
if petscversion.VERSION < '3.0.0':
|
if petscversion.VERSION < '3.0.0':
|
sys.exit('ERROR: This SLEPc version is not compatible with PETSc version '+petscversion.VERSION)
|
sys.exit('ERROR: This SLEPc version is not compatible with PETSc version '+petscversion.VERSION)
|
|
|
# Check some information about PETSc configuration
|
# Check some information about PETSc configuration
|
petscconf.Load(petscdir)
|
petscconf.Load(petscdir)
|
if not petscconf.PRECISION in ['double','single','matsingle']:
|
if not petscconf.PRECISION in ['double','single','matsingle']:
|
sys.exit('ERROR: This SLEPc version does not work with '+petscconf.PRECISION+' precision')
|
sys.exit('ERROR: This SLEPc version does not work with '+petscconf.PRECISION+' precision')
|
if prefixdir and not petscconf.ISINSTALL:
|
if prefixdir and not petscconf.ISINSTALL:
|
sys.exit('ERROR: SLEPc cannot be configured for non-source installation if PETSc is not configured in the same way.')
|
sys.exit('ERROR: SLEPc cannot be configured for non-source installation if PETSc is not configured in the same way.')
|
|
|
# Create architecture directory and configuration file
|
# Create architecture directory and configuration file
|
archdir = os.sep.join([slepcdir,petscconf.ARCH])
|
archdir = os.sep.join([slepcdir,petscconf.ARCH])
|
if not os.path.exists(archdir):
|
if not os.path.exists(archdir):
|
try:
|
try:
|
os.mkdir(archdir)
|
os.mkdir(archdir)
|
except:
|
except:
|
sys.exit('ERROR: cannot create architecture directory ' + archdir)
|
sys.exit('ERROR: cannot create architecture directory ' + archdir)
|
confdir = os.sep.join([archdir,'conf'])
|
confdir = os.sep.join([archdir,'conf'])
|
if not os.path.exists(confdir):
|
if not os.path.exists(confdir):
|
try:
|
try:
|
os.mkdir(confdir)
|
os.mkdir(confdir)
|
except:
|
except:
|
sys.exit('ERROR: cannot create configuration directory ' + confdir)
|
sys.exit('ERROR: cannot create configuration directory ' + confdir)
|
incdir = os.sep.join([archdir,'include'])
|
incdir = os.sep.join([archdir,'include'])
|
if not os.path.exists(incdir):
|
if not os.path.exists(incdir):
|
try:
|
try:
|
os.mkdir(incdir)
|
os.mkdir(incdir)
|
except:
|
except:
|
sys.exit('ERROR: cannot create include directory ' + incdir)
|
sys.exit('ERROR: cannot create include directory ' + incdir)
|
try:
|
try:
|
slepcconf = open(os.sep.join([confdir,'slepcvariables']),'w')
|
slepcconf = open(os.sep.join([confdir,'slepcvariables']),'w')
|
if not prefixdir:
|
if not prefixdir:
|
prefixdir = archdir
|
prefixdir = archdir
|
slepcconf.write('SLEPC_INSTALL_DIR =' + prefixdir +'\n')
|
slepcconf.write('SLEPC_INSTALL_DIR =' + prefixdir +'\n')
|
except:
|
except:
|
sys.exit('ERROR: cannot create configuration file in ' + confdir)
|
sys.exit('ERROR: cannot create configuration file in ' + confdir)
|
|
|
# Open log file
|
# Open log file
|
log.Open(os.sep.join([confdir,'configure.log']))
|
log.Open(os.sep.join([confdir,'configure.log']))
|
log.Write('='*80)
|
log.Write('='*80)
|
log.Write('Starting Configure Run at '+time.ctime(time.time()))
|
log.Write('Starting Configure Run at '+time.ctime(time.time()))
|
log.Write('Configure Options: '+str.join(' ',sys.argv))
|
log.Write('Configure Options: '+str.join(' ',sys.argv))
|
log.Write('Working directory: '+os.getcwd())
|
log.Write('Working directory: '+os.getcwd())
|
log.Write('Python version:\n' + sys.version)
|
log.Write('Python version:\n' + sys.version)
|
log.Write('make: ' + petscconf.MAKE)
|
log.Write('make: ' + petscconf.MAKE)
|
log.Write('PETSc source directory: ' + petscdir)
|
log.Write('PETSc source directory: ' + petscdir)
|
log.Write('PETSc install directory: ' + petscconf.INSTALL_DIR)
|
log.Write('PETSc install directory: ' + petscconf.INSTALL_DIR)
|
log.Write('PETSc version: ' + petscversion.VERSION)
|
log.Write('PETSc version: ' + petscversion.VERSION)
|
log.Write('PETSc architecture: ' + petscconf.ARCH)
|
log.Write('PETSc architecture: ' + petscconf.ARCH)
|
log.Write('SLEPc source directory: ' + slepcdir)
|
log.Write('SLEPc source directory: ' + slepcdir)
|
log.Write('SLEPc install directory: ' + prefixdir)
|
log.Write('SLEPc install directory: ' + prefixdir)
|
log.Write('='*80)
|
log.Write('='*80)
|
|
|
# Check if PETSc is working
|
# Check if PETSc is working
|
log.Println('Checking PETSc installation...')
|
log.Println('Checking PETSc installation...')
|
if petscversion.VERSION > '3.0.0':
|
if petscversion.VERSION > '3.0.0':
|
log.Println('WARNING: PETSc version '+petscversion.VERSION+' is newer than SLEPc version')
|
log.Println('WARNING: PETSc version '+petscversion.VERSION+' is newer than SLEPc version')
|
if petscversion.RELEASE != '1':
|
if petscversion.RELEASE != '1':
|
log.Println('WARNING: using PETSc development version')
|
log.Println('WARNING: using PETSc development version')
|
if petscconf.ISINSTALL:
|
if petscconf.ISINSTALL:
|
if petscconf.INSTALL_DIR != petscdir:
|
if petscconf.INSTALL_DIR != petscdir:
|
log.Println('WARNING: PETSC_DIR does not point to PETSc installation path')
|
log.Println('WARNING: PETSC_DIR does not point to PETSc installation path')
|
if not check.Link([],[],[]):
|
if not check.Link([],[],[]):
|
log.Exit('ERROR: Unable to link with PETSc')
|
log.Exit('ERROR: Unable to link with PETSc')
|
|
|
# Check for external packages
|
# Check for external packages
|
if havearpack:
|
if havearpack:
|
arpacklibs = arpack.Check(slepcconf,arpackdir,arpacklibs)
|
arpacklibs = arpack.Check(slepcconf,arpackdir,arpacklibs)
|
if haveblzpack:
|
if haveblzpack:
|
blzpacklibs = blzpack.Check(slepcconf,blzpackdir,blzpacklibs)
|
blzpacklibs = blzpack.Check(slepcconf,blzpackdir,blzpacklibs)
|
if havetrlan:
|
if havetrlan:
|
trlanlibs = trlan.Check(slepcconf,trlandir,trlanlibs)
|
trlanlibs = trlan.Check(slepcconf,trlandir,trlanlibs)
|
if haveprimme:
|
if haveprimme:
|
primmelibs = primme.Check(slepcconf,primmedir,primmelibs)
|
primmelibs = primme.Check(slepcconf,primmedir,primmelibs)
|
|
|
# Check for missing LAPACK functions
|
# Check for missing LAPACK functions
|
missing = lapack.Check(slepcconf)
|
missing = lapack.Check(slepcconf)
|
|
|
slepcconf.close()
|
slepcconf.close()
|
|
|
log.Println('')
|
log.Println('')
|
log.Println('='*80)
|
log.Println('='*80)
|
log.Println('SLEPc Configuration')
|
log.Println('SLEPc Configuration')
|
log.Println('='*80)
|
log.Println('='*80)
|
log.Println('')
|
log.Println('')
|
log.Println('SLEPc source directory:')
|
log.Println('SLEPc source directory:')
|
log.Println(' '+slepcdir)
|
log.Println(' '+slepcdir)
|
log.Println('SLEPc install directory:')
|
log.Println('SLEPc install directory:')
|
log.Println(' '+prefixdir)
|
log.Println(' '+prefixdir)
|
log.Println('PETSc directory:')
|
log.Println('PETSc directory:')
|
log.Println(' '+petscdir)
|
log.Println(' '+petscdir)
|
log.Println('Architecture "'+petscconf.ARCH+'" with '+petscconf.PRECISION+' precision '+petscconf.SCALAR+' numbers')
|
log.Println('Architecture "'+petscconf.ARCH+'" with '+petscconf.PRECISION+' precision '+petscconf.SCALAR+' numbers')
|
if havearpack:
|
if havearpack:
|
log.Println('ARPACK library flags:')
|
log.Println('ARPACK library flags:')
|
log.Println(' '+str.join(' ',arpacklibs))
|
log.Println(' '+str.join(' ',arpacklibs))
|
if haveblzpack:
|
if haveblzpack:
|
log.Println('BLZPACK library flags:')
|
log.Println('BLZPACK library flags:')
|
log.Println(' '+str.join(' ',blzpacklibs))
|
log.Println(' '+str.join(' ',blzpacklibs))
|
if havetrlan:
|
if havetrlan:
|
log.Println('TRLAN library flags:')
|
log.Println('TRLAN library flags:')
|
log.Println(' '+str.join(' ',trlanlibs))
|
log.Println(' '+str.join(' ',trlanlibs))
|
if haveprimme:
|
if haveprimme:
|
log.Println('PRIMME library flags:')
|
log.Println('PRIMME library flags:')
|
log.Println(' '+str.join(' ',primmelibs))
|
log.Println(' '+str.join(' ',primmelibs))
|
if missing:
|
if missing:
|
log.Println('LAPACK missing functions:')
|
log.Println('LAPACK missing functions:')
|
log.Print(' ')
|
log.Print(' ')
|
for i in missing: log.Print(i)
|
for i in missing: log.Print(i)
|
log.Println('')
|
log.Println('')
|
log.Println('')
|
log.Println('')
|
log.Println('WARNING: Some SLEPc functionality will not be available')
|
log.Println('WARNING: Some SLEPc functionality will not be available')
|
log.Println('PLEASE reconfigure and recompile PETSc with a full LAPACK implementation')
|
log.Println('PLEASE reconfigure and recompile PETSc with a full LAPACK implementation')
|
if petscconf.ISINSTALL:
|
if petscconf.ISINSTALL:
|
log.Println('')
|
log.Println('')
|
log.Println(' **')
|
log.Println(' **')
|
log.Println(' ** Before running "make" your PETSC_ARCH must be specified with:')
|
log.Println(' ** Before running "make" your PETSC_ARCH must be specified with:')
|
log.Println(' ** ** setenv PETSC_ARCH '+petscconf.ARCH+' (csh/tcsh)')
|
log.Println(' ** ** setenv PETSC_ARCH '+petscconf.ARCH+' (csh/tcsh)')
|
log.Println(' ** ** PETSC_ARCH='+petscconf.ARCH+' ; export PETSC_ARCH (sh/bash)')
|
log.Println(' ** ** PETSC_ARCH='+petscconf.ARCH+' ; export PETSC_ARCH (sh/bash)')
|
log.Println(' **')
|
log.Println(' **')
|
print
|
print
|
|
|
|
|