diff options
author | Stefan van der Walt <stefan@sun.ac.za> | 2008-02-09 00:45:11 +0000 |
---|---|---|
committer | Stefan van der Walt <stefan@sun.ac.za> | 2008-02-09 00:45:11 +0000 |
commit | fbc211df7a2ebd27efe45cf4f943e21f5ad9b104 (patch) | |
tree | 9cea7049a873c0cd38bda75a5a5fe8d2d401b4fd /numpy | |
parent | a2df3f7818deaf51d08b8bd9095e05d1011b46a5 (diff) | |
parent | d42ab1598a44cb00bffcc907605013eca012dbf9 (diff) | |
download | numpy-fbc211df7a2ebd27efe45cf4f943e21f5ad9b104.tar.gz |
Merge maskedarray branch up to r4776.
Diffstat (limited to 'numpy')
48 files changed, 1892 insertions, 241 deletions
diff --git a/numpy/_import_tools.py b/numpy/_import_tools.py index d289a752b..4053057ab 100644 --- a/numpy/_import_tools.py +++ b/numpy/_import_tools.py @@ -152,10 +152,10 @@ class PackageLoader: Parameters ---------- - *packges : arg-tuple + *packges : arg-tuple the names (one or more strings) of all the modules one wishes to load into the top-level namespace. - verbose= : integer + verbose= : integer verbosity level [default: -1]. verbose=-1 will suspend also warnings. force= : bool diff --git a/numpy/add_newdocs.py b/numpy/add_newdocs.py index 91c6a6e80..7955beca7 100644 --- a/numpy/add_newdocs.py +++ b/numpy/add_newdocs.py @@ -1,7 +1,7 @@ # This is only meant to add docs to # objects defined in C-extension modules. # The purpose is to allow easier editing of the -# docstrings without requiring a re-compile. +# docstrings without requiring a re-compile. from lib import add_newdoc add_newdoc('numpy.core','dtype', @@ -216,6 +216,7 @@ add_newdoc('numpy.core.multiarray','fromstring', size is determined by the size of string. If sep is not empty then the string is interpreted in ASCII mode and converted to the desired number type using sep as the separator between elements (extra whitespace is ignored). + ASCII integer conversions are base-10; octal and hex are not supported. """) @@ -237,7 +238,7 @@ add_newdoc('numpy.core.multiarray','fromfile', open file object or string containing file name. dtype : data-type data type of the returned array - count : int + count : int number of items to read (-1 mean 'all') sep : string separater between items if file is a text file (default "") @@ -1106,8 +1107,8 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('round', is done if the array is not of float type and 'decimals' is >= 0. The keyword 'out' may be used to specify a different array to hold the - result rather than the default new array. If the type of the array - specified by 'out' differs from that of 'a', the result is cast to the + result rather than the default new array. If the type of the array + specified by 'out' differs from that of 'a', the result is cast to the new type, otherwise the original type is kept. Floats round to floats by default. @@ -1208,7 +1209,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('sort', |'heapsort' | 3 | O(n*log(n)) | 0 | no | |------------------------------------------------------| - All the sort algorithms make temporary copies of the data when the sort is + All the sort algorithms make temporary copies of the data when the sort is not along the last axis. Consequently, sorts along the last axis are faster and use less space than sorts along other axis. """)) diff --git a/numpy/core/SConstruct b/numpy/core/SConstruct new file mode 100644 index 000000000..209d642c7 --- /dev/null +++ b/numpy/core/SConstruct @@ -0,0 +1,292 @@ +# Last Change: Wed Jan 23 08:00 PM 2008 J +# vim:syntax=python +import os +import sys +from os.path import join as pjoin, basename as pbasename, dirname as pdirname +from copy import deepcopy + +from numscons import get_python_inc, get_pythonlib_dir +from numscons import GetNumpyEnvironment +from numscons import CheckCBLAS +from numscons import write_info + +from scons_support import CheckBrokenMathlib, define_no_smp, \ + check_mlib, check_mlibs, is_npy_no_signal + +env = GetNumpyEnvironment(ARGUMENTS) +env.Append(CPPPATH = [get_python_inc()]) +if os.name == 'nt': + # NT needs the pythonlib to run any code importing Python.h, including + # simple code using only typedef and so on, so we need it for configuration + # checks + env.AppendUnique(LIBPATH = [get_pythonlib_dir()]) + +#======================= +# Starting Configuration +#======================= +config = env.NumpyConfigure(custom_tests = {'CheckBrokenMathlib' : CheckBrokenMathlib, + 'CheckCBLAS' : CheckCBLAS}, config_h = pjoin(env['build_dir'], 'config.h')) + +# numpyconfig_sym will keep the values of some configuration variables, the one +# needed for the public numpy API. + +# Convention: list of tuples (definition, value). value: +# - 0: #undef definition +# - 1: #define definition +# - string: #define definition value +numpyconfig_sym = [] + +#--------------- +# Checking Types +#--------------- +def check_type(type, include = None): + st = config.CheckTypeSize(type, includes = include) + type = type.replace(' ', '_') + if st: + numpyconfig_sym.append(('SIZEOF_%s' % type.upper(), '%d' % st)) + else: + numpyconfig_sym.append(('SIZEOF_%s' % type.upper(), 0)) + +for type in ('short', 'int', 'long', 'float', 'double', 'long double'): + check_type(type) + +for type in ('Py_intptr_t',): + check_type(type, include = "#include <Python.h>\n") + +# We check declaration AND type because that's how distutils does it. +if config.CheckDeclaration('PY_LONG_LONG', includes = '#include <Python.h>\n'): + st = config.CheckTypeSize('PY_LONG_LONG', includes = '#include <Python.h>\n') + assert not st == 0 + numpyconfig_sym.append(('DEFINE_NPY_SIZEOF_LONGLONG', '#define NPY_SIZEOF_LONGLONG %d' % st)) + numpyconfig_sym.append(('DEFINE_NPY_SIZEOF_PY_LONG_LONG', '#define NPY_SIZEOF_PY_LONG_LONG %d' % st)) +else: + numpyconfig_sym.append(('DEFINE_NPY_SIZEOF_LONGLONG', '')) + numpyconfig_sym.append(('DEFINE_NPY_SIZEOF_PY_LONG_LONG', '')) + +if not config.CheckDeclaration('CHAR_BIT', includes= '#include <Python.h>\n'): + raise RuntimeError("Config wo CHAR_BIT is not supported with scons: please contact the maintainer (cdavid)") + +#---------------------- +# Checking signal stuff +#---------------------- +if is_npy_no_signal(): + numpyconfig_sym.append(('DEFINE_NPY_NO_SIGNAL', '#define NPY_NO_SIGNAL\n')) + config.Define('__NPY_PRIVATE_NO_SIGNAL', comment = "define to 1 to disable SMP support ") +else: + numpyconfig_sym.append(('DEFINE_NPY_NO_SIGNAL', '')) + +#--------------------- +# Checking SMP option +#--------------------- +if define_no_smp(): + nosmp = 1 +else: + nosmp = 0 +numpyconfig_sym.append(('NPY_NO_SMP', nosmp)) + +#---------------------- +# Checking the mathlib +#---------------------- +mlibs = [[], ['m'], ['cpml']] +mathlib = os.environ.get('MATHLIB') +if mathlib: + mlibs.insert(0, mathlib) + +mlib = check_mlibs(config, mlibs) + +# XXX: this is ugly: mathlib has nothing to do in a public header file +numpyconfig_sym.append(('MATHLIB', ','.join(mlib))) + +#---------------------------------- +# Checking the math funcs available +#---------------------------------- +# Function to check: +mfuncs = ('expl', 'expf', 'log1p', 'expm1', 'asinh', 'atanhf', 'atanhl', + 'isnan', 'isinf', 'rint') + +# Set value to 1 for each defined function (in math lib) +mfuncs_defined = dict([(f, 0) for f in mfuncs]) + +# TODO: checklib vs checkfunc ? +def check_func(f): + """Check that f is available in mlib, and add the symbol appropriately. """ + st = config.CheckDeclaration(f, language = 'C', includes = "#include <math.h>") + if st: + st = config.CheckFunc(f, language = 'C') + if st: + mfuncs_defined[f] = 1 + else: + mfuncs_defined[f] = 0 + +for f in mfuncs: + check_func(f) + +if mfuncs_defined['expl'] == 1: + config.Define('HAVE_LONGDOUBLE_FUNCS', + comment = 'Define to 1 if long double funcs are available') +if mfuncs_defined['expf'] == 1: + config.Define('HAVE_FLOAT_FUNCS', + comment = 'Define to 1 if long double funcs are available') +if mfuncs_defined['asinh'] == 1: + config.Define('HAVE_INVERSE_HYPERBOLIC', + comment = 'Define to 1 if inverse hyperbolic funcs are available') +if mfuncs_defined['atanhf'] == 1: + config.Define('HAVE_INVERSE_HYPERBOLIC_FLOAT', + comment = 'Define to 1 if inverse hyperbolic float funcs are available') +if mfuncs_defined['atanhl'] == 1: + config.Define('HAVE_INVERSE_HYPERBOLIC_LONGDOUBLE', + comment = 'Define to 1 if inverse hyperbolic long double funcs are available') + +#------------------------------------------------------- +# Define the function PyOS_ascii_strod if not available +#------------------------------------------------------- +if not config.CheckDeclaration('PyOS_ascii_strtod', + includes = "#include <Python.h>"): + if config.CheckFunc('strtod'): + config.Define('PyOS_ascii_strtod', 'strtod', + "Define to a function to use as a replacement for "\ + "PyOS_ascii_strtod if not available in python header") + +#------------------------------------ +# DISTUTILS Hack on AMD64 on windows +#------------------------------------ +# XXX: this is ugly +if sys.platform=='win32' or os.name=='nt': + from distutils.msvccompiler import get_build_architecture + a = get_build_architecture() + print 'BUILD_ARCHITECTURE: %r, os.name=%r, sys.platform=%r' % (a, os.name, sys.platform) + if a == 'AMD64': + distutils_use_sdk = 1 + config.Define('DISTUTILS_USE_SDK', distutils_use_sdk, + "define to 1 to disable SMP support ") + +#-------------- +# Checking Blas +#-------------- +if config.CheckCBLAS(): + build_blasdot = 1 +else: + build_blasdot = 0 + +config.Finish() +write_info(env) + +#========== +# Build +#========== + +#--------------------------------------- +# Generate the public configuration file +#--------------------------------------- +config_dict = {} +# XXX: this is ugly, make the API for config.h and numpyconfig.h similar +for key, value in numpyconfig_sym: + config_dict['@%s@' % key] = str(value) +env['SUBST_DICT'] = config_dict + +include_dir = 'include/numpy' +env.SubstInFile(pjoin(env['build_dir'], 'numpyconfig.h'), + pjoin(env['src_dir'], include_dir, 'numpyconfig.h.in')) + +env['CONFIG_H_GEN'] = numpyconfig_sym + +#--------------------------- +# Builder for generated code +#--------------------------- +from scons_support import do_generate_array_api, do_generate_ufunc_api, \ + generate_api_emitter,\ + generate_from_template, generate_from_template_emitter, \ + generate_umath, generate_umath_emitter + +array_api_gen_bld = Builder(action = do_generate_array_api, + emitter = generate_api_emitter) + +ufunc_api_gen_bld = Builder(action = do_generate_ufunc_api, + emitter = generate_api_emitter) + +template_bld = Builder(action = generate_from_template, + emitter = generate_from_template_emitter) + +umath_bld = Builder(action = generate_umath, + emitter = generate_umath_emitter) + +env.Append(BUILDERS = {'GenerateMultiarrayApi' : array_api_gen_bld, + 'GenerateUfuncApi' : ufunc_api_gen_bld, + 'GenerateFromTemplate' : template_bld, + 'GenerateUmath' : umath_bld}) + +#------------------------ +# Generate generated code +#------------------------ +# XXX: the use of env['build_dir'] and env['src_dir'] are really ugly. Will +# have to think about how removing them (using hierarchical scons and dir +# option ?) +from os.path import join as pjoin + +scalartypes_src = env.GenerateFromTemplate( + pjoin(env['build_dir'], 'src', 'scalartypes'), + pjoin(env['src_dir'], 'src', 'scalartypes.inc.src')) + +arraytypes_src = env.GenerateFromTemplate( + pjoin(env['build_dir'], 'src', 'arraytypes'), + pjoin(env['src_dir'], 'src', 'arraytypes.inc.src')) + +sortmodule_src = env.GenerateFromTemplate( + pjoin(env['build_dir'], 'src', '_sortmodule'), + pjoin(env['src_dir'], 'src', '_sortmodule.c.src')) + +umathmodule_src = env.GenerateFromTemplate( + pjoin(env['build_dir'], 'src', 'umathmodule'), + pjoin(env['src_dir'], 'src', 'umathmodule.c.src')) + +scalarmathmodule_src = env.GenerateFromTemplate( + pjoin(env['build_dir'], 'src', 'scalarmathmodule'), + pjoin(env['src_dir'], 'src', 'scalarmathmodule.c.src')) + +umath = env.GenerateUmath( + pjoin(env['build_dir'], '__umath_generated'), + pjoin(env['src_dir'], 'code_generators', 'generate_umath.py')) + +multiarray_api = env.GenerateMultiarrayApi( + pjoin(env['build_dir'], 'multiarray_api'), + [ pjoin(env['src_dir'], 'code_generators', + 'array_api_order.txt'), + pjoin(env['src_dir'], 'code_generators', + 'multiarray_api_order.txt')]) + +ufunc_api = env.GenerateUfuncApi( + pjoin(env['build_dir'], 'ufunc_api'), + pjoin(env['src_dir'], 'code_generators', 'ufunc_api_order.txt')) + +env.Append(CPPPATH = [pjoin(env['src_dir'], 'include'), env['build_dir']]) + +#----------------- +# Build multiarray +#----------------- +multiarray_src = [pjoin('src', 'multiarraymodule.c')] +multiarray = env.NumpyPythonExtension('multiarray', source = multiarray_src) + +#------------------ +# Build sort module +#------------------ +sort = env.NumpyPythonExtension('_sort', source = sortmodule_src) + +#------------------- +# Build umath module +#------------------- +umathmodule = env.NumpyPythonExtension('umath', source = umathmodule_src) + +#------------------------ +# Build scalarmath module +#------------------------ +scalarmathmodule = env.NumpyPythonExtension('scalarmath', + source = scalarmathmodule_src) + +#---------------------- +# Build _dotblas module +#---------------------- +if build_blasdot: + dotblas_src = [pjoin('blasdot', i) for i in ['_dotblas.c']] + blasenv = env.Copy() + blasenv.Append(CPPPATH = pjoin(env['src_dir'], 'blasdot')) + dotblas = blasenv.NumpyPythonExtension('_dotblas', source = dotblas_src) diff --git a/numpy/core/code_generators/__init__.py b/numpy/core/code_generators/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/numpy/core/code_generators/__init__.py diff --git a/numpy/core/code_generators/generate_array_api.py b/numpy/core/code_generators/generate_array_api.py index c6f73c33f..94ab37fa3 100644 --- a/numpy/core/code_generators/generate_array_api.py +++ b/numpy/core/code_generators/generate_array_api.py @@ -1,9 +1,6 @@ import os import genapi -OBJECT_API_ORDER = 'array_api_order.txt' -MULTIARRAY_API_ORDER = 'multiarray_api_order.txt' - types = ['Generic','Number','Integer','SignedInteger','UnsignedInteger', 'Inexact', 'Floating', 'ComplexFloating', 'Flexible', 'Character', @@ -122,22 +119,30 @@ void *PyArray_API[] = { """ def generate_api(output_dir, force=False): - header_file = os.path.join(output_dir, '__multiarray_api.h') - c_file = os.path.join(output_dir,'__multiarray_api.c') - doc_file = os.path.join(output_dir, 'multiarray_api.txt') - - targets = (header_file, c_file, doc_file) - if (not force - and not genapi.should_rebuild(targets, - [OBJECT_API_ORDER, - MULTIARRAY_API_ORDER, - __file__])): + basename = 'multiarray_api' + + h_file = os.path.join(output_dir, '__%s.h' % basename) + c_file = os.path.join(output_dir, '__%s.c' % basename) + d_file = os.path.join(output_dir, '%s.txt' % basename) + targets = (h_file, c_file, d_file) + sources = ['array_api_order.txt', 'multiarray_api_order.txt'] + + if (not force and not genapi.should_rebuild(targets, sources + [__file__])): return targets + else: + do_generate_api(targets, sources) + + return targets + +def do_generate_api(targets, sources): + header_file = targets[0] + c_file = targets[1] + doc_file = targets[2] objectapi_list = genapi.get_api_functions('OBJECT_API', - OBJECT_API_ORDER) + sources[0]) multiapi_list = genapi.get_api_functions('MULTIARRAY_API', - MULTIARRAY_API_ORDER) + sources[1]) # API fixes for __arrayobject_api.h fixed = 10 diff --git a/numpy/core/code_generators/generate_ufunc_api.py b/numpy/core/code_generators/generate_ufunc_api.py index 96bb47cae..a7afc5aaa 100644 --- a/numpy/core/code_generators/generate_ufunc_api.py +++ b/numpy/core/code_generators/generate_ufunc_api.py @@ -1,8 +1,6 @@ import os import genapi -UFUNC_API_ORDER = 'ufunc_api_order.txt' - h_template = r""" #ifdef _UMATHMODULE @@ -72,17 +70,28 @@ void *PyUFunc_API[] = { """ def generate_api(output_dir, force=False): - header_file = os.path.join(output_dir, '__ufunc_api.h') - c_file = os.path.join(output_dir, '__ufunc_api.c') - doc_file = os.path.join(output_dir, 'ufunc_api.txt') - - targets = (header_file, c_file, doc_file) - if (not force - and not genapi.should_rebuild(targets, - [UFUNC_API_ORDER, __file__])): + basename = 'ufunc_api' + + h_file = os.path.join(output_dir, '__%s.h' % basename) + c_file = os.path.join(output_dir, '__%s.c' % basename) + d_file = os.path.join(output_dir, '%s.txt' % basename) + targets = (h_file, c_file, d_file) + + sources = ['ufunc_api_order.txt'] + + if (not force and not genapi.should_rebuild(targets, sources + [__file__])): return targets + else: + do_generate_api(targets, sources) + + return targets + +def do_generate_api(targets, sources): + header_file = targets[0] + c_file = targets[1] + doc_file = targets[2] - ufunc_api_list = genapi.get_api_functions('UFUNC_API', UFUNC_API_ORDER) + ufunc_api_list = genapi.get_api_functions('UFUNC_API', sources[0]) # API fixes for __arrayobject_api.h diff --git a/numpy/core/defmatrix.py b/numpy/core/defmatrix.py index 7e1cacfce..c3f57efdf 100644 --- a/numpy/core/defmatrix.py +++ b/numpy/core/defmatrix.py @@ -51,16 +51,16 @@ def asmatrix(data, dtype=None): class matrix(N.ndarray): """mat = matrix(data, dtype=None, copy=True) - Returns a matrix from an array-like object, or a string of + Returns a matrix from an array-like object, or a string of data. A matrix is a specialized 2-d array that retains it's 2-d nature through operations and where '*' means matrix - multiplication and '**' means matrix power. + multiplication and '**' means matrix power. Parameters ---------- data : array-like or string - If data is a string, then interpret the string as a matrix - with commas or spaces separating columns and semicolons + If data is a string, then interpret the string as a matrix + with commas or spaces separating columns and semicolons separating rows. If data is array-like than convert the array to a matrix. dtype : data-type @@ -273,7 +273,7 @@ class matrix(N.ndarray): the flattened array by default, otherwise over the specified axis. Parameters - ---------- + ---------- axis : integer Axis along which the means are computed. The default is to compute the standard deviation of the flattened array. @@ -289,7 +289,7 @@ class matrix(N.ndarray): cast if necessary. Returns - ------- + ------- mean : The return type varies, see above. A new array holding the result is returned unless out is specified, in which case a reference to out is returned. @@ -342,7 +342,7 @@ class matrix(N.ndarray): mean : average Notes - ----- + ----- The standard deviation is the square root of the average of the squared deviations from the mean, i.e. var = sqrt(mean((x - x.mean())**2)). The computed standard @@ -362,7 +362,7 @@ class matrix(N.ndarray): ---------- axis : integer Axis along which the variance is computed. The default is to - compute the variance of the flattened array. + compute the variance of the flattened array. dtype : data-type Type to use in computing the variance. For arrays of integer type the default is float32, for arrays of float types it is diff --git a/numpy/core/include/numpy/ndarrayobject.h b/numpy/core/include/numpy/ndarrayobject.h index 62986a9eb..3b1376cd3 100644 --- a/numpy/core/include/numpy/ndarrayobject.h +++ b/numpy/core/include/numpy/ndarrayobject.h @@ -13,7 +13,14 @@ extern "C" CONFUSE_EMACS everything when you're typing */ #endif /* This is auto-generated by the installer */ -#include "config.h" +#include "numpyconfig.h" + +/* Only use thread if configured in config and python supports it */ +#if defined WITH_THREAD && !NPY_NO_SMP + #define NPY_ALLOW_THREADS 1 +#else + #define NPY_ALLOW_THREADS 0 +#endif /* There are several places in the code where an array of dimensions is * allocated statically. This is the size of that static allocation. @@ -80,7 +87,8 @@ typedef unsigned char npy_bool; #define NPY_FALSE 0 #define NPY_TRUE 1 -#if SIZEOF_LONG_DOUBLE==SIZEOF_DOUBLE + +#if NPY_SIZEOF_LONGDOUBLE == NPY_SIZEOF_DOUBLE typedef double npy_longdouble; #define NPY_LONGDOUBLE_FMT "g" #else @@ -279,22 +287,15 @@ typedef enum { #define NPY_MAX_ULONG ULONG_MAX -#define NPY_SIZEOF_LONG SIZEOF_LONG -#define NPY_SIZEOF_INT SIZEOF_INT -#define NPY_SIZEOF_SHORT SIZEOF_SHORT -#define NPY_SIZEOF_FLOAT SIZEOF_FLOAT -#define NPY_SIZEOF_DOUBLE SIZEOF_DOUBLE -#define NPY_SIZEOF_LONGDOUBLE SIZEOF_LONG_DOUBLE -#define NPY_SIZEOF_LONGLONG SIZEOF_LONG_LONG #define NPY_BITSOF_BOOL (sizeof(npy_bool)*CHAR_BIT) #define NPY_BITSOF_CHAR CHAR_BIT -#define NPY_BITSOF_SHORT (SIZEOF_SHORT*CHAR_BIT) -#define NPY_BITSOF_INT (SIZEOF_INT*CHAR_BIT) -#define NPY_BITSOF_LONG (SIZEOF_LONG*CHAR_BIT) -#define NPY_BITSOF_LONGLONG (NPY_SIZEOF_LONGLONG*CHAR_BIT) -#define NPY_BITSOF_FLOAT (SIZEOF_FLOAT*CHAR_BIT) -#define NPY_BITSOF_DOUBLE (SIZEOF_DOUBLE*CHAR_BIT) -#define NPY_BITSOF_LONGDOUBLE (NPY_SIZEOF_LONGDOUBLE*CHAR_BIT) +#define NPY_BITSOF_SHORT (NPY_SIZEOF_SHORT * CHAR_BIT) +#define NPY_BITSOF_INT (NPY_SIZEOF_INT * CHAR_BIT) +#define NPY_BITSOF_LONG (NPY_SIZEOF_LONG * CHAR_BIT) +#define NPY_BITSOF_LONGLONG (NPY_SIZEOF_LONGLONG * CHAR_BIT) +#define NPY_BITSOF_FLOAT (NPY_SIZEOF_FLOAT * CHAR_BIT) +#define NPY_BITSOF_DOUBLE (NPY_SIZEOF_DOUBLE * CHAR_BIT) +#define NPY_BITSOF_LONGDOUBLE (NPY_SIZEOF_LONGDOUBLE * CHAR_BIT) #if NPY_BITSOF_LONG == 8 #define NPY_INT8 NPY_LONG @@ -918,8 +919,8 @@ typedef enum { * platform. Py_intptr_t, Py_uintptr_t are defined in pyport.h. */ typedef Py_intptr_t npy_intp; typedef Py_uintptr_t npy_uintp; -#define NPY_SIZEOF_INTP SIZEOF_PY_INTPTR_T -#define NPY_SIZEOF_UINTP SIZEOF_PY_INTPTR_T +#define NPY_SIZEOF_INTP NPY_SIZEOF_PY_INTPTR_T +#define NPY_SIZEOF_UINTP NPY_SIZEOF_PY_INTPTR_T #ifdef constchar #undef constchar @@ -940,7 +941,7 @@ typedef Py_uintptr_t npy_uintp; #define constchar char #endif -#if SIZEOF_PY_INTPTR_T == SIZEOF_INT +#if NPY_SIZEOF_PY_INTPTR_T == NPY_SIZEOF_INT #define NPY_INTP NPY_INT #define NPY_UINTP NPY_UINT #define PyIntpArrType_Type PyIntArrType_Type @@ -949,7 +950,7 @@ typedef Py_uintptr_t npy_uintp; #define NPY_MIN_INTP NPY_MIN_INT #define NPY_MAX_UINTP NPY_MAX_UINT #define NPY_INTP_FMT "d" -#elif SIZEOF_PY_INTPTR_T == SIZEOF_LONG +#elif NPY_SIZEOF_PY_INTPTR_T == NPY_SIZEOF_LONG #define NPY_INTP NPY_LONG #define NPY_UINTP NPY_ULONG #define PyIntpArrType_Type PyLongArrType_Type @@ -958,7 +959,7 @@ typedef Py_uintptr_t npy_uintp; #define NPY_MIN_INTP MIN_LONG #define NPY_MAX_UINTP NPY_MAX_ULONG #define NPY_INTP_FMT "ld" -#elif defined(PY_LONG_LONG) && (SIZEOF_PY_INTPTR_T == SIZEOF_LONG_LONG) +#elif defined(PY_LONG_LONG) && (NPY_SIZEOF_PY_INTPTR_T == NPY_SIZEOF_LONGLONG) #define NPY_INTP NPY_LONGLONG #define NPY_UINTP NPY_ULONGLONG #define PyIntpArrType_Type PyLongLongArrType_Type @@ -1894,7 +1895,7 @@ typedef struct { #define PyArray_REFCOUNT(obj) (((PyObject *)(obj))->ob_refcnt) #define NPY_REFCOUNT PyArray_REFCOUNT -#define NPY_MAX_ELSIZE (2*SIZEOF_LONGDOUBLE) +#define NPY_MAX_ELSIZE (2 * NPY_SIZEOF_LONGDOUBLE) #define PyArray_ContiguousFromAny(op, type, min_depth, max_depth) \ PyArray_FromAny(op, PyArray_DescrFromType(type), min_depth, \ diff --git a/numpy/core/include/numpy/numpyconfig.h.in b/numpy/core/include/numpy/numpyconfig.h.in new file mode 100644 index 000000000..929dc720d --- /dev/null +++ b/numpy/core/include/numpy/numpyconfig.h.in @@ -0,0 +1,16 @@ +#define NPY_SIZEOF_SHORT @SIZEOF_SHORT@ +#define NPY_SIZEOF_INT @SIZEOF_INT@ +#define NPY_SIZEOF_LONG @SIZEOF_LONG@ +#define NPY_SIZEOF_FLOAT @SIZEOF_FLOAT@ +#define NPY_SIZEOF_DOUBLE @SIZEOF_DOUBLE@ +#define NPY_SIZEOF_LONGDOUBLE @SIZEOF_LONG_DOUBLE@ +#define NPY_SIZEOF_PY_INTPTR_T @SIZEOF_PY_INTPTR_T@ + +@DEFINE_NPY_NO_SIGNAL@ +#define NPY_NO_SMP @NPY_NO_SMP@ + +/* XXX: this has really nothing to do in a config file... */ +#define NPY_MATHLIB @MATHLIB@ + +@DEFINE_NPY_SIZEOF_LONGLONG@ +@DEFINE_NPY_SIZEOF_PY_LONG_LONG@ diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index 312db3510..00c70256f 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -149,7 +149,7 @@ def asfortranarray(a, dtype=None): def require(a, dtype=None, requirements=None): """Return an ndarray of the provided type that satisfies requirements. - + This function is useful to be sure that an array with the correct flags is returned for passing to compiled code (perhaps through ctypes). @@ -160,7 +160,7 @@ def require(a, dtype=None, requirements=None): dtype : data-type The required data-type (None is the default data-type -- float64) requirements : list of strings - The requirements list can be any of the + The requirements list can be any of the 'ENSUREARRAY' ('E') - ensure that a base-class ndarray 'F_CONTIGUOUS' ('F') - ensure a Fortran-contiguous array 'C_CONTIGUOUS' ('C') - ensure a C-contiguous array @@ -169,7 +169,7 @@ def require(a, dtype=None, requirements=None): 'OWNDATA' ('O') - ensure an array that owns its own data The returned array will be guaranteed to have the listed requirements - by making a copy if needed. + by making a copy if needed. """ if requirements is None: requirements = [] @@ -276,7 +276,7 @@ def vdot(a, b): try: # importing this changes the dot function for basic 4 types # to blas-optimized versions. - from _dotblas import dot, vdot, inner, alterdot, restoredot + from _dotblas import dot, vdot, inner, alterdot, restoredot except ImportError: def alterdot(): "Does Nothing" diff --git a/numpy/core/records.py b/numpy/core/records.py index 2067ed059..f9826376e 100644 --- a/numpy/core/records.py +++ b/numpy/core/records.py @@ -45,9 +45,9 @@ def find_duplicate(list): class format_parser: """Class to convert formats, names, titles description to a dtype - After constructing the format_parser object, the dtype attribute is + After constructing the format_parser object, the dtype attribute is the converted data-type. - + dtype = format_parser(formats, names, titles).dtype Parameters @@ -59,18 +59,18 @@ class format_parser: comma-separated field names --- 'col1, col2, col3' list or tuple of field names titles : sequence - sequence of title strings or unicode + sequence of title strings or unicode aligned : bool align the fields by padding as the C-compiler would - byteorder : - If specified, all the fields will be changed to the + byteorder : + If specified, all the fields will be changed to the provided byteorder. Otherwise, the default byteorder is used. Returns ------- object - A Python object whose dtype attribute is a data-type. + A Python object whose dtype attribute is a data-type. """ def __init__(self, formats, names, titles, aligned=False, byteorder=None): self._parseFormats(formats, aligned) @@ -227,9 +227,9 @@ class recarray(ndarray): by the *formats*, *names*, *titles*, *aligned*, and *byteorder* keywords. buf : [buffer] or None If this is None, then a new array is created of the given shape and data-type - If this is an object exposing the buffer interface, then the array will - use the memory from an existing buffer. In this case, the *offset* and - *strides* keywords can also be used. + If this is an object exposing the buffer interface, then the array will + use the memory from an existing buffer. In this case, the *offset* and + *strides* keywords can also be used. See Also -------- diff --git a/numpy/core/scons_support.py b/numpy/core/scons_support.py new file mode 100644 index 000000000..bb4721744 --- /dev/null +++ b/numpy/core/scons_support.py @@ -0,0 +1,183 @@ +#! Last Change: Tue Jan 08 10:00 PM 2008 J + +"""Code to support special facilities to scons which are only useful for +numpy.core, hence not put into numpy.distutils.scons""" + +import sys +import os + +from os.path import join as pjoin, dirname as pdirname, basename as pbasename +from copy import deepcopy + +from code_generators.generate_array_api import \ + do_generate_api as nowrap_do_generate_array_api +from code_generators.generate_ufunc_api import \ + do_generate_api as nowrap_do_generate_ufunc_api + +from numscons.numdist import process_c_str as process_str +from numscons.core.utils import rsplit, isstring + +import SCons.Node +import SCons + +def split_ext(string): + sp = rsplit(string, '.', 1) + if len(sp) == 1: + return (sp[0], '') + else: + return sp +#------------------------------------ +# Ufunc and multiarray API generators +#------------------------------------ +def do_generate_array_api(target, source, env): + nowrap_do_generate_array_api([str(i) for i in target], + [str(i) for i in source]) + return 0 + +def do_generate_ufunc_api(target, source, env): + nowrap_do_generate_ufunc_api([str(i) for i in target], + [str(i) for i in source]) + return 0 + +def generate_api_emitter(target, source, env): + """Returns the list of targets generated by the code generator for array + api and ufunc api.""" + base, ext = split_ext(str(target[0])) + dir = pdirname(base) + ba = pbasename(base) + h = pjoin(dir, '__' + ba + '.h') + c = pjoin(dir, '__' + ba + '.c') + txt = base + '.txt' + #print h, c, txt + t = [h, c, txt] + return (t, source) + +#------------------------- +# From template generators +#------------------------- +# XXX: this is general and can be used outside numpy.core. +def do_generate_from_template(targetfile, sourcefile, env): + t = open(targetfile, 'w') + s = open(sourcefile, 'r') + allstr = s.read() + s.close() + writestr = process_str(allstr) + t.write(writestr) + t.close() + return 0 + +def generate_from_template(target, source, env): + for t, s in zip(target, source): + do_generate_from_template(str(t), str(s), env) + +def generate_from_template_emitter(target, source, env): + base, ext = split_ext(pbasename(str(source[0]))) + t = pjoin(pdirname(str(target[0])), base) + return ([t], source) + +#---------------- +# umath generator +#---------------- +def do_generate_umath(targetfile, sourcefile, env): + t = open(targetfile, 'w') + from code_generators import generate_umath + code = generate_umath.make_code(generate_umath.defdict, generate_umath.__file__) + t.write(code) + t.close() + +def generate_umath(target, source, env): + for t, s in zip(target, source): + do_generate_umath(str(t), str(s), env) + +def generate_umath_emitter(target, source, env): + t = str(target[0]) + '.c' + return ([t], source) + +#----------------------------------------- +# Other functions related to configuration +#----------------------------------------- +def CheckBrokenMathlib(context, mathlib): + src = """ +/* check whether libm is broken */ +#include <math.h> +int main(int argc, char *argv[]) +{ + return exp(-720.) > 1.0; /* typically an IEEE denormal */ +} +""" + + try: + oldLIBS = deepcopy(context.env['LIBS']) + except: + oldLIBS = [] + + try: + context.Message("Checking if math lib %s is usable for numpy ... " % mathlib) + context.env.AppendUnique(LIBS = mathlib) + st = context.TryRun(src, '.c') + finally: + context.env['LIBS'] = oldLIBS + + if st[0]: + context.Result(' Yes !') + else: + context.Result(' No !') + return st[0] + +def check_mlib(config, mlib): + """Return 1 if mlib is available and usable by numpy, 0 otherwise. + + mlib can be a string (one library), or a list of libraries.""" + # Check the libraries in mlib are linkable + if len(mlib) > 0: + # XXX: put an autoadd argument to 0 here and add an autoadd argument to + # CheckBroekenMathlib (otherwise we may add bogus libraries, the ones + # which do not path the CheckBrokenMathlib test). + st = config.CheckLib(mlib) + if not st: + return 0 + # Check the mlib is usable by numpy + return config.CheckBrokenMathlib(mlib) + +def check_mlibs(config, mlibs): + for mlib in mlibs: + if check_mlib(config, mlib): + return mlib + + # No mlib was found. + raise SCons.Errors.UserError("No usable mathlib was found: chose another "\ + "one using the MATHLIB env variable, eg "\ + "'MATHLIB=m python setup.py build'") + + +def is_npy_no_signal(): + """Return True if the NPY_NO_SIGNAL symbol must be defined in configuration + header.""" + return sys.platform == 'win32' + +def define_no_smp(): + """Returns True if we should define NPY_NOSMP, False otherwise.""" + #-------------------------------- + # Checking SMP and thread options + #-------------------------------- + # Python 2.3 causes a segfault when + # trying to re-acquire the thread-state + # which is done in error-handling + # ufunc code. NPY_ALLOW_C_API and friends + # cause the segfault. So, we disable threading + # for now. + if sys.version[:5] < '2.4.2': + nosmp = 1 + else: + # Perhaps a fancier check is in order here. + # so that threads are only enabled if there + # are actually multiple CPUS? -- but + # threaded code can be nice even on a single + # CPU so that long-calculating code doesn't + # block. + try: + nosmp = os.environ['NPY_NOSMP'] + nosmp = 1 + except KeyError: + nosmp = 0 + return nosmp == 1 diff --git a/numpy/core/setup.py b/numpy/core/setup.py index a8fd46911..e68d3137c 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -18,6 +18,36 @@ FUNCTIONS_TO_CHECK = [ ('rint', 'HAVE_RINT'), ] +def is_npy_no_signal(): + """Return True if the NPY_NO_SIGNAL symbol must be defined in configuration + header.""" + return sys.platform == 'win32' + +def is_npy_no_smp(): + """Return True if the NPY_NO_SMP symbol must be defined in public + header (when SMP support cannot be reliably enabled).""" + # Python 2.3 causes a segfault when + # trying to re-acquire the thread-state + # which is done in error-handling + # ufunc code. NPY_ALLOW_C_API and friends + # cause the segfault. So, we disable threading + # for now. + if sys.version[:5] < '2.4.2': + nosmp = 1 + else: + # Perhaps a fancier check is in order here. + # so that threads are only enabled if there + # are actually multiple CPUS? -- but + # threaded code can be nice even on a single + # CPU so that long-calculating code doesn't + # block. + try: + nosmp = os.environ['NPY_NOSMP'] + nosmp = 1 + except KeyError: + nosmp = 0 + return nosmp == 1 + def configuration(parent_package='',top_path=None): from numpy.distutils.misc_util import Configuration,dot_join from numpy.distutils.system_info import get_info, default_lib_dirs @@ -53,28 +83,7 @@ def configuration(parent_package='',top_path=None): raise SystemError,"Failed to test configuration. "\ "See previous error messages for more information." - # Python 2.3 causes a segfault when - # trying to re-acquire the thread-state - # which is done in error-handling - # ufunc code. NPY_ALLOW_C_API and friends - # cause the segfault. So, we disable threading - # for now. - if sys.version[:5] < '2.4.2': - nosmp = 1 - else: - # Perhaps a fancier check is in order here. - # so that threads are only enabled if there - # are actually multiple CPUS? -- but - # threaded code can be nice even on a single - # CPU so that long-calculating code doesn't - # block. - try: - nosmp = os.environ['NPY_NOSMP'] - nosmp = 1 - except KeyError: - nosmp = 0 - if nosmp: moredefs = [('NPY_ALLOW_THREADS', '0')] - else: moredefs = [] + moredefs = [] # mathlibs = [] tc = testcode_mathlib() @@ -102,8 +111,8 @@ def configuration(parent_package='',top_path=None): if check_func(func_name): moredefs.append(defsymbol) - if sys.platform == 'win32': - moredefs.append('NPY_NO_SIGNAL') + if is_npy_no_signal(): + moredefs.append('__NPY_PRIVATE_NO_SIGNAL') if sys.platform=='win32' or os.name=='nt': from distutils.msvccompiler import get_build_architecture @@ -123,8 +132,6 @@ def configuration(parent_package='',top_path=None): target_f.write('#define %s\n' % (d)) else: target_f.write('#define %s %s\n' % (d[0],d[1])) - if not nosmp: # default is to use WITH_THREAD - target_f.write('#ifdef WITH_THREAD\n#define NPY_ALLOW_THREADS 1\n#else\n#define NPY_ALLOW_THREADS 0\n#endif\n') target_f.close() print 'File:',target target_f = open(target) @@ -151,6 +158,40 @@ def configuration(parent_package='',top_path=None): config.add_data_files((header_dir,target)) return target + def generate_numpyconfig_h(ext, build_dir): + """Depends on config.h: generate_config_h has to be called before !""" + target = join(build_dir,'numpyconfig.h') + if newer(__file__,target): + config_cmd = config.get_config_cmd() + log.info('Generating %s',target) + testcode = generate_numpyconfig_code(target) + + from distutils import sysconfig + python_include = sysconfig.get_python_inc() + python_h = join(python_include, 'Python.h') + if not os.path.isfile(python_h): + raise SystemError,\ + "Non-existing %s. Perhaps you need to install"\ + " python-dev|python-devel." % (python_h) + + config.numpy_include_dirs + result = config_cmd.try_run(testcode, + include_dirs = [python_include] + \ + config.numpy_include_dirs, + library_dirs = default_lib_dirs) + + if not result: + raise SystemError,"Failed to generate numpy configuration. "\ + "See previous error messages for more information." + + print 'File: %s' % target + target_f = open(target) + print target_f.read() + target_f.close() + print 'EOF' + config.add_data_files((header_dir, target)) + return target + def generate_api_func(module_name): def generate_api(ext, build_dir): script = join(codegen_dir, module_name + '.py') @@ -205,6 +246,7 @@ def configuration(parent_package='',top_path=None): config.add_extension('multiarray', sources = [join('src','multiarraymodule.c'), generate_config_h, + generate_numpyconfig_h, generate_array_api, join('src','scalartypes.inc.src'), join('src','arraytypes.inc.src'), @@ -216,6 +258,7 @@ def configuration(parent_package='',top_path=None): config.add_extension('umath', sources = [generate_config_h, + generate_numpyconfig_h, join('src','umathmodule.c.src'), generate_umath_c, generate_ufunc_api, @@ -231,6 +274,7 @@ def configuration(parent_package='',top_path=None): config.add_extension('_sort', sources=[join('src','_sortmodule.c.src'), generate_config_h, + generate_numpyconfig_h, generate_array_api, ], ) @@ -238,6 +282,7 @@ def configuration(parent_package='',top_path=None): config.add_extension('scalarmath', sources=[join('src','scalarmathmodule.c.src'), generate_config_h, + generate_numpyconfig_h, generate_array_api, generate_ufunc_api], ) @@ -342,6 +387,85 @@ int main(int argc, char **argv) testcode = '\n'.join(testcode) return testcode +def generate_numpyconfig_code(target): + """Return the source code as a string of the code to generate the + numpyconfig header file.""" + if sys.platform == 'win32': + target = target.replace('\\','\\\\') + # Config symbols to prepend + prepends = [('NPY_SIZEOF_SHORT', 'SIZEOF_SHORT'), + ('NPY_SIZEOF_INT', 'SIZEOF_INT'), + ('NPY_SIZEOF_LONG', 'SIZEOF_LONG'), + ('NPY_SIZEOF_FLOAT', 'SIZEOF_FLOAT'), + ('NPY_SIZEOF_DOUBLE', 'SIZEOF_DOUBLE'), + ('NPY_SIZEOF_LONGDOUBLE', 'SIZEOF_LONG_DOUBLE'), + ('NPY_SIZEOF_PY_INTPTR_T', 'SIZEOF_PY_INTPTR_T')] + + testcode = [""" +#include <Python.h> +#include "config.h" + +int main() +{ + FILE* f; + + f = fopen("%s", "w"); + if (f == NULL) { + return -1; + } +""" % target] + + testcode.append(r""" + fprintf(f, "/*\n * This file is generated by %s. DO NOT EDIT \n */\n"); +""" % __file__) + + # Prepend NPY_ to any SIZEOF defines + testcode.extend([r' fprintf(f, "#define ' + i + r' %%d \n", %s);' % j for i, j in prepends]) + + # Conditionally define NPY_NO_SIGNAL + if is_npy_no_signal(): + testcode.append(r' fprintf(f, "\n#define NPY_NO_SIGNAL\n");') + + # Define NPY_NOSMP to 1 if explicitely requested, or if we cannot + # support thread support reliably + if is_npy_no_smp(): + testcode.append(r' fprintf(f, "#define NPY_NO_SMP 1\n");') + else: + testcode.append(r' fprintf(f, "#define NPY_NO_SMP 0\n");') + + tmpcode = r""" + #ifdef PY_LONG_LONG + fprintf(f, "\n#define %s %%d \n", %s); + fprintf(f, "#define %s %%d \n", %s); + #else + fprintf(f, "/* PY_LONG_LONG not defined */ \n"); + #endif""" + testcode.append(tmpcode % ('NPY_SIZEOF_LONGLONG', 'SIZEOF_LONG_LONG', + 'NPY_SIZEOF_PY_LONG_LONG', 'SIZEOF_PY_LONG_LONG')) + + testcode.append(r""" +#ifndef CHAR_BIT + { + unsigned char var = 2; + int i = 0; + while (var >= 2) { + var = var << 1; + i++; + } + fprintf(f,"#define CHAR_BIT %d\n", i+1); + } +#else + fprintf(f, "/* #define CHAR_BIT %d */\n", CHAR_BIT); +#endif""") + + testcode.append(""" + fclose(f); + + return 0; +} +""") + return "\n".join(testcode) + if __name__=='__main__': from numpy.distutils.core import setup setup(configuration=configuration) diff --git a/numpy/core/setupscons.py b/numpy/core/setupscons.py new file mode 100644 index 000000000..857491b88 --- /dev/null +++ b/numpy/core/setupscons.py @@ -0,0 +1,106 @@ +import os +import sys +import glob +from os.path import join, basename + +from numpy.distutils import log + +from numscons import get_scons_build_dir + +def configuration(parent_package='',top_path=None): + from numpy.distutils.misc_util import Configuration,dot_join + from numpy.distutils.system_info import get_info, default_lib_dirs + + config = Configuration('core',parent_package,top_path) + local_dir = config.local_path + + header_dir = 'include/numpy' # this is relative to config.path_in_package + + config.add_subpackage('code_generators') + + # List of files to register to numpy.distutils + dot_blas_src = [join('blasdot', '_dotblas.c'), + join('blasdot', 'cblas.h')] + api_definition = [join('code_generators', 'array_api_order.txt'), + join('code_generators', 'multiarray_api_order.txt'), + join('code_generators', 'ufunc_api_order.txt')] + core_src = [join('src', basename(i)) for i in glob.glob(join(local_dir, + 'src', + '*.c'))] + core_src += [join('src', basename(i)) for i in glob.glob(join(local_dir, + 'src', + '*.src'))] + + source_files = dot_blas_src + api_definition + core_src + \ + [join(header_dir, 'numpyconfig.h.in')] + + # Add generated files to distutils... + def add_config_header(): + scons_build_dir = get_scons_build_dir() + # XXX: I really have to think about how to communicate path info + # between scons and distutils, and set the options at one single + # location. + target = join(scons_build_dir, local_dir, 'config.h') + incl_dir = os.path.dirname(target) + if incl_dir not in config.numpy_include_dirs: + config.numpy_include_dirs.append(incl_dir) + + def add_numpyconfig_header(): + scons_build_dir = get_scons_build_dir() + # XXX: I really have to think about how to communicate path info + # between scons and distutils, and set the options at one single + # location. + target = join(scons_build_dir, local_dir, 'numpyconfig.h') + incl_dir = os.path.dirname(target) + if incl_dir not in config.numpy_include_dirs: + config.numpy_include_dirs.append(incl_dir) + config.add_data_files((header_dir, target)) + + def add_array_api(): + scons_build_dir = get_scons_build_dir() + # XXX: I really have to think about how to communicate path info + # between scons and distutils, and set the options at one single + # location. + h_file = join(scons_build_dir, local_dir, '__multiarray_api.h') + t_file = join(scons_build_dir, local_dir, 'multiarray_api.txt') + config.add_data_files((header_dir, h_file), + (header_dir, t_file)) + + def add_ufunc_api(): + scons_build_dir = get_scons_build_dir() + # XXX: I really have to think about how to communicate path info + # between scons and distutils, and set the options at one single + # location. + h_file = join(scons_build_dir, local_dir, '__ufunc_api.h') + t_file = join(scons_build_dir, local_dir, 'ufunc_api.txt') + config.add_data_files((header_dir, h_file), + (header_dir, t_file)) + + def add_generated_files(): + add_config_header() + add_numpyconfig_header() + add_array_api() + add_ufunc_api() + config.add_configres() + + config.add_sconscript('SConstruct', + post_hook = add_generated_files, + source_files = source_files) + + config.add_data_files('include/numpy/*.h') + config.add_include_dirs('src') + + config.numpy_include_dirs.extend(config.paths('include')) + + # Don't install fenv unless we need them. + if sys.platform == 'cygwin': + config.add_data_dir('include/numpy/fenv') + + config.add_data_dir('tests') + config.make_svn_version_py() + + return config + +if __name__=='__main__': + from numpy.distutils.core import setup + setup(configuration=configuration) diff --git a/numpy/core/src/arraytypes.inc.src b/numpy/core/src/arraytypes.inc.src index 2499fc059..dbee57c33 100644 --- a/numpy/core/src/arraytypes.inc.src +++ b/numpy/core/src/arraytypes.inc.src @@ -1,4 +1,5 @@ /* -*- c -*- */ +#include "config.h" static longlong MyPyLong_AsLongLong(PyObject *vv) @@ -934,7 +935,7 @@ static int { @btype@ result; - result = PyOS_strto@func@(str, endptr, 0); + result = PyOS_strto@func@(str, endptr, 10); *ip = (@type@) result; return 0; } diff --git a/numpy/core/src/multiarraymodule.c b/numpy/core/src/multiarraymodule.c index 137c81a4d..40b287715 100644 --- a/numpy/core/src/multiarraymodule.c +++ b/numpy/core/src/multiarraymodule.c @@ -3065,23 +3065,25 @@ PyArray_SearchSorted(PyArrayObject *op1, PyObject *op2, NPY_SEARCHSIDE side) PyArrayObject *ap1=NULL; PyArrayObject *ap2=NULL; PyArrayObject *ret=NULL; - int typenum = 0; + PyArray_Descr *dtype; NPY_BEGIN_THREADS_DEF - typenum = PyArray_ObjectType((PyObject *)op1, 0); - typenum = PyArray_ObjectType(op2, typenum); - + dtype = PyArray_DescrFromObject((PyObject *)op2, op1->descr); + /* need ap1 as contiguous array and of right type */ - ap1 = (PyArrayObject *)PyArray_ContiguousFromAny((PyObject *)op1, - typenum, - 1, 1); - if (ap1 == NULL) + Py_INCREF(dtype); + ap1 = (PyArrayObject *)PyArray_FromAny((PyObject *)op1, dtype, + 1, 1, NPY_DEFAULT, NULL); + + if (ap1 == NULL) { + Py_DECREF(dtype); return NULL; + } /* need ap2 as contiguous array and of right type */ - ap2 = (PyArrayObject *)PyArray_ContiguousFromAny(op2, typenum, - 0, 0); + ap2 = (PyArrayObject *)PyArray_FromAny(op2, dtype, 0, 0, NPY_DEFAULT, NULL); + if (ap2 == NULL) goto fail; @@ -7267,7 +7269,7 @@ compare_chararrays(PyObject *dummy, PyObject *args, PyObject *kwds) } -#ifndef NPY_NO_SIGNAL +#ifndef __NPY_PRIVATE_NO_SIGNAL SIGJMP_BUF _NPY_SIGINT_BUF; diff --git a/numpy/core/src/umathmodule.c.src b/numpy/core/src/umathmodule.c.src index ec531e0e5..dfb50aba3 100644 --- a/numpy/core/src/umathmodule.c.src +++ b/numpy/core/src/umathmodule.c.src @@ -5,6 +5,7 @@ #define _UMATHMODULE #include "numpy/ufuncobject.h" #include "abstract.h" +#include "config.h" #include <math.h> /* A whole slew of basic math functions are provided originally diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py index dcaea1cd5..b8fdff56f 100644 --- a/numpy/core/tests/test_regression.py +++ b/numpy/core/tests/test_regression.py @@ -771,5 +771,14 @@ class TestRegression(NumpyTestCase): def check_binary_repr_0_width(self, level=rlevel): assert_equal(np.binary_repr(0,width=3),'000') + def check_fromstring(self, level=rlevel): + assert_equal(np.fromstring("12:09:09", dtype=int, sep=":"), + [12,9,9]) + + def check_searchsorted_variable_length(self, level=rlevel): + x = np.array(['a','aa','b']) + y = np.array(['d','e']) + assert_equal(x.searchsorted(y), [3,3]) + if __name__ == "__main__": NumpyTest().run() diff --git a/numpy/distutils/command/build.py b/numpy/distutils/command/build.py index 1f5c08205..2f5dc31ab 100644 --- a/numpy/distutils/command/build.py +++ b/numpy/distutils/command/build.py @@ -32,3 +32,9 @@ class build(old_build): if build_scripts is None: self.build_scripts = os.path.join(self.build_base, 'scripts' + plat_specifier) + + def run(self): + # Make sure that scons based extensions are complete. + self.run_command('scons') + + old_build.run(self) diff --git a/numpy/distutils/command/config.py b/numpy/distutils/command/config.py index 41c8f4f02..ce42a36e0 100644 --- a/numpy/distutils/command/config.py +++ b/numpy/distutils/command/config.py @@ -101,6 +101,21 @@ class config(old_config): (body, headers, include_dirs, libraries, library_dirs, lang)) + def check_decl(self, symbol, + headers=None, include_dirs=None): + self._check_compiler() + body = """ +int main() +{ +#ifndef %s + (void) %s; +#endif + ; + return 0; +}""" % (symbol, symbol) + + return self.try_compile(body, headers, include_dirs) + def check_func(self, func, headers=None, include_dirs=None, libraries=None, library_dirs=None, diff --git a/numpy/distutils/command/scons.py b/numpy/distutils/command/scons.py new file mode 100644 index 000000000..9bb61ae07 --- /dev/null +++ b/numpy/distutils/command/scons.py @@ -0,0 +1,335 @@ +import os +import os.path +from os.path import join as pjoin, dirname as pdirname + +from distutils.errors import DistutilsPlatformError +from distutils.errors import DistutilsExecError, DistutilsSetupError + +from numpy.distutils.command.build_ext import build_ext as old_build_ext +from numpy.distutils.ccompiler import CCompiler +from numpy.distutils.fcompiler import FCompiler +from numpy.distutils.exec_command import find_executable +from numpy.distutils import log +from numpy.distutils.misc_util import get_numpy_include_dirs + +def get_scons_build_dir(): + """Return the top path where everything produced by scons will be put. + + The path is relative to the top setup.py""" + from numscons import get_scons_build_dir + return get_scons_build_dir() + +def get_scons_configres_dir(): + """Return the top path where everything produced by scons will be put. + + The path is relative to the top setup.py""" + from numscons import get_scons_configres_dir + return get_scons_configres_dir() + +def get_scons_configres_filename(): + """Return the top path where everything produced by scons will be put. + + The path is relative to the top setup.py""" + from numscons import get_scons_configres_filename + return get_scons_configres_filename() + +def get_scons_local_path(): + """This returns the full path where scons.py for scons-local is located.""" + from numscons import get_scons_path + return get_scons_path() + +def get_python_exec_invoc(): + """This returns the python executable from which this file is invocated.""" + # Do we need to take into account the PYTHONPATH, in a cross platform way, + # that is the string returned can be executed directly on supported + # platforms, and the sys.path of the executed python should be the same + # than the caller ? This may not be necessary, since os.system is said to + # take into accound os.environ. This actually also works for my way of + # using "local python", using the alias facility of bash. + import sys + return sys.executable + +def dirl_to_str(dirlist): + """Given a list of directories, returns a string where the paths are + concatenated by the path separator. + + example: ['foo/bar', 'bar/foo'] will return 'foo/bar:bar/foo'.""" + return os.pathsep.join(dirlist) + +def dist2sconscc(compiler): + """This converts the name passed to distutils to scons name convention (C + compiler). compiler should be a CCompiler instance. + + Example: + --compiler=intel -> intelc""" + compiler_type = compiler.compiler_type + if compiler_type == 'msvc': + return 'msvc' + elif compiler_type == 'intel': + return 'intelc' + elif compiler_type == 'mingw32': + return 'mingw' + else: + return compiler.compiler[0] + +def dist2sconsfc(compiler): + """This converts the name passed to distutils to scons name convention + (Fortran compiler). The argument should be a FCompiler instance. + + Example: + --fcompiler=intel -> ifort on linux, ifl on windows""" + if compiler.compiler_type == 'intel': + #raise NotImplementedError('FIXME: intel fortran compiler name ?') + return 'ifort' + elif compiler.compiler_type == 'gnu': + return 'g77' + elif compiler.compiler_type == 'gnu95': + return 'gfortran' + else: + # XXX: Just give up for now, and use generic fortran compiler + return 'fortran' + +def dist2sconscxx(compiler): + """This converts the name passed to distutils to scons name convention + (C++ compiler). The argument should be a Compiler instance.""" + if compiler.compiler_type == 'gnu': + return 'g++' + else: + return 'c++' + return compiler.compiler_cxx[0] + +def get_compiler_executable(compiler): + """For any give CCompiler instance, this gives us the name of C compiler + (the actual executable). + + NOTE: does NOT work with FCompiler instances.""" + # Geez, why does distutils has no common way to get the compiler name... + if compiler.compiler_type == 'msvc': + # this is harcoded in distutils... A bit cleaner way would be to + # initialize the compiler instance and then get compiler.cc, but this + # may be costly: we really just want a string. + # XXX: we need to initialize the compiler anyway, so do not use + # hardcoded string + #compiler.initialize() + #print compiler.cc + return 'cl.exe' + else: + return compiler.compiler[0] + +def get_f77_compiler_executable(compiler): + """For any give FCompiler instance, this gives us the name of F77 compiler + (the actual executable).""" + return compiler.compiler_f77[0] + +def get_cxxcompiler_executable(compiler): + """For any give CCompiler instance, this gives us the name of CXX compiler + (the actual executable). + + NOTE: does NOT work with FCompiler instances.""" + # Geez, why does distutils has no common way to get the compiler name... + if compiler.compiler_type == 'msvc': + # this is harcoded in distutils... A bit cleaner way would be to + # initialize the compiler instance and then get compiler.cc, but this + # may be costly: we really just want a string. + # XXX: we need to initialize the compiler anyway, so do not use + # hardcoded string + #compiler.initialize() + #print compiler.cc + return 'cl.exe' + else: + return compiler.compiler_cxx[0] + +def get_tool_path(compiler): + """Given a distutils.ccompiler.CCompiler class, returns the path of the + toolset related to C compilation.""" + fullpath_exec = find_executable(get_compiler_executable(compiler)) + if fullpath_exec: + fullpath = pdirname(fullpath_exec) + else: + raise DistutilsSetupError("Could not find compiler executable info for scons") + return fullpath + +def get_f77_tool_path(compiler): + """Given a distutils.ccompiler.FCompiler class, returns the path of the + toolset related to F77 compilation.""" + fullpath_exec = find_executable(get_f77_compiler_executable(compiler)) + if fullpath_exec: + fullpath = pdirname(fullpath_exec) + else: + raise DistutilsSetupError("Could not find F77 compiler executable "\ + "info for scons") + return fullpath + +def get_cxx_tool_path(compiler): + """Given a distutils.ccompiler.CCompiler class, returns the path of the + toolset related to C compilation.""" + fullpath_exec = find_executable(get_cxxcompiler_executable(compiler)) + if fullpath_exec: + fullpath = pdirname(fullpath_exec) + else: + raise DistutilsSetupError("Could not find compiler executable info for scons") + return fullpath + +def protect_path(path): + """Convert path (given as a string) to something the shell will have no + problem to understand (space, etc... problems).""" + # XXX: to this correctly, this is totally bogus for now (does not check for + # already quoted path, for example). + return '"' + path + '"' + +class scons(old_build_ext): + # XXX: add an option to the scons command for configuration (auto/force/cache). + description = "Scons builder" + user_options = old_build_ext.user_options + \ + [('jobs=', None, + "specify number of worker threads when executing scons"), + ('scons-tool-path=', None, 'specify additional path '\ + '(absolute) to look for scons tools'), + ('silent=', None, 'specify whether scons output should be silent '\ + '(1), super silent (2) or not (0, default)')] + + def initialize_options(self): + old_build_ext.initialize_options(self) + self.jobs = None + self.silent = 0 + self.scons_tool_path = '' + # If true, we bypass distutils to find the c compiler altogether. This + # is to be used in desperate cases (like incompatible visual studio + # version). + self._bypass_distutils_cc = False + self.scons_compiler = None + self.scons_compiler_path = None + self.scons_fcompiler = None + + def finalize_options(self): + old_build_ext.finalize_options(self) + if self.distribution.has_scons_scripts(): + self.sconscripts = self.distribution.get_scons_scripts() + self.pre_hooks = self.distribution.get_scons_pre_hooks() + self.post_hooks = self.distribution.get_scons_post_hooks() + self.pkg_names = self.distribution.get_scons_parent_names() + else: + self.sconscripts = [] + self.pre_hooks = [] + self.post_hooks = [] + self.pkg_names = [] + + # Try to get the same compiler than the ones used by distutils: this is + # non trivial because distutils and scons have totally different + # conventions on this one (distutils uses PATH from user's environment, + # whereas scons uses standard locations). The way we do it is once we + # got the c compiler used, we use numpy.distutils function to get the + # full path, and add the path to the env['PATH'] variable in env + # instance (this is done in numpy.distutils.scons module). + + # XXX: The logic to bypass distutils is ... not so logic. + compiler_type = self.compiler + if compiler_type == 'msvc': + self._bypass_distutils_cc = True + from numpy.distutils.ccompiler import new_compiler + try: + distutils_compiler = new_compiler(compiler=compiler_type, + verbose=self.verbose, + dry_run=self.dry_run, + force=self.force) + distutils_compiler.customize(self.distribution) + # This initialization seems necessary, sometimes, for find_executable to work... + if hasattr(distutils_compiler, 'initialize'): + distutils_compiler.initialize() + self.scons_compiler = dist2sconscc(distutils_compiler) + self.scons_compiler_path = protect_path(get_tool_path(distutils_compiler)) + except DistutilsPlatformError, e: + if not self._bypass_distutils_cc: + raise e + else: + self.scons_compiler = compiler_type + + # We do the same for the fortran compiler ... + fcompiler_type = self.fcompiler + from numpy.distutils.fcompiler import new_fcompiler + self.fcompiler = new_fcompiler(compiler = fcompiler_type, + verbose = self.verbose, + dry_run = self.dry_run, + force = self.force) + if self.fcompiler is not None: + self.fcompiler.customize(self.distribution) + + # And the C++ compiler + cxxcompiler = new_compiler(compiler = compiler_type, + verbose = self.verbose, + dry_run = self.dry_run, + force = self.force) + if cxxcompiler is not None: + cxxcompiler.customize(self.distribution, need_cxx = 1) + cxxcompiler.customize_cmd(self) + self.cxxcompiler = cxxcompiler.cxx_compiler() + #print self.cxxcompiler.compiler_cxx[0] + + def run(self): + if len(self.sconscripts) > 0: + try: + import numscons + except ImportError, e: + raise RuntimeError("importing numscons failed (error was %s), using " \ + "scons within distutils is not possible without " + "this package " % str(e)) + else: + # nothing to do, just leave it here. + return + # XXX: when a scons script is missing, scons only prints warnings, and + # does not return a failure (status is 0). We have to detect this from + # distutils (this cannot work for recursive scons builds...) + + # XXX: passing everything at command line may cause some trouble where + # there is a size limitation ? What is the standard solution in thise + # case ? + + scons_exec = get_python_exec_invoc() + scons_exec += ' ' + protect_path(pjoin(get_scons_local_path(), 'scons.py')) + + for sconscript, pre_hook, post_hook, pkg_name in zip(self.sconscripts, + self.pre_hooks, self.post_hooks, + self.pkg_names): + if pre_hook: + pre_hook() + + cmd = [scons_exec, "-f", sconscript, '-I.'] + if self.jobs: + cmd.append(" --jobs=%d" % int(self.jobs)) + cmd.append('scons_tool_path="%s"' % self.scons_tool_path) + cmd.append('src_dir="%s"' % pdirname(sconscript)) + cmd.append('pkg_name="%s"' % pkg_name) + #cmd.append('distutils_libdir=%s' % protect_path(pjoin(self.build_lib, + # pdirname(sconscript)))) + cmd.append('distutils_libdir=%s' % protect_path(pjoin(self.build_lib))) + + if not self._bypass_distutils_cc: + cmd.append('cc_opt=%s' % self.scons_compiler) + cmd.append('cc_opt_path=%s' % self.scons_compiler_path) + else: + cmd.append('cc_opt=%s' % self.scons_compiler) + + + if self.fcompiler: + cmd.append('f77_opt=%s' % dist2sconsfc(self.fcompiler)) + cmd.append('f77_opt_path=%s' % protect_path(get_f77_tool_path(self.fcompiler))) + + if self.cxxcompiler: + cmd.append('cxx_opt=%s' % dist2sconscxx(self.cxxcompiler)) + cmd.append('cxx_opt_path=%s' % protect_path(get_cxx_tool_path(self.cxxcompiler))) + + cmd.append('include_bootstrap=%s' % dirl_to_str(get_numpy_include_dirs())) + if self.silent: + if int(self.silent) == 1: + cmd.append('-Q') + elif int(self.silent) == 2: + cmd.append('-s') + cmdstr = ' '.join(cmd) + log.info("Executing scons command: %s ", cmdstr) + st = os.system(cmdstr) + if st: + print "status is %d" % st + raise DistutilsExecError("Error while executing scons command "\ + "%s (see above)" % cmdstr) + if post_hook: + post_hook() diff --git a/numpy/distutils/core.py b/numpy/distutils/core.py index 19e1b33a3..842f6fbc3 100644 --- a/numpy/distutils/core.py +++ b/numpy/distutils/core.py @@ -21,9 +21,10 @@ import distutils.core import distutils.dist from numpy.distutils.extension import Extension +from numpy.distutils.numpy_distribution import NumpyDistribution from numpy.distutils.command import config, config_compiler, \ build, build_py, build_ext, build_clib, build_src, build_scripts, \ - sdist, install_data, install_headers, install, bdist_rpm + sdist, install_data, install_headers, install, bdist_rpm, scons from numpy.distutils.misc_util import get_data_files, is_sequence, is_string numpy_cmdclass = {'build': build.build, @@ -36,6 +37,7 @@ numpy_cmdclass = {'build': build.build, 'build_py': build_py.build_py, 'build_clib': build_clib.build_clib, 'sdist': sdist.sdist, + 'scons': scons.scons, 'install_data': install_data.install_data, 'install_headers': install_headers.install_headers, 'install': install.install, @@ -95,9 +97,10 @@ def get_distribution(always=False): # class is local to a function in setuptools.command.easy_install if dist is not None and \ 'DistributionWithoutHelpCommands' in repr(dist): + raise NotImplementedError("setuptools not supported yet for numpy.scons branch") dist = None if always and dist is None: - dist = distutils.dist.Distribution() + dist = NumpyDistribution() return dist def _exit_interactive_session(_cache=[]): @@ -175,6 +178,9 @@ def setup(**attr): and 'headers' not in new_attr: new_attr['headers'] = [] + # Use our custom NumpyDistribution class instead of distutils' one + new_attr['distclass'] = NumpyDistribution + return old_setup(**new_attr) def _check_append_library(libraries, item): diff --git a/numpy/distutils/misc_util.py b/numpy/distutils/misc_util.py index 79fdd46ec..acc2f5ebf 100644 --- a/numpy/distutils/misc_util.py +++ b/numpy/distutils/misc_util.py @@ -112,11 +112,11 @@ def njoin(*path): return minrelpath(joined) def get_mathlibs(path=None): - """Return the MATHLIB line from config.h + """Return the MATHLIB line from numpyconfig.h """ if path is None: path = os.path.join(get_numpy_include_dirs()[0], 'numpy') - config_file = os.path.join(path,'config.h') + config_file = os.path.join(path,'numpyconfig.h') fid = open(config_file) mathlibs = [] s = '#define MATHLIB' @@ -574,7 +574,7 @@ def get_frame(level=0): class Configuration(object): _list_keys = ['packages', 'ext_modules', 'data_files', 'include_dirs', - 'libraries', 'headers', 'scripts', 'py_modules'] + 'libraries', 'headers', 'scripts', 'py_modules', 'scons_data'] _dict_keys = ['package_dir'] _extra_keys = ['name', 'version'] @@ -586,6 +586,7 @@ class Configuration(object): top_path=None, package_path=None, caller_level=1, + setup_name='setup.py', **attrs): """Construct configuration instance of a package. @@ -674,6 +675,8 @@ class Configuration(object): if caller_instance.options['delegate_options_to_subpackages']: self.set_options(**caller_instance.options) + self.setup_name = setup_name + def todict(self): """Return configuration distionary suitable for passing to distutils.core.setup() function. @@ -795,7 +798,7 @@ class Configuration(object): else: subpackage_path = njoin([subpackage_path] + l[:-1]) subpackage_path = self.paths([subpackage_path])[0] - setup_py = njoin(subpackage_path, 'setup.py') + setup_py = njoin(subpackage_path, self.setup_name) if not self.options['ignore_setup_xxx_py']: if not os.path.isfile(setup_py): setup_py = njoin(subpackage_path, @@ -1165,6 +1168,55 @@ class Configuration(object): self.warn('distutils distribution has been initialized,'\ ' it may be too late to add a library '+ name) + def add_sconscript(self, sconscript, subpackage_path=None, + standalone = False, pre_hook = None, + post_hook = None, source_files = None): + """Add a sconscript to configuration. + + pre_hook and post hook should be sequences of callable, which will be + use before and after executing scons. """ + if standalone: + parent_name = None + else: + parent_name = self.name + + dist = self.get_distribution() + # Convert the sconscript name to a relative filename (relative from top + # setup.py's directory) + fullsconsname = self.paths(sconscript)[0] + + # XXX: Think about a way to automatically register source files from + # scons... + full_source_files = [] + if source_files: + full_source_files.extend([self.paths(i)[0] for i in source_files]) + + if dist is not None: + dist.scons_data.append((fullsconsname, + pre_hook, + post_hook, + full_source_files, + parent_name)) + self.warn('distutils distribution has been initialized,'\ + ' it may be too late to add a subpackage '+ subpackage_name) + # XXX: we add a fake extension, to correctly initialize some + # options in distutils command. + dist.add_extension('', sources = []) + else: + self.scons_data.append((fullsconsname, + pre_hook, + post_hook, + full_source_files, + parent_name)) + # XXX: we add a fake extension, to correctly initialize some + # options in distutils command. + self.add_extension('', sources = []) + + def add_configres(self): + from numscons import get_scons_configres_dir, get_scons_configres_filename + file = os.path.join(get_scons_configres_dir(), self.local_path, + get_scons_configres_filename()) + def add_scripts(self,*files): """Add scripts to configuration. """ @@ -1394,6 +1446,12 @@ class Configuration(object): """ self.py_modules.append((self.name,name,generate_config_py)) + def scons_make_config_py(self, name = '__config__'): + """Generate package __config__.py file containing system_info + information used during building the package. + """ + self.py_modules.append((self.name, name, scons_generate_config_py)) + def get_info(self,*names): """Get resources information. """ @@ -1425,6 +1483,50 @@ def get_numpy_include_dirs(): # else running numpy/core/setup.py return include_dirs +def scons_generate_config_py(target): + """generate config.py file containing system_info information + used during building the package. + + usage: + config['py_modules'].append((packagename, '__config__',generate_config_py)) + """ + from distutils.dir_util import mkpath + from numscons import get_scons_configres_dir, get_scons_configres_filename + d = {} + mkpath(os.path.dirname(target)) + f = open(target, 'w') + f.write('# this file is generated by %s\n' % (os.path.abspath(sys.argv[0]))) + f.write('# it contains system_info results at the time of building this package.\n') + f.write('__all__ = ["show"]\n\n') + confdir = get_scons_configres_dir() + confilename = get_scons_configres_filename() + for root, dirs, files in os.walk(confdir): + if files: + file = os.path.join(root, confilename) + assert root.startswith(confdir) + pkg_name = '.'.join(root[len(confdir)+1:].split(os.sep)) + fid = open(file, 'r') + try: + cnt = fid.read() + d[pkg_name] = eval(cnt) + finally: + fid.close() + # d is a dictionary whose keys are package names, and values the + # corresponding configuration. Each configuration is itself a dictionary + # (lib : libinfo) + f.write('_config = %s\n' % d) + f.write(r''' +def show(): + for pkg, config in _config.items(): + print "package %s configuration:" % pkg + for lib, libc in config.items(): + print ' %s' % lib + for line in libc.split('\n'): + print '\t%s' % line + ''') + f.close() + return target + ######################### def default_config_dict(name = None, parent_name = None, local_path=None): diff --git a/numpy/distutils/numpy_distribution.py b/numpy/distutils/numpy_distribution.py new file mode 100644 index 000000000..681b8b316 --- /dev/null +++ b/numpy/distutils/numpy_distribution.py @@ -0,0 +1,28 @@ +# XXX: Handle setuptools ? +from distutils.core import Distribution + +# This class is used because we add new files (sconscripts, and so on) with the +# scons command +class NumpyDistribution(Distribution): + def __init__(self, attrs = None): + # A list of (sconscripts, pre_hook, post_hook, src, parent_names) + self.scons_data = [] + Distribution.__init__(self, attrs) + + def has_scons_scripts(self): + return bool(self.scons_data) + + def get_scons_scripts(self): + return [i[0] for i in self.scons_data] + + def get_scons_pre_hooks(self): + return [i[1] for i in self.scons_data] + + def get_scons_post_hooks(self): + return [i[2] for i in self.scons_data] + + def get_scons_sources(self): + return [i[3] for i in self.scons_data] + + def get_scons_parent_names(self): + return [i[4] for i in self.scons_data] diff --git a/numpy/distutils/setupscons.py b/numpy/distutils/setupscons.py new file mode 100644 index 000000000..b16225f41 --- /dev/null +++ b/numpy/distutils/setupscons.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +def configuration(parent_package='',top_path=None): + from numpy.distutils.misc_util import Configuration + config = Configuration('distutils',parent_package,top_path) + config.add_subpackage('command') + config.add_subpackage('fcompiler') + config.add_data_dir('tests') + config.add_data_files('site.cfg') + config.make_config_py() + return config + +if __name__ == '__main__': + from numpy.distutils.core import setup + setup(configuration=configuration) diff --git a/numpy/doc/example.py b/numpy/doc/example.py index 32a7e6602..bfc0cf338 100644 --- a/numpy/doc/example.py +++ b/numpy/doc/example.py @@ -53,7 +53,7 @@ def foo(var1, var2, long_var_name='hi') : Explanation See Also - -------- + -------- otherfunc : relationship (optional) newfunc : relationship (optional) diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py index 0e7dbd44c..48d1eaac5 100755 --- a/numpy/f2py/crackfortran.py +++ b/numpy/f2py/crackfortran.py @@ -791,7 +791,7 @@ def analyzeline(m,case,line): grouplist[groupcounter]=[] if needinterface: if verbose>1: - outmess('analyzeline: Creating additional interface block.\n',0) + outmess('analyzeline: Creating additional interface block (groupcounter=%s).\n' % (groupcounter),0) groupname[groupcounter]='interface' groupcache[groupcounter]['block']='interface' groupcache[groupcounter]['name']='unknown_interface' @@ -892,6 +892,7 @@ def analyzeline(m,case,line): pl = ch[0] outmess('analyzeline: cannot handle multiple attributes without type specification. Ignoring %r.\n' % (','.join(ch[1:]))) last_name = None + for e in [x.strip() for x in markoutercomma(ll).split('@,@')]: m1=namepattern.match(e) if not m1: @@ -910,11 +911,14 @@ def analyzeline(m,case,line): ap=m.group('this')+pl if _intentcallbackpattern.match(ap): if k not in groupcache[groupcounter]['args']: - if groupcounter>1 and \ - '__user__' in groupcache[groupcounter-2]['name']: + if groupcounter>1: outmess('analyzeline: appending intent(callback) %s'\ ' to %s arguments\n' % (k,groupcache[groupcounter]['name'])) + if '__user__' not in groupcache[groupcounter-2]['name']: + outmess('analyzeline: missing __user__ module (could be nothing)\n') groupcache[groupcounter]['args'].append(k) + else: + errmess('analyzeline: intent(callback) %s is ignored' % (k)) else: errmess('analyzeline: intent(callback) %s is already'\ ' in argument list' % (k)) diff --git a/numpy/f2py/setupscons.py b/numpy/f2py/setupscons.py new file mode 100755 index 000000000..1b8693df9 --- /dev/null +++ b/numpy/f2py/setupscons.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python +""" +setup.py for installing F2PY + +Usage: + python setup.py install + +Copyright 2001-2005 Pearu Peterson all rights reserved, +Pearu Peterson <pearu@cens.ioc.ee> +Permission to use, modify, and distribute this software is given under the +terms of the NumPy License. + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. +$Revision: 1.32 $ +$Date: 2005/01/30 17:22:14 $ +Pearu Peterson +""" + +__version__ = "$Id: setup.py,v 1.32 2005/01/30 17:22:14 pearu Exp $" + +import os +import sys +from distutils.dep_util import newer +from numpy.distutils import log +from numpy.distutils.core import setup +from numpy.distutils.misc_util import Configuration + +from __version__ import version + +def configuration(parent_package='',top_path=None): + config = Configuration('f2py', parent_package, top_path) + + config.add_subpackage('lib') + + config.add_data_dir('docs') + + config.add_data_files('src/fortranobject.c', + 'src/fortranobject.h', + 'f2py.1' + ) + + config.make_svn_version_py() + + def generate_f2py_py(build_dir): + f2py_exe = 'f2py'+os.path.basename(sys.executable)[6:] + if f2py_exe[-4:]=='.exe': + f2py_exe = f2py_exe[:-4] + '.py' + if 'bdist_wininst' in sys.argv and f2py_exe[-3:] != '.py': + f2py_exe = f2py_exe + '.py' + target = os.path.join(build_dir,f2py_exe) + if newer(__file__,target): + log.info('Creating %s', target) + f = open(target,'w') + f.write('''\ +#!/usr/bin/env %s +# See http://cens.ioc.ee/projects/f2py2e/ +import os, sys +for mode in ["g3-numpy", "2e-numeric", "2e-numarray", "2e-numpy"]: + try: + i=sys.argv.index("--"+mode) + del sys.argv[i] + break + except ValueError: pass +os.environ["NO_SCIPY_IMPORT"]="f2py" +if mode=="g3-numpy": + try: + from main import main + except ImportError: + from numpy.f2py.lib.api import main +elif mode=="2e-numeric": + from f2py2e import main +elif mode=="2e-numarray": + sys.argv.append("-DNUMARRAY") + from f2py2e import main +elif mode=="2e-numpy": + from numpy.f2py import main +else: + print >> sys.stderr, "Unknown mode:",`mode` + sys.exit(1) +main() +'''%(os.path.basename(sys.executable))) + f.close() + return target + + config.add_scripts(generate_f2py_py) + + log.info('F2PY Version %s', config.get_version()) + + return config + +if __name__ == "__main__": + + config = configuration(top_path='') + version = config.get_version() + print 'F2PY Version',version + config = config.todict() + + if sys.version[:3]>='2.3': + config['download_url'] = "http://cens.ioc.ee/projects/f2py2e/2.x"\ + "/F2PY-2-latest.tar.gz" + config['classifiers'] = [ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'Intended Audience :: Science/Research', + 'License :: OSI Approved :: NumPy License', + 'Natural Language :: English', + 'Operating System :: OS Independent', + 'Programming Language :: C', + 'Programming Language :: Fortran', + 'Programming Language :: Python', + 'Topic :: Scientific/Engineering', + 'Topic :: Software Development :: Code Generators', + ] + setup(version=version, + description = "F2PY - Fortran to Python Interface Generaton", + author = "Pearu Peterson", + author_email = "pearu@cens.ioc.ee", + maintainer = "Pearu Peterson", + maintainer_email = "pearu@cens.ioc.ee", + license = "BSD", + platforms = "Unix, Windows (mingw|cygwin), Mac OSX", + long_description = """\ +The Fortran to Python Interface Generator, or F2PY for short, is a +command line tool (f2py) for generating Python C/API modules for +wrapping Fortran 77/90/95 subroutines, accessing common blocks from +Python, and calling Python functions from Fortran (call-backs). +Interfacing subroutines/data from Fortran 90/95 modules is supported.""", + url = "http://cens.ioc.ee/projects/f2py2e/", + keywords = ['Fortran','f2py'], + **config) diff --git a/numpy/fft/SConstruct b/numpy/fft/SConstruct new file mode 100644 index 000000000..2a53f6477 --- /dev/null +++ b/numpy/fft/SConstruct @@ -0,0 +1,13 @@ +# Last Change: Thu Oct 18 09:00 PM 2007 J +# vim:syntax=python +import __builtin__ +__builtin__.__NUMPY_SETUP__ = True +from numpy.distutils.misc_util import get_numpy_include_dirs +from numscons import GetNumpyEnvironment, scons_get_paths + +env = GetNumpyEnvironment(ARGUMENTS) +env.Append(CPPPATH = scons_get_paths(env['include_bootstrap'])) + +fftpack_lite = env.NumpyPythonExtension('fftpack_lite', + source = ['fftpack_litemodule.c', + 'fftpack.c']) diff --git a/numpy/fft/setupscons.py b/numpy/fft/setupscons.py new file mode 100644 index 000000000..54551b0a3 --- /dev/null +++ b/numpy/fft/setupscons.py @@ -0,0 +1,15 @@ +def configuration(parent_package = '', top_path = None): + from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs + config = Configuration('fft', parent_package, top_path) + + config.add_data_dir('tests') + + config.add_sconscript('SConstruct', + source_files = ['fftpack_litemodule.c', 'fftpack.c', + 'fftpack.h']) + + return config + +if __name__ == '__main__': + from numpy.distutils.core import setup + setup(configuration=configuration) diff --git a/numpy/lib/SConstruct b/numpy/lib/SConstruct new file mode 100644 index 000000000..84795da48 --- /dev/null +++ b/numpy/lib/SConstruct @@ -0,0 +1,12 @@ +# Last Change: Thu Oct 18 09:00 PM 2007 J +# vim:syntax=python +import __builtin__ +__builtin__.__NUMPY_SETUP__ = True +from numpy.distutils.misc_util import get_numpy_include_dirs +from numscons import GetNumpyEnvironment, scons_get_paths + +env = GetNumpyEnvironment(ARGUMENTS) +env.Append(CPPPATH = scons_get_paths(env['include_bootstrap'])) + +_compiled_base = env.NumpyPythonExtension('_compiled_base', + source = ['src/_compiled_base.c']) diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py index 1d99f7a97..f8304cced 100644 --- a/numpy/lib/arraysetops.py +++ b/numpy/lib/arraysetops.py @@ -207,7 +207,7 @@ def setmember1d( ar1, ar2 ): b1 = nm.zeros( ar1.shape, dtype = nm.int8 ) b2 = nm.ones( ar2.shape, dtype = nm.int8 ) tt = nm.concatenate( (b1, b2) ) - + # We need this to be a stable sort, so always use 'mergesort' here. The # values from the first array should always come before the values from the # second array. diff --git a/numpy/lib/format.py b/numpy/lib/format.py index bb58c5c61..10d6d27b7 100644 --- a/numpy/lib/format.py +++ b/numpy/lib/format.py @@ -227,7 +227,7 @@ def read_array_header_1_0(fp): raise ValueError("Header does not contain the correct keys: %r" % (keys,)) # Sanity-check the values. - if (not isinstance(d['shape'], tuple) or + if (not isinstance(d['shape'], tuple) or not numpy.all([isinstance(x, int) for x in d['shape']])): raise ValueError("shape is not valid: %r" % (d['shape'],)) if not isinstance(d['fortran_order'], bool): @@ -407,6 +407,3 @@ def open_memmap(filename, mode='r+', dtype=None, shape=None, mode=mode, offset=offset) return marray - - - diff --git a/numpy/lib/io.py b/numpy/lib/io.py index 077bc797b..aa832487f 100644 --- a/numpy/lib/io.py +++ b/numpy/lib/io.py @@ -19,8 +19,8 @@ from _compiled_base import packbits, unpackbits _file = file class BagObj(object): - """A simple class that converts attribute lookups to - getitems on the class passed in. + """A simple class that converts attribute lookups to + getitems on the class passed in. """ def __init__(self, obj): self._obj = obj @@ -31,8 +31,8 @@ class BagObj(object): raise AttributeError, key class NpzFile(object): - """A dictionary-like object with lazy-loading of files in the zipped - archive provided on construction. + """A dictionary-like object with lazy-loading of files in the zipped + archive provided on construction. The arrays and file strings are lazily loaded on either getitem access using obj['key'] or attribute lookup using obj.f.key @@ -54,13 +54,13 @@ class NpzFile(object): def __getitem__(self, key): # FIXME: This seems like it will copy strings around - # more than is strictly necessary. The zipfile + # more than is strictly necessary. The zipfile # will read the string and then # the format.read_array will copy the string - # to another place in memory. - # It would be better if the zipfile could read + # to another place in memory. + # It would be better if the zipfile could read # (or at least uncompress) the data - # directly into the array memory. + # directly into the array memory. member = 0 if key in self._files: member = 1 @@ -90,21 +90,21 @@ def load(file, memmap=False): memmap : bool If true, then memory-map the .npy file or unzip the .npz file into a temporary directory and memory-map each component - This has no effect for a pickle. + This has no effect for a pickle. Returns ------- result : array, tuple, dict, etc. - data stored in the file. + data stored in the file. If file contains pickle data, then whatever is stored in the pickle is returned. - If the file is .npy file, then an array is returned. - If the file is .npz file, then a dictionary-like object is returned + If the file is .npy file, then an array is returned. + If the file is .npz file, then a dictionary-like object is returned which has a filename:array key:value pair for every file in the zip. Raises ------ - IOError + IOError """ if isinstance(file, type("")): fid = _file(file,"rb") @@ -124,7 +124,7 @@ def load(file, memmap=False): elif magic == format.MAGIC_PREFIX: # .npy file return format.read_array(fid) else: # Try a pickle - try: + try: return _cload(fid) except: raise IOError, \ @@ -133,8 +133,8 @@ def load(file, memmap=False): def save(file, arr): """Save an array to a binary file (a string or file-like object). - If the file is a string, then if it does not have the .npy extension, - it is appended and a file open. + If the file is a string, then if it does not have the .npy extension, + it is appended and a file open. Data is saved to the open file in NumPy-array format @@ -144,7 +144,7 @@ def save(file, arr): ... np.save('myfile', a) a = np.load('myfile.npy') - """ + """ if isinstance(file, str): if not file.endswith('.npy'): file = file + '.npy' @@ -158,15 +158,15 @@ def save(file, arr): def savez(file, *args, **kwds): """Save several arrays into an .npz file format which is a zipped-archive of arrays - - If keyword arguments are given, then filenames are taken from the keywords. - If arguments are passed in with no keywords, then stored file names are - arr_0, arr_1, etc. + + If keyword arguments are given, then filenames are taken from the keywords. + If arguments are passed in with no keywords, then stored file names are + arr_0, arr_1, etc. """ if isinstance(file, str): if not file.endswith('.npz'): - file = file + '.npz' + file = file + '.npz' namedict = kwds for i, val in enumerate(args): @@ -190,7 +190,7 @@ def savez(file, *args, **kwds): format.write_array(fid, np.asanyarray(val)) fid.close() zip.write(filename, arcname=fname) - + zip.close() for name in todel: os.remove(name) @@ -359,7 +359,3 @@ def savetxt(fname, X, fmt='%.18e',delimiter=' '): if origShape is not None: X.shape = origShape - - - - diff --git a/numpy/lib/scimath.py b/numpy/lib/scimath.py index 429eac9c8..f35c87578 100644 --- a/numpy/lib/scimath.py +++ b/numpy/lib/scimath.py @@ -93,7 +93,7 @@ def _fix_real_lt_zero(x): """Convert `x` to complex if it has real, negative components. Otherwise, output is just the array version of the input (via asarray). - + Parameters ---------- x : array_like @@ -119,7 +119,7 @@ def _fix_int_lt_zero(x): """Convert `x` to double if it has real, negative components. Otherwise, output is just the array version of the input (via asarray). - + Parameters ---------- x : array_like @@ -145,7 +145,7 @@ def _fix_real_abs_gt_1(x): """Convert `x` to complex if it has real components x_i with abs(x_i)>1. Otherwise, output is just the array version of the input (via asarray). - + Parameters ---------- x : array_like @@ -203,7 +203,7 @@ def log(x): If x contains negative inputs, the answer is computed and returned in the complex domain. - + Parameters ---------- x : array_like @@ -221,7 +221,7 @@ def log(x): Negative arguments are correctly handled (recall that for negative arguments, the identity exp(log(z))==z does not hold anymore): - + >>> log(-math.exp(1)) == (1+1j*math.pi) True """ @@ -233,7 +233,7 @@ def log10(x): If x contains negative inputs, the answer is computed and returned in the complex domain. - + Parameters ---------- x : array_like @@ -263,7 +263,7 @@ def logn(n, x): If x contains negative inputs, the answer is computed and returned in the complex domain. - + Parameters ---------- x : array_like @@ -293,7 +293,7 @@ def log2(x): If x contains negative inputs, the answer is computed and returned in the complex domain. - + Parameters ---------- x : array_like @@ -307,7 +307,7 @@ def log2(x): (We set the printing precision so the example can be auto-tested) >>> import numpy as np; np.set_printoptions(precision=4) - + >>> log2([4,8]) array([ 2., 3.]) @@ -323,7 +323,7 @@ def power(x, p): If x contains negative values, it is converted to the complex domain. If p contains negative values, it is converted to floating point. - + Parameters ---------- x : array_like @@ -332,7 +332,7 @@ def power(x, p): Returns ------- array_like - + Examples -------- (We set the printing precision so the example can be auto-tested) @@ -357,7 +357,7 @@ def arccos(x): For real x with abs(x)<=1, this returns the principal value. If abs(x)>1, the complex arccos() is computed. - + Parameters ---------- x : array_like @@ -385,7 +385,7 @@ def arcsin(x): For real x with abs(x)<=1, this returns the principal value. If abs(x)>1, the complex arcsin() is computed. - + Parameters ---------- x : array_like @@ -414,7 +414,7 @@ def arctanh(x): For real x with abs(x)<=1, this returns the principal value. If abs(x)>1, the complex arctanh() is computed. - + Parameters ---------- x : array_like diff --git a/numpy/lib/setupscons.py b/numpy/lib/setupscons.py new file mode 100644 index 000000000..4f31f6e8a --- /dev/null +++ b/numpy/lib/setupscons.py @@ -0,0 +1,16 @@ +from os.path import join + +def configuration(parent_package='',top_path=None): + from numpy.distutils.misc_util import Configuration + + config = Configuration('lib',parent_package,top_path) + + config.add_sconscript('SConstruct', + source_files = [join('src', '_compiled_base.c')]) + config.add_data_dir('tests') + + return config + +if __name__=='__main__': + from numpy.distutils.core import setup + setup(configuration=configuration) diff --git a/numpy/lib/tests/test_format.py b/numpy/lib/tests/test_format.py index 28e938f0f..e7b27ce94 100644 --- a/numpy/lib/tests/test_format.py +++ b/numpy/lib/tests/test_format.py @@ -21,9 +21,9 @@ Set up: ... np.complex128, ... object, ... ] - >>> + >>> >>> basic_arrays = [] - >>> + >>> >>> for scalar in scalars: ... for endian in '<>': ... dtype = np.dtype(scalar).newbyteorder(endian) @@ -36,20 +36,20 @@ Set up: ... basic.reshape((3,5)).T, ... basic.reshape((3,5))[::-1,::2], ... ]) - ... - >>> + ... + >>> >>> Pdescr = [ ... ('x', 'i4', (2,)), ... ('y', 'f8', (2, 2)), ... ('z', 'u1')] - >>> - >>> + >>> + >>> >>> PbufferT = [ ... ([3,2], [[6.,4.],[6.,4.]], 8), ... ([4,3], [[7.,5.],[7.,5.]], 9), ... ] - >>> - >>> + >>> + >>> >>> Ndescr = [ ... ('x', 'i4', (2,)), ... ('Info', [ @@ -68,14 +68,14 @@ Set up: ... ('Value', 'c16')]), ... ('y', 'f8', (2, 2)), ... ('z', 'u1')] - >>> - >>> + >>> + >>> >>> NbufferT = [ ... ([3,2], (6j, 6., ('nn', [6j,4j], [6.,4.], [1,2]), 'NN', True), 'cc', ('NN', 6j), [[6.,4.],[6.,4.]], 8), ... ([4,3], (7j, 7., ('oo', [7j,5j], [7.,5.], [2,1]), 'OO', False), 'dd', ('OO', 7j), [[7.,5.],[7.,5.]], 9), ... ] - >>> - >>> + >>> + >>> >>> record_arrays = [ ... np.array(PbufferT, dtype=np.dtype(Pdescr).newbyteorder('<')), ... np.array(NbufferT, dtype=np.dtype(Ndescr).newbyteorder('<')), @@ -111,7 +111,7 @@ Test the header writing. ... f = StringIO() ... format.write_array_header_1_0(f, arr) ... print repr(f.getvalue()) - ... + ... "F\x00{'descr': '|u1', 'fortran_order': False, 'shape': (0,)} \n" "F\x00{'descr': '|u1', 'fortran_order': False, 'shape': ()} \n" "F\x00{'descr': '|u1', 'fortran_order': False, 'shape': (15,)} \n" @@ -506,5 +506,3 @@ def test_read_version_1_0_bad_magic(): for magic in bad_version_magic + malformed_magic: f = StringIO(magic) yield raises(ValueError)(format.read_array), f - - diff --git a/numpy/lib/utils.py b/numpy/lib/utils.py index a3bdc743b..9c97a1fdf 100644 --- a/numpy/lib/utils.py +++ b/numpy/lib/utils.py @@ -106,7 +106,7 @@ def deprecate(func, oldname=None, newname=None): else: str1 = "%s is deprecated, use %s" % (oldname, newname), depdoc = '%s is DEPRECATED!! -- use %s instead' % (oldname, newname,) - + def newfunc(*args,**kwds): warnings.warn(str1, DeprecationWarning) return func(*args, **kwds) @@ -487,28 +487,28 @@ def source(object, output=sys.stdout): # * raise SyntaxError instead of a custom exception. class SafeEval(object): - + def visit(self, node, **kw): cls = node.__class__ meth = getattr(self,'visit'+cls.__name__,self.default) return meth(node, **kw) - + def default(self, node, **kw): raise SyntaxError("Unsupported source construct: %s" % node.__class__) - + def visitExpression(self, node, **kw): for child in node.getChildNodes(): return self.visit(child, **kw) - + def visitConst(self, node, **kw): return node.value def visitDict(self, node,**kw): return dict([(self.visit(k),self.visit(v)) for k,v in node.items]) - + def visitTuple(self, node, **kw): return tuple([self.visit(i) for i in node.nodes]) - + def visitList(self, node, **kw): return [self.visit(i) for i in node.nodes] @@ -578,5 +578,3 @@ def safe_eval(source): raise #----------------------------------------------------------------------------- - - diff --git a/numpy/linalg/SConstruct b/numpy/linalg/SConstruct new file mode 100644 index 000000000..24d648ef7 --- /dev/null +++ b/numpy/linalg/SConstruct @@ -0,0 +1,33 @@ +# Last Change: Fri Nov 16 05:00 PM 2007 J +# vim:syntax=python +import os.path + +import __builtin__ +__builtin__.__NUMPY_SETUP__ = True + +from numpy.distutils.misc_util import get_numpy_include_dirs, get_mathlibs +from numscons import GetNumpyEnvironment, scons_get_paths, \ + scons_get_mathlib +from numscons import CheckF77LAPACK +from numscons import write_info + +env = GetNumpyEnvironment(ARGUMENTS) +env.Append(CPPPATH = scons_get_paths(env['include_bootstrap'])) + +config = env.NumpyConfigure(custom_tests = + {'CheckLAPACK' : CheckF77LAPACK}) + +use_lapack = config.CheckLAPACK() + +mlib = scons_get_mathlib(env) +env.AppendUnique(LIBS = mlib) + +config.Finish() +write_info(env) + +sources = ['lapack_litemodule.c'] +if not use_lapack: + sources.extend(['zlapack_lite.c', 'dlapack_lite.c', 'blas_lite.c', + 'dlamch.c', 'f2c_lite.c']) +lapack_lite = env.NumpyPythonExtension('lapack_lite', source = sources) + diff --git a/numpy/linalg/linalg.py b/numpy/linalg/linalg.py index 5b35f1b49..1ee2b9bf8 100644 --- a/numpy/linalg/linalg.py +++ b/numpy/linalg/linalg.py @@ -138,11 +138,11 @@ def _assertNonEmpty(*arrays): def tensorsolve(a, b, axes=None): """Solve the tensor equation a x = b for x - + It is assumed that all indices of x are summed over in the product, together with the rightmost indices of a, similarly as in tensordot(a, x, axes=len(b.shape)). - + Parameters ---------- a : array, shape b.shape+Q @@ -153,11 +153,11 @@ def tensorsolve(a, b, axes=None): axes : tuple of integers Axes in a to reorder to the right, before inversion. If None (default), no reordering is done. - + Returns ------- x : array, shape Q - + Examples -------- >>> from numpy import * @@ -169,7 +169,7 @@ def tensorsolve(a, b, axes=None): (2, 3, 4) >>> allclose(tensordot(a, x, axes=3), b) True - + """ a = asarray(a) b = asarray(b) @@ -206,7 +206,7 @@ def solve(a, b): x : array, shape (M,) Raises LinAlgError if a is singular or not square - + """ one_eq = len(b.shape) == 1 if one_eq: @@ -239,10 +239,10 @@ def tensorinv(a, ind=2): The result is an inverse corresponding to the operation tensordot(a, b, ind), ie., - + x == tensordot(tensordot(tensorinv(a), a, ind), x, ind) == tensordot(tensordot(a, tensorinv(a), ind), x, ind) - + for all x (up to floating-point accuracy). Parameters @@ -298,12 +298,12 @@ def tensorinv(a, ind=2): def inv(a): """Compute the inverse of a matrix. - + Parameters ---------- a : array-like, shape (M, M) Matrix to be inverted - + Returns ------- ainv : array-like, shape (M, M) @@ -330,20 +330,20 @@ def inv(a): def cholesky(a): """Compute the Cholesky decomposition of a matrix. - + Returns the Cholesky decomposition, :lm:`A = L L^*` of a Hermitian positive-definite matrix :lm:`A`. - + Parameters ---------- a : array, shape (M, M) Matrix to be decomposed - + Returns ------- L : array, shape (M, M) Lower-triangular Cholesky factor of A - + Raises LinAlgError if decomposition fails Examples @@ -357,7 +357,7 @@ def cholesky(a): >>> dot(L, L.T.conj()) array([[ 1.+0.j, 0.-2.j], [ 0.+2.j, 5.+0.j]]) - + """ _assertRank2(a) _assertSquareness(a) @@ -400,7 +400,7 @@ def qr(a, mode='full'): Q : double or complex array, shape (M, K) R : double or complex array, shape (K, N) Size K = min(M, N) - + mode = 'r' R : double or complex array, shape (K, N) @@ -429,7 +429,7 @@ def qr(a, mode='full'): True >>> allclose(r, triu(r3[:6,:6], k=0)) True - + """ _assertRank2(a) m, n = a.shape @@ -507,7 +507,7 @@ def qr(a, mode='full'): def eigvals(a): """Compute the eigenvalues of a general matrix. - + Parameters ---------- a : array, shape (M, M) @@ -520,7 +520,7 @@ def eigvals(a): The eigenvalues, each repeated according to its multiplicity. They are not necessarily ordered, nor are they necessarily real for real matrices. - + Raises LinAlgError if eigenvalue computation does not converge See Also @@ -534,7 +534,7 @@ def eigvals(a): This is a simple interface to the LAPACK routines dgeev and zgeev that sets the flags to return only the eigenvalues of general real and complex arrays respectively. - + The number w is an eigenvalue of a if there exists a vector v satisfying the equation dot(a,v) = w*v. Alternately, if w is a root of the characteristic equation det(a - w[i]*I) = 0, where det is the @@ -586,7 +586,7 @@ def eigvals(a): def eigvalsh(a, UPLO='L'): """Compute the eigenvalues of a Hermitean or real symmetric matrix. - + Parameters ---------- a : array, shape (M, M) @@ -596,7 +596,7 @@ def eigvalsh(a, UPLO='L'): Specifies whether the pertinent array data is taken from the upper or lower triangular part of a. Possible values are 'L', and 'U' for upper and lower respectively. Default is 'L'. - + Returns ------- w : double array, shape (M,) @@ -616,7 +616,7 @@ def eigvalsh(a, UPLO='L'): This is a simple interface to the LAPACK routines dsyevd and zheevd that sets the flags to return only the eigenvalues of real symmetric and complex Hermetian arrays respectively. - + The number w is an eigenvalue of a if there exists a vector v satisfying the equation dot(a,v) = w*v. Alternately, if w is a root of the characteristic equation det(a - w[i]*I) = 0, where det is the @@ -714,10 +714,10 @@ def eig(a): that fact. If the eigenvalues are all different, then theoretically the eigenvectors are independent. Likewise, the matrix of eigenvectors is unitary if the matrix a is normal, i.e., if dot(a, a.H) = dot(a.H, a). - + The left and right eigenvectors are not necessarily the (Hermitian) transposes of each other. - + """ a, wrap = _makearray(a) _assertRank2(a) @@ -775,7 +775,7 @@ def eig(a): def eigh(a, UPLO='L'): """Compute eigenvalues for a Hermitian or real symmetric matrix. - + Parameters ---------- a : array, shape (M, M) @@ -785,7 +785,7 @@ def eigh(a, UPLO='L'): Specifies whether the pertinent array date is taken from the upper or lower triangular part of a. Possible values are 'L', and 'U'. Default is 'L'. - + Returns ------- w : double array, shape (M,) @@ -793,7 +793,7 @@ def eigh(a, UPLO='L'): v : double or complex double array, shape (M, M) The normalized eigenvector corresponding to the eigenvalue w[i] is the column v[:,i]. - + Raises LinAlgError if eigenvalue computation does not converge See Also @@ -801,13 +801,13 @@ def eigh(a, UPLO='L'): eigvalsh : eigenvalues of symmetric or Hemitiean arrays. eig : eigenvalues and right eigenvectors for non-symmetric arrays eigvals : eigenvalues of non-symmetric array. - + Notes ----- A simple interface to the LAPACK routines dsyevd and zheevd that compute the eigenvalues and eigenvectors of real symmetric and complex Hermitian arrays respectively. - + The number w is an eigenvalue of a if there exists a vector v satisfying the equation dot(a,v) = w*v. Alternately, if w is a root of the characteristic equation det(a - w[i]*I) = 0, where det is the @@ -866,7 +866,7 @@ def svd(a, full_matrices=1, compute_uv=1): an 1d-array s of singular values (real, non-negative) such that a == U S Vh if S is an suitably shaped matrix of zeros whose main diagonal is s. - + Parameters ---------- a : array, shape (M, N) @@ -876,7 +876,7 @@ def svd(a, full_matrices=1, compute_uv=1): If false, the shapes are (M,K), (K,N) where K = min(M,N) compute_uv : boolean Whether to compute also U, Vh in addition to s - + Returns ------- U: array, shape (M,M) or (M,K) depending on full_matrices @@ -884,7 +884,7 @@ def svd(a, full_matrices=1, compute_uv=1): The singular values, sorted so that s[i] >= s[i+1] K = min(M, N) Vh: array, shape (N,N) or (K,N) depending on full_matrices - + For compute_uv = False, only s is returned. Raises LinAlgError if SVD computation does not converge @@ -895,14 +895,14 @@ def svd(a, full_matrices=1, compute_uv=1): >>> U, s, Vh = linalg.svd(a) >>> U.shape, Vh.shape, s.shape ((9, 9), (6, 6), (6,)) - + >>> U, s, Vh = linalg.svd(a, full_matrices=False) >>> U.shape, Vh.shape, s.shape ((9, 6), (6, 6), (6,)) >>> S = diag(s) >>> allclose(a, dot(U, dot(S, Vh))) True - + >>> s2 = linalg.svd(a, compute_uv=False) >>> allclose(s, s2) True @@ -969,11 +969,11 @@ def svd(a, full_matrices=1, compute_uv=1): def pinv(a, rcond=1e-15 ): """Compute the (Moore-Penrose) pseudo-inverse of a matrix. - + Calculate a generalized inverse of a matrix using its singular-value decomposition and including all 'large' singular values. - + Parameters ---------- a : array, shape (M, N) @@ -982,11 +982,11 @@ def pinv(a, rcond=1e-15 ): Cutoff for 'small' singular values. Singular values smaller than rcond*largest_singular_value are considered zero. - + Returns ------- B : array, shape (N, M) - + Raises LinAlgError if SVD computation does not converge Examples @@ -998,7 +998,7 @@ def pinv(a, rcond=1e-15 ): True >>> allclose(B, dot(B, dot(a, B))) True - + """ a, wrap = _makearray(a) _assertNonEmpty(a) @@ -1028,7 +1028,7 @@ def det(a): ------- det : float or complex Determinant of a - + Notes ----- The determinant is computed via LU factorization, LAPACK routine z/dgetrf. @@ -1057,9 +1057,9 @@ def det(a): def lstsq(a, b, rcond=-1): """Compute least-squares solution to equation :m:`a x = b` - + Compute a vector x such that the 2-norm :m:`|b - a x|` is minimised. - + Parameters ---------- a : array, shape (M, N) @@ -1068,9 +1068,9 @@ def lstsq(a, b, rcond=-1): Cutoff for 'small' singular values. Singular values smaller than rcond*largest_singular_value are considered zero. - + Raises LinAlgError if computation does not converge - + Returns ------- x : array, shape (N,) or (N, K) depending on shape of b @@ -1169,7 +1169,7 @@ def norm(x, ord=None): -2 smallest singular value as below other - sum(abs(x)**ord)**(1./ord) ===== ============================ ========================== - + Returns ------- n : float @@ -1180,7 +1180,7 @@ def norm(x, ord=None): For values ord < 0, the result is, strictly speaking, not a mathematical 'norm', but it may still be useful for numerical purposes. - + """ x = asarray(x) nd = len(x.shape) diff --git a/numpy/linalg/setupscons.py b/numpy/linalg/setupscons.py new file mode 100644 index 000000000..0cf22dd4f --- /dev/null +++ b/numpy/linalg/setupscons.py @@ -0,0 +1,20 @@ + +def configuration(parent_package='',top_path=None): + from numpy.distutils.misc_util import Configuration + from numpy.distutils.system_info import get_info + config = Configuration('linalg',parent_package,top_path) + + config.add_data_dir('tests') + + config.add_sconscript('SConstruct', + source_files = ['lapack_litemodule.c', + 'zlapack_lite.c', 'dlapack_lite.c', + 'blas_lite.c', 'dlamch.c', + 'f2c_lite.c','f2c.h'], + post_hook = config.add_configres) + + return config + +if __name__ == '__main__': + from numpy.distutils.core import setup + setup(configuration=configuration) diff --git a/numpy/numarray/SConstruct b/numpy/numarray/SConstruct new file mode 100644 index 000000000..aa780be87 --- /dev/null +++ b/numpy/numarray/SConstruct @@ -0,0 +1,12 @@ +# Last Change: Fri Oct 19 09:00 AM 2007 J +# vim:syntax=python +import __builtin__ +__builtin__.__NUMPY_SETUP__ = True +from numpy.distutils.misc_util import get_numpy_include_dirs +from numscons import GetNumpyEnvironment, scons_get_paths + +env = GetNumpyEnvironment(ARGUMENTS) +env.Append(CPPPATH = scons_get_paths(env['include_bootstrap'])) +env.Append(CPPPATH = env['src_dir']) + +_capi = env.NumpyPythonExtension('_capi', source = ['_capi.c']) diff --git a/numpy/numarray/setupscons.py b/numpy/numarray/setupscons.py new file mode 100644 index 000000000..37d53a8ef --- /dev/null +++ b/numpy/numarray/setupscons.py @@ -0,0 +1,14 @@ +from os.path import join + +def configuration(parent_package='',top_path=None): + from numpy.distutils.misc_util import Configuration + config = Configuration('numarray',parent_package,top_path) + + config.add_data_files('numpy/') + config.add_sconscript('SConstruct', source_files = ['_capi.c']) + + return config + +if __name__ == '__main__': + from numpy.distutils.core import setup + setup(configuration=configuration) diff --git a/numpy/oldnumeric/setupscons.py b/numpy/oldnumeric/setupscons.py new file mode 100644 index 000000000..82e8a6201 --- /dev/null +++ b/numpy/oldnumeric/setupscons.py @@ -0,0 +1,8 @@ + +def configuration(parent_package='',top_path=None): + from numpy.distutils.misc_util import Configuration + return Configuration('oldnumeric',parent_package,top_path) + +if __name__ == '__main__': + from numpy.distutils.core import setup + setup(configuration=configuration) diff --git a/numpy/random/SConstruct b/numpy/random/SConstruct new file mode 100644 index 000000000..95957ccd7 --- /dev/null +++ b/numpy/random/SConstruct @@ -0,0 +1,50 @@ +# Last Change: Tue Nov 13 11:00 PM 2007 J +# vim:syntax=python +import os + +import __builtin__ +__builtin__.__NUMPY_SETUP__ = True + +from numpy.distutils.misc_util import get_numpy_include_dirs, get_mathlibs +from numscons import GetNumpyEnvironment, scons_get_paths, \ + scons_get_mathlib + +def CheckWincrypt(context): + from copy import deepcopy + src = """\ +/* check to see if _WIN32 is defined */ +int main(int argc, char *argv[]) +{ +#ifdef _WIN32 + return 0; +#else + return 1; +#endif +} +""" + + context.Message("Checking if using wincrypt ... ") + st = context.env.TryRun(src, '.C') + if st[0] == 0: + context.Result('No') + else: + context.Result('Yes') + return st[0] + +env = GetNumpyEnvironment(ARGUMENTS) +env.Append(CPPPATH = scons_get_paths(env['include_bootstrap'])) + +mlib = scons_get_mathlib(env) +env.AppendUnique(LIBS = mlib) + +# On windows, see if we should use Advapi32 +if os.name == 'nt': + config = env.NumpyConfigure(custom_tests = {'CheckWincrypt' : CheckWincrypt}) + if config.CheckWincrypt: + config.env.AppendUnique(LIBS = 'Advapi32') + +sources = [os.path.join('mtrand', x) for x in + ['mtrand.c', 'randomkit.c', 'initarray.c', 'distributions.c']] + +# XXX: Pyrex dependency +mtrand = env.NumpyPythonExtension('mtrand', source = sources) diff --git a/numpy/random/setupscons.py b/numpy/random/setupscons.py new file mode 100644 index 000000000..f5342c39e --- /dev/null +++ b/numpy/random/setupscons.py @@ -0,0 +1,40 @@ +import glob +from os.path import join, split + +def configuration(parent_package='',top_path=None): + from numpy.distutils.misc_util import Configuration, get_mathlibs + config = Configuration('random',parent_package,top_path) + + source_files = [join('mtrand', i) for i in ['mtrand.c', + 'mtrand.pyx', + 'numpy.pxi', + 'randomkit.c', + 'randomkit.h', + 'Python.pxi', + 'initarray.c', + 'initarray.h', + 'distributions.c', + 'distributions.h', + ]] + config.add_sconscript('SConstruct', source_files = source_files) + config.add_data_files(('.', join('mtrand', 'randomkit.h'))) + config.add_data_dir('tests') + + return config + +def testcode_wincrypt(): + return """\ +/* check to see if _WIN32 is defined */ +int main(int argc, char *argv[]) +{ +#ifdef _WIN32 + return 0; +#else + return 1; +#endif +} +""" + +if __name__ == '__main__': + from numpy.distutils.core import setup + setup(configuration=configuration) diff --git a/numpy/setupscons.py b/numpy/setupscons.py new file mode 100644 index 000000000..5c235d2ad --- /dev/null +++ b/numpy/setupscons.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +def configuration(parent_package='',top_path=None): + from numpy.distutils.misc_util import Configuration + config = Configuration('numpy',parent_package,top_path, setup_name = 'setupscons.py') + config.add_subpackage('distutils') + config.add_subpackage('testing') + config.add_subpackage('f2py') + config.add_subpackage('core') + config.add_subpackage('lib') + config.add_subpackage('oldnumeric') + config.add_subpackage('numarray') + config.add_subpackage('fft') + config.add_subpackage('linalg') + config.add_subpackage('random') + config.add_data_dir('doc') + config.add_data_dir('tests') + config.scons_make_config_py() # installs __config__.py + return config + +if __name__ == '__main__': + print 'This is the wrong setup.py file to run' diff --git a/numpy/testing/setupscons.py b/numpy/testing/setupscons.py new file mode 100755 index 000000000..ad248d27f --- /dev/null +++ b/numpy/testing/setupscons.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +def configuration(parent_package='',top_path=None): + from numpy.distutils.misc_util import Configuration + config = Configuration('testing',parent_package,top_path) + return config + +if __name__ == '__main__': + from numpy.distutils.core import setup + setup(maintainer = "NumPy Developers", + maintainer_email = "numpy-dev@numpy.org", + description = "NumPy test module", + url = "http://www.numpy.org", + license = "NumPy License (BSD Style)", + configuration = configuration, + ) |