From scipy-svn at scipy.org Fri Aug 1 17:47:40 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 1 Aug 2008 16:47:40 -0500 (CDT) Subject: [Scipy-svn] r4593 - in branches/Interpolate1D: . docs tests Message-ID: <20080801214740.44BA039C1B5@scipy.org> Author: fcady Date: 2008-08-01 16:47:36 -0500 (Fri, 01 Aug 2008) New Revision: 4593 Added: branches/Interpolate1D/interpolate2d.py branches/Interpolate1D/tests/ branches/Interpolate1D/tests/regression_test.py branches/Interpolate1D/tests/test_fitpack_wrapper.py branches/Interpolate1D/tests/test_interpolate1d.py branches/Interpolate1D/tests/test_interpolate2d.py branches/Interpolate1D/tests/test_interpolate_wrapper.py Modified: branches/Interpolate1D/docs/tutorial.rst branches/Interpolate1D/fitpack_wrapper.py branches/Interpolate1D/interpolate1d.py Log: interpolate2d.py added. Maybe not the perfect api, but it is functional. Also added unit tests Modified: branches/Interpolate1D/docs/tutorial.rst =================================================================== --- branches/Interpolate1D/docs/tutorial.rst 2008-08-01 00:06:19 UTC (rev 4592) +++ branches/Interpolate1D/docs/tutorial.rst 2008-08-01 21:47:36 UTC (rev 4593) @@ -7,7 +7,7 @@ the most basic mathematical tools available to a researcher. The interpolate package provides tools for interpolating and extrapolating new data points from a known set of data points. -Interpolate provides both a functional interface that is flexible and easy to use as well as an object oriented interface that +It provides a functional interface that is flexible and easy to use as well as an object oriented interface that can be more efficient and flexible for some cases. It is able to interpolate and extrapolate in 1D, 2D, and even N dimensions. *[FIXME : 1D only right now]* @@ -472,24 +472,24 @@ At instantiation: #) bbox - This is a 2-element list specifying the endpoints of the approximation interval. - It default to [x[0],x[-1]] +This is a 2-element list specifying the endpoints of the approximation interval. +It default to [x[0],x[-1]] #) w - a 1D sequence of weights which defaults to all ones. +a 1D sequence of weights which defaults to all ones. #) s - If s is zero, the interpolation is exact. If s is not 0, the curve is smoothe subject to - the constraint that sum((w[i]*( y[i]-s(x[i]) ))**2,axis=0) <= s +If s is zero, the interpolation is exact. If s is not 0, the curve is smoothe subject to +the constraint that sum((w[i]*( y[i]-s(x[i]) ))**2,axis=0) <= s - BEWARE : in the current implementation of the code, if s is small but not zero, - instantiating Spline can become painfully slow. +BEWARE : in the current implementation of the code, if s is small but not zero, + instantiating Spline can become painfully slow. At calling: #) nu - Spline returns, not the spline function S, but the (nu)th derivative of S. nu defaults - to 0, so Spline usually returns the zeroth derivative of S, ie S. +Spline returns, not the spline function S, but the (nu)th derivative of S. nu defaults +to 0, so Spline usually returns the zeroth derivative of S, ie S. ----------------- Special Methods @@ -497,16 +497,73 @@ #) set_smoothing_factor(s) #) get_knots - returns the positions of the knots of the spline +returns the positions of the knots of the spline #) get_coeffs - returns the coefficients of the +returns the coefficients of the #) get_residual - returns the weighted sum of the errors (due to smoothing) at the data points - sum((w[i]*( y[i]-s(x[i]) ))**2,axis=0) +returns the weighted sum of the errors (due to smoothing) at the data points +sum((w[i]*( y[i]-s(x[i]) ))**2,axis=0) #) integral(a, b) - returns the integral from a to b +returns the integral from a to b #) derivatives(x) - returns all the derivatives of the spline at point x +returns all the derivatives of the spline at point x #) roots - This only works for cubic splines. But it returns the places where the spline - is identically zero. +This only works for cubic splines. But it returns the places where the spline +is identically zero. + + +================================================ +2D Interpolation +================================================ + +*[This is being written preemptively]* + +In 2D interpolation, known data are of the form (x, y, z), and we interpolate +z_new from (x_new, y_new). + +As in the case of 1D interpolation, there is a convenient functional interface +for 2D interpolation as well as a callable object which can be more efficient. +In analogy to 1D interpolation, the function is interp2d and the class is Interpolate2d. + +------------------------------------------ +The Functional Interface +------------------------------------------ + +The functional interface is virtually identical to that for interp1d: :: + + new_z = interp2d(x, y, z, new_x, new_y) + +The range of interpolation is the rectangle given by the largest and +smallest values in x and y. +As in the case of 1D, string arguments can be passed +as keywords to specify particular types of interpolation. The keywords +in this case are kind (for in-range interpolation) and out (for out-of-bounds). + +By default, out of bounds returns NaN, and in-bounds returns a linear +interpolation. + +new_x and new_y may be either arrays, lists or scalars. If they are +scalars or zero-dimensional arrays, new_z will be a scalar as well. Otherwise +a vector is returned. + +------------------------------------------ +The Objective Interface +------------------------------------------ + +The objective interface for 2D is slightly more complicated. + +================================================ +ND Interpolation +================================================ + + + +================================================ +ND Scattered Interpolation +================================================ + + Still in development. + + Ideally the range of interpolation would be the convex hull of the known + data points, and a Delaunay triangulation would be determined and stored + at instantiation. Then again, that would be VERY expensive. \ No newline at end of file Modified: branches/Interpolate1D/fitpack_wrapper.py =================================================================== --- branches/Interpolate1D/fitpack_wrapper.py 2008-08-01 00:06:19 UTC (rev 4592) +++ branches/Interpolate1D/fitpack_wrapper.py 2008-08-01 21:47:36 UTC (rev 4593) @@ -1,26 +1,20 @@ """ -This module is used for spline interpolation, and functions -as a wrapper around the FITPACK Fortran interpolation -package. Its functionality is contained in the Spline -class. + This module is used for spline interpolation, and functions + as a wrapper around the FITPACK Fortran interpolation + package. Its functionality is contained in the Spline + class. -Spline is primarily meant to be called by Interpolate1d -or inter1d, but is a stand-alone class in its own right. + Spline is primarily meant to be called by Interpolate1d + or interp1d, but is a stand-alone class in its own right + that is not available through these interfaces. + The code has been modified from an older version of + scipy.interpolate, where it was directly called by the + user. As such, it includes functionality not available through + Interpolate1d. For this reason, users may wish to get + under the hood. -The code has been modified from an older version of -scipy.interpolate, where it was directly called by the -user. As such, it includes functionality not available through -Interpolate1d. For this reason, users may wish to get -under the hood. - """ -# FIXME : CLEAN UP THIS FILE! scipy.interpolate contained a lot of -# nice functionality that is only partially in this file. -# The question is whether to copy over the full functionality -# to the point where we may as well include fitting.py from -# scipy.interpolate, or whether we should strip this down some. -# Until that's decided, cleaning is premature. import numpy as np @@ -29,26 +23,26 @@ class Spline(object): """ Univariate spline s(x) of degree k on the interval - [xb,xe] calculated from a given set of data points - (x,y). + [xb,xe] calculated from a given set of data points + (x,y). - Can include least-squares fitting. + Can include least-squares fitting. """ def __init__(self, x=None, y=None, w=None, bbox = [None]*2, k=3, s=0.0): """ Input: - x,y - 1-d sequences of data points (x must be + x,y - 1-d sequences of data points (x must be in strictly ascending order) Optional input: - w - positive 1-d sequence of weights - bbox - 2-sequence specifying the boundary of + k=3 - degree of the univariate spline. + w - positive 1-d sequence of weights + bbox - 2-sequence specifying the boundary of the approximation interval. By default, bbox=[x[0],x[-1]] - k=3 - degree of the univariate spline. - s - positive smoothing factor defined for + s - positive smoothing factor defined for estimation condition: sum((w[i]*( y[i]-s(x[i]) ))**2,axis=0) <= s Default s=0 Modified: branches/Interpolate1D/interpolate1d.py =================================================================== --- branches/Interpolate1D/interpolate1d.py 2008-08-01 00:06:19 UTC (rev 4592) +++ branches/Interpolate1D/interpolate1d.py 2008-08-01 21:47:36 UTC (rev 4593) @@ -10,18 +10,19 @@ # dictionary of interpolation functions/classes/objects method_register = \ { # functions - 'linear' : linear, - 'logarithmic' : logarithmic, - 'block' : block, + 'linear' : linear, 'Linear' : linear, + 'logarithmic' : logarithmic, 'Logarithmic' : logarithmic, + 'block' : block, 'Block' : block, 'block_average_above' : block_average_above, - 'nearest' : nearest, + 'Block_average_above' : block_average_above, + 'nearest' : nearest, 'Nearest' : nearest, # Splines 'Spline' : Spline, 'spline' : Spline, 'Quadratic' : Spline(k=2), 'quadratic' : Spline(k=2), 'Quad' : Spline(k=2), 'quad' : Spline(k=2), 'Cubic' : Spline(k=3), 'cubic' : Spline(k=3), - 'Quartic' : Spline(k=3), 'quartic' : Spline(k=3), + 'Quartic' : Spline(k=4), 'quartic' : Spline(k=4), 'Quar' : Spline(k=4), 'quar' : Spline(k=4), 'Quintic' : Spline(k=5), 'quintic' : Spline(k=5), 'Quin' : Spline(k=5), 'quin' : Spline(k=5) @@ -76,20 +77,14 @@ Same options as for 'kind'. Defaults to returning numpy.NaN ('not a number') for all values above the range of x. - bad_data -- list + bad_data -- list of numbers List of numerical values (in x or y) which indicate unacceptable data. If bad_data is not None (its default), all points whose x or y coordinate is in - bad_data, OR ones of whose coordinates is NaN, will be removed. + bad_data, OR ones of whose coordinates is NaN, will be removed. Note that + bad_data != None means NaNs will be removed even if they are not in + bad_data. - interpkw -- dictionary - If interp is set to a function, class or callable object, this contains - additional keywords. - - lowkw (highkw) -- dictionary - like interpkw, but for extrap_low and extrap_high - - Some Acceptable Input Strings ------------------------ @@ -97,14 +92,13 @@ "logarithmic" -- logarithmic interpolation : linear in log space? "block" -- "block_average_above' -- block average above - "Spline" -- spline interpolation. keyword k (defaults to 3) - indicates order of spline + "Spline" -- spline interpolation of default order "quad", "quadratic" -- spline interpolation order 2 "cubic" -- spline interpolation order 3 "quartic" -- spline interpolation order 4 "quintic" -- spline interpolation order 5 - Other options for interp, extrap_low, and extrap_high + Other options for kind, low, and high --------------------------------------------------- If you choose to use a non-string argument, you must @@ -112,21 +106,21 @@ If a function is passed, it will be called when interpolating. It is assumed to have the form - newy = interp(x, y, newx, **kw), + newy = interp(x, y, newx), where x, y, newx, and newy are all numpy arrays. If a callable class is passed, it is assumed to have format - instance = Class(x, y, **kw). + instance = Class(x, y). which can then be called by new_y = instance(new_x) If a callable object with method "init_xy" or "set_xy" is passed, that method will be used to set x and y as follows - instance.set_xy(x, y, **kw) + instance.set_xy(x, y) and the object will be called during interpolation. new_y = instance(new_x) If the "init_xy" and "set_xy" are not present, it will be called as - new_y = argument(new_x) + new_y = argument(x, y, new_x) A primitive type which is not a string signifies a function which is identically that value (e.g. val and @@ -187,11 +181,13 @@ Same options as for 'kind'. Defaults to returning numpy.NaN ('not a number') for all values above the range of x. - bad_data -- list + bad_data -- list of numbers List of numerical values (in x or y) which indicate unacceptable data. If bad_data is not None (its default), all points whose x or y coordinate is in - bad_data, OR ones of whose coordinates is NaN, will be removed. + bad_data, OR ones of whose coordinates is NaN, will be removed. Note that + bad_data != None means NaNs will be removed even if they are not in + bad_data. Some Acceptable Input Strings ------------------------ @@ -200,8 +196,7 @@ "logarithmic" -- logarithmic interpolation : linear in log space? "block" -- "block_average_above' -- block average above - "Spline" -- spline interpolation. keyword k (defaults to 3) - indicates order of spline + "Spline" -- spline interpolation of default order "quad", "quadratic" -- spline interpolation order 2 "cubic" -- spline interpolation order 3 "quartic" -- spline interpolation order 4 @@ -229,7 +224,7 @@ and the object will be called during interpolation. new_y = instance(new_x) If the "init_xy" and "set_xy" are not present, it will be called as - new_y = argument(new_x) + new_y = argument(x, y, new_x) A primitive type which is not a string signifies a function which is identically that value (e.g. val and @@ -239,7 +234,7 @@ --------- >>> import numpy - >>> from interpolate1d import Interpolate1d + >>> from interpolate import Interpolate1d >>> x = range(5) # note list is permitted >>> y = numpy.arange(5.) >>> new_x = [.2, 2.3, 5.6, 7.0] Added: branches/Interpolate1D/interpolate2d.py =================================================================== --- branches/Interpolate1D/interpolate2d.py 2008-08-01 00:06:19 UTC (rev 4592) +++ branches/Interpolate1D/interpolate2d.py 2008-08-01 21:47:36 UTC (rev 4593) @@ -0,0 +1,261 @@ + +from numpy import NaN, array +import numpy as np +from fitpack_wrapper2d import Spline2d + +def atleast_1d_and_contiguous(ary, dtype = np.float64): + # FIXME : don't have in 2 places + return np.atleast_1d( np.ascontiguousarray(ary, dtype) ) + +# dictionary of interpolation functions/classes/objects +method_register = \ + { + 'linear' : Spline2d(kx=1, ky=1), + 'Linear' : Spline2d(kx=1, ky=1), + 'Spline' : Spline2d(), 'spline' : Spline2d(), + 'Quadratic' : Spline2d(kx=2, ky=2), 'quadratic' : Spline2d(kx=2, ky=2), + 'Quad' : Spline2d(kx=2, ky=2), 'quad' : Spline2d(kx=2, ky=2), + 'Cubic' : Spline2d(kx=3, ky=3), 'cubic' : Spline2d(kx=3, ky=3), + 'Quartic' : Spline2d(kx=4, ky=4), 'quartic' : Spline2d(kx=4, ky=4), + 'Quar' : Spline2d(kx=4, ky=4), 'quar' : Spline2d(kx=4, ky=4), + 'Quintic' : Spline2d(kx=5, ky=5), 'quintic' : Spline2d(kx=5, ky=5), + 'Quin' : Spline2d(kx=5, ky=5), 'quin' : Spline2d(kx=5, ky=5) + } + +# dictionary of types for casting. key = possible datatype, value = datatype it is cast to +# BEWARE : if you cast things to integers, you will lose interpolation ability +dtype_register = {np.float32 : np.float32, + np.float64 : np.float64 + } +dtype_default = np.float64 + +def interp2d(x, y, z, newx, newy, kind='linear', out=NaN, bad_data=None): + return Interpolate2d(x, y, z, kind=kind, out=out, bad_data=bad_data)(newx, newy) + +class Interpolate2d: + """ A callable class for interpolation of 1D, real-valued data. + + Parameters + ----------- + + x -- list or 1D NumPy array + x includes the x-values for the data set to + interpolate from. + + y -- list or 1D NumPy array + y includes the y-values for the data set to + interpolate from. + + z -- list or 1D NumPy array + z includes the z-values for the data set to + interpolate from. + + Optional Arguments + ------------------- + + kind -- Usually a string. But can be any type. + Specifies the type of interpolation to use for values within + the range of x. + + By default, linear interpolation is used. + + See below for details on other options. + + out -- same as for kind + How to extrapolate values for outside the rectangle defined by + min(x) <= newx[i] <= max(x) , min(y) <= newy[i] <= max(y) + Same options as for 'kind'. Defaults to returning numpy.NaN ('not + a number') for all values below the region. + + bad_data -- list of numbers + List of numerical values (in x, y or z) which indicate unacceptable data. + + If bad_data is not None (its default), all points whose x, y or z coordinate is in + bad_data, OR ones of whose coordinates is NaN, will be removed. Note that + bad_data != None means NaNs will be removed even if they are not in + bad_data. + + Some Acceptable Input Strings + ------------------------ + + "linear" -- linear interpolation : default + "spline" -- spline interpolation of default order + "quad", "quadratic" -- spline interpolation order 2 + "cubic" -- spline interpolation order 3 + "quartic" -- spline interpolation order 4 + "quintic" -- spline interpolation order 5 + + Other options for kind and out + --------------------------------------------------- + + If you choose to use a non-string argument, you must + be careful to use correct formatting. + + If a function is passed, it will be called when interpolating. + It is assumed to have the form + newz = interp(x, y, z, newx, newy), + where x, y, newx, and newy are all numpy arrays. + + If a callable class is passed, it is assumed to have format + instance = Class(x, y, z). + which can then be called by + newz = instance(newx, newy) + + If a callable object with method "init_xyz" or "set_xyz" is + passed, that method will be used to set x and y as follows + instance.set_xy(x, y) + and the object will be called during interpolation. + newz = instance(newx, newy) + If the "init_xyz" and "set_xyz" are not present, it will be called as + newz = argument(x, y, z, newx, newy) + + A primitive type which is not a string signifies a function + which is identically that value (e.g. val and + lambda x, y, newx : val are equivalent). + + Example + --------- + + >>> import numpy + >>> from interpolate import Interpolate2d + >>> x = range(5) # note list is permitted + >>> y = numpy.arange(5.) + >>> z = x+y + >>> newx = [.2, 2.3, 2.6, 7.0] + >>> newy = [1, 1, 1, 1] + >>> interp_func = Interpolate2d(x, y, z) + >>> interp_fuc(newx, newy) + array([1.2, 3.3, 3.6, NaN]) + + """ + def __init__(self, x, y, z, kind='linear', out=NaN, bad_data=None): + + self._init_xyz(x, y, z, bad_data) + + self.kind = self._init_interp_method(kind) + self.out = self._init_interp_method(out) + + def _init_xyz(self, x, y, z, bad_data): + # all must be vectors. Should allow meshgrid, though? Perhaps. + # Mention that in documentation. + + if bad_data is not None: + try: # check that bad_data contains only numerical values + sum_of_bad_data = sum(bad_data) + except: + raise TypeError, "bad_data must be either None \ + or a list of numbers" + x, y, z = self._remove_bad_data(x, y, z, bad_data) + + # check acceptable sizes and dimensions + x = np.atleast_1d(x) + y = np.atleast_1d(y) + z = np.atleast_1d(z) + assert len(x) > 0 and len(y) > 0 and len(z)>0, "Arrays cannot be of zero length" + assert x.ndim == 1 , "x must be one-dimensional" + assert y.ndim == 1 , "y must be one-dimensional" + assert z.ndim == 1 , "z must be one-dimensional" + assert len(x) == len(y) , "x and y must be of the same length" + assert len(x) == len(z) , "x and z must be of the same length" + + # select proper dataypes and make arrays + self._xdtype = dtype_register.setdefault(type(x[0]), dtype_default) + self._ydtype = dtype_register.setdefault(type(y[0]), dtype_default) + self._zdtype = dtype_register.setdefault(type(z[0]), dtype_default) + self._x = atleast_1d_and_contiguous(x, self._xdtype).copy() + self._y = atleast_1d_and_contiguous(y, self._ydtype).copy() + self._z = atleast_1d_and_contiguous(z, self._zdtype).copy() + + def _init_interp_method(self, method): + """ returns the interpolating function specified by interp_arg. + """ + from inspect import isclass, isfunction + + # primary usage : user passes a string indicating a known function + # pick interpolator accordingly + if isinstance(method, basestring): + interpolator = method_register.setdefault(method, None ) + if interpolator is None: + raise TypeError, "input string %s not valid" % method + else: + interpolator = method + + # interpolator is a callable : function, class, or instance of class + if hasattr(interpolator, '__call__'): + # function + if isfunction(interpolator): + result = lambda newx, newy : interpolator(self._x, self._y, self._z, newx, newy) + + # callable class + elif isclass(interpolator): + if hasattr(interpolator, 'set_xyz'): + result = interpolator() + result.set_xyz(self._x, self._y, self._z) + if hasattr(interpolator, 'init_xyz'): + result = interpolator() + result.init_xyz(self._x, self._y, self._z) + else: + result = interpolator(self._x, self._y, self._z) + + # instance of callable class + else: + if hasattr(interpolator, 'init_xyz'): + result = interpolator + result.init_xyz(self._x, self._y, self._z) + elif hasattr(interpolator, 'set_xyz'): + result = interpolator + result.set_xyz(self._x, self._y, self._z) + else: + result = lambda newx, newy : interpolator(self._x, self._y, self._z, newx, newy) + + # non-callable : user has passed a default value to always be returned + else: + result = np.vectorize(lambda newx, newy : interpolator) + + return result + + def _remove_bad_data(self, x, y, z, bad_data): + """ removes data points whose x or y coordinate is + either in bad_data or is a NaN. + """ + + bad_data_mask = np.isnan(x) | np.isnan(y) | np.isnan(z) + for bad_num in bad_data: + bad_data_mask = \ + bad_data_mask | (x==bad_num) | (y==bad_num) | (z==bad_num) + + x = x[~bad_data_mask] + y = y[~bad_data_mask] + z = z[~bad_data_mask] + + return x, y, z + + def __call__(self, newx, newy): + + # record if input is scalar or 0-dimemsional array, in which case output will be scalar + input_is_scalar = np.isscalar(newx) or np.isscalar(newy) or \ + isinstance( newx , np.ndarray ) and np.shape(newx) == () or \ + isinstance( newy , np.ndarray ) and np.shape(newy) == () + + # make input into a nice 1d, contiguous array + newx = atleast_1d_and_contiguous(newx, dtype=self._xdtype) + assert newx.ndim == 1, "newx can be at most 1-dimensional" + newy = atleast_1d_and_contiguous(newy, dtype=self._ydtype) + assert newy.ndim == 1, "newy can be at most 1-dimensional" + assert len(newx) == len(newy), "newx and newy must be the same length" + + in_range_mask = (min(self._x) <= newx) & (newx <= max(self._x)) & \ + (min(self._y) <= newy) & (newy <= max(self._y)) + + result = np.zeros(np.shape(newx)) + if sum(in_range_mask) > 0: + # hack to deal with behavior of vectorize on arrays of length 0 + result[in_range_mask] = self.kind(newx[in_range_mask], newy[in_range_mask]) + if sum(~in_range_mask) > 0: + # hack to deal with behavior of vectorize on arrays of length 0 + result[~in_range_mask] = self.out(newx[~in_range_mask], newy[~in_range_mask]) + + if input_is_scalar: + result = result[0] + + return result \ No newline at end of file Added: branches/Interpolate1D/tests/regression_test.py =================================================================== --- branches/Interpolate1D/tests/regression_test.py 2008-08-01 00:06:19 UTC (rev 4592) +++ branches/Interpolate1D/tests/regression_test.py 2008-08-01 21:47:36 UTC (rev 4593) @@ -0,0 +1,37 @@ +""" + regression test: + + This script runs a simple regression test on the functionality of + the interpolation module. Currently, when run, it times each + unit test in interpolate1d.py and stores those times in a dict + of dicts; outer keys are time test was performed, and inner + keys are names of tests run. + +""" + +# hack to test on Field's computer +import sys +sys.path.append('c:/home/python/Interpolate1d') + +import shelve, time +from test_interpolate1d import Test + +# name of log file to which all data is stored. +filename = 'regression_test.dbm' + +log_total = shelve.open(filename) +current_time = str(time.localtime()[0:5]) # specified up to the minute + +# run all tests in interpolate1d's test class +test_list = [name for name in dir(Test) if name.find('test_') == 0] +log_now = {} + +# record time taken for each test +for test_name in test_list: + t1 = time.clock() + eval('Test.%s' % test_name) + t2 = time.clock() + log_now[test_name] = t2-t1 + +log_total[current_time] = log_now +log_total.close() Added: branches/Interpolate1D/tests/test_fitpack_wrapper.py =================================================================== --- branches/Interpolate1D/tests/test_fitpack_wrapper.py 2008-08-01 00:06:19 UTC (rev 4592) +++ branches/Interpolate1D/tests/test_fitpack_wrapper.py 2008-08-01 21:47:36 UTC (rev 4593) @@ -0,0 +1,76 @@ +""" module to test fitpack_wrapper.py +""" + +# hack to test on Field's computer +import sys +sys.path.append('c:/home/python/Interpolate1d') + +# testing +import unittest +import time +from numpy import arange, allclose, ones +import numpy as np +from fitpack_wrapper import Spline + +class Test(unittest.TestCase): + + def assertAllclose(self, x, y): + self.assert_(np.allclose(x, y)) + + def test_linearInterp(self): + """ make sure : linear interpolation (spline with order = 1, s = 0)works + """ + N = 3000. + x = np.arange(N) + y = np.arange(N) + #T1 = time.clock() + interp_func = Spline(x, y, k=1) + #T2 = time.clock() + #print "time to create order 1 spline interpolation function with N = %i:" % N, T2 - T1 + new_x = np.arange(N)+0.5 + #t1 = time.clock() + new_y = interp_func(new_x) + #t2 = time.clock() + #print "time for order 1 spline interpolation with N = %i:" % N, t2 - t1 + self.assertAllclose(new_y[:5], [0.5, 1.5, 2.5, 3.5, 4.5]) + + def test_quadInterp(self): + """ make sure : quadratic interpolation (spline with order = 2, s = 0)works + """ + N = 3000. + x = np.arange(N) + y = x**2 + interp_func = Spline(x, y, k=2) + #print "time to create order 1 spline interpolation function with N = %i:" % N, T2 - T1 + new_x = np.arange(N)+0.5 + #t1 = time.clock() + new_y = interp_func(x) + #t2 = time.clock() + #print "time for order 1 spline interpolation with N = %i:" % N, t2 - t1 + self.assertAllclose(new_y, y) + + + def test_inputFormat(self): + """ make sure : it's possible to instantiate Spline without x and y + """ + #print "testing input format" + N = 3000. + x = np.arange(N) + y = np.arange(N) + interp_func = Spline(k=1) + interp_func.init_xy(x, y) + new_x = np.arange(N)+0.5 + new_y = interp_func(new_x) + self.assertAllclose(new_y[:5], [0.5, 1.5, 2.5, 3.5, 4.5]) + + def runTest(self): + test_list = [name for name in dir(self) if name.find('test_')==0] + for test_name in test_list: + exec("self.%s()" % test_name) + + + +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file Added: branches/Interpolate1D/tests/test_interpolate1d.py =================================================================== --- branches/Interpolate1D/tests/test_interpolate1d.py 2008-08-01 00:06:19 UTC (rev 4592) +++ branches/Interpolate1D/tests/test_interpolate1d.py 2008-08-01 21:47:36 UTC (rev 4593) @@ -0,0 +1,170 @@ +""" Test module for interpolate1d.py +""" + +# hack to test on Field's computer +import sys +sys.path.append('c:/home/python/Interpolate1d') + +import numpy as np +from numpy import arange + +from interpolate1d import interp1d, Interpolate1d, atleast_1d_and_contiguous +from fitpack_wrapper import Spline + +# unit testing +import unittest, time +class Test(unittest.TestCase): + + def assertAllclose(self, x, y): + self.assert_(np.allclose(atleast_1d_and_contiguous(x), atleast_1d_and_contiguous(y))) + + def test_interpolate_wrapper(self): + """ run unit test contained in interpolate_wrapper.py + """ + #print "\n\nTESTING _interpolate_wrapper MODULE" + from test_interpolate_wrapper import Test + T = Test() + T.runTest() + + def test_fitpack_wrapper(self): + """ run unit test contained in fitpack_wrapper.py + """ + #print "\n\nTESTING _fitpack_wrapper MODULE" + from test_fitpack_wrapper import Test + T = Test() + T.runTest() + + def test_callable_class_interpolation(self): + """ make sure : an instance of a callable class in which + x and y haven't been initiated works + """ + N = 7 #must be > 5 + x = np.arange(N) + y = np.arange(N) + interp_func = Interpolate1d(x, y, kind=Spline(k=2), low=Spline, high=Spline) + new_x = np.arange(N+1)-0.5 + new_y = interp_func(new_x) + self.assertAllclose(new_x, new_y) + + def test_no_out_of_range_args(self): + """ make sure : having no out-of-range elements in new_x is fine + """ + # There was a bug with this earlier. + N = 5 + x = arange(N) + y = arange(N) + new_x = arange(1,N-1)+.2 + interp_func = Interpolate1d(x, y, kind='linear', low='linear', high=np.NaN) + new_y = interp_func(new_x) + self.assertAllclose(new_x, new_y) + + def test_remove_bad_data(self): + """make sure : interp1d works with bad data + """ + N = 7.0 # must be >=5 + x = arange(N); x[2] = np.NaN + y = arange(N); y[4] = 52.3; y[0]=np.NaN + new_x = arange(N+1)-0.5 + new_y = interp1d(x, y, new_x, kind='linear', low='linear', + high='linear', bad_data = [52.3]) + self.assertAllclose(new_x, new_y) + + def test_interp1d(self): + """ make sure : interp1d works, at least in the linear case + """ + N = 7 + x = arange(N) + y = arange(N) + new_x = arange(N+1)-0.5 + new_y = interp1d(x, y, new_x, kind='linear', low='linear', high='linear') + self.assertAllclose(new_x, new_y) + + + def test_spline1_default_extrapolation(self): + """ make sure : spline order 1 (linear) interpolation works correctly + make sure : default extrapolation works + """ + #print "\n\nTESTING LINEAR (1st ORDER) SPLINE" + N = 7 # must be > 5 + x = np.arange(N) + y = np.arange(N) + interp_func = Interpolate1d(x, y, kind=Spline(k=1), low=None, high=599.73) + new_x = np.arange(N+1)-0.5 + new_y = interp_func(new_x) + + self.assertAllclose(new_y[1:5], [0.5, 1.5, 2.5, 3.5]) + self.assert_(new_y[0] == None) + self.assert_(new_y[-1] == 599.73) + + def test_spline2(self): + """ make sure : order-2 splines work on linear data + make sure : order-2 splines work on non-linear data + make sure : 'cubic' and 'quad' as arguments yield + the desired spline + """ + #print "\n\nTESTING 2nd ORDER SPLINE" + N = 7 #must be > 5 + x = np.arange(N) + y = np.arange(N) + T1 = time.clock() + interp_func = Interpolate1d(x, y, kind=Spline(k=2), low='spline', high='spline') + T2 = time.clock() + #print "time to create 2nd order spline interp function with N = %i: " % N, T2 - T1 + new_x = np.arange(N+1)-0.5 + t1 = time.clock() + new_y = interp_func(new_x) + t2 = time.clock() + #print "time to evaluate 2nd order spline interp function with N = %i: " % N, t2 - t1 + self.assertAllclose(new_x, new_y) + + # make sure for non-linear data + N = 7 + x = np.arange(N) + y = x**2 + interp_func = Interpolate1d(x, y, kind=Spline(k=2), low='quad', high='cubic') + new_x = np.arange(N+1)-0.5 + new_y = interp_func(new_x) + self.assertAllclose(new_x**2, new_y) + + + def test_linear(self): + """ make sure : linear interpolation works + make sure : linear extrapolation works + """ + #print "\n\nTESTING LINEAR INTERPOLATION" + N = 7 + x = arange(N) + y = arange(N) + new_x = arange(N+1)-0.5 + T1 = time.clock() + interp_func = Interpolate1d(x, y, kind='linear', low='linear', high='linear') + T2 = time.clock() + #print "time to create linear interp function with N = %i: " % N, T2 - T1 + t1 = time.clock() + new_y = interp_func(new_x) + t2 = time.clock() + #print "time to create linear interp function with N = %i: " % N, t2 - t1 + + self.assertAllclose(new_x, new_y) + + def test_scalar_input(self): + """ make sure : newx being a scalar or a 0-degree array + makes the output a scalar + """ + N = 7 + x = arange(N) + y = arange(N) + interp_func = Interpolate1d(x, y, kind='linear', low='linear', high='linear') + + # scalar input + newx1 = 0.5 + newy1 = interp_func(newx1) + self.assert_( np.isscalar(newy1) ) + + # zero-degree array + newx2 = np.array(0.5) + newy2 = interp_func(newx2) + self.assert_( np.isscalar(newy2) ) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file Added: branches/Interpolate1D/tests/test_interpolate2d.py =================================================================== --- branches/Interpolate1D/tests/test_interpolate2d.py 2008-08-01 00:06:19 UTC (rev 4592) +++ branches/Interpolate1D/tests/test_interpolate2d.py 2008-08-01 21:47:36 UTC (rev 4593) @@ -0,0 +1,178 @@ +""" Test module for interpolate1d.py +""" + +# hack to test on Field's computer +import sys +sys.path.append('c:/home/python/Interpolate1d') + +import numpy as np +from numpy import arange, meshgrid, ravel + +from interpolate2d import interp2d, Interpolate2d, atleast_1d_and_contiguous +from fitpack_wrapper2d import Spline2d + +# unit testing +import unittest, time +class Test(unittest.TestCase): + + def assertAllclose(self, x, y): + self.assert_(np.allclose(atleast_1d_and_contiguous(x), atleast_1d_and_contiguous(y))) + + def test_callable_class_interpolation(self): + """ make sure : instance of callable class with xyz not initiated works + """ + N = 7 + X, Y = meshgrid(arange(N), arange(N)) + Z = X + Y + x, y, z = map(ravel, [X, Y, Z] ) + + newx = np.arange(N-1)+0.5 + newy = newx + + interp_func = Interpolate2d(x, y, z, kind=Spline2d(kx=1, ky=1)) + newz = interp_func(newx, newy) + + self.assertAllclose(newz, newx+newy) + + def test_no_out_of_range_args(self): + """ make sure : having no out-of-range elements in new_x is fine + """ + # There was a bug with this earlier. + N = 7 + X, Y = meshgrid(arange(N), arange(N)) + Z = X + Y + x, y, z = map(ravel, [X, Y, Z] ) + + newx = arange(1,N-1)+.2 + newy = arange(1,N-1)+.3 + + interp_func = Interpolate2d(x, y, z, kind='linear', out = 'linear') + newz = interp_func(newx, newy) + + self.assertAllclose(newz, newx + newy) + + def test_remove_bad_data(self): + """make sure : works with bad data + """ + N = 5. + X, Y = meshgrid(arange(N), arange(N)) + Z = X + Y + x, y, z = map(ravel, [X, Y, Z] ) + + x[2] = 55.0 + z[4] = np.NaN + + newx = arange(1, N-1)-0.5 + newy = newx + + newz = interp2d(x, y, z, newx, newy, kind='linear', bad_data = [55.0]) + self.assertAllclose(newz, newx+newy) + + def test_interp2d(self): + """ make sure : interp2d works, at least in the linear case + """ + N = 7 + X, Y = meshgrid(arange(N), arange(N)) + Z = X + Y + x, y, z = map(ravel, [X, Y, Z] ) + + newx = arange(1, N)-0.5 + newy = newx + + newz = interp2d(x, y, z, newx, newy, kind='linear', out='linear') + + self.assertAllclose(newz, newx+newy) + + def test_scalar_input(self): + """ make sure : scalar input or a 0-degree array works + """ + + N = 7 + X, Y = meshgrid(arange(N), arange(N)) + Z = X + Y + x, y, z = map(ravel, [X, Y, Z] ) + + interp_func = Interpolate2d(x, y, z, kind='linear', out='linear') + + # scalar input + newx1 = 0.5 + newy1 = 0.7 + + newz1 = interp_func(newx1, newy1) + self.assert_( np.isscalar(newz1) ) + + # zero-degree array + newx2 = 0.5 + newy2 = 0.7 + + newz2 = interp_func(newx2, newy2) + self.assert_( np.isscalar(newz2) ) + + def test_extrapolation(self): + """ make sure : default extrapolation works + """ + N = 7 + X, Y = meshgrid(arange(N), arange(N)) + Z = X + Y + x, y, z = map(ravel, [X, Y, Z] ) + + newx = np.arange(0, N+1)-0.5 + newy = newx + + interp_func = Interpolate2d(x, y, z, kind=Spline2d(kx=1, ky=1) ) + newz = interp_func(newx, newy) + + self.assertAllclose(newz[1:5], newx[1:5]+newy[1:5] ) + self.assert_( np.isnan(newz[0]) ) + self.assert_( np.isnan(newz[-1]) ) + + def test_string_linear(self): + """ make sure : string 'linear' works + """ + N = 7 + X, Y = meshgrid(arange(N), arange(N)) + Z = X + Y + x, y, z = map(ravel, [X, Y, Z] ) + + newx = np.arange(1, N)-0.5 + newy = newx + + interp_func = Interpolate2d(x, y, z, kind='linear', out='linear') + newz = interp_func(newx, newy) + + self.assertAllclose(newz, newx+newy) + + def test_string_quadratic(self): + """ make sure : string 'quadratic' works + """ + N = 7 + X, Y = meshgrid(arange(N), arange(N)) + Z = X + Y + x, y, z = map(ravel, [X, Y, Z] ) + + newx = np.arange(1, N)-0.5 + newy = newx + + interp_func = Interpolate2d(x, y, z, kind='quadratic', out='quad') + newz = interp_func(newx, newy) + + self.assertAllclose(newz, newx+newy) + + def test_string_cubic(self): + """make sure : string "cubic" works + """ + N = 7 + X, Y = meshgrid(arange(N), arange(N)) + Z = X + Y + x, y, z = map(ravel, [X, Y, Z] ) + + newx = np.arange(1, N)-0.5 + newy = newx + + interp_func = Interpolate2d(x, y, z, kind='cubic', out='cubic') + newz = interp_func(newx, newy) + + self.assertAllclose(newz, newx+newy) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file Added: branches/Interpolate1D/tests/test_interpolate_wrapper.py =================================================================== --- branches/Interpolate1D/tests/test_interpolate_wrapper.py 2008-08-01 00:06:19 UTC (rev 4592) +++ branches/Interpolate1D/tests/test_interpolate_wrapper.py 2008-08-01 21:47:36 UTC (rev 4593) @@ -0,0 +1,90 @@ +""" module to test interpolate_wrapper.py +""" + +# hack to test on Field's computer +import sys +sys.path.append('c:/home/python/Interpolate1d') + +# Unit Test +import unittest +import time +from numpy import arange, allclose, ones, NaN, isnan +import numpy as np + +# functionality to be tested +from interpolate_wrapper import atleast_1d_and_contiguous, \ + linear, logarithmic, block_average_above, block, nearest + +class Test(unittest.TestCase): + + def assertAllclose(self, x, y, rtol=1.0e-5): + for i, xi in enumerate(x): + self.assert_(allclose(xi, y[i], rtol) or (isnan(xi) and isnan(y[i]))) + + def test_nearest(self): + N = 5 + x = arange(N) + y = arange(N) + self.assertAllclose(y, nearest(x, y, x+.1)) + self.assertAllclose(y, nearest(x, y, x-.1)) + + def test_linear(self): + N = 3000. + x = arange(N) + y = arange(N) + new_x = arange(N)+0.5 + t1 = time.clock() + new_y = linear(x, y, new_x) + t2 = time.clock() + #print "time for linear interpolation with N = %i:" % N, t2 - t1 + + self.assertAllclose(new_y[:5], [0.5, 1.5, 2.5, 3.5, 4.5]) + + def test_block_average_above(self): + N = 3000. + x = arange(N) + y = arange(N) + + new_x = arange(N/2)*2 + t1 = time.clock() + new_y = block_average_above(x, y, new_x) + t2 = time.clock() + #print "time for block_avg_above interpolation with N = %i:" % N, t2 - t1 + self.assertAllclose(new_y[:5], [0.0, 0.5, 2.5, 4.5, 6.5]) + + def test_linear2(self): + N = 3000. + x = arange(N) + y = ones((100,N)) * arange(N) + new_x = arange(N)+0.5 + t1 = time.clock() + new_y = linear(x, y, new_x) + t2 = time.clock() + #print "time for 2D linear interpolation with N = %i:" % N, t2 - t1 + self.assertAllclose(new_y[:5,:5], + [[ 0.5, 1.5, 2.5, 3.5, 4.5], + [ 0.5, 1.5, 2.5, 3.5, 4.5], + [ 0.5, 1.5, 2.5, 3.5, 4.5], + [ 0.5, 1.5, 2.5, 3.5, 4.5], + [ 0.5, 1.5, 2.5, 3.5, 4.5]]) + + def test_logarithmic(self): + N = 4000. + x = arange(N) + y = arange(N) + new_x = arange(N)+0.5 + t1 = time.clock() + new_y = logarithmic(x, y, new_x) + t2 = time.clock() + #print "time for logarithmic interpolation with N = %i:" % N, t2 - t1 + correct_y = [np.NaN, 1.41421356, 2.44948974, 3.46410162, 4.47213595] + self.assertAllclose(new_y[:5], correct_y) + + def runTest(self): + test_list = [name for name in dir(self) if name.find('test_')==0] + for test_name in test_list: + exec("self.%s()" % test_name) + +if __name__ == '__main__': + unittest.main() + \ No newline at end of file From scipy-svn at scipy.org Fri Aug 1 17:48:33 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 1 Aug 2008 16:48:33 -0500 (CDT) Subject: [Scipy-svn] r4594 - branches/Interpolate1D Message-ID: <20080801214833.4D1AB39C1B5@scipy.org> Author: fcady Date: 2008-08-01 16:48:32 -0500 (Fri, 01 Aug 2008) New Revision: 4594 Added: branches/Interpolate1D/fitpack_wrapper2d.py Log: forgot to add new fitpack wrapper Added: branches/Interpolate1D/fitpack_wrapper2d.py =================================================================== --- branches/Interpolate1D/fitpack_wrapper2d.py 2008-08-01 21:47:36 UTC (rev 4593) +++ branches/Interpolate1D/fitpack_wrapper2d.py 2008-08-01 21:48:32 UTC (rev 4594) @@ -0,0 +1,194 @@ +import warnings +from numpy import zeros, concatenate, alltrue, ravel, all, diff +import numpy as np + +import _dfitpack + +_surfit_messages = {1:""" + The required storage space exceeds the available storage space: nxest + or nyest too small, or s too small. + The weighted least-squares spline corresponds to the current set of + knots.""", + 2:""" + A theoretically impossible result was found during the iteration + process for finding a smoothing spline with fp = s: s too small or + badly chosen eps. + Weighted sum of squared residuals does not satisfy abs(fp-s)/s < tol.""", + 3:""" + the maximal number of iterations maxit (set to 20 by the program) + allowed for finding a smoothing spline with fp=s has been reached: + s too small. + Weighted sum of squared residuals does not satisfy abs(fp-s)/s < tol.""", + 4:""" + No more knots can be added because the number of b-spline coefficients + (nx-kx-1)*(ny-ky-1) already exceeds the number of data points m: + either s or m too small. + The weighted least-squares spline corresponds to the current set of + knots.""", + 5:""" + No more knots can be added because the additional knot would (quasi) + coincide with an old one: s too small or too large a weight to an + inaccurate data point. + The weighted least-squares spline corresponds to the current set of + knots.""", + 10:""" + Error on entry, no approximation returned. The following conditions + must hold: + xb<=x[i]<=xe, yb<=y[i]<=ye, w[i]>0, i=0..m-1 + If iopt==-1, then + xb Author: fcady Date: 2008-08-04 09:37:45 -0500 (Mon, 04 Aug 2008) New Revision: 4596 Modified: branches/Interpolate1D/fitpack_wrapper2d.py branches/Interpolate1D/tests/test_fitpack_wrapper2d.py Log: all tests, including those for 2D interpolation, are passing Modified: branches/Interpolate1D/fitpack_wrapper2d.py =================================================================== --- branches/Interpolate1D/fitpack_wrapper2d.py 2008-08-01 23:34:03 UTC (rev 4595) +++ branches/Interpolate1D/fitpack_wrapper2d.py 2008-08-04 14:37:45 UTC (rev 4596) @@ -113,7 +113,7 @@ self._is_initialized = True def __call__(self, x, y): - """ Evaluate spline at positions x[i],y[i]. + """ Evaluate spline at positions (x[i], y[i]). x and y should be 1d arrays. If (xi, yi) is outside the interpolation range, it will be @@ -123,6 +123,11 @@ if self._is_initialized is not True: raise Error, "x, y and z must be initialized before interpolating" + + # check input format + assert isinstance(x, np.ndarray) and isinstance(y, np.ndarray), \ + "newx and newy must both be numpy arrays" + assert len(x) == len(y), "newx and newy must be of the same length" # sort only once for efficiency sorted_x = sorted(x) @@ -143,6 +148,11 @@ if self._is_initialized is not True: raise Error, "x, y and z must be initialized before interpolating" + # check input format + assert isinstance(x, np.ndarray) and isinstance(y, np.ndarray), \ + "newx and newy must both be numpy arrays" + assert len(x) == len(y), "newx and newy must be of the same length" + tx,ty,c = self.tck[:3] kx,ky = self.degrees z,ier = _dfitpack.bispev(tx,ty,c,kx,ky,x,y) Modified: branches/Interpolate1D/tests/test_fitpack_wrapper2d.py =================================================================== --- branches/Interpolate1D/tests/test_fitpack_wrapper2d.py 2008-08-01 23:34:03 UTC (rev 4595) +++ branches/Interpolate1D/tests/test_fitpack_wrapper2d.py 2008-08-04 14:37:45 UTC (rev 4596) @@ -75,24 +75,13 @@ Z = X + Y x, y, z = map(ravel, [X, Y, Z]) - newx = arange(N+8) +.5 - newy = 2*newx - interp_func = Spline2d(x, y, z, kx=1, ky=1) - newz = interp_func(newx, newy) - print "newx: ", newx - print "newy: ", newy - print "sum : ", newx+newy - print "newz: ", newz + # upper-right region of R2 + self.assertAllclose(interp_func(np.array([N+1.]),np.array([N+1.])) , 2*N-2) - print "Homer Simpson" - print interp_func(array([-2.0]),array([3.5])) - print interp_func(array([-7.0]),array([3.5])) - print interp_func(array([-2.0]),array([7])) - print "Bartman" - - self.assertAllclose(newz, newx+newy) + # directly above interpolation region; only extrapolating in one variable + self.assertAllclose(interp_func(np.array([N])/2.,2.*np.array([N])) , N/2. + (N-1.)) def runTest(self): test_list = [name for name in dir(self) if name.find('test_')==0] From scipy-svn at scipy.org Mon Aug 4 14:58:39 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 4 Aug 2008 13:58:39 -0500 (CDT) Subject: [Scipy-svn] r4597 - trunk/scipy/cluster/tests Message-ID: <20080804185839.2D51239C192@scipy.org> Author: damian.eads Date: 2008-08-04 13:58:20 -0500 (Mon, 04 Aug 2008) New Revision: 4597 Added: trunk/scipy/cluster/tests/test_distance.py Log: forgot to commit this file. Added: trunk/scipy/cluster/tests/test_distance.py =================================================================== --- trunk/scipy/cluster/tests/test_distance.py 2008-08-04 14:37:45 UTC (rev 4596) +++ trunk/scipy/cluster/tests/test_distance.py 2008-08-04 18:58:20 UTC (rev 4597) @@ -0,0 +1,949 @@ +#! /usr/bin/env python +# +# Author: Damian Eads +# Date: April 17, 2008 +# +# Copyright (C) 2008 Damian Eads +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# +# 3. The name of the author may not be used to endorse or promote +# products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +import sys +import os.path +from scipy.testing import * +from scipy.cluster.hierarchy import squareform, linkage, from_mlab_linkage, numobs_dm, numobs_y, numobs_linkage +from scipy.cluster.distance import pdist, matching, jaccard, dice, sokalsneath, rogerstanimoto, russellrao, yule + +import numpy +#import math + +#from scipy.cluster.hierarchy import pdist, euclidean + +_filenames = ["iris.txt", + "pdist-hamming-ml.txt", + "pdist-boolean-inp.txt", + "pdist-jaccard-ml.txt", + "pdist-cityblock-ml-iris.txt", + "pdist-minkowski-3.2-ml-iris.txt", + "pdist-cityblock-ml.txt", + "pdist-correlation-ml-iris.txt", + "pdist-minkowski-5.8-ml-iris.txt", + "pdist-correlation-ml.txt", + "pdist-minkowski-3.2-ml.txt", + "pdist-cosine-ml-iris.txt", + "pdist-seuclidean-ml-iris.txt", + "pdist-cosine-ml.txt", + "pdist-seuclidean-ml.txt", + "pdist-double-inp.txt", + "pdist-spearman-ml.txt", + "pdist-euclidean-ml.txt", + "pdist-euclidean-ml-iris.txt", + "pdist-chebychev-ml.txt", + "pdist-chebychev-ml-iris.txt", + "random-bool-data.txt"] + +_tdist = numpy.array([[0, 662, 877, 255, 412, 996], + [662, 0, 295, 468, 268, 400], + [877, 295, 0, 754, 564, 138], + [255, 468, 754, 0, 219, 869], + [412, 268, 564, 219, 0, 669], + [996, 400, 138, 869, 669, 0 ]], dtype='double') + +_ytdist = squareform(_tdist) + +# A hashmap of expected output arrays for the tests. These arrays +# come from a list of text files, which are read prior to testing. + +eo = {} + +def load_testing_files(): + for fn in _filenames: + name = fn.replace(".txt", "").replace("-ml", "") + fqfn = os.path.join(os.path.dirname(__file__), fn) + eo[name] = numpy.loadtxt(open(fqfn)) + #print "%s: %s %s" % (name, str(eo[name].shape), str(eo[name].dtype)) + eo['pdist-boolean-inp'] = numpy.bool_(eo['pdist-boolean-inp']) + +load_testing_files() + +#print eo.keys() + + +#print numpy.abs(Y_test2 - Y_right).max() +#print numpy.abs(Y_test1 - Y_right).max() + +class TestPdist(TestCase): + """ + Test suite for the pdist function. + """ + + ################### pdist: euclidean + def test_pdist_euclidean_random(self): + "Tests pdist(X, 'euclidean') on random data." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = eo['pdist-double-inp'] + Y_right = eo['pdist-euclidean'] + + Y_test1 = pdist(X, 'euclidean') + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_euclidean_random_float32(self): + "Tests pdist(X, 'euclidean') on random data (float32)." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['pdist-double-inp']) + Y_right = eo['pdist-euclidean'] + + Y_test1 = pdist(X, 'euclidean') + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_euclidean_random_nonC(self): + "Tests pdist(X, 'test_euclidean') [the non-C implementation] on random data." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = eo['pdist-double-inp'] + Y_right = eo['pdist-euclidean'] + Y_test2 = pdist(X, 'test_euclidean') + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + def test_pdist_euclidean_iris_double(self): + "Tests pdist(X, 'euclidean') on the Iris data set." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-euclidean-iris'] + + Y_test1 = pdist(X, 'euclidean') + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_euclidean_iris_float32(self): + "Tests pdist(X, 'euclidean') on the Iris data set. (float32)" + eps = 1e-06 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['iris']) + Y_right = eo['pdist-euclidean-iris'] + + Y_test1 = pdist(X, 'euclidean') + print numpy.abs(Y_right - Y_test1).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_euclidean_iris_nonC(self): + "Tests pdist(X, 'test_euclidean') [the non-C implementation] on the Iris data set." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-euclidean-iris'] + Y_test2 = pdist(X, 'test_euclidean') + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + ################### pdist: seuclidean + def test_pdist_seuclidean_random(self): + "Tests pdist(X, 'seuclidean') on random data." + eps = 1e-05 + # Get the data: the input matrix and the right output. + X = eo['pdist-double-inp'] + Y_right = eo['pdist-seuclidean'] + + Y_test1 = pdist(X, 'seuclidean') + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_seuclidean_random_float32(self): + "Tests pdist(X, 'seuclidean') on random data (float32)." + eps = 1e-05 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['pdist-double-inp']) + Y_right = eo['pdist-seuclidean'] + + Y_test1 = pdist(X, 'seuclidean') + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_seuclidean_random_nonC(self): + "Tests pdist(X, 'test_sqeuclidean') [the non-C implementation] on random data." + eps = 1e-05 + # Get the data: the input matrix and the right output. + X = eo['pdist-double-inp'] + Y_right = eo['pdist-seuclidean'] + Y_test2 = pdist(X, 'test_sqeuclidean') + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + def test_pdist_seuclidean_iris(self): + "Tests pdist(X, 'seuclidean') on the Iris data set." + eps = 1e-05 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-seuclidean-iris'] + + Y_test1 = pdist(X, 'seuclidean') + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_seuclidean_iris_float32(self): + "Tests pdist(X, 'seuclidean') on the Iris data set (float32)." + eps = 1e-05 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['iris']) + Y_right = eo['pdist-seuclidean-iris'] + + Y_test1 = pdist(X, 'seuclidean') + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_seuclidean_iris_nonC(self): + "Tests pdist(X, 'test_seuclidean') [the non-C implementation] on the Iris data set." + eps = 1e-05 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-seuclidean-iris'] + Y_test2 = pdist(X, 'test_sqeuclidean') + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + ################### pdist: cosine + def test_pdist_cosine_random(self): + "Tests pdist(X, 'cosine') on random data." + eps = 1e-08 + # Get the data: the input matrix and the right output. + X = eo['pdist-double-inp'] + Y_right = eo['pdist-cosine'] + Y_test1 = pdist(X, 'cosine') + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_cosine_random_float32(self): + "Tests pdist(X, 'cosine') on random data. (float32)" + eps = 1e-08 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['pdist-double-inp']) + Y_right = eo['pdist-cosine'] + + Y_test1 = pdist(X, 'cosine') + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_cosine_random_nonC(self): + "Tests pdist(X, 'test_cosine') [the non-C implementation] on random data." + eps = 1e-08 + # Get the data: the input matrix and the right output. + X = eo['pdist-double-inp'] + Y_right = eo['pdist-cosine'] + Y_test2 = pdist(X, 'test_cosine') + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + def test_pdist_cosine_iris(self): + "Tests pdist(X, 'cosine') on the Iris data set." + eps = 1e-08 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-cosine-iris'] + + Y_test1 = pdist(X, 'cosine') + self.failUnless(within_tol(Y_test1, Y_right, eps)) + #print "cosine-iris", numpy.abs(Y_test1 - Y_right).max() + + def test_pdist_cosine_iris_float32(self): + "Tests pdist(X, 'cosine') on the Iris data set." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['iris']) + Y_right = eo['pdist-cosine-iris'] + + Y_test1 = pdist(X, 'cosine') + print numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + #print "cosine-iris", numpy.abs(Y_test1 - Y_right).max() + + def test_pdist_cosine_iris_nonC(self): + "Tests pdist(X, 'test_cosine') [the non-C implementation] on the Iris data set." + eps = 1e-08 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-cosine-iris'] + Y_test2 = pdist(X, 'test_cosine') + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + ################### pdist: cityblock + def test_pdist_cityblock_random(self): + "Tests pdist(X, 'cityblock') on random data." + eps = 1e-06 + # Get the data: the input matrix and the right output. + X = eo['pdist-double-inp'] + Y_right = eo['pdist-cityblock'] + Y_test1 = pdist(X, 'cityblock') + #print "cityblock", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_cityblock_random_float32(self): + "Tests pdist(X, 'cityblock') on random data. (float32)" + eps = 1e-06 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['pdist-double-inp']) + Y_right = eo['pdist-cityblock'] + Y_test1 = pdist(X, 'cityblock') + #print "cityblock", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_cityblock_random_nonC(self): + "Tests pdist(X, 'test_cityblock') [the non-C implementation] on random data." + eps = 1e-06 + # Get the data: the input matrix and the right output. + X = eo['pdist-double-inp'] + Y_right = eo['pdist-cityblock'] + Y_test2 = pdist(X, 'test_cityblock') + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + def test_pdist_cityblock_iris(self): + "Tests pdist(X, 'cityblock') on the Iris data set." + eps = 1e-14 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-cityblock-iris'] + + Y_test1 = pdist(X, 'cityblock') + self.failUnless(within_tol(Y_test1, Y_right, eps)) + #print "cityblock-iris", numpy.abs(Y_test1 - Y_right).max() + + def test_pdist_cityblock_iris_float32(self): + "Tests pdist(X, 'cityblock') on the Iris data set. (float32)" + eps = 1e-06 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['iris']) + Y_right = eo['pdist-cityblock-iris'] + + Y_test1 = pdist(X, 'cityblock') + print "cityblock-iris-float32", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_cityblock_iris_nonC(self): + "Tests pdist(X, 'test_cityblock') [the non-C implementation] on the Iris data set." + eps = 1e-14 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-cityblock-iris'] + Y_test2 = pdist(X, 'test_cityblock') + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + ################### pdist: correlation + def test_pdist_correlation_random(self): + "Tests pdist(X, 'correlation') on random data." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = eo['pdist-double-inp'] + Y_right = eo['pdist-correlation'] + + Y_test1 = pdist(X, 'correlation') + #print "correlation", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_correlation_random_float32(self): + "Tests pdist(X, 'correlation') on random data. (float32)" + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['pdist-double-inp']) + Y_right = eo['pdist-correlation'] + + Y_test1 = pdist(X, 'correlation') + #print "correlation", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_correlation_random_nonC(self): + "Tests pdist(X, 'test_correlation') [the non-C implementation] on random data." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = eo['pdist-double-inp'] + Y_right = eo['pdist-correlation'] + Y_test2 = pdist(X, 'test_correlation') + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + def test_pdist_correlation_iris(self): + "Tests pdist(X, 'correlation') on the Iris data set." + eps = 1e-08 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-correlation-iris'] + + Y_test1 = pdist(X, 'correlation') + #print "correlation-iris", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_correlation_iris_float32(self): + "Tests pdist(X, 'correlation') on the Iris data set. (float32)" + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = numpy.float32(eo['pdist-correlation-iris']) + + Y_test1 = pdist(X, 'correlation') + print "correlation-iris", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_correlation_iris_nonC(self): + "Tests pdist(X, 'test_correlation') [the non-C implementation] on the Iris data set." + eps = 1e-08 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-correlation-iris'] + Y_test2 = pdist(X, 'test_correlation') + #print "test-correlation-iris", numpy.abs(Y_test2 - Y_right).max() + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + ################# minkowski + + def test_pdist_minkowski_random(self): + "Tests pdist(X, 'minkowski') on random data." + eps = 1e-05 + # Get the data: the input matrix and the right output. + X = eo['pdist-double-inp'] + Y_right = eo['pdist-minkowski-3.2'] + + Y_test1 = pdist(X, 'minkowski', 3.2) + #print "minkowski", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_minkowski_random_float32(self): + "Tests pdist(X, 'minkowski') on random data. (float32)" + eps = 1e-05 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['pdist-double-inp']) + Y_right = eo['pdist-minkowski-3.2'] + + Y_test1 = pdist(X, 'minkowski', 3.2) + #print "minkowski", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_minkowski_random_nonC(self): + "Tests pdist(X, 'test_minkowski') [the non-C implementation] on random data." + eps = 1e-05 + # Get the data: the input matrix and the right output. + X = eo['pdist-double-inp'] + Y_right = eo['pdist-minkowski-3.2'] + Y_test2 = pdist(X, 'test_minkowski', 3.2) + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + def test_pdist_minkowski_iris(self): + "Tests pdist(X, 'minkowski') on iris data." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-minkowski-3.2-iris'] + Y_test1 = pdist(X, 'minkowski', 3.2) + #print "minkowski-iris-3.2", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_minkowski_iris_float32(self): + "Tests pdist(X, 'minkowski') on iris data. (float32)" + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['iris']) + Y_right = eo['pdist-minkowski-3.2-iris'] + Y_test1 = pdist(X, 'minkowski', 3.2) + #print "minkowski-iris-3.2", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_minkowski_iris_nonC(self): + "Tests pdist(X, 'test_minkowski') [the non-C implementation] on iris data." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-minkowski-3.2-iris'] + Y_test2 = pdist(X, 'test_minkowski', 3.2) + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + def test_pdist_minkowski_iris(self): + "Tests pdist(X, 'minkowski') on iris data." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-minkowski-5.8-iris'] + Y_test1 = pdist(X, 'minkowski', 5.8) + #print "minkowski-iris-5.8", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_minkowski_iris_float32(self): + "Tests pdist(X, 'minkowski') on iris data. (float32)" + eps = 1e-06 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['iris']) + Y_right = eo['pdist-minkowski-5.8-iris'] + + Y_test1 = pdist(X, 'minkowski', 5.8) + print "minkowski-iris-5.8", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_minkowski_iris_nonC(self): + "Tests pdist(X, 'test_minkowski') [the non-C implementation] on iris data." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-minkowski-5.8-iris'] + Y_test2 = pdist(X, 'test_minkowski', 5.8) + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + ################### pdist: hamming + def test_pdist_hamming_random(self): + "Tests pdist(X, 'hamming') on random data." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = eo['pdist-boolean-inp'] + Y_right = eo['pdist-hamming'] + + Y_test1 = pdist(X, 'hamming') + #print "hamming", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_hamming_random_float32(self): + "Tests pdist(X, 'hamming') on random data." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['pdist-boolean-inp']) + Y_right = eo['pdist-hamming'] + + Y_test1 = pdist(X, 'hamming') + #print "hamming", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_hamming_random_nonC(self): + "Tests pdist(X, 'test_hamming') [the non-C implementation] on random data." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = eo['pdist-boolean-inp'] + Y_right = eo['pdist-hamming'] + Y_test2 = pdist(X, 'test_hamming') + #print "test-hamming", numpy.abs(Y_test2 - Y_right).max() + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + ################### pdist: hamming (double) + def test_pdist_dhamming_random(self): + "Tests pdist(X, 'hamming') on random data." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = numpy.float64(eo['pdist-boolean-inp']) + Y_right = eo['pdist-hamming'] + Y_test1 = pdist(X, 'hamming') + #print "hamming", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_dhamming_random_float32(self): + "Tests pdist(X, 'hamming') on random data. (float32)" + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['pdist-boolean-inp']) + Y_right = eo['pdist-hamming'] + Y_test1 = pdist(X, 'hamming') + #print "hamming", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_dhamming_random_nonC(self): + "Tests pdist(X, 'test_hamming') [the non-C implementation] on random data." + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = numpy.float64(eo['pdist-boolean-inp']) + Y_right = eo['pdist-hamming'] + Y_test2 = pdist(X, 'test_hamming') + #print "test-hamming", numpy.abs(Y_test2 - Y_right).max() + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + ################### pdist: jaccard + def test_pdist_jaccard_random(self): + "Tests pdist(X, 'jaccard') on random data." + eps = 1e-08 + # Get the data: the input matrix and the right output. + X = eo['pdist-boolean-inp'] + Y_right = eo['pdist-jaccard'] + + Y_test1 = pdist(X, 'jaccard') + #print "jaccard", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_jaccard_random_float32(self): + "Tests pdist(X, 'jaccard') on random data. (float32)" + eps = 1e-08 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['pdist-boolean-inp']) + Y_right = eo['pdist-jaccard'] + + Y_test1 = pdist(X, 'jaccard') + #print "jaccard", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_jaccard_random_nonC(self): + "Tests pdist(X, 'test_jaccard') [the non-C implementation] on random data." + eps = 1e-08 + # Get the data: the input matrix and the right output. + X = eo['pdist-boolean-inp'] + Y_right = eo['pdist-jaccard'] + Y_test2 = pdist(X, 'test_jaccard') + #print "test-jaccard", numpy.abs(Y_test2 - Y_right).max() + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + ################### pdist: jaccard (double) + def test_pdist_djaccard_random(self): + "Tests pdist(X, 'jaccard') on random data." + eps = 1e-08 + # Get the data: the input matrix and the right output. + X = numpy.float64(eo['pdist-boolean-inp']) + Y_right = eo['pdist-jaccard'] + + Y_test1 = pdist(X, 'jaccard') + #print "jaccard", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_djaccard_random_float32(self): + "Tests pdist(X, 'jaccard') on random data. (float32)" + eps = 1e-08 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['pdist-boolean-inp']) + Y_right = eo['pdist-jaccard'] + + Y_test1 = pdist(X, 'jaccard') + #print "jaccard", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_djaccard_random_nonC(self): + "Tests pdist(X, 'test_jaccard') [the non-C implementation] on random data." + eps = 1e-08 + # Get the data: the input matrix and the right output. + X = numpy.float64(eo['pdist-boolean-inp']) + Y_right = eo['pdist-jaccard'] + Y_test2 = pdist(X, 'test_jaccard') + #print "test-jaccard", numpy.abs(Y_test2 - Y_right).max() + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + ################### pdist: chebychev + def test_pdist_chebychev_random(self): + "Tests pdist(X, 'chebychev') on random data." + eps = 1e-08 + # Get the data: the input matrix and the right output. + X = eo['pdist-double-inp'] + Y_right = eo['pdist-chebychev'] + + Y_test1 = pdist(X, 'chebychev') + #print "chebychev", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_chebychev_random_float32(self): + "Tests pdist(X, 'chebychev') on random data. (float32)" + eps = 1e-07 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['pdist-double-inp']) + Y_right = eo['pdist-chebychev'] + + Y_test1 = pdist(X, 'chebychev') + print "chebychev", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_chebychev_random_nonC(self): + "Tests pdist(X, 'test_chebychev') [the non-C implementation] on random data." + eps = 1e-08 + # Get the data: the input matrix and the right output. + X = eo['pdist-double-inp'] + Y_right = eo['pdist-chebychev'] + Y_test2 = pdist(X, 'test_chebychev') + #print "test-chebychev", numpy.abs(Y_test2 - Y_right).max() + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + def test_pdist_chebychev_iris(self): + "Tests pdist(X, 'chebychev') on the Iris data set." + eps = 1e-15 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-chebychev-iris'] + Y_test1 = pdist(X, 'chebychev') + #print "chebychev-iris", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_chebychev_iris_float32(self): + "Tests pdist(X, 'chebychev') on the Iris data set. (float32)" + eps = 1e-06 + # Get the data: the input matrix and the right output. + X = numpy.float32(eo['iris']) + Y_right = eo['pdist-chebychev-iris'] + Y_test1 = pdist(X, 'chebychev') + print "chebychev-iris", numpy.abs(Y_test1 - Y_right).max() + self.failUnless(within_tol(Y_test1, Y_right, eps)) + + def test_pdist_chebychev_iris_nonC(self): + "Tests pdist(X, 'test_chebychev') [the non-C implementation] on the Iris data set." + eps = 1e-15 + # Get the data: the input matrix and the right output. + X = eo['iris'] + Y_right = eo['pdist-chebychev-iris'] + Y_test2 = pdist(X, 'test_chebychev') + #print "test-chebychev-iris", numpy.abs(Y_test2 - Y_right).max() + self.failUnless(within_tol(Y_test2, Y_right, eps)) + + def test_pdist_matching_mtica1(self): + "Tests matching(*,*) with mtica example #1 (nums)." + m = matching(numpy.array([1, 0, 1, 1, 0]), + numpy.array([1, 1, 0, 1, 1])) + m2 = matching(numpy.array([1, 0, 1, 1, 0], dtype=numpy.bool), + numpy.array([1, 1, 0, 1, 1], dtype=numpy.bool)) + self.failUnless(numpy.abs(m - 0.6) <= 1e-10) + self.failUnless(numpy.abs(m2 - 0.6) <= 1e-10) + + def test_pdist_matching_mtica2(self): + "Tests matching(*,*) with mtica example #2." + m = matching(numpy.array([1, 0, 1]), + numpy.array([1, 1, 0])) + m2 = matching(numpy.array([1, 0, 1], dtype=numpy.bool), + numpy.array([1, 1, 0], dtype=numpy.bool)) + self.failUnless(numpy.abs(m - (2.0/3.0)) <= 1e-10) + self.failUnless(numpy.abs(m2 - (2.0/3.0)) <= 1e-10) + + def test_pdist_matching_match(self): + "Tests pdist(X, 'matching') to see if the two implementations match on random boolean input data." + D = eo['random-bool-data'] + B = numpy.bool_(D) + print B.shape, B.dtype + eps = 1e-10 + y1 = pdist(B, "matching") + y2 = pdist(B, "test_matching") + y3 = pdist(D, "test_matching") + print numpy.abs(y1-y2).max() + print numpy.abs(y1-y3).max() + self.failUnless(within_tol(y1, y2, eps)) + self.failUnless(within_tol(y2, y3, eps)) + + def test_pdist_jaccard_mtica1(self): + "Tests jaccard(*,*) with mtica example #1." + m = jaccard(numpy.array([1, 0, 1, 1, 0]), + numpy.array([1, 1, 0, 1, 1])) + m2 = jaccard(numpy.array([1, 0, 1, 1, 0], dtype=numpy.bool), + numpy.array([1, 1, 0, 1, 1], dtype=numpy.bool)) + self.failUnless(numpy.abs(m - 0.6) <= 1e-10) + self.failUnless(numpy.abs(m2 - 0.6) <= 1e-10) + + def test_pdist_jaccard_mtica2(self): + "Tests jaccard(*,*) with mtica example #2." + m = jaccard(numpy.array([1, 0, 1]), + numpy.array([1, 1, 0])) + m2 = jaccard(numpy.array([1, 0, 1], dtype=numpy.bool), + numpy.array([1, 1, 0], dtype=numpy.bool)) + self.failUnless(numpy.abs(m - (2.0/3.0)) <= 1e-10) + self.failUnless(numpy.abs(m2 - (2.0/3.0)) <= 1e-10) + + def test_pdist_jaccard_match(self): + "Tests pdist(X, 'jaccard') to see if the two implementations match on random double input data." + D = eo['random-bool-data'] + print D.shape, D.dtype + eps = 1e-10 + y1 = pdist(D, "jaccard") + y2 = pdist(D, "test_jaccard") + y3 = pdist(numpy.bool_(D), "test_jaccard") + print numpy.abs(y1-y2).max() + print numpy.abs(y2-y3).max() + self.failUnless(within_tol(y1, y2, eps)) + self.failUnless(within_tol(y2, y3, eps)) + + def test_pdist_yule_mtica1(self): + "Tests yule(*,*) with mtica example #1." + m = yule(numpy.array([1, 0, 1, 1, 0]), + numpy.array([1, 1, 0, 1, 1])) + m2 = yule(numpy.array([1, 0, 1, 1, 0], dtype=numpy.bool), + numpy.array([1, 1, 0, 1, 1], dtype=numpy.bool)) + print m + self.failUnless(numpy.abs(m - 2.0) <= 1e-10) + self.failUnless(numpy.abs(m2 - 2.0) <= 1e-10) + + def test_pdist_yule_mtica2(self): + "Tests yule(*,*) with mtica example #2." + m = yule(numpy.array([1, 0, 1]), + numpy.array([1, 1, 0])) + m2 = yule(numpy.array([1, 0, 1], dtype=numpy.bool), + numpy.array([1, 1, 0], dtype=numpy.bool)) + print m + self.failUnless(numpy.abs(m - 2.0) <= 1e-10) + self.failUnless(numpy.abs(m2 - 2.0) <= 1e-10) + + def test_pdist_yule_match(self): + "Tests pdist(X, 'yule') to see if the two implementations match on random double input data." + D = eo['random-bool-data'] + print D.shape, D.dtype + eps = 1e-10 + y1 = pdist(D, "yule") + y2 = pdist(D, "test_yule") + y3 = pdist(numpy.bool_(D), "test_yule") + print numpy.abs(y1-y2).max() + print numpy.abs(y2-y3).max() + self.failUnless(within_tol(y1, y2, eps)) + self.failUnless(within_tol(y2, y3, eps)) + + def test_pdist_dice_mtica1(self): + "Tests dice(*,*) with mtica example #1." + m = dice(numpy.array([1, 0, 1, 1, 0]), + numpy.array([1, 1, 0, 1, 1])) + m2 = dice(numpy.array([1, 0, 1, 1, 0], dtype=numpy.bool), + numpy.array([1, 1, 0, 1, 1], dtype=numpy.bool)) + print m + self.failUnless(numpy.abs(m - (3.0/7.0)) <= 1e-10) + self.failUnless(numpy.abs(m2 - (3.0/7.0)) <= 1e-10) + + def test_pdist_dice_mtica2(self): + "Tests dice(*,*) with mtica example #2." + m = dice(numpy.array([1, 0, 1]), + numpy.array([1, 1, 0])) + m2 = dice(numpy.array([1, 0, 1], dtype=numpy.bool), + numpy.array([1, 1, 0], dtype=numpy.bool)) + print m + self.failUnless(numpy.abs(m - 0.5) <= 1e-10) + self.failUnless(numpy.abs(m2 - 0.5) <= 1e-10) + + def test_pdist_dice_match(self): + "Tests pdist(X, 'dice') to see if the two implementations match on random double input data." + D = eo['random-bool-data'] + print D.shape, D.dtype + eps = 1e-10 + y1 = pdist(D, "dice") + y2 = pdist(D, "test_dice") + y3 = pdist(D, "test_dice") + print numpy.abs(y1-y2).max() + print numpy.abs(y2-y3).max() + self.failUnless(within_tol(y1, y2, eps)) + self.failUnless(within_tol(y2, y3, eps)) + + def test_pdist_sokalsneath_mtica1(self): + "Tests sokalsneath(*,*) with mtica example #1." + m = sokalsneath(numpy.array([1, 0, 1, 1, 0]), + numpy.array([1, 1, 0, 1, 1])) + m2 = sokalsneath(numpy.array([1, 0, 1, 1, 0], dtype=numpy.bool), + numpy.array([1, 1, 0, 1, 1], dtype=numpy.bool)) + print m + self.failUnless(numpy.abs(m - (3.0/4.0)) <= 1e-10) + self.failUnless(numpy.abs(m2 - (3.0/4.0)) <= 1e-10) + + def test_pdist_sokalsneath_mtica2(self): + "Tests sokalsneath(*,*) with mtica example #2." + m = sokalsneath(numpy.array([1, 0, 1]), + numpy.array([1, 1, 0])) + m2 = sokalsneath(numpy.array([1, 0, 1], dtype=numpy.bool), + numpy.array([1, 1, 0], dtype=numpy.bool)) + print m + self.failUnless(numpy.abs(m - (4.0/5.0)) <= 1e-10) + self.failUnless(numpy.abs(m2 - (4.0/5.0)) <= 1e-10) + + def test_pdist_sokalsneath_match(self): + "Tests pdist(X, 'sokalsneath') to see if the two implementations match on random double input data." + D = eo['random-bool-data'] + print D.shape, D.dtype + eps = 1e-10 + y1 = pdist(D, "sokalsneath") + y2 = pdist(D, "test_sokalsneath") + y3 = pdist(numpy.bool_(D), "test_sokalsneath") + print numpy.abs(y1-y2).max() + print numpy.abs(y2-y3).max() + self.failUnless(within_tol(y1, y2, eps)) + self.failUnless(within_tol(y2, y3, eps)) + + def test_pdist_rogerstanimoto_mtica1(self): + "Tests rogerstanimoto(*,*) with mtica example #1." + m = rogerstanimoto(numpy.array([1, 0, 1, 1, 0]), + numpy.array([1, 1, 0, 1, 1])) + m2 = rogerstanimoto(numpy.array([1, 0, 1, 1, 0], dtype=numpy.bool), + numpy.array([1, 1, 0, 1, 1], dtype=numpy.bool)) + print m + self.failUnless(numpy.abs(m - (3.0/4.0)) <= 1e-10) + self.failUnless(numpy.abs(m2 - (3.0/4.0)) <= 1e-10) + + def test_pdist_rogerstanimoto_mtica2(self): + "Tests rogerstanimoto(*,*) with mtica example #2." + m = rogerstanimoto(numpy.array([1, 0, 1]), + numpy.array([1, 1, 0])) + m2 = rogerstanimoto(numpy.array([1, 0, 1], dtype=numpy.bool), + numpy.array([1, 1, 0], dtype=numpy.bool)) + print m + self.failUnless(numpy.abs(m - (4.0/5.0)) <= 1e-10) + self.failUnless(numpy.abs(m2 - (4.0/5.0)) <= 1e-10) + + def test_pdist_rogerstanimoto_match(self): + "Tests pdist(X, 'rogerstanimoto') to see if the two implementations match on random double input data." + D = eo['random-bool-data'] + print D.shape, D.dtype + eps = 1e-10 + y1 = pdist(D, "rogerstanimoto") + y2 = pdist(D, "test_rogerstanimoto") + y3 = pdist(numpy.bool_(D), "test_rogerstanimoto") + print numpy.abs(y1-y2).max() + print numpy.abs(y2-y3).max() + self.failUnless(within_tol(y1, y2, eps)) + self.failUnless(within_tol(y2, y3, eps)) + + def test_pdist_russellrao_mtica1(self): + "Tests russellrao(*,*) with mtica example #1." + m = russellrao(numpy.array([1, 0, 1, 1, 0]), + numpy.array([1, 1, 0, 1, 1])) + m2 = russellrao(numpy.array([1, 0, 1, 1, 0], dtype=numpy.bool), + numpy.array([1, 1, 0, 1, 1], dtype=numpy.bool)) + print m + self.failUnless(numpy.abs(m - (3.0/5.0)) <= 1e-10) + self.failUnless(numpy.abs(m2 - (3.0/5.0)) <= 1e-10) + + def test_pdist_russellrao_mtica2(self): + "Tests russellrao(*,*) with mtica example #2." + m = russellrao(numpy.array([1, 0, 1]), + numpy.array([1, 1, 0])) + m2 = russellrao(numpy.array([1, 0, 1], dtype=numpy.bool), + numpy.array([1, 1, 0], dtype=numpy.bool)) + print m + self.failUnless(numpy.abs(m - (2.0/3.0)) <= 1e-10) + self.failUnless(numpy.abs(m2 - (2.0/3.0)) <= 1e-10) + + def test_pdist_russellrao_match(self): + "Tests pdist(X, 'russellrao') to see if the two implementations match on random double input data." + D = eo['random-bool-data'] + print D.shape, D.dtype + eps = 1e-10 + y1 = pdist(D, "russellrao") + y2 = pdist(D, "test_russellrao") + y3 = pdist(numpy.bool_(D), "test_russellrao") + print numpy.abs(y1-y2).max() + print numpy.abs(y2-y3).max() + self.failUnless(within_tol(y1, y2, eps)) + self.failUnless(within_tol(y2, y3, eps)) + + def test_pdist_sokalmichener_match(self): + "Tests pdist(X, 'sokalmichener') to see if the two implementations match on random double input data." + D = eo['random-bool-data'] + print D.shape, D.dtype + eps = 1e-10 + y1 = pdist(D, "sokalmichener") + y2 = pdist(D, "test_sokalmichener") + y3 = pdist(numpy.bool_(D), "test_sokalmichener") + print numpy.abs(y1-y2).max() + print numpy.abs(y2-y3).max() + self.failUnless(within_tol(y1, y2, eps)) + self.failUnless(within_tol(y2, y3, eps)) + + def test_pdist_kulsinski_match(self): + "Tests pdist(X, 'kulsinski') to see if the two implementations match on random double input data." + D = eo['random-bool-data'] + print D.shape, D.dtype + eps = 1e-10 + y1 = pdist(D, "kulsinski") + y2 = pdist(D, "test_kulsinski") + y3 = pdist(numpy.bool_(D), "test_kulsinski") + print numpy.abs(y1-y2).max() + self.failUnless(within_tol(y1, y2, eps)) + +def within_tol(a, b, tol): + return numpy.abs(a - b).max() < tol From scipy-svn at scipy.org Mon Aug 4 15:00:13 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 4 Aug 2008 14:00:13 -0500 (CDT) Subject: [Scipy-svn] r4598 - trunk/scipy/cluster/tests Message-ID: <20080804190013.87C6139C192@scipy.org> Author: damian.eads Date: 2008-08-04 14:00:04 -0500 (Mon, 04 Aug 2008) New Revision: 4598 Modified: trunk/scipy/cluster/tests/test_hierarchy.py Log: Moved distance tests out of test_hierarchy.py Modified: trunk/scipy/cluster/tests/test_hierarchy.py =================================================================== --- trunk/scipy/cluster/tests/test_hierarchy.py 2008-08-04 18:58:20 UTC (rev 4597) +++ trunk/scipy/cluster/tests/test_hierarchy.py 2008-08-04 19:00:04 UTC (rev 4598) @@ -38,7 +38,7 @@ import numpy from numpy.testing import * -from scipy.cluster.hierarchy import squareform, linkage, from_mlab_linkage, numobs_dm, numobs_y, numobs_linkage +from scipy.cluster.hierarchy import squareform, linkage, from_mlab_linkage, numobs_dm, numobs_y, numobs_linkage, inconsistent from scipy.cluster.distance import pdist, matching, jaccard, dice, sokalsneath, rogerstanimoto, russellrao, yule _tdist = numpy.array([[0, 662, 877, 255, 412, 996], @@ -58,9 +58,23 @@ "linkage-complete-tdist.txt", "linkage-average-tdist.txt", "linkage-weighted-tdist.txt", + "inconsistent-complete-tdist-depth-1.txt", + "inconsistent-complete-tdist-depth-2.txt", + "inconsistent-complete-tdist-depth-3.txt", + "inconsistent-complete-tdist-depth-4.txt", + "inconsistent-single-tdist-depth-0.txt", + "inconsistent-single-tdist-depth-1.txt", + "inconsistent-single-tdist-depth-2.txt", + "inconsistent-single-tdist-depth-3.txt", + "inconsistent-single-tdist-depth-4.txt", + "inconsistent-single-tdist-depth-5.txt", + "inconsistent-single-tdist.txt", + "inconsistent-weighted-tdist-depth-1.txt", + "inconsistent-weighted-tdist-depth-2.txt", + "inconsistent-weighted-tdist-depth-3.txt", + "inconsistent-weighted-tdist-depth-4.txt", "random-bool-data.txt"] - def load_testing_files(): for fn in _filenames: name = fn.replace(".txt", "").replace("-ml", "") @@ -204,6 +218,21 @@ #print Z, expectedZ, numpy.abs(Z - expectedZ).max() self.failUnless(within_tol(Z, expectedZ, eps)) +class TestInconsistent(TestCase): + + def test_single_inconsistent_tdist(self): + for i in xrange(0, 100): + yield help_single_inconsistent_depth, i + +def help_single_inconsistent_depth(self, i): + Y = squareform(_tdist) + Z = linkage(Y, 'single') + R = inconsistent(Z, i) + Rright = eo['inconsistent-single-tdist-depth-' + str(i)] + eps = 1e-05 + print numpy.abs(R - Rright).max() + self.failUnless(within_tol(R, Rright, eps)) + def within_tol(a, b, tol): return numpy.abs(a - b).max() < tol From scipy-svn at scipy.org Mon Aug 4 15:48:26 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 4 Aug 2008 14:48:26 -0500 (CDT) Subject: [Scipy-svn] r4599 - trunk/scipy/cluster Message-ID: <20080804194826.1F02E39C113@scipy.org> Author: damian.eads Date: 2008-08-04 14:48:18 -0500 (Mon, 04 Aug 2008) New Revision: 4599 Modified: trunk/scipy/cluster/distance.py Log: Fixed canberra. Now passes a double array to C-extension instead of a bool. Modified: trunk/scipy/cluster/distance.py =================================================================== --- trunk/scipy/cluster/distance.py 2008-08-04 19:00:04 UTC (rev 4598) +++ trunk/scipy/cluster/distance.py 2008-08-04 19:48:18 UTC (rev 4599) @@ -764,7 +764,7 @@ # (u-v)V^(-1)(u-v)^T _distance_wrap.pdist_mahalanobis_wrap(_convert_to_double(X), VI, dm) elif mstr == 'canberra': - _distance_wrap.pdist_canberra_wrap(_convert_to_bool(X), dm) + _distance_wrap.pdist_canberra_wrap(_convert_to_double(X), dm) elif mstr == 'braycurtis': _distance_wrap.pdist_bray_curtis_wrap(_convert_to_bool(X), dm) elif mstr == 'yule': @@ -802,6 +802,8 @@ [VI] = _copy_arrays_if_base_present([VI]) # (u-v)V^(-1)(u-v)^T dm = pdist(X, (lambda u, v: mahalanobis(u, v, VI))) + elif metric == 'test_canberra': + dm = pdist(X, canberra) elif metric == 'test_cityblock': dm = pdist(X, cityblock) elif metric == 'test_minkowski': From scipy-svn at scipy.org Mon Aug 4 16:27:29 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 4 Aug 2008 15:27:29 -0500 (CDT) Subject: [Scipy-svn] r4600 - in branches/Interpolate1D: . docs Message-ID: <20080804202729.4E8E839C55E@scipy.org> Author: fcady Date: 2008-08-04 15:27:24 -0500 (Mon, 04 Aug 2008) New Revision: 4600 Added: branches/Interpolate1D/docs/XY-crossection.png branches/Interpolate1D/docs/XY-surface.png Modified: branches/Interpolate1D/TODO.txt branches/Interpolate1D/docs/tutorial.rst branches/Interpolate1D/fitpack_wrapper2d.py branches/Interpolate1D/interpolate2d.py Log: more work done on documentation, a format check on the input, and some bug fixes. This should be rpetty good now. Modified: branches/Interpolate1D/TODO.txt =================================================================== --- branches/Interpolate1D/TODO.txt 2008-08-04 19:48:18 UTC (rev 4599) +++ branches/Interpolate1D/TODO.txt 2008-08-04 20:27:24 UTC (rev 4600) @@ -5,7 +5,7 @@ at appropriate places in the code. -************ PRESSING ISSUES *********** +************ API and/or MAJOR ISSUES *********** **handle smoothing There is a question of whether, if, and how much to allow @@ -19,7 +19,11 @@ This appears resolved, in that Spline can do smoothing (but defaults to not), and user-defined classes are allowed to smooth. +**remove list comprehension in interpolate2d.Interpolate2d.__call__ +**possibly allow interp2d to return a 2d array? Like in the case that + x and y are 2d arrays in meshgrid format. + **pick best spline Under-the-hood machinery currently comes from _interpolate.cpp (used in enthought.interpolate) and FITPACK (Fortran, used in @@ -31,15 +35,6 @@ regular grid. I'm inclined to stay with FITPACK, except for the slow performance when x is small (we could add a hack to not let s be tiny > 0). - - -**clean up fitpack_wrapper.py - Currently it is all hacked together from scipy.interpolate. - There is unused functionality, commented-out functionality, - and other undesirables. Once it has been established what - we will include, and what should be accessible to the user, - that stuff needs to be cleaned up, and the - rest needs to be either removed or set aside. **allow y to be 2-dimensional? It is not decided whether this feature should be supported, but @@ -69,7 +64,11 @@ See also "allow y to be 2-dimensional?" below +**Put Spline2d into fitpack_wrapper.py + It's out now so that is can be worked on separately, but the + fitpack-based code should all be in one module. + *********** DOCUMENTATION-TYPE AND NON-URGENT TASKS ******* @@ -113,7 +112,7 @@ ********* LONGER TERM ************ -**update for 2D and ND +**update for ND This will take the form of two additional classes both modelled after interpolate1d. Thus it probably shouldn't be done until interpolate1d is more settled. Added: branches/Interpolate1D/docs/XY-crossection.png =================================================================== (Binary files differ) Property changes on: branches/Interpolate1D/docs/XY-crossection.png ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: branches/Interpolate1D/docs/XY-surface.png =================================================================== (Binary files differ) Property changes on: branches/Interpolate1D/docs/XY-surface.png ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Modified: branches/Interpolate1D/docs/tutorial.rst =================================================================== --- branches/Interpolate1D/docs/tutorial.rst 2008-08-04 19:48:18 UTC (rev 4599) +++ branches/Interpolate1D/docs/tutorial.rst 2008-08-04 20:27:24 UTC (rev 4600) @@ -6,28 +6,30 @@ a sample of a function into an approximation of that function for every value, and is one of the most basic mathematical tools available to a researcher. -The interpolate package provides tools for interpolating and extrapolating new data points from a known set of data points. -It provides a functional interface that is flexible and easy to use as well as an object oriented interface that -can be more efficient and flexible for some cases. It is able to interpolate and extrapolate in 1D, 2D, and even N -dimensions. *[FIXME : 1D only right now]* +The interpolate package provides tools for interpolating and extrapolating new data points +from a known set of data points. It provides a functional interface that is flexible and easy +to use as well as an object oriented interface that can be more efficient and flexible for some +cases. It is able to interpolate and extrapolate in 1D, 2D, and even N dimensions. *[FIXME : 1D only right now]* -For 1D interpolation, it handles linear and spline(cubic, quadratic, and quintic) for both uniformly and non-uniformly spaced -data points "out of the box." Users can choose the behavior when new values fall outside the range of known data, and -with a little more work, they can incorporate interpolation methods that are specially tailored to their needs. +For 1D interpolation, it handles both uniformly and non-uniformly spaced data points, +and many popular interpolation methods (particularly splines) are available by simply passing in a keyword +string ('linear' for linear interpolation, 'cubic' for spline order 3, etc). With a little +more work, users can design and incorporate interpolation methods that are specially tailored to their needs. -For 2D interpolation, *[FIXME : include this]* +2D interpolation is analogous to 1D, with a nearly identical user interface (corrected for the fact +that each data point has one more component) and functionality. This tutorial covers how to use the interpolate module, provides some basic examples, and shows them at work in realistic sample sessions. These sessions demonstrate how to use the interpolate module, but also highlight some of the uses of interpolation techniques. -================================================ -1D Interpolation with the Functional Interface -================================================ +====================== +1D Interpolation +====================== -------------- -Basic Usage -------------- +--------------------------------------------------------- +Basic Usage with the Functional Interface +--------------------------------------------------------- For most users, the primary feature of interpolate is the function 'interp1d'. It takes in known data points and the points at which to interpolate values, and returns @@ -161,6 +163,7 @@ using bad_data removed both those points, so the entire range of x is linearly interpolated. + -------------------------------------- User-defined Interpolation Methods -------------------------------------- @@ -244,12 +247,25 @@ Out []: array([ 5.7, 4.0, 5.7 ]) +----------------------------- +Smoothing data +----------------------------- +Interpolate1d does not explicitly support smoothing of noisy data. Other packages +can be used to pre-filter the data before calling Interpolate1d on it, but +a more convenient option is provided by the Spline class described below. +Spline supports data smoothing with the keyword s (which defaults to 0, i.e. no +smoothing). If you want smoothing, you can set kind equal to an instance of the +Spline class which has s != 0. For example: :: + In []: import interpolate as I + In []: newy = I.interp1d(x, y, newx, kind=I.Spline(s=4.0) ) -================================================ + + +-------------------------------------------------------------------- 1D Interpolation with the Object Interface -================================================ +-------------------------------------------------------------------- interp1d is built as a wrapper around the class Interpolate1d. If you want to interpolate multiple times from the same dataset, it can be more efficient @@ -281,17 +297,17 @@ In []: new_y2 == new_Y2 Out []: True -================================================== +-------------------------------------------------------------------- Sample Data Analysis Sessions Using Interpolate -================================================== +-------------------------------------------------------------------- Below are several sample sessions or code pieces from various applications showing uses for interpolation and how it can be done using the interpolate module. ------------------------------------------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Estimating Function Statistics and Displaying Data ------------------------------------------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In this session, the geologist has a data set of data indicating the temperature at various @@ -322,9 +338,9 @@ # are not necessarily uniform, but it is easy to uniformly sample the interpolated function In []: average_temp = average( I.interp1d(depth, temp, linspace(0,20,100), 'cubic', bad_data=[1000]) ) ---------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Modeling from a small dataset ---------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This computational biologist wants to model the growth rate of cancer cells in tissue. For several levels of blood glucose, he has measurements @@ -366,9 +382,9 @@ def __call__(self, glucose_level): return self.CO2_to_growth( self.glucose_to_CO2( glucose_level )) --------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Optimization --------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This engineer is developing a piece of hardware, and needs to find the optimal thickness for a thin film it contains. Because performance (by some metric) is at a premium, @@ -404,9 +420,9 @@ More sophisticated optimization tools are also available from the scipy.optimize module. -=================== +----------------------------------------- The Spline Class -=================== +----------------------------------------- Interpolate1d, with the string arguments 'spline', 'cubic', 'quad', 'quintic', etc, is actually a wrapper around the Spline class, which contains fast and powerful Fortran @@ -415,9 +431,9 @@ This section describes the operation of the Spline class. ----------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Intro to Splines ----------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Splines are a class of functions which #) are easy and quick to evaluate, @@ -440,9 +456,9 @@ through all the data points but is smoother than it would be if it had to. k=3 is the most common order of spline used in interpolation, and is often called a cubic spline. -------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Basic Usage -------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ At instantiation, the user passes in x, y, and possibly the spline order k (which defaults to 3). Calls are then made with the new_x array. :: @@ -465,9 +481,9 @@ In []: interp2.init_xy(x, y) ---------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Optional Arguments ---------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ At instantiation: @@ -490,27 +506,27 @@ to 0, so Spline usually returns the zeroth derivative of S, ie S. ------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Special Methods ------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The following special methods are also available, which are not wrapped by Interpolate1d. +The following special methods are also available, which are not wrapped by Interpolate1d : #. set_smoothing_factor(s = 0.0) #. get_knots -returns the positions of the knots of the spline + returns the positions of the knots of the spline #. get_coeffs -returns the coefficients of the + returns the coefficients of the #. get_residual -returns the weighted sum of the errors (due to smoothing) at the data points -sum((w[i]*( y[i]-s(x[i]) ))**2,axis=0) + returns the weighted sum of the errors (due to smoothing) at the data points + sum((w[i]*( y[i]-s(x[i]) ))**2,axis=0) #. integral(a, b) -returns the integral from a to b + returns the integral from a to b #. derivatives(x) -returns all the derivatives of the spline at point x + returns all the derivatives of the spline at point x #. roots -This only works for cubic splines. But it returns the places where the spline -is identically zero. + This only works for cubic splines. But it returns the places where the spline + is identically zero. ================================================ @@ -530,29 +546,68 @@ The Functional Interface ------------------------------------------ -The functional interface is virtually identical to that for interp1d: :: +The functional interface is completely analogous to that for interp1d: :: - new_z = interp2d(x, y, z, new_x, new_y) + newz = interp2d(x, y, z, newx, newy, kind='linear', out=NaN) -The range of interpolation is the rectangle given by the largest and -smallest values in x and y. -As in the case of 1D, string arguments can be passed -as keywords to specify particular types of interpolation. The keywords -in this case are kind (for in-range interpolation) and out (for out-of-bounds). +where x, y, z, are 1D arrays or lists, and newx and newy may be either arrays, lists or scalars. +If they are scalars or zero-dimensional arrays, newz will be a scalar as well. Otherwise +a vector is returned. The only differences from intper1d are -By default, out of bounds returns NaN, and in-bounds returns a linear -interpolation. +#. The known data points are specified by 3 arrays (x, y and z) rather than 2 (x and y). + z is the dependent variable, while x and y are independent variables. +#. Where to interpolate values is specified by two arrays, newx and newy, rather + than only one array. +#. The extrapolation keywords "low" and "high" are replaced by the single keyword "out" + for out-of-bounds. +#. Not all of the same keyword arguments are available for 1D and 2D. The main ones like + 'linear', 'cubic' and 'spline', however, work in both cases, and we try to give analogous + methods the same name. But some methods are particular to, or have only been written + for, one praticular dimensionality. -new_x and new_y may be either arrays, lists or scalars. If they are -scalars or zero-dimensional arrays, new_z will be a scalar as well. Otherwise -a vector is returned. +As in 1D, linear interpolation is used by default, while out of bounds returns NaN. +Here is an example session: :: + + In []: from interpolate import interp2d + In []: x, y = meshgrid( arange(10.), arange(10.) ) + In []: z = x*y + In []: x, y, z = map(ravel, [x, y, z] ) + # calling with scalars to get the value at a point + In []: interp2d(x, y, z, 5.5, 7.0) + Out []: 38.5 + # plotting a cross-section of the surface + In []: newx = arange(0, 5, .2) + In []: newy = arange(0, 5, .2) + In []: plot( interp2d(x, y, z, newx, newy )) + +.. image :: XY-crossection.png + +We can also use imshow to see the whole surface, though we must use +reshape to turn z back into a 2D array. :: + + In []: X, Y = meshgrid( arange(0,9,.2), arange(0,9,.2) ) + In []: Z = interp2d(x, y, z, ravel(X), ravel(Y)) + In []: len(Z) + Out []: 2025 + # sqrt(2025) = 45 + In []: imshow( reshape(Z, (45,45) ) ) + +.. image :: XY-surface.png + ------------------------------------------ The Objective Interface ------------------------------------------ -The objective interface for 2D is similarly analogous to 1D. +The objective interface for 2D is similarly analogous to 1D. The class is +instantiated with x, y, z, kind and out. It is called with newx and newy. :: + In []: interp_obj = Interpolate2d(x, y, z) + In []: newz = interp_obj(newx, newy) + + + + ------------------------------------------ The Spline2d Class ------------------------------------------ @@ -571,20 +626,18 @@ Beyond basic usage, Spline2 also has the methods #) get_grid(self, x, y) -x and y are treated as the coordinates of a grid, and all -points on the grid are interpolated and returned in an array. - -That is, if z = S.get_grid(x,y), z[i,j] is the interpolated value -at the point (xi, yj) - + x and y are treated as the coordinates of a grid, and all + points on the grid are interpolated and returned in an array. + That is, if z = S.get_grid(x,y), z[i,j] is the interpolated value + at the point (xi, yj) #) integral(xa, xb, ya, yb) -Integrate the interpolated function over the indicated rectangle - + Integrate the interpolated function over the indicated rectangle #) get_residual - + Same as Spline #) get_knots - + Same as Spline #) get_coeffs + Same as Spline Modified: branches/Interpolate1D/fitpack_wrapper2d.py =================================================================== --- branches/Interpolate1D/fitpack_wrapper2d.py 2008-08-04 19:48:18 UTC (rev 4599) +++ branches/Interpolate1D/fitpack_wrapper2d.py 2008-08-04 20:27:24 UTC (rev 4600) @@ -120,22 +120,26 @@ assigned the value of the nearest point that is within the interpolation range. """ + # FIXME : this function calls self.get_grid, which is extremely inefficient. However, + # I don't believe Fitpack really provides functionality to interpolate at scattered values. - if self._is_initialized is not True: + if self._is_initialized is False: raise Error, "x, y and z must be initialized before interpolating" # check input format - assert isinstance(x, np.ndarray) and isinstance(y, np.ndarray), \ + assert ( isinstance(x, np.ndarray) and isinstance(y, np.ndarray) ), \ "newx and newy must both be numpy arrays" assert len(x) == len(y), "newx and newy must be of the same length" # sort only once for efficiency - sorted_x = sorted(x) - sorted_y = sorted(y) + sorted_x = x.copy() + sorted_x.sort() + sorted_y = y.copy() + sorted_y.sort() data_grid = self.get_grid(sorted_x, sorted_y) - # fixme : no list comprehension + # FIXME : no list comprehension z = np.array([ data_grid[np.searchsorted(sorted_x, x[i]), np.searchsorted(sorted_y,y[i])] \ for i,xi in enumerate(x) ]) Modified: branches/Interpolate1D/interpolate2d.py =================================================================== --- branches/Interpolate1D/interpolate2d.py 2008-08-04 19:48:18 UTC (rev 4599) +++ branches/Interpolate1D/interpolate2d.py 2008-08-04 20:27:24 UTC (rev 4600) @@ -239,22 +239,23 @@ # make input into a nice 1d, contiguous array newx = atleast_1d_and_contiguous(newx, dtype=self._xdtype) + newy = atleast_1d_and_contiguous(newy, dtype=self._ydtype) assert newx.ndim == 1, "newx can be at most 1-dimensional" - newy = atleast_1d_and_contiguous(newy, dtype=self._ydtype) assert newy.ndim == 1, "newy can be at most 1-dimensional" assert len(newx) == len(newy), "newx and newy must be the same length" in_range_mask = (min(self._x) <= newx) & (newx <= max(self._x)) & \ (min(self._y) <= newy) & (newy <= max(self._y)) + # filling array of interpolated z-values result = np.zeros(np.shape(newx)) - if sum(in_range_mask) > 0: - # hack to deal with behavior of vectorize on arrays of length 0 + if sum(in_range_mask) > 0: # if there are in-range values. hack to deal + # with behavior of np.vectorize on arrays of length 0 result[in_range_mask] = self.kind(newx[in_range_mask], newy[in_range_mask]) if sum(~in_range_mask) > 0: - # hack to deal with behavior of vectorize on arrays of length 0 result[~in_range_mask] = self.out(newx[~in_range_mask], newy[~in_range_mask]) + # revert to scalar if applicable if input_is_scalar: result = result[0] From scipy-svn at scipy.org Tue Aug 5 15:07:54 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 5 Aug 2008 14:07:54 -0500 (CDT) Subject: [Scipy-svn] r4601 - in branches/Interpolate1D: . ndimage ndimage/register ndimage/segment tests Message-ID: <20080805190754.CC1DC39C1B5@scipy.org> Author: fcady Date: 2008-08-05 14:07:52 -0500 (Tue, 05 Aug 2008) New Revision: 4601 Added: branches/Interpolate1D/ndimage/ branches/Interpolate1D/ndimage/nd_image.c branches/Interpolate1D/ndimage/nd_image.h branches/Interpolate1D/ndimage/ni_filters.c branches/Interpolate1D/ndimage/ni_filters.h branches/Interpolate1D/ndimage/ni_fourier.c branches/Interpolate1D/ndimage/ni_fourier.h branches/Interpolate1D/ndimage/ni_interpolation.c branches/Interpolate1D/ndimage/ni_interpolation.h branches/Interpolate1D/ndimage/ni_measure.c branches/Interpolate1D/ndimage/ni_measure.h branches/Interpolate1D/ndimage/ni_morphology.c branches/Interpolate1D/ndimage/ni_morphology.h branches/Interpolate1D/ndimage/ni_support.c branches/Interpolate1D/ndimage/ni_support.h branches/Interpolate1D/ndimage/register/ branches/Interpolate1D/ndimage/register/Register_EXT.c branches/Interpolate1D/ndimage/register/Register_IMPL.c branches/Interpolate1D/ndimage/segment/ branches/Interpolate1D/ndimage/segment/Segmenter_EXT.c branches/Interpolate1D/ndimage/segment/Segmenter_IMPL.c branches/Interpolate1D/ndimage/segment/ndImage_Segmenter_structs.h branches/Interpolate1D/ndimage_wrapper.py branches/Interpolate1D/tests/test_ndimage.py Modified: branches/Interpolate1D/setup.py Log: more ND work, including unit tests. They're all failing right now, though, so I need to work on that. Added: branches/Interpolate1D/ndimage/nd_image.c =================================================================== --- branches/Interpolate1D/ndimage/nd_image.c 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/nd_image.c 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,1320 @@ +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define ND_IMPORT_ARRAY +#include "nd_image.h" +#undef ND_IMPORT_ARRAY +#include "ni_support.h" +#include "ni_filters.h" +#include "ni_fourier.h" +#include "ni_morphology.h" +#include "ni_interpolation.h" +#include "ni_measure.h" + +typedef struct { + PyObject *function; + PyObject *extra_arguments; + PyObject *extra_keywords; +} NI_PythonCallbackData; + +/* Convert an input array of any type, not necessarily contiguous */ +static int +NI_ObjectToInputArray(PyObject *object, PyArrayObject **array) +{ + *array = NA_InputArray(object, tAny, NPY_ALIGNED|NPY_NOTSWAPPED); + return *array ? 1 : 0; +} + +/* Convert an input array of any type, not necessarily contiguous */ +static int +NI_ObjectToOptionalInputArray(PyObject *object, PyArrayObject **array) +{ + if (object == Py_None) { + *array = NULL; + return 1; + } else { + *array = NA_InputArray(object, tAny, NPY_ALIGNED|NPY_NOTSWAPPED); + return *array ? 1 : 0; + } +} + +/* Convert an output array of any type, not necessarily contiguous */ +static int +NI_ObjectToOutputArray(PyObject *object, PyArrayObject **array) +{ + *array = NA_OutputArray(object, tAny, NPY_ALIGNED|NPY_NOTSWAPPED); + return *array ? 1 : 0; +} + +/* Convert an output array of any type, not necessarily contiguous */ +static int +NI_ObjectToOptionalOutputArray(PyObject *object, PyArrayObject **array) +{ + if (object == Py_None) { + *array = NULL; + return 1; + } else { + *array = NA_OutputArray(object, tAny, NPY_ALIGNED|NPY_NOTSWAPPED); + return *array ? 1 : 0; + } +} + +/* Convert an input/output array of any type, not necessarily contiguous */ +static int +NI_ObjectToIoArray(PyObject *object, PyArrayObject **array) +{ + *array = NA_IoArray(object, tAny, NPY_ALIGNED|NPY_NOTSWAPPED); + return *array ? 1 : 0; +} + +/* Convert an Long sequence */ +static maybelong +NI_ObjectToLongSequenceAndLength(PyObject *object, maybelong **sequence) +{ + long *pa, ii; + PyArrayObject *array = NA_InputArray(object, PyArray_LONG, NPY_CARRAY); + maybelong length = PyArray_SIZE(array); + + *sequence = (maybelong*)malloc(length * sizeof(maybelong)); + if (!*sequence) { + PyErr_NoMemory(); + Py_XDECREF(array); + return -1; + } + pa = (long*)PyArray_DATA(array); + for(ii = 0; ii < length; ii++) + (*sequence)[ii] = pa[ii]; + Py_XDECREF(array); + return length; +} + +static int +NI_ObjectToLongSequence(PyObject *object, maybelong **sequence) +{ + return NI_ObjectToLongSequenceAndLength(object, sequence) >= 0; +} + +/*********************************************************************/ +/* wrapper functions: */ +/*********************************************************************/ + +static PyObject *Py_Correlate1D(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *weights = NULL; + int axis, mode; + long origin; + double cval; + + if (!PyArg_ParseTuple(args, "O&O&iO&idl", NI_ObjectToInputArray, &input, + NI_ObjectToInputArray, &weights, &axis, + NI_ObjectToOutputArray, &output, &mode, &cval, &origin)) + goto exit; + if (!NI_Correlate1D(input, weights, axis, output, + (NI_ExtendMode)mode, cval, origin)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(weights); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_Correlate(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *weights = NULL; + maybelong *origin = NULL; + int mode; + double cval; + + if (!PyArg_ParseTuple(args, "O&O&O&idO&", NI_ObjectToInputArray, &input, + NI_ObjectToInputArray, &weights, NI_ObjectToOutputArray, &output, + &mode, &cval, NI_ObjectToLongSequence, &origin)) + goto exit; + if (!NI_Correlate(input, weights, output, (NI_ExtendMode)mode, cval, + origin)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(weights); + Py_XDECREF(output); + if (origin) + free(origin); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_UniformFilter1D(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL; + int axis, mode; + long filter_size, origin; + double cval; + + if (!PyArg_ParseTuple(args, "O&liO&idl", NI_ObjectToInputArray, &input, + &filter_size, &axis, NI_ObjectToOutputArray, &output, + &mode, &cval, &origin)) + goto exit; + if (!NI_UniformFilter1D(input, filter_size, axis, output, + (NI_ExtendMode)mode, cval, origin)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_MinOrMaxFilter1D(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL; + int axis, mode, minimum; + long filter_size, origin; + double cval; + + if (!PyArg_ParseTuple(args, "O&liO&idli", NI_ObjectToInputArray, &input, + &filter_size, &axis, NI_ObjectToOutputArray, &output, + &mode, &cval, &origin, &minimum)) + goto exit; + if (!NI_MinOrMaxFilter1D(input, filter_size, axis, output, + (NI_ExtendMode)mode, cval, origin, minimum)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_MinOrMaxFilter(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *footprint = NULL; + PyArrayObject *structure = NULL; + maybelong *origin = NULL; + int mode, minimum; + double cval; + + if (!PyArg_ParseTuple(args, "O&O&O&O&idO&i", NI_ObjectToInputArray, + &input, NI_ObjectToInputArray, &footprint, + NI_ObjectToOptionalInputArray, &structure, + NI_ObjectToOutputArray, &output, &mode, &cval, + NI_ObjectToLongSequence, &origin, &minimum)) + goto exit; + if (!NI_MinOrMaxFilter(input, footprint, structure, output, + (NI_ExtendMode)mode, cval, origin, minimum)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(footprint); + Py_XDECREF(structure); + Py_XDECREF(output); + if (origin) + free(origin); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_RankFilter(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *footprint = NULL; + maybelong *origin = NULL; + int mode, rank; + double cval; + + if (!PyArg_ParseTuple(args, "O&iO&O&idO&", NI_ObjectToInputArray, + &input, &rank, NI_ObjectToInputArray, &footprint, + NI_ObjectToOutputArray, &output, &mode, &cval, + NI_ObjectToLongSequence, &origin)) + goto exit; + if (!NI_RankFilter(input, rank, footprint, output, (NI_ExtendMode)mode, + cval, origin)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(footprint); + Py_XDECREF(output); + if (origin) + free(origin); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static int Py_Filter1DFunc(double *iline, maybelong ilen, + double *oline, maybelong olen, void *data) +{ + PyArrayObject *py_ibuffer = NULL, *py_obuffer = NULL; + PyObject *rv = NULL, *args = NULL, *tmp = NULL; + maybelong ii; + double *po = NULL; + NI_PythonCallbackData *cbdata = (NI_PythonCallbackData*)data; + + py_ibuffer = NA_NewArray(iline, PyArray_DOUBLE, 1, &ilen); + py_obuffer = NA_NewArray(NULL, PyArray_DOUBLE, 1, &olen); + if (!py_ibuffer || !py_obuffer) + goto exit; + tmp = Py_BuildValue("(OO)", py_ibuffer, py_obuffer); + if (!tmp) + goto exit; + args = PySequence_Concat(tmp, cbdata->extra_arguments); + if (!args) + goto exit; + rv = PyObject_Call(cbdata->function, args, cbdata->extra_keywords); + if (!rv) + goto exit; + po = (double*)PyArray_DATA(py_obuffer); + for(ii = 0; ii < olen; ii++) + oline[ii] = po[ii]; +exit: + Py_XDECREF(py_ibuffer); + Py_XDECREF(py_obuffer); + Py_XDECREF(rv); + Py_XDECREF(args); + Py_XDECREF(tmp); + return PyErr_Occurred() ? 0 : 1; +} + +static PyObject *Py_GenericFilter1D(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL; + PyObject *fnc = NULL, *extra_arguments = NULL, *extra_keywords = NULL; + void *func = Py_Filter1DFunc, *data = NULL; + NI_PythonCallbackData cbdata; + int axis, mode; + long origin, filter_size; + double cval; + + if (!PyArg_ParseTuple(args, "O&OliO&idlOO", NI_ObjectToInputArray, + &input, &fnc, &filter_size, &axis, NI_ObjectToOutputArray, + &output, &mode, &cval, &origin, &extra_arguments, &extra_keywords)) + goto exit; + if (!PyTuple_Check(extra_arguments)) { + PyErr_SetString(PyExc_RuntimeError, + "extra_arguments must be a tuple"); + goto exit; + } + if (!PyDict_Check(extra_keywords)) { + PyErr_SetString(PyExc_RuntimeError, + "extra_keywords must be a dictionary"); + goto exit; + } + if (PyCObject_Check(fnc)) { + func = PyCObject_AsVoidPtr(fnc); + data = PyCObject_GetDesc(fnc); + } else if (PyCallable_Check(fnc)) { + cbdata.function = fnc; + cbdata.extra_arguments = extra_arguments; + cbdata.extra_keywords = extra_keywords; + data = (void*)&cbdata; + } else { + PyErr_SetString(PyExc_RuntimeError, + "function parameter is not callable"); + goto exit; + } + if (!NI_GenericFilter1D(input, func, data, filter_size, axis, output, + (NI_ExtendMode)mode, cval, origin)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static int Py_FilterFunc(double *buffer, maybelong filter_size, + double *output, void *data) +{ + PyArrayObject *py_buffer = NULL; + PyObject *rv = NULL, *args = NULL, *tmp = NULL; + NI_PythonCallbackData *cbdata = (NI_PythonCallbackData*)data; + + py_buffer = NA_NewArray(buffer, PyArray_DOUBLE, 1, &filter_size); + if (!py_buffer) + goto exit; + tmp = Py_BuildValue("(O)", py_buffer); + if (!tmp) + goto exit; + args = PySequence_Concat(tmp, cbdata->extra_arguments); + if (!args) + goto exit; + rv = PyObject_Call(cbdata->function, args, cbdata->extra_keywords); + if (!rv) + goto exit; + *output = PyFloat_AsDouble(rv); +exit: + Py_XDECREF(py_buffer); + Py_XDECREF(rv); + Py_XDECREF(args); + Py_XDECREF(tmp); + return PyErr_Occurred() ? 0 : 1; +} + +static PyObject *Py_GenericFilter(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *footprint = NULL; + PyObject *fnc = NULL, *extra_arguments = NULL, *extra_keywords = NULL; + void *func = Py_FilterFunc, *data = NULL; + NI_PythonCallbackData cbdata; + int mode; + maybelong *origin = NULL; + double cval; + + if (!PyArg_ParseTuple(args, "O&OO&O&idO&OO", NI_ObjectToInputArray, + &input, &fnc, NI_ObjectToInputArray, &footprint, + NI_ObjectToOutputArray, &output, &mode, &cval, + NI_ObjectToLongSequence, &origin, + &extra_arguments, &extra_keywords)) + goto exit; + if (!PyTuple_Check(extra_arguments)) { + PyErr_SetString(PyExc_RuntimeError, + "extra_arguments must be a tuple"); + goto exit; + } + if (!PyDict_Check(extra_keywords)) { + PyErr_SetString(PyExc_RuntimeError, + "extra_keywords must be a dictionary"); + goto exit; + } + if (PyCObject_Check(fnc)) { + func = PyCObject_AsVoidPtr(fnc); + data = PyCObject_GetDesc(fnc); + } else if (PyCallable_Check(fnc)) { + cbdata.function = fnc; + cbdata.extra_arguments = extra_arguments; + cbdata.extra_keywords = extra_keywords; + data = (void*)&cbdata; + } else { + PyErr_SetString(PyExc_RuntimeError, + "function parameter is not callable"); + goto exit; + } + if (!NI_GenericFilter(input, func, data, footprint, output, + (NI_ExtendMode)mode, cval, origin)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(output); + Py_XDECREF(footprint); + if (origin) + free(origin); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_FourierFilter(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *parameters = NULL; + int axis, filter_type; + long n; + + if (!PyArg_ParseTuple(args, "O&O&liO&i", NI_ObjectToInputArray, &input, + NI_ObjectToInputArray, ¶meters, &n, &axis, + NI_ObjectToOutputArray, &output, &filter_type)) + goto exit; + + if (!NI_FourierFilter(input, parameters, n, axis, output, filter_type)) + goto exit; + +exit: + Py_XDECREF(input); + Py_XDECREF(parameters); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_FourierShift(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *shifts = NULL; + int axis; + long n; + + if (!PyArg_ParseTuple(args, "O&O&liO&", NI_ObjectToInputArray, &input, + NI_ObjectToInputArray, &shifts, &n, &axis, + NI_ObjectToOutputArray, &output)) + goto exit; + + if (!NI_FourierShift(input, shifts, n, axis, output)) + goto exit; + +exit: + Py_XDECREF(input); + Py_XDECREF(shifts); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_SplineFilter1D(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL; + int axis, order; + + if (!PyArg_ParseTuple(args, "O&iiO&", NI_ObjectToInputArray, &input, + &order, &axis, NI_ObjectToOutputArray, &output)) + goto exit; + + if (!NI_SplineFilter1D(input, order, axis, output)) + goto exit; + +exit: + Py_XDECREF(input); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static int Py_Map(maybelong *ocoor, double* icoor, int orank, int irank, + void *data) +{ + PyObject *coors = NULL, *rets = NULL, *args = NULL, *tmp = NULL; + maybelong ii; + NI_PythonCallbackData *cbdata = (NI_PythonCallbackData*)data; + + coors = PyTuple_New(orank); + if (!coors) + goto exit; + for(ii = 0; ii < orank; ii++) { + PyTuple_SetItem(coors, ii, PyInt_FromLong(ocoor[ii])); + if (PyErr_Occurred()) + goto exit; + } + tmp = Py_BuildValue("(O)", coors); + if (!tmp) + goto exit; + args = PySequence_Concat(tmp, cbdata->extra_arguments); + if (!args) + goto exit; + rets = PyObject_Call(cbdata->function, args, cbdata->extra_keywords); + if (!rets) + goto exit; + for(ii = 0; ii < irank; ii++) { + icoor[ii] = PyFloat_AsDouble(PyTuple_GetItem(rets, ii)); + if (PyErr_Occurred()) + goto exit; + } +exit: + Py_XDECREF(coors); + Py_XDECREF(tmp); + Py_XDECREF(rets); + Py_XDECREF(args); + return PyErr_Occurred() ? 0 : 1; +} + + +static PyObject *Py_GeometricTransform(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL; + PyArrayObject *coordinates = NULL, *matrix = NULL, *shift = NULL; + PyObject *fnc = NULL, *extra_arguments = NULL, *extra_keywords = NULL; + int mode, order; + double cval; + void *func = NULL, *data = NULL; + NI_PythonCallbackData cbdata; + + if (!PyArg_ParseTuple(args, "O&OO&O&O&O&iidOO", NI_ObjectToInputArray, + &input, &fnc, NI_ObjectToOptionalInputArray, + &coordinates, NI_ObjectToOptionalInputArray, + &matrix, NI_ObjectToOptionalInputArray, &shift, + NI_ObjectToOutputArray, &output, &order, &mode, + &cval, &extra_arguments, &extra_keywords)) + goto exit; + + if (fnc != Py_None) { + if (!PyTuple_Check(extra_arguments)) { + PyErr_SetString(PyExc_RuntimeError, + "extra_arguments must be a tuple"); + goto exit; + } + if (!PyDict_Check(extra_keywords)) { + PyErr_SetString(PyExc_RuntimeError, + "extra_keywords must be a dictionary"); + goto exit; + } + if (PyCObject_Check(fnc)) { + func = PyCObject_AsVoidPtr(fnc); + data = PyCObject_GetDesc(fnc); + } else if (PyCallable_Check(fnc)) { + func = Py_Map; + cbdata.function = fnc; + cbdata.extra_arguments = extra_arguments; + cbdata.extra_keywords = extra_keywords; + data = (void*)&cbdata; + } else { + PyErr_SetString(PyExc_RuntimeError, + "function parameter is not callable"); + goto exit; + } + } + + if (!NI_GeometricTransform(input, func, data, matrix, shift, coordinates, + output, order, (NI_ExtendMode)mode, cval)) + goto exit; + +exit: + Py_XDECREF(input); + Py_XDECREF(output); + Py_XDECREF(coordinates); + Py_XDECREF(matrix); + Py_XDECREF(shift); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_ZoomShift(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *shift = NULL; + PyArrayObject *zoom = NULL; + int mode, order; + double cval; + + if (!PyArg_ParseTuple(args, "O&O&O&O&iid", NI_ObjectToInputArray, + &input, NI_ObjectToOptionalInputArray, &zoom, + NI_ObjectToOptionalInputArray, &shift, NI_ObjectToOutputArray, + &output, &order, &mode, &cval)) + goto exit; + + if (!NI_ZoomShift(input, zoom, shift, output, order, (NI_ExtendMode)mode, + cval)) + goto exit; + +exit: + Py_XDECREF(input); + Py_XDECREF(shift); + Py_XDECREF(zoom); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_Label(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *strct = NULL; + maybelong max_label; + + if (!PyArg_ParseTuple(args, "O&O&O&", NI_ObjectToInputArray, &input, + NI_ObjectToInputArray, &strct, NI_ObjectToOutputArray, &output)) + goto exit; + + if (!NI_Label(input, strct, &max_label, output)) + goto exit; + +exit: + Py_XDECREF(input); + Py_XDECREF(strct); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue("l", (long)max_label); +} + +static PyObject *Py_FindObjects(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL; + PyObject *result = NULL, *tuple = NULL, *start = NULL, *end = NULL; + PyObject *slc = NULL; + int jj; + long max_label; + maybelong ii, *regions = NULL; + + if (!PyArg_ParseTuple(args, "O&l", NI_ObjectToInputArray, &input, + &max_label)) + goto exit; + + if (max_label < 0) + max_label = 0; + if (max_label > 0) { + if (input->nd > 0) { + regions = (maybelong*)malloc(2 * max_label * input->nd * + sizeof(maybelong)); + } else { + regions = (maybelong*)malloc(max_label * sizeof(maybelong)); + } + if (!regions) { + PyErr_NoMemory(); + goto exit; + } + } + + if (!NI_FindObjects(input, max_label, regions)) + goto exit; + + result = PyList_New(max_label); + if (!result) { + PyErr_NoMemory(); + goto exit; + } + + for(ii = 0; ii < max_label; ii++) { + maybelong idx = input->nd > 0 ? 2 * input->nd * ii : ii; + if (regions[idx] >= 0) { + PyObject *tuple = PyTuple_New(input->nd); + if (!tuple) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < input->nd; jj++) { + start = PyInt_FromLong(regions[idx + jj]); + end = PyInt_FromLong(regions[idx + jj + input->nd]); + if (!start || !end) { + PyErr_NoMemory(); + goto exit; + } + slc = PySlice_New(start, end, NULL); + if (!slc) { + PyErr_NoMemory(); + goto exit; + } + Py_XDECREF(start); + Py_XDECREF(end); + start = end = NULL; + PyTuple_SetItem(tuple, jj, slc); + slc = NULL; + } + PyList_SetItem(result, ii, tuple); + tuple = NULL; + } else { + Py_INCREF(Py_None); + PyList_SetItem(result, ii, Py_None); + } + } + + Py_INCREF(result); + + exit: + Py_XDECREF(input); + Py_XDECREF(result); + Py_XDECREF(tuple); + Py_XDECREF(start); + Py_XDECREF(end); + Py_XDECREF(slc); + if (regions) + free(regions); + if (PyErr_Occurred()) { + Py_XDECREF(result); + return NULL; + } else { + return result; + } +} + +static PyObject *Py_WatershedIFT(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *markers = NULL; + PyArrayObject *strct = NULL; + + if (!PyArg_ParseTuple(args, "O&O&O&O&", NI_ObjectToInputArray, &input, + NI_ObjectToInputArray, &markers, NI_ObjectToInputArray, + &strct, NI_ObjectToOutputArray, &output)) + goto exit; + + if (!NI_WatershedIFT(input, markers, strct, output)) + goto exit; + +exit: + Py_XDECREF(input); + Py_XDECREF(markers); + Py_XDECREF(strct); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static int _NI_GetIndices(PyObject* indices_object, + maybelong** result_indices, maybelong* min_label, + maybelong* max_label, maybelong* n_results) +{ + maybelong *indices = NULL, n_indices, ii; + + if (indices_object == Py_None) { + *min_label = -1; + *n_results = 1; + } else { + n_indices = NI_ObjectToLongSequenceAndLength(indices_object, &indices); + if (n_indices < 0) + goto exit; + if (n_indices < 1) { + PyErr_SetString(PyExc_RuntimeError, "no correct indices provided"); + goto exit; + } else { + *min_label = *max_label = indices[0]; + if (*min_label < 0) { + PyErr_SetString(PyExc_RuntimeError, + "negative indices not allowed"); + goto exit; + } + for(ii = 1; ii < n_indices; ii++) { + if (indices[ii] < 0) { + PyErr_SetString(PyExc_RuntimeError, + "negative indices not allowed"); + goto exit; + } + if (indices[ii] < *min_label) + *min_label = indices[ii]; + if (indices[ii] > *max_label) + *max_label = indices[ii]; + } + *result_indices = (maybelong*)malloc((*max_label - *min_label + 1) * + sizeof(maybelong)); + if (!*result_indices) { + PyErr_NoMemory(); + goto exit; + } + for(ii = 0; ii < *max_label - *min_label + 1; ii++) + (*result_indices)[ii] = -1; + *n_results = 0; + for(ii = 0; ii < n_indices; ii++) { + if ((*result_indices)[indices[ii] - *min_label] >= 0) { + PyErr_SetString(PyExc_RuntimeError, "duplicate index"); + goto exit; + } + (*result_indices)[indices[ii] - *min_label] = ii; + ++(*n_results); + } + } + } + exit: + if (indices) + free(indices); + return PyErr_Occurred() == NULL; +} + + +PyObject* _NI_BuildMeasurementResultArrayObject(maybelong n_results, + PyArrayObject** values) +{ + PyObject *result = NULL; + if (n_results > 1) { + result = PyList_New(n_results); + if (result) { + maybelong ii; + for(ii = 0; ii < n_results; ii++) { + PyList_SET_ITEM(result, ii, (PyObject*)values[ii]); + Py_XINCREF(values[ii]); + } + } + } else { + result = (PyObject*)values[0]; + Py_XINCREF(values[0]); + } + return result; +} + + +PyObject* _NI_BuildMeasurementResultDouble(maybelong n_results, + double* values) +{ + PyObject *result = NULL; + if (n_results > 1) { + result = PyList_New(n_results); + if (result) { + int ii; + for(ii = 0; ii < n_results; ii++) { + PyObject* val = PyFloat_FromDouble(values[ii]); + if (!val) { + Py_XDECREF(result); + return NULL; + } + PyList_SET_ITEM(result, ii, val); + } + } + } else { + result = Py_BuildValue("d", values[0]); + } + return result; +} + + +PyObject* _NI_BuildMeasurementResultDoubleTuple(maybelong n_results, + int tuple_size, double* values) +{ + PyObject *result = NULL; + maybelong ii; + int jj; + + if (n_results > 1) { + result = PyList_New(n_results); + if (result) { + for(ii = 0; ii < n_results; ii++) { + PyObject* val = PyTuple_New(tuple_size); + if (!val) { + Py_XDECREF(result); + return NULL; + } + for(jj = 0; jj < tuple_size; jj++) { + maybelong idx = jj + ii * tuple_size; + PyTuple_SetItem(val, jj, PyFloat_FromDouble(values[idx])); + if (PyErr_Occurred()) { + Py_XDECREF(result); + return NULL; + } + } + PyList_SET_ITEM(result, ii, val); + } + } + } else { + result = PyTuple_New(tuple_size); + if (result) { + for(ii = 0; ii < tuple_size; ii++) { + PyTuple_SetItem(result, ii, PyFloat_FromDouble(values[ii])); + if (PyErr_Occurred()) { + Py_XDECREF(result); + return NULL; + } + } + } + } + return result; +} + + +PyObject* _NI_BuildMeasurementResultInt(maybelong n_results, + maybelong* values) +{ + PyObject *result = NULL; + if (n_results > 1) { + result = PyList_New(n_results); + if (result) { + maybelong ii; + for(ii = 0; ii < n_results; ii++) { + PyObject* val = PyInt_FromLong(values[ii]); + if (!val) { + Py_XDECREF(result); + return NULL; + } + PyList_SET_ITEM(result, ii, val); + } + } + } else { + result = Py_BuildValue("l", values[0]); + } + return result; +} + + +static PyObject *Py_Statistics(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *labels = NULL; + PyObject *indices_object, *result = NULL; + PyObject *res1 = NULL, *res2 = NULL, *res3 = NULL, *res4 = NULL; + double *dresult1 = NULL, *dresult2 = NULL; + maybelong *lresult1 = NULL, *lresult2 = NULL; + maybelong min_label, max_label, *result_indices = NULL, n_results, ii; + int type; + + if (!PyArg_ParseTuple(args, "O&O&Oi", NI_ObjectToInputArray, &input, + NI_ObjectToOptionalInputArray, &labels, &indices_object, &type)) + goto exit; + + if (!_NI_GetIndices(indices_object, &result_indices, &min_label, + &max_label, &n_results)) + goto exit; + + if (type >= 0 && type <= 7) { + dresult1 = (double*)malloc(n_results * sizeof(double)); + if (!dresult1) { + PyErr_NoMemory(); + goto exit; + } + } + if (type == 2 || type == 7) { + dresult2 = (double*)malloc(n_results * sizeof(double)); + if (!dresult2) { + PyErr_NoMemory(); + goto exit; + } + } + if (type == 1 || type == 2 || (type >= 5 && type <= 7)) { + lresult1 = (maybelong*)malloc(n_results * sizeof(maybelong)); + if (!lresult1) { + PyErr_NoMemory(); + goto exit; + } + } + if (type == 7) { + lresult2 = (maybelong*)malloc(n_results * sizeof(maybelong)); + if (!lresult2) { + PyErr_NoMemory(); + goto exit; + } + } + switch(type) { + case 0: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, dresult1, NULL, NULL, NULL, NULL, NULL, NULL)) + goto exit; + result = _NI_BuildMeasurementResultDouble(n_results, dresult1); + break; + case 1: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, dresult1, lresult1, NULL, NULL, NULL, NULL, NULL)) + goto exit; + for(ii = 0; ii < n_results; ii++) + dresult1[ii] = lresult1[ii] > 0 ? dresult1[ii] / lresult1[ii] : 0.0; + + result = _NI_BuildMeasurementResultDouble(n_results, dresult1); + break; + case 2: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, dresult1, lresult1, dresult2, NULL, NULL, NULL, NULL)) + goto exit; + result = _NI_BuildMeasurementResultDouble(n_results, dresult2); + break; + case 3: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, NULL, NULL, NULL, dresult1, NULL, NULL, NULL)) + goto exit; + result = _NI_BuildMeasurementResultDouble(n_results, dresult1); + break; + case 4: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, NULL, NULL, NULL, NULL, dresult1, NULL, NULL)) + goto exit; + result = _NI_BuildMeasurementResultDouble(n_results, dresult1); + break; + case 5: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, NULL, NULL, NULL, dresult1, NULL, lresult1, NULL)) + goto exit; + result = _NI_BuildMeasurementResultInt(n_results, lresult1); + break; + case 6: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, NULL, NULL, NULL, NULL, dresult1, NULL, lresult1)) + goto exit; + result = _NI_BuildMeasurementResultInt(n_results, lresult1); + break; + case 7: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, NULL, NULL, NULL, dresult1, dresult2, + lresult1, lresult2)) + goto exit; + res1 = _NI_BuildMeasurementResultDouble(n_results, dresult1); + res2 = _NI_BuildMeasurementResultDouble(n_results, dresult2); + res3 = _NI_BuildMeasurementResultInt(n_results, lresult1); + res4 = _NI_BuildMeasurementResultInt(n_results, lresult2); + if (!res1 || !res2 || !res3 || !res4) + goto exit; + result = Py_BuildValue("OOOO", res1, res2, res3, res4); + break; + default: + PyErr_SetString(PyExc_RuntimeError, "operation not supported"); + goto exit; + } + + exit: + Py_XDECREF(input); + Py_XDECREF(labels); + if (result_indices) + free(result_indices); + if (dresult1) + free(dresult1); + if (dresult2) + free(dresult2); + if (lresult1) + free(lresult1); + if (lresult2) + free(lresult2); + return result; +} + + +static PyObject *Py_CenterOfMass(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *labels = NULL; + PyObject *indices_object, *result = NULL; + double *center_of_mass = NULL; + maybelong min_label, max_label, *result_indices = NULL, n_results; + + if (!PyArg_ParseTuple(args, "O&O&O", NI_ObjectToInputArray, &input, + NI_ObjectToOptionalInputArray, &labels, &indices_object)) + goto exit; + + if (!_NI_GetIndices(indices_object, &result_indices, &min_label, + &max_label, &n_results)) + goto exit; + + center_of_mass = (double*)malloc(input->nd * n_results * + sizeof(double)); + if (!center_of_mass) { + PyErr_NoMemory(); + goto exit; + } + + if (!NI_CenterOfMass(input, labels, min_label, max_label, + result_indices, n_results, center_of_mass)) + goto exit; + + result = _NI_BuildMeasurementResultDoubleTuple(n_results, input->nd, + center_of_mass); + + exit: + Py_XDECREF(input); + Py_XDECREF(labels); + if (result_indices) + free(result_indices); + if (center_of_mass) + free(center_of_mass); + return result; +} + +static PyObject *Py_Histogram(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *labels = NULL, **histograms = NULL; + PyObject *indices_object, *result = NULL; + maybelong min_label, max_label, *result_indices = NULL, n_results; + maybelong jj, nbins; + long nbins_in; + double min, max; + + if (!PyArg_ParseTuple(args, "O&ddlO&O", NI_ObjectToInputArray, &input, + &min, &max, &nbins_in, NI_ObjectToOptionalInputArray, + &labels, &indices_object)) + goto exit; + nbins = nbins_in; + + if (!_NI_GetIndices(indices_object, &result_indices, &min_label, + &max_label, &n_results)) + goto exit; + + /* Set all pointers to NULL, so that freeing the memory */ + /* doesn't cause problems. */ + histograms = (PyArrayObject**)calloc(input->nd * n_results, + sizeof(PyArrayObject*)); + if (!histograms) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < n_results; jj++) { + histograms[jj] = NA_NewArray(NULL, tInt32, 1, &nbins); + if (!histograms[jj]) { + PyErr_NoMemory(); + goto exit; + } + } + + if (!NI_Histogram(input, labels, min_label, max_label, result_indices, + n_results, histograms, min, max, nbins)) + goto exit; + + result = _NI_BuildMeasurementResultArrayObject(n_results, histograms); + + exit: + Py_XDECREF(input); + Py_XDECREF(labels); + if (result_indices) + free(result_indices); + if (histograms) { + for(jj = 0; jj < n_results; jj++) { + Py_XDECREF(histograms[jj]); + } + free(histograms); + } + return result; +} + +static PyObject *Py_DistanceTransformBruteForce(PyObject *obj, + PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *features = NULL; + PyArrayObject *sampling = NULL; + int metric; + + if (!PyArg_ParseTuple(args, "O&iO&O&O&", NI_ObjectToInputArray, &input, + &metric, NI_ObjectToOptionalInputArray, &sampling, + NI_ObjectToOptionalOutputArray, &output, + NI_ObjectToOptionalOutputArray, &features)) + goto exit; + if (!NI_DistanceTransformBruteForce(input, metric, sampling, + output, features)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(sampling); + Py_XDECREF(output); + Py_XDECREF(features); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_DistanceTransformOnePass(PyObject *obj, PyObject *args) +{ + PyArrayObject *strct = NULL, *distances = NULL, *features = NULL; + + if (!PyArg_ParseTuple(args, "O&O&O&", NI_ObjectToInputArray, &strct, + NI_ObjectToIoArray, &distances, + NI_ObjectToOptionalOutputArray, &features)) + goto exit; + if (!NI_DistanceTransformOnePass(strct, distances, features)) + goto exit; +exit: + Py_XDECREF(strct); + Py_XDECREF(distances); + Py_XDECREF(features); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_EuclideanFeatureTransform(PyObject *obj, + PyObject *args) +{ + PyArrayObject *input = NULL, *features = NULL, *sampling = NULL; + + if (!PyArg_ParseTuple(args, "O&O&O&", NI_ObjectToInputArray, &input, + NI_ObjectToOptionalInputArray, &sampling, + NI_ObjectToOutputArray, &features)) + goto exit; + if (!NI_EuclideanFeatureTransform(input, sampling, features)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(sampling); + Py_XDECREF(features); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static void _FreeCoordinateList(void* ptr) +{ + NI_FreeCoordinateList((NI_CoordinateList*)ptr); +} + +static PyObject *Py_BinaryErosion(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *strct = NULL; + PyArrayObject *mask = NULL; + PyObject *cobj = NULL; + int border_value, invert, center_is_true; + int changed = 0, return_coordinates; + NI_CoordinateList *coordinate_list = NULL; + maybelong *origins = NULL; + + if (!PyArg_ParseTuple(args, "O&O&O&O&iO&iii", NI_ObjectToInputArray, + &input, NI_ObjectToInputArray, &strct, + NI_ObjectToOptionalInputArray, &mask, + NI_ObjectToOutputArray, &output, &border_value, + NI_ObjectToLongSequence, &origins, &invert, + ¢er_is_true, &return_coordinates)) + goto exit; + if (!NI_BinaryErosion(input, strct, mask, output, border_value, + origins, invert, center_is_true, &changed, + return_coordinates ? &coordinate_list : NULL)) + goto exit; + if (return_coordinates) { + cobj = PyCObject_FromVoidPtr(coordinate_list, _FreeCoordinateList); + } +exit: + Py_XDECREF(input); + Py_XDECREF(strct); + Py_XDECREF(mask); + Py_XDECREF(output); + if (origins) + free(origins); + if (PyErr_Occurred()) { + Py_XDECREF(cobj); + return NULL; + } else { + if (return_coordinates) { + return Py_BuildValue("iN", changed, cobj); + } else { + return Py_BuildValue("i", changed); + } + } +} + +static PyObject *Py_BinaryErosion2(PyObject *obj, PyObject *args) +{ + PyArrayObject *array = NULL, *strct = NULL, *mask = NULL; + PyObject *cobj = NULL; + int invert, niter; + maybelong *origins = NULL; + + if (!PyArg_ParseTuple(args, "O&O&O&iO&iO", NI_ObjectToIoArray, &array, + NI_ObjectToInputArray, &strct, NI_ObjectToOptionalInputArray, + &mask, &niter, NI_ObjectToLongSequence, &origins, &invert, + &cobj)) + goto exit; + + if (PyCObject_Check(cobj)) { + NI_CoordinateList *cobj_data = PyCObject_AsVoidPtr(cobj); + if (!NI_BinaryErosion2(array, strct, mask, niter, origins, invert, + &cobj_data)) + goto exit; + } else { + PyErr_SetString(PyExc_RuntimeError, "cannot convert CObject"); + goto exit; + } +exit: + Py_XDECREF(array); + Py_XDECREF(strct); + Py_XDECREF(mask); + if (origins) free(origins); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyMethodDef methods[] = { + {"correlate1d", (PyCFunction)Py_Correlate1D, + METH_VARARGS, NULL}, + {"correlate", (PyCFunction)Py_Correlate, + METH_VARARGS, NULL}, + {"uniform_filter1d", (PyCFunction)Py_UniformFilter1D, + METH_VARARGS, NULL}, + {"min_or_max_filter1d", (PyCFunction)Py_MinOrMaxFilter1D, + METH_VARARGS, NULL}, + {"min_or_max_filter", (PyCFunction)Py_MinOrMaxFilter, + METH_VARARGS, NULL}, + {"rank_filter", (PyCFunction)Py_RankFilter, + METH_VARARGS, NULL}, + {"generic_filter", (PyCFunction)Py_GenericFilter, + METH_VARARGS, NULL}, + {"generic_filter1d", (PyCFunction)Py_GenericFilter1D, + METH_VARARGS, NULL}, + {"fourier_filter", (PyCFunction)Py_FourierFilter, + METH_VARARGS, NULL}, + {"fourier_shift", (PyCFunction)Py_FourierShift, + METH_VARARGS, NULL}, + {"spline_filter1d", (PyCFunction)Py_SplineFilter1D, + METH_VARARGS, NULL}, + {"geometric_transform", (PyCFunction)Py_GeometricTransform, + METH_VARARGS, NULL}, + {"zoom_shift", (PyCFunction)Py_ZoomShift, + METH_VARARGS, NULL}, + {"label", (PyCFunction)Py_Label, + METH_VARARGS, NULL}, + {"find_objects", (PyCFunction)Py_FindObjects, + METH_VARARGS, NULL}, + {"watershed_ift", (PyCFunction)Py_WatershedIFT, + METH_VARARGS, NULL}, + {"statistics", (PyCFunction)Py_Statistics, + METH_VARARGS, NULL}, + {"center_of_mass", (PyCFunction)Py_CenterOfMass, + METH_VARARGS, NULL}, + {"histogram", (PyCFunction)Py_Histogram, + METH_VARARGS, NULL}, + {"distance_transform_bf", (PyCFunction)Py_DistanceTransformBruteForce, + METH_VARARGS, NULL}, + {"distance_transform_op", (PyCFunction)Py_DistanceTransformOnePass, + METH_VARARGS, NULL}, + {"euclidean_feature_transform", + (PyCFunction)Py_EuclideanFeatureTransform, + METH_VARARGS, NULL}, + {"binary_erosion", (PyCFunction)Py_BinaryErosion, + METH_VARARGS, NULL}, + {"binary_erosion2", (PyCFunction)Py_BinaryErosion2, + METH_VARARGS, NULL}, + {NULL, NULL, 0, NULL} +}; + +PyMODINIT_FUNC init_nd_image(void) +{ + Py_InitModule("_nd_image", methods); + import_array(); +} Added: branches/Interpolate1D/ndimage/nd_image.h =================================================================== --- branches/Interpolate1D/ndimage/nd_image.h 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/nd_image.h 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,278 @@ +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ND_IMAGE_H +#define ND_IMAGE_H + +#include "Python.h" + +#ifndef ND_IMPORT_ARRAY +#define NO_IMPORT_ARRAY +#endif + +#include +#undef NO_IMPORT_ARRAY + +/* Eventually get rid of everything below this line */ + +typedef enum +{ + tAny=-1, + tBool=PyArray_BOOL, + tInt8=PyArray_INT8, + tUInt8=PyArray_UINT8, + tInt16=PyArray_INT16, + tUInt16=PyArray_UINT16, + tInt32=PyArray_INT32, + tUInt32=PyArray_UINT32, + tInt64=PyArray_INT64, + tUInt64=PyArray_UINT64, + tFloat32=PyArray_FLOAT32, + tFloat64=PyArray_FLOAT64, + tComplex64=PyArray_COMPLEX64, + tComplex128=PyArray_COMPLEX128, + tObject=PyArray_OBJECT, /* placeholder... does nothing */ + tMaxType=PyArray_NTYPES, + tDefault=PyArray_FLOAT64, + tLong=PyArray_LONG, +} NumarrayType; + +#define NI_MAXDIM NPY_MAXDIMS + +typedef npy_intp maybelong; +#define MAXDIM NPY_MAXDIMS + +#define HAS_UINT64 1 + + + +#ifdef ND_IMPORT_ARRAY + +/* Numarray Helper Functions */ + +static PyArrayObject* +NA_InputArray(PyObject *a, NumarrayType t, int requires) +{ + PyArray_Descr *descr; + if (t == tAny) descr = NULL; + else descr = PyArray_DescrFromType(t); + return (PyArrayObject *) \ + PyArray_CheckFromAny(a, descr, 0, 0, requires, NULL); +} + +/* satisfies ensures that 'a' meets a set of requirements and matches +the specified type. +*/ +static int +satisfies(PyArrayObject *a, int requirements, NumarrayType t) +{ + int type_ok = (a->descr->type_num == t) || (t == tAny); + + if (PyArray_ISCARRAY(a)) + return type_ok; + if (PyArray_ISBYTESWAPPED(a) && (requirements & NPY_NOTSWAPPED)) + return 0; + if (!PyArray_ISALIGNED(a) && (requirements & NPY_ALIGNED)) + return 0; + if (!PyArray_ISCONTIGUOUS(a) && (requirements & NPY_CONTIGUOUS)) + return 0; + if (!PyArray_ISWRITEABLE(a) && (requirements & NPY_WRITEABLE)) + return 0; + if (requirements & NPY_ENSURECOPY) + return 0; + return type_ok; +} + +static PyArrayObject * +NA_OutputArray(PyObject *a, NumarrayType t, int requires) +{ + PyArray_Descr *dtype; + PyArrayObject *ret; + + if (!PyArray_Check(a) || !PyArray_ISWRITEABLE(a)) { + PyErr_Format(PyExc_TypeError, + "NA_OutputArray: only writeable arrays work for output."); + return NULL; + } + + if (satisfies((PyArrayObject *)a, requires, t)) { + Py_INCREF(a); + return (PyArrayObject *)a; + } + if (t == tAny) { + dtype = PyArray_DESCR(a); + Py_INCREF(dtype); + } + else { + dtype = PyArray_DescrFromType(t); + } + ret = (PyArrayObject *)PyArray_Empty(PyArray_NDIM(a), PyArray_DIMS(a), + dtype, 0); + ret->flags |= NPY_UPDATEIFCOPY; + ret->base = a; + PyArray_FLAGS(a) &= ~NPY_WRITEABLE; + Py_INCREF(a); + return ret; +} + +/* NA_IoArray is a combination of NA_InputArray and NA_OutputArray. + +Unlike NA_OutputArray, if a temporary is required it is initialized to a copy +of the input array. + +Unlike NA_InputArray, deallocating any resulting temporary array results in a +copy from the temporary back to the original. +*/ +static PyArrayObject * +NA_IoArray(PyObject *a, NumarrayType t, int requires) +{ + PyArrayObject *shadow = NA_InputArray(a, t, requires | NPY_UPDATEIFCOPY ); + + if (!shadow) return NULL; + + /* Guard against non-writable, but otherwise satisfying requires. + In this case, shadow == a. + */ + if (!PyArray_ISWRITEABLE(shadow)) { + PyErr_Format(PyExc_TypeError, + "NA_IoArray: I/O array must be writable array"); + PyArray_XDECREF_ERR(shadow); + return NULL; + } + + return shadow; +} + +#define NUM_LITTLE_ENDIAN 0 +#define NUM_BIG_ENDIAN 1 + +static int +NA_ByteOrder(void) +{ + unsigned long byteorder_test; + byteorder_test = 1; + if (*((char *) &byteorder_test)) + return NUM_LITTLE_ENDIAN; + else + return NUM_BIG_ENDIAN; +} + +/* ignores bytestride */ +static PyArrayObject * +NA_NewAllFromBuffer(int ndim, maybelong *shape, NumarrayType type, + PyObject *bufferObject, maybelong byteoffset, maybelong bytestride, + int byteorder, int aligned, int writeable) +{ + PyArrayObject *self = NULL; + PyArray_Descr *dtype; + + if (type == tAny) + type = tDefault; + + dtype = PyArray_DescrFromType(type); + if (dtype == NULL) return NULL; + + if (byteorder != NA_ByteOrder()) { + PyArray_Descr *temp; + temp = PyArray_DescrNewByteorder(dtype, PyArray_SWAP); + Py_DECREF(dtype); + if (temp == NULL) return NULL; + dtype = temp; + } + + if (bufferObject == Py_None || bufferObject == NULL) { + self = (PyArrayObject *) \ + PyArray_NewFromDescr(&PyArray_Type, dtype, + ndim, shape, NULL, NULL, + 0, NULL); + } + else { + npy_intp size = 1; + int i; + PyArrayObject *newself; + PyArray_Dims newdims; + for(i=0; idata, buffer, PyArray_NBYTES(result)); + } else { + memset(result->data, 0, PyArray_NBYTES(result)); + } + } + } + return result; +} + +/* Create a new numarray which is initially a C_array, or which +references a C_array: aligned, !byteswapped, contiguous, ... +Call with buffer==NULL to allocate storage. +*/ +static PyArrayObject * +NA_NewArray(void *buffer, NumarrayType type, int ndim, maybelong *shape) +{ + return (PyArrayObject *) NA_NewAll(ndim, shape, type, buffer, 0, 0, + NA_ByteOrder(), 1, 1); +} + +#endif /* ND_IMPORT_ARRAY */ + +#endif /* ND_IMAGE_H */ Added: branches/Interpolate1D/ndimage/ni_filters.c =================================================================== --- branches/Interpolate1D/ndimage/ni_filters.c 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/ni_filters.c 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,888 @@ +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ni_support.h" +#include "ni_filters.h" +#include +#include + +#define BUFFER_SIZE 256000 + +int NI_Correlate1D(PyArrayObject *input, PyArrayObject *weights, + int axis, PyArrayObject *output, NI_ExtendMode mode, + double cval, maybelong origin) +{ + int symmetric = 0, ii, jj, more; + maybelong ll, lines, length, size1, size2, filter_size; + double *ibuffer = NULL, *obuffer = NULL; + Float64 *fw; + NI_LineBuffer iline_buffer, oline_buffer; + + /* test for symmetry or anti-symmetry: */ + filter_size = weights->dimensions[0]; + size1 = filter_size / 2; + size2 = filter_size - size1 - 1; + fw = (void *)PyArray_DATA(weights); + if (filter_size & 0x1) { + symmetric = 1; + for(ii = 1; ii <= filter_size / 2; ii++) { + if (fabs(fw[ii + size1] - fw[size1 - ii]) > DBL_EPSILON) { + symmetric = 0; + break; + } + } + if (symmetric == 0) { + symmetric = -1; + for(ii = 1; ii <= filter_size / 2; ii++) { + if (fabs(fw[size1 + ii] + fw[size1 - ii]) > DBL_EPSILON) { + symmetric = 0; + break; + } + } + } + } + /* allocate and initialize the line buffers: */ + lines = -1; + if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, + &lines, BUFFER_SIZE, &ibuffer)) + goto exit; + if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, + &obuffer)) + goto exit; + if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, + lines, ibuffer, mode, cval, &iline_buffer)) + goto exit; + if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, + &oline_buffer)) + goto exit; + length = input->nd > 0 ? input->dimensions[axis] : 1; + fw += size1; + /* iterate over all the array lines: */ + do { + /* copy lines from array to buffer: */ + if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) + goto exit; + /* iterate over the lines in the buffers: */ + for(ii = 0; ii < lines; ii++) { + /* get lines: */ + double *iline = NI_GET_LINE(iline_buffer, ii) + size1; + double *oline = NI_GET_LINE(oline_buffer, ii); + /* the correlation calculation: */ + if (symmetric > 0) { + for(ll = 0; ll < length; ll++) { + oline[ll] = iline[0] * fw[0]; + for(jj = -size1 ; jj < 0; jj++) + oline[ll] += (iline[jj] + iline[-jj]) * fw[jj]; + ++iline; + } + } else if (symmetric < 0) { + for(ll = 0; ll < length; ll++) { + oline[ll] = iline[0] * fw[0]; + for(jj = -size1 ; jj < 0; jj++) + oline[ll] += (iline[jj] - iline[-jj]) * fw[jj]; + ++iline; + } + } else { + for(ll = 0; ll < length; ll++) { + oline[ll] = iline[size2] * fw[size2]; + for(jj = -size1; jj < size2; jj++) + oline[ll] += iline[jj] * fw[jj]; + ++iline; + } + } + } + /* copy lines from buffer to array: */ + if (!NI_LineBufferToArray(&oline_buffer)) + goto exit; + } while(more); +exit: + if (ibuffer) free(ibuffer); + if (obuffer) free(obuffer); + return PyErr_Occurred() ? 0 : 1; +} + +#define CASE_CORRELATE_POINT(_pi, _weights, _offsets, _filter_size, \ + _cvalue, _type, _res, _mv) \ +case t ## _type: \ +{ \ + maybelong _ii, _offset; \ + for(_ii = 0; _ii < _filter_size; _ii++) { \ + _offset = _offsets[_ii]; \ + if (_offset == _mv) \ + _res += _weights[_ii] * _cvalue; \ + else \ + _res += _weights[_ii] * (double)*(_type*)(_pi + _offset); \ + } \ +} \ +break + +#define CASE_FILTER_OUT(_po, _tmp, _type) \ +case t ## _type: \ + *(_type*)_po = (_type)_tmp; \ + break + +int NI_Correlate(PyArrayObject* input, PyArrayObject* weights, + PyArrayObject* output, NI_ExtendMode mode, + double cvalue, maybelong *origins) +{ + Bool *pf = NULL; + maybelong fsize, jj, kk, filter_size = 0, border_flag_value; + maybelong *offsets = NULL, *oo, size; + NI_FilterIterator fi; + NI_Iterator ii, io; + char *pi, *po; + Float64 *pw; + Float64 *ww = NULL; + int ll; + + /* get the the footprint: */ + fsize = 1; + for(ll = 0; ll < weights->nd; ll++) + fsize *= weights->dimensions[ll]; + pw = (Float64*)PyArray_DATA(weights); + pf = (Bool*)malloc(fsize * sizeof(Bool)); + if (!pf) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < fsize; jj++) { + if (fabs(pw[jj]) > DBL_EPSILON) { + pf[jj] = 1; + ++filter_size; + } else { + pf[jj] = 0; + } + } + /* copy the weights to contiguous memory: */ + ww = (Float64*)malloc(filter_size * sizeof(Float64)); + if (!ww) { + PyErr_NoMemory(); + goto exit; + } + jj = 0; + for(kk = 0; kk < fsize; kk++) { + if (pf[kk]) { + ww[jj++] = pw[kk]; + } + } + /* initialize filter offsets: */ + if (!NI_InitFilterOffsets(input, pf, weights->dimensions, origins, + mode, &offsets, &border_flag_value, NULL)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(input->nd, weights->dimensions, filter_size, + input->dimensions, origins, &fi)) + goto exit; + /* initialize input element iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* initialize output element iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + /* get data pointers an array size: */ + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(ll = 0; ll < input->nd; ll++) + size *= input->dimensions[ll]; + /* iterator over the elements: */ + oo = offsets; + for(jj = 0; jj < size; jj++) { + double tmp = 0.0; + switch (input->descr->type_num) { + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Bool, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt8, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt16, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt32, + tmp, border_flag_value); +#if HAS_UINT64 + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt64, + tmp, border_flag_value); +#endif + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int8, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int16, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int32, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int64, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Float32, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Float64, + tmp, border_flag_value); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_FILTER_OUT(po, tmp, Bool); + CASE_FILTER_OUT(po, tmp, UInt8); + CASE_FILTER_OUT(po, tmp, UInt16); + CASE_FILTER_OUT(po, tmp, UInt32); +#if HAS_UINT64 + CASE_FILTER_OUT(po, tmp, UInt64); +#endif + CASE_FILTER_OUT(po, tmp, Int8); + CASE_FILTER_OUT(po, tmp, Int16); + CASE_FILTER_OUT(po, tmp, Int32); + CASE_FILTER_OUT(po, tmp, Int64); + CASE_FILTER_OUT(po, tmp, Float32); + CASE_FILTER_OUT(po, tmp, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); + } +exit: + if (offsets) free(offsets); + if (ww) free(ww); + if (pf) free(pf); + return PyErr_Occurred() ? 0 : 1; +} + +int +NI_UniformFilter1D(PyArrayObject *input, long filter_size, + int axis, PyArrayObject *output, NI_ExtendMode mode, + double cval, long origin) +{ + maybelong lines, kk, ll, length, size1, size2; + int more; + double *ibuffer = NULL, *obuffer = NULL; + NI_LineBuffer iline_buffer, oline_buffer; + + size1 = filter_size / 2; + size2 = filter_size - size1 - 1; + /* allocate and initialize the line buffers: */ + lines = -1; + if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, + &lines, BUFFER_SIZE, &ibuffer)) + goto exit; + if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, + &obuffer)) + goto exit; + if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, + lines, ibuffer, mode, cval, &iline_buffer)) + goto exit; + if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, + &oline_buffer)) + goto exit; + length = input->nd > 0 ? input->dimensions[axis] : 1; + + /* iterate over all the array lines: */ + do { + /* copy lines from array to buffer: */ + if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) + goto exit; + /* iterate over the lines in the buffers: */ + for(kk = 0; kk < lines; kk++) { + /* get lines: */ + double *iline = NI_GET_LINE(iline_buffer, kk); + double *oline = NI_GET_LINE(oline_buffer, kk); + /* do the uniform filter: */ + double tmp = 0.0; + double *l1 = iline; + double *l2 = iline + filter_size; + for(ll = 0; ll < filter_size; ll++) + tmp += iline[ll]; + tmp /= (double)filter_size; + oline[0] = tmp; + for(ll = 1; ll < length; ll++) { + tmp += (*l2++ - *l1++) / (double)filter_size; + oline[ll] = tmp; + } + } + /* copy lines from buffer to array: */ + if (!NI_LineBufferToArray(&oline_buffer)) + goto exit; + } while(more); + + exit: + if (ibuffer) free(ibuffer); + if (obuffer) free(obuffer); + return PyErr_Occurred() ? 0 : 1; +} + +int +NI_MinOrMaxFilter1D(PyArrayObject *input, long filter_size, + int axis, PyArrayObject *output, NI_ExtendMode mode, + double cval, long origin, int minimum) +{ + maybelong lines, kk, jj, ll, length, size1, size2; + int more; + double *ibuffer = NULL, *obuffer = NULL; + NI_LineBuffer iline_buffer, oline_buffer; + + size1 = filter_size / 2; + size2 = filter_size - size1 - 1; + /* allocate and initialize the line buffers: */ + lines = -1; + if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, + &lines, BUFFER_SIZE, &ibuffer)) + goto exit; + if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, + &obuffer)) + goto exit; + if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, + lines, ibuffer, mode, cval, &iline_buffer)) + goto exit; + if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, + &oline_buffer)) + goto exit; + length = input->nd > 0 ? input->dimensions[axis] : 1; + + /* iterate over all the array lines: */ + do { + /* copy lines from array to buffer: */ + if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) + goto exit; + /* iterate over the lines in the buffers: */ + for(kk = 0; kk < lines; kk++) { + /* get lines: */ + double *iline = NI_GET_LINE(iline_buffer, kk) + size1; + double *oline = NI_GET_LINE(oline_buffer, kk); + for(ll = 0; ll < length; ll++) { + /* find minimum or maximum filter: */ + double val = iline[ll - size1]; + for(jj = -size1 + 1; jj <= size2; jj++) { + double tmp = iline[ll + jj]; + if (minimum) { + if (tmp < val) + val = tmp; + } else { + if (tmp > val) + val = tmp; + } + } + oline[ll] = val; + } + } + /* copy lines from buffer to array: */ + if (!NI_LineBufferToArray(&oline_buffer)) + goto exit; + } while(more); + + exit: + if (ibuffer) free(ibuffer); + if (obuffer) free(obuffer); + return PyErr_Occurred() ? 0 : 1; +} + + +#define CASE_MIN_OR_MAX_POINT(_pi, _offsets, _filter_size, _cval, \ + _type, _minimum, _res, _mv, _ss) \ +case t ## _type: \ +{ \ + maybelong _ii, _oo = *_offsets; \ + _type _cv = (_type)_cval, _tmp; \ + _res = _oo == _mv ? _cv : *(_type*)(_pi + _oo); \ + if (_ss) \ + _res += *_ss; \ + for(_ii = 1; _ii < _filter_size; _ii++) { \ + _oo = _offsets[_ii]; \ + _tmp = _oo == _mv ? _cv : *(_type*)(_pi + _oo); \ + if (_ss) \ + _tmp += _ss[_ii]; \ + if (_minimum) { \ + if (_tmp < _res) \ + _res = (_type)_tmp; \ + } else { \ + if (_tmp > _res) \ + _res = (_type)_tmp; \ + } \ + } \ +} \ +break + +int NI_MinOrMaxFilter(PyArrayObject* input, PyArrayObject* footprint, + PyArrayObject* structure, PyArrayObject* output, + NI_ExtendMode mode, double cvalue, maybelong *origins, int minimum) +{ + Bool *pf = NULL; + maybelong fsize, jj, kk, filter_size = 0, border_flag_value; + maybelong *offsets = NULL, *oo, size; + NI_FilterIterator fi; + NI_Iterator ii, io; + char *pi, *po; + int ll; + double *ss = NULL; + Float64 *ps; + + /* get the the footprint: */ + fsize = 1; + for(ll = 0; ll < footprint->nd; ll++) + fsize *= footprint->dimensions[ll]; + pf = (Bool*)PyArray_DATA(footprint); + for(jj = 0; jj < fsize; jj++) { + if (pf[jj]) { + ++filter_size; + } + } + /* get the structure: */ + if (structure) { + ss = (double*)malloc(filter_size * sizeof(double)); + if (!ss) { + PyErr_NoMemory(); + goto exit; + } + /* copy the weights to contiguous memory: */ + ps = (Float64*)PyArray_DATA(structure); + jj = 0; + for(kk = 0; kk < fsize; kk++) + if (pf[kk]) + ss[jj++] = minimum ? -ps[kk] : ps[kk]; + } + /* initialize filter offsets: */ + if (!NI_InitFilterOffsets(input, pf, footprint->dimensions, origins, + mode, &offsets, &border_flag_value, NULL)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(input->nd, footprint->dimensions, + filter_size, input->dimensions, origins, &fi)) + goto exit; + /* initialize input element iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* initialize output element iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + /* get data pointers an array size: */ + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(ll = 0; ll < input->nd; ll++) + size *= input->dimensions[ll]; + /* iterator over the elements: */ + oo = offsets; + for(jj = 0; jj < size; jj++) { + double tmp = 0.0; + switch (input->descr->type_num) { + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Bool, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt8, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt16, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt32, + minimum, tmp, border_flag_value, ss); +#if HAS_UINT64 + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt64, + minimum, tmp, border_flag_value, ss); +#endif + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int8, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int16, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int32, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int64, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Float32, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Float64, + minimum, tmp, border_flag_value, ss); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_FILTER_OUT(po, tmp, Bool); + CASE_FILTER_OUT(po, tmp, UInt8); + CASE_FILTER_OUT(po, tmp, UInt16); + CASE_FILTER_OUT(po, tmp, UInt32); +#if HAS_UINT64 + CASE_FILTER_OUT(po, tmp, UInt64); +#endif + CASE_FILTER_OUT(po, tmp, Int8); + CASE_FILTER_OUT(po, tmp, Int16); + CASE_FILTER_OUT(po, tmp, Int32); + CASE_FILTER_OUT(po, tmp, Int64); + CASE_FILTER_OUT(po, tmp, Float32); + CASE_FILTER_OUT(po, tmp, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); + } +exit: + if (offsets) free(offsets); + if (ss) free(ss); + return PyErr_Occurred() ? 0 : 1; +} + +static double NI_Select(double *buffer, int min, int max, int rank) +{ + int ii, jj; + double x, t; + + if (min == max) + return buffer[min]; + + x = buffer[min]; + ii = min - 1; + jj = max + 1; + for(;;) { + do + jj--; + while(buffer[jj] > x); + do + ii++; + while(buffer[ii] < x); + if (ii < jj) { + t = buffer[ii]; + buffer[ii] = buffer[jj]; + buffer[jj] = t; + } else { + break; + } + } + + ii = jj - min + 1; + if (rank < ii) + return NI_Select(buffer, min, jj, rank); + else + return NI_Select(buffer, jj + 1, max, rank - ii); +} + +#define CASE_RANK_POINT(_pi, _offsets, _filter_size, _cval, _type, \ + _rank, _buffer, _res, _mv) \ +case t ## _type: \ +{ \ + maybelong _ii; \ + for(_ii = 0; _ii < _filter_size; _ii++) { \ + maybelong _offset = _offsets[_ii]; \ + if (_offset == _mv) \ + _buffer[_ii] = (_type)_cval; \ + else \ + _buffer[_ii] = *(_type*)(_pi + _offsets[_ii]); \ + } \ + _res = (_type)NI_Select(_buffer, 0, _filter_size - 1, _rank); \ +} \ +break + +int NI_RankFilter(PyArrayObject* input, int rank, + PyArrayObject* footprint, PyArrayObject* output, + NI_ExtendMode mode, double cvalue, maybelong *origins) +{ + maybelong fsize, jj, filter_size = 0, border_flag_value; + maybelong *offsets = NULL, *oo, size; + NI_FilterIterator fi; + NI_Iterator ii, io; + char *pi, *po; + Bool *pf = NULL; + double *buffer = NULL; + int ll; + + /* get the the footprint: */ + fsize = 1; + for(ll = 0; ll < footprint->nd; ll++) + fsize *= footprint->dimensions[ll]; + pf = (Bool*)PyArray_DATA(footprint); + for(jj = 0; jj < fsize; jj++) { + if (pf[jj]) { + ++filter_size; + } + } + /* buffer for rank calculation: */ + buffer = (double*)malloc(filter_size * sizeof(double)); + if (!buffer) { + PyErr_NoMemory(); + goto exit; + } + /* iterator over the elements: */ + oo = offsets; + /* initialize filter offsets: */ + if (!NI_InitFilterOffsets(input, pf, footprint->dimensions, origins, + mode, &offsets, &border_flag_value, NULL)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(input->nd, footprint->dimensions, + filter_size, input->dimensions, origins, &fi)) + goto exit; + /* initialize input element iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* initialize output element iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + /* get data pointers an array size: */ + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(ll = 0; ll < input->nd; ll++) + size *= input->dimensions[ll]; + /* iterator over the elements: */ + oo = offsets; + for(jj = 0; jj < size; jj++) { + double tmp = 0.0; + switch (input->descr->type_num) { + CASE_RANK_POINT(pi, oo, filter_size, cvalue, Bool, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, UInt8, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, UInt16, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, UInt32, + rank, buffer, tmp, border_flag_value); +#if HAS_UINT64 + CASE_RANK_POINT(pi, oo, filter_size, cvalue, UInt64, + rank, buffer, tmp, border_flag_value); +#endif + CASE_RANK_POINT(pi, oo, filter_size, cvalue, Int8, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, Int16, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, Int32, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, Int64, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, Float32, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, Float64, + rank, buffer, tmp, border_flag_value); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_FILTER_OUT(po, tmp, Bool); + CASE_FILTER_OUT(po, tmp, UInt8); + CASE_FILTER_OUT(po, tmp, UInt16); + CASE_FILTER_OUT(po, tmp, UInt32); +#if HAS_UINT64 + CASE_FILTER_OUT(po, tmp, UInt64); +#endif + CASE_FILTER_OUT(po, tmp, Int8); + CASE_FILTER_OUT(po, tmp, Int16); + CASE_FILTER_OUT(po, tmp, Int32); + CASE_FILTER_OUT(po, tmp, Int64); + CASE_FILTER_OUT(po, tmp, Float32); + CASE_FILTER_OUT(po, tmp, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); + } +exit: + if (offsets) free(offsets); + if (buffer) free(buffer); + return PyErr_Occurred() ? 0 : 1; +} + +int NI_GenericFilter1D(PyArrayObject *input, + int (*function)(double*, maybelong, double*, maybelong, void*), + void* data, long filter_size, int axis, PyArrayObject *output, + NI_ExtendMode mode, double cval, long origin) +{ + int more; + maybelong ii, lines, length, size1, size2; + double *ibuffer = NULL, *obuffer = NULL; + NI_LineBuffer iline_buffer, oline_buffer; + + /* allocate and initialize the line buffers: */ + size1 = filter_size / 2; + size2 = filter_size - size1 - 1; + lines = -1; + if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, + &lines, BUFFER_SIZE, &ibuffer)) + goto exit; + if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, + &obuffer)) + goto exit; + if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, + lines, ibuffer, mode, cval, &iline_buffer)) + goto exit; + if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, + &oline_buffer)) + goto exit; + length = input->nd > 0 ? input->dimensions[axis] : 1; + /* iterate over all the array lines: */ + do { + /* copy lines from array to buffer: */ + if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) + goto exit; + /* iterate over the lines in the buffers: */ + for(ii = 0; ii < lines; ii++) { + /* get lines: */ + double *iline = NI_GET_LINE(iline_buffer, ii); + double *oline = NI_GET_LINE(oline_buffer, ii); + if (!function(iline, length + size1 + size2, oline, length, data)) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, + "unknown error in line processing function"); + goto exit; + } + } + /* copy lines from buffer to array: */ + if (!NI_LineBufferToArray(&oline_buffer)) + goto exit; + } while(more); +exit: + if (ibuffer) free(ibuffer); + if (obuffer) free(obuffer); + return PyErr_Occurred() ? 0 : 1; +} + +#define CASE_FILTER_POINT(_pi, _offsets, _filter_size, _cvalue, _type, \ + _res, _mv, _function, _data, _buffer) \ +case t ## _type: \ +{ \ + maybelong _ii, _offset; \ + for(_ii = 0; _ii < _filter_size; _ii++) { \ + _offset = _offsets[_ii]; \ + if (_offset == _mv) \ + _buffer[_ii] = (double)_cvalue; \ + else \ + _buffer[_ii] = (double)*(_type*)(_pi + _offset); \ + } \ + if (!_function(_buffer, _filter_size, &_res, _data)) { \ + if (!PyErr_Occurred()) \ + PyErr_SetString(PyExc_RuntimeError, \ + "unknown error in filter function"); \ + goto exit; \ + } \ +} \ +break + + +int NI_GenericFilter(PyArrayObject* input, + int (*function)(double*, maybelong, double*, void*), void *data, + PyArrayObject* footprint, PyArrayObject* output, + NI_ExtendMode mode, double cvalue, maybelong *origins) +{ + Bool *pf = NULL; + maybelong fsize, jj, filter_size = 0, border_flag_value; + maybelong *offsets = NULL, *oo, size; + NI_FilterIterator fi; + NI_Iterator ii, io; + char *pi, *po; + double *buffer = NULL; + int ll; + + /* get the the footprint: */ + fsize = 1; + for(ll = 0; ll < footprint->nd; ll++) + fsize *= footprint->dimensions[ll]; + pf = (Bool*)PyArray_DATA(footprint); + for(jj = 0; jj < fsize; jj++) { + if (pf[jj]) + ++filter_size; + } + /* initialize filter offsets: */ + if (!NI_InitFilterOffsets(input, pf, footprint->dimensions, origins, + mode, &offsets, &border_flag_value, NULL)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(input->nd, footprint->dimensions, + filter_size, input->dimensions, origins, &fi)) + goto exit; + /* initialize input element iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* initialize output element iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + /* get data pointers an array size: */ + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(ll = 0; ll < input->nd; ll++) + size *= input->dimensions[ll]; + /* buffer for filter calculation: */ + buffer = (double*)malloc(filter_size * sizeof(double)); + if (!buffer) { + PyErr_NoMemory(); + goto exit; + } + /* iterate over the elements: */ + oo = offsets; + for(jj = 0; jj < size; jj++) { + double tmp = 0.0; + switch (input->descr->type_num) { + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Bool, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt8, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt16, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt32, + tmp, border_flag_value, function, data, buffer); +#if HAS_UINT64 + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt64, + tmp, border_flag_value, function, data, buffer); +#endif + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int8, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int16, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int32, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int64, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Float32, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Float64, + tmp, border_flag_value, function, data, buffer); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_FILTER_OUT(po, tmp, Bool); + CASE_FILTER_OUT(po, tmp, UInt8); + CASE_FILTER_OUT(po, tmp, UInt16); + CASE_FILTER_OUT(po, tmp, UInt32); +#if HAS_UINT64 + CASE_FILTER_OUT(po, tmp, UInt64); +#endif + CASE_FILTER_OUT(po, tmp, Int8); + CASE_FILTER_OUT(po, tmp, Int16); + CASE_FILTER_OUT(po, tmp, Int32); + CASE_FILTER_OUT(po, tmp, Int64); + CASE_FILTER_OUT(po, tmp, Float32); + CASE_FILTER_OUT(po, tmp, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); + } +exit: + if (offsets) free(offsets); + if (buffer) free(buffer); + return PyErr_Occurred() ? 0 : 1; +} Added: branches/Interpolate1D/ndimage/ni_filters.h =================================================================== --- branches/Interpolate1D/ndimage/ni_filters.h 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/ni_filters.h 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,54 @@ +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NI_FILTERS_H +#define NI_FILTERS_H + +int NI_Correlate1D(PyArrayObject*, PyArrayObject*, int, PyArrayObject*, + NI_ExtendMode, double, maybelong); +int NI_Correlate(PyArrayObject*, PyArrayObject*, PyArrayObject*, + NI_ExtendMode, double, maybelong*); +int NI_UniformFilter1D(PyArrayObject*, long, int, PyArrayObject*, + NI_ExtendMode, double, long); +int NI_MinOrMaxFilter1D(PyArrayObject*, long, int, PyArrayObject*, + NI_ExtendMode, double, long, int); +int NI_MinOrMaxFilter(PyArrayObject*, PyArrayObject*, PyArrayObject*, + PyArrayObject*, NI_ExtendMode, double, maybelong*, + int); +int NI_RankFilter(PyArrayObject*, int, PyArrayObject*, PyArrayObject*, + NI_ExtendMode, double, maybelong*); +int NI_GenericFilter1D(PyArrayObject*, int (*)(double*, maybelong, + double*, maybelong, void*), void*, long, int, + PyArrayObject*, NI_ExtendMode, double, long); +int NI_GenericFilter(PyArrayObject*, int (*)(double*, maybelong, double*, + void*), void*, PyArrayObject*, PyArrayObject*, + NI_ExtendMode, double, maybelong*); +#endif Added: branches/Interpolate1D/ndimage/ni_fourier.c =================================================================== --- branches/Interpolate1D/ndimage/ni_fourier.c 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/ni_fourier.c 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,548 @@ +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ni_support.h" +#include +#include +#include + +#if !defined(M_PI) +#define M_PI 3.14159265358979323846 +#endif + +#define _NI_GAUSSIAN 0 +#define _NI_UNIFORM 1 +#define _NI_ELLIPSOID 2 + +static double polevl(double x, const double coef[], int N) +{ + double ans; + const double *p = coef; + int i = N; + + ans = *p++; + do + ans = ans * x + *p++; + while(--i); + + return ans ; +} + +double p1evl(double x, const double coef[], int N) +{ + double ans; + const double *p = coef; + int i = N - 1; + + ans = x + *p++; + do + ans = ans * x + *p++; + while(--i); + + return ans; +} + +#define THPIO4 2.35619449019234492885 +#define SQ2OPI .79788456080286535588 +#define Z1 1.46819706421238932572E1 +#define Z2 4.92184563216946036703E1 + +static double _bessel_j1(double x) +{ + double w, z, p, q, xn; + const double RP[4] = { + -8.99971225705559398224E8, + 4.52228297998194034323E11, + -7.27494245221818276015E13, + 3.68295732863852883286E15, + }; + const double RQ[8] = { + 6.20836478118054335476E2, + 2.56987256757748830383E5, + 8.35146791431949253037E7, + 2.21511595479792499675E10, + 4.74914122079991414898E12, + 7.84369607876235854894E14, + 8.95222336184627338078E16, + 5.32278620332680085395E18, + }; + const double PP[7] = { + 7.62125616208173112003E-4, + 7.31397056940917570436E-2, + 1.12719608129684925192E0, + 5.11207951146807644818E0, + 8.42404590141772420927E0, + 5.21451598682361504063E0, + 1.00000000000000000254E0, + }; + const double PQ[7] = { + 5.71323128072548699714E-4, + 6.88455908754495404082E-2, + 1.10514232634061696926E0, + 5.07386386128601488557E0, + 8.39985554327604159757E0, + 5.20982848682361821619E0, + 9.99999999999999997461E-1, + }; + const double QP[8] = { + 5.10862594750176621635E-2, + 4.98213872951233449420E0, + 7.58238284132545283818E1, + 3.66779609360150777800E2, + 7.10856304998926107277E2, + 5.97489612400613639965E2, + 2.11688757100572135698E2, + 2.52070205858023719784E1, + }; + const double QQ[7] = { + 7.42373277035675149943E1, + 1.05644886038262816351E3, + 4.98641058337653607651E3, + 9.56231892404756170795E3, + 7.99704160447350683650E3, + 2.82619278517639096600E3, + 3.36093607810698293419E2, + }; + + w = x; + if (x < 0) + w = -x; + + if (w <= 5.0) { + z = x * x; + w = polevl(z, RP, 3) / p1evl(z, RQ, 8); + w = w * x * (z - Z1) * (z - Z2); + return w ; + } + + w = 5.0 / x; + z = w * w; + p = polevl(z, PP, 6) / polevl(z, PQ, 6); + q = polevl(z, QP, 7) / p1evl(z, QQ, 7); + xn = x - THPIO4; + p = p * cos(xn) - w * q * sin(xn); + return p * SQ2OPI / sqrt(x); +} + +#define CASE_FOURIER_OUT_RR(_po, _tmp, _type) \ +case t ## _type: \ + *(_type*)_po = _tmp; \ + break + +#define CASE_FOURIER_OUT_RC(_po, _tmp, _type) \ +case t ## _type: \ + (*(_type*)_po).real = tmp; \ + (*(_type*)_po).imag = 0.0; \ + break + +#define CASE_FOURIER_OUT_CC(_po, _tmp_r, _tmp_i, _type) \ +case t ## _type: \ + (*(_type*)_po).real = _tmp_r; \ + (*(_type*)_po).imag = _tmp_i; \ + break + +#define CASE_FOURIER_FILTER_RC(_pi, _tmp, _tmp_r, _tmp_i, _type) \ +case t ## _type: \ + _tmp_r = (*(_type*)_pi).real * _tmp; \ + _tmp_i = (*(_type*)_pi).imag * _tmp; \ + break; + +#define CASE_FOURIER_FILTER_RR(_pi, _tmp, _type) \ +case t ## _type: \ + _tmp *= *(_type*)_pi; \ + break; + +int NI_FourierFilter(PyArrayObject *input, PyArrayObject* parameter_array, + maybelong n, int axis, PyArrayObject* output, int filter_type) +{ + NI_Iterator ii, io; + char *pi, *po; + double *parameters = NULL, **params = NULL; + maybelong kk, hh, size; + Float64 *iparameters = (void *)PyArray_DATA(parameter_array); + int ll; + + /* precalculate the parameters: */ + parameters = (double*)malloc(input->nd * sizeof(double)); + if (!parameters) { + PyErr_NoMemory(); + goto exit; + } + for(kk = 0; kk < input->nd; kk++) { + /* along the direction of the real transform we must use the given + length of that dimensons, unless a complex transform is assumed + (n < 0): */ + int shape = kk == axis ? + (n < 0 ? input->dimensions[kk] : n) : input->dimensions[kk]; + switch (filter_type) { + case _NI_GAUSSIAN: + parameters[kk] = *iparameters++ * M_PI / (double)shape; + parameters[kk] = -2.0 * parameters[kk] * parameters[kk]; + break; + case _NI_ELLIPSOID: + case _NI_UNIFORM: + parameters[kk] = *iparameters++; + break; + } + } + /* allocate memory for tables: */ + params = (double**) malloc(input->nd * sizeof(double*)); + if (!params) { + PyErr_NoMemory(); + goto exit; + } + for(kk = 0; kk < input->nd; kk++) + params[kk] = NULL; + for(kk = 0; kk < input->nd; kk++) { + if (input->dimensions[kk] > 1) { + params[kk] = (double*)malloc(input->dimensions[kk] * sizeof(double)); + if (!params[kk]) { + PyErr_NoMemory(); + goto exit; + } + } + } + switch (filter_type) { + case _NI_GAUSSIAN: + /* calculate the tables of exponentials: */ + for (hh = 0; hh < input->nd; hh++) { + if (params[hh]) { + if (hh == axis && n >= 0) { + for(kk = 0; kk < input->dimensions[hh]; kk++) { + double tmp = parameters[hh] * kk * kk; + params[hh][kk] = fabs(tmp) > 50.0 ? 0.0 : exp(tmp); + } + } else { + int jj = 0; + for(kk = 0; kk < (input->dimensions[hh] + 1) / 2; kk++) { + double tmp = parameters[hh] * kk * kk; + params[hh][jj++] = fabs(tmp) > 50.0 ? 0.0 : exp(tmp); + } + for(kk = -(input->dimensions[hh] / 2); kk < 0; kk++) { + double tmp = parameters[hh] * kk * kk; + params[hh][jj++] = fabs(tmp) > 50.0 ? 0.0 : exp(tmp); + } + } + } + } + break; + case _NI_UNIFORM: + /* calculate the tables of parameters: */ + for (hh = 0; hh < input->nd; hh++) { + if (params[hh]) { + params[hh][0] = 1.0; + if (hh == axis && n >= 0) { + double tmp = M_PI * parameters[hh] / n; + for(kk = 1; kk < input->dimensions[hh]; kk++) + params[hh][kk] = tmp > 0.0 ? + sin(tmp * kk) / (tmp * kk) : 0.0; + } else { + double tmp = M_PI * parameters[hh] / input->dimensions[hh]; + int jj = 1; + for(kk = 1; kk < (input->dimensions[hh] + 1) / 2; kk++) + params[hh][jj++] = tmp > 0.0 ? + sin(tmp * kk) / (tmp * kk) : 0.0; + for(kk = -(input->dimensions[hh] / 2); kk < 0; kk++) + params[hh][jj++] = tmp > 0.0 ? + sin(tmp * kk) / (tmp * kk) : 0.0; + } + } + } + break; + case _NI_ELLIPSOID: + /* calculate the tables of parameters: */ + for (hh = 0; hh < input->nd; hh++) { + if (params[hh]) { + params[hh][0] = 1.0; + if (hh == axis && n >= 0) { + double tmp = M_PI * parameters[hh] / n; + for(kk = 0; kk < input->dimensions[hh]; kk++) + params[hh][kk] = (double)kk * tmp; + } else { + double tmp = M_PI * parameters[hh] / input->dimensions[hh]; + int jj = 0; + for(kk = 0; kk < (input->dimensions[hh] + 1) / 2; kk++) + params[hh][jj++] = (double)kk * tmp; + for(kk = -(input->dimensions[hh] / 2); kk < 0; kk++) + params[hh][jj++] = (double)kk * tmp; + } + } else if (input->dimensions[hh] > 0) { + params[hh][0] = 1.0; + } + } + if (input->nd > 1) + for(hh = 0; hh < input->nd; hh++) + for(kk = 0; kk < input->dimensions[hh]; kk++) + params[hh][kk] = params[hh][kk] * params[hh][kk]; + break; + default: + break; + } + /* initialize input element iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* initialize output element iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(ll = 0; ll < input->nd; ll++) + size *= input->dimensions[ll]; + /* iterator over the elements: */ + for(hh = 0; hh < size; hh++) { + double tmp = 1.0; + switch (filter_type) { + case _NI_GAUSSIAN: + case _NI_UNIFORM: + for(kk = 0; kk < input->nd; kk++) + if (params[kk]) + tmp *= params[kk][ii.coordinates[kk]]; + break; + case _NI_ELLIPSOID: + switch (input->nd) { + case 1: + tmp = params[0][ii.coordinates[0]]; + tmp = tmp > 0.0 ? sin(tmp) / (tmp) : 1.0; + break; + case 2: + tmp = 0.0; + for(kk = 0; kk < 2; kk++) + tmp += params[kk][ii.coordinates[kk]]; + tmp = sqrt(tmp); + tmp = tmp > 0.0 ? 2.0 * _bessel_j1(tmp) / tmp : 1.0; + break; + case 3: + { + double r = 0.0; + for(kk = 0; kk < 3; kk++) + r += params[kk][ii.coordinates[kk]]; + r = sqrt(r); + if (r > 0.0) { + tmp = 3.0 * (sin(r) - r * cos(r)); + tmp /= r * r * r; + } else { + tmp = 1.0; + } + } + break; + } + break; + default: + break; + } + if (input->descr->type_num == tComplex64 || + input->descr->type_num == tComplex128) { + double tmp_r = 0.0, tmp_i = 0.0; + switch (input->descr->type_num) { + CASE_FOURIER_FILTER_RC(pi, tmp, tmp_r, tmp_i, Complex64); + CASE_FOURIER_FILTER_RC(pi, tmp, tmp_r, tmp_i, Complex128); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_FOURIER_OUT_CC(po, tmp_r, tmp_i, Complex64); + CASE_FOURIER_OUT_CC(po, tmp_r, tmp_i, Complex128); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + } else { + switch (input->descr->type_num) { + CASE_FOURIER_FILTER_RR(pi, tmp, Bool) + CASE_FOURIER_FILTER_RR(pi, tmp, UInt8) + CASE_FOURIER_FILTER_RR(pi, tmp, UInt16) + CASE_FOURIER_FILTER_RR(pi, tmp, UInt32) +#if HAS_UINT64 + CASE_FOURIER_FILTER_RR(pi, tmp, UInt64) +#endif + CASE_FOURIER_FILTER_RR(pi, tmp, Int8) + CASE_FOURIER_FILTER_RR(pi, tmp, Int16) + CASE_FOURIER_FILTER_RR(pi, tmp, Int32) + CASE_FOURIER_FILTER_RR(pi, tmp, Int64) + CASE_FOURIER_FILTER_RR(pi, tmp, Float32) + CASE_FOURIER_FILTER_RR(pi, tmp, Float64) + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_FOURIER_OUT_RR(po, tmp, Float32); + CASE_FOURIER_OUT_RR(po, tmp, Float64); + CASE_FOURIER_OUT_RC(po, tmp, Complex64); + CASE_FOURIER_OUT_RC(po, tmp, Complex128); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + } + NI_ITERATOR_NEXT2(ii, io, pi, po); + } + + exit: + if (parameters) free(parameters); + if (params) { + for(kk = 0; kk < input->nd; kk++) + if (params[kk]) free(params[kk]); + free(params); + } + return PyErr_Occurred() ? 0 : 1; +} + +#define CASE_FOURIER_SHIFT_R(_pi, _tmp, _r, _i, _cost, _sint, _type) \ +case t ## _type: \ + _tmp = *(_type*)_pi; \ + _r = _tmp * _cost; \ + _i = _tmp * _sint; \ + break; + +#define CASE_FOURIER_SHIFT_C(_pi, _r, _i, _cost, _sint, _type) \ +case t ## _type: \ + _r = (*(_type*)_pi).real * _cost - (*(_type*)_pi).imag * _sint; \ + _i = (*(_type*)_pi).real * _sint + (*(_type*)_pi).imag * _cost; \ + break; + +int NI_FourierShift(PyArrayObject *input, PyArrayObject* shift_array, + maybelong n, int axis, PyArrayObject* output) +{ + NI_Iterator ii, io; + char *pi, *po; + double *shifts = NULL, **params = NULL; + maybelong kk, hh, size; + Float64 *ishifts = (void *)PyArray_DATA(shift_array); + int ll; + + /* precalculate the shifts: */ + shifts = (double*)malloc(input->nd * sizeof(double)); + if (!shifts) { + PyErr_NoMemory(); + goto exit; + } + for(kk = 0; kk < input->nd; kk++) { + /* along the direction of the real transform we must use the given + length of that dimensons, unless a complex transform is assumed + (n < 0): */ + int shape = kk == axis ? + (n < 0 ? input->dimensions[kk] : n) : input->dimensions[kk]; + shifts[kk] = -2.0 * M_PI * *ishifts++ / (double)shape; + } + /* allocate memory for tables: */ + params = (double**) malloc(input->nd * sizeof(double*)); + if (!params) { + PyErr_NoMemory(); + goto exit; + } + for(kk = 0; kk < input->nd; kk++) + params[kk] = NULL; + for(kk = 0; kk < input->nd; kk++) { + if (input->dimensions[kk] > 1) { + params[kk] = (double*)malloc(input->dimensions[kk] * sizeof(double)); + if (!params[kk]) { + PyErr_NoMemory(); + goto exit; + } + } + } + for (hh = 0; hh < input->nd; hh++) { + if (params[hh]) { + if (hh == axis && n >= 0) { + for(kk = 0; kk < input->dimensions[hh]; kk++) + params[hh][kk] = shifts[hh] * kk; + } else { + int jj = 0; + for(kk = 0; kk < (input->dimensions[hh] + 1) / 2; kk++) { + params[hh][jj++] = shifts[hh] * kk; + } + for(kk = -(input->dimensions[hh] / 2); kk < 0; kk++) { + params[hh][jj++] = shifts[hh] * kk; + } + } + } + } + /* initialize input element iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* initialize output element iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(ll = 0; ll < input->nd; ll++) + size *= input->dimensions[ll]; + /* iterator over the elements: */ + for(hh = 0; hh < size; hh++) { + double tmp = 0.0, sint, cost, r = 0.0, i = 0.0; + for(kk = 0; kk < input->nd; kk++) + if (params[kk]) + tmp += params[kk][ii.coordinates[kk]]; + sint = sin(tmp); + cost = cos(tmp); + switch (input->descr->type_num) { + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Bool) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, UInt8) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, UInt16) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, UInt32) +#if HAS_UINT64 + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, UInt64) +#endif + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Int8) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Int16) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Int32) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Int64) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Float32) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Float64) + CASE_FOURIER_SHIFT_C(pi, r, i, cost, sint, Complex64) + CASE_FOURIER_SHIFT_C(pi, r, i, cost, sint, Complex128) + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_FOURIER_OUT_CC(po, r, i, Complex64); + CASE_FOURIER_OUT_CC(po, r, i, Complex128); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + NI_ITERATOR_NEXT2(ii, io, pi, po); + } + + exit: + if (shifts) free(shifts); + if (params) { + for(kk = 0; kk < input->nd; kk++) + if (params[kk]) free(params[kk]); + free(params); + } + return PyErr_Occurred() ? 0 : 1; +} Added: branches/Interpolate1D/ndimage/ni_fourier.h =================================================================== --- branches/Interpolate1D/ndimage/ni_fourier.h 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/ni_fourier.h 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,40 @@ +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NI_FOURIER_H +#define NI_FOURIER_H + +int NI_FourierFilter(PyArrayObject*, PyArrayObject*, maybelong, int, + PyArrayObject*, int); +int NI_FourierShift(PyArrayObject*, PyArrayObject*, maybelong, int, + PyArrayObject*); + +#endif Added: branches/Interpolate1D/ndimage/ni_interpolation.c =================================================================== --- branches/Interpolate1D/ndimage/ni_interpolation.c 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/ni_interpolation.c 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,966 @@ +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ni_support.h" +#include "ni_interpolation.h" +#include +#include + +/* calculate the B-spline interpolation coefficients for given x: */ +static void +spline_coefficients(double x, int order, double *result) +{ + int hh; + double y, start; + + if (order & 1) { + start = (int)floor(x) - order / 2; + } else { + start = (int)floor(x + 0.5) - order / 2; + } + + for(hh = 0; hh <= order; hh++) { + y = fabs(start - x + hh); + + switch(order) { + case 1: + result[hh] = y > 1.0 ? 0.0 : 1.0 - y; + break; + case 2: + if (y < 0.5) { + result[hh] = 0.75 - y * y; + } else if (y < 1.5) { + y = 1.5 - y; + result[hh] = 0.5 * y * y; + } else { + result[hh] = 0.0; + } + break; + case 3: + if (y < 1.0) { + result[hh] = + (y * y * (y - 2.0) * 3.0 + 4.0) / 6.0; + } else if (y < 2.0) { + y = 2.0 - y; + result[hh] = y * y * y / 6.0; + } else { + result[hh] = 0.0; + } + break; + case 4: + if (y < 0.5) { + y *= y; + result[hh] = y * (y * 0.25 - 0.625) + 115.0 / 192.0; + } else if (y < 1.5) { + result[hh] = y * (y * (y * (5.0 / 6.0 - y / 6.0) - 1.25) + + 5.0 / 24.0) + 55.0 / 96.0; + } else if (y < 2.5) { + y -= 2.5; + y *= y; + result[hh] = y * y / 24.0; + } else { + result[hh] = 0.0; + } + break; + case 5: + if (y < 1.0) { + double f = y * y; + result[hh] = + f * (f * (0.25 - y / 12.0) - 0.5) + 0.55; + } else if (y < 2.0) { + result[hh] = y * (y * (y * (y * (y / 24.0 - 0.375) + + 1.25) - 1.75) + 0.625) + 0.425; + } else if (y < 3.0) { + double f = 3.0 - y; + y = f * f; + result[hh] = f * y * y / 120.0; + } else { + result[hh] = 0.0; + } + break; + } + } +} + +/* map a coordinate outside the borders, according to the requested + boundary condition: */ +static double +map_coordinate(double in, maybelong len, int mode) +{ + if (in < 0) { + switch (mode) { + case NI_EXTEND_MIRROR: + if (len <= 1) { + in = 0; + } else { + maybelong sz2 = 2 * len - 2; + in = sz2 * (maybelong)(-in / sz2) + in; + in = in <= 1 - len ? in + sz2 : -in; + } + break; + case NI_EXTEND_REFLECT: + if (len <= 1) { + in = 0; + } else { + maybelong sz2 = 2 * len; + if (in < -sz2) + in = sz2 * (maybelong)(-in / sz2) + in; + in = in < -len ? in + sz2 : -in - 1; + } + break; + case NI_EXTEND_WRAP: + if (len <= 1) { + in = 0; + } else { + maybelong sz = len - 1; + // Integer division of -in/sz gives (-in mod sz) + // Note that 'in' is negative + in += sz * ((maybelong)(-in / sz) + 1); + } + break; + case NI_EXTEND_NEAREST: + in = 0; + break; + case NI_EXTEND_CONSTANT: + in = -1; + break; + } + } else if (in > len-1) { + switch (mode) { + case NI_EXTEND_MIRROR: + if (len <= 1) { + in = 0; + } else { + maybelong sz2 = 2 * len - 2; + in -= sz2 * (maybelong)(in / sz2); + if (in >= len) + in = sz2 - in; + } + break; + case NI_EXTEND_REFLECT: + if (len <= 1) { + in = 0; + } else { + maybelong sz2 = 2 * len; + in -= sz2 * (maybelong)(in / sz2); + if (in >= len) + in = sz2 - in - 1; + } + break; + case NI_EXTEND_WRAP: + if (len <= 1) { + in = 0; + } else { + maybelong sz = len - 1; + in -= sz * (maybelong)(in / sz); + } + break; + case NI_EXTEND_NEAREST: + in = len - 1; + break; + case NI_EXTEND_CONSTANT: + in = -1; + break; + } + } + + return in; +} + +#define BUFFER_SIZE 256000 +#define TOLERANCE 1e-15 + +/* one-dimensional spline filter: */ +int NI_SplineFilter1D(PyArrayObject *input, int order, int axis, + PyArrayObject *output) +{ + int hh, npoles = 0, more; + maybelong kk, ll, lines, len; + double *buffer = NULL, weight, pole[2]; + NI_LineBuffer iline_buffer, oline_buffer; + + len = input->nd > 0 ? input->dimensions[axis] : 1; + if (len < 1) + goto exit; + + /* these are used in the spline filter calculation below: */ + switch (order) { + case 2: + npoles = 1; + pole[0] = sqrt(8.0) - 3.0; + break; + case 3: + npoles = 1; + pole[0] = sqrt(3.0) - 2.0; + break; + case 4: + npoles = 2; + pole[0] = sqrt(664.0 - sqrt(438976.0)) + sqrt(304.0) - 19.0; + pole[1] = sqrt(664.0 + sqrt(438976.0)) - sqrt(304.0) - 19.0; + break; + case 5: + npoles = 2; + pole[0] = sqrt(67.5 - sqrt(4436.25)) + sqrt(26.25) - 6.5; + pole[1] = sqrt(67.5 + sqrt(4436.25)) - sqrt(26.25) - 6.5; + break; + default: + break; + } + + weight = 1.0; + for(hh = 0; hh < npoles; hh++) + weight *= (1.0 - pole[hh]) * (1.0 - 1.0 / pole[hh]); + + /* allocate an initialize the line buffer, only a single one is used, + because the calculation is in-place: */ + lines = -1; + if (!NI_AllocateLineBuffer(input, axis, 0, 0, &lines, BUFFER_SIZE, + &buffer)) + goto exit; + if (!NI_InitLineBuffer(input, axis, 0, 0, lines, buffer, + NI_EXTEND_DEFAULT, 0.0, &iline_buffer)) + goto exit; + if (!NI_InitLineBuffer(output, axis, 0, 0, lines, buffer, + NI_EXTEND_DEFAULT, 0.0, &oline_buffer)) + goto exit; + + /* iterate over all the array lines: */ + do { + /* copy lines from array to buffer: */ + if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) + goto exit; + /* iterate over the lines in the buffer: */ + for(kk = 0; kk < lines; kk++) { + /* get line: */ + double *ln = NI_GET_LINE(iline_buffer, kk); + /* spline filter: */ + if (len > 1) { + for(ll = 0; ll < len; ll++) + ln[ll] *= weight; + for(hh = 0; hh < npoles; hh++) { + double p = pole[hh]; + int max = (int)ceil(log(TOLERANCE) / log(fabs(p))); + if (max < len) { + double zn = p; + double sum = ln[0]; + for(ll = 1; ll < max; ll++) { + sum += zn * ln[ll]; + zn *= p; + } + ln[0] = sum; + } else { + double zn = p; + double iz = 1.0 / p; + double z2n = pow(p, (double)(len - 1)); + double sum = ln[0] + z2n * ln[len - 1]; + z2n *= z2n * iz; + for(ll = 1; ll <= len - 2; ll++) { + sum += (zn + z2n) * ln[ll]; + zn *= p; + z2n *= iz; + } + ln[0] = sum / (1.0 - zn * zn); + } + for(ll = 1; ll < len; ll++) + ln[ll] += p * ln[ll - 1]; + ln[len-1] = (p / (p * p - 1.0)) * (ln[len-1] + p * ln[len-2]); + for(ll = len - 2; ll >= 0; ll--) + ln[ll] = p * (ln[ll + 1] - ln[ll]); + } + } + } + /* copy lines from buffer to array: */ + if (!NI_LineBufferToArray(&oline_buffer)) + goto exit; + } while(more); + + exit: + if (buffer) free(buffer); + return PyErr_Occurred() ? 0 : 1; +} + +#define CASE_MAP_COORDINATES(_p, _coor, _rank, _stride, _type) \ +case t ## _type: \ +{ \ + int _hh; \ + for(_hh = 0; _hh < _rank; _hh++) { \ + _coor[_hh] = *(_type*)_p; \ + _p += _stride; \ + } \ +} \ +break; + +#define CASE_INTERP_COEFF(_coeff, _pi, _idx, _type) \ +case t ## _type: \ + _coeff = *(_type*)(_pi + _idx); \ + break; + +#define CASE_INTERP_OUT(_po, _t, _type) \ +case t ## _type: \ + *(_type*)_po = (_type)_t; \ + break; + +#define CASE_INTERP_OUT_UINT(_po, _t, _type, type_min, type_max) \ +case t ## _type: \ + _t = _t > 0 ? _t + 0.5 : 0; \ + _t = _t > type_max ? type_max : t; \ + _t = _t < type_min ? type_min : t; \ + *(_type*)_po = (_type)_t; \ + break; + +#define CASE_INTERP_OUT_INT(_po, _t, _type, type_min, type_max) \ +case t ## _type: \ + _t = _t > 0 ? _t + 0.5 : _t - 0.5; \ + _t = _t > type_max ? type_max : t; \ + _t = _t < type_min ? type_min : t; \ + *(_type*)_po = (_type)_t; \ + break; + +int +NI_GeometricTransform(PyArrayObject *input, int (*map)(maybelong*, double*, + int, int, void*), void* map_data, PyArrayObject* matrix_ar, + PyArrayObject* shift_ar, PyArrayObject *coordinates, + PyArrayObject *output, int order, int mode, double cval) +{ + char *po, *pi, *pc = NULL; + maybelong **edge_offsets = NULL, **data_offsets = NULL, filter_size; + maybelong ftmp[MAXDIM], *fcoordinates = NULL, *foffsets = NULL; + maybelong cstride = 0, kk, hh, ll, jj, *idxs = NULL; + maybelong size; + double **splvals = NULL, icoor[MAXDIM]; + double idimensions[MAXDIM], istrides[MAXDIM]; + NI_Iterator io, ic; + Float64 *matrix = matrix_ar ? (Float64*)PyArray_DATA(matrix_ar) : NULL; + Float64 *shift = shift_ar ? (Float64*)PyArray_DATA(shift_ar) : NULL; + int irank = 0, orank, qq; + + for(kk = 0; kk < input->nd; kk++) { + idimensions[kk] = input->dimensions[kk]; + istrides[kk] = input->strides[kk]; + } + irank = input->nd; + orank = output->nd; + + /* if the mapping is from array coordinates: */ + if (coordinates) { + /* initialze a line iterator along the first axis: */ + if (!NI_InitPointIterator(coordinates, &ic)) + goto exit; + cstride = ic.strides[0]; + if (!NI_LineIterator(&ic, 0)) + goto exit; + pc = (void *)(PyArray_DATA(coordinates)); + } + + /* offsets used at the borders: */ + edge_offsets = (maybelong**)malloc(irank * sizeof(maybelong*)); + data_offsets = (maybelong**)malloc(irank * sizeof(maybelong*)); + if (!edge_offsets || !data_offsets) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < irank; jj++) + data_offsets[jj] = NULL; + for(jj = 0; jj < irank; jj++) { + data_offsets[jj] = (maybelong*)malloc((order + 1) * sizeof(maybelong)); + if (!data_offsets[jj]) { + PyErr_NoMemory(); + goto exit; + } + } + /* will hold the spline coefficients: */ + splvals = (double**)malloc(irank * sizeof(double*)); + if (!splvals) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < irank; jj++) + splvals[jj] = NULL; + for(jj = 0; jj < irank; jj++) { + splvals[jj] = (double*)malloc((order + 1) * sizeof(double)); + if (!splvals[jj]) { + PyErr_NoMemory(); + goto exit; + } + } + + filter_size = 1; + for(jj = 0; jj < irank; jj++) + filter_size *= order + 1; + idxs = (maybelong*)malloc(filter_size * sizeof(idxs)); + if (!idxs) { + PyErr_NoMemory(); + goto exit; + } + + /* initialize output iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + + /* get data pointers: */ + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + + /* make a table of all possible coordinates within the spline filter: */ + fcoordinates = (maybelong*)malloc(irank * filter_size * sizeof(maybelong)); + /* make a table of all offsets within the spline filter: */ + foffsets = (maybelong*)malloc(filter_size * sizeof(maybelong)); + if (!fcoordinates || !foffsets) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < irank; jj++) + ftmp[jj] = 0; + kk = 0; + for(hh = 0; hh < filter_size; hh++) { + for(jj = 0; jj < irank; jj++) + fcoordinates[jj + hh * irank] = ftmp[jj]; + foffsets[hh] = kk; + for(jj = irank - 1; jj >= 0; jj--) { + if (ftmp[jj] < order) { + ftmp[jj]++; + kk += istrides[jj]; + break; + } else { + ftmp[jj] = 0; + kk -= istrides[jj] * order; + } + } + } + + size = 1; + for(qq = 0; qq < output->nd; qq++) + size *= output->dimensions[qq]; + for(kk = 0; kk < size; kk++) { + double t = 0.0; + int constant = 0, edge = 0, offset = 0; + if (map) { + /* call mappint functions: */ + if (!map(io.coordinates, icoor, orank, irank, map_data)) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, + "unknown error in mapping function"); + goto exit; + } + } else if (matrix) { + /* do an affine transformation: */ + Float64 *p = matrix; + for(hh = 0; hh < irank; hh++) { + icoor[hh] = 0.0; + for(ll = 0; ll < orank; ll++) + icoor[hh] += io.coordinates[ll] * *p++; + icoor[hh] += shift[hh]; + } + } else if (coordinates) { + /* mapping is from an coordinates array: */ + char *p = pc; + switch(coordinates->descr->type_num) { + CASE_MAP_COORDINATES(p, icoor, irank, cstride, Bool); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt8); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt16); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt32); +#if HAS_UINT64 + CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt64); +#endif + CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int8); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int16); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int32); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int64); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, Float32); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, + "coordinate array data type not supported"); + goto exit; + } + } + /* iterate over axes: */ + for(hh = 0; hh < irank; hh++) { + /* if the input coordinate is outside the borders, map it: */ + double cc = map_coordinate(icoor[hh], idimensions[hh], mode); + if (cc > -1.0) { + /* find the filter location along this axis: */ + int start; + if (order & 1) { + start = (int)floor(cc) - order / 2; + } else { + start = (int)floor(cc + 0.5) - order / 2; + } + /* get the offset to the start of the filter: */ + offset += istrides[hh] * start; + if (start < 0 || start + order >= idimensions[hh]) { + /* implement border mapping, if outside border: */ + edge = 1; + edge_offsets[hh] = data_offsets[hh]; + for(ll = 0; ll <= order; ll++) { + int idx = start + ll; + int len = idimensions[hh]; + if (len <= 1) { + idx = 0; + } else { + int s2 = 2 * len - 2; + if (idx < 0) { + idx = s2 * (int)(-idx / s2) + idx; + idx = idx <= 1 - len ? idx + s2 : -idx; + } else if (idx >= len) { + idx -= s2 * (int)(idx / s2); + if (idx >= len) + idx = s2 - idx; + } + } + /* calculate and store the offests at this edge: */ + edge_offsets[hh][ll] = istrides[hh] * (idx - start); + } + } else { + /* we are not at the border, use precalculated offsets: */ + edge_offsets[hh] = NULL; + } + spline_coefficients(cc, order, splvals[hh]); + } else { + /* we use the constant border condition: */ + constant = 1; + break; + } + } + + if (!constant) { + maybelong *ff = fcoordinates; + for(hh = 0; hh < filter_size; hh++) { + int idx = 0; + if (edge) { + for(ll = 0; ll < irank; ll++) { + if (edge_offsets[ll]) + idx += edge_offsets[ll][ff[ll]]; + else + idx += ff[ll] * istrides[ll]; + } + } else { + idx = foffsets[hh]; + } + idx += offset; + idxs[hh] = idx; + ff += irank; + } + } + if (!constant) { + maybelong *ff = fcoordinates; + t = 0.0; + for(hh = 0; hh < filter_size; hh++) { + double coeff = 0.0; + switch(input->descr->type_num) { + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Bool); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt8); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt16); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt32); +#if HAS_UINT64 + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt64); +#endif + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int8); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int16); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int32); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int64); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float32); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + /* calculate the interpolated value: */ + for(ll = 0; ll < irank; ll++) + if (order > 0) + coeff *= splvals[ll][ff[ll]]; + t += coeff; + ff += irank; + } + } else { + t = cval; + } + /* store output value: */ + switch (output->descr->type_num) { + CASE_INTERP_OUT(po, t, Bool); + CASE_INTERP_OUT_UINT(po, t, UInt8, 0, MAX_UINT8); + CASE_INTERP_OUT_UINT(po, t, UInt16, 0, MAX_UINT16); + CASE_INTERP_OUT_UINT(po, t, UInt32, 0, MAX_UINT32); +#if HAS_UINT64 + /* FIXME */ + CASE_INTERP_OUT_UINT(po, t, UInt64, 0, MAX_UINT32); +#endif + CASE_INTERP_OUT_INT(po, t, Int8, MIN_INT8, MAX_INT8); + CASE_INTERP_OUT_INT(po, t, Int16, MIN_INT16, MAX_INT16); + CASE_INTERP_OUT_INT(po, t, Int32, MIN_INT32, MAX_INT32); + CASE_INTERP_OUT_INT(po, t, Int64, MIN_INT64, MAX_INT64); + CASE_INTERP_OUT(po, t, Float32); + CASE_INTERP_OUT(po, t, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + if (coordinates) { + NI_ITERATOR_NEXT2(io, ic, po, pc); + } else { + NI_ITERATOR_NEXT(io, po); + } + } + + exit: + if (edge_offsets) + free(edge_offsets); + if (data_offsets) { + for(jj = 0; jj < irank; jj++) + free(data_offsets[jj]); + free(data_offsets); + } + if (splvals) { + for(jj = 0; jj < irank; jj++) + free(splvals[jj]); + free(splvals); + } + if (foffsets) + free(foffsets); + if (fcoordinates) + free(fcoordinates); + if (idxs) + free(idxs); + return PyErr_Occurred() ? 0 : 1; +} + +int NI_ZoomShift(PyArrayObject *input, PyArrayObject* zoom_ar, + PyArrayObject* shift_ar, PyArrayObject *output, + int order, int mode, double cval) +{ + char *po, *pi; + maybelong **zeros = NULL, **offsets = NULL, ***edge_offsets = NULL; + maybelong ftmp[MAXDIM], *fcoordinates = NULL, *foffsets = NULL; + maybelong jj, hh, kk, filter_size, odimensions[MAXDIM]; + maybelong idimensions[MAXDIM], istrides[MAXDIM], *idxs = NULL; + maybelong size; + double ***splvals = NULL; + NI_Iterator io; + Float64 *zooms = zoom_ar ? (Float64*)PyArray_DATA(zoom_ar) : NULL; + Float64 *shifts = shift_ar ? (Float64*)PyArray_DATA(shift_ar) : NULL; + int rank = 0, qq; + + for(kk = 0; kk < input->nd; kk++) { + idimensions[kk] = input->dimensions[kk]; + istrides[kk] = input->strides[kk]; + odimensions[kk] = output->dimensions[kk]; + } + rank = input->nd; + + /* if the mode is 'constant' we need some temps later: */ + if (mode == NI_EXTEND_CONSTANT) { + zeros = (maybelong**)malloc(rank * sizeof(maybelong*)); + if (!zeros) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < rank; jj++) + zeros[jj] = NULL; + for(jj = 0; jj < rank; jj++) { + zeros[jj] = (maybelong*)malloc(odimensions[jj] * sizeof(maybelong)); + if(!zeros[jj]) { + PyErr_NoMemory(); + goto exit; + } + } + } + + /* store offsets, along each axis: */ + offsets = (maybelong**)malloc(rank * sizeof(maybelong*)); + /* store spline coefficients, along each axis: */ + splvals = (double***)malloc(rank * sizeof(double**)); + /* store offsets at all edges: */ + edge_offsets = (maybelong***)malloc(rank * sizeof(maybelong**)); + if (!offsets || !splvals || !edge_offsets) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < rank; jj++) { + offsets[jj] = NULL; + splvals[jj] = NULL; + edge_offsets[jj] = NULL; + } + for(jj = 0; jj < rank; jj++) { + offsets[jj] = (maybelong*)malloc(odimensions[jj] * sizeof(maybelong)); + splvals[jj] = (double**)malloc(odimensions[jj] * sizeof(double*)); + edge_offsets[jj] = (maybelong**)malloc(odimensions[jj] * sizeof(maybelong*)); + if (!offsets[jj] || !splvals[jj] || !edge_offsets[jj]) { + PyErr_NoMemory(); + goto exit; + } + for(hh = 0; hh < odimensions[jj]; hh++) { + splvals[jj][hh] = NULL; + edge_offsets[jj][hh] = NULL; + } + } + + /* precalculate offsets, and offsets at the edge: */ + for(jj = 0; jj < rank; jj++) { + double shift = 0.0, zoom = 0.0; + if (shifts) + shift = shifts[jj]; + if (zooms) + zoom = zooms[jj]; + for(kk = 0; kk < odimensions[jj]; kk++) { + double cc = (double)kk; + if (shifts) + cc += shift; + if (zooms) + cc *= zoom; + cc = map_coordinate(cc, idimensions[jj], mode); + if (cc > -1.0) { + int start; + if (zeros && zeros[jj]) + zeros[jj][kk] = 0; + if (order & 1) { + start = (int)floor(cc) - order / 2; + } else { + start = (int)floor(cc + 0.5) - order / 2; + } + offsets[jj][kk] = istrides[jj] * start; + if (start < 0 || start + order >= idimensions[jj]) { + edge_offsets[jj][kk] = (maybelong*)malloc((order + 1) * sizeof(maybelong)); + if (!edge_offsets[jj][kk]) { + PyErr_NoMemory(); + goto exit; + } + for(hh = 0; hh <= order; hh++) { + int idx = start + hh; + int len = idimensions[jj]; + if (len <= 1) { + idx = 0; + } else { + int s2 = 2 * len - 2; + if (idx < 0) { + idx = s2 * (int)(-idx / s2) + idx; + idx = idx <= 1 - len ? idx + s2 : -idx; + } else if (idx >= len) { + idx -= s2 * (int)(idx / s2); + if (idx >= len) + idx = s2 - idx; + } + } + edge_offsets[jj][kk][hh] = istrides[jj] * (idx - start); + } + } + if (order > 0) { + splvals[jj][kk] = (double*)malloc((order + 1) * sizeof(double)); + if (!splvals[jj][kk]) { + PyErr_NoMemory(); + goto exit; + } + spline_coefficients(cc, order, splvals[jj][kk]); + } + } else { + zeros[jj][kk] = 1; + } + } + } + + filter_size = 1; + for(jj = 0; jj < rank; jj++) + filter_size *= order + 1; + idxs = (maybelong*)malloc(filter_size * sizeof(idxs)); + if (!idxs) { + PyErr_NoMemory(); + goto exit; + } + + if (!NI_InitPointIterator(output, &io)) + goto exit; + + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + + /* store all coordinates and offsets with filter: */ + fcoordinates = (maybelong*)malloc(rank * filter_size * sizeof(maybelong)); + foffsets = (maybelong*)malloc(filter_size * sizeof(maybelong)); + if (!fcoordinates || !foffsets) { + PyErr_NoMemory(); + goto exit; + } + + for(jj = 0; jj < rank; jj++) + ftmp[jj] = 0; + kk = 0; + for(hh = 0; hh < filter_size; hh++) { + for(jj = 0; jj < rank; jj++) + fcoordinates[jj + hh * rank] = ftmp[jj]; + foffsets[hh] = kk; + for(jj = rank - 1; jj >= 0; jj--) { + if (ftmp[jj] < order) { + ftmp[jj]++; + kk += istrides[jj]; + break; + } else { + ftmp[jj] = 0; + kk -= istrides[jj] * order; + } + } + } + size = 1; + for(qq = 0; qq < output->nd; qq++) + size *= output->dimensions[qq]; + for(kk = 0; kk < size; kk++) { + double t = 0.0; + int edge = 0, oo = 0, zero = 0; + + for(hh = 0; hh < rank; hh++) { + if (zeros && zeros[hh][io.coordinates[hh]]) { + /* we use constant border condition */ + zero = 1; + break; + } + oo += offsets[hh][io.coordinates[hh]]; + if (edge_offsets[hh][io.coordinates[hh]]) + edge = 1; + } + + if (!zero) { + maybelong *ff = fcoordinates; + for(hh = 0; hh < filter_size; hh++) { + int idx = 0; + if (edge) { + /* use precalculated edge offsets: */ + for(jj = 0; jj < rank; jj++) { + if (edge_offsets[jj][io.coordinates[jj]]) + idx += edge_offsets[jj][io.coordinates[jj]][ff[jj]]; + else + idx += ff[jj] * istrides[jj]; + } + idx += oo; + } else { + /* use normal offsets: */ + idx += oo + foffsets[hh]; + } + idxs[hh] = idx; + ff += rank; + } + } + if (!zero) { + maybelong *ff = fcoordinates; + t = 0.0; + for(hh = 0; hh < filter_size; hh++) { + double coeff = 0.0; + switch(input->descr->type_num) { + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Bool); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt8); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt16); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt32); +#if HAS_UINT64 + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt64); +#endif + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int8); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int16); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int32); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int64); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float32); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + /* calculate interpolated value: */ + for(jj = 0; jj < rank; jj++) + if (order > 0) + coeff *= splvals[jj][io.coordinates[jj]][ff[jj]]; + t += coeff; + ff += rank; + } + } else { + t = cval; + } + /* store output: */ + switch (output->descr->type_num) { + CASE_INTERP_OUT(po, t, Bool); + CASE_INTERP_OUT_UINT(po, t, UInt8, 0, MAX_UINT8); + CASE_INTERP_OUT_UINT(po, t, UInt16, 0, MAX_UINT16); + CASE_INTERP_OUT_UINT(po, t, UInt32, 0, MAX_UINT32); +#if HAS_UINT64 + /* FIXME */ + CASE_INTERP_OUT_UINT(po, t, UInt64, 0, MAX_UINT32); +#endif + CASE_INTERP_OUT_INT(po, t, Int8, MIN_INT8, MAX_INT8); + CASE_INTERP_OUT_INT(po, t, Int16, MIN_INT16, MAX_INT16); + CASE_INTERP_OUT_INT(po, t, Int32, MIN_INT32, MAX_INT32); + CASE_INTERP_OUT_INT(po, t, Int64, MIN_INT64, MAX_INT64); + CASE_INTERP_OUT(po, t, Float32); + CASE_INTERP_OUT(po, t, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + NI_ITERATOR_NEXT(io, po); + } + + exit: + if (zeros) { + for(jj = 0; jj < rank; jj++) + if (zeros[jj]) + free(zeros[jj]); + free(zeros); + } + if (offsets) { + for(jj = 0; jj < rank; jj++) + if (offsets[jj]) + free(offsets[jj]); + free(offsets); + } + if (splvals) { + for(jj = 0; jj < rank; jj++) { + if (splvals[jj]) { + for(hh = 0; hh < odimensions[jj]; hh++) + if (splvals[jj][hh]) + free(splvals[jj][hh]); + free(splvals[jj]); + } + } + free(splvals); + } + if (edge_offsets) { + for(jj = 0; jj < rank; jj++) { + if (edge_offsets[jj]) { + for(hh = 0; hh < odimensions[jj]; hh++) + if (edge_offsets[jj][hh]) + free(edge_offsets[jj][hh]); + free(edge_offsets[jj]); + } + } + free(edge_offsets); + } + if (foffsets) + free(foffsets); + if (fcoordinates) + free(fcoordinates); + if (idxs) + free(idxs); + return PyErr_Occurred() ? 0 : 1; +} Added: branches/Interpolate1D/ndimage/ni_interpolation.h =================================================================== --- branches/Interpolate1D/ndimage/ni_interpolation.h 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/ni_interpolation.h 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,43 @@ +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NI_INTERPOLATION_H +#define NI_INTERPOLATION_H + +int NI_SplineFilter1D(PyArrayObject*, int, int, PyArrayObject*); +int NI_GeometricTransform(PyArrayObject*, int (*)(maybelong*, double*, int, int, + void*), void*, PyArrayObject*, PyArrayObject*, + PyArrayObject*, PyArrayObject*, int, int, + double); +int NI_ZoomShift(PyArrayObject*, PyArrayObject*, PyArrayObject*, + PyArrayObject*, int, int, double); + +#endif Added: branches/Interpolate1D/ndimage/ni_measure.c =================================================================== --- branches/Interpolate1D/ndimage/ni_measure.c 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/ni_measure.c 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,1197 @@ +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ni_support.h" +#include "ni_measure.h" +#include +#include +#include +#include + +typedef struct { + Int32 index1, index2; + void* next; +} _index_pair; + +#define CASE_LABEL(_p, _pi, _type) \ +case t ## _type: \ + *_p = *(_type*)_pi ? -1 : 0; \ + break + +int NI_Label(PyArrayObject* input, PyArrayObject* strct, + maybelong *max_label, PyArrayObject* output) +{ + int kk; + maybelong jj, ll, ssize, size, filter_size, *offsets = NULL; + maybelong mask_value, *oo; + Bool *ps, *footprint = NULL; + char *pi, *po; + Int32 index = 0, *index_map = NULL; + NI_FilterIterator fi; + NI_Iterator ii, io; + _index_pair *pairs = NULL; + + /* structure size */ + ssize = 1; + for(kk = 0; kk < strct->nd; kk++) + ssize *= strct->dimensions[kk]; + /* we only use the first half of the structure data, so we make a + temporary structure for use with the filter functions: */ + footprint = (Bool*)malloc(ssize * sizeof(Bool)); + if (!footprint) { + PyErr_NoMemory(); + goto exit; + } + ps = (Bool*)PyArray_DATA(strct); + filter_size = 0; + for(jj = 0; jj < ssize / 2; jj++) { + footprint[jj] = ps[jj]; + if (ps[jj]) + ++filter_size; + } + for(jj = ssize / 2; jj < ssize; jj++) + footprint[jj] = 0; + /* get data and size */ + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(kk = 0; kk < output->nd; kk++) + size *= output->dimensions[kk]; + if (!NI_InitPointIterator(input, &ii)) + goto exit; + if (!NI_InitPointIterator(output, &io)) + goto exit; + /* set all elements in the output corresponding to non-zero elements + in input to -1: */ + for(jj = 0; jj < size; jj++) { + Int32 *p = (Int32*)po; + switch (input->descr->type_num) { + CASE_LABEL(p, pi, Bool); + CASE_LABEL(p, pi, UInt8); + CASE_LABEL(p, pi, UInt16); + CASE_LABEL(p, pi, UInt32); +#if HAS_UINT64 + CASE_LABEL(p, pi, UInt64); +#endif + CASE_LABEL(p, pi, Int8); + CASE_LABEL(p, pi, Int16); + CASE_LABEL(p, pi, Int32); + CASE_LABEL(p, pi, Int64); + CASE_LABEL(p, pi, Float32); + CASE_LABEL(p, pi, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + NI_ITERATOR_NEXT2(ii, io, pi, po); + } + + /* calculate the filter offsets: */ + if (!NI_InitFilterOffsets(output, footprint, strct->dimensions, NULL, + NI_EXTEND_CONSTANT, &offsets, &mask_value, NULL)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(input->nd, strct->dimensions, filter_size, + input->dimensions, NULL, &fi)) + goto exit; + /* reset output iterator: */ + NI_ITERATOR_RESET(io); + po = (void *)PyArray_DATA(output); + /* iterator over the elements: */ + oo = offsets; + for(jj = 0; jj < size; jj++) { + if (*(Int32*)po < 0) { + Int32 neighbor = 0; + /* iterate over structuring element: */ + for(ll = 0; ll < filter_size; ll++) { + int offset = oo[ll]; + if (offset != mask_value) { + Int32 tt = *(Int32*)(po + offset); + if (tt > 0) { + /* this element is next to an already found object: */ + if (neighbor && neighbor != tt) { + /* we have two objects that must be merged later: */ + _index_pair* tp = (_index_pair*)malloc(sizeof(_index_pair)); + if (!tp) { + PyErr_NoMemory(); + goto exit; + } + tp->next = pairs; + /* the pairs must be ordered: */ + if (neighbor < tt) { + tp->index1 = neighbor; + tp->index2 = tt; + } else { + tp->index1 = tt; + tp->index2 = neighbor; + } + pairs = tp; + } else { + neighbor = tt; + } + } + } + } + if (neighbor) { + /* this point belongs to an existing object */ + *(Int32*)po = neighbor; + } else { + /* this may be a new object: */ + *(Int32*)po = ++index; + } + } + NI_FILTER_NEXT(fi, io, oo, po); + } + *max_label = index; + /* merge any touching objects: */ + if (pairs) { + Int32 counter; + index_map = (Int32*)malloc(index * sizeof(Int32)); + if (!index_map) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < index; jj++) + index_map[jj] = (Int32)jj; + while (pairs) { + Int32 idx1 = pairs->index1 - 1; + Int32 idx2 = pairs->index2 - 1; + if (index_map[idx2] == idx1 || index_map[idx2] == idx2) { + /* if this pair was already processed, or if idx2 was not + mapped yet, we delete this pair and map idx2 to idx1: */ + _index_pair *tp = pairs; + pairs = tp->next; + free(tp); + index_map[idx2] = idx1; + } else { + /* idx2 was already mapped, therefore we find what it was + mapped to and change the current pair to the result of that + and idx1. Since the pair is not destroyed, it will be + re-processed with the adapted values. */ + idx2 = index_map[idx2]; + /* keep the pairs ordered: */ + if (idx1 < idx2) { + pairs->index1 = idx1 + 1; + pairs->index2 = idx2 + 1; + } else { + pairs->index1 = idx2 + 1; + pairs->index2 = idx1 + 1; + } + } + } + for(jj = 0; jj < index; jj++) { + /* if the current index maps to a index that is also mapped, + change it to map to that index. Since an index always maps to + a lower index or to itself, this will make sure that at the + end all indices map to an unmapped index. */ + if (index_map[index_map[jj]] < index_map[jj]) + index_map[jj] = index_map[index_map[jj]]; + } + /* renumber the indices that are not mapped: */ + counter = 0; + for(jj = 0; jj < index; jj++) + if (index_map[jj] == jj) + index_map[jj] = ++counter; + else + index_map[jj] = index_map[index_map[jj]]; + } + + /* relabel the output if we merged some objects: */ + if (index_map) { + *max_label = 0; + NI_ITERATOR_RESET(io); + po = (void *)PyArray_DATA(output); + for(jj = 0; jj < size; jj++) { + Int32 p = *(Int32*)po; + if (p > 0 ) + *(Int32*)po = index_map[p - 1]; + if (*(Int32*)po > *max_label) + *max_label = *(Int32*)po; + NI_ITERATOR_NEXT(io, po); + } + } + exit: + if (offsets) free(offsets); + if (index_map) free(index_map); + while (pairs) { + _index_pair *tp = pairs; + pairs = (_index_pair*)pairs->next; + free(tp); + } + if (footprint) + free(footprint); + return PyErr_Occurred() ? 0 : 1; +} + +#define CASE_FIND_OBJECT_POINT(_pi, _regions, _rank, _dimensions, \ + _max_label, _ii, _type) \ +case t ## _type: \ +{ \ + int _kk; \ + maybelong _sindex = *(_type*)_pi - 1; \ + if (_sindex >= 0 && _sindex < _max_label) { \ + if (_rank > 0) { \ + _sindex *= 2 * _rank; \ + if (_regions[_sindex] < 0) { \ + for(_kk = 0; _kk < _rank; _kk++) { \ + maybelong _cc = _ii.coordinates[_kk]; \ + _regions[_sindex + _kk] = _cc; \ + _regions[_sindex + _kk + _rank] = _cc + 1; \ + } \ + } else { \ + for(_kk = 0; _kk < _rank; _kk++) { \ + maybelong _cc = _ii.coordinates[_kk]; \ + if (_cc < _regions[_sindex + _kk]) \ + _regions[_sindex + _kk] = _cc; \ + if (_cc + 1 > _regions[_sindex + _kk + _rank]) \ + _regions[_sindex + _kk + _rank] = _cc + 1; \ + } \ + } \ + } else { \ + _regions[_sindex] = 1; \ + } \ + } \ +} \ +break + +int NI_FindObjects(PyArrayObject* input, maybelong max_label, + maybelong* regions) +{ + int kk; + maybelong size, jj; + NI_Iterator ii; + char *pi; + + /* get input data, size and iterator: */ + pi = (void *)PyArray_DATA(input); + size = 1; + for(kk = 0; kk < input->nd; kk++) + size *= input->dimensions[kk]; + if (!NI_InitPointIterator(input, &ii)) + goto exit; + if (input->nd > 0) { + for(jj = 0; jj < 2 * input->nd * max_label; jj++) + regions[jj] = -1; + } else { + for(jj = 0; jj < max_label; jj++) + regions[jj] = -1; + } + /* iterate over all points: */ + for(jj = 0 ; jj < size; jj++) { + switch (input->descr->type_num) { + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, Bool); + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, UInt8); + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, UInt16); + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, UInt32); +#if HAS_UINT64 + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, UInt64); +#endif + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, Int8); + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, Int16); + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, Int32); + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, Int64); + break; + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + NI_ITERATOR_NEXT(ii, pi); + } + exit: + return PyErr_Occurred() ? 0 : 1; +} + + +/* macro to get input value: */ +#if HAS_UINT64 +#define NI_GET_VALUE(_pi, _v, _type) \ +{ \ + switch(_type) { \ + case tBool: \ + _v = (*(Bool*)_pi) != 0; \ + break; \ + case tUInt8: \ + _v = *(UInt8*)_pi; \ + break; \ + case tUInt16: \ + _v = *(UInt16*)_pi; \ + break; \ + case tUInt32: \ + _v = *(UInt32*)_pi; \ + break; \ + case tInt8: \ + _v = *(Int8*)_pi; \ + break; \ + case tInt16: \ + _v = *(Int16*)_pi; \ + break; \ + case tInt32: \ + _v = *(Int32*)_pi; \ + break; \ + case tInt64: \ + _v = *(Int64*)_pi; \ + break; \ + case tUInt64: \ + _v = *(UInt64*)_pi; \ + break; \ + case tFloat32: \ + _v = *(Float32*)_pi; \ + break; \ + case tFloat64: \ + _v = *(Float64*)_pi; \ + break; \ + default: \ + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); \ + return 0; \ + } \ +} +#else +#define NI_GET_VALUE(_pi, _v, _type) \ +{ \ + switch(_type) { \ + case tBool: \ + _v = (*(Bool*)_pi) != 0; \ + break; \ + case tUInt8: \ + _v = *(UInt8*)_pi; \ + break; \ + case tUInt16: \ + _v = *(UInt16*)_pi; \ + break; \ + case tUInt32: \ + _v = *(UInt32*)_pi; \ + break; \ + case tInt8: \ + _v = *(Int8*)_pi; \ + break; \ + case tInt16: \ + _v = *(Int16*)_pi; \ + break; \ + case tInt32: \ + _v = *(Int32*)_pi; \ + break; \ + case tInt64: \ + _v = *(Int64*)_pi; \ + break; \ + case tFloat32: \ + _v = *(Float32*)_pi; \ + break; \ + case tFloat64: \ + _v = *(Float64*)_pi; \ + break; \ + default: \ + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); \ + return 0; \ + } \ +} +#endif + +/* macro to get label value: */ +#if HAS_UINT64 +#define NI_GET_LABEL(_pm, _label, _type) \ +{ \ + if (_pm) { \ + switch(_type) { \ + case tBool: \ + _label = *(Bool*)_pm; \ + break; \ + case tUInt8: \ + _label = *(UInt8*)_pm; \ + break; \ + case tUInt16: \ + _label = *(UInt16*)_pm; \ + break; \ + case tUInt32: \ + _label = *(UInt32*)_pm; \ + break; \ + case tUInt64: \ + _label = *(UInt64*)_pm; \ + break; \ + case tInt8: \ + _label = *(Int8*)_pm; \ + break; \ + case tInt16: \ + _label = *(Int16*)_pm; \ + break; \ + case tInt32: \ + _label = *(Int32*)_pm; \ + break; \ + case tInt64: \ + _label = *(Int64*)_pm; \ + break; \ + case tFloat32: \ + _label = *(Float32*)_pm; \ + break; \ + case tFloat64: \ + _label = *(Float64*)_pm; \ + break; \ + default: \ + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); \ + return 0; \ + } \ + } \ +} +#else +#define NI_GET_LABEL(_pm, _label, _type) \ +{ \ + if (_pm) { \ + switch(_type) { \ + case tBool: \ + _label = *(Bool*)_pm; \ + break; \ + case tUInt8: \ + _label = *(UInt8*)_pm; \ + break; \ + case tUInt16: \ + _label = *(UInt16*)_pm; \ + break; \ + case tUInt32: \ + _label = *(UInt32*)_pm; \ + break; \ + case tInt8: \ + _label = *(Int8*)_pm; \ + break; \ + case tInt16: \ + _label = *(Int16*)_pm; \ + break; \ + case tInt32: \ + _label = *(Int32*)_pm; \ + break; \ + case tInt64: \ + _label = *(Int64*)_pm; \ + break; \ + case tFloat32: \ + _label = *(Float32*)_pm; \ + break; \ + case tFloat64: \ + _label = *(Float64*)_pm; \ + break; \ + default: \ + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); \ + return 0; \ + } \ + } \ +} +#endif + +int NI_Statistics(PyArrayObject *input, PyArrayObject *labels, + maybelong min_label, maybelong max_label, maybelong *indices, + maybelong n_results, double *sum, maybelong *total, double *variance, + double *minimum, double *maximum, maybelong* min_pos, maybelong* max_pos) +{ + char *pi = NULL, *pm = NULL; + NI_Iterator ii, mi; + maybelong jj, size, idx = 0, label = 1, doit = 1; + int qq; + + /* input iterator: */ + if (!NI_InitPointIterator(input, &ii)) + return 0; + /* input data: */ + pi = (void *)PyArray_DATA(input); + if (labels) { + if (!NI_InitPointIterator(labels, &mi)) + return 0; + pm = (void *)PyArray_DATA(labels); + } + /* input size: */ + size = 1; + for(qq = 0; qq < input->nd; qq++) + size *= input->dimensions[qq]; + for(jj = 0; jj < n_results; jj++) { + if (sum) + sum[jj] = 0.0; + if (total) + total[jj] = 0; + if (variance) + variance[jj] = 0; + if (minimum) + minimum[jj] = DBL_MAX; + if (maximum) + maximum[jj] = -DBL_MAX; + if (min_pos) + min_pos[jj] = 0; + if (max_pos) + max_pos[jj] = 0; + } + /* iterate over array: */ + for(jj = 0; jj < size; jj++) { + NI_GET_LABEL(pm, label, labels->descr->type_num); + if (min_label >= 0) { + if (label >= min_label && label <= max_label) { + idx = indices[label - min_label]; + doit = idx >= 0; + } else { + doit = 0; + } + } else { + doit = label != 0; + } + if (doit) { + double val; + NI_GET_VALUE(pi, val, input->descr->type_num); + if (sum) + sum[idx] += val; + if (total) + total[idx]++; + if (minimum && val < minimum[idx]) { + minimum[idx] = val; + if (min_pos) + min_pos[idx] = jj; + } + if (maximum && (val > maximum[idx])) { + maximum[idx] = val; + if (max_pos) + max_pos[idx] = jj; + } + } + if (labels) { + NI_ITERATOR_NEXT2(ii, mi, pi, pm); + } else { + NI_ITERATOR_NEXT(ii, pi); + } + } + if (minimum) { + for(jj = 0; jj < n_results; jj++) { + if (!(minimum[jj] < DBL_MAX)) + minimum[jj] = 0.0; + } + } + if (maximum) { + for(jj = 0; jj < n_results; jj++) { + if (!(maximum[jj] > -DBL_MAX)) + maximum[jj] = 0.0; + } + } + if (variance) { + int do_var = 0; + for(jj = 0; jj < n_results; jj++) + if (total[jj] > 1) { + do_var = 1; + break; + } + if (do_var) { + /* reset input iterator: */ + NI_ITERATOR_RESET(ii); + pi = (void *)PyArray_DATA(input); + if (labels) { + /* reset label iterator: */ + NI_ITERATOR_RESET(mi); + pm = (void *)PyArray_DATA(labels); + } + for(jj = 0; jj < size; jj++) { + NI_GET_LABEL(pm, label, labels->descr->type_num); + if (min_label >= 0) { + if (label >= min_label && label <= max_label) { + idx = indices[label - min_label]; + doit = idx >= 0; + } else { + doit = 0; + } + } else { + doit = label != 0; + } + if (doit) { + double val; + NI_GET_VALUE(pi, val, input->descr->type_num); + val = val - sum[idx] / total[idx]; + variance[idx] += val * val; + } + if (labels) { + NI_ITERATOR_NEXT2(ii, mi, pi, pm); + } else { + NI_ITERATOR_NEXT(ii, pi); + } + } + for(jj = 0; jj < n_results; jj++) + variance[jj] = (total[jj] > 1 ? + variance[jj] / (total[jj] - 1) : 0.0); + } + } + return 1; +} + + +int NI_CenterOfMass(PyArrayObject *input, PyArrayObject *labels, + maybelong min_label, maybelong max_label, maybelong *indices, + maybelong n_results, double *center_of_mass) +{ + char *pi = NULL, *pm = NULL; + NI_Iterator ii, mi; + maybelong jj, kk, size, idx = 0, label = 1, doit = 1; + double *sum = NULL; + int qq; + + /* input iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* input data: */ + pi = (void *)PyArray_DATA(input); + if (labels) { + if (!NI_InitPointIterator(labels, &mi)) + goto exit; + pm = (void *)PyArray_DATA(labels); + } + /* input size: */ + size = 1; + for(qq = 0; qq < input->nd; qq++) + size *= input->dimensions[qq]; + sum = (double*)malloc(n_results * sizeof(double)); + if (!sum) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < n_results; jj++) { + sum[jj] = 0.0; + for(kk = 0; kk < input->nd; kk++) + center_of_mass[jj * input->nd + kk] = 0.0; + } + /* iterate over array: */ + for(jj = 0; jj < size; jj++) { + NI_GET_LABEL(pm, label, labels->descr->type_num); + if (min_label >= 0) { + if (label >= min_label && label <= max_label) { + idx = indices[label - min_label]; + doit = idx >= 0; + } else { + doit = 0; + } + } else { + doit = label != 0; + } + if (doit) { + double val; + NI_GET_VALUE(pi, val, input->descr->type_num); + sum[idx] += val; + for(kk = 0; kk < input->nd; kk++) + center_of_mass[idx * input->nd + kk] += val * ii.coordinates[kk]; + } + if (labels) { + NI_ITERATOR_NEXT2(ii, mi, pi, pm); + } else { + NI_ITERATOR_NEXT(ii, pi); + } + } + for(jj = 0; jj < n_results; jj++) + for(kk = 0; kk < input->nd; kk++) + center_of_mass[jj * input->nd + kk] /= sum[jj]; + exit: + if (sum) + free(sum); + return PyErr_Occurred() == NULL; +} + + +int NI_Histogram(PyArrayObject *input, PyArrayObject *labels, + maybelong min_label, maybelong max_label, maybelong *indices, + maybelong n_results, PyArrayObject **histograms, + double min, double max, maybelong nbins) +{ + char *pi = NULL, *pm = NULL; + NI_Iterator ii, mi; + maybelong jj, kk, size, idx = 0, label = 1, doit = 1; + Int32 **ph = NULL; + double bsize; + int qq; + + /* input iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* input data: */ + pi = (void *)PyArray_DATA(input); + if (labels) { + if (!NI_InitPointIterator(labels, &mi)) + goto exit; + pm = (void *)PyArray_DATA(labels); + } + ph = (Int32**)malloc(n_results * sizeof(Int32*)); + if (!ph) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < n_results; jj++) { + ph[jj] = (Int32*)PyArray_DATA(histograms[jj]); + for(kk = 0; kk < nbins; kk++) + ph[jj][kk] = 0; + } + bsize = (max - min) / (double)nbins; + /* input size: */ + size = 1; + for(qq = 0; qq < input->nd; qq++) + size *= input->dimensions[qq]; + /* iterate over array: */ + for(jj = 0; jj < size; jj++) { + NI_GET_LABEL(pm, label, labels->descr->type_num); + if (min_label >= 0) { + if (label >= min_label && label <= max_label) { + idx = indices[label - min_label]; + doit = idx >= 0; + } else { + doit = 0; + } + } else { + doit = label != 0; + } + if (doit) { + int bin; + double val; + NI_GET_VALUE(pi, val, input->descr->type_num); + if (val >= min && val < max) { + bin = (int)((val - min) / bsize); + ++(ph[idx][bin]); + } + } + if (labels) { + NI_ITERATOR_NEXT2(ii, mi, pi, pm); + } else { + NI_ITERATOR_NEXT(ii, pi); + } + } + exit: + if (ph) + free(ph); + return PyErr_Occurred() == NULL; +} + +#define WS_GET_INDEX(_index, _c_strides, _b_strides, _rank, _out, \ + _contiguous, _type) \ +do { \ + if (_contiguous) { \ + _out = _index * sizeof(_type); \ + } else { \ + int _qq; \ + maybelong _cc, _idx = _index; \ + _out = 0; \ + for (_qq = 0; _qq < _rank; _qq++) { \ + _cc = _idx / _c_strides[_qq]; \ + _idx -= _cc * _c_strides[_qq]; \ + _out += _b_strides[_qq] * _cc; \ + } \ + } \ +} while(0) + +#define CASE_GET_INPUT(_ival, _pi, _type) \ +case t ## _type: \ + _ival = *((_type*)_pi); \ + break + +#define CASE_GET_LABEL(_label, _pm, _type) \ +case t ## _type: \ + _label = *(_type*)_pm; \ + break + +#define CASE_PUT_LABEL(_label, _pl, _type) \ +case t ## _type: \ + *((_type*)_pl) = _label; \ + break + +#define CASE_WINDEX1(_v_index, _p_index, _strides, _istrides, _irank, \ + _icont, _p_idx, _v_idx, _pi, _vval, _pval, _type) \ +case t ## _type: \ + WS_GET_INDEX(_v_index, _strides, _istrides, _irank, _p_idx, _icont, \ + _type); \ + WS_GET_INDEX(_p_index, _strides, _istrides, _irank, _v_idx, _icont, \ + _type); \ + _vval = *(_type*)(_pi + _v_idx); \ + _pval = *(_type*)(_pi + _p_idx); \ + break + +#define CASE_WINDEX2(_v_index, _strides, _ostrides, _irank, _idx, \ + _ocont, _label, _pl, _type) \ +case t ## _type: \ + WS_GET_INDEX(_v_index, _strides, _ostrides, _irank, _idx, \ + _ocont, _type); \ + _label = *(_type*)(_pl + _idx); \ + break + +#define CASE_WINDEX3(_p_index, _strides, _ostrides, _irank, _idx, \ + _ocont, _label, _pl, _type) \ +case t ## _type: \ + WS_GET_INDEX(_p_index, _strides, _ostrides, _irank, _idx, \ + _ocont, _type); \ + *(_type*)(_pl + _idx) = _label; \ +break + +#define DONE_TYPE UInt8 +#define COST_TYPE UInt16 +#define WS_MAXDIM 7 + +typedef struct { + maybelong index; + COST_TYPE cost; + void *next, *prev; + DONE_TYPE done; +} NI_WatershedElement; + +int NI_WatershedIFT(PyArrayObject* input, PyArrayObject* markers, + PyArrayObject* strct, PyArrayObject* output) +{ + char *pl, *pm, *pi; + int ll; + maybelong size, jj, hh, kk, maxval; + maybelong strides[WS_MAXDIM], coordinates[WS_MAXDIM]; + maybelong *nstrides = NULL, nneigh, ssize; + int i_contiguous, o_contiguous; + NI_WatershedElement *temp = NULL, **first = NULL, **last = NULL; + Bool *ps = NULL; + NI_Iterator mi, ii, li; + + i_contiguous = PyArray_ISCONTIGUOUS(input); + o_contiguous = PyArray_ISCONTIGUOUS(output); + ssize = 1; + for(ll = 0; ll < strct->nd; ll++) + ssize *= strct->dimensions[ll]; + if (input->nd > WS_MAXDIM) { + PyErr_SetString(PyExc_RuntimeError, "too many dimensions"); + goto exit; + } + size = 1; + for(ll = 0; ll < input->nd; ll++) + size *= input->dimensions[ll]; + /* Storage for the temporary queue data. */ + temp = (NI_WatershedElement*)malloc(size * sizeof(NI_WatershedElement)); + if (!temp) { + PyErr_NoMemory(); + goto exit; + } + pi = (void *)PyArray_DATA(input); + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* Initialization and find the maximum of the input. */ + maxval = 0; + for(jj = 0; jj < size; jj++) { + int ival = 0; + switch(input->descr->type_num) { + CASE_GET_INPUT(ival, pi, UInt8); + CASE_GET_INPUT(ival, pi, UInt16); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + temp[jj].index = jj; + temp[jj].done = 0; + if (ival > maxval) + maxval = ival; + NI_ITERATOR_NEXT(ii, pi); + } + pi = (void *)PyArray_DATA(input); + /* Allocate and initialize the storage for the queue. */ + first = (NI_WatershedElement**)malloc((maxval + 1) * + sizeof(NI_WatershedElement*)); + last = (NI_WatershedElement**)malloc((maxval + 1) * + sizeof(NI_WatershedElement*)); + if (!first || !last) { + PyErr_NoMemory(); + goto exit; + } + for(hh = 0; hh <= maxval; hh++) { + first[hh] = NULL; + last[hh] = NULL; + } + if (!NI_InitPointIterator(markers, &mi)) + goto exit; + if (!NI_InitPointIterator(output, &li)) + goto exit; + pm = (void *)PyArray_DATA(markers); + pl = (void *)PyArray_DATA(output); + /* initialize all nodes */ + for(ll = 0; ll < input->nd; ll++) + coordinates[ll] = 0; + for(jj = 0; jj < size; jj++) { + /* get marker */ + int label = 0; + switch(markers->descr->type_num) { + CASE_GET_LABEL(label, pm, UInt8); + CASE_GET_LABEL(label, pm, UInt16); + CASE_GET_LABEL(label, pm, UInt32); +#if HAS_UINT64 + CASE_GET_LABEL(label, pm, UInt64); +#endif + CASE_GET_LABEL(label, pm, Int8); + CASE_GET_LABEL(label, pm, Int16); + CASE_GET_LABEL(label, pm, Int32); + CASE_GET_LABEL(label, pm, Int64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + switch(output->descr->type_num) { + CASE_PUT_LABEL(label, pl, UInt8); + CASE_PUT_LABEL(label, pl, UInt16); + CASE_PUT_LABEL(label, pl, UInt32); +#if HAS_UINT64 + CASE_PUT_LABEL(label, pl, UInt64); +#endif + CASE_PUT_LABEL(label, pl, Int8); + CASE_PUT_LABEL(label, pl, Int16); + CASE_PUT_LABEL(label, pl, Int32); + CASE_PUT_LABEL(label, pl, Int64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + NI_ITERATOR_NEXT2(mi, li, pm, pl); + if (label != 0) { + /* This node is a marker */ + temp[jj].cost = 0; + if (!first[0]) { + first[0] = &(temp[jj]); + first[0]->next = NULL; + first[0]->prev = NULL; + last[0] = first[0]; + } else { + if (label > 0) { + /* object markers are enqueued at the beginning, so they are + processed first. */ + temp[jj].next = first[0]; + temp[jj].prev = NULL; + first[0]->prev = &(temp[jj]); + first[0] = &(temp[jj]); + } else { + /* background markers are enqueued at the end, so they are + processed after the object markers. */ + temp[jj].next = NULL; + temp[jj].prev = last[0]; + last[0]->next = &(temp[jj]); + last[0] = &(temp[jj]); + } + } + } else { + /* This node is not a marker */ + temp[jj].cost = maxval + 1; + temp[jj].next = NULL; + temp[jj].prev = NULL; + } + for(ll = input->nd - 1; ll >= 0; ll--) + if (coordinates[ll] < input->dimensions[ll] - 1) { + coordinates[ll]++; + break; + } else { + coordinates[ll] = 0; + } + } + + pl = (void *)PyArray_DATA(output); + ps = (Bool*)PyArray_DATA(strct); + nneigh = 0; + for (kk = 0; kk < ssize; kk++) + if (ps[kk] && kk != (ssize / 2)) + ++nneigh; + nstrides = (maybelong*)malloc(nneigh * sizeof(maybelong)); + if (!nstrides) { + PyErr_NoMemory(); + goto exit; + } + strides[input->nd - 1] = 1; + for(ll = input->nd - 2; ll >= 0; ll--) + strides[ll] = input->dimensions[ll + 1] * strides[ll + 1]; + for(ll = 0; ll < input->nd; ll++) + coordinates[ll] = -1; + for(kk = 0; kk < nneigh; kk++) + nstrides[kk] = 0; + jj = 0; + for(kk = 0; kk < ssize; kk++) { + if (ps[kk]) { + int offset = 0; + for(ll = 0; ll < input->nd; ll++) + offset += coordinates[ll] * strides[ll]; + if (offset != 0) + nstrides[jj++] += offset; + } + for(ll = input->nd - 1; ll >= 0; ll--) + if (coordinates[ll] < 1) { + coordinates[ll]++; + break; + } else { + coordinates[ll] = -1; + } + } + /* Propagation phase: */ + for(jj = 0; jj <= maxval; jj++) { + while (first[jj]) { + /* dequeue first element: */ + NI_WatershedElement *v = first[jj]; + first[jj] = first[jj]->next; + if (first[jj]) + first[jj]->prev = NULL; + v->prev = NULL; + v->next = NULL; + /* Mark element as done: */ + v->done = 1; + /* Iterate over the neighbors of the element: */ + for(hh = 0; hh < nneigh; hh++) { + maybelong v_index = v->index, p_index = v->index, idx, cc; + int qq, outside = 0; + p_index += nstrides[hh]; + /* check if the neighbor is within the extent of the array: */ + idx = p_index; + for (qq = 0; qq < input->nd; qq++) { + cc = idx / strides[qq]; + if (cc < 0 || cc >= input->dimensions[qq]) { + outside = 1; + break; + } + idx -= cc * strides[qq]; + } + if (!outside) { + NI_WatershedElement *p = &(temp[p_index]); + if (!(p->done)) { + /* If the neighbor was not processed yet: */ + int max, pval, vval, wvp, pcost, label, p_idx, v_idx; + switch(input->descr->type_num) { + CASE_WINDEX1(v_index, p_index, strides, input->strides, + input->nd, i_contiguous, p_idx, v_idx, pi, + vval, pval, UInt8); + CASE_WINDEX1(v_index, p_index, strides, input->strides, + input->nd, i_contiguous, p_idx, v_idx, pi, + vval, pval, UInt16); + default: + PyErr_SetString(PyExc_RuntimeError, + "data type not supported"); + goto exit; + } + /* Calculate cost: */ + wvp = pval - vval; + if (wvp < 0) + wvp = -wvp; + /* Find the maximum of this cost and the current + element cost: */ + pcost = p->cost; + max = v->cost > wvp ? v->cost : wvp; + if (max < pcost) { + /* If this maximum is less than the neighbors cost, + adapt the cost and the label of the neighbor: */ + int idx; + p->cost = max; + switch(output->descr->type_num) { + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt8); + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt16); + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt32); +#if HAS_UINT64 + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt64); +#endif + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int8); + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int16); + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int32); + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int64); + default: + PyErr_SetString(PyExc_RuntimeError, + "data type not supported"); + goto exit; + } + switch(output->descr->type_num) { + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt8); + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt16); + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt32); +#if HAS_UINT64 + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt64); +#endif + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int8); + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int16); + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int32); + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int64); + default: + PyErr_SetString(PyExc_RuntimeError, + "data type not supported"); + goto exit; + } + /* If the neighbor is in a queue, remove it: */ + if (p->next || p->prev) { + NI_WatershedElement *prev = p->prev, *next = p->next; + if (first[pcost] == p) + first[pcost] = next; + if (last[pcost] == p) + last[pcost] = prev; + if (prev) + prev->next = next; + if (next) + next->prev = prev; + } + /* Insert the neighbor in the appropiate queue: */ + if (label < 0) { + p->prev = last[max]; + p->next = NULL; + if (last[max]) + last[max]->next = p; + last[max] = p; + if (!first[max]) + first[max] = p; + } else { + p->next = first[max]; + p->prev = NULL; + if (first[max]) + first[max]->prev = p; + first[max] = p; + if (!last[max]) + last[max] = p; + } + } + } + } + } + } + } + exit: + if (temp) + free(temp); + if (first) + free(first); + if (last) + free(last); + if (nstrides) + free(nstrides); + return PyErr_Occurred() ? 0 : 1; +} Added: branches/Interpolate1D/ndimage/ni_measure.h =================================================================== --- branches/Interpolate1D/ndimage/ni_measure.h 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/ni_measure.h 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,59 @@ +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NI_MEASURE_H +#define NI_MEASURE_H + +#include "nd_image.h" + +/* structure for array regions to find objects: */ +typedef struct { + int start[NI_MAXDIM], end[NI_MAXDIM]; +} NI_ObjectRegion; + +int NI_Label(PyArrayObject*, PyArrayObject*, maybelong*, PyArrayObject*); + +int NI_FindObjects(PyArrayObject*, maybelong, maybelong*); + +int NI_CenterOfMass(PyArrayObject*, PyArrayObject*, maybelong, maybelong, + maybelong*, maybelong, double*); + +int NI_Histogram(PyArrayObject*, PyArrayObject*, maybelong, maybelong, + maybelong*, maybelong, PyArrayObject**, double, double, maybelong); + +int NI_Statistics(PyArrayObject*, PyArrayObject*, maybelong, maybelong, + maybelong*, maybelong, double*, maybelong*, double*, + double*, double*, maybelong*, maybelong*); + +int NI_WatershedIFT(PyArrayObject*, PyArrayObject*, PyArrayObject*, + PyArrayObject*); + +#endif Added: branches/Interpolate1D/ndimage/ni_morphology.c =================================================================== --- branches/Interpolate1D/ndimage/ni_morphology.c 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/ni_morphology.c 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,955 @@ +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ni_support.h" +#include "ni_morphology.h" +#include +#include +#include +#include + +#define LIST_SIZE 100000 + +#define CASE_GET_MASK(_msk_value, _pm, _type) \ +case t ## _type: \ + _msk_value = *(_type*)_pm ? 1 : 0; \ + break + +#define CASE_OUTPUT(_po, _out, _type) \ +case t ## _type: \ + *(_type*)_po = (_type)_out; \ + break + +#define CASE_NI_ERODE_POINT(_pi, _out, _offsets, _filter_size, _type, \ + _mv, _border_value, _bv, _center_is_true,\ + _true, _false, _changed) \ +case t ## _type: \ +{ \ + maybelong _ii, _oo; \ + int _in = *(_type*)_pi ? 1 : 0; \ + if (_mv) { \ + if (_center_is_true && _in == false) { \ + _changed = 0; \ + _out = _in; \ + } else { \ + _out = _true; \ + for(_ii = 0; _ii < _filter_size; _ii++) { \ + _oo = _offsets[_ii]; \ + if (_oo == _bv) { \ + if (!_border_value) { \ + _out = _false; \ + break; \ + } \ + } else { \ + int _nn = *(_type*)(_pi + _oo) ? _true : _false; \ + if (!_nn) { \ + _out = _false; \ + break; \ + } \ + } \ + } \ + _changed = _out != _in; \ + } \ + } else { \ + _out = _in; \ + } \ +} \ +break + +int NI_BinaryErosion(PyArrayObject* input, PyArrayObject* strct, + PyArrayObject* mask, PyArrayObject* output, int bdr_value, + maybelong *origins, int invert, int center_is_true, int* changed, + NI_CoordinateList **coordinate_list) +{ + maybelong struct_size = 0, *offsets = NULL, size, *oo, jj; + maybelong ssize, block_size = 0, *current = NULL, border_flag_value; + int kk, true, false, msk_value; + NI_Iterator ii, io, mi; + NI_FilterIterator fi; + Bool *ps, out = 0; + char *pi, *po, *pm = NULL; + NI_CoordinateBlock *block = NULL; + + ps = (Bool*)PyArray_DATA(strct); + ssize = 1; + for(kk = 0; kk < strct->nd; kk++) + ssize *= strct->dimensions[kk]; + for(jj = 0; jj < ssize; jj++) + if (ps[jj]) ++struct_size; + if (mask) { + if (!NI_InitPointIterator(mask, &mi)) + return 0; + pm = (void *)PyArray_DATA(mask); + } + /* calculate the filter offsets: */ + if (!NI_InitFilterOffsets(input, ps, strct->dimensions, origins, + NI_EXTEND_CONSTANT, &offsets, &border_flag_value, NULL)) + goto exit; + /* initialize input element iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* initialize output element iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(input->nd, strct->dimensions, struct_size, + input->dimensions, origins, &fi)) + goto exit; + + /* get data pointers an size: */ + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(kk = 0; kk < input->nd; kk++) + size *= input->dimensions[kk]; + if (invert) { + bdr_value = bdr_value ? 0 : 1; + true = 0; + false = 1; + } else { + bdr_value = bdr_value ? 1 : 0; + true = 1; + false = 0; + } + if (coordinate_list) { + block_size = LIST_SIZE / input->nd / sizeof(int); + if (block_size < 1) + block_size = 1; + if (block_size > size) + block_size = size; + *coordinate_list = NI_InitCoordinateList(block_size, input->nd); + if (!*coordinate_list) + goto exit; + } + /* iterator over the elements: */ + oo = offsets; + *changed = 0; + msk_value = 1; + for(jj = 0; jj < size; jj++) { + int pchange = 0; + if (mask) { + switch(mask->descr->type_num) { + CASE_GET_MASK(msk_value, pm, Bool); + CASE_GET_MASK(msk_value, pm, UInt8); + CASE_GET_MASK(msk_value, pm, UInt16); + CASE_GET_MASK(msk_value, pm, UInt32); +#if HAS_UINT64 + CASE_GET_MASK(msk_value, pm, UInt64); +#endif + CASE_GET_MASK(msk_value, pm, Int8); + CASE_GET_MASK(msk_value, pm, Int16); + CASE_GET_MASK(msk_value, pm, Int32); + CASE_GET_MASK(msk_value, pm, Int64); + CASE_GET_MASK(msk_value, pm, Float32); + CASE_GET_MASK(msk_value, pm, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + return 0; + } + } + switch (input->descr->type_num) { + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Bool, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, UInt8, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, UInt16, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, UInt32, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); +#if HAS_UINT64 + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, UInt64, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); +#endif + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Int8, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Int16, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Int32, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Int64, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Float32, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Float64, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_OUTPUT(po, out, Bool); + CASE_OUTPUT(po, out, UInt8); + CASE_OUTPUT(po, out, UInt16); + CASE_OUTPUT(po, out, UInt32); +#if HAS_UINT64 + CASE_OUTPUT(po, out, UInt64); +#endif + CASE_OUTPUT(po, out, Int8); + CASE_OUTPUT(po, out, Int16); + CASE_OUTPUT(po, out, Int32); + CASE_OUTPUT(po, out, Int64); + CASE_OUTPUT(po, out, Float32); + CASE_OUTPUT(po, out, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + if (pchange) { + *changed = 1; + if (coordinate_list) { + if (block == NULL || block->size == block_size) { + block = NI_CoordinateListAddBlock(*coordinate_list); + current = block->coordinates; + } + for(kk = 0; kk < input->nd; kk++) + *current++ = ii.coordinates[kk]; + block->size++; + } + } + if (mask) { + NI_FILTER_NEXT3(fi, ii, io, mi, oo, pi, po, pm); + } else { + NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); + } + } + + exit: + if (offsets) + free(offsets); + if (PyErr_Occurred()) { + if (coordinate_list) { + NI_FreeCoordinateList(*coordinate_list); + *coordinate_list = NULL; + } + return 0; + } else { + return 1; + } + return PyErr_Occurred() ? 0 : 1; +} + +#define CASE_ERODE_POINT2(_struct_size, _offsets, _coordinate_offsets, \ + _pi, _oo, _irank, _list1, _list2, \ + _current_coors1, _current_coors2, _block1, \ + _block2, _bf_value, _true, _false, _type, \ + _mklist) \ +case t ## _type: \ +{ \ + maybelong _hh, _kk; \ + for(_hh = 0; _hh < _struct_size; _hh++) { \ + maybelong _to = _offsets[_oo + _hh]; \ + if (_to != _bf_value && *(_type*)(_pi + _to) == _true) { \ + if (_mklist) { \ + maybelong *_tc = &(_coordinate_offsets[(_oo + _hh) * _irank]); \ + if (_block2 == NULL || _block2->size == _list2->block_size) { \ + _block2 = NI_CoordinateListAddBlock(_list2); \ + _current_coors2 = _block2->coordinates; \ + } \ + for(_kk = 0; _kk < _irank; _kk++) \ + *_current_coors2++ = _current_coors1[_kk] + _tc[_kk]; \ + _block2->size++; \ + } \ + *(_type*)(_pi + _to) = _false; \ + } \ + } \ +} \ +break + +int NI_BinaryErosion2(PyArrayObject* array, PyArrayObject* strct, + PyArrayObject* mask, int niter, maybelong *origins, + int invert, NI_CoordinateList **iclist) +{ + maybelong struct_size = 0, *offsets = NULL, oo, jj, ssize; + maybelong *coordinate_offsets = NULL, size = 0; + maybelong *current_coordinates1 = NULL, *current_coordinates2 = NULL; + maybelong kk, border_flag_value, current = 0; + int true, false; + NI_Iterator ii, mi; + NI_FilterIterator fi, ci; + Bool *ps; + char *pi, *ibase, *pm = NULL; + NI_CoordinateBlock *block1 = NULL, *block2 = NULL; + NI_CoordinateList *list1 = NULL, *list2 = NULL; + + ps = (Bool*)PyArray_DATA(strct); + ssize = 1; + for(kk = 0; kk < strct->nd; kk++) + ssize *= strct->dimensions[kk]; + for(jj = 0; jj < ssize; jj++) + if (ps[jj]) ++struct_size; + + /* calculate the filter offsets: */ + if (!NI_InitFilterOffsets(array, ps, strct->dimensions, origins, + NI_EXTEND_CONSTANT, &offsets, + &border_flag_value, &coordinate_offsets)) + goto exit; + + /* initialize input element iterator: */ + if (!NI_InitPointIterator(array, &ii)) + goto exit; + + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(array->nd, strct->dimensions, struct_size, + array->dimensions, origins, &fi)) + goto exit; + if (!NI_InitFilterIterator(array->nd, strct->dimensions, + struct_size * array->nd, array->dimensions, + origins, &ci)) + goto exit; + + /* get data pointers and size: */ + ibase = pi = (void *)PyArray_DATA(array); + + if (invert) { + true = 0; + false = 1; + } else { + true = 1; + false = 0; + } + + if (mask) { + /* iterator, data pointer and type of mask array: */ + if (!NI_InitPointIterator(mask, &mi)) + return 0; + pm = (void *)PyArray_DATA(mask); + + size = 1; + for(kk = 0; kk < array->nd; kk++) + size *= array->dimensions[kk]; + + for(jj = 0; jj < size; jj++) { + if (*(Int8*)pm) { + *(Int8*)pm = -1; + } else { + *(Int8*)pm = (Int8)*(Bool*)pi; + *(Bool*)pi = false; + } + NI_ITERATOR_NEXT2(ii, mi, pi, pm) + } + NI_ITERATOR_RESET(ii) + pi = (void *)PyArray_DATA(array); + } + + list1 = NI_InitCoordinateList((*iclist)->block_size, (*iclist)->rank); + list2 = NI_InitCoordinateList((*iclist)->block_size, (*iclist)->rank); + if (!list1 || !list2) + goto exit; + if (NI_CoordinateListStealBlocks(list2, *iclist)) + goto exit; + block2 = list2->blocks; + jj = 0; + while(block1 || block2) { + int mklist = 1; + if (!block1) { + if (niter <= 0 || jj < niter) { + if (NI_CoordinateListStealBlocks(list1, list2)) + goto exit; + block1 = list1->blocks; + block2 = NULL; + current_coordinates1 = block1->coordinates; + current = 0; + ++jj; + mklist = niter <= 0 || jj < niter; + } else { + break; + } + } + NI_ITERATOR_GOTO(ii, current_coordinates1, ibase, pi); + NI_FILTER_GOTO(fi, ii, 0, oo); + + switch (array->descr->type_num) { + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, Bool, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, UInt8, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, UInt16, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, UInt32, mklist); +#if HAS_UINT64 + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, UInt64, mklist); +#endif + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, Int8, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, Int16, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, Int32, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, Int64, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, Float32, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, Float64, mklist); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + + ++current; + if (current == block1->size) { + block1 = NI_CoordinateListDeleteBlock(list1); + if (block1) { + current_coordinates1 = block1->coordinates; + current = 0; + } + } else { + current_coordinates1 += array->nd; + } + } + + if (mask) { + NI_ITERATOR_RESET(ii) + NI_ITERATOR_RESET(mi) + pi = (void *)PyArray_DATA(array); + pm = (void *)PyArray_DATA(mask); + for(jj = 0; jj < size; jj++) { + int value = *(Int8*)pm; + if (value >= 0) + *(Bool*)pi = value; + NI_ITERATOR_NEXT2(ii, mi, pi, pm) + } + } + + exit: + if (offsets) + free(offsets); + if (coordinate_offsets) + free(coordinate_offsets); + NI_FreeCoordinateList(list1); + NI_FreeCoordinateList(list2); + if (PyErr_Occurred()) { + return 0; + } else { + return 1; + } + return PyErr_Occurred() ? 0 : 1; +} + + +#define NI_DISTANCE_EUCLIDIAN 1 +#define NI_DISTANCE_CITY_BLOCK 2 +#define NI_DISTANCE_CHESSBOARD 3 + +typedef struct { + maybelong *coordinates; + maybelong index; + void *next; +} NI_BorderElement; + +int NI_DistanceTransformBruteForce(PyArrayObject* input, int metric, + PyArrayObject *sampling_arr, + PyArrayObject* distances, + PyArrayObject* features) +{ + maybelong size, jj, min_index = 0; + int kk; + NI_BorderElement *border_elements = NULL, *temp; + NI_Iterator ii, di, fi; + char *pi, *pd = NULL, *pf = NULL; + Float64 *sampling = sampling_arr ? (void *)PyArray_DATA(sampling_arr) : NULL; + + /* check the output arrays: */ + if (distances) { + pd = (void *)PyArray_DATA(distances); + if (!NI_InitPointIterator(distances, &di)) + goto exit; + } + + if (features) { + pf = (void *)PyArray_DATA(features); + if (!NI_InitPointIterator(features, &fi)) + goto exit; + } + + size = 1; + for(kk = 0; kk < input->nd; kk++) + size *= input->dimensions[kk]; + pi = (void *)PyArray_DATA(input); + + if (!NI_InitPointIterator(input, &ii)) + goto exit; + + for(jj = 0; jj < size; jj++) { + if (*(Int8*)pi < 0) { + temp = (NI_BorderElement*)malloc(sizeof(NI_BorderElement)); + if (!temp) { + PyErr_NoMemory(); + goto exit; + } + temp->next = border_elements; + border_elements = temp; + temp->index = jj; + temp->coordinates = (maybelong*)malloc(input->nd * sizeof(maybelong)); + for(kk = 0; kk < input->nd; kk++) + temp->coordinates[kk] = ii.coordinates[kk]; + } + NI_ITERATOR_NEXT(ii, pi); + } + + NI_ITERATOR_RESET(ii); + pi = (void *)PyArray_DATA(input); + + switch(metric) { + case NI_DISTANCE_EUCLIDIAN: + for(jj = 0; jj < size; jj++) { + if (*(Int8*)pi > 0) { + double distance = DBL_MAX; + temp = border_elements; + while(temp) { + double d = 0.0, t; + for(kk = 0; kk < input->nd; kk++) { + t = ii.coordinates[kk] - temp->coordinates[kk]; + if (sampling) + t *= sampling[kk]; + d += t * t; + } + if (d < distance) { + distance = d; + if (features) + min_index = temp->index; + } + temp = temp->next; + } + if (distances) + *(Float64*)pd = sqrt(distance); + if (features) + *(Int32*)pf = min_index; + } else { + if (distances) + *(Float64*)pd = 0.0; + if (features) + *(Int32*)pf = jj; + } + if (features && distances) { + NI_ITERATOR_NEXT3(ii, di, fi, pi, pd, pf); + } else if (distances) { + NI_ITERATOR_NEXT2(ii, di, pi, pd); + } else { + NI_ITERATOR_NEXT2(ii, fi, pi, pf); + } + } + break; + case NI_DISTANCE_CITY_BLOCK: + case NI_DISTANCE_CHESSBOARD: + for(jj = 0; jj < size; jj++) { + if (*(Int8*)pi > 0) { + unsigned long distance = ULONG_MAX; + temp = border_elements; + while(temp) { + unsigned int d = 0; + maybelong t; + for(kk = 0; kk < input->nd; kk++) { + t = ii.coordinates[kk] - temp->coordinates[kk]; + if (t < 0) + t = -t; + if (metric == NI_DISTANCE_CITY_BLOCK) { + d += t; + } else { + if ((unsigned int)t > d) + d = t; + } + } + if (d < distance) { + distance = d; + if (features) + min_index = temp->index; + } + temp = temp->next; + } + if (distances) + *(UInt32*)pd = distance; + if (features) + *(Int32*)pf = min_index; + } else { + if (distances) + *(UInt32*)pd = 0; + if (features) + *(Int32*)pf = jj; + } + if (features && distances) { + NI_ITERATOR_NEXT3(ii, di, fi, pi, pd, pf); + } else if (distances) { + NI_ITERATOR_NEXT2(ii, di, pi, pd); + } else { + NI_ITERATOR_NEXT2(ii, fi, pi, pf); + } + } + break; + default: + PyErr_SetString(PyExc_RuntimeError, "distance metric not supported"); + goto exit; + } + + exit: + while (border_elements) { + temp = border_elements; + border_elements = border_elements->next; + if (temp->coordinates) + free(temp->coordinates); + free(temp); + } + return PyErr_Occurred() ? 0 : 1; +} + + +int NI_DistanceTransformOnePass(PyArrayObject *strct, + PyArrayObject* distances, PyArrayObject *features) +{ + int kk; + maybelong jj, ii, ssize, size, filter_size, mask_value, *oo; + maybelong *foffsets = NULL, *foo = NULL, *offsets = NULL; + Bool *ps, *pf = NULL, *footprint = NULL; + char *pd; + NI_FilterIterator si, ti; + NI_Iterator di, fi; + + ssize = 1; + for(kk = 0; kk < strct->nd; kk++) + ssize *= strct->dimensions[kk]; + + /* we only use the first half of the structure data, so we make a + temporary structure for use with the filter functions: */ + footprint = (Bool*)malloc(ssize * sizeof(Bool)); + if (!footprint) { + PyErr_NoMemory(); + goto exit; + } + ps = (Bool*)PyArray_DATA(strct); + filter_size = 0; + for(jj = 0; jj < ssize / 2; jj++) { + footprint[jj] = ps[jj]; + if (ps[jj]) + ++filter_size; + } + for(jj = ssize / 2; jj < ssize; jj++) + footprint[jj] = 0; + /* get data and size */ + pd = (void *)PyArray_DATA(distances); + size = 1; + for(kk = 0; kk < distances->nd; kk++) + size *= distances->dimensions[kk]; + if (!NI_InitPointIterator(distances, &di)) + goto exit; + /* calculate the filter offsets: */ + if (!NI_InitFilterOffsets(distances, footprint, strct->dimensions, NULL, + NI_EXTEND_CONSTANT, &offsets, &mask_value, NULL)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(distances->nd, strct->dimensions, + filter_size, distances->dimensions, NULL, &si)) + goto exit; + + if (features) { + maybelong dummy; + /* initialize point iterator: */ + pf = (void *)PyArray_DATA(features); + if (!NI_InitPointIterator(features, &fi)) + goto exit; + /* calculate the filter offsets: */ + if (!NI_InitFilterOffsets(features, footprint, strct->dimensions, + NULL, NI_EXTEND_CONSTANT, &foffsets, &dummy, NULL)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(distances->nd, strct->dimensions, + filter_size, distances->dimensions, NULL, &ti)) + goto exit; + } + /* iterator over the elements: */ + oo = offsets; + if (features) + foo = foffsets; + for(jj = 0; jj < size; jj++) { + Int32 value = *(Int32*)pd; + if (value != 0) { + Int32 min = value; + maybelong min_offset = 0; + /* iterate over structuring element: */ + for(ii = 0; ii < filter_size; ii++) { + maybelong offset = oo[ii]; + Int32 tt = -1; + if (offset < mask_value) + tt = *(Int32*)(pd + offset); + if (tt >= 0) { + if ((min < 0) || (tt + 1 < min)) { + min = tt + 1; + if (features) + min_offset = foo[ii]; + } + } + } + *(Int32*)pd = min; + if (features) + *(Int32*)pf = *(Int32*)(pf + min_offset); + } + if (features) { + NI_FILTER_NEXT(ti, fi, foo, pf); + } + NI_FILTER_NEXT(si, di, oo, pd); + } + + exit: + if (offsets) free(offsets); + if (foffsets) free(foffsets); + if (footprint) + free(footprint); + return PyErr_Occurred() ? 0 : 1; +} + +static void _VoronoiFT(char *pf, maybelong len, maybelong *coor, int rank, + int d, maybelong stride, maybelong cstride, + maybelong **f, maybelong *g, Float64 *sampling) +{ + maybelong l = -1, ii, maxl, idx1, idx2; + int jj; + + for(ii = 0; ii < len; ii++) + for(jj = 0; jj < rank; jj++) + f[ii][jj] = *(Int32*)(pf + ii * stride + cstride * jj); + for(ii = 0; ii < len; ii++) { + if (*(Int32*)(pf + ii * stride) >= 0) { + double fd = f[ii][d]; + double wR = 0.0; + for(jj = 0; jj < rank; jj++) { + if (jj != d) { + double tw = f[ii][jj] - coor[jj]; + if (sampling) + tw *= sampling[jj]; + wR += tw * tw; + } + } + while(l >= 1) { + double a, b, c, uR = 0.0, vR = 0.0, f1; + idx1 = g[l]; + f1 = f[idx1][d]; + idx2 = g[l - 1]; + a = f1 - f[idx2][d]; + b = fd - f1; + if (sampling) { + a *= sampling[d]; + b *= sampling[d]; + } + c = a + b; + for(jj = 0; jj < rank; jj++) { + if (jj != d) { + double cc = coor[jj]; + double tu = f[idx2][jj] - cc; + double tv = f[idx1][jj] - cc; + if (sampling) { + tu *= sampling[jj]; + tv *= sampling[jj]; + } + uR += tu * tu; + vR += tv * tv; + } + } + if (c * vR - b * uR - a * wR - a * b * c <= 0.0) + break; + --l; + } + ++l; + g[l] = ii; + } + } + maxl = l; + if (maxl >= 0) { + l = 0; + for (ii = 0; ii < len; ii++) { + double delta1 = 0.0, t; + for(jj = 0; jj < rank; jj++) { + t = jj == d ? f[g[l]][jj] - ii : f[g[l]][jj] - coor[jj]; + if (sampling) + t *= sampling[jj]; + delta1 += t * t; + } + while (l < maxl) { + double delta2 = 0.0; + for(jj = 0; jj < rank; jj++) { + t = jj == d ? f[g[l + 1]][jj] - ii : f[g[l + 1]][jj] - coor[jj]; + if (sampling) + t *= sampling[jj]; + delta2 += t * t; + } + if (delta1 <= delta2) + break; + delta1 = delta2; + ++l; + } + idx1 = g[l]; + for(jj = 0; jj < rank; jj++) + *(Int32*)(pf + ii * stride + jj * cstride) = f[idx1][jj]; + } + } +} + + +/* Recursive feature transform */ +static void _ComputeFT(char *pi, char *pf, maybelong *ishape, + maybelong *istrides, maybelong *fstrides, int rank, + int d, maybelong *coor, maybelong **f, maybelong *g, + PyArrayObject *features, Float64 *sampling) +{ + int kk; + maybelong jj; + + if (d == 0) { + char *tf1 = pf; + for(jj = 0; jj < ishape[0]; jj++) { + if (*(Int8*)pi) { + *(Int32*)tf1 = -1; + } else { + char *tf2 = tf1; + *(Int32*)tf2 = jj; + for(kk = 1; kk < rank; kk++) { + tf2 += fstrides[0]; + *(Int32*)tf2 = coor[kk]; + } + } + pi += istrides[0]; + tf1 += fstrides[1]; + } + _VoronoiFT(pf, ishape[0], coor, rank, 0, fstrides[1], fstrides[0], f, + g, sampling); + } else { + UInt32 axes = 0; + char *tf = pf; + maybelong size = 1; + NI_Iterator ii; + + for(jj = 0; jj < ishape[d]; jj++) { + coor[d] = jj; + _ComputeFT(pi, tf, ishape, istrides, fstrides, rank, d - 1, coor, f, + g, features, sampling); + pi += istrides[d]; + tf += fstrides[d + 1]; + } + + for(jj = 0; jj < d; jj++) { + axes |= (UInt32)1 << (jj + 1); + size *= ishape[jj]; + } + NI_InitPointIterator(features, &ii); + NI_SubspaceIterator(&ii, axes); + tf = pf; + for(jj = 0; jj < size; jj++) { + for(kk = 0; kk < d; kk++) + coor[kk] = ii.coordinates[kk]; + _VoronoiFT(tf, ishape[d], coor, rank, d, fstrides[d + 1], + fstrides[0], f, g, sampling); + NI_ITERATOR_NEXT(ii, tf); + } + for(kk = 0; kk < d; kk++) + coor[kk] = 0; + } +} + +/* Exact euclidean feature transform, as described in: C. R. Maurer, + Jr., R. Qi, V. Raghavan, "A linear time algorithm for computing + exact euclidean distance transforms of binary images in arbitrary + dimensions. IEEE Trans. PAMI 25, 265-270, 2003. */ +int NI_EuclideanFeatureTransform(PyArrayObject* input, + PyArrayObject *sampling_arr, + PyArrayObject* features) +{ + int ii; + maybelong coor[NI_MAXDIM], mx = 0, jj; + maybelong *tmp = NULL, **f = NULL, *g = NULL; + char *pi, *pf; + Float64 *sampling = sampling_arr ? ((void *)PyArray_DATA(sampling_arr)) : NULL; + + pi = (void *)PyArray_DATA(input); + pf = (void *)PyArray_DATA(features); + for(ii = 0; ii < input->nd; ii++) { + coor[ii] = 0; + if (input->dimensions[ii] > mx) + mx = input->dimensions[ii]; + } + + /* Some temporaries */ + f = (maybelong**)malloc(mx * sizeof(maybelong*)); + g = (maybelong*)malloc(mx * sizeof(maybelong)); + tmp = (maybelong*)malloc(mx * input->nd * sizeof(maybelong)); + if (!f || !g || !tmp) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < mx; jj++) + f[jj] = tmp + jj * input->nd; + + /* First call of recursive feature transform */ + _ComputeFT(pi, pf, input->dimensions, input->strides, features->strides, + input->nd, input->nd - 1, coor, f, g, features, sampling); + + exit: + if (f) + free(f); + if (g) + free(g); + if (tmp) + free(tmp); + + return PyErr_Occurred() ? 0 : 1; +} Added: branches/Interpolate1D/ndimage/ni_morphology.h =================================================================== --- branches/Interpolate1D/ndimage/ni_morphology.h 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/ni_morphology.h 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,46 @@ +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NI_MORPHOLOGY_H +#define NI_MORPHOLOGY_H + +int NI_BinaryErosion(PyArrayObject*, PyArrayObject*, PyArrayObject*, + PyArrayObject*, int, maybelong*, int, int, int*, NI_CoordinateList**); +int NI_BinaryErosion2(PyArrayObject*, PyArrayObject*, PyArrayObject*, + int, maybelong*, int, NI_CoordinateList**); +int NI_DistanceTransformBruteForce(PyArrayObject*, int, PyArrayObject*, + PyArrayObject*, PyArrayObject*); +int NI_DistanceTransformOnePass(PyArrayObject*, PyArrayObject *, + PyArrayObject*); +int NI_EuclideanFeatureTransform(PyArrayObject*, PyArrayObject*, + PyArrayObject*); + +#endif Added: branches/Interpolate1D/ndimage/ni_support.c =================================================================== --- branches/Interpolate1D/ndimage/ni_support.c 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/ni_support.c 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,751 @@ +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ni_support.h" + +/* initialize iterations over single array elements: */ +int NI_InitPointIterator(PyArrayObject *array, NI_Iterator *iterator) +{ + int ii; + + iterator->rank_m1 = array->nd - 1; + for(ii = 0; ii < array->nd; ii++) { + /* adapt dimensions for use in the macros: */ + iterator->dimensions[ii] = array->dimensions[ii] - 1; + /* initialize coordinates: */ + iterator->coordinates[ii] = 0; + /* initialize strides: */ + iterator->strides[ii] = array->strides[ii]; + /* calculate the strides to move back at the end of an axis: */ + iterator->backstrides[ii] = + array->strides[ii] * iterator->dimensions[ii]; + } + return 1; +} + + +/* initialize iteration over a lower sub-space: */ +int NI_SubspaceIterator(NI_Iterator *iterator, UInt32 axes) +{ + int ii, last = 0; + + for(ii = 0; ii <= iterator->rank_m1; ii++) { + if (axes & (((UInt32)1) << ii)) { + if (last != ii) { + iterator->dimensions[last] = iterator->dimensions[ii]; + iterator->strides[last] = iterator->strides[ii]; + iterator->backstrides[last] = iterator->backstrides[ii]; + } + ++last; + } + } + iterator->rank_m1 = last - 1; + return 1; +} + +/* initialize iteration over array lines: */ +int NI_LineIterator(NI_Iterator *iterator, int axis) +{ + UInt32 axes = ((UInt32)1) << axis; + return NI_SubspaceIterator(iterator, ~axes); +} + + +/******************************************************************/ +/* Line buffers */ +/******************************************************************/ + +/* Allocate line buffer data */ +int NI_AllocateLineBuffer(PyArrayObject* array, int axis, maybelong size1, + maybelong size2, maybelong *lines, maybelong max_size, double **buffer) +{ + maybelong line_size, max_lines; + int ii; + + /* the number of lines of the array is an upper limit for the + number of lines in the buffer: */ + max_lines = 1; + for(ii = 0; ii < array->nd; ii++) + max_lines *= array->dimensions[ii]; + if (array->nd > 0 && array->dimensions[axis] > 0) + max_lines /= array->dimensions[axis]; + /* calculate the space needed for one line, including space to + support the boundary conditions: */ + line_size = sizeof(double) * (array->dimensions[axis] + size1 + size2); + /* if *lines < 1, no number of lines is proposed, so we calculate it + from the maximum size allowed: */ + if (*lines < 1) { + *lines = line_size > 0 ? max_size / line_size : 0; + if (*lines < 1) + *lines = 1; + } + /* no need to allocate too many lines: */ + if (*lines > max_lines) + *lines = max_lines; + /* allocate data for the buffer: */ + *buffer = (double*)malloc(*lines * line_size); + if (!*buffer) { + PyErr_NoMemory(); + return 0; + } + return 1; +} + +/* Initialize a line buffer */ +int NI_InitLineBuffer(PyArrayObject *array, int axis, maybelong size1, + maybelong size2, maybelong buffer_lines, double *buffer_data, + NI_ExtendMode extend_mode, double extend_value, NI_LineBuffer *buffer) +{ + maybelong line_length = 0, array_lines = 0, size; + int ii; + + size = 1; + for(ii = 0; ii < array->nd; ii++) + size *= array->dimensions[ii]; + /* check if the buffer is big enough: */ + if (size > 0 && buffer_lines < 1) { + PyErr_SetString(PyExc_RuntimeError, "buffer too small"); + return 0; + } + /* Initialize a line iterator to move over the array: */ + if (!NI_InitPointIterator(array, &(buffer->iterator))) + return 0; + if (!NI_LineIterator(&(buffer->iterator), axis)) + return 0; + line_length = array->nd > 0 ? array->dimensions[axis] : 1; + if (line_length > 0) + array_lines = line_length > 0 ? size / line_length : 1; + /* initialize the buffer structure: */ + buffer->array_data = (void *)PyArray_DATA(array); + buffer->buffer_data = buffer_data; + buffer->buffer_lines = buffer_lines; + buffer->array_type = array->descr->type_num; + buffer->array_lines = array_lines; + buffer->next_line = 0; + buffer->size1 = size1; + buffer->size2 = size2; + buffer->line_length = line_length; + buffer->line_stride = array->nd > 0 ? array->strides[axis] : 0; + buffer->extend_mode = extend_mode; + buffer->extend_value = extend_value; + return 1; +} + +/* Extend a line in memory to implement boundary conditions: */ +int NI_ExtendLine(double *line, maybelong length, maybelong size1, + maybelong size2, NI_ExtendMode mode, double constant_value) +{ + maybelong ii, jj, length1, nextend, rextend; + double *l1, *l2, *l3, val; + + switch (mode) { + case NI_EXTEND_WRAP: + nextend = size1 / length; + rextend = size1 - nextend * length; + l1 = line + size1 + length - rextend; + l2 = line; + for(ii = 0; ii < rextend; ii++) + *l2++ = *l1++; + for(ii = 0; ii < nextend; ii++) { + l1 = line + size1; + for(jj = 0; jj < length; jj++) + *l2++ = *l1++; + } + nextend = size2 / length; + rextend = size2 - nextend * length; + l1 = line + size1; + l2 = line + size1 + length; + for(ii = 0; ii < nextend; ii++) { + l3 = l1; + for(jj = 0; jj < length; jj++) + *l2++ = *l3++; + } + for(ii = 0; ii < rextend; ii++) + *l2++ = *l1++; + break; + case NI_EXTEND_MIRROR: + if (length == 1) { + l1 = line; + val = line[size1]; + for(ii = 0; ii < size1; ii++) + *l1++ = val; + l1 = line + size1 + length; + val = line[size1 + length - 1]; + for(ii = 0; ii < size2; ii++) + *l1++ = val; + } else { + length1 = length - 1; + nextend = size1 / length1; + rextend = size1 - nextend * length1; + l1 = line + size1 + 1; + l2 = l1 - 2; + for(ii = 0; ii < nextend; ii++) { + l3 = l1; + for(jj = 0; jj < length1; jj++) + *l2-- = *l3++; + l1 -= length1; + } + for(ii = 0; ii < rextend; ii++) + *l2-- = *l1++; + nextend = size2 / length1; + rextend = size2 - nextend * length1; + l1 = line + size1 + length1 - 1; + l2 = l1 + 2; + for(ii = 0; ii < nextend; ii++) { + l3 = l1; + for(jj = 0; jj < length1; jj++) + *l2++ = *l3--; + l1 += length1; + } + for(ii = 0; ii < rextend; ii++) + *l2++ = *l1--; + } + break; + case NI_EXTEND_REFLECT: + nextend = size1 / length; + rextend = size1 - nextend * length; + l1 = line + size1; + l2 = l1 - 1; + for(ii = 0; ii < nextend; ii++) { + l3 = l1; + for(jj = 0; jj < length; jj++) + *l2-- = *l3++; + l1 -= length; + } + l3 = l1; + for(ii = 0; ii < rextend; ii++) + *l2-- = *l3++; + nextend = size2 / length; + rextend = size2 - nextend * length; + l1 = line + size1 + length - 1; + l2 = l1 + 1; + for(ii = 0; ii < nextend; ii++) { + l3 = l1; + for(jj = 0; jj < length; jj++) + *l2++ = *l3--; + l1 += length; + } + for(ii = 0; ii < rextend; ii++) + *l2++ = *l1--; + break; + case NI_EXTEND_NEAREST: + l1 = line; + val = line[size1]; + for(ii = 0; ii < size1; ii++) + *l1++ = val; + l1 = line + size1 + length; + val = line[size1 + length - 1]; + for(ii = 0; ii < size2; ii++) + *l1++ = val; + break; + case NI_EXTEND_CONSTANT: + l1 = line; + for(ii = 0; ii < size1; ii++) + *l1++ = constant_value; + l1 = line + size1 + length; + for(ii = 0; ii < size2; ii++) + *l1++ = constant_value; + break; + default: + PyErr_SetString(PyExc_RuntimeError, "mode not supported"); + return 0; + } + return 1; +} + + +#define CASE_COPY_DATA_TO_LINE(_pi, _po, _length, _stride, _type) \ +case t ## _type: \ +{ \ + maybelong _ii; \ + for(_ii = 0; _ii < _length; _ii++) { \ + _po[_ii] = (double)*(_type*)_pi; \ + _pi += _stride; \ + } \ +} \ +break + + +/* Copy a line from an array to a buffer: */ +int NI_ArrayToLineBuffer(NI_LineBuffer *buffer, + maybelong *number_of_lines, int *more) +{ + double *pb = buffer->buffer_data; + char *pa; + maybelong length = buffer->line_length; + + pb += buffer->size1; + *number_of_lines = 0; + /* fill until all lines in the array have been processed, or until + the buffer is full: */ + while (buffer->next_line < buffer->array_lines && + *number_of_lines < buffer->buffer_lines) { + pa = buffer->array_data; + /* copy the data from the array to the buffer: */ + switch (buffer->array_type) { + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Bool); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, UInt8); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, UInt16); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, UInt32); +#if HAS_UINT64 + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, UInt64); +#endif + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Int8); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Int16); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Int32); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Int64); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Float32); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Float64); + default: + PyErr_Format(PyExc_RuntimeError, "array type %d not supported", buffer->array_type); + return 0; + } + /* goto next line in the array: */ + NI_ITERATOR_NEXT(buffer->iterator, buffer->array_data); + /* implement boundary conditions to the line: */ + if (buffer->size1 + buffer->size2 > 0) + if (!NI_ExtendLine(pb - buffer->size1, length, buffer->size1, + buffer->size2, buffer->extend_mode, + buffer->extend_value)) + return 0; + /* The number of the array lines copied: */ + ++(buffer->next_line); + /* keep track of (and return) the number of lines in the buffer: */ + ++(*number_of_lines); + pb += buffer->line_length + buffer->size1 + buffer->size2; + } + /* if not all array lines were processed, *more is set true: */ + *more = buffer->next_line < buffer->array_lines; + return 1; +} + +#define CASE_COPY_LINE_TO_DATA(_pi, _po, _length, _stride, _type) \ +case t ## _type: \ +{ \ + maybelong _ii; \ + for(_ii = 0; _ii < _length; _ii++) { \ + *(_type*)_po = (_type)_pi[_ii]; \ + _po += _stride; \ + } \ +} \ +break + +/* Copy a line from a buffer to an array: */ +int NI_LineBufferToArray(NI_LineBuffer *buffer) +{ + double *pb = buffer->buffer_data; + char *pa; + maybelong jj, length = buffer->line_length; + + pb += buffer->size1; + for(jj = 0; jj < buffer->buffer_lines; jj++) { + /* if all array lines are copied return: */ + if (buffer->next_line == buffer->array_lines) + break; + pa = buffer->array_data; + /* copy data from the buffer to the array: */ + switch (buffer->array_type) { + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Bool); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, UInt8); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, UInt16); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, UInt32); +#if HAS_UINT64 + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, UInt64); +#endif + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Int8); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Int16); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Int32); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Int64); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Float32); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + return 0; + } + /* move to the next line in the array: */ + NI_ITERATOR_NEXT(buffer->iterator, buffer->array_data); + /* number of lines copied: */ + ++(buffer->next_line); + /* move the buffer data pointer to the next line: */ + pb += buffer->line_length + buffer->size1 + buffer->size2; + } + return 1; +} + +/******************************************************************/ +/* Multi-dimensional filter support functions */ +/******************************************************************/ + +/* Initialize a filter iterator: */ +int +NI_InitFilterIterator(int rank, maybelong *filter_shape, + maybelong filter_size, maybelong *array_shape, + maybelong *origins, NI_FilterIterator *iterator) +{ + int ii; + maybelong fshape[MAXDIM], forigins[MAXDIM]; + + for(ii = 0; ii < rank; ii++) { + fshape[ii] = *filter_shape++; + forigins[ii] = origins ? *origins++ : 0; + } + /* calculate the strides, used to move the offsets pointer through + the offsets table: */ + if (rank > 0) { + iterator->strides[rank - 1] = filter_size; + for(ii = rank - 2; ii >= 0; ii--) { + maybelong step = array_shape[ii + 1] < fshape[ii + 1] ? + array_shape[ii + 1] : fshape[ii + 1]; + iterator->strides[ii] = iterator->strides[ii + 1] * step; + } + } + for(ii = 0; ii < rank; ii++) { + maybelong step = array_shape[ii] < fshape[ii] ? + array_shape[ii] : fshape[ii]; + maybelong orgn = fshape[ii] / 2 + forigins[ii]; + /* stride for stepping back to previous offsets: */ + iterator->backstrides[ii] = (step - 1) * iterator->strides[ii]; + /* initialize boundary extension sizes: */ + iterator->bound1[ii] = orgn; + iterator->bound2[ii] = array_shape[ii] - fshape[ii] + orgn; + } + return 1; +} + +/* Calculate the offsets to the filter points, for all border regions and + the interior of the array: */ +int NI_InitFilterOffsets(PyArrayObject *array, Bool *footprint, + maybelong *filter_shape, maybelong* origins, + NI_ExtendMode mode, maybelong **offsets, maybelong *border_flag_value, + maybelong **coordinate_offsets) +{ + int rank, ii; + maybelong kk, ll, filter_size = 1, offsets_size = 1, max_size = 0; + maybelong max_stride = 0, *ashape = NULL, *astrides = NULL; + maybelong footprint_size = 0, coordinates[MAXDIM], position[MAXDIM]; + maybelong fshape[MAXDIM], forigins[MAXDIM], *po, *pc = NULL; + + rank = array->nd; + ashape = array->dimensions; + astrides = array->strides; + for(ii = 0; ii < rank; ii++) { + fshape[ii] = *filter_shape++; + forigins[ii] = origins ? *origins++ : 0.0; + } + /* the size of the footprint array: */ + for(ii = 0; ii < rank; ii++) + filter_size *= fshape[ii]; + /* calculate the number of non-zero elements in the footprint: */ + if (footprint) { + for(kk = 0; kk < filter_size; kk++) + if (footprint[kk]) + ++footprint_size; + } else { + footprint_size = filter_size; + } + /* calculate how many sets of offsets must be stored: */ + for(ii = 0; ii < rank; ii++) + offsets_size *= (ashape[ii] < fshape[ii] ? ashape[ii] : fshape[ii]); + /* allocate offsets data: */ + *offsets = (maybelong*)malloc(offsets_size * footprint_size * + sizeof(maybelong)); + if (!*offsets) { + PyErr_NoMemory(); + goto exit; + } + if (coordinate_offsets) { + *coordinate_offsets = (maybelong*)malloc(offsets_size * rank * + footprint_size * sizeof(maybelong)); + if (!*coordinate_offsets) { + PyErr_NoMemory(); + goto exit; + } + } + for(ii = 0; ii < rank; ii++) { + maybelong stride; + /* find maximum axis size: */ + if (ashape[ii] > max_size) + max_size = ashape[ii]; + /* find maximum stride: */ + stride = astrides[ii] < 0 ? -astrides[ii] : astrides[ii]; + if (stride > max_stride) + max_stride = stride; + /* coordinates for iterating over the kernel elements: */ + coordinates[ii] = 0; + /* keep track of the kernel position: */ + position[ii] = 0; + } + /* the flag to indicate that we are outside the border must have a + value that is larger than any possible offset: */ + *border_flag_value = max_size * max_stride + 1; + /* calculate all possible offsets to elements in the filter kernel, + for all regions in the array (interior and border regions): */ + po = *offsets; + if (coordinate_offsets) { + pc = *coordinate_offsets; + } + /* iterate over all regions: */ + for(ll = 0; ll < offsets_size; ll++) { + /* iterate over the elements in the footprint array: */ + for(kk = 0; kk < filter_size; kk++) { + maybelong offset = 0; + /* only calculate an offset if the footprint is 1: */ + if (!footprint || footprint[kk]) { + /* find offsets along all axes: */ + for(ii = 0; ii < rank; ii++) { + maybelong orgn = fshape[ii] / 2 + forigins[ii]; + maybelong cc = coordinates[ii] - orgn + position[ii]; + maybelong len = ashape[ii]; + /* apply boundary conditions, if necessary: */ + switch (mode) { + case NI_EXTEND_MIRROR: + if (cc < 0) { + if (len <= 1) { + cc = 0; + } else { + int sz2 = 2 * len - 2; + cc = sz2 * (int)(-cc / sz2) + cc; + cc = cc <= 1 - len ? cc + sz2 : -cc; + } + } else if (cc >= len) { + if (len <= 1) { + cc = 0; + } else { + int sz2 = 2 * len - 2; + cc -= sz2 * (int)(cc / sz2); + if (cc >= len) + cc = sz2 - cc; + } + } + break; + case NI_EXTEND_REFLECT: + if (cc < 0) { + if (len <= 1) { + cc = 0; + } else { + int sz2 = 2 * len; + if (cc < -sz2) + cc = sz2 * (int)(-cc / sz2) + cc; + cc = cc < -len ? cc + sz2 : -cc - 1; + } + } else if (cc >= len) { + if (len <= 1) {cc = 0; + } else { + int sz2 = 2 * len; + cc -= sz2 * (int)(cc / sz2); + if (cc >= len) + cc = sz2 - cc - 1; + } + } + break; + case NI_EXTEND_WRAP: + if (cc < 0) { + if (len <= 1) { + cc = 0; + } else { + int sz = len; + cc += sz * (int)(-cc / sz); + if (cc < 0) + cc += sz; + } + } else if (cc >= len) { + if (len <= 1) { + cc = 0; + } else { + int sz = len; + cc -= sz * (int)(cc / sz); + } + } + break; + case NI_EXTEND_NEAREST: + if (cc < 0) { + cc = 0; + } else if (cc >= len) { + cc = len - 1; + } + break; + case NI_EXTEND_CONSTANT: + if (cc < 0 || cc >= len) + cc = *border_flag_value; + break; + default: + PyErr_SetString(PyExc_RuntimeError, + "boundary mode not supported"); + goto exit; + } + + /* calculate offset along current axis: */ + if (cc == *border_flag_value) { + /* just flag that we are outside the border */ + offset = *border_flag_value; + if (coordinate_offsets) + pc[ii] = 0; + break; + } else { + /* use an offset that is possibly mapped from outside the + border: */ + cc = cc - position[ii]; + offset += astrides[ii] * cc; + if (coordinate_offsets) + pc[ii] = cc; + } + } + /* store the offset */ + *po++ = offset; + if (coordinate_offsets) + pc += rank; + } + /* next point in the filter: */ + for(ii = rank - 1; ii >= 0; ii--) { + if (coordinates[ii] < fshape[ii] - 1) { + coordinates[ii]++; + break; + } else { + coordinates[ii] = 0; + } + } + } + + /* move to the next array region: */ + for(ii = rank - 1; ii >= 0; ii--) { + int orgn = fshape[ii] / 2 + forigins[ii]; + if (position[ii] == orgn) { + position[ii] += ashape[ii] - fshape[ii] + 1; + if (position[ii] <= orgn) + position[ii] = orgn + 1; + } else { + position[ii]++; + } + if (position[ii] < ashape[ii]) { + break; + } else { + position[ii] = 0; + } + } + } + + exit: + if (PyErr_Occurred()) { + if (*offsets) + free(*offsets); + if (coordinate_offsets && *coordinate_offsets) + free(*coordinate_offsets); + return 0; + } else { + return 1; + } +} + +NI_CoordinateList* NI_InitCoordinateList(int size, int rank) +{ + NI_CoordinateList *list = \ + (NI_CoordinateList*)malloc(sizeof(NI_CoordinateList)); + if (!list) { + PyErr_NoMemory(); + return NULL; + } + list->block_size = size; + list->rank = rank; + list->blocks = NULL; + return list; +} + +int NI_CoordinateListStealBlocks(NI_CoordinateList *list1, + NI_CoordinateList *list2) +{ + if (list1->block_size != list2->block_size || + list1->rank != list2->rank) { + PyErr_SetString(PyExc_RuntimeError, "coordinate lists not compatible"); + return 1; + } + if (list1->blocks) { + PyErr_SetString(PyExc_RuntimeError, "first is list not empty"); + return 1; + } + list1->blocks = list2->blocks; + list2->blocks = NULL; + return 0; +} + +NI_CoordinateBlock* NI_CoordinateListAddBlock(NI_CoordinateList *list) +{ + NI_CoordinateBlock* block = NULL; + block = (NI_CoordinateBlock*)malloc(sizeof(NI_CoordinateBlock)); + if (!block) { + PyErr_NoMemory(); + goto exit; + } + block->coordinates = (maybelong*)malloc(list->block_size * list->rank * + sizeof(maybelong)); + if (!block->coordinates) { + PyErr_NoMemory(); + goto exit; + } + block->next = list->blocks; + list->blocks = block; + block->size = 0; + +exit: + if (PyErr_Occurred()) { + if (block) + free(block); + return NULL; + } + return block; +} + +NI_CoordinateBlock* NI_CoordinateListDeleteBlock(NI_CoordinateList *list) +{ + NI_CoordinateBlock* block = list->blocks; + if (block) { + list->blocks = block->next; + if (block->coordinates) + free(block->coordinates); + free(block); + } + return list->blocks; +} + +void NI_FreeCoordinateList(NI_CoordinateList *list) +{ + if (list) { + NI_CoordinateBlock *block = list->blocks; + while (block) { + NI_CoordinateBlock *tmp = block; + block = block->next; + if (tmp->coordinates) + free(tmp->coordinates); + free(tmp); + } + list->blocks = NULL; + free(list); + } +} Added: branches/Interpolate1D/ndimage/ni_support.h =================================================================== --- branches/Interpolate1D/ndimage/ni_support.h 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/ni_support.h 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,323 @@ +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NI_SUPPORT_H +#define NI_SUPPORT_H + +#include "nd_image.h" +#include +#include +#include +#include + +/* The different boundary conditions. The mirror condition is not used + by the python code, but C code is kept around in case we might wish + to add it. */ +typedef enum { + NI_EXTEND_FIRST = 0, + NI_EXTEND_NEAREST = 0, + NI_EXTEND_WRAP = 1, + NI_EXTEND_REFLECT = 2, + NI_EXTEND_MIRROR = 3, + NI_EXTEND_CONSTANT = 4, + NI_EXTEND_LAST = NI_EXTEND_CONSTANT, + NI_EXTEND_DEFAULT = NI_EXTEND_MIRROR +} NI_ExtendMode; + +/******************************************************************/ +/* Iterators */ +/******************************************************************/ + +/******************************************************************/ +/* Iterators */ +/******************************************************************/ + +/* the iterator structure: */ +typedef struct { + int rank_m1; + maybelong dimensions[MAXDIM]; + maybelong coordinates[MAXDIM]; + maybelong strides[MAXDIM]; + maybelong backstrides[MAXDIM]; +} NI_Iterator; + +/* initialize iterations over single array elements: */ +int NI_InitPointIterator(PyArrayObject*, NI_Iterator*); + +/* initialize iterations over an arbritrary sub-space: */ +int NI_SubspaceIterator(NI_Iterator*, UInt32); + +/* initialize iteration over array lines: */ +int NI_LineIterator(NI_Iterator*, int); + +/* reset an iterator */ +#define NI_ITERATOR_RESET(iterator) \ +{ \ + int _ii; \ + for(_ii = 0; _ii <= (iterator).rank_m1; _ii++) \ + (iterator).coordinates[_ii] = 0; \ +} + +/* go to the next point in a single array */ +#define NI_ITERATOR_NEXT(iterator, pointer) \ +{ \ + int _ii; \ + for(_ii = (iterator).rank_m1; _ii >= 0; _ii--) \ + if ((iterator).coordinates[_ii] < (iterator).dimensions[_ii]) { \ + (iterator).coordinates[_ii]++; \ + pointer += (iterator).strides[_ii]; \ + break; \ + } else { \ + (iterator).coordinates[_ii] = 0; \ + pointer -= (iterator).backstrides[_ii]; \ + } \ +} + +/* go to the next point in two arrays of the same size */ +#define NI_ITERATOR_NEXT2(iterator1, iterator2, pointer1, pointer2) \ +{ \ + int _ii; \ + for(_ii = (iterator1).rank_m1; _ii >= 0; _ii--) \ + if ((iterator1).coordinates[_ii] < (iterator1).dimensions[_ii]) { \ + (iterator1).coordinates[_ii]++; \ + pointer1 += (iterator1).strides[_ii]; \ + pointer2 += (iterator2).strides[_ii]; \ + break; \ + } else { \ + (iterator1).coordinates[_ii] = 0; \ + pointer1 -= (iterator1).backstrides[_ii]; \ + pointer2 -= (iterator2).backstrides[_ii]; \ + } \ +} + +/* go to the next point in three arrays of the same size */ +#define NI_ITERATOR_NEXT3(iterator1, iterator2, iterator3, \ + pointer1, pointer2, pointer3) \ +{ \ + int _ii; \ + for(_ii = (iterator1).rank_m1; _ii >= 0; _ii--) \ + if ((iterator1).coordinates[_ii] < (iterator1).dimensions[_ii]) { \ + (iterator1).coordinates[_ii]++; \ + pointer1 += (iterator1).strides[_ii]; \ + pointer2 += (iterator2).strides[_ii]; \ + pointer3 += (iterator3).strides[_ii]; \ + break; \ + } else { \ + (iterator1).coordinates[_ii] = 0; \ + pointer1 -= (iterator1).backstrides[_ii]; \ + pointer2 -= (iterator2).backstrides[_ii]; \ + pointer3 -= (iterator3).backstrides[_ii]; \ + } \ +} + +/* go to an arbitrary point in a single array */ +#define NI_ITERATOR_GOTO(iterator, destination, base, pointer) \ +{ \ + int _ii; \ + pointer = base; \ + for(_ii = (iterator).rank_m1; _ii >= 0; _ii--) { \ + pointer += destination[_ii] * (iterator).strides[_ii]; \ + (iterator).coordinates[_ii] = destination[_ii]; \ + } \ +} + +/******************************************************************/ +/* Line buffers */ +/******************************************************************/ + +/* the linebuffer structure: */ +typedef struct { + double *buffer_data; + maybelong buffer_lines, line_length, line_stride; + maybelong size1, size2, array_lines, next_line; + NI_Iterator iterator; + char* array_data; + NumarrayType array_type; + NI_ExtendMode extend_mode; + double extend_value; +} NI_LineBuffer; + +/* Get the next line being processed: */ +#define NI_GET_LINE(_buffer, _line) \ + ((_buffer).buffer_data + (_line) * ((_buffer).line_length + \ + (_buffer).size1 + (_buffer).size2)) +/* Allocate line buffer data */ +int NI_AllocateLineBuffer(PyArrayObject*, int, maybelong, maybelong, + maybelong*, maybelong, double**); + +/* Initialize a line buffer */ +int NI_InitLineBuffer(PyArrayObject*, int, maybelong, maybelong, maybelong, + double*, NI_ExtendMode, double, NI_LineBuffer*); + +/* Extend a line in memory to implement boundary conditions: */ +int NI_ExtendLine(double*, maybelong, maybelong, maybelong, NI_ExtendMode, double); + +/* Copy a line from an array to a buffer: */ +int NI_ArrayToLineBuffer(NI_LineBuffer*, maybelong*, int*); + +/* Copy a line from a buffer to an array: */ +int NI_LineBufferToArray(NI_LineBuffer*); + +/******************************************************************/ +/* Multi-dimensional filter support functions */ +/******************************************************************/ + +/* the filter iterator structure: */ +typedef struct { + maybelong strides[MAXDIM], backstrides[MAXDIM]; + maybelong bound1[MAXDIM], bound2[MAXDIM]; +} NI_FilterIterator; + +/* Initialize a filter iterator: */ +int NI_InitFilterIterator(int, maybelong*, maybelong, maybelong*, + maybelong*, NI_FilterIterator*); + +/* Calculate the offsets to the filter points, for all border regions and + the interior of the array: */ +int NI_InitFilterOffsets(PyArrayObject*, Bool*, maybelong*, + maybelong*, NI_ExtendMode, maybelong**, maybelong*, maybelong**); + +/* Move to the next point in an array, possible changing the filter + offsets, to adapt to boundary conditions: */ +#define NI_FILTER_NEXT(iteratorf, iterator1, pointerf, pointer1) \ +{ \ + int _ii; \ + for(_ii = (iterator1).rank_m1; _ii >= 0; _ii--) { \ + maybelong _pp = (iterator1).coordinates[_ii]; \ + if (_pp < (iterator1).dimensions[_ii]) { \ + if (_pp < (iteratorf).bound1[_ii] || \ + _pp >= (iteratorf).bound2[_ii]) \ + pointerf += (iteratorf).strides[_ii]; \ + (iterator1).coordinates[_ii]++; \ + pointer1 += (iterator1).strides[_ii]; \ + break; \ + } else { \ + (iterator1).coordinates[_ii] = 0; \ + pointer1 -= (iterator1).backstrides[_ii]; \ + pointerf -= (iteratorf).backstrides[_ii]; \ + } \ + } \ +} + +/* Move to the next point in two arrays, possible changing the pointer + to the filter offsets when moving into a different region in the + array: */ +#define NI_FILTER_NEXT2(iteratorf, iterator1, iterator2, \ + pointerf, pointer1, pointer2) \ +{ \ + int _ii; \ + for(_ii = (iterator1).rank_m1; _ii >= 0; _ii--) { \ + maybelong _pp = (iterator1).coordinates[_ii]; \ + if (_pp < (iterator1).dimensions[_ii]) { \ + if (_pp < (iteratorf).bound1[_ii] || \ + _pp >= (iteratorf).bound2[_ii]) \ + pointerf += (iteratorf).strides[_ii]; \ + (iterator1).coordinates[_ii]++; \ + pointer1 += (iterator1).strides[_ii]; \ + pointer2 += (iterator2).strides[_ii]; \ + break; \ + } else { \ + (iterator1).coordinates[_ii] = 0; \ + pointer1 -= (iterator1).backstrides[_ii]; \ + pointer2 -= (iterator2).backstrides[_ii]; \ + pointerf -= (iteratorf).backstrides[_ii]; \ + } \ + } \ +} + +/* Move to the next point in three arrays, possible changing the pointer + to the filter offsets when moving into a different region in the + array: */ +#define NI_FILTER_NEXT3(iteratorf, iterator1, iterator2, iterator3, \ + pointerf, pointer1, pointer2, pointer3) \ +{ \ + int _ii; \ + for(_ii = (iterator1).rank_m1; _ii >= 0; _ii--) { \ + maybelong _pp = (iterator1).coordinates[_ii]; \ + if (_pp < (iterator1).dimensions[_ii]) { \ + if (_pp < (iteratorf).bound1[_ii] || \ + _pp >= (iteratorf).bound2[_ii]) \ + pointerf += (iteratorf).strides[_ii]; \ + (iterator1).coordinates[_ii]++; \ + pointer1 += (iterator1).strides[_ii]; \ + pointer2 += (iterator2).strides[_ii]; \ + pointer3 += (iterator3).strides[_ii]; \ + break; \ + } else { \ + (iterator1).coordinates[_ii] = 0; \ + pointer1 -= (iterator1).backstrides[_ii]; \ + pointer2 -= (iterator2).backstrides[_ii]; \ + pointer3 -= (iterator3).backstrides[_ii]; \ + pointerf -= (iteratorf).backstrides[_ii]; \ + } \ + } \ +} + +/* Move the pointer to the filter offsets according to the given + coordinates: */ +#define NI_FILTER_GOTO(iteratorf, iterator, fbase, pointerf) \ +{ \ + int _ii; \ + maybelong _jj; \ + pointerf = fbase; \ + for(_ii = iterator.rank_m1; _ii >= 0; _ii--) { \ + maybelong _pp = iterator.coordinates[_ii]; \ + maybelong b1 = (iteratorf).bound1[_ii]; \ + maybelong b2 = (iteratorf).bound2[_ii]; \ + if (_pp < b1) { \ + _jj = _pp; \ + } else if (_pp > b2 && b2 >= b1) { \ + _jj = _pp + b1 - b2; \ + } else { \ + _jj = b1; \ + } \ + pointerf += (iteratorf).strides[_ii] * _jj; \ + } \ +} + +typedef struct { + maybelong *coordinates; + int size; + void *next; +} NI_CoordinateBlock; + +typedef struct { + int block_size, rank; + void *blocks; +} NI_CoordinateList; + +NI_CoordinateList* NI_InitCoordinateList(int, int); +int NI_CoordinateListStealBlocks(NI_CoordinateList*, NI_CoordinateList*); +NI_CoordinateBlock* NI_CoordinateListAddBlock(NI_CoordinateList*); +NI_CoordinateBlock* NI_CoordinateListDeleteBlock(NI_CoordinateList*); +void NI_FreeCoordinateList(NI_CoordinateList*); + +#endif Added: branches/Interpolate1D/ndimage/register/Register_EXT.c =================================================================== --- branches/Interpolate1D/ndimage/register/Register_EXT.c 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/register/Register_EXT.c 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,753 @@ +/* Python extension interface code */ + +#include "Python.h" +#include "numpy/arrayobject.h" + +static PyObject *Register_Histogram(PyObject *self, PyObject *args) +{ + /* + joint histogram memory is created in python to avoid memory leak problem + */ + + int num; + int numM; + int nd; + int type; + int itype; + int nd_histo; + int nd_rotmatrix; + int nd_S; + npy_intp *dimsF; + npy_intp *dimsG; + npy_intp *dims_histo; + npy_intp *dims_rotmatrix; + npy_intp *dims_S; + unsigned char *imageG; + unsigned char *imageF; + double *pHisto; + double *M; + int *S; + PyObject *imgArray1 = NULL; + PyObject *imgArray2 = NULL; + PyObject *rotArray = NULL; + PyObject *SArray = NULL; + PyObject *hArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOOO", &imgArray1, &imgArray2, &rotArray, &SArray, &hArray)) + goto exit; + + /* check in the Python code that F and G are the same dims, type */ + imageF = (unsigned char *)PyArray_DATA(imgArray1); + imageG = (unsigned char *)PyArray_DATA(imgArray2); + nd = PyArray_NDIM(imgArray1); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + dimsF = PyArray_DIMS(imgArray1); + dimsG = PyArray_DIMS(imgArray2); + type = PyArray_TYPE(imgArray1); + num = PyArray_SIZE(imgArray1); + + M = (double *)PyArray_DATA(rotArray); + nd_rotmatrix = PyArray_NDIM(rotArray); + dims_rotmatrix = PyArray_DIMS(rotArray); + numM = PyArray_SIZE(rotArray); + + S = (int *)PyArray_DATA(SArray); + nd_S = PyArray_NDIM(SArray); + dims_S = PyArray_DIMS(SArray); + + pHisto = (double *)PyArray_DATA(hArray); + nd_histo = PyArray_NDIM(hArray); + dims_histo = PyArray_DIMS(hArray); + /* check to make sure this is 256x256 */ + + if(!NI_Histogram2D((int)dimsF[0], (int)dimsF[1], (int)dimsF[2], + (int)dimsG[0], (int)dimsG[1], (int)dimsG[2], + S, M, imageG, imageF, pHisto)) + goto exit; + +exit: + + /* return the 2D histogram */ + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Register_HistogramLite(PyObject *self, PyObject *args) +{ + /* + joint histogram memory is created in python to avoid memory leak problem + */ + + int num; + int numG; + int nd; + int type; + int itype; + int nd_histo; + int nd_rotmatrix; + int nd_S; + npy_intp *dimsF; + npy_intp *dimsG; + npy_intp *dims_histo; + npy_intp *dims_rotmatrix; + npy_intp *dims_S; + unsigned char *imageG; + unsigned char *imageF; + double *pHisto; + double *M; + int *S; + PyObject *imgArray1 = NULL; + PyObject *imgArray2 = NULL; + PyObject *rotArray = NULL; + PyObject *SArray = NULL; + PyObject *hArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOOO", &imgArray1, &imgArray2, &rotArray, &SArray, &hArray)) + goto exit; + + /* check in the Python code that F and G are the same dims, type */ + imageF = (unsigned char *)PyArray_DATA(imgArray1); + imageG = (unsigned char *)PyArray_DATA(imgArray2); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArray1); + dimsF = PyArray_DIMS(imgArray1); + dimsG = PyArray_DIMS(imgArray2); + type = PyArray_TYPE(imgArray1); + num = PyArray_SIZE(imgArray1); + numG = PyArray_SIZE(imgArray2); + + M = (double *)PyArray_DATA(rotArray); + nd_rotmatrix = PyArray_NDIM(rotArray); + dims_rotmatrix = PyArray_DIMS(rotArray); + + S = (int *)PyArray_DATA(SArray); + nd_S = PyArray_NDIM(SArray); + dims_S = PyArray_DIMS(SArray); + + pHisto = (double *)PyArray_DATA(hArray); + nd_histo = PyArray_NDIM(hArray); + dims_histo = PyArray_DIMS(hArray); + /* check to make sure this is 256x256 */ + + if(!NI_Histogram2DLite((int)dimsF[0], (int)dimsF[1], (int)dimsF[2], + (int)dimsG[0], (int)dimsG[1], (int)dimsG[2], + S, M, imageG, imageF, pHisto)) + goto exit; + +exit: + + /* return the 2D histogram */ + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + +static PyObject *Register_VolumeResample(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int itype; + int mode; + int scale; + npy_intp *dimsF; + npy_intp *dimsG; + unsigned char *imageG; + unsigned char *imageF; + double *Z; + PyObject *imgArray1 = NULL; + PyObject *imgArray2 = NULL; + PyObject *coordZoom = NULL; + + if(!PyArg_ParseTuple(args, "OOOii", &imgArray1, &imgArray2, &coordZoom, &scale, &mode)) + goto exit; + + /* check in the Python code that F and G are the same dims, type */ + imageF = (unsigned char *)PyArray_DATA(imgArray1); + imageG = (unsigned char *)PyArray_DATA(imgArray2); + Z = (double *)PyArray_DATA(coordZoom); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArray1); + dimsF = PyArray_DIMS(imgArray1); + dimsG = PyArray_DIMS(imgArray2); + type = PyArray_TYPE(imgArray1); + num = PyArray_SIZE(imgArray1); + + if(!NI_VolumeResample((int)dimsF[0], (int)dimsF[1], (int)dimsF[2], + (int)dimsG[0], (int)dimsG[1], (int)dimsG[2], + scale, mode, imageG, imageF, Z)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + + +static PyObject *Register_CubicResample(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int itype; + int nd_rotmatrix; + int nd_S; + npy_intp *dimsF; + npy_intp *dimsG; + npy_intp *dims_rotmatrix; + npy_intp *dims_S; + unsigned char *imageG; + unsigned char *imageF; + double *M; + int *S; + PyObject *imgArray1 = NULL; + PyObject *imgArray2 = NULL; + PyObject *rotArray = NULL; + PyObject *SArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOO", &imgArray1, &imgArray2, &rotArray, &SArray)) + goto exit; + + /* check in the Python code that F and G are the same dims, type */ + imageF = (unsigned char *)PyArray_DATA(imgArray1); + imageG = (unsigned char *)PyArray_DATA(imgArray2); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArray1); + dimsF = PyArray_DIMS(imgArray1); + dimsG = PyArray_DIMS(imgArray2); + type = PyArray_TYPE(imgArray1); + num = PyArray_SIZE(imgArray1); + + M = (double *)PyArray_DATA(rotArray); + nd_rotmatrix = PyArray_NDIM(rotArray); + dims_rotmatrix = PyArray_DIMS(rotArray); + + S = (int *)PyArray_DATA(SArray); + nd_S = PyArray_NDIM(SArray); + dims_S = PyArray_DIMS(SArray); + + if(!NI_CubicResample((int)dimsF[0], (int)dimsF[1], (int)dimsF[2], + (int)dimsG[0], (int)dimsG[1], (int)dimsG[2], + S, M, imageG, imageF)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Register_LinearResample(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int itype; + int nd_rotmatrix; + int nd_S; + npy_intp *dimsF; + npy_intp *dimsG; + npy_intp *dims_rotmatrix; + npy_intp *dims_S; + unsigned char *imageG; + unsigned char *imageF; + double *M; + int *S; + PyObject *imgArray1 = NULL; + PyObject *imgArray2 = NULL; + PyObject *rotArray = NULL; + PyObject *SArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOO", &imgArray1, &imgArray2, &rotArray, &SArray)) + goto exit; + + /* check in the Python code that F and G are the same dims, type */ + imageF = (unsigned char *)PyArray_DATA(imgArray1); + imageG = (unsigned char *)PyArray_DATA(imgArray2); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArray1); + dimsF = PyArray_DIMS(imgArray1); + dimsG = PyArray_DIMS(imgArray2); + type = PyArray_TYPE(imgArray1); + num = PyArray_SIZE(imgArray1); + + M = (double *)PyArray_DATA(rotArray); + nd_rotmatrix = PyArray_NDIM(rotArray); + dims_rotmatrix = PyArray_DIMS(rotArray); + + S = (int *)PyArray_DATA(SArray); + nd_S = PyArray_NDIM(SArray); + dims_S = PyArray_DIMS(SArray); + + if(!NI_LinearResample((int)dimsF[0], (int)dimsF[1], (int)dimsF[2], + (int)dimsG[0], (int)dimsG[1], (int)dimsG[2], + S, M, imageG, imageF)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Register_ImageThreshold(PyObject *self, PyObject *args) +{ + + /* set threshold from the volume integrated histogram */ + int num; + int nd; + int type; + int itype; + int histogram_elements; + int tindex; + npy_intp *dimsImage; + npy_intp *dimsHistogram; + unsigned short *image; + double *H; + double *IH; + double threshold; + PyObject *imgArray = NULL; + PyObject *histogram = NULL; + PyObject *ihistogram = NULL; + + if(!PyArg_ParseTuple(args, "OOOd", &imgArray, &histogram, &ihistogram, &threshold)) + goto exit; + + image = (unsigned short *)PyArray_DATA(imgArray); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArray); + dimsImage = PyArray_DIMS(imgArray); + type = PyArray_TYPE(imgArray); + num = PyArray_SIZE(imgArray); + + H = (double *)PyArray_DATA(histogram); + IH = (double *)PyArray_DATA(ihistogram); + histogram_elements = PyArray_SIZE(histogram); + + if(!NI_ImageThreshold((int)dimsImage[0], (int)dimsImage[1], (int)dimsImage[2], + image, H, IH, histogram_elements, threshold, &tindex)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("i", tindex); + +} + + +static PyObject *Register_ResampleWithGradient(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int itype; + int nd_rotmatrix; + int nd_S; + npy_intp *dimsScale; + npy_intp *dimsOffset; + npy_intp *dimsS; + npy_intp *dimsD; + npy_intp *dims_rotmatrix; + npy_intp *dims_S; + unsigned char *imageS; + unsigned char *imageD; + double *M; + int *S; + double *scale; + int *offset; + double *gradientX; + double *gradientY; + double *gradientZ; + PyObject *imgArrayS = NULL; + PyObject *imgArrayD = NULL; + PyObject *rotArray = NULL; + PyObject *SArray = NULL; + PyObject *scaleArray = NULL; + PyObject *offsetArray = NULL; + PyObject *gradXArray = NULL; + PyObject *gradYArray = NULL; + PyObject *gradZArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOOOOOOO", &imgArrayS, &imgArrayD, &rotArray, &SArray, &scaleArray, + &offsetArray, &gradXArray, &gradYArray, &gradZArray)) + goto exit; + + /* check in the Python code that S and D are the same dims, type */ + imageS = (unsigned char *)PyArray_DATA(imgArrayS); + imageD = (unsigned char *)PyArray_DATA(imgArrayD); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArrayS); + dimsS = PyArray_DIMS(imgArrayS); + dimsD = PyArray_DIMS(imgArrayD); + type = PyArray_TYPE(imgArrayS); + num = PyArray_SIZE(imgArrayS); + + M = (double *)PyArray_DATA(rotArray); + nd_rotmatrix = PyArray_NDIM(rotArray); + dims_rotmatrix = PyArray_DIMS(rotArray); + + S = (int *)PyArray_DATA(SArray); + nd_S = PyArray_NDIM(SArray); + dims_S = PyArray_DIMS(SArray); + + scale = (double *)PyArray_DATA(scaleArray); + offset = (int *)PyArray_DATA(offsetArray); + dimsScale = PyArray_DIMS(scaleArray); + dimsOffset = PyArray_DIMS(offsetArray); + + gradientX = (double *)PyArray_DATA(gradXArray); + gradientY = (double *)PyArray_DATA(gradYArray); + gradientZ = (double *)PyArray_DATA(gradZArray); + + if(!NI_ResampleWithGradient((int)dimsS[0], (int)dimsS[1], (int)dimsS[2], + (int)dimsD[0], (int)dimsD[1], (int)dimsD[2], + S, M, imageD, imageS, scale, offset, gradientX, + gradientY, gradientZ)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Register_Find_Mask(PyObject *self, PyObject *args) +{ + + int i; + int num; + int length; + double *X; + double *Y; + double *Z; + int *xLims; + int *yLims; + int *zLims; + int *mask; + PyObject *MArray = NULL; + PyObject *XArray = NULL; + PyObject *YArray = NULL; + PyObject *ZArray = NULL; + PyObject *XLimits = NULL; + PyObject *YLimits = NULL; + PyObject *ZLimits = NULL; + + if(!PyArg_ParseTuple(args, "OOOOOOO", &MArray, &XArray, &YArray, &ZArray, &XLimits, &YLimits, &ZLimits)) + goto exit; + + num = PyArray_SIZE(XArray); + X = (double *)PyArray_DATA(XArray); + Y = (double *)PyArray_DATA(YArray); + Z = (double *)PyArray_DATA(ZArray); + mask = (int *)PyArray_DATA(MArray); + xLims = (int *)PyArray_DATA(XLimits); + yLims = (int *)PyArray_DATA(YLimits); + zLims = (int *)PyArray_DATA(ZLimits); + + for(length = 0, i = 0; i < num; ++i){ + if( ((X[i] >= xLims[0]) && (X[i] <= xLims[1])) && + ((Y[i] >= yLims[0]) && (Y[i] <= yLims[1])) && + ((Z[i] >= zLims[0]) && (Z[i] <= zLims[1])) ){ + mask[length++] = i; + } + } + + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("i", length); + +} + + + +static PyObject *Register_Resample_Gradient_Coords(PyObject *self, PyObject *args) +{ + + int num; + int size; + int nd; + int type; + int itype; + int nd_S; + npy_intp *dimsScale; + npy_intp *dimsOffset; + npy_intp *dimsS; + npy_intp *dimsD; + npy_intp *dims_S; + npy_intp *dims_Coords; + unsigned char *imageS; + unsigned char *imageD; + double *X; + double *Y; + double *Z; + int *S; + double *scale; + int *offset; + double *gradientX; + double *gradientY; + double *gradientZ; + PyObject *imgArrayS = NULL; + PyObject *imgArrayD = NULL; + PyObject *SArray = NULL; + PyObject *scaleArray = NULL; + PyObject *offsetArray = NULL; + PyObject *gradXArray = NULL; + PyObject *gradYArray = NULL; + PyObject *gradZArray = NULL; + PyObject *coordXArray = NULL; + PyObject *coordYArray = NULL; + PyObject *coordZArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOOOOOOOOO", &coordZArray, &coordYArray, &coordXArray, + &imgArrayS, &imgArrayD, &SArray, &scaleArray, &offsetArray, + &gradXArray, &gradYArray, &gradZArray)) + goto exit; + + /* check in the Python code that S and D are the same dims, type */ + imageS = (unsigned char *)PyArray_DATA(imgArrayS); + imageD = (unsigned char *)PyArray_DATA(imgArrayD); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArrayS); + dimsS = PyArray_DIMS(imgArrayS); + dimsD = PyArray_DIMS(imgArrayD); + type = PyArray_TYPE(imgArrayS); + num = PyArray_SIZE(imgArrayS); + + S = (int *)PyArray_DATA(SArray); + nd_S = PyArray_NDIM(SArray); + dims_S = PyArray_DIMS(SArray); + + scale = (double *)PyArray_DATA(scaleArray); + offset = (int *)PyArray_DATA(offsetArray); + dimsScale = PyArray_DIMS(scaleArray); + dimsOffset = PyArray_DIMS(offsetArray); + + gradientX = (double *)PyArray_DATA(gradXArray); + gradientY = (double *)PyArray_DATA(gradYArray); + gradientZ = (double *)PyArray_DATA(gradZArray); + + X = (double *)PyArray_DATA(coordXArray); + Y = (double *)PyArray_DATA(coordYArray); + Z = (double *)PyArray_DATA(coordZArray); + + dims_Coords = PyArray_DIMS(coordXArray); + size = PyArray_SIZE(coordXArray); + + if(!NI_Resample_Gradient_Coords(size, (int)dimsS[0], (int)dimsS[1], (int)dimsS[2], (int)dimsD[0], + (int)dimsD[1], (int)dimsD[2], S, X, Y, Z, imageD, imageS, scale, + offset, gradientX, gradientY, gradientZ)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + + +static PyObject *Register_Resample_Coords(PyObject *self, PyObject *args) +{ + + int num; + int size; + int nd; + int type; + int itype; + int nd_S; + npy_intp *dimsScale; + npy_intp *dimsOffset; + npy_intp *dimsS; + npy_intp *dimsD; + npy_intp *dims_S; + npy_intp *dims_Coords; + unsigned char *imageS; + unsigned char *imageD; + double *X; + double *Y; + double *Z; + int *S; + double *scale; + int *offset; + PyObject *imgArrayS = NULL; + PyObject *imgArrayD = NULL; + PyObject *SArray = NULL; + PyObject *scaleArray = NULL; + PyObject *offsetArray = NULL; + PyObject *coordXArray = NULL; + PyObject *coordYArray = NULL; + PyObject *coordZArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOOOOOO", &coordZArray, &coordYArray, &coordXArray, + &imgArrayS, &imgArrayD, &SArray, &scaleArray, &offsetArray)) + goto exit; + + /* check in the Python code that S and D are the same dims, type */ + imageS = (unsigned char *)PyArray_DATA(imgArrayS); + imageD = (unsigned char *)PyArray_DATA(imgArrayD); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArrayS); + dimsS = PyArray_DIMS(imgArrayS); + dimsD = PyArray_DIMS(imgArrayD); + type = PyArray_TYPE(imgArrayS); + num = PyArray_SIZE(imgArrayS); + + S = (int *)PyArray_DATA(SArray); + nd_S = PyArray_NDIM(SArray); + dims_S = PyArray_DIMS(SArray); + + scale = (double *)PyArray_DATA(scaleArray); + offset = (int *)PyArray_DATA(offsetArray); + dimsScale = PyArray_DIMS(scaleArray); + dimsOffset = PyArray_DIMS(offsetArray); + + X = (double *)PyArray_DATA(coordXArray); + Y = (double *)PyArray_DATA(coordYArray); + Z = (double *)PyArray_DATA(coordZArray); + + dims_Coords = PyArray_DIMS(coordXArray); + size = PyArray_SIZE(coordXArray); + + if(!NI_Resample_Coords(size, (int)dimsS[0], (int)dimsS[1], (int)dimsS[2], (int)dimsD[0], + (int)dimsD[1], (int)dimsD[2], S, X, Y, Z, imageD, imageS, scale, offset)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Register_Complete_Symmetry(PyObject *self, PyObject *args) +{ + + int nx; + int ny; + int nz; + int ni; + double *A; + PyObject *AlphaArray = NULL; + + if(!PyArg_ParseTuple(args, "Oiiii", &AlphaArray, &nx, &ny, &nz, &ni)) + goto exit; + + A = (double *)PyArray_DATA(AlphaArray); + + if(!NI_Complete_Symmetry(A, nx, ny, nz, ni)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + + +static PyObject *Register_LT_Tensor_Product(PyObject *self, PyObject *args) +{ + int M1; + int M2; + int rows; + int cur_row; + int coeff_1; + int coeff_2; + double *A1; + double *A2; + double *B1; + double *B2; + double *Basis; + PyObject *AlphaArray1 = NULL; + PyObject *AlphaArray2 = NULL; + PyObject *BetaArray1 = NULL; + PyObject *BetaArray2 = NULL; + PyObject *BasisArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOOOiiiiii", &AlphaArray1, &AlphaArray2, &BetaArray1, &BetaArray2, + &BasisArray, &M1, &M2, &rows, &cur_row, &coeff_1, &coeff_2)) + goto exit; + + A1 = (double *)PyArray_DATA(AlphaArray1); + A2 = (double *)PyArray_DATA(AlphaArray2); + B1 = (double *)PyArray_DATA(BetaArray1); + B2 = (double *)PyArray_DATA(BetaArray2); + Basis = (double *)PyArray_DATA(BasisArray); + + if(!NI_LT_Tensor_Product(A1, A2, B1, B2, Basis, M1, M2, rows, cur_row, coeff_1, coeff_2)) + goto exit; + + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + + +static PyObject *Register_LT_Mrqcof(PyObject *self, PyObject *args) +{ + + int M1; + double wt; + double value; + double *A; + double *B; + double *V; + PyObject *AlphaArray = NULL; + PyObject *BetaArray = NULL; + PyObject *VArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOddi", &AlphaArray, &BetaArray, &VArray, &wt, &value, &M1)) + goto exit; + + A = (double *)PyArray_DATA(AlphaArray); + B = (double *)PyArray_DATA(BetaArray); + V = (double *)PyArray_DATA(VArray); + + if(!NI_LT_Mrqcof(A, B, V, wt, value, M1)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyMethodDef RegisterMethods[] = +{ + { "register_complete_symmetry", Register_Complete_Symmetry, METH_VARARGS, NULL }, + { "register_lt_mrqcof", Register_LT_Mrqcof, METH_VARARGS, NULL }, + { "register_lt_tensor_product", Register_LT_Tensor_Product, METH_VARARGS, NULL }, + { "register_find_mask", Register_Find_Mask, METH_VARARGS, NULL }, + { "register_resample_coords", Register_Resample_Coords, METH_VARARGS, NULL }, + { "register_resample_gradient_coords", Register_Resample_Gradient_Coords, METH_VARARGS, NULL }, + { "register_resample_w_gradient", Register_ResampleWithGradient, METH_VARARGS, NULL }, + { "register_histogram", Register_Histogram, METH_VARARGS, NULL }, + { "register_histogram_lite", Register_HistogramLite, METH_VARARGS, NULL }, + { "register_linear_resample", Register_LinearResample, METH_VARARGS, NULL }, + { "register_cubic_resample", Register_CubicResample, METH_VARARGS, NULL }, + { "register_volume_resample", Register_VolumeResample, METH_VARARGS, NULL }, + { "register_image_threshold", Register_ImageThreshold, METH_VARARGS, NULL }, + { NULL, NULL, 0, NULL}, +}; + +PyMODINIT_FUNC init_register(void) +{ + Py_InitModule("_register", RegisterMethods); + import_array(); +} + + Added: branches/Interpolate1D/ndimage/register/Register_IMPL.c =================================================================== --- branches/Interpolate1D/ndimage/register/Register_IMPL.c 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/register/Register_IMPL.c 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,1369 @@ +#include +#include + +float tri_cubic_convolve(unsigned char *pVolume, int x, int y, int z, float xp, float yp, + float zp, int colsG, int rowsG, int layersG, int sliceSizeG){ + + int i, j, k; + int layerOffsets[4]; + int rowOffsets[4]; + float ps1, ps2, ps3; + float Y[4], NewRow[4], NewLayer[4]; + float R, C, L, D, T; + float valueXYZ = 0.0; + float dataCube[4][4][4]; + /* [cols][rows][layers] */ + + rowOffsets[0] = (y-1)*colsG; + rowOffsets[1] = (y )*colsG; + rowOffsets[2] = (y+1)*colsG; + rowOffsets[3] = (y+2)*colsG; + + layerOffsets[0] = (z-1)*sliceSizeG; + layerOffsets[1] = (z )*sliceSizeG; + layerOffsets[2] = (z+1)*sliceSizeG; + layerOffsets[3] = (z+2)*sliceSizeG; + + /* get numerator for interpolation */ + C = xp - (float)x; + R = yp - (float)y; + L = zp - (float)z; + D = (float)0.002; + + /* get 4x4 window over all 4 layers */ + for(i = 0; i < 4; ++i){ + for(j = 0; j < 4; ++j){ + dataCube[0][j][i] = (float)pVolume[layerOffsets[i]+rowOffsets[j]+x-1]; + dataCube[1][j][i] = (float)pVolume[layerOffsets[i]+rowOffsets[j]+x]; + dataCube[2][j][i] = (float)pVolume[layerOffsets[i]+rowOffsets[j]+x+1]; + dataCube[3][j][i] = (float)pVolume[layerOffsets[i]+rowOffsets[j]+x+2]; + } + } + + for(i = 0; i < 4; ++i){ + /* interpolate 4 rows in all 4 layers */ + for(j = 0; j < 4; ++j){ + if(C > D){ + Y[0] = dataCube[0][j][i]; + Y[1] = dataCube[1][j][i]; + Y[2] = dataCube[2][j][i]; + Y[3] = dataCube[3][j][i]; + ps1 = Y[2] - Y[0]; + ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; + ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; + NewRow[j] = Y[1]+C*(ps1+C*(ps2+C*ps3)); + } + else{ + NewRow[j] = dataCube[1][j][i]; + } + } + /* interpolate across 4 columns */ + if(R > D){ + Y[0] = NewRow[0]; + Y[1] = NewRow[1]; + Y[2] = NewRow[2]; + Y[3] = NewRow[3]; + ps1 = Y[2] - Y[0]; + ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; + ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; + T = (Y[1]+R*(ps1+R*(ps2+R*ps3))); + NewLayer[i] = T; + } + else{ + T = NewRow[1]; + NewLayer[i] = T; + } + } + /* interpolate across 4 layers */ + if(L > D){ + Y[0] = NewLayer[0]; + Y[1] = NewLayer[1]; + Y[2] = NewLayer[2]; + Y[3] = NewLayer[3]; + ps1 = Y[2] - Y[0]; + ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; + ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; + T = (Y[1]+L*(ps1+L*(ps2+L*ps3))); + valueXYZ = T; + } + else{ + T = NewLayer[1]; + valueXYZ = T; + } + + return(valueXYZ); + +} + +float trilinear_A(unsigned char *pVolume, int x, int y, int z, float dx, float dy, float dz, int dims[]){ + + // Vxyz for [0,1] values of x, y, z + int V000; + int V100; + int V010; + int V001; + int V011; + int V101; + int V110; + int V111; + + int ptr_x0; + int ptr_y0; + int ptr_z0; + + int ptr_x1; + int ptr_y1; + int ptr_z1; + + float valueXYZ; + + ptr_x0 = x; + ptr_y0 = y * dims[0]; + ptr_z0 = z * dims[1]; + + ptr_x1 = ptr_x0 + 1; + ptr_y1 = ptr_y0 + dims[0]; + ptr_z1 = ptr_z0 + dims[1]; + + V000 = pVolume[ptr_x0+ptr_y0+ptr_z0]; + V100 = pVolume[ptr_x1+ptr_y0+ptr_z0]; + V010 = pVolume[ptr_x0+ptr_y1+ptr_z0]; + V001 = pVolume[ptr_x0+ptr_y0+ptr_z1]; + V011 = pVolume[ptr_x0+ptr_y1+ptr_z1]; + V101 = pVolume[ptr_x1+ptr_y0+ptr_z1]; + V110 = pVolume[ptr_x1+ptr_y1+ptr_z0]; + V111 = pVolume[ptr_x1+ptr_y1+ptr_z1]; + + // dx, dy, dz are increments in x, y, z + // dx = 0 is x = 1 as x, y and z are [0, 1] in range + + valueXYZ = + V000 * (1.0-dx) * (1.0 - dy) * (1.0 - dz) + + V100 * (dx) * (1.0 - dy) * (1.0 - dz) + + V010 * (1.0-dx) * (dy) * (1.0 - dz) + + V001 * (1.0-dx) * (1.0 - dy) * (dz) + + V101 * (dx) * (1.0 - dy) * (dz) + + V011 * (1.0-dx) * (dy) * (dz) + + V110 * (dx) * (dy) * (1.0 - dz) + + V111 * (dx) * (dy) * (dz); + + + return(valueXYZ); + +} + +float trilinear_B(unsigned char *pVolume, float dx, float dy, float dz, int corners[]){ + + // Vxyz for [0,1] values of x, y, z + int V000; + int V100; + int V010; + int V001; + int V011; + int V101; + int V110; + int V111; + + int ptr_x0 = corners[0]; + int ptr_y0 = corners[1]; + int ptr_z0 = corners[2]; + + int ptr_x1 = corners[3]; + int ptr_y1 = corners[4]; + int ptr_z1 = corners[5]; + + float valueXYZ; + + V000 = pVolume[ptr_x0+ptr_y0+ptr_z0]; + V100 = pVolume[ptr_x1+ptr_y0+ptr_z0]; + V010 = pVolume[ptr_x0+ptr_y1+ptr_z0]; + V001 = pVolume[ptr_x0+ptr_y0+ptr_z1]; + V011 = pVolume[ptr_x0+ptr_y1+ptr_z1]; + V101 = pVolume[ptr_x1+ptr_y0+ptr_z1]; + V110 = pVolume[ptr_x1+ptr_y1+ptr_z0]; + V111 = pVolume[ptr_x1+ptr_y1+ptr_z1]; + + // dx, dy, dz are increments in x, y, z + // dx = 0 is x = 1 as x, y and z are [0, 1] in range + + valueXYZ = + V000 * (1.0-dx) * (1.0 - dy) * (1.0 - dz) + + V100 * (dx) * (1.0 - dy) * (1.0 - dz) + + V010 * (1.0-dx) * (dy) * (1.0 - dz) + + V001 * (1.0-dx) * (1.0 - dy) * (dz) + + V101 * (dx) * (1.0 - dy) * (dz) + + V011 * (1.0-dx) * (dy) * (dz) + + V110 * (dx) * (dy) * (1.0 - dz) + + V111 * (dx) * (dy) * (dz); + + + return(valueXYZ); + +} + +int NI_Histogram2D(int layersF, int rowsF, int colsF, int layersG, int rowsG, int colsG, + int *dimSteps, double *M, unsigned char *imageG, unsigned char *imageF, double *H) +{ + + int status; + int seed; + int dimsF[3]; + int dimsG[3]; + int dims_F[2]; + int dims_G[2]; + int ivf, ivg; + float ran_x, ran_y, ran_z; + float vf, delta; + float x, y, z; + float dx, dy, dz; + float xp, yp, zp; + float rx, ry, rz; + + dimsF[0] = colsF; + dimsF[1] = rowsF; + dimsF[2] = layersF; + dimsG[0] = colsG; + dimsG[1] = rowsG; + dimsG[2] = layersG; + + dims_G[0] = dimsG[0]; + dims_G[1] = dimsG[0]*dimsG[1]; + dims_F[0] = dimsF[0]; + dims_F[1] = dimsF[0]*dimsF[1]; + + seed = 1000; + srand(seed); + + /* because of stochastic sampling, subtract 1 from upper bounds */ + for(z = 0.0; z < layersG-dimSteps[2]-1; z += dimSteps[2]){ + for(y = 0.0; y < rowsG-dimSteps[1]-1; y += dimSteps[1]){ + for(x = 0.0; x < colsG-dimSteps[0]-1; x += dimSteps[0]){ + /* positive jitter the x, y, z values */ + ran_x = 1.0 * rand()/((float)RAND_MAX); + ran_y = 1.0 * rand()/((float)RAND_MAX); + ran_z = 1.0 * rand()/((float)RAND_MAX); + dx = x + ran_x*dimSteps[0]; + dy = y + ran_y*dimSteps[1]; + dz = z + ran_z*dimSteps[2]; + + /* get the 'from' coordinates */ + xp = M[0]*dx + M[1]*dy + M[2]*dz + M[3]; + yp = M[4]*dx + M[5]*dy + M[6]*dz + M[7]; + zp = M[8]*dx + M[9]*dy + M[10]*dz + M[11]; + /* clip the resample window */ + if((zp >= 0.0 && zp < layersF-dimSteps[2]) && + (yp >= 0.0 && yp < rowsF-dimSteps[1]) && + (xp >= 0.0 && xp < colsF-dimSteps[0])){ + /* resample the coordinates using a trilinear interpolation */ + /* resample imageF using the rotated-jittered xyz coordinates */ + rx = xp - (int)xp; + ry = yp - (int)yp; + rz = zp - (int)zp; + //vf = trilinear_A(imageF, (int)dx, (int)dy, (int)dz, rx, ry, rz, dims_F); + vf = trilinear_A(imageF, (int)xp, (int)yp, (int)zp, rx, ry, rz, dims_F); + /* floor */ + ivf = (int)vf; + delta = vf - ivf; + /* resample imageG using the jittered xyz coordinates */ + rx = dx - (int)dx; + ry = dy - (int)dy; + rz = dz - (int)dz; + ivg = (int)trilinear_A(imageG, (int)dx, (int)dy, (int)dz, rx, ry, rz, dims_G); + //ivg = (int)trilinear_A(imageG, (int)xp, (int)yp, (int)zp, rx, ry, rz, dims_G); + /* ivf will be < 255 as 8 bit data and trilinear doesn't ring */ + H[ivf+256*ivg] += 1.0 - delta; + if(ivf < 255){ + H[ivf+1+256*ivg] += delta; + } + } + } + } + } + + status = 1; + + return status; + +} + + +int NI_Histogram2DLite(int layersF, int rowsF, int colsF, int layersG, int rowsG, int colsG, + int *dimSteps, double *M, unsigned char *imageG, unsigned char *imageF, double *H) +{ + + int i; + int status; + int sliceG; + int rowG; + int sliceSizeG; + int dimsF[3]; + int dimsG[3]; + int dims[2]; + int ivf, ivg; + float vf, delta; + float x, y, z; + float xp, yp, zp; + float dx, dy, dz; + + int ptr_x0; + int ptr_y0; + int ptr_z0; + int ptr_x1; + int ptr_y1; + int ptr_z1; + // + // Vxyz for [0,1] values of x, y, z + // + int V000; + int V100; + int V010; + int V001; + int V011; + int V101; + int V110; + int V111; + int g[64], f[64]; + float valueXYZ; + + // + // G is fixed; F is rotated + // + sliceSizeG = rowsG * colsG; + dimsF[0] = colsF; + dimsF[1] = rowsF; + dimsF[2] = layersF; + dimsG[0] = colsG; + dimsG[1] = rowsG; + dimsG[2] = layersG; + + dims[0] = dimsF[0]; + dims[1] = dimsF[0]*dimsF[1]; + + for(z = 0.0; z < layersG-dimSteps[2]-1; z += dimSteps[2]){ + sliceG = (int)z * sliceSizeG; + for(y = 0.0; y < rowsG-dimSteps[1]-1; y += dimSteps[1]){ + rowG = (int)y * colsG; + for(x = 0.0; x < colsG-dimSteps[0]-1; x += dimSteps[0]){ + // get the 'from' coordinates + xp = M[0]*x + M[1]*y + M[2]*z + M[3]; + yp = M[4]*x + M[5]*y + M[6]*z + M[7]; + zp = M[8]*x + M[9]*y + M[10]*z + M[11]; + // clip the resample window + if((zp >= 0.0 && zp < layersF-dimSteps[2]) && + (yp >= 0.0 && yp < rowsF-dimSteps[1]) && + (xp >= 0.0 && xp < colsF-dimSteps[0])){ + + // corners of the 3D unit volume cube + ptr_z0 = (int)zp * dims[1]; + ptr_z1 = ptr_z0 + dims[1]; + ptr_y0 = (int)yp * dims[0]; + ptr_y1 = ptr_y0 + dims[0]; + ptr_x0 = (int)xp; + ptr_x1 = ptr_x0 + 1; + dx = xp - (int)xp; + dy = yp - (int)yp; + dz = zp - (int)zp; + + // imageG is not rotated. sample the given x,y,z + ivg = imageG[sliceG+rowG+(int)x]; + // imageF IS rotated. sample the rotated xp,yp,zp + V000 = imageF[ptr_x0+ptr_y0+ptr_z0]; + V100 = imageF[ptr_x1+ptr_y0+ptr_z0]; + V010 = imageF[ptr_x0+ptr_y1+ptr_z0]; + V001 = imageF[ptr_x0+ptr_y0+ptr_z1]; + V011 = imageF[ptr_x0+ptr_y1+ptr_z1]; + V101 = imageF[ptr_x1+ptr_y0+ptr_z1]; + V110 = imageF[ptr_x1+ptr_y1+ptr_z0]; + V111 = imageF[ptr_x1+ptr_y1+ptr_z1]; + + vf = V000 * (1.0-dx) * (1.0 - dy) * (1.0 - dz) + + V100 * (dx) * (1.0 - dy) * (1.0 - dz) + + V010 * (1.0-dx) * (dy) * (1.0 - dz) + + V001 * (1.0-dx) * (1.0 - dy) * (dz) + + V101 * (dx) * (1.0 - dy) * (dz) + + V011 * (1.0-dx) * (dy) * (dz) + + V110 * (dx) * (dy) * (1.0 - dz) + + V111 * (dx) * (dy) * (dz); + + ivf = (int)(vf); + H[ivf+256*ivg] += 1.0; + } + } + } + } + + status = 1; + + return status; + +} + + +int NI_LinearResample(int layersF, int rowsF, int colsF, int layersG, int rowsG, int colsG, + int *dimSteps, double *M, unsigned char *imageG, unsigned char *imageF) +{ + + int i; + int status; + int sliceG; + int rowG; + int sliceSizeG; + int dimsF[3]; + int dimsG[3]; + int dims[2]; + int ivf, ivg; + float vf, delta; + float x, y, z; + float xp, yp, zp; + float dx, dy, dz; + + int ptr_x0; + int ptr_y0; + int ptr_z0; + int ptr_x1; + int ptr_y1; + int ptr_z1; + // + // Vxyz for [0,1] values of x, y, z + // + int V000; + int V100; + int V010; + int V001; + int V011; + int V101; + int V110; + int V111; + float valueXYZ; + + // + // G is fixed; F is rotated + // + sliceSizeG = rowsG * colsG; + dimsF[0] = colsF; + dimsF[1] = rowsF; + dimsF[2] = layersF; + dimsG[0] = colsG; + dimsG[1] = rowsG; + dimsG[2] = layersG; + + dims[0] = dimsF[0]; + dims[1] = dimsF[0]*dimsF[1]; + + for(z = 0.0; z < layersG-dimSteps[2]-1; z += dimSteps[2]){ + sliceG = (int)z * sliceSizeG; + for(y = 0.0; y < rowsG-dimSteps[1]-1; y += dimSteps[1]){ + rowG = (int)y * colsG; + for(x = 0.0; x < colsG-dimSteps[0]-1; x += dimSteps[0]){ + // get the 'from' coordinates + xp = M[0]*x + M[1]*y + M[2]*z + M[3]; + yp = M[4]*x + M[5]*y + M[6]*z + M[7]; + zp = M[8]*x + M[9]*y + M[10]*z + M[11]; + // clip the resample window + if((zp >= 0.0 && zp < layersF-dimSteps[2]) && + (yp >= 0.0 && yp < rowsF-dimSteps[1]) && + (xp >= 0.0 && xp < colsF-dimSteps[0])){ + + // corners of the 3D unit volume cube + ptr_z0 = (int)zp * dims[1]; + ptr_z1 = ptr_z0 + dims[1]; + ptr_y0 = (int)yp * dims[0]; + ptr_y1 = ptr_y0 + dims[0]; + ptr_x0 = (int)xp; + ptr_x1 = ptr_x0 + 1; + dx = xp - (int)xp; + dy = yp - (int)yp; + dz = zp - (int)zp; + + // imageF IS rotated. sample the rotated xp,yp,zp + // and stored in imageG + V000 = imageF[ptr_x0+ptr_y0+ptr_z0]; + V100 = imageF[ptr_x1+ptr_y0+ptr_z0]; + V010 = imageF[ptr_x0+ptr_y1+ptr_z0]; + V001 = imageF[ptr_x0+ptr_y0+ptr_z1]; + V011 = imageF[ptr_x0+ptr_y1+ptr_z1]; + V101 = imageF[ptr_x1+ptr_y0+ptr_z1]; + V110 = imageF[ptr_x1+ptr_y1+ptr_z0]; + V111 = imageF[ptr_x1+ptr_y1+ptr_z1]; + + vf = V000 * (1.0-dx) * (1.0 - dy) * (1.0 - dz) + + V100 * (dx) * (1.0 - dy) * (1.0 - dz) + + V010 * (1.0-dx) * (dy) * (1.0 - dz) + + V001 * (1.0-dx) * (1.0 - dy) * (dz) + + V101 * (dx) * (1.0 - dy) * (dz) + + V011 * (1.0-dx) * (dy) * (dz) + + V110 * (dx) * (dy) * (1.0 - dz) + + V111 * (dx) * (dy) * (dz); + + imageG[sliceG+rowG+(int)x] = (int)vf; + + } + } + } + } + + status = 1; + + return status; + +} + + + +int NI_VolumeResample(int layersS, int rowsS, int colsS, int layersD, int rowsD, int colsD, + int scale, int mode, unsigned char *imageD, unsigned char *imageS, double *Z) +{ + + int i; + int x, y, z; + int sliceSizeSrc; + int sliceSizeDst; + int status; + int ivf; + int xf, xg, yg, zg; + int g_slice, f_slice; + int g_row, f_row; + int g_slicesize, f_slicesize; + int itemp, sOffset, dOffset; + int XInt, YInt, ZInt; + float ps1, ps2, ps3; + float Y[4], tpoint, reSampler; + float XPrime, YPrime, ZPrime; + float C, R, L; + float *RLUT; + float *samples; + + if(mode ==1){ + /* + * integer subsample + */ + g_slicesize = rowsD * colsD; + f_slicesize = rowsS * colsS; + for(zg = 0; zg < layersD; ++zg){ + g_slice = zg * g_slicesize; + f_slice = zg * scale * f_slicesize; + for(yg = 0; yg < rowsD; ++yg){ + g_row = yg * colsD; + f_row = yg * scale * colsS; + for(xg = 0; xg < colsD; ++xg){ + xf = xg * scale; + ivf = imageS[f_slice+f_row+xf]; + imageD[g_slice+g_row+xg] = ivf; + } + } + } + } + else if(mode ==2){ + /* + * fractional cubic convolution resample + */ + + /* first resample each column in all rows and all layers */ + + sliceSizeSrc = colsS * rowsS; + sliceSizeDst = colsD * rowsD; + + RLUT = calloc(colsD, sizeof(float)); + samples = calloc(colsS+4, sizeof(float)); + reSampler = (float)1.0/Z[0]; + tpoint = (float)0.0; + for(i = 0; i < colsD; ++i){ + RLUT[i] = tpoint; + tpoint += reSampler; + } + + for(z = 0; z < layersS; ++z){ + sOffset = z * sliceSizeSrc; + dOffset = z * sliceSizeDst; + for(y = 0; y < rowsS; ++y){ + for(x = 0; x < colsS; ++x){ + samples[x] = (float)imageS[sOffset+x]; + } + for(x = 1; x < colsD; ++x){ + XPrime = RLUT[x]; + XInt = (int)XPrime; + C = XPrime - (float)XInt; + Y[0] = samples[XInt-1]; + Y[1] = samples[XInt]; + Y[2] = samples[XInt+1]; + Y[3] = samples[XInt+2]; + ps1 = Y[2] - Y[0]; + ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; + ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; + itemp = (int)(Y[1]+C*(ps1+C*(ps2+C*ps3))); + if(itemp < 0) itemp = 0; + if(itemp > 255) itemp = 255; + imageD[dOffset+x] = itemp; + } + sOffset += colsS; + dOffset += colsD; + } + } + free(RLUT); + free(samples); + + /* second resample each row in all columns and all layers */ + RLUT = calloc(rowsD, sizeof(float)); + samples = calloc(rowsS+4, sizeof(float)); + reSampler = (float)1.0/Z[1]; + tpoint = (float)0.0; + for(i = 0; i < rowsD; ++i){ + RLUT[i] = tpoint; + tpoint += reSampler; + } + + for(z = 0; z < layersS; ++z){ + dOffset = z * sliceSizeDst; + for(x = 0; x < colsD; ++x){ + for(y = 0; y < rowsS; ++y){ + samples[y] = (float)imageD[dOffset+x+y*colsD]; + } + for(y = 1; y < rowsD; ++y){ + YPrime = RLUT[y]; + YInt = (int)YPrime; + R = YPrime - (float)YInt; + Y[0] = samples[YInt-1]; + Y[1] = samples[YInt]; + Y[2] = samples[YInt+1]; + Y[3] = samples[YInt+2]; + ps1 = Y[2] - Y[0]; + ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; + ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; + itemp = (int)(Y[1]+R*(ps1+R*(ps2+R*ps3))); + if(itemp < 0) itemp = 0; + if(itemp > 255) itemp = 255; + imageD[dOffset+x+y*colsD] = itemp; + } + } + } + free(RLUT); + free(samples); + + /* third resample each layers in all columns and all rows */ + RLUT = calloc(layersD, sizeof(float)); + samples = calloc(layersS+4, sizeof(float)); + reSampler = (float)1.0/Z[2]; + tpoint = (float)0.0; + for(i = 0; i < layersD; ++i){ + RLUT[i] = tpoint; + tpoint += reSampler; + } + + for(y = 0; y < rowsD; ++y){ + dOffset = y * colsD; + for(x = 0; x < colsD; ++x){ + for(z = 0; z < layersS; ++z){ + samples[z] = (float)imageD[dOffset+x+z*sliceSizeDst]; + } + for(z = 1; z < layersD; ++z){ + ZPrime = RLUT[z]; + ZInt = (int)ZPrime; + L = ZPrime - (float)ZInt; + Y[0] = samples[ZInt-1]; + Y[1] = samples[ZInt]; + Y[2] = samples[ZInt+1]; + Y[3] = samples[ZInt+2]; + ps1 = Y[2] - Y[0]; + ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; + ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; + itemp = (int)(Y[1]+R*(ps1+R*(ps2+R*ps3))); + if(itemp < 0) itemp = 0; + if(itemp > 255) itemp = 255; + imageD[dOffset+x+z*sliceSizeDst] = itemp; + } + } + } + free(RLUT); + free(samples); + } + + status = 1; + + return status; + +} + + +int NI_CubicResample(int layersF, int rowsF, int colsF, int layersG, int rowsG, int colsG, + int *dimSteps, double *M, unsigned char *imageG, unsigned char *imageF) +{ + + int i; + int status; + int sliceG; + int rowG; + int sliceSizeG; + int ivf; + float vf; + float x, y, z; + float xp, yp, zp; + + sliceSizeG = rowsG * colsG; + for(z = 1.0; z < layersG-dimSteps[2]-2; z += dimSteps[2]){ + sliceG = (int)z * sliceSizeG; + for(y = 1.0; y < rowsG-dimSteps[1]-2; y += dimSteps[1]){ + rowG = (int)y * colsG; + for(x = 1.0; x < colsG-dimSteps[0]-2; x += dimSteps[0]){ + // get the 'from' coordinates + xp = M[0]*x + M[1]*y + M[2]*z + M[3]; + yp = M[4]*x + M[5]*y + M[6]*z + M[7]; + zp = M[8]*x + M[9]*y + M[10]*z + M[11]; + // clip the resample window + if((zp >= 1.0 && zp < layersF-dimSteps[2]-2) && + (yp >= 1.0 && yp < rowsF-dimSteps[1]-2) && + (xp >= 1.0 && xp < colsF-dimSteps[0]-2)){ + vf = tri_cubic_convolve(imageF, (int)xp, (int)yp, (int)zp, xp, yp, + zp, colsG, rowsG, layersG, sliceSizeG); + /* clip at hard edges */ + if(vf < 0.0) vf = 0.0; + if(vf > 255.0) vf = 255.0; + imageG[sliceG+rowG+(int)x] = (int)vf; + } + } + } + } + + status = 1; + + return status; + +} + +int NI_ImageThreshold(int layers, int rows, int cols, unsigned short *image, double *H, + double *IH, int histogram_elements, double threshold, int *index) +{ + + int i, j, k; + int status; + int ptr; + int value; + float sum; + + for(i = 0; i < histogram_elements; ++i){ + H[i] = 0; + IH[i] = 0; + } + ptr = 0; + for(i = 0; i < layers; ++i){ + for(j = 0; j < rows; ++j){ + for(k = 0; k < cols; ++k){ + value = image[ptr++]; + ++H[value]; + } + } + } + + sum = 0.0; + for(i = 0; i < histogram_elements; ++i){ + sum += H[i]; + } + /* normalize the volume histogram */ + for(i = 0; i < histogram_elements; ++i){ + H[i] = H[i] / sum; + } + + /* build the integrated histogram */ + IH[0] = H[0]; + for(i = 1; i < histogram_elements; ++i){ + IH[i] = IH[i-1] + H[i]; + } + + /* get the threshold crossing. this deals with the high amplitude outliers in the volume */ + *index = histogram_elements-1; + for(i = 0; i < histogram_elements; ++i){ + if(IH[i] > threshold){ + *index = i; + break; + } + } + + status = 1; + + return status; + +} + + +int NI_ResampleWithGradient(int layersS, int rowsS, int colsS, int layersD, int rowsD, + int colsD, int *dimSteps, double *M, unsigned char *imageD, + unsigned char *imageS, double *scale, int *offset, double *gradientX, + double *gradientY, double *gradientZ) +{ + + int i; + int seed; + int status; + int sliceD; + int rowD; + int sliceSizeD; + int dimsS[3]; + int dimsD[3]; + int dims[2]; + float vs; + float x, y, z; + float xp, yp, zp; + float dx1, dy1, dz1; + float dx2, dy2, dz2; + float ran_x, ran_y, ran_z; + float dx, dy, dz; + double gradX, gradY, gradZ; + + int ptr_x0; + int ptr_y0; + int ptr_z0; + int ptr_x1; + int ptr_y1; + int ptr_z1; + // + // Vxyz for [0,1] values of x, y, z + // + int V000; + int V100; + int V010; + int V001; + int V011; + int V101; + int V110; + int V111; + float valueXYZ; + + sliceSizeD = rowsD * colsD; + dimsD[0] = colsD; + dimsD[1] = rowsD; + dimsD[2] = layersD; + dimsS[0] = colsS; + dimsS[1] = rowsS; + dimsS[2] = layersS; + + dims[0] = dimsS[0]; + dims[1] = dimsS[0]*dimsS[1]; + + seed = 1000; + srand(seed); + + for(z = 0.0; z < layersD-dimSteps[2]-1; z += dimSteps[2]){ + sliceD = (int)z * sliceSizeD; + for(y = 0.0; y < rowsD-dimSteps[1]-1; y += dimSteps[1]){ + rowD = (int)y * colsD; + for(x = 0.0; x < colsD-dimSteps[0]-1; x += dimSteps[0]){ + + /* jitter the coordinates to prevent aliasing */ + ran_x = 1.0 * rand()/((float)RAND_MAX); + ran_y = 1.0 * rand()/((float)RAND_MAX); + ran_z = 1.0 * rand()/((float)RAND_MAX); + + dx = x + ran_x; + dy = y + ran_y; + dz = z + ran_z; + + // get the 'from' coordinates + xp = M[0]*dx + M[1]*dy + M[2]*dz + M[3]; + yp = M[4]*dx + M[5]*dy + M[6]*dz + M[7]; + zp = M[8]*dx + M[9]*dy + M[10]*dz + M[11]; + // clip the resample window + if((zp >= 0.0 && zp < layersS-dimSteps[2]) && + (yp >= 0.0 && yp < rowsS-dimSteps[1]) && + (xp >= 0.0 && xp < colsS-dimSteps[0])){ + + // corners of the 3D unit volume cube + ptr_z0 = (int)zp * dims[1]; + ptr_z1 = ptr_z0 + dims[1]; + ptr_y0 = (int)yp * dims[0]; + ptr_y1 = ptr_y0 + dims[0]; + ptr_x0 = (int)xp; + ptr_x1 = ptr_x0 + 1; + + dx1 = xp - (int)xp; + dy1 = yp - (int)yp; + dz1 = zp - (int)zp; + dx2 = 1.0 - dx1; + dy2 = 1.0 - dy1; + dz2 = 1.0 - dz1; + + V000 = imageS[ptr_x0+ptr_y0+ptr_z0]; + V100 = imageS[ptr_x1+ptr_y0+ptr_z0]; + V010 = imageS[ptr_x0+ptr_y1+ptr_z0]; + V001 = imageS[ptr_x0+ptr_y0+ptr_z1]; + V011 = imageS[ptr_x0+ptr_y1+ptr_z1]; + V101 = imageS[ptr_x1+ptr_y0+ptr_z1]; + V110 = imageS[ptr_x1+ptr_y1+ptr_z0]; + V111 = imageS[ptr_x1+ptr_y1+ptr_z1]; + + vs = V000 * (dx2) * (dy2) * (dz2) + + V100 * (dx1) * (dy2) * (dz2) + + V010 * (dx2) * (dy1) * (dz2) + + V001 * (dx2) * (dy2) * (dz1) + + V101 * (dx1) * (dy2) * (dz1) + + V011 * (dx2) * (dy1) * (dz1) + + V110 * (dx1) * (dy1) * (dz2) + + V111 * (dx1) * (dy1) * (dz1); + + /* resampled voxel */ + imageD[sliceD+rowD+(int)x] = (int)(vs*scale[(int)zp]) + offset[(int)zp]; + + /* + * x gradient voxel. for no resample dz1, dy1 = 0.0 and + * dy2, dz2 = 1.0 so gradX = V100 - V000 + */ + + /* d/d(dx1) = 1.0, d/d(dx2) = -1.0 */ + gradX = V000 * (-1.0) * (dy2) * (dz2) + + V100 * (1.0) * (dy2) * (dz2) + + V010 * (-1.0) * (dy1) * (dz2) + + V001 * (-1.0) * (dy2) * (dz1) + + V101 * (1.0) * (dy2) * (dz1) + + V011 * (-1.0) * (dy1) * (dz1) + + V110 * (1.0) * (dy1) * (dz2) + + V111 * (1.0) * (dy1) * (dz1); + + /* d/d(dy1) = 1.0, d/d(dy2) = -1.0 */ + gradY = V000 * (dx2) * (-1.0) * (dz2) + + V100 * (dx1) * (-1.0) * (dz2) + + V010 * (dx2) * (1.0) * (dz2) + + V001 * (dx2) * (-1.0) * (dz1) + + V101 * (dx1) * (-1.0) * (dz1) + + V011 * (dx2) * (1.0) * (dz1) + + V110 * (dx1) * (1.0) * (dz2) + + V111 * (dx1) * (1.0) * (dz1); + + /* d/d(dz1) = 1.0, d/d(dz2) = -1.0 */ + gradZ = V000 * (dx2) * (dy2) * (-1.0) + + V100 * (dx1) * (dy2) * (-1.0) + + V010 * (dx2) * (dy1) * (-1.0) + + V001 * (dx2) * (dy2) * (1.0) + + V101 * (dx1) * (dy2) * (1.0) + + V011 * (dx2) * (dy1) * (1.0) + + V110 * (dx1) * (dy1) * (-1.0) + + V111 * (dx1) * (dy1) * (1.0); + + gradientX[sliceD+rowD+(int)x] = (gradX*scale[(int)zp]); + gradientY[sliceD+rowD+(int)x] = (gradY*scale[(int)zp]); + gradientZ[sliceD+rowD+(int)x] = (gradZ*scale[(int)zp]); + + } + } + } + } + + status = 1; + + return status; + +} + + +int NI_Resample_Gradient_Coords(int size, int layersS, int rowsS, int colsS, int layersD, int rowsD, + int colsD, int *dimSteps, double *X, double *Y, double *Z, + unsigned char *imageD, unsigned char *imageS, double *scale, + int *offset, double *gradientX, double *gradientY, double *gradientZ) +{ + + int i; + int status; + int sliceSizeD; + int dimsS[3]; + int dimsD[3]; + int dims[2]; + float vs; + float xp, yp, zp; + float dx1, dy1, dz1; + float dx2, dy2, dz2; + double gradX, gradY, gradZ; + + int ptr_x0; + int ptr_y0; + int ptr_z0; + int ptr_x1; + int ptr_y1; + int ptr_z1; + // + // Vxyz for [0,1] values of x, y, z + // + int V000; + int V100; + int V010; + int V001; + int V011; + int V101; + int V110; + int V111; + float valueXYZ; + + sliceSizeD = rowsD * colsD; + dimsD[0] = colsD; + dimsD[1] = rowsD; + dimsD[2] = layersD; + dimsS[0] = colsS; + dimsS[1] = rowsS; + dimsS[2] = layersS; + + dims[0] = dimsS[0]; + dims[1] = dimsS[0]*dimsS[1]; + + for(i = 0; i < size; ++i){ + // get the 'from' unrolled coordinates + zp = Z[i]; + yp = Y[i]; + xp = X[i]; + + // clip the resample window + if((zp >= 0.0 && zp < layersS-dimSteps[2]) && + (yp >= 0.0 && yp < rowsS-dimSteps[1]) && + (xp >= 0.0 && xp < colsS-dimSteps[0])){ + + // corners of the 3D unit volume cube + ptr_z0 = (int)zp * dims[1]; + ptr_z1 = ptr_z0 + dims[1]; + ptr_y0 = (int)yp * dims[0]; + ptr_y1 = ptr_y0 + dims[0]; + ptr_x0 = (int)xp; + ptr_x1 = ptr_x0 + 1; + + dx1 = xp - (int)xp; + dy1 = yp - (int)yp; + dz1 = zp - (int)zp; + dx2 = 1.0 - dx1; + dy2 = 1.0 - dy1; + dz2 = 1.0 - dz1; + + V000 = imageS[ptr_x0+ptr_y0+ptr_z0]; + V100 = imageS[ptr_x1+ptr_y0+ptr_z0]; + V010 = imageS[ptr_x0+ptr_y1+ptr_z0]; + V001 = imageS[ptr_x0+ptr_y0+ptr_z1]; + V011 = imageS[ptr_x0+ptr_y1+ptr_z1]; + V101 = imageS[ptr_x1+ptr_y0+ptr_z1]; + V110 = imageS[ptr_x1+ptr_y1+ptr_z0]; + V111 = imageS[ptr_x1+ptr_y1+ptr_z1]; + + vs = V000 * (dx2) * (dy2) * (dz2) + + V100 * (dx1) * (dy2) * (dz2) + + V010 * (dx2) * (dy1) * (dz2) + + V001 * (dx2) * (dy2) * (dz1) + + V101 * (dx1) * (dy2) * (dz1) + + V011 * (dx2) * (dy1) * (dz1) + + V110 * (dx1) * (dy1) * (dz2) + + V111 * (dx1) * (dy1) * (dz1); + + /* resampled voxel saved in the unrolled clipped volume */ + imageD[i] = (int)(vs*scale[(int)zp]) + offset[(int)zp]; + + /* + * x gradient voxel. for no resample dz1, dy1 = 0.0 and + * dy2, dz2 = 1.0 so gradX = V100 - V000 + */ + + /* d/d(dx1) = 1.0, d/d(dx2) = -1.0 */ + gradX = V000 * (-1.0) * (dy2) * (dz2) + + V100 * (1.0) * (dy2) * (dz2) + + V010 * (-1.0) * (dy1) * (dz2) + + V001 * (-1.0) * (dy2) * (dz1) + + V101 * (1.0) * (dy2) * (dz1) + + V011 * (-1.0) * (dy1) * (dz1) + + V110 * (1.0) * (dy1) * (dz2) + + V111 * (1.0) * (dy1) * (dz1); + + /* d/d(dy1) = 1.0, d/d(dy2) = -1.0 */ + gradY = V000 * (dx2) * (-1.0) * (dz2) + + V100 * (dx1) * (-1.0) * (dz2) + + V010 * (dx2) * (1.0) * (dz2) + + V001 * (dx2) * (-1.0) * (dz1) + + V101 * (dx1) * (-1.0) * (dz1) + + V011 * (dx2) * (1.0) * (dz1) + + V110 * (dx1) * (1.0) * (dz2) + + V111 * (dx1) * (1.0) * (dz1); + + /* d/d(dz1) = 1.0, d/d(dz2) = -1.0 */ + gradZ = V000 * (dx2) * (dy2) * (-1.0) + + V100 * (dx1) * (dy2) * (-1.0) + + V010 * (dx2) * (dy1) * (-1.0) + + V001 * (dx2) * (dy2) * (1.0) + + V101 * (dx1) * (dy2) * (1.0) + + V011 * (dx2) * (dy1) * (1.0) + + V110 * (dx1) * (dy1) * (-1.0) + + V111 * (dx1) * (dy1) * (1.0); + + /* gradients saved in the unrolled clipped gradient volume */ + gradientX[i] = (gradX*scale[(int)zp]); + gradientY[i] = (gradY*scale[(int)zp]); + gradientZ[i] = (gradZ*scale[(int)zp]); + + } + + } + + status = 1; + + return status; + +} + + + +int NI_Resample_Coords(int size, int layersS, int rowsS, int colsS, int layersD, int rowsD, + int colsD, int *dimSteps, double *X, double *Y, double *Z, + unsigned char *imageD, unsigned char *imageS, double *scale, int *offset) +{ + + int i; + int status; + int sliceSizeD; + int dimsS[3]; + int dimsD[3]; + int dims[2]; + float vs; + float xp, yp, zp; + float dx1, dy1, dz1; + float dx2, dy2, dz2; + + int ptr_x0; + int ptr_y0; + int ptr_z0; + int ptr_x1; + int ptr_y1; + int ptr_z1; + // + // Vxyz for [0,1] values of x, y, z + // + int V000; + int V100; + int V010; + int V001; + int V011; + int V101; + int V110; + int V111; + float valueXYZ; + + sliceSizeD = rowsD * colsD; + dimsD[0] = colsD; + dimsD[1] = rowsD; + dimsD[2] = layersD; + dimsS[0] = colsS; + dimsS[1] = rowsS; + dimsS[2] = layersS; + + dims[0] = dimsS[0]; + dims[1] = dimsS[0]*dimsS[1]; + + for(i = 0; i < size; ++i){ + // get the 'from' unrolled coordinates + zp = Z[i]; + yp = Y[i]; + xp = X[i]; + + // clip the resample window + if((zp >= 0.0 && zp < layersS-dimSteps[2]) && + (yp >= 0.0 && yp < rowsS-dimSteps[1]) && + (xp >= 0.0 && xp < colsS-dimSteps[0])){ + + // corners of the 3D unit volume cube + ptr_z0 = (int)zp * dims[1]; + ptr_z1 = ptr_z0 + dims[1]; + ptr_y0 = (int)yp * dims[0]; + ptr_y1 = ptr_y0 + dims[0]; + ptr_x0 = (int)xp; + ptr_x1 = ptr_x0 + 1; + + dx1 = xp - (int)xp; + dy1 = yp - (int)yp; + dz1 = zp - (int)zp; + dx2 = 1.0 - dx1; + dy2 = 1.0 - dy1; + dz2 = 1.0 - dz1; + + V000 = imageS[ptr_x0+ptr_y0+ptr_z0]; + V100 = imageS[ptr_x1+ptr_y0+ptr_z0]; + V010 = imageS[ptr_x0+ptr_y1+ptr_z0]; + V001 = imageS[ptr_x0+ptr_y0+ptr_z1]; + V011 = imageS[ptr_x0+ptr_y1+ptr_z1]; + V101 = imageS[ptr_x1+ptr_y0+ptr_z1]; + V110 = imageS[ptr_x1+ptr_y1+ptr_z0]; + V111 = imageS[ptr_x1+ptr_y1+ptr_z1]; + + vs = V000 * (dx2) * (dy2) * (dz2) + + V100 * (dx1) * (dy2) * (dz2) + + V010 * (dx2) * (dy1) * (dz2) + + V001 * (dx2) * (dy2) * (dz1) + + V101 * (dx1) * (dy2) * (dz1) + + V011 * (dx2) * (dy1) * (dz1) + + V110 * (dx1) * (dy1) * (dz2) + + V111 * (dx1) * (dy1) * (dz1); + + /* resampled voxel saved in the unrolled clipped volume */ + imageD[i] = (int)(vs*scale[(int)zp]) + offset[(int)zp]; + } + + } + + status = 1; + + return status; + +} + + + +int NI_LT_Mrqcof(double *alpha, double *beta, double *V, double wt, double value, int M1){ + + int i, j; + double v1; + int status; + + for(i = 0; i < M1; ++i){ + v1 = V[i]; + beta[i] = v1 * value * wt; + for(j = 0; j <= i; ++j){ + alpha[M1*i+j] = v1 * V[j]; + } + } + + status = 1; + + return status; + +} + + +int NI_LT_Tensor_Product(double *alpha_1, double *alpha_2, double *beta_1, double *beta_2, double *basis, + int M1, int M2, int rows, int row_number, int coeff_1, int coeff_2){ + + + // + // lower triangular tensor product + // + + int i, j, k, m; + int loop3_outer, loop3_inner; + int status; + double wt1; + double wt2; + double *ptr1; + double *ptr2; + + for(i = 0; i < coeff_1; ++i){ + wt1 = basis[rows*i + row_number]; + for(loop3_outer = 0; loop3_outer < 3; ++loop3_outer){ + // + // spatial-spatial covariances + // + for(loop3_inner = 0; loop3_inner <= loop3_outer; ++loop3_inner){ + for(j = 0; j <= i; ++j){ + // + // outer product of basis array + // + wt2 = wt1 * basis[rows*j + row_number]; + ptr1 = &alpha_1[coeff_2*(M1*(coeff_1*loop3_outer+i)+(coeff_1*loop3_inner)+j)]; + ptr2 = &alpha_2[coeff_2*(M2*loop3_outer+loop3_inner)]; + for(k = 0; k < coeff_2; ++k){ + for(m = 0; m <= k; ++m){ + ptr1[M1*k+m] += (wt2 * ptr2[M2*k+m]); + } + } + } + // + // spatial-intensity covariances (single G volume assumed) + // + ptr1 = &alpha_1[coeff_2*(M1*coeff_1*3+(coeff_1*loop3_inner)+i)]; + ptr2 = &alpha_2[coeff_2*(M2*3+loop3_outer)]; + for(k = 0; k < coeff_2; ++k){ + ptr1[M1+k] += (wt1 * ptr2[M2+k]); + } + // + // spatial component of beta + // + for(k = 0; k < coeff_2; ++k){ + beta_1[k+coeff_2*(coeff_1*loop3_outer+i)] += (wt1 * beta_2[coeff_2*loop3_outer+k]); + } + } + } + } + + // + // intensity-intensity covariances + // + ptr1 = &alpha_1[coeff_2*(M1*coeff_1*3+(coeff_1*3))]; + ptr2 = &alpha_2[coeff_2*(M2*3+3)]; + for(k = 0; k < coeff_2; ++k){ + ptr1[k] += ptr2[k]; + } + + // + // intensity component of beta + // + + beta_1[coeff_2*coeff_1*3] += beta_2[coeff_2*3]; + + status = 1; + + return status; + +} + + + +int NI_Complete_Symmetry(double *Alpha, int nx, int ny, int nz, int ni4){ + + // + // complete symmetry of Alpha matrix over the 3D brain volume + // + + int z1, z2; + int y1, y2; + int x1, x2; + int loop3_outer, loop3_inner; + int M1; + int status; + double *ptrx; + double *ptry; + double *ptrz; + + M1 = 3*nx*ny*nz + ni4; + + for(loop3_outer = 0; loop3_outer < 3; ++loop3_outer){ + for(loop3_inner = 0; loop3_inner <= loop3_outer; ++loop3_inner){ + ptrz = &Alpha[nx*ny*nz*(M1*loop3_outer+loop3_inner)]; + for(z1 = 0; z1 < nz; ++z1){ + for(z2 = 0; z2 <= z1; ++z2){ + ptry = ptrz + nx*ny*(M1*z1 + z2); + for(y1 = 0; y1 < ny; ++y1){ + for(y2 = 0; y2 <= y1; ++y2){ + ptrx = ptry + nx*(M1*y1 + y2); + for(x1 = 0; x1 <= nx; ++x1){ + for(y2 = 0; y2 <= y1; ++y2){ + ptrx[M1*x2+x1] = ptrx[M1*x1+x2]; + } + } + } + } + for(x1 = 0; x1 < nx*ny; ++x1){ + for(x2 = 0; x2 < x1; ++x2){ + ptry[M1*x2+x1] = ptry[M1*x1+x2]; + } + } + } + for(x1 = 0; x1 < nx*ny*nz; ++x1){ + for(x2 = 0; x2 < x1; ++x2){ + ptrz[M1*x2+x1] = ptrz[M1*x1+x2]; + } + } + + } + } + } + + for(x1 = 0; x1 < nx*ny*nz*3+ni4; ++x1){ + for(x2 = 0; x2 < x1; ++x2){ + Alpha[M1*x2+x1] = Alpha[M1*x1+x2]; + } + } + + + status = 1; + + return status; + +} + + + + Added: branches/Interpolate1D/ndimage/segment/Segmenter_EXT.c =================================================================== --- branches/Interpolate1D/ndimage/segment/Segmenter_EXT.c 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/segment/Segmenter_EXT.c 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,682 @@ +#include "ndImage_Segmenter_structs.h" +#include "Python.h" +#include "numpy/arrayobject.h" + +static PyObject *Segmenter_EdgePreFilter(PyObject *self, PyObject *args) +{ + + int lowThreshold; + int highThreshold; + int num; + int nd; + int type; + int aperature; + int half_taps; + npy_intp *dims; + unsigned short *fP1; + double *fP2; + double *pKernel; + PyObject *iArray = NULL; + PyObject *eArray = NULL; + PyObject *kernel = NULL; + + // + // pass in 2D LPF coefficients + if(!PyArg_ParseTuple(args, "iiiOOO", &lowThreshold, &highThreshold, + &half_taps, &kernel, &iArray, &eArray)) + goto exit; + + fP1 = (unsigned short *)PyArray_DATA(iArray); + nd = PyArray_NDIM(iArray); + dims = PyArray_DIMS(iArray); + type = PyArray_TYPE(iArray); + num = PyArray_SIZE(iArray); + fP2 = (double *)PyArray_DATA(eArray); + pKernel = (double *)PyArray_DATA(kernel); + aperature = PyArray_SIZE(kernel); + + if(!PyArray_ISCONTIGUOUS(iArray) || !PyArray_ISCONTIGUOUS(eArray)) + goto exit; + + + if(!NI_EdgePreFilter(num, (int)dims[0], (int)dims[1], lowThreshold, + highThreshold, aperature, half_taps, fP1, fP2, pKernel)) + + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Segmenter_SobelImage(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + npy_intp *dims; + double *fP1; + double *fP2; + double pAve; + int minValue; + int maxValue; + PyObject *iArray = NULL; + PyObject *eArray = NULL; + + if(!PyArg_ParseTuple(args, "OO", &iArray, &eArray)) + goto exit; + + fP1 = (double *)PyArray_DATA(iArray); + nd = PyArray_NDIM(iArray); + dims = PyArray_DIMS(iArray); + type = PyArray_TYPE(iArray); + num = PyArray_SIZE(iArray); + fP2 = (double *)PyArray_DATA(eArray); + + if(!PyArray_ISCONTIGUOUS(iArray) || !PyArray_ISCONTIGUOUS(eArray)) + goto exit; + + + if(!NI_SobelImage(num, (int)dims[0], (int)dims[1], fP1, fP2, &pAve, &minValue, &maxValue)) + + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("dii", pAve, minValue, maxValue); + +} + + +static PyObject *Segmenter_SobelEdges(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + npy_intp *dims; + double *fP1; + unsigned short *fP2; + double pAve; + int minValue; + int maxValue; + int mode; + double sobelLow; + PyObject *iArray = NULL; + PyObject *eArray = NULL; + + if(!PyArg_ParseTuple(args, "OOdiiid", &iArray, &eArray, &pAve, &minValue, &maxValue, &mode, + &sobelLow)) + goto exit; + + fP1 = (double *)PyArray_DATA(iArray); + nd = PyArray_NDIM(iArray); + dims = PyArray_DIMS(iArray); + type = PyArray_TYPE(iArray); + num = PyArray_SIZE(iArray); + fP2 = (unsigned short *)PyArray_DATA(eArray); + + if(!PyArray_ISCONTIGUOUS(iArray) || !PyArray_ISCONTIGUOUS(eArray)) + goto exit; + + + if(!NI_SobelEdge(num, (int)dims[0], (int)dims[1], fP1, fP2, mode, pAve, minValue, maxValue, sobelLow)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + + +static PyObject *Segmenter_GetBlobs(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int mask; + npy_intp *dims; + unsigned short *fP1; + unsigned short *fP2; + int groups; + PyObject *iArray = NULL; + PyObject *eArray = NULL; + + if(!PyArg_ParseTuple(args, "OOi", &iArray, &eArray, &mask)) + goto exit; + + fP1 = (unsigned short *)PyArray_DATA(iArray); + nd = PyArray_NDIM(iArray); + dims = PyArray_DIMS(iArray); + type = PyArray_TYPE(iArray); + num = PyArray_SIZE(iArray); + fP2 = (unsigned short *)PyArray_DATA(eArray); + + if(!PyArray_ISCONTIGUOUS(iArray) || !PyArray_ISCONTIGUOUS(eArray)) + goto exit; + + + if(nd == 2){ + if(!NI_GetBlobs2D(num, (int)dims[0], (int)dims[1], fP1, fP2, &groups, mask)) + goto exit; + } + else if(nd == 3){ + if(!NI_GetBlobs3D(num, (int)dims[0], (int)dims[1], (int)dims[2], fP1, fP2, + &groups, mask)) + goto exit; + } + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("i", groups); + +} + +static PyObject *Segmenter_GetBlobRegions(PyObject *self, PyObject *args) +{ + + + int num; + int nd; + int type; + npy_intp *dims; + npy_intp *objNumber; + unsigned short *fP1; + PyObject *iArray = NULL; + PyObject *nArray = NULL; + objStruct *myData; + + if(!PyArg_ParseTuple(args, "OO", &iArray, &nArray)) + goto exit; + + if(!PyArray_ISCONTIGUOUS(iArray) || !PyArray_ISCONTIGUOUS(nArray)) + goto exit; + + // + // PyArray_ContiguousFromObject or PyArray_ContiguousFromAny to be explored + // for non-contiguous + // + + + // pointer to the edge-labeled image + nd = PyArray_NDIM(iArray); + dims = PyArray_DIMS(iArray); + type = PyArray_TYPE(iArray); + num = PyArray_SIZE(iArray); + fP1 = (unsigned short *)PyArray_DATA(iArray); + + // the object descriptor array that was allocated from numpy + objNumber = PyArray_DIMS(nArray); // this is the number of labels in the edge image + myData = (objStruct*)PyArray_DATA(nArray); + + /* need to pass in 2D/3D flag and mask. NI_GetBlobRegions will call + * 2D or 3D blob_extraction */ + + if(nd == 2){ + if(!NI_GetBlobRegions2D((int)dims[0], (int)dims[1], (int)objNumber[0], fP1, myData)) + goto exit; + } + else if(nd == 3){ + if(!NI_GetBlobRegions3D((int)dims[0], (int)dims[1], (int)dims[2], + (int)objNumber[0], fP1, myData)) + goto exit; + } + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Segmenter_ThinFilter(PyObject *self, PyObject *args) +{ + + int number_masks; + int roi_rows; + int roi_cols; + int cols; + unsigned char *input; + unsigned char *cinput; + unsigned char *erosion; + unsigned char *dialation; + unsigned char *hmt; + unsigned char *copy; + unsigned short *j_mask; + unsigned short *k_mask; + PyObject *jArray = NULL; + PyObject *kArray = NULL; + PyObject *iArray = NULL; + PyObject *cArray = NULL; + PyObject *eArray = NULL; + PyObject *dArray = NULL; + PyObject *hArray = NULL; + PyObject *pArray = NULL; + + if(!PyArg_ParseTuple(args, "OOiiiiOOOOOO", &jArray, &kArray, &number_masks, &roi_rows, + &roi_cols, &cols, &iArray, &cArray, &eArray, &dArray, &hArray, &pArray)) + goto exit; + + + j_mask = (unsigned short *)PyArray_DATA(jArray); + k_mask = (unsigned short *)PyArray_DATA(kArray); + + input = (unsigned char *)PyArray_DATA(iArray); + cinput = (unsigned char *)PyArray_DATA(cArray); + erosion = (unsigned char *)PyArray_DATA(eArray); + dialation = (unsigned char *)PyArray_DATA(dArray); + hmt = (unsigned char *)PyArray_DATA(hArray); + copy = (unsigned char *)PyArray_DATA(pArray); + + if(!PyArray_ISCONTIGUOUS(iArray)) + goto exit; + + if(!NI_ThinMorphoFilter(roi_rows, roi_cols, cols, number_masks, j_mask, k_mask, + input, cinput, erosion, dialation, hmt, copy)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Segmenter_CannyFilter(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int aperature; + npy_intp *dims; + double *fP1; + double *h_DG_image; + double *v_DG_image; + double *pKernel; + float aveXValue; + float aveYValue; + PyObject *iArray = NULL; + PyObject *hArray = NULL; + PyObject *vArray = NULL; + PyObject *kernel = NULL; + + if(!PyArg_ParseTuple(args, "OOOOi", &iArray, &hArray, &vArray, &kernel, &aperature)) + goto exit; + + fP1 = (double *)PyArray_DATA(iArray); + nd = PyArray_NDIM(iArray); + dims = PyArray_DIMS(iArray); + type = PyArray_TYPE(iArray); + num = PyArray_SIZE(iArray); + + h_DG_image = (double *)PyArray_DATA(hArray); + v_DG_image = (double *)PyArray_DATA(vArray); + pKernel = (double *)PyArray_DATA(kernel); + + if(!PyArray_ISCONTIGUOUS(iArray)) + goto exit; + + if(!NI_CannyFilter(num, (int)dims[0], (int)dims[1], fP1, h_DG_image, + v_DG_image, pKernel, aperature, &aveXValue, &aveYValue)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("dd", aveXValue, aveYValue); + +} + + + + +static PyObject *Segmenter_CannyNonMaxSupress(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int aperature; + int mode; + npy_intp *dims; + double *h_DG_image; + double *v_DG_image; + double *magnitude; + double aveXValue; + double aveYValue; + double aveMagnitude; + double canny_low; + double canny_high; + double canny_l; + double canny_h; + PyObject *mArray = NULL; + PyObject *hArray = NULL; + PyObject *vArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOidddd", &hArray, &vArray, &mArray, &mode, &aveXValue, + &aveYValue, &canny_l, &canny_h)) + goto exit; + + magnitude = (double *)PyArray_DATA(mArray); + nd = PyArray_NDIM(mArray); + dims = PyArray_DIMS(mArray); + type = PyArray_TYPE(mArray); + num = PyArray_SIZE(mArray); + + h_DG_image = (double *)PyArray_DATA(hArray); + v_DG_image = (double *)PyArray_DATA(vArray); + + if(!PyArray_ISCONTIGUOUS(mArray)) + goto exit; + + if(!NI_CannyNonMaxSupress(num, (int)dims[0], (int)dims[1], magnitude, h_DG_image, + v_DG_image, mode, aveXValue, aveYValue, &aveMagnitude, + &canny_low, &canny_high, canny_l, canny_h)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("ddd", aveMagnitude, canny_low, canny_high); + +} + + + +static PyObject *Segmenter_CannyHysteresis(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int aperature; + int mode; + npy_intp *dims; + double *magnitude; + unsigned short *hys_image; + double canny_low; + double canny_high; + PyObject *mArray = NULL; + PyObject *hArray = NULL; + + if(!PyArg_ParseTuple(args, "OOdd", &mArray, &hArray, &canny_low, &canny_high)) + goto exit; + + magnitude = (double *)PyArray_DATA(mArray); + nd = PyArray_NDIM(mArray); + dims = PyArray_DIMS(mArray); + type = PyArray_TYPE(mArray); + num = PyArray_SIZE(mArray); + + hys_image = (unsigned short *)PyArray_DATA(hArray); + + if(!PyArray_ISCONTIGUOUS(mArray)) + goto exit; + + if(!NI_CannyHysteresis(num, (int)dims[0], (int)dims[1], magnitude, hys_image, + canny_low, canny_high)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Segmenter_BinaryEdge(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + npy_intp *dims; + unsigned short *mask_image; + unsigned short *edge_image; + PyObject *mArray = NULL; + PyObject *eArray = NULL; + + if(!PyArg_ParseTuple(args, "OO", &mArray, &eArray)) + goto exit; + + mask_image = (unsigned short *)PyArray_DATA(mArray); + nd = PyArray_NDIM(mArray); + dims = PyArray_DIMS(mArray); + type = PyArray_TYPE(mArray); + num = PyArray_SIZE(mArray); + edge_image = (unsigned short *)PyArray_DATA(eArray); + + if(!PyArray_ISCONTIGUOUS(mArray)) + goto exit; + + if(!NI_BinaryEdge(num, (int)dims[0], (int)dims[1], mask_image, edge_image)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + +static PyObject *Segmenter_LawsTextureMetric(PyObject *self, PyObject *args) +{ + + int i; + int num; + int nd; + int type; + int mode; + npy_intp *dims; + npy_intp *laws_dims; + float *lawsImage; + double *src_image; + unsigned short *mask; + double *L7; + double *E7; + double *S7; + double *W7; + double *R7; + double *O7; + int number_kernels; + int kernel_size; + int filters; + LawsFilter7 lawsFilter; + PyObject *lArray = NULL; + PyObject *mArray = NULL; + PyObject *sArray = NULL; + PyObject *LArray = NULL; + PyObject *EArray = NULL; + PyObject *SArray = NULL; + PyObject *WArray = NULL; + PyObject *RArray = NULL; + PyObject *OArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOiiiOOOOOO", &mArray, &sArray, &lArray, &number_kernels, + &kernel_size, &filters, &LArray, &EArray, + &SArray, &WArray, &RArray, &OArray)) + goto exit; + + src_image = (double*)PyArray_DATA(sArray); + nd = PyArray_NDIM(sArray); + dims = PyArray_DIMS(sArray); + type = PyArray_TYPE(sArray); + num = PyArray_SIZE(sArray); + + laws_dims = PyArray_DIMS(lArray); + mask = (unsigned short *)PyArray_DATA(mArray); + lawsImage = (float*)PyArray_DATA(lArray); + L7 = (double *)PyArray_DATA(LArray); + E7 = (double *)PyArray_DATA(EArray); + S7 = (double *)PyArray_DATA(SArray); + W7 = (double *)PyArray_DATA(WArray); + R7 = (double *)PyArray_DATA(RArray); + O7 = (double *)PyArray_DATA(OArray); + + lawsFilter.numberKernels = number_kernels; + lawsFilter.kernelLength = kernel_size; + lawsFilter.numberFilterLayers = filters; + for(i = 0; i < kernel_size; ++i){ + lawsFilter.lawsKernel[0][i] = L7[i]; + lawsFilter.lawsKernel[1][i] = E7[i]; + lawsFilter.lawsKernel[2][i] = S7[i]; + lawsFilter.lawsKernel[3][i] = W7[i]; + lawsFilter.lawsKernel[4][i] = R7[i]; + lawsFilter.lawsKernel[5][i] = O7[i]; + } + + if(!PyArray_ISCONTIGUOUS(sArray)){ + printf("PyArray_ISCONTIGUOUS error\n"); + goto exit; + } + + if(!NI_LawsTexture(num, (int)dims[0], (int)dims[1], src_image, mask, lawsImage, + lawsFilter)){ + goto exit; + } + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + +static PyObject *Segmenter_RoiCoOccurence(PyObject *self, PyObject *args) +{ + int num; + int nd; + int type; + int distance; + int orientation; + npy_intp *dims; + npy_intp *dims_cocm; + unsigned short *mask_image; + unsigned short *raw_image; + int *coc_matrix; + PyObject *mArray = NULL; + PyObject *rArray = NULL; + PyObject *cArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOii", &mArray, &rArray, &cArray, &distance, &orientation)) + goto exit; + + mask_image = (unsigned short *)PyArray_DATA(mArray); + nd = PyArray_NDIM(mArray); + dims = PyArray_DIMS(mArray); + type = PyArray_TYPE(mArray); + num = PyArray_SIZE(mArray); + raw_image = (unsigned short *)PyArray_DATA(rArray); + coc_matrix = (int *)PyArray_DATA(cArray); + dims_cocm = PyArray_DIMS(cArray); + + if(!PyArray_ISCONTIGUOUS(mArray) || !PyArray_ISCONTIGUOUS(rArray)){ + printf("PyArray_ISCONTIGUOUS error\n"); + goto exit; + } + + if(!NI_RoiCoOccurence(num, (int)dims[0], (int)dims[1], mask_image, raw_image, + coc_matrix, distance, orientation)) + goto exit; + + + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + +static PyObject *Segmenter_GrowRegion(PyObject *self, PyObject *args) +{ + + + int num; + int nd; + int type; + int Label; + int N_connectivity; + double low_threshold; + double high_threshold; + npy_intp *dims; + npy_intp *objNumber; + unsigned short *label; + double *section; + PyObject *sArray = NULL; + PyObject *lArray = NULL; + PyObject *eArray = NULL; + PyObject *nArray = NULL; + objStruct *expanded_ROI; + objStruct *newgrow_ROI; + + if(!PyArg_ParseTuple(args, "OOOOddii", &sArray, &lArray, &eArray, &nArray, &low_threshold, + &high_threshold, &Label, &N_connectivity)){ + printf("PyArg_ParseTuple error\n"); + goto exit; + } + + if(!PyArray_ISCONTIGUOUS(sArray) || !PyArray_ISCONTIGUOUS(lArray)){ + printf("PyArray_ISCONTIGUOUS error\n"); + goto exit; + } + + section = (double *)PyArray_DATA(sArray); + nd = PyArray_NDIM(sArray); + dims = PyArray_DIMS(sArray); + type = PyArray_TYPE(sArray); + num = PyArray_SIZE(sArray); + + label = (unsigned short *)PyArray_DATA(lArray); + expanded_ROI = (objStruct*)PyArray_DATA(eArray); + newgrow_ROI = (objStruct*)PyArray_DATA(nArray); + + if(nd == 2){ + if(!NI_GrowRegion2D((int)dims[0], (int)dims[1], section, label, expanded_ROI, + newgrow_ROI, low_threshold, high_threshold, Label, N_connectivity)) + goto exit; + } + else if(nd == 3){ + if(!NI_GrowRegion3D((int)dims[0], (int)dims[1], (int)dims[2], section, label, + expanded_ROI, newgrow_ROI, low_threshold, high_threshold, + Label, N_connectivity)) + goto exit; + } + + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + +static PyMethodDef SegmenterMethods[] = +{ + { "region_grow", Segmenter_GrowRegion, METH_VARARGS, NULL }, + { "roi_co_occurence", Segmenter_RoiCoOccurence, METH_VARARGS, NULL }, + { "binary_edge", Segmenter_BinaryEdge, METH_VARARGS, NULL }, + { "laws_texture_metric", Segmenter_LawsTextureMetric, METH_VARARGS, NULL }, + { "canny_hysteresis", Segmenter_CannyHysteresis, METH_VARARGS, NULL }, + { "canny_nonmax_supress", Segmenter_CannyNonMaxSupress, METH_VARARGS, NULL }, + { "canny_filter", Segmenter_CannyFilter, METH_VARARGS, NULL }, + { "sobel_edges", Segmenter_SobelEdges, METH_VARARGS, NULL }, + { "sobel_image", Segmenter_SobelImage, METH_VARARGS, NULL }, + { "edge_prefilter", Segmenter_EdgePreFilter, METH_VARARGS, NULL }, + { "get_blobs", Segmenter_GetBlobs, METH_VARARGS, NULL }, + { "get_blob_regions", Segmenter_GetBlobRegions, METH_VARARGS, NULL }, + { "thin_filter", Segmenter_ThinFilter, METH_VARARGS, NULL }, + { NULL, NULL, 0, NULL}, +}; + +PyMODINIT_FUNC init_segment(void) +{ + Py_InitModule("_segment", SegmenterMethods); + import_array(); +} + + + + + Added: branches/Interpolate1D/ndimage/segment/Segmenter_IMPL.c =================================================================== --- branches/Interpolate1D/ndimage/segment/Segmenter_IMPL.c 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/segment/Segmenter_IMPL.c 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,1671 @@ +#include +#include +#include +#include +#include "ndImage_Segmenter_structs.h" + +// these are for this standalone and come out with the full build +// +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define FALSE 0 +#define TRUE 1 + + +int NI_EdgePreFilter(int num, int rows, int cols, int lowThreshold, int highThreshold, + int aperature, int HalfFilterTaps, unsigned short *sImage, double *dImage, + double *kernel){ + + int i, j, k, n, num1; + int offset; + double sum, value; + double *buffer; + int max_buffer = MAX(rows, cols); + int status; + + buffer = calloc(max_buffer+aperature+16, sizeof(double)); + + num1 = HalfFilterTaps; + offset = 0; + for(i = 0; i < rows; ++i){ + /* copy image row to local buffer */ + for(j = 0; j < cols; ++j){ + buffer[num1+j] = sImage[offset+j]; + } + /* constant pad the ends of the buffer */ + for(j = 0; j < num1; ++j){ + buffer[j] = buffer[num1]; + } + for(j = cols+num1; j < cols+2*num1; ++j){ + buffer[j] = buffer[cols-1+num1]; + } + + /* Perform Symmetric Convolution in the X dimension. */ + for(n = 0, j = num1; j < (cols+num1); ++j, ++n){ + sum = buffer[j] * kernel[num1]; + for(k = 1; k < num1; ++k){ + sum += kernel[num1-k] * (buffer[j+k] + buffer[j-k]); + } + dImage[offset+n] = sum; + } + offset += cols; + } + + offset = 0; + for(i = 0; i < cols; ++i){ + /* copy image column to local buffer */ + offset = 0; + for(j = 0; j < rows; ++j){ + buffer[num1+j] = dImage[offset+i]; + offset += cols; + } + /* constant pad the ends of the buffer */ + for(j = 0; j < num1; ++j){ + buffer[j] = buffer[num1]; + } + for(j = rows+num1; j < rows+2*num1; ++j){ + buffer[j] = buffer[rows-1+num1]; + } + + /* Perform Symmetric Convolution in the Y dimension. */ + offset = 0; + for(j = num1; j < (rows+num1); ++j){ + sum = buffer[j] * kernel[num1]; + for(k = 1; k < num1; ++k){ + sum += kernel[num1-k] * (buffer[j+k] + buffer[j-k]); + } + dImage[offset+i] = sum; + offset += cols; + } + } + + /* threshold the image */ + offset = 0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + value = dImage[offset+j]; + if(value < (float)lowThreshold) value = (float)0.0; + if(value > (float)highThreshold) value = (float)0.0; + dImage[offset+j] = value; + } + offset += cols; + } + + free(buffer); + + status = 1; + + return(status); + +} + +int NI_SobelImage(int samples, int rows, int cols, double *rawImage, double *edgeImage, double *pAve, + int *minValue, int *maxValue){ + + int i, j; + int p, m, n; + int offset; + int offsetM1; + int offsetP1; + int status; + int count = 0; + + /* + // Sobel + */ + offset = cols; + *pAve = 0.0; + *minValue = 10000; + *maxValue = -10000; + for(i = 1; i < rows-1; ++i){ + offsetM1 = offset - cols; + offsetP1 = offset + cols; + for(j = 1; j < cols-1; ++j){ + n = 2*rawImage[offsetM1+j] + rawImage[offsetM1+j-1] + rawImage[offsetM1+j+1] - + 2*rawImage[offsetP1+j] - rawImage[offsetP1+j-1] - rawImage[offsetP1+j+1]; + m = 2*rawImage[offset+j-1] + rawImage[offsetM1+j-1] + rawImage[offsetP1+j-1] - + 2*rawImage[offset+j+1] - rawImage[offsetM1+j+1] - rawImage[offsetP1+j+1]; + p = (int)sqrt((float)(m*m) + (float)(n*n)); + if(p > 0){ + *pAve += p; + if(p > *maxValue) *maxValue = p; + if(p < *minValue) *minValue = p; + ++count; + } + edgeImage[offset+j] = p; + } + offset += cols; + } + /* threshold based on ave */ + *pAve /= count; + + status = 1; + + return(status); + +} + + +int NI_BinaryEdge(int samples, int rows, int cols, unsigned short *labelImage, unsigned short *edgeImage){ + + int i, j, k; + int maxValue; + int offset; + int offsetM1; + int offsetP1; + int values3x3[8]; + int status; + + offset = cols; + for(i = 1; i < rows-1; ++i){ + offsetM1 = offset - cols; + offsetP1 = offset + cols; + for(j = 1; j < cols-1; ++j){ + values3x3[0] = labelImage[offset+j] - labelImage[offset+j+1]; + values3x3[1] = labelImage[offset+j] - labelImage[offsetM1+j+1]; + values3x3[2] = labelImage[offset+j] - labelImage[offsetM1+j]; + values3x3[3] = labelImage[offset+j] - labelImage[offsetM1+j-1]; + values3x3[4] = labelImage[offset+j] - labelImage[offset+j-1]; + values3x3[5] = labelImage[offset+j] - labelImage[offsetP1+j-1]; + values3x3[6] = labelImage[offset+j] - labelImage[offsetP1+j]; + values3x3[7] = labelImage[offset+j] - labelImage[offsetP1+j+1]; + maxValue = -1; + for(k = 0; k < 8; ++k){ + maxValue = MAX(maxValue, values3x3[k]); + } + edgeImage[offset+j] = maxValue; + } + offset += cols; + } + + status = 1; + + return(status); + +} + +int NI_SobelEdge(int samples, int rows, int cols, double *edgeImage, unsigned short *edges, + int mode, double pAve, int minValue, int maxValue, double sobelLow){ + + int i, j; + int offset; + int value; + int maxIndex; + int status; + int histogram[256]; + float pThreshold; + double scale; + double step; + + scale = 1.0 / maxValue; + + step = 255.0/(maxValue-minValue); + for(i = 0; i < 256; ++i){ + histogram[i] = 0; + } + offset = 0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + value = (int)(step*(edgeImage[offset+j]-minValue)); + ++histogram[value]; + } + offset += cols; + } + + if(mode == 1){ + /* based on the mean value of edge energy */ + pThreshold = (int)(sobelLow * (float)pAve); + } + else{ + /* based on the mode value of edge energy */ + pThreshold = (sobelLow * (minValue + ((float)maxIndex/step))); + } + + offset = 0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + if(edgeImage[offset+j] > pThreshold){ + edges[offset+j] = 1; + } + else{ + edges[offset+j] = 0; + } + } + offset += cols; + } + + status = 1; + return(status); + +} + +int NI_GetBlobs3D(int samples, int layers, int rows, int cols, unsigned short *edges, + unsigned short *connectedEdges, int *groups, int mask){ + + int i, j, k, l, m; + int lOffset, rOffset, Label; + int lOffsetP, lOffsetN; + int rOffsetP, rOffsetN; + int Classes[4096]; + int dwImageSize, ptr; + bool NewLabel; + bool Change; + bool connected; + int T[27]; + int *ccompImage; + int layerSize; + int count; + int status; + + layerSize = rows * cols; + dwImageSize = layers * rows * cols; + ccompImage = calloc(dwImageSize, sizeof(int )); + + Label = 1; + for(i = 1; i < layers-1; ++i){ + lOffset = i * layerSize; + lOffsetP = lOffset+layerSize; + lOffsetN = lOffset-layerSize; + for(j = 1; j < rows-1; ++j){ + rOffset = j * cols; + rOffsetP = rOffset+cols; + rOffsetN = rOffset-cols; + for(k = 1; k < cols-1; ++k){ + if(edges[lOffset+rOffset+k]){ + /* + check 3x3x3 connectivity + */ + + T[0] = edges[lOffset+rOffset+k]; + T[1] = edges[lOffset+rOffset+k+1]; + T[2] = edges[lOffset+rOffsetN+k+1]; + T[3] = edges[lOffset+rOffsetN+k]; + T[4] = edges[lOffset+rOffsetN+k-1]; + T[5] = edges[lOffset+rOffset+k-1]; + T[6] = edges[lOffset+rOffsetP+k-1]; + T[7] = edges[lOffset+rOffsetP+k]; + T[8] = edges[lOffset+rOffsetP+k+1]; + + T[9] = edges[lOffsetN+rOffset+k]; + T[10] = edges[lOffsetN+rOffset+k+1]; + T[11] = edges[lOffsetN+rOffsetN+k+1]; + T[12] = edges[lOffsetN+rOffsetN+k]; + T[13] = edges[lOffsetN+rOffsetN+k-1]; + T[14] = edges[lOffsetN+rOffset+k-1]; + T[15] = edges[lOffsetN+rOffsetP+k-1]; + T[16] = edges[lOffsetN+rOffsetP+k]; + T[17] = edges[lOffsetN+rOffsetP+k+1]; + + T[18] = edges[lOffsetP+rOffset+k]; + T[19] = edges[lOffsetP+rOffset+k+1]; + T[20] = edges[lOffsetP+rOffsetN+k+1]; + T[21] = edges[lOffsetP+rOffsetN+k]; + T[22] = edges[lOffsetP+rOffsetN+k-1]; + T[23] = edges[lOffsetP+rOffset+k-1]; + T[24] = edges[lOffsetP+rOffsetP+k-1]; + T[25] = edges[lOffsetP+rOffsetP+k]; + T[26] = edges[lOffsetP+rOffsetP+k+1]; + + connected = FALSE; + if(mask == 1){ + count = 0; + for(l = 1; l < 27; ++l){ + count += T[l]; + } + if(count){ + connected = TRUE; + } + } + else if(mask == 6){ + count = (T[2] + T[4] + T[6] + T[8] + T[9] + T[18]); + if(count == 6){ + connected = TRUE; + } + } + else if(mask == 14){ + count = (T[2] + T[4] + T[6] + T[8] + T[9] + T[18] + T[11] + + T[13] + T[15] + T[17] + T[20] + T[22] + T[24] + T[26]); + if(count == 14){ + connected = TRUE; + } + } + else if(mask == 26){ + count = 0; + for(l = 1; l < 27; ++l){ + count += T[l]; + } + if(count == 26){ + connected = TRUE; + } + } + if(connected){ + ccompImage[lOffset+rOffset+k] = Label++; + } + } + } + } + } + + + while(1){ + Change = FALSE; + /* + // TOP-DOWN Pass for labeling + */ + for(i = 1; i < layers-1; ++i){ + lOffset = i * layerSize; + lOffsetP = lOffset+layerSize; + lOffsetN = lOffset-layerSize; + for(j = 1; j < rows-1; ++j){ + rOffset = j * cols; + rOffsetP = rOffset+cols; + rOffsetN = rOffset-cols; + for(k = 1; k < cols-1; ++k){ + if(ccompImage[lOffset+rOffset+k] != 0){ + + T[0] = ccompImage[lOffset+rOffset+k]; + T[1] = ccompImage[lOffset+rOffset+k+1]; + T[2] = ccompImage[lOffset+rOffsetN+k+1]; + T[3] = ccompImage[lOffset+rOffsetN+k]; + T[4] = ccompImage[lOffset+rOffsetN+k-1]; + T[5] = ccompImage[lOffset+rOffset+k-1]; + T[6] = ccompImage[lOffset+rOffsetP+k-1]; + T[7] = ccompImage[lOffset+rOffsetP+k]; + T[8] = ccompImage[lOffset+rOffsetP+k+1]; + + T[9] = ccompImage[lOffsetN+rOffset+k]; + T[10] = ccompImage[lOffsetN+rOffset+k+1]; + T[11] = ccompImage[lOffsetN+rOffsetN+k+1]; + T[12] = ccompImage[lOffsetN+rOffsetN+k]; + T[13] = ccompImage[lOffsetN+rOffsetN+k-1]; + T[14] = ccompImage[lOffsetN+rOffset+k-1]; + T[15] = ccompImage[lOffsetN+rOffsetP+k-1]; + T[16] = ccompImage[lOffsetN+rOffsetP+k]; + T[17] = ccompImage[lOffsetN+rOffsetP+k+1]; + + T[18] = ccompImage[lOffsetP+rOffset+k]; + T[19] = ccompImage[lOffsetP+rOffset+k+1]; + T[20] = ccompImage[lOffsetP+rOffsetN+k+1]; + T[21] = ccompImage[lOffsetP+rOffsetN+k]; + T[22] = ccompImage[lOffsetP+rOffsetN+k-1]; + T[23] = ccompImage[lOffsetP+rOffset+k-1]; + T[24] = ccompImage[lOffsetP+rOffsetP+k-1]; + T[25] = ccompImage[lOffsetP+rOffsetP+k]; + T[26] = ccompImage[lOffsetP+rOffsetP+k+1]; + + m = T[0]; + for(l = 1; l < 27; ++l){ + if(T[l] != 0){ + if(T[l] < m) m = T[l]; + } + } + if(m != ccompImage[lOffset+rOffset+k]){ + Change = TRUE; + ccompImage[lOffset+rOffset+k] = m; + } + } + } + } + } + /* + // BOTTOM-UP Pass for labeling + */ + for(i = layers-1; i > 0; --i){ + lOffset = i * layerSize; + lOffsetP = lOffset+layerSize; + lOffsetN = lOffset-layerSize; + for(j = rows-1; j > 0; --j){ + rOffset = j * cols; + rOffsetP = rOffset+cols; + rOffsetN = rOffset-cols; + for(k = cols-1; k > 0; --k){ + if(ccompImage[lOffset+rOffset+k] != 0){ + + T[0] = ccompImage[lOffset+rOffset+k]; + T[1] = ccompImage[lOffset+rOffset+k+1]; + T[2] = ccompImage[lOffset+rOffsetN+k+1]; + T[3] = ccompImage[lOffset+rOffsetN+k]; + T[4] = ccompImage[lOffset+rOffsetN+k-1]; + T[5] = ccompImage[lOffset+rOffset+k-1]; + T[6] = ccompImage[lOffset+rOffsetP+k-1]; + T[7] = ccompImage[lOffset+rOffsetP+k]; + T[8] = ccompImage[lOffset+rOffsetP+k+1]; + + T[9] = ccompImage[lOffsetN+rOffset+k]; + T[10] = ccompImage[lOffsetN+rOffset+k+1]; + T[11] = ccompImage[lOffsetN+rOffsetN+k+1]; + T[12] = ccompImage[lOffsetN+rOffsetN+k]; + T[13] = ccompImage[lOffsetN+rOffsetN+k-1]; + T[14] = ccompImage[lOffsetN+rOffset+k-1]; + T[15] = ccompImage[lOffsetN+rOffsetP+k-1]; + T[16] = ccompImage[lOffsetN+rOffsetP+k]; + T[17] = ccompImage[lOffsetN+rOffsetP+k+1]; + + T[18] = ccompImage[lOffsetP+rOffset+k]; + T[19] = ccompImage[lOffsetP+rOffset+k+1]; + T[20] = ccompImage[lOffsetP+rOffsetN+k+1]; + T[21] = ccompImage[lOffsetP+rOffsetN+k]; + T[22] = ccompImage[lOffsetP+rOffsetN+k-1]; + T[23] = ccompImage[lOffsetP+rOffset+k-1]; + T[24] = ccompImage[lOffsetP+rOffsetP+k-1]; + T[25] = ccompImage[lOffsetP+rOffsetP+k]; + T[26] = ccompImage[lOffsetP+rOffsetP+k+1]; + + m = T[0]; + for(l = 1; l < 27; ++l){ + if(T[l] != 0){ + if(T[l] < m) m = T[l]; + } + } + if(m != ccompImage[lOffset+rOffset+k]){ + Change = TRUE; + ccompImage[lOffset+rOffset+k] = m; + } + } + } + } + } + + if(!Change) break; + + } /* end while loop */ + + Label = 1; + Classes[0] = 0; + ptr = 0; + for(i = 0; i < layers; ++i){ + for(j = 0; j < rows; ++j){ + for(k = 0; k < cols; ++k){ + m = ccompImage[ptr]; + ++ptr; + if(m > 0){ + NewLabel = TRUE; + for(l = 1; l < Label; ++l){ + if(Classes[l] == m) NewLabel = FALSE; + } + if(NewLabel){ + Classes[Label++] = m; + if(Label > 4000){ + return 0; + } + } + } + } + } + } + + *groups = Label; + + ptr = 0; + for(i = 0; i < layers; ++i){ + for(j = 0; j < rows; ++j){ + for(k = 0; k < cols; ++k){ + m = ccompImage[ptr]; + for(l = 1; l < Label; ++l){ + if(Classes[l] == m){ + connectedEdges[ptr] = l; + break; + } + } + ++ptr; + } + } + } + + free(ccompImage); + + status = 1; + return(status); + +} + +int NI_GetBlobs2D(int samples, int rows, int cols, unsigned short *edges, unsigned short *connectedEdges, + int *groups, int mask){ + + int i, j, k, l, m; + int offset; + int Label; + int status; + int Classes[4096]; + bool NewLabel; + bool Change; + bool connected; + int count; + unsigned short T[12]; + + /* + // connected components labeling. pixels with 1, 4 or 8 connectedness. + */ + Label = 1; + offset = 0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + connectedEdges[offset+j] = 0; + if(edges[offset+j] == 1){ + connected = FALSE; + if(mask == 1){ + count = 0; + for(l = 1; l < 9; ++l){ + count += T[l]; + } + if(count){ + connected = TRUE; + } + } + else if(mask == 4){ + count = (T[2] + T[4] + T[6] + T[8]); + if(count == 4){ + connected = TRUE; + } + } + else if(mask == 8){ + count = 0; + for(l = 1; l < 9; ++l){ + count += T[l]; + } + if(count == 8){ + connected = TRUE; + } + } + if(connected){ + connectedEdges[offset+j] = Label++; + } + } + } + offset += cols; + } + + while(1){ + Change = FALSE; + /* + // TOP-DOWN Pass for labeling + */ + offset = cols; + for(i = 1; i < rows-1; ++i){ + for(j = 1; j < cols-1; ++j){ + if(connectedEdges[offset+j] != 0){ + T[0] = connectedEdges[offset+j]; + T[1] = connectedEdges[offset+j+1]; + T[2] = connectedEdges[offset-cols+j+1]; + T[3] = connectedEdges[offset-cols+j]; + T[4] = connectedEdges[offset-cols+j-1]; + T[5] = connectedEdges[offset+j-1]; + T[6] = connectedEdges[offset+cols+j-1]; + T[7] = connectedEdges[offset+cols+j]; + T[8] = connectedEdges[offset+cols+j+1]; + m = T[0]; + for(l = 1; l < 9; ++l){ + if(T[l] != 0){ + if(T[l] < m) m = T[l]; + } + } + if(m != connectedEdges[offset+j]){ + Change = TRUE; + connectedEdges[offset+j] = m; + } + } + } + offset += cols; + } + /* + // BOTTOM-UP Pass for labeling + */ + offset = (rows-1)*cols; + for(i = (rows-1); i > 1; --i){ + for(j = (cols-1); j > 1; --j){ + if(connectedEdges[offset+j] != 0){ + T[0] = connectedEdges[offset+j]; + T[1] = connectedEdges[offset+j+1]; + T[2] = connectedEdges[offset-cols+j+1]; + T[3] = connectedEdges[offset-cols+j]; + T[4] = connectedEdges[offset-cols+j-1]; + T[5] = connectedEdges[offset+j-1]; + T[6] = connectedEdges[offset+cols+j-1]; + T[7] = connectedEdges[offset+cols+j]; + T[8] = connectedEdges[offset+cols+j+1]; + m = T[0]; + for(l = 1; l < 9; ++l){ + if(T[l] != 0){ + if(T[l] < m) m = T[l]; + } + } + if(m != connectedEdges[offset+j]){ + Change = TRUE; + connectedEdges[offset+j] = m; + } + } + } + offset -= cols; + } + if(!Change) break; + } /* end while loop */ + + Classes[0] = 0; + Label = 1; + offset = cols; + for(i = 1; i < (rows-1); ++i){ + for(j = 1; j < (cols-1); ++j){ + m = connectedEdges[offset+j]; + if(m > 0){ + NewLabel = TRUE; + for(k = 1; k < Label; ++k){ + if(Classes[k] == m) NewLabel = FALSE; + } + if(NewLabel){ + Classes[Label++] = m; + if(Label > 4000){ + return 0; /* too many labeled regions. this is a pathology */ + } + } + } + } + offset += cols; + } + + /* + // re-label the connected blobs in continuous label order + */ + offset = cols; + for(i = 1; i < (rows-1); ++i){ + for(j = 1; j < (cols-1); ++j){ + m = connectedEdges[offset+j]; + if(m > 0){ + for(k = 1; k < Label; ++k){ + if(Classes[k] == m){ + connectedEdges[offset+j] = (unsigned short)k; + break; + } + } + } + } + offset += cols; + } + + *groups = Label; + + /* + // prune the isolated pixels + */ + offset = 0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + if(connectedEdges[offset+j] > (*groups)){ + connectedEdges[offset+j] = 0; + } + } + offset += cols; + } + + status = 1; + return(status); + +} + +int NI_GetBlobRegions3D(int layers, int rows, int cols, int numberObjects, + unsigned short *labeledEdges, objStruct objectMetrics[]){ + + + int status; + int i, j, k, l, m; + int offset; + int count; + int LowX; + int LowY; + int LowZ; + int HighX; + int HighY; + int HighZ; + int ptr; + float centerX; + float centerY; + float centerZ; + + for(l = 1; l < numberObjects; ++l){ + offset = cols; + LowX = 32767; + LowY = 32767; + LowZ = 32767; + HighX = 0; + HighY = 0; + HighZ = 0; + count = 0; + centerX = (float)0.0; + centerY = (float)0.0; + centerZ = (float)0.0; + ptr = 0; + for(i = 0; i < layers; ++i){ + for(j = 0; j < rows; ++j){ + for(k = 0; k < cols; ++k){ + m = labeledEdges[ptr++]; + if(l == m){ + if(i < LowZ) LowZ = i; + if(j < LowY) LowY = j; + if(k < LowX) LowX = k; + if(i > HighZ) HighZ = i; + if(j > HighY) HighY = j; + if(k > HighX) HighX = k; + centerX += (float)k; + centerY += (float)j; + centerZ += (float)i; + ++count; + } + } + } + } + /* the bounding box for the 2D blob */ + objectMetrics[l-1].Left = LowX; + objectMetrics[l-1].Right = HighX; + objectMetrics[l-1].Bottom = LowY; + objectMetrics[l-1].Top = HighY; + objectMetrics[l-1].Front = LowZ; + objectMetrics[l-1].Back = HighZ; + objectMetrics[l-1].Mass = count; + objectMetrics[l-1].cX = centerX/(float)count; + objectMetrics[l-1].cY = centerY/(float)count; + objectMetrics[l-1].cZ = centerZ/(float)count; + objectMetrics[l-1].Label = l; + } + + status = numberObjects; + + return(status); + +} + +int NI_GetBlobRegions2D(int rows, int cols, int numberObjects, unsigned short *labeledEdges, + objStruct objectMetrics[]){ + + int i, j, k, m; + int count; + int LowX; + int LowY; + int HighX; + int HighY; + int status; + int ptr; + float centerX; + float centerY; + + for(k = 1; k < numberObjects; ++k){ + LowX = 32767; + LowY = 32767; + HighX = 0; + HighY = 0; + count = 0; + centerX = (float)0.0; + centerY = (float)0.0; + ptr = 0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + m = labeledEdges[ptr++]; + if(k == m){ + if(i < LowY) LowY = i; + if(j < LowX) LowX = j; + if(i > HighY) HighY = i; + if(j > HighX) HighX = j; + centerX += (float)j; + centerY += (float)i; + ++count; + } + } + } + /* the bounding box for the 2D blob */ + objectMetrics[k-1].Left = LowX; + objectMetrics[k-1].Right = HighX; + objectMetrics[k-1].Bottom = LowY; + objectMetrics[k-1].Top = HighY; + objectMetrics[k-1].Mass = count; + objectMetrics[k-1].cX = centerX/(float)count; + objectMetrics[k-1].cY = centerY/(float)count; + objectMetrics[k-1].Label = k; + } + + status = numberObjects; + return status; + +} + + +int NI_ThinMorphoFilter(int regRows, int regColumns, int spadSize, int masks, unsigned short *J_mask, + unsigned short *K_mask, unsigned char *Input, unsigned char *CInput, + unsigned char *ErosionStage, unsigned char *DialationStage, + unsigned char *HMT, unsigned char *Copy){ + + int i, j, k, l, m, n, overlap, hit; + int LowValue1, HighValue1; + int LowValue2, HighValue2; + int Column, T, nloop; + int Offset; + int N, M; + int maskCols = 3; + int j_mask[3][3]; + int k_mask[3][3]; + int status; + + N = regRows; + M = regColumns; + + LowValue1 = 1; + HighValue1 = 0; + + LowValue2 = 0; + HighValue2 = 1; + + Offset = 0; + for(i = 0; i < N; ++i){ + for(j = 0; j < M; ++j){ + Copy[Offset+j] = Input[Offset+j]; + } + Offset += spadSize; + } + + nloop = 0; + while(1){ + /* erode */ + Column = 0; + for(n = 0; n < masks; ++n){ + for(i = 0; i < 3; ++i){ + for(j = 0; j < 3; ++j){ + j_mask[i][j] = J_mask[i+maskCols*(Column+j)]; + } + } + for(i = 0; i < 3; ++i){ + for(j = 0; j < 3; ++j){ + k_mask[i][j] = K_mask[i+maskCols*(Column+j)]; + } + } + Column += 3; + + Offset = spadSize; + for(i = 1; i < N-1; ++i){ + for(j = 1; j < M-1; ++j){ + hit = LowValue1; + for(k = -1; k < 2; ++k){ + for(l = -1; l < 2; ++l){ + T = j_mask[k+1][l+1]; + if(T == 1){ + overlap = T*Input[Offset+(k*spadSize)+j+l]; + if(overlap == HighValue1) hit = HighValue1; + } + } + } + ErosionStage[Offset+j] = hit; + } + Offset += spadSize; + } + + /* dialate */ + Offset = 0; + for(i = 0; i < N; ++i){ + for(j = 0; j < M; ++j){ + CInput[Offset+j] = (~Input[Offset+j]) & 0x1; + } + Offset += spadSize; + } + + Offset = spadSize; + for(i = 1; i < N-1; ++i){ + for(j = 1; j < M-1; ++j){ + hit = LowValue1; + for(k = -1; k < 2; ++k){ + for(l = -1; l < 2; ++l){ + T = k_mask[k+1][l+1]; + if(T == 1){ + overlap = T*CInput[Offset+(k*spadSize)+j+l]; + if(overlap == HighValue1) hit = HighValue1; + } + } + } + DialationStage[Offset+j] = hit; + } + Offset += spadSize; + } + + /* form the HMT */ + Offset = 0; + for(i = 0; i < N; ++i){ + for(j = 0; j < M; ++j){ + m = (ErosionStage[Offset+j]*DialationStage[Offset+j]); + HMT[Offset+j] = m; + } + Offset += spadSize; + } + + /* Thin for stage n */ + + Offset = 0; + for(i = 0; i < N; ++i){ + for(j = 0; j < M; ++j){ + HMT[Offset+j] = (~HMT[Offset+j]) & 0x1; + } + Offset += spadSize; + } + + Offset = 0; + for (i = 0; i < N; ++i){ + for (j = 0; j < M; ++j){ + m = (Input[Offset+j]*HMT[Offset+j]); + Input[Offset+j] = m; + } + Offset += spadSize; + } + } + + /* check for no change */ + hit = 0; + Offset = 0; + for(i = 0; i < N; ++i){ + for(j = 0; j < M; ++j){ + hit += abs(Copy[Offset+j]-Input[Offset+j]); + } + Offset += spadSize; + } + if(!hit) break; + + hit = 0; + Offset = 0; + for(i = 0; i < N; ++i){ + for(j = 0; j < M; ++j){ + Copy[Offset+j] = Input[Offset+j]; + if(Input[Offset+j]) ++hit; + } + Offset += spadSize; + } + /* nloop is data dependent. */ + ++nloop; + } + + + status = 1; + return status; + +} + + +int NI_CannyFilter(int samples, int rows, int cols, double *rawImage, + double *hDGImage, double *vDGImage, double *dgKernel, + int gWidth, float *aveXValue, float *aveYValue){ + + + /* + // implements the derivative of Gaussian filter. kernel set by CannyEdges + */ + int i, j, k; + int ptr; + int mLength; + int count; + int status; + float *tBuffer = NULL; + double sum; + + *aveXValue = (float)0.0; + *aveYValue = (float)0.0; + + mLength = MAX(rows, cols) + 64; + tBuffer = calloc(mLength, sizeof(float)); + + /* + // filter X + */ + count = 0; + for(i = 0; i < rows; ++i){ + ptr = i * cols; + for(j = gWidth; j < cols-gWidth; ++j){ + sum = dgKernel[0] * rawImage[ptr+j]; + for(k = 1; k < gWidth; ++k){ + sum += dgKernel[k] * (-rawImage[ptr+j+k] + rawImage[ptr+j-k]); + } + hDGImage[ptr+j] = (float)sum; + if(sum != (float)0.0){ + ++count; + *aveXValue += (float)fabs(sum); + } + } + } + if(count){ + *aveXValue /= (float)count; + } + /* + // filter Y + */ + count = 0; + for(i = 0; i < cols; ++i){ + for(j = 0; j < rows; ++j){ + ptr = j * cols; + tBuffer[j] = rawImage[ptr+i]; + } + for(j = gWidth; j < rows-gWidth; ++j){ + ptr = j * cols; + sum = dgKernel[0] * tBuffer[j]; + for(k = 1; k < gWidth; ++k){ + sum += dgKernel[k] * (-tBuffer[j+k] + tBuffer[j-k]); + } + vDGImage[ptr+i] = sum; + if(sum != (float)0.0){ + ++count; + *aveYValue += (float)fabs(sum); + } + } + } + if(count){ + *aveYValue /= (float)count; + } + + free(tBuffer); + + status = 1; + + return status; + +} + +double tmagnitude(double X, double Y){ + return sqrt(X*X + Y*Y); +} + +int NI_CannyNonMaxSupress(int num, int rows, int cols, double *magImage, double *hDGImage, + double *vDGImage, int mode, double aveXValue, double aveYValue, + double *tAve, double *cannyLow, double *cannyHigh, + double cannyL, double cannyH){ + + int i, j; + int ptr, ptr_m1, ptr_p1; + float xSlope, ySlope, G1, G2, G3, G4, G, xC, yC; + float scale; + float maxValue = (float)0.0; + float minValue = (float)0.0; + int value; + int mValue; + int mIndex; + int count; + int status; + int histogram[256]; + double step; + + for(i = 1; i < rows-1; ++i){ + ptr = i * cols; + ptr_m1 = ptr - cols; + ptr_p1 = ptr + cols; + for(j = 1; j < cols; ++j){ + magImage[ptr+j] = (float)0.0; + xC = hDGImage[ptr+j]; + yC = vDGImage[ptr+j]; + if(!((fabs(xC) < aveXValue) && (fabs(yC) < aveYValue))){ + G = tmagnitude(xC, yC); + if(fabs(yC) > fabs(xC)){ + /* vertical gradient */ + xSlope = (float)(fabs(xC) / fabs(yC)); + ySlope = (float)1.0; + G2 = tmagnitude(hDGImage[ptr_m1+j], vDGImage[ptr_m1+j]); + G4 = tmagnitude(hDGImage[ptr_p1+j], vDGImage[ptr_p1+j]); + if((xC*yC) > (float)0.0){ + G1 = tmagnitude(hDGImage[ptr_m1+j-1], vDGImage[ptr_m1+j-1]); + G3 = tmagnitude(hDGImage[ptr_p1+j+1], vDGImage[ptr_p1+j+1]); + } + else{ + G1 = tmagnitude(hDGImage[ptr_m1+j+1], vDGImage[ptr_m1+j+1]); + G3 = tmagnitude(hDGImage[ptr_p1+j-1], vDGImage[ptr_p1+j-1]); + } + } + else{ + /* horizontal gradient */ + xSlope = (float)(fabs(yC) / fabs(xC)); + ySlope = (float)1.0; + G2 = tmagnitude(hDGImage[ptr+j+1], vDGImage[ptr+j+1]); + G4 = tmagnitude(hDGImage[ptr+j-1], vDGImage[ptr+j-1]); + if((xC*yC) > (float)0.0){ + G1 = tmagnitude(hDGImage[ptr_p1+j+1], vDGImage[ptr_p1+j+1]); + G3 = tmagnitude(hDGImage[ptr_m1+j-1], vDGImage[ptr_m1+j-1]); + } + else{ + G1 = tmagnitude(hDGImage[ptr_m1+j+1], vDGImage[ptr_m1+j+1]); + G3 = tmagnitude(hDGImage[ptr_p1+j-1], vDGImage[ptr_p1+j-1]); + } + } + if((G > (xSlope*G1+(ySlope-xSlope)*G2))&&(G > (xSlope*G3+(ySlope-xSlope)*G4))){ + magImage[ptr+j] = G; + } + if(magImage[ptr+j] > maxValue) maxValue = magImage[ptr+j]; + if(magImage[ptr+j] < minValue) minValue = magImage[ptr+j]; + } + } + } + + scale = (float)1.0 / (maxValue-minValue); + ptr = 0; + count = 0; + *tAve = 0.0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + magImage[ptr] = scale * (magImage[ptr]-minValue); + if(magImage[ptr] > 0.0){ + *tAve += magImage[ptr]; + ++count; + } + ++ptr; + } + } + *tAve /= (float)count; + + step = 255.0; + for(i = 0; i < 256; ++i){ + histogram[i] = 0; + } + ptr = 0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + value = (int)(step*(magImage[ptr])); + ++histogram[value]; + ++ptr; + } + } + /* + // now get the max after skipping the low values + */ + mValue = -1; + mIndex = 0; + for(i = 10; i < 256; ++i){ + if(histogram[i] > mValue){ + mValue = histogram[i]; + mIndex = i; + } + } + + if(mode == 1){ + /* based on the mean value of edge energy */ + *cannyLow = ((cannyL) * *tAve); + *cannyHigh = ((cannyH) * *tAve); + } + else{ + /* based on the mode value of edge energy */ + *cannyLow = ((cannyL) * ((float)mIndex/step)); + *cannyHigh = ((cannyH) * ((float)mIndex/step)); + } + status = 1; + + return status; + +} + +int trace_Edge(int i, int j, int rows, int cols, double cannyLow, double *magImage, + unsigned short *hys_image){ + + int n, m; + int ptr; + int flag; + + ptr = i * cols; + if(hys_image[ptr+j] == 0){ + /* + // this point is above high threshold + */ + hys_image[ptr+j] = 1; + flag = 0; + for(n = -1; n <= 1; ++n){ + for(m = -1; m <= 1; ++m){ + if(n == 0 && m == 0) continue; + if(((i+n) > 0) && ((j+m) > 0) && ((i+n) < rows) && ((j+m) < cols)){ + ptr = (i+n) * cols; + if(magImage[ptr+j+m] > cannyLow){ + /* + // this point is above low threshold + */ + if(trace_Edge(i+n, j+m, rows, cols, cannyLow, magImage, hys_image)){ + flag = 1; + break; + } + } + } + } + if(flag) break; + } + return(1); + } + + return(0); + +} + +int NI_CannyHysteresis(int num, int rows, int cols, double *magImage, unsigned short *hys_image, + double cannyLow, double cannyHigh){ + + + int status; + int i, j; + int ptr; + + for(i = 0; i < rows; ++i){ + ptr = i * cols; + for(j = 0; j < cols; ++j){ + if(magImage[ptr+j] > cannyHigh){ + trace_Edge(i, j, rows, cols, cannyLow, magImage, hys_image); + } + } + } + + status = 1; + + return status; + +} + +float lawsConvolution(float *image, float *rowFilter, float *colFilter, int kernelSize){ + + int i, j; + int offset; + float result[7]; + float sum; + + /* filter rows */ + for(i = 0; i < kernelSize; ++i){ + sum = (float)0.0; + offset = i * kernelSize; + for(j = 0; j < kernelSize; ++j){ + sum += (rowFilter[j]*image[offset+j]); + } + result[i] = sum; + } + + /* filter columns */ + sum = (float)0.0; + for(j = 0; j < kernelSize; ++j){ + sum += (rowFilter[j]*result[j]); + } + + return(sum); + +} + +void computeLaws(LawsFilter7 lawsFilter, int aperature, int srcRows, int srcCols, + unsigned short *MaskImage, float *lawsImage, double *sourceImage){ + + /* + // hard-wirred to Law's 7 kernels + */ + int i, j; + int lawsLayer; + int column, row; + int maskOffset[7]; + int dataOffset[7]; + float myImage[49]; + int count; + int outerKernelNumber; + int innerKernelNumber; + int rowNumber; + int kernelSize = lawsFilter.kernelLength; + int fullMask = kernelSize*kernelSize; + int layerStep = srcRows*srcCols; + float *rowFilter; + float *colFilter; + float filterResult1; + float filterResult2; + float lawsLL=1.0; + + for(i = aperature; i < srcRows-aperature; ++i){ + // get the row array offset for mask and data source. + for(row = -aperature; row <= aperature; ++row){ + maskOffset[row+aperature] = (i+row)*srcCols; + dataOffset[row+aperature] = maskOffset[row+aperature]; + } + for(j = aperature; j < srcCols-aperature; ++j){ + /* + // get 7x7 segment and make sure have 100% mask coverage + */ + count = 0; + for(row = -aperature; row <= aperature; ++row){ + rowNumber = (row+aperature)*kernelSize; + for(column = -aperature; column <= aperature; ++column){ + if(MaskImage[maskOffset[row+aperature]+j+column]){ + myImage[rowNumber+column+aperature] = sourceImage[dataOffset[row+aperature]+j+column]; + ++count; + } + } + } + if(count == fullMask){ + /* + // 100% mask coverage. now do the Law's texture filters + */ + lawsLayer = 0; + for(outerKernelNumber = 0; outerKernelNumber < lawsFilter.numberKernels; ++outerKernelNumber){ + /* + // outer loop pulls the i'th kernel. kernel 0 is the LP kernel + // the outer loop is the iso-kernel + */ + rowFilter = &lawsFilter.lawsKernel[outerKernelNumber][0]; + colFilter = &lawsFilter.lawsKernel[outerKernelNumber][0]; + filterResult1 = lawsConvolution(myImage, rowFilter, colFilter, kernelSize); + /* lawsLayer 0 is the LP and needs to be used to scale. */ + if(outerKernelNumber){ + lawsImage[lawsLayer*layerStep + i*srcCols + j] = (float)2.0 * filterResult1; + } + else{ + lawsLL = filterResult1; + lawsLL = (float)2.0 * filterResult1; + lawsImage[lawsLayer*layerStep + i*srcCols + j] = (float)2.0 * filterResult1; + } + ++lawsLayer; + /* + // now do the inner loop and get the column filters for the other laws kernels + */ + for(innerKernelNumber = outerKernelNumber+1; + innerKernelNumber < lawsFilter.numberKernels; + ++innerKernelNumber){ + colFilter = &lawsFilter.lawsKernel[innerKernelNumber][0]; + filterResult1 = lawsConvolution(myImage, rowFilter, colFilter, kernelSize); + filterResult2 = lawsConvolution(myImage, colFilter, rowFilter, kernelSize); + lawsImage[lawsLayer*layerStep + i*srcCols + j] = filterResult1 + filterResult2; + ++lawsLayer; + } + } + } + } + } + + return; + +} + + +int NI_LawsTexture(int num, int rows, int cols, double *src_image, unsigned short *mask, + float *lawsImage, LawsFilter7 lawsFilter){ + + int status; + int number_kernels; + int kernel_size; + int filters; + int aperature; + number_kernels = lawsFilter.numberKernels; + kernel_size = lawsFilter.kernelLength; + filters = lawsFilter.numberFilterLayers; + aperature = (kernel_size-1)/2; + + computeLaws(lawsFilter, aperature, rows, cols, mask, lawsImage, src_image); + + status = 1; + + return status; + +} + + +int NI_RoiCoOccurence(int samples, int rows, int cols, unsigned short *labelImage, + unsigned short *rawImage, int *cocMatrix, int distance, int orientation){ + + int i, j; + int offset; + int d_row; + int d_col; + int status; + int start_row; + int stop_row; + int start_col; + int stop_col; + int mask; + int pixel; + int d_mask_value; + int d_pixel_value; + + /* built around 8 bit histograms */ + + offset = 0; + if(orientation == 90){ + start_row = 0; + stop_row = rows; + start_col = 0; + stop_col = cols-distance; + d_row = 0; + d_col = distance; + } + else if(orientation == 180){ + start_row = 0; + stop_row = rows-distance; + start_col = 0; + stop_col = cols; + d_row = cols*distance; + d_col = 0; + } + else if(orientation == 45){ + start_row = 0; + stop_row = rows-distance; + start_col = distance; + stop_col = cols; + d_row = cols*distance; + d_col = -distance; + } + else if(orientation == 135){ + start_row = 0; + stop_row = rows-distance; + start_col = 0; + stop_col = cols-distance; + d_row = cols*distance; + d_col = distance; + } + + for(i = start_row; i < stop_row; ++i){ + for(j = start_col; j < stop_col; ++j){ + mask = labelImage[offset+j]; + if(mask){ + /* d rows away from current row */ + pixel = rawImage[offset+j]; + d_mask_value = labelImage[offset+d_row+j+d_col]; + if(d_mask_value){ + /* over the mask */ + d_pixel_value = rawImage[offset+d_row+j+d_col]; + /* update the 2D joint histograms */ + ++cocMatrix[d_pixel_value*256+pixel]; + ++cocMatrix[d_pixel_value+pixel*256]; + } + } + } + offset += cols; + } + + status = 1; + + return(status); + +} + +int NI_GrowRegion2D(int rows, int cols, double *rawimage, unsigned short *label, + objStruct *expanded_ROI, objStruct *newgrow_ROI, double low_threshold, + double high_threshold, int Label, int N_connectivity){ + + int i, j, p, m; + int offset; + int offsetM, offsetP; + int status; + int T[8], count; + int LowX; + int LowY; + int HighX; + int HighY; + double value; + bool change; + + while(1){ + change = FALSE; + for(i = 1; i < rows-1; ++i){ + offset = i * cols; + offsetM = offset - cols; + offsetP = offset + cols; + for(j = 1; j < cols-1; ++j){ + m = label[offset+j]; + if(!m){ + /* un-labeled pixel */ + value = rawimage[offset+j]; + if((value > low_threshold) && (value < high_threshold)){ + /* check for N-connectivity */ + T[0] = label[offset+j+1]; + T[1] = label[offsetM+j+1]; + T[2] = label[offsetM+j]; + T[3] = label[offsetM+j-1]; + T[4] = label[offset+j-1]; + T[5] = label[offsetP+j-1]; + T[6] = label[offsetP+j]; + T[7] = label[offsetP+j+1]; + count = 0; + for(p = 0; p < 8; ++p){ + if(T[p] == Label){ + ++count; + } + } + if(count > N_connectivity){ + label[offset+j] = Label; + change = TRUE; + } + } + } + } + } + if(!change) break; + } + + /* get new bounding box */ + newgrow_ROI->Left = expanded_ROI->Left + LowX; + newgrow_ROI->Right = newgrow_ROI->Left + (HighX-LowX); + newgrow_ROI->Bottom = expanded_ROI->Bottom + LowY; + newgrow_ROI->Top = expanded_ROI->Bottom + (HighY-LowY); + newgrow_ROI->Mass = count; + + status = 1; + + return(status); + +} + +int NI_GrowRegion3D(int layers, int rows, int cols, double *rawimage, unsigned short *label, + objStruct *expanded_ROI, objStruct *newgrow_ROI, double low_threshold, + double high_threshold, int Label, int N_connectivity){ + + int i, j, k, m, p; + int offset; + int ptr; + int lOffset, rOffset; + int lOffsetP, lOffsetN; + int rOffsetP, rOffsetN; + int layerSize; + int status; + int T[26], count; + int LowX; + int LowY; + int LowZ; + int HighX; + int HighY; + int HighZ; + float centerX; + float centerY; + float centerZ; + double value; + bool change; + + layerSize = rows * cols; + while(1){ + change = FALSE; + for(i = 1; i < layers-1; ++i){ + lOffset = i * layerSize; + lOffsetP = lOffset+layerSize; + lOffsetN = lOffset-layerSize; + for(j = 1; j < rows-1; ++j){ + rOffset = j * cols; + rOffsetP = rOffset+cols; + rOffsetN = rOffset-cols; + for(k = 1; k < cols-1; ++k){ + m = label[lOffset+rOffset+k]; + if(!m){ + /* un-labeled voxel */ + value = rawimage[lOffset+rOffset+k]; + if((value > low_threshold) && (value < high_threshold)){ + /* check for N-connectivity */ + T[0] = label[lOffset+rOffset+k+1]; + T[1] = label[lOffset+rOffsetN+k+1]; + T[2] = label[lOffset+rOffsetN+k]; + T[3] = label[lOffset+rOffsetN+k-1]; + T[4] = label[lOffset+rOffset+k-1]; + T[5] = label[lOffset+rOffsetP+k-1]; + T[6] = label[lOffset+rOffsetP+k]; + T[7] = label[lOffset+rOffsetP+k+1]; + + T[8] = label[lOffsetN+rOffset+k]; + T[9] = label[lOffsetN+rOffset+k+1]; + T[10] = label[lOffsetN+rOffsetN+k+1]; + T[11] = label[lOffsetN+rOffsetN+k]; + T[12] = label[lOffsetN+rOffsetN+k-1]; + T[13] = label[lOffsetN+rOffset+k-1]; + T[14] = label[lOffsetN+rOffsetP+k-1]; + T[15] = label[lOffsetN+rOffsetP+k]; + T[16] = label[lOffsetN+rOffsetP+k+1]; + + T[17] = label[lOffsetP+rOffset+k]; + T[18] = label[lOffsetP+rOffset+k+1]; + T[19] = label[lOffsetP+rOffsetN+k+1]; + T[20] = label[lOffsetP+rOffsetN+k]; + T[21] = label[lOffsetP+rOffsetN+k-1]; + T[22] = label[lOffsetP+rOffset+k-1]; + T[23] = label[lOffsetP+rOffsetP+k-1]; + T[24] = label[lOffsetP+rOffsetP+k]; + T[25] = label[lOffsetP+rOffsetP+k+1]; + + count = 0; + for(p = 0; p < 26; ++p){ + if(T[p] == Label){ + ++count; + } + } + if(count > N_connectivity){ + label[lOffset+rOffset+k]= Label; + change = TRUE; + } + } + } + } + } + } + if(!change) break; + } + + LowX = 32767; + LowY = 32767; + LowZ = 32767; + HighX = 0; + HighY = 0; + HighZ = 0; + count = 0; + centerX = (float)0.0; + centerY = (float)0.0; + centerZ = (float)0.0; + ptr = 0; + count = 0; + for(i = 0; i < layers; ++i){ + for(j = 0; j < rows; ++j){ + for(k = 0; k < cols; ++k){ + m = label[ptr++]; + if(m == Label){ + if(i < LowZ) LowZ = i; + if(j < LowY) LowY = j; + if(k < LowX) LowX = k; + if(i > HighZ) HighZ = i; + if(j > HighY) HighY = j; + if(k > HighX) HighX = k; + centerX += (float)k; + centerY += (float)j; + centerZ += (float)i; + ++count; + } + } + } + } + + newgrow_ROI->Left = expanded_ROI->Left + LowX; + newgrow_ROI->Right = newgrow_ROI->Left + (HighX-LowX); + newgrow_ROI->Bottom = expanded_ROI->Bottom + LowY; + newgrow_ROI->Top = newgrow_ROI->Bottom + (HighY-LowY); + newgrow_ROI->Front = expanded_ROI->Front + LowZ; + newgrow_ROI->Back = expanded_ROI->Front + (HighZ-LowZ); + newgrow_ROI->Mass = count; + + status = 1; + + return(status); + +} + + Added: branches/Interpolate1D/ndimage/segment/ndImage_Segmenter_structs.h =================================================================== --- branches/Interpolate1D/ndimage/segment/ndImage_Segmenter_structs.h 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage/segment/ndImage_Segmenter_structs.h 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,29 @@ +#ifndef V1_STRUCTSH +#define V1_STRUCTSH + +#define bool unsigned char + +typedef struct{ + int numberKernels; + int kernelLength; + int numberFilterLayers; + float lawsKernel[6][7]; + char name[7]; +}LawsFilter7; + +typedef struct{ + // filled in GetObjectStats + int Left; + int Right; + int Top; + int Bottom; + int Front; + int Back; + int Label; + int Mass; + float cX; + float cY; + float cZ; +}objStruct; + +#endif Added: branches/Interpolate1D/ndimage_wrapper.py =================================================================== --- branches/Interpolate1D/ndimage_wrapper.py 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/ndimage_wrapper.py 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,146 @@ +""" ND Interpolation wrapping using code from NDImage""" + +from numpy import array, arange, NaN +import numpy as np +import _nd_image + +class InterpolateNd: + def __init__(self, data, starting_coords =None, spacings = None, + order=3, out=NaN): + """ data = array or list of lists + starting_coords = None, list, 1D array or 2D (nx1) array + spacings = None, list, 1D array or 2D (nx1) array + out = string in 'nearest', 'wrap', 'reflect', 'mirror', 'constant' + or just NaN + """ + + # FIXME : include spline filtering + + if order < 0 or order > 5: + raise RuntimeError, 'spline order not supported' + + # checking format of input + data = array(data) + + # for proper processing later, starting_coords and spacings must be of shape (data.ndim, 1) + if starting_coords == None: + starting_coords = np.zeros(( data.ndim, 1 )) + else: + starting_coords = array(starting_coords) + assert starting_coords.size == data.ndim, "There must be one element of \ + starting_coords per data dimension. Size mismatch." + starting_coords = reshape(starting_coords, (data.ndim, 1)) + if spacings == None: + spacings = np.zeros(( data.ndim, 1 )) + else: + spacings = array(spacings) + assert starting_coords.size == data.ndim, "There must be one element of \ + starting_coords per data dimension" + spacings = reshape(spacings, (data.ndim, 1)) + + # storing relevant data + self._data_array = data + self.ndim = data.ndim + self._shape = np.shape(data) + self._spacings = spacings + self._min_coords = starting_coords + self._max_coords = self._min_coords + self._shape*self._spacings + self.out = out + self.order = order + + def __call__(self, coordinates): + """ coordinates is an n x L array, where n is the dimensionality of the data + and L is number of points. That is, each column of coordinates + indicates a point at which to interpolate. + """ + + # format checking + coordinates = array(coordinates) + if coordinates.ndim == 1: # passed in a single point + coordinates = np.reshape(coordinates, ( self.ndim, 1)) + assert coordinates.ndim == 2, "Coordinates must be 1 or 2 dimensional" + n, num_points = coordinates.shape + assert n == self.ndim, "The first dimension of the input \ + must be as long as the dimensionality of the space" + + # converting from points in ND space to array indices + indices = (coordinates - self._min_coords)/self._spacings + + if self.out in ['nearest', 'wrap', 'reflect', 'mirror', 'constant']: + # out of bounds can be performed by _interpolate_array_entry + result = self._interpolate_array_entry(self._data_array, indices, self.order, out = self.out) + else: + # need to return NaN when entry is out of bounds + in_bounds_mask = self._index_in_bounds(indices) + in_bounds = indices[:, in_bounds_mask] + out_bounds = indices[:, ~in_bounds_mask] + + result = np.zeros(num_points) + result[in_bounds_mask] = \ + self._interpolate_array_entry(self._data_array, indices[:,in_bounds_mask], self.order) + result[~in_bounds_mask] = NaN + + return result + + + def _interpolate_array_entry(self, data_array, indices, order, out='nearest'): + """ indices is nxL matrix, where n is data_array.ndim + returns array of length L giving interpolated entries. + """ + + extrap_code_register = { 'nearest':0, + 'wrap': 1, + 'reflect':2, + 'mirror':3, + 'constant':4, + } + + n, L = np.shape(indices) + + output = np.zeros( L , dtype=np.float64 ) # place to store the data + + # geometric transform takes data_array, interpolates its values at indices, and + # stores those values in output. Other parameters give details of interpolation method. + _nd_image.geometric_transform(data_array, None, indices, None, None, \ + output, order, extrap_code_register[out], 0.0, None, None) + + return output + + def _index_in_bounds(self, indices): + """ return an array of bools saying which + points are in interpolation bounds + """ + shape_as_column_vec = np.reshape(self._shape, (self.ndim, 1)) + + # entry is 1 if that coordinate of a point is in its bounds + index_in_bounds = (0 <= indices) & \ + (indices <= shape_as_column_vec) + + # for each point, number of coordinates that are in bounds + num_indices_in_bounds = np.sum(index_in_bounds, axis=0) + + # True if each coordinate for the point is in bounds + return num_indices_in_bounds == self.ndim + + def _coord_in_bounds(self, coordinates): + """ return an array of bools saying which + points are in interpolation bounds + """ + # entry is 1 if that coordinate of a point is in its bounds + coord_in_bounds = (self._min_coords <= coordinates) & \ + (coordinates <= self._max_coords) + + # for each point, number of coordinates that are in bounds + num_coords_in_bounds = np.sum(coord_in_bounds, axis=0) + + # True if each coordinate for the point is in bounds + return num_coords_in_bounds == self.ndim + + + + + + + + + \ No newline at end of file Property changes on: branches/Interpolate1D/ndimage_wrapper.py ___________________________________________________________________ Name: svn:executable + * Modified: branches/Interpolate1D/setup.py =================================================================== --- branches/Interpolate1D/setup.py 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/setup.py 2008-08-05 19:07:52 UTC (rev 4601) @@ -1,5 +1,7 @@ #!/usr/bin/env python +from numpy import get_include + import os from os.path import join @@ -11,23 +13,35 @@ # C++ extension for several basic interpolation types config.add_extension('_interpolate', - ['_interpolate.cpp'], - include_dirs = ['.'], - depends = ['interpolate.h']) + ['_interpolate.cpp'], + include_dirs = ['.'], + depends = ['interpolate.h']) # used by dfitpack extension config.add_library('_fitpack', - sources=[join('fitpack', '*.f')], + sources=[join('fitpack', '*.f')], ) # Fortran routines (collectively "FITPACK" for spline interpolation) config.add_extension('_dfitpack', - sources=['_fitpack.pyf'], - libraries=['_fitpack'], + sources=['_fitpack.pyf'], + libraries=['_fitpack'], ) + # ND Image routines for ND interpolation + config.add_extension('_nd_image', + sources=["ndimage/nd_image.c", + "ndimage/ni_filters.c", + "ndimage/ni_fourier.c", + "ndimage/ni_interpolation.c", + "ndimage/ni_measure.c", + "ndimage/ni_morphology.c", + "ndimage/ni_support.c"], + include_dirs=['ndimage']+[get_include()], + ) + # FIXME : add documentation files - # config.add_data_dir( + config.add_data_dir('docs') return config Added: branches/Interpolate1D/tests/test_ndimage.py =================================================================== --- branches/Interpolate1D/tests/test_ndimage.py 2008-08-04 20:27:24 UTC (rev 4600) +++ branches/Interpolate1D/tests/test_ndimage.py 2008-08-05 19:07:52 UTC (rev 4601) @@ -0,0 +1,56 @@ +""" module for testing ndimage_wrapper +""" + +# hack to test on Field's computer +import sys +sys.path.append('c:/home/python/Interpolate1d') + +import unittest +import time +from numpy import arange, allclose, ones +import numpy as np +import ndimage_wrapper as nd + +class Test (unittest.TestCase): + + def assertAllclose(self, x, y): + self.assert_(np.allclose(x, y)) + + def test_linear(self): + boring_data = np.ones((5,5,5)) + interp = nd.InterpolateNd(boring_data, order = 1) + self.assertAllclose( interp(np.array([[2.3], [1.0], [3.9]])) , 1.0 ) + + def test_data_is_list(self): + boring_data = [ [1.0, 1.0, 1.0], + [1.0, 1.0, 1.0], + [1.0, 1.0, 1.0]] + interp = nd.InterpolateNd(boring_data, order = 1) + self.assertAllclose( interp(np.array([[1.3], [1.0]])) , 1.0 ) + + def test_coords_is_1d(self): + boring_data = np.ones((5,5,5)) + interp = nd.InterpolateNd(boring_data, order = 1) + self.assertAllclose( interp(np.array([2.3, 1.0, 3.9])) , 1.0 ) + + def test_coords_is_list(self): + boring_data = np.ones((5,5,5)) + interp = nd.InterpolateNd(boring_data, order = 1) + self.assertAllclose( interp([2.3, 1.0, 3.9]) , 1.0 ) + + def runTest(self): + test_list = [method_name for method_name in dir(self) if method_name.find('test')==0] + for test_name in test_list: + exec("self.%s()" % test_name) + + def test_order2(self): + boring_data = np.ones((5,5,5)) + interp = nd.InterpolateNd(boring_data, order = 2) + self.assertAllclose( interp(np.array([[2.3], [1.0], [3.9]])) , 1.0 ) + + def test_out(self): + pass + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file From scipy-svn at scipy.org Tue Aug 5 18:56:24 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 5 Aug 2008 17:56:24 -0500 (CDT) Subject: [Scipy-svn] r4602 - trunk/scipy/stats/models Message-ID: <20080805225624.AC70939C0AE@scipy.org> Author: tom.waite Date: 2008-08-05 17:56:21 -0500 (Tue, 05 Aug 2008) New Revision: 4602 Added: trunk/scipy/stats/models/_bspline.py Log: rename bspline to make private. part of weave to extension conversion. Copied: trunk/scipy/stats/models/_bspline.py (from rev 4600, trunk/scipy/stats/models/bspline.py) =================================================================== --- trunk/scipy/stats/models/bspline.py 2008-08-04 20:27:24 UTC (rev 4600) +++ trunk/scipy/stats/models/_bspline.py 2008-08-05 22:56:21 UTC (rev 4602) @@ -0,0 +1,657 @@ +''' +Bspines and smoothing splines. + +General references: + + Craven, P. and Wahba, G. (1978) "Smoothing noisy data with spline functions. + Estimating the correct degree of smoothing by + the method of generalized cross-validation." + Numerische Mathematik, 31(4), 377-403. + + Hastie, Tibshirani and Friedman (2001). "The Elements of Statistical + Learning." Springer-Verlag. 536 pages. + + Hutchison, M. and Hoog, F. "Smoothing noisy data with spline functions." + Numerische Mathematik, 47(1), 99-106. +''' + +import numpy as N +import numpy.linalg as L + +from scipy.linalg import solveh_banded +from scipy.optimize import golden +from scipy.stats.models import _bspline + + +# Issue warning regarding heavy development status of this module +import warnings +_msg = "The bspline code is technology preview and requires significant work\ +on the public API and documentation. The API will likely change in the future" +warnings.warn(_msg, UserWarning) + + +def _band2array(a, lower=0, symmetric=False, hermitian=False): + """ + Take an upper or lower triangular banded matrix and return a + numpy array. + + INPUTS: + a -- a matrix in upper or lower triangular banded matrix + lower -- is the matrix upper or lower triangular? + symmetric -- if True, return the original result plus its transpose + hermitian -- if True (and symmetric False), return the original + result plus its conjugate transposed + + """ + + n = a.shape[1] + r = a.shape[0] + _a = 0 + + if not lower: + for j in range(r): + _b = N.diag(a[r-1-j],k=j)[j:(n+j),j:(n+j)] + _a += _b + if symmetric and j > 0: _a += _b.T + elif hermitian and j > 0: _a += _b.conjugate().T + else: + for j in range(r): + _b = N.diag(a[j],k=j)[0:n,0:n] + _a += _b + if symmetric and j > 0: _a += _b.T + elif hermitian and j > 0: _a += _b.conjugate().T + _a = _a.T + + return _a + + +def _upper2lower(ub): + """ + Convert upper triangular banded matrix to lower banded form. + + INPUTS: + ub -- an upper triangular banded matrix + + OUTPUTS: lb + lb -- a lower triangular banded matrix with same entries + as ub + """ + + lb = N.zeros(ub.shape, ub.dtype) + nrow, ncol = ub.shape + for i in range(ub.shape[0]): + lb[i,0:(ncol-i)] = ub[nrow-1-i,i:ncol] + lb[i,(ncol-i):] = ub[nrow-1-i,0:i] + return lb + +def _lower2upper(lb): + """ + Convert lower triangular banded matrix to upper banded form. + + INPUTS: + lb -- a lower triangular banded matrix + + OUTPUTS: ub + ub -- an upper triangular banded matrix with same entries + as lb + """ + + ub = N.zeros(lb.shape, lb.dtype) + nrow, ncol = lb.shape + for i in range(lb.shape[0]): + ub[nrow-1-i,i:ncol] = lb[i,0:(ncol-i)] + ub[nrow-1-i,0:i] = lb[i,(ncol-i):] + return ub + +def _triangle2unit(tb, lower=0): + """ + Take a banded triangular matrix and return its diagonal and the + unit matrix: the banded triangular matrix with 1's on the diagonal, + i.e. each row is divided by the corresponding entry on the diagonal. + + INPUTS: + tb -- a lower triangular banded matrix + lower -- if True, then tb is assumed to be lower triangular banded, + in which case return value is also lower triangular banded. + + OUTPUTS: d, b + d -- diagonal entries of tb + b -- unit matrix: if lower is False, b is upper triangular + banded and its rows of have been divided by d, + else lower is True, b is lower triangular banded + and its columns have been divieed by d. + + """ + + if lower: d = tb[0].copy() + else: d = tb[-1].copy() + + if lower: return d, (tb / d) + else: + l = _upper2lower(tb) + return d, _lower2upper(l / d) + +def _trace_symbanded(a, b, lower=0): + """ + Compute the trace(ab) for two upper or banded real symmetric matrices + stored either in either upper or lower form. + + INPUTS: + a, b -- two banded real symmetric matrices (either lower or upper) + lower -- if True, a and b are assumed to be the lower half + + + OUTPUTS: trace + trace -- trace(ab) + + """ + + if lower: + t = _zero_triband(a * b, lower=1) + return t[0].sum() + 2 * t[1:].sum() + else: + t = _zero_triband(a * b, lower=0) + return t[-1].sum() + 2 * t[:-1].sum() + + +def _zero_triband(a, lower=0): + """ + Explicitly zero out unused elements of a real symmetric banded matrix. + + INPUTS: + a -- a real symmetric banded matrix (either upper or lower hald) + lower -- if True, a is assumed to be the lower half + + """ + + nrow, ncol = a.shape + if lower: + for i in range(nrow): a[i,(ncol-i):] = 0. + else: + for i in range(nrow): a[i,0:i] = 0. + return a + + +class BSpline(object): + + ''' + + Bsplines of a given order and specified knots. + + Implementation is based on description in Chapter 5 of + + Hastie, Tibshirani and Friedman (2001). "The Elements of Statistical + Learning." Springer-Verlag. 536 pages. + + + INPUTS: + knots -- a sorted array of knots with knots[0] the lower boundary, + knots[1] the upper boundary and knots[1:-1] the internal + knots. + order -- order of the Bspline, default is 4 which yields cubic + splines + M -- number of additional boundary knots, if None it defaults + to order + coef -- an optional array of real-valued coefficients for the Bspline + of shape (knots.shape + 2 * (M - 1) - order,). + x -- an optional set of x values at which to evaluate the + Bspline to avoid extra evaluation in the __call__ method + + ''' + + def __init__(self, knots, order=4, M=None, coef=None, x=None): + + knots = N.squeeze(N.unique(N.asarray(knots))) + + if knots.ndim != 1: + raise ValueError, 'expecting 1d array for knots' + + self.m = order + if M is None: + M = self.m + self.M = M + + self.tau = N.hstack([[knots[0]]*(self.M-1), knots, [knots[-1]]*(self.M-1)]) + + self.K = knots.shape[0] - 2 + if coef is None: + self.coef = N.zeros((self.K + 2 * self.M - self.m), N.float64) + else: + self.coef = N.squeeze(coef) + if self.coef.shape != (self.K + 2 * self.M - self.m): + raise ValueError, 'coefficients of Bspline have incorrect shape' + if x is not None: + self.x = x + + def _setx(self, x): + self._x = x + self._basisx = self.basis(self._x) + + def _getx(self): + return self._x + + x = property(_getx, _setx) + + def __call__(self, *args): + """ + Evaluate the BSpline at a given point, yielding + a matrix B and return + + B * self.coef + + + INPUTS: + args -- optional arguments. If None, it returns self._basisx, + the BSpline evaluated at the x values passed in __init__. + Otherwise, return the BSpline evaluated at the + first argument args[0]. + + OUTPUTS: y + y -- value of Bspline at specified x values + + BUGS: + If self has no attribute x, an exception will be raised + because self has no attribute _basisx. + + """ + + if not args: + b = self._basisx.T + else: + x = args[0] + b = N.asarray(self.basis(x)).T + return N.squeeze(N.dot(b, self.coef)) + + def basis_element(self, x, i, d=0): + """ + Evaluate a particular basis element of the BSpline, + or its derivative. + + INPUTS: + x -- x values at which to evaluate the basis element + i -- which element of the BSpline to return + d -- the order of derivative + + OUTPUTS: y + y -- value of d-th derivative of the i-th basis element + of the BSpline at specified x values + + """ + + x = N.asarray(x, N.float64) + _shape = x.shape + if _shape == (): + x.shape = (1,) + x.shape = (N.product(_shape,axis=0),) + if i < self.tau.shape[0] - 1: + ## TODO: OWNDATA flags... + v = _bspline.evaluate(x, self.tau, self.m, d, i, i+1) + else: + return N.zeros(x.shape, N.float64) + + if (i == self.tau.shape[0] - self.m): + v = N.where(N.equal(x, self.tau[-1]), 1, v) + v.shape = _shape + return v + + def basis(self, x, d=0, lower=None, upper=None): + """ + Evaluate the basis of the BSpline or its derivative. + If lower or upper is specified, then only + the [lower:upper] elements of the basis are returned. + + INPUTS: + x -- x values at which to evaluate the basis element + i -- which element of the BSpline to return + d -- the order of derivative + lower -- optional lower limit of the set of basis + elements + upper -- optional upper limit of the set of basis + elements + + OUTPUTS: y + y -- value of d-th derivative of the basis elements + of the BSpline at specified x values + + """ + x = N.asarray(x) + _shape = x.shape + if _shape == (): + x.shape = (1,) + x.shape = (N.product(_shape,axis=0),) + + if upper is None: + upper = self.tau.shape[0] - self.m + if lower is None: + lower = 0 + upper = min(upper, self.tau.shape[0] - self.m) + lower = max(0, lower) + + d = N.asarray(d) + if d.shape == (): + v = _bspline.evaluate(x, self.tau, self.m, int(d), lower, upper) + else: + if d.shape[0] != 2: + raise ValueError, "if d is not an integer, expecting a jx2 \ + array with first row indicating order \ + of derivative, second row coefficient in front." + + v = 0 + for i in range(d.shape[1]): + v += d[1,i] * _bspline.evaluate(x, self.tau, self.m, d[0,i], lower, upper) + + v.shape = (upper-lower,) + _shape + if upper == self.tau.shape[0] - self.m: + v[-1] = N.where(N.equal(x, self.tau[-1]), 1, v[-1]) + return v + + def gram(self, d=0): + """ + Compute Gram inner product matrix, storing it in lower + triangular banded form. + + The (i,j) entry is + + G_ij = integral b_i^(d) b_j^(d) + + where b_i are the basis elements of the BSpline and (d) is the + d-th derivative. + + If d is a matrix then, it is assumed to specify a differential + operator as follows: the first row represents the order of derivative + with the second row the coefficient corresponding to that order. + + For instance: + + [[2, 3], + [3, 1]] + + represents 3 * f^(2) + 1 * f^(3). + + INPUTS: + d -- which derivative to apply to each basis element, + if d is a matrix, it is assumed to specify + a differential operator as above + + OUTPUTS: gram + gram -- the matrix of inner products of (derivatives) + of the BSpline elements + + """ + + d = N.squeeze(d) + if N.asarray(d).shape == (): + self.g = _bspline.gram(self.tau, self.m, int(d), int(d)) + else: + d = N.asarray(d) + if d.shape[0] != 2: + raise ValueError, "if d is not an integer, expecting a jx2 \ + array with first row indicating order \ + of derivative, second row coefficient in front." + if d.shape == (2,): + d.shape = (2,1) + self.g = 0 + for i in range(d.shape[1]): + for j in range(d.shape[1]): + self.g += d[1,i]* d[1,j] * _bspline.gram(self.tau, self.m, int(d[0,i]), int(d[0,j])) + self.g = self.g.T + self.d = d + return N.nan_to_num(self.g) + +class SmoothingSpline(BSpline): + + penmax = 30. + method = "target_df" + target_df = 5 + default_pen = 1.0e-03 + optimize = True + + ''' + A smoothing spline, which can be used to smooth scatterplots, i.e. + a list of (x,y) tuples. + + See fit method for more information. + + ''' + + def fit(self, y, x=None, weights=None, pen=0.): + """ + Fit the smoothing spline to a set of (x,y) pairs. + + INPUTS: + y -- response variable + x -- if None, uses self.x + weights -- optional array of weights + pen -- constant in front of Gram matrix + + OUTPUTS: None + The smoothing spline is determined by self.coef, + subsequent calls of __call__ will be the smoothing spline. + + ALGORITHM: + Formally, this solves a minimization: + + fhat = ARGMIN_f SUM_i=1^n (y_i-f(x_i))^2 + pen * int f^(2)^2 + + See Chapter 5 of + + Hastie, Tibshirani and Friedman (2001). "The Elements of Statistical + Learning." Springer-Verlag. 536 pages. + + for more details. + + TODO: + Should add arbitrary derivative penalty instead of just + second derivative. + """ + + banded = True + + if x is None: + x = self._x + bt = self._basisx.copy() + else: + bt = self.basis(x) + + if pen == 0.: # can't use cholesky for singular matrices + banded = False + + if x.shape != y.shape: + raise ValueError, 'x and y shape do not agree, by default x are \ + the Bspline\'s internal knots' + + if pen >= self.penmax: + pen = self.penmax + + + if weights is not None: + self.weights = weights + else: + self.weights = 1. + + _w = N.sqrt(self.weights) + bt *= _w + + # throw out rows with zeros (this happens at boundary points!) + + mask = N.flatnonzero(1 - N.alltrue(N.equal(bt, 0), axis=0)) + + bt = bt[:,mask] + y = y[mask] + + self.df_total = y.shape[0] + + bty = N.squeeze(N.dot(bt, _w * y)) + self.N = y.shape[0] + + if not banded: + self.btb = N.dot(bt, bt.T) + _g = _band2array(self.g, lower=1, symmetric=True) + self.coef, _, self.rank = L.lstsq(self.btb + pen*_g, bty)[0:3] + self.rank = min(self.rank, self.btb.shape[0]) + del(_g) + else: + self.btb = N.zeros(self.g.shape, N.float64) + nband, nbasis = self.g.shape + for i in range(nbasis): + for k in range(min(nband, nbasis-i)): + self.btb[k,i] = (bt[i] * bt[i+k]).sum() + + bty.shape = (1,bty.shape[0]) + self.pen = pen + self.chol, self.coef = solveh_banded(self.btb + + pen*self.g, + bty, lower=1) + + self.coef = N.squeeze(self.coef) + self.resid = y * self.weights - N.dot(self.coef, bt) + self.pen = pen + + del(bty); del(mask); del(bt) + + def smooth(self, y, x=None, weights=None): + + if self.method == "target_df": + if hasattr(self, 'pen'): + self.fit(y, x=x, weights=weights, pen=self.pen) + else: + self.fit_target_df(y, x=x, weights=weights, df=self.target_df) + elif self.method == "optimize_gcv": + self.fit_optimize_gcv(y, x=x, weights=weights) + + + def gcv(self): + """ + Generalized cross-validation score of current fit. + + Craven, P. and Wahba, G. "Smoothing noisy data with spline functions. + Estimating the correct degree of smoothing by + the method of generalized cross-validation." + Numerische Mathematik, 31(4), 377-403. + """ + + norm_resid = (self.resid**2).sum() + return norm_resid / (self.df_total - self.trace()) + + def df_resid(self): + """ + Residual degrees of freedom in the fit. + + self.N - self.trace() + + where self.N is the number of observations of last fit. + """ + + return self.N - self.trace() + + def df_fit(self): + """ + How many degrees of freedom used in the fit? + + self.trace() + + """ + return self.trace() + + def trace(self): + """ + Trace of the smoothing matrix S(pen) + + TODO: addin a reference to Wahba, and whoever else I used. + """ + + if self.pen > 0: + _invband = _bspline.invband(self.chol.copy()) + tr = _trace_symbanded(_invband, self.btb, lower=1) + return tr + else: + return self.rank + + def fit_target_df(self, y, x=None, df=None, weights=None, tol=1.0e-03, + apen=0, bpen=1.0e-03): + + """ + Fit smoothing spline with approximately df degrees of freedom + used in the fit, i.e. so that self.trace() is approximately df. + + Uses binary search strategy. + + In general, df must be greater than the dimension of the null space + of the Gram inner product. For cubic smoothing splines, this means + that df > 2. + + INPUTS: + y -- response variable + x -- if None, uses self.x + df -- target degrees of freedom + weights -- optional array of weights + tol -- (relative) tolerance for convergence + apen -- lower bound of penalty for binary search + bpen -- upper bound of penalty for binary search + + OUTPUTS: None + The smoothing spline is determined by self.coef, + subsequent calls of __call__ will be the smoothing spline. + + """ + + df = df or self.target_df + + olddf = y.shape[0] - self.m + + if hasattr(self, "pen"): + self.fit(y, x=x, weights=weights, pen=self.pen) + curdf = self.trace() + if N.fabs(curdf - df) / df < tol: + return + if curdf > df: + apen, bpen = self.pen, 2 * self.pen + else: + apen, bpen = 0., self.pen + + while True: + + curpen = 0.5 * (apen + bpen) + self.fit(y, x=x, weights=weights, pen=curpen) + curdf = self.trace() + if curdf > df: + apen, bpen = curpen, 2 * curpen + else: + apen, bpen = apen, curpen + if apen >= self.penmax: + raise ValueError, "penalty too large, try setting penmax \ + higher or decreasing df" + if N.fabs(curdf - df) / df < tol: + break + + def fit_optimize_gcv(self, y, x=None, weights=None, tol=1.0e-03, + brack=(-100,20)): + """ + Fit smoothing spline trying to optimize GCV. + + Try to find a bracketing interval for scipy.optimize.golden + based on bracket. + + It is probably best to use target_df instead, as it is + sometimes difficult to find a bracketing interval. + + INPUTS: + y -- response variable + x -- if None, uses self.x + df -- target degrees of freedom + weights -- optional array of weights + tol -- (relative) tolerance for convergence + brack -- an initial guess at the bracketing interval + + OUTPUTS: None + The smoothing spline is determined by self.coef, + subsequent calls of __call__ will be the smoothing spline. + + """ + + def _gcv(pen, y, x): + self.fit(y, x=x, pen=N.exp(pen)) + a = self.gcv() + return a + + a = golden(_gcv, args=(y,x), brack=bracket, tol=tol) From scipy-svn at scipy.org Tue Aug 5 19:24:54 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 5 Aug 2008 18:24:54 -0500 (CDT) Subject: [Scipy-svn] r4603 - trunk/scipy/stats Message-ID: <20080805232454.A0DBA39C0AE@scipy.org> Author: pierregm Date: 2008-08-05 18:24:52 -0500 (Tue, 05 Aug 2008) New Revision: 4603 Modified: trunk/scipy/stats/mstats.py Log: * mstats: link cov and corrcoef to the numpy.ma.extras equivalents Modified: trunk/scipy/stats/mstats.py =================================================================== --- trunk/scipy/stats/mstats.py 2008-08-05 22:56:21 UTC (rev 4602) +++ trunk/scipy/stats/mstats.py 2008-08-05 23:24:52 UTC (rev 4603) @@ -13,7 +13,7 @@ __all__ = ['argstoarray', 'betai', - 'chisquare','corrcoef','count_tied_groups','cov', + 'chisquare','count_tied_groups', 'describe', 'f_oneway','f_value_wilks_lambda','find_repeats','friedmanchisquare', 'gmean', @@ -288,97 +288,11 @@ """Returns the sign of x, or 0 if x is masked.""" return ma.filled(np.sign(x), 0) +cov = ma.cov -def cov(x, y=None, rowvar=False, bias=False, allow_masked=True): - """Estimates the covariance matrix. +corrcoef = ma.corrcoef -Normalization is by (N-1) where N is the number of observations (unbiased -estimate). If bias is True then normalization is by N. - - -Parameters ----------- - x : ndarray - Input data. If x is a 1D array, returns the variance. If x is a 2D array, - returns the covariance matrix. - y : {None, ndarray} optional - Optional set of variables. - rowvar : {False, True} optional - If rowvar is true, then each row is a variable with obersvations in columns. - If rowvar is False, each column is a variable and the observations are in - the rows. - bias : {False, True} optional - Whether to use a biased (True) or unbiased (False) estimate of the covariance. - If bias is True, then the normalization is by N, the number of observations. - Otherwise, the normalization is by (N-1). - allow_masked : {True, False} optional - If True, masked values are propagated pair-wise: if a value is masked in x, - the corresponding value is masked in y. - If False, raises an exception. - """ - x = ma.asarray(x) - if y is None: - y = x - else: - y = ma.asarray(y) - common_mask = ma.mask_or(ma.getmask(x), ma.getmask(y)) - if allow_masked: - x.unshare_mask() - y.unshare_mask() - x._mask = y._mask = common_mask - elif common_mask is not nomask: - raise ValueError("Cannot process masked data...") - n = x.count() - # - if rowvar: - (x, y) = (x.T, y.T) - # - x -= x.mean(0) - y -= y.mean(0) - result = np.dot(x.filled(0).T, y.filled(0).conj()).squeeze() - if bias: - result /= float(n) - else: - result /= (n-1.) - return result - - -def corrcoef(x, y=None, rowvar=False, bias=False, allow_masked=True): - """The correlation coefficients formed from 2-d array x, where the - rows are the observations, and the columns are variables. - - corrcoef(x,y) where x and y are 1d arrays is the same as - corrcoef(transpose([x,y])) - -Parameters ----------- - x : ndarray - Input data. If x is a 1D array, returns the variance. If x is a 2D array, - returns the covariance matrix. - y : {None, ndarray} optional - Optional set of variables. - rowvar : {False, True} optional - If True, then each row is a variable with obersvations in columns. - If False, each column is a variable and the observations are in the rows. - bias : {False, True} optional - Whether to use a biased (True) or unbiased (False) estimate of the - covariance. - If True, then the normalization is by N, the number of observations. - Otherwise, the normalization is by (N-1). - allow_masked : {True, False} optional - If True, masked values are propagated pair-wise: if a value is masked in x, - the corresponding value is masked in y. - If False, raises an exception. - """ - if y is not None: - x = ma.column_stack([x,y]) - y = None - c = cov(x, y, rowvar=rowvar, bias=bias, allow_masked=allow_masked) - d = ma.diagonal(c) - return c/ma.sqrt(ma.multiply.outer(d,d)) - - def pearsonr(x,y): """Calculates a Pearson correlation coefficient and the p-value for testing non-correlation. From scipy-svn at scipy.org Wed Aug 6 17:46:57 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Wed, 6 Aug 2008 16:46:57 -0500 (CDT) Subject: [Scipy-svn] r4604 - branches Message-ID: <20080806214657.D5E5839C2E4@scipy.org> Author: chris.burns Date: 2008-08-06 16:46:50 -0500 (Wed, 06 Aug 2008) New Revision: 4604 Added: branches/stats_models/ Log: Branch stats.models to work on weave to C extension conversion. Copied: branches/stats_models (from rev 4603, trunk/scipy/stats/models) From scipy-svn at scipy.org Wed Aug 6 18:14:34 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Wed, 6 Aug 2008 17:14:34 -0500 (CDT) Subject: [Scipy-svn] r4605 - in branches/stats_models: . src Message-ID: <20080806221434.AB2B339C2E4@scipy.org> Author: tom.waite Date: 2008-08-06 17:14:32 -0500 (Wed, 06 Aug 2008) New Revision: 4605 Added: branches/stats_models/src/ branches/stats_models/src/bspline_ext.c branches/stats_models/src/bspline_impl.c Log: adding c-ext files for bspline Added: branches/stats_models/src/bspline_ext.c =================================================================== --- branches/stats_models/src/bspline_ext.c 2008-08-06 21:46:50 UTC (rev 4604) +++ branches/stats_models/src/bspline_ext.c 2008-08-06 22:14:32 UTC (rev 4605) @@ -0,0 +1,142 @@ +#include "Python.h" +#include "numpy/arrayobject.h" + +/* function prototypes */ + +double *bspline(double*, double*, int, double *, int, int, int, int, int); +void bspline_gram(double **, double *, int, int, int, int); +void invband_compute(double **, double *, int, int); + + +static PyObject *BSpline_Invband(PyObject *self, PyObject *args) +{ + + double *data; + double *L_data; + npy_intp *dims_invband; + npy_intp *dims_L; + PyObject *L = NULL; + PyObject *invband = NULL; + + if(!PyArg_ParseTuple(args, "O", &L)) + goto exit; + + dims_L = PyArray_DIMS(L); + L_data = (double *)PyArray_DATA(L); + + dims_invband = calloc(2, sizeof(npy_intp)); + dims_invband[0] = dims_L[0]; + dims_invband[1] = dims_L[1]; + + invband = (PyObject*)PyArray_SimpleNew(2, dims_invband, PyArray_DOUBLE); + data = (double *)PyArray_DATA(invband); + free(dims_invband); + + invband_compute(data, L_data, (int)dims_L[0], (int)dims_L[1]); + + Py_DECREF(invband); + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("O", invband); + +} + + + +static PyObject *BSpline_Gram(PyObject *self, PyObject *args) +{ + + int m; + int dl; + int dr; + double *knots; + double *data; + npy_intp *nknots; + npy_intp *dims_gram; + PyObject *knots_array = NULL; + PyObject *gram_array = NULL; + + if(!PyArg_ParseTuple(args, "Oiii", &knots_array, &m, &dl, &dr)) + goto exit; + + nknots = PyArray_DIMS(knots_array); + knots = (double *)PyArray_DATA(knots_array); + + dims_gram = calloc(2, sizeof(npy_intp)); + dims_gram[0] = (int)nknots[0] - m; + dims_gram[1] = m; + + gram_array = (PyObject*)PyArray_SimpleNew(2, dims_gram, PyArray_DOUBLE); + data = (double *)PyArray_DATA(gram_array); + free(dims_gram); + + bspline_gram(data, knots, (int)nknots[0], m, dl, dr); + + Py_DECREF(gram_array); + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("O", gram_array); + +} + + +static PyObject *BSpline_Evaluate(PyObject *self, PyObject *args) +{ + + int upper; + int lower; + int m; + int d; + double *knots; + double *x; + double *data; + npy_intp *nknots; + npy_intp *nx; + npy_intp *dims_basis; + PyObject *knots_array = NULL; + PyObject *x_array = NULL; + PyObject *basis_array = NULL; + + if(!PyArg_ParseTuple(args, "OOiiii", &knots_array, &x_array, &lower, &upper, &m, &d)) + goto exit; + + nknots = PyArray_DIMS(knots_array); + nx = PyArray_DIMS(x_array); + + knots = (double *)PyArray_DATA(knots_array); + x = (double *)PyArray_DATA(x_array); + + dims_basis = calloc(2, sizeof(npy_intp)); + dims_basis[0] = upper-lower; + dims_basis[1] = (int)nx[0]; + basis_array = (PyObject*)PyArray_SimpleNew(2, dims_basis, PyArray_DOUBLE); + data = (double *)PyArray_DATA(basis_array); + free(dims_basis); + + bspline(data, x, (int)nx[0], knots, (int)nknots[0], m, d, lower, upper); + + Py_DECREF(basis_array); + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("O", basis_array); + +} + + +static PyMethodDef BSplineMethods[] = +{ + { "evaluate", BSpline_Evaluate, METH_VARARGS, NULL }, + { "gram", BSpline_Gram, METH_VARARGS, NULL }, + { "invband", BSpline_Invband, METH_VARARGS, NULL }, + { NULL, NULL, 0, NULL}, +}; + +PyMODINIT_FUNC init_segment(void) +{ + Py_InitModule("_hbspline", BSplineMethods); + import_array(); +} + Added: branches/stats_models/src/bspline_impl.c =================================================================== --- branches/stats_models/src/bspline_impl.c 2008-08-06 21:46:50 UTC (rev 4604) +++ branches/stats_models/src/bspline_impl.c 2008-08-06 22:14:32 UTC (rev 4605) @@ -0,0 +1,272 @@ + +/* function prototypes */ + +double *bspline(double **, double *, int, double *, int, int, int, int, int); +double bspline_quad(double *, int, int, int, int, int, int); +double *bspline_prod(double *, int, double *, int, int, int, int, int, int); +void bspline_gram(double **, double *, int, int, int, int); +void invband_compute(double **, double *, int, int); + + +double *bspline(double **output, double *x, int nx, + double *knots, int nknots, + int m, int d, int lower, int upper){ + + int nbasis; + int index, i, j, k; + double *result, *b, *b0, *b1; + double *f0, *f1; + double denom; + + nbasis = upper - lower; + + result = *((double **) output); + f0 = (double *) malloc(sizeof(*f0) * nx); + f1 = (double *) malloc(sizeof(*f1) * nx); + + if (m == 1) { + for(i=0; i= knots[index]) * (x[k] < knots[index+1]); + result++; + } + } + else { + for (k=0; k nknots - 1) { upper = nknots-1; } + + for (k=lower; k 0) { data[j*n+i] = 0;} + } + } + + for (i=n-1; i>=0; i--) { + for (j=1; j <= (m Author: tom.waite Date: 2008-08-06 18:22:16 -0500 (Wed, 06 Aug 2008) New Revision: 4606 Modified: branches/stats_models/setup.py Log: update setup for new c-ext bspline code. Modified: branches/stats_models/setup.py =================================================================== --- branches/stats_models/setup.py 2008-08-06 22:14:32 UTC (rev 4605) +++ branches/stats_models/setup.py 2008-08-06 23:22:16 UTC (rev 4606) @@ -1,27 +1,21 @@ -def configuration(parent_package='',top_path=None, package_name='models'): +def configuration(parent_package='',top_path=None): from numpy.distutils.misc_util import Configuration - config = Configuration(package_name,parent_package,top_path) + config = Configuration('models',parent_package,top_path) - config.add_subpackage('*') + config.add_subpackage('family') + config.add_subpackage('robust') config.add_data_dir('tests') - try: - from scipy.stats.models.bspline_module import mod - n, s, d = weave_ext(mod) - config.add_extension(n, s, **d) - except ImportError: pass - + config.add_extension('_hbspline', + sources=['src/bspline_ext.c', + 'src/bspline_impl.c'], + ) return config -def weave_ext(mod): - d = mod.setup_extension().__dict__ - n = d['name']; del(d['name']) - s = d['sources']; del(d['sources']) - return n, s, d - if __name__ == '__main__': from numpy.distutils.core import setup - setup(**configuration(top_path='', package_name='scipy.stats.models').todict()) + setup(**configuration(top_path='').todict()) + From scipy-svn at scipy.org Wed Aug 6 19:43:23 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Wed, 6 Aug 2008 18:43:23 -0500 (CDT) Subject: [Scipy-svn] r4607 - branches/stats_models/src Message-ID: <20080806234323.EEDBC39C442@scipy.org> Author: tom.waite Date: 2008-08-06 18:43:17 -0500 (Wed, 06 Aug 2008) New Revision: 4607 Modified: branches/stats_models/src/bspline_ext.c Log: fixed evaluate argument order Modified: branches/stats_models/src/bspline_ext.c =================================================================== --- branches/stats_models/src/bspline_ext.c 2008-08-06 23:22:16 UTC (rev 4606) +++ branches/stats_models/src/bspline_ext.c 2008-08-06 23:43:17 UTC (rev 4607) @@ -99,7 +99,7 @@ PyObject *x_array = NULL; PyObject *basis_array = NULL; - if(!PyArg_ParseTuple(args, "OOiiii", &knots_array, &x_array, &lower, &upper, &m, &d)) + if(!PyArg_ParseTuple(args, "OOiiii", &x_array, &knots_array, &m, &d, &lower, &upper)) goto exit; nknots = PyArray_DIMS(knots_array); From scipy-svn at scipy.org Thu Aug 7 15:31:47 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Thu, 7 Aug 2008 14:31:47 -0500 (CDT) Subject: [Scipy-svn] r4608 - in branches/Interpolate1D: . docs tests Message-ID: <20080807193147.CBB6639C502@scipy.org> Author: fcady Date: 2008-08-07 14:31:44 -0500 (Thu, 07 Aug 2008) New Revision: 4608 Modified: branches/Interpolate1D/docs/tutorial.rst branches/Interpolate1D/ndimage_wrapper.py branches/Interpolate1D/tests/test_ndimage.py Log: more exhaustive tests (which resulted in fixing a few bugs that had been there) and more-or-less complete documentation Modified: branches/Interpolate1D/docs/tutorial.rst =================================================================== --- branches/Interpolate1D/docs/tutorial.rst 2008-08-06 23:43:17 UTC (rev 4607) +++ branches/Interpolate1D/docs/tutorial.rst 2008-08-07 19:31:44 UTC (rev 4608) @@ -645,8 +645,57 @@ ND Interpolation ================================================ +1D and 2D interpolation are analogous in their user interface. However, +the ND interpolation breaks from their patterns in certain important respects. +The biggest difference is that the known data must be on a uniformly spaced +grid; scattered points are not acceptable. Rather than a list of points, the +user passes in an N-dimensional array of data. By default, the (i, j, k) element +of the array is taken to give the value of the function at the point (i, j, k), but +the user can specify a different set of starting points and spacings. The +starting points and spacings can be different for each axis. Starting points +and spacings are specified by the keywords 'starting_coords' and 'spacings', +which can be passed as arrays or lists. +Second, when calling the object / function, the points to be interpolated are +passed as an nxL array, where n is the dimensionality of the data; each column +of the array specifies a point at which to interpolate a value, and the returned +array of length L gives the value at each of the points. + +Here is a basic example which illustrates these points: :: + + In []: from interpolate import interpNd + In []: X, Y = meshgrid(arange(10.), arange(10.)) + In []: Z = X+Y # function just adds coordinates + In []: coordinates = array([ [1.1, 2.2, 4.6], + [1.1, 2.2, 4.0 ]) + In []: interpNd(Z, coordinates) + Out []: array([2.2, 4.4, 8.6]) + # say the data start at the point (2, 1) and + # points are spaced 2 apart + In []: interpNd(Z, coordinates, starting_coords = array([1, 1], spacings=[2, 2]) + Out []: array([ .1, 1.2, 3.3]) + +By default, the interpolation is linear for points in-range and returns NaN for +out-of-bounds; alternate types can be specified by the keywords +'kind' and 'out', as in 2D interpolation. However, + +#) 'kind' must be a string ('linear', 'block', 'cubic', etc) indicating a type of + spline interpolation, or else an integers specifying the spline order. +#) 'out' must be either NaN (the default), 'nearest', 'wrap', 'reflect' or 'constant' + +The user cannot pass in specially-tailored interpolation methods. + +There + +The second point is that all interpolation is done using splines. The keyword is still +"kind", but only keywords specifying splines ('spline', 'cubic', 'quadratic', 'quintic', etc) +are acceptable. If kind is an integer, that integer is taken to be the order of the spline. +Note also that 'linear' denotes a spline of order 1, and 'block' denotes a spline of order +zero. + + + ================================================ ND Scattered Interpolation ================================================ Modified: branches/Interpolate1D/ndimage_wrapper.py =================================================================== --- branches/Interpolate1D/ndimage_wrapper.py 2008-08-06 23:43:17 UTC (rev 4607) +++ branches/Interpolate1D/ndimage_wrapper.py 2008-08-07 19:31:44 UTC (rev 4608) @@ -4,21 +4,28 @@ import numpy as np import _nd_image +def interpNd(data, coordinates, starting_coords=None, spacings=None, kind='linear',out=NaN): + return Interpolate1d(data = data, + starting_coords = starting_coords, + spacings = spacings, + kind = kind, + out = out + )(coordinates) + class InterpolateNd: def __init__(self, data, starting_coords =None, spacings = None, - order=3, out=NaN): + kind='linear', out=NaN): """ data = array or list of lists starting_coords = None, list, 1D array or 2D (nx1) array spacings = None, list, 1D array or 2D (nx1) array + kind = string or integer + 0 = block extrapolation between midpoints out = string in 'nearest', 'wrap', 'reflect', 'mirror', 'constant' or just NaN """ # FIXME : include spline filtering - if order < 0 or order > 5: - raise RuntimeError, 'spline order not supported' - # checking format of input data = array(data) @@ -29,15 +36,54 @@ starting_coords = array(starting_coords) assert starting_coords.size == data.ndim, "There must be one element of \ starting_coords per data dimension. Size mismatch." - starting_coords = reshape(starting_coords, (data.ndim, 1)) + starting_coords = np.reshape(starting_coords, (data.ndim, 1)) if spacings == None: - spacings = np.zeros(( data.ndim, 1 )) + spacings = np.ones(( data.ndim, 1 )) else: spacings = array(spacings) assert starting_coords.size == data.ndim, "There must be one element of \ starting_coords per data dimension" - spacings = reshape(spacings, (data.ndim, 1)) + spacings = np.reshape(spacings, (data.ndim, 1)) + # determining the order + order_dict = \ + { 0:0, + '0':0, + 'block':0, + 1:1, + '1':1, + 'linear':1, + 'Linear':1, + 2:2, + '2':2, + 'quadratic':2, + 'quad':2, + 'Quadratic':2, + 'Quad':2, + 3:3, + '3':3, + 'spline':3, + 'Spline':3, + 'cubic':3, + 'Cubic':3, + 4:4, + '4':4, + 'quartic':4, + 'Quartic':4, + 5:5, + '5':5, + 'quintic':5, + 'quint':5, + 'Quintic':5, + 'Quint':5 + } + if order_dict.has_key(kind): + self.order = order_dict[kind] + elif isinstance(kind, int): + raise ValueError, "Only spline orders 0, 1, ..., 5 are supported" + else: + raise ValueError, "argument kind = %s not recognized" % str(kind) + # storing relevant data self._data_array = data self.ndim = data.ndim @@ -46,7 +92,6 @@ self._min_coords = starting_coords self._max_coords = self._min_coords + self._shape*self._spacings self.out = out - self.order = order def __call__(self, coordinates): """ coordinates is an n x L array, where n is the dimensionality of the data Modified: branches/Interpolate1D/tests/test_ndimage.py =================================================================== --- branches/Interpolate1D/tests/test_ndimage.py 2008-08-06 23:43:17 UTC (rev 4607) +++ branches/Interpolate1D/tests/test_ndimage.py 2008-08-07 19:31:44 UTC (rev 4608) @@ -7,7 +7,7 @@ import unittest import time -from numpy import arange, allclose, ones +from numpy import arange, allclose, ones, array import numpy as np import ndimage_wrapper as nd @@ -17,40 +17,97 @@ self.assert_(np.allclose(x, y)) def test_linear(self): + """ Make sure : basic linear works + """ boring_data = np.ones((5,5,5)) - interp = nd.InterpolateNd(boring_data, order = 1) + interp = nd.InterpolateNd(boring_data, kind = 'linear') self.assertAllclose( interp(np.array([[2.3], [1.0], [3.9]])) , 1.0 ) + def test_linear_not_1(self): + """ Make sure : linear interpolation works on a general dataset + """ + X, Y = np.meshgrid(arange(10.), arange(10.)) + interesting_data = X+Y + interp = nd.InterpolateNd(interesting_data, kind = 'linear') + self.assertAllclose( interp(np.array([[2.3], [1.0]])) , 3.3 ) + def test_data_is_list(self): + """ Make sure : data can be entered as a list + """ boring_data = [ [1.0, 1.0, 1.0], [1.0, 1.0, 1.0], [1.0, 1.0, 1.0]] - interp = nd.InterpolateNd(boring_data, order = 1) + interp = nd.InterpolateNd(boring_data) self.assertAllclose( interp(np.array([[1.3], [1.0]])) , 1.0 ) def test_coords_is_1d(self): + """ Make sure : coordinates for a single point can be entered as a 1D array + """ boring_data = np.ones((5,5,5)) - interp = nd.InterpolateNd(boring_data, order = 1) + interp = nd.InterpolateNd(boring_data) self.assertAllclose( interp(np.array([2.3, 1.0, 3.9])) , 1.0 ) def test_coords_is_list(self): + """ Make sure : coordinates for a single point can be entered as a list + """ boring_data = np.ones((5,5,5)) - interp = nd.InterpolateNd(boring_data, order = 1) + interp = nd.InterpolateNd(boring_data) self.assertAllclose( interp([2.3, 1.0, 3.9]) , 1.0 ) + + def test_order2(self): + """ Make sure : quadratic interpolation works + """ + X, Y = np.meshgrid(arange(10.), arange(10.)) + interesting_data = X+Y + interp = nd.InterpolateNd(interesting_data, kind = 2) + self.assertAllclose( interp(np.array([[2.3], [1.0]])) , 3.3 ) + def test_order0(self): + """ Make sure : block interpolation works + """ + X, Y = np.meshgrid(arange(10.), arange(10.)) + interesting_data = X+Y + interp = nd.InterpolateNd(interesting_data, kind = 0) + self.assertAllclose( interp(np.array([[2.3], [1.1]])) , 3.0 ) + + def test_order3(self): + """ Make sure : cubic interpolation works + """ + X, Y = np.meshgrid(arange(10.), arange(10.)) + interesting_data = X+Y + interp = nd.InterpolateNd(interesting_data, kind = 3) + self.assertAllclose( interp(np.array([[4.3], [4.1]])) , 8.4 ) + + def test_out(self): + """ Make sure : out-of-bounds returns NaN + """ + boring_data = np.ones((5,5,5)) + interp = nd.InterpolateNd(boring_data, kind = 'linear') + self.assert_( np.isnan(interp( np.array([[7.3], [1.0], [3.9]]) ))) + + def test_starting_coords(self): + """ Make sure : non-zero starting coordinates work correctly + """ + X, Y = np.meshgrid(arange(10.), arange(10.)) + interesting_data = X+Y + interp = nd.InterpolateNd(interesting_data, starting_coords = array([2, 1])) + self.assertAllclose( interp(np.array([[2.3], [1.0]])) , 0.3 ) + + def test_spacings(self): + """ Make sure : spacings other than 1 work correctly + """ + X, Y = np.meshgrid(arange(10.), arange(10.)) + interesting_data = X+Y + interp = nd.InterpolateNd(interesting_data, spacings = array([2, 1])) + self.assertAllclose( interp(np.array([[2.4], [1.0]])) , 2.2 ) + def runTest(self): + """ run all tests + """ test_list = [method_name for method_name in dir(self) if method_name.find('test')==0] for test_name in test_list: exec("self.%s()" % test_name) - - def test_order2(self): - boring_data = np.ones((5,5,5)) - interp = nd.InterpolateNd(boring_data, order = 2) - self.assertAllclose( interp(np.array([[2.3], [1.0], [3.9]])) , 1.0 ) - def test_out(self): - pass - if __name__ == '__main__': unittest.main() \ No newline at end of file From scipy-svn at scipy.org Thu Aug 7 17:05:51 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Thu, 7 Aug 2008 16:05:51 -0500 (CDT) Subject: [Scipy-svn] r4609 - in branches/Interpolate1D: . docs tests Message-ID: <20080807210551.26B8E39C502@scipy.org> Author: fcady Date: 2008-08-07 16:05:37 -0500 (Thu, 07 Aug 2008) New Revision: 4609 Added: branches/Interpolate1D/interpolateNd.py Removed: branches/Interpolate1D/erics_notes.txt branches/Interpolate1D/fitpack_wrapper2d.py branches/Interpolate1D/ndimage_wrapper.py branches/Interpolate1D/regression_test.py Modified: branches/Interpolate1D/TODO.txt branches/Interpolate1D/__init__.py branches/Interpolate1D/docs/tutorial.rst branches/Interpolate1D/fitpack_wrapper.py branches/Interpolate1D/info.py branches/Interpolate1D/interpolate1d.py branches/Interpolate1D/interpolate2d.py branches/Interpolate1D/setup.py branches/Interpolate1D/tests/test_fitpack_wrapper2d.py branches/Interpolate1D/tests/test_ndimage.py Log: msotly cleaning up and condensing the existing files. The different projects and classes were scattered among a range of different files. Also improvements to the documentation Modified: branches/Interpolate1D/TODO.txt =================================================================== --- branches/Interpolate1D/TODO.txt 2008-08-07 19:31:44 UTC (rev 4608) +++ branches/Interpolate1D/TODO.txt 2008-08-07 21:05:37 UTC (rev 4609) @@ -4,37 +4,15 @@ note with ideas. More info is often contained in FIXMEs at appropriate places in the code. +Note that I don't include much about docstrings, documentation, or +comments here. Improvement of those, esp as other stuff evolves, +is a given. + ************ API and/or MAJOR ISSUES *********** -**handle smoothing - There is a question of whether, if, and how much to allow - smoothing of the data. If we smooth, we're not technically - interpolating, but users often want to smooth data. - - In fitpack_wrapper the smoothing parameter is s. It now defaults - to 0.0 (exact interpolation). Zero smoothing and moderate (s ~ 1) - are fast, but small non-zero s makes the algorithm VERY slow. - - This appears resolved, in that Spline can do smoothing (but defaults - to not), and user-defined classes are allowed to smooth. - -**remove list comprehension in interpolate2d.Interpolate2d.__call__ - **possibly allow interp2d to return a 2d array? Like in the case that x and y are 2d arrays in meshgrid format. - -**pick best spline - Under-the-hood machinery currently comes from _interpolate.cpp - (used in enthought.interpolate) and FITPACK (Fortran, used in - scipy.interpolate). This isn't necessarily the best. Other code - is used in scipy.ndimage and scipy.signal. There is surely other - code out there too. Figure out what is best and incorporate it. - - Signal code is slower than FITPACK, and NDImage requires a - regular grid. I'm inclined to stay with FITPACK, except for the - slow performance when x is small (we could add a hack to not - let s be tiny > 0). **allow y to be 2-dimensional? It is not decided whether this feature should be supported, but @@ -53,99 +31,43 @@ deleted for each column. **better handling of variable types - Currently everything is cast to a float64 if it is not already - a float32. Is this the best way to do it? - - There's also the question of Y being 2-dimensional and/or - incorporating strings for record arrays. My instinct is to - have Interpolate1d only interpolate functions that are from - R1 -> R1. That's how it is currently designed. Other stuff - can be made as wrappers around Interpolate1d. + Currently only 1D interpolation deals with both float32 + and float64 data. - See also "allow y to be 2-dimensional?" below - -**Put Spline2d into fitpack_wrapper.py - It's out now so that is can be worked on separately, but the - fitpack-based code should all be in one module. - - +**include spline pre-filtering in ND interpolation, + or understand why we don't need to do that. -*********** DOCUMENTATION-TYPE AND NON-URGENT TASKS ******* +**README file that describes the architecture of the + package and also includes license information. -**improve regression tests - desired for fitpack_wrapper and _interpolate_wrapper - as well as Interpolate1d. What I have now is - really basic. - - -**improve unit tests in tests directory - - -**comment all files - There are comments there already, but they should be - made better. Plus, features are changing, which requires - updating the documentation. - - -**doc strings for interpolate1d and its members - There's docstrings there already, but they should be - made better. In particular, it must be ensured that - they are of the proper format and include examples. - - The doc strings for __init__.py, interpolate1d.py, - Interpolate1d, and interp1d are virtually identical - and very long; perhaps a master string can be stored - somewhere that they all reference. This would make - updates of documentation easier. - - **figure out NumPy stuff with vectorize. In function Interpolate1d.__call__ It would be nice to remove the hack I used. I believe vectorize is supposed to handle arrays of length 0, but it's not working on my computer. - -**allow newx to be in non-sorted order +**allow newx to be in non-sorted order for 1D This requires rethinking the partition of newx into low, high and mid +**put all extension files into their own directory + ********* LONGER TERM ************ -**update for ND - This will take the form of two additional - classes both modelled after interpolate1d. Thus it probably - shouldn't be done until interpolate1d is more settled. +**allow for scattered ND data + A Delaunay triangulation may be a good way to do this. I + would really like to code it up, but that may be a bit preliminary. - There is an interesting problem here. Most of the extensions - I have assume a regular grid. First off, this is often not general. - Secondly, if I DO use a regular grid, how do I deal with bad - data? The best way is probably a pre-processing where you - interpolate values for the bad points (linear would be a nice simple - way to do it at first, just to get it working) - - We should probably use something other than FITPACK for this. - But firstly it's at most 2D. Much worse, it doesn't evaluate at - a set of points; it evaluates over a grid, which requires inputs - being in sorted order (both in x and y coordinates). This makes - input inconvenient and the code runs a lot slower than ndimage. - ND image has 2 main downsides :1) it requires x and y be uniform - spacing (since its really interpolating entries of an array, rather - than values of a function on Rn), and 2) the C code is TERRIBLY - documented/commented. But that can be fixed. - - So we may have two separate classes: Interpolate1d which is - based on FITPACK (or something else, depending on what - happens with the smoothing parameter), and InterpolateNd - which is based on ndimage. - - Another option is to have two classes: one for uniformly spaced data and - and one for scattered data. Regularly spaced would use NDImage, and - scattered would start as an inefficient wrapper around FITPACK. But longer - term the scattered data could be done with Delaunay triangulation, - perhaps something that would implicitly calculate the convex hull - of the points and interpolate within it. +**rethink extension packages and capabilities + Under-the-hood machinery currently comes from _interpolate.cpp + (used in enthought.interpolate), FITPACK (Fortran, used in + scipy.interpolate) and ndimage. This isn't necessarily the best. + Other code is used in scipy.signal. There is surely other + code out there too. Figure out what is best and incorporate it. + Currently, 1D and 2D both mostly wrap FITPACK through the Spline + and Spline2d classes, and ND wraps ndimage. + **high-level road map when the module is more established, there should be a page on the wiki which describes the big-picture of the module; what Modified: branches/Interpolate1D/__init__.py =================================================================== --- branches/Interpolate1D/__init__.py 2008-08-07 19:31:44 UTC (rev 4608) +++ branches/Interpolate1D/__init__.py 2008-08-07 21:05:37 UTC (rev 4609) @@ -2,11 +2,16 @@ # information about included functions from info import __doc__ +# primary usage for 1, 2, and N-dimensional interpolation +from interpolate1d import Interpolate1d, interp1d +from interpolate2d import Interpolate2d, interp2d +from interpolateNd import InterpolateNd, interpNd + # basic interpolation routines +# wrapped by interpolate*.py files from interpolate_wrapper import linear, logarithmic, block, block_average_above # support for spline interpolation +# wrapped by interpolate*.py files from fitpack_wrapper import Spline -# wrapping for all supported interpolation types. -from interpolate1d import Interpolate1d, interp1 \ No newline at end of file Modified: branches/Interpolate1D/docs/tutorial.rst =================================================================== --- branches/Interpolate1D/docs/tutorial.rst 2008-08-07 19:31:44 UTC (rev 4608) +++ branches/Interpolate1D/docs/tutorial.rst 2008-08-07 21:05:37 UTC (rev 4609) @@ -683,16 +683,15 @@ #) 'kind' must be a string ('linear', 'block', 'cubic', etc) indicating a type of spline interpolation, or else an integers specifying the spline order. #) 'out' must be either NaN (the default), 'nearest', 'wrap', 'reflect' or 'constant' + where the strings indicate extrapolation methods. The user cannot pass in specially-tailored interpolation methods. -There +There is also an objective interface that interpNd wraps around. The +class InterpolateNd is instantiated with all arguments other than coordinates, +and called with coordinates. -The second point is that all interpolation is done using splines. The keyword is still -"kind", but only keywords specifying splines ('spline', 'cubic', 'quadratic', 'quintic', etc) -are acceptable. If kind is an integer, that integer is taken to be the order of the spline. -Note also that 'linear' denotes a spline of order 1, and 'block' denotes a spline of order -zero. +Finally, removal of bad data points is not supported for ND interpolation. Deleted: branches/Interpolate1D/erics_notes.txt =================================================================== --- branches/Interpolate1D/erics_notes.txt 2008-08-07 19:31:44 UTC (rev 4608) +++ branches/Interpolate1D/erics_notes.txt 2008-08-07 21:05:37 UTC (rev 4609) @@ -1,92 +0,0 @@ -*. _remove_bad_data should be left up to the interpolation method if it knows what to do. - otherwise, it is handled by this top level class. - And, we definitely don't want the list comprehension in the remove_bad_data class. - -*. Function signatures: - - def interp1d(x, y, new_x, kind='linear', low=np.NaN, high=np.NaN, \ - kindkw={}, lowkw={}, highkw={}, \ - remove_bad_data = False, bad_data=[], interp_axis = 0): - - o. It is dangerous to initialize containers as default arguments because they are - effectively a singleton for the function. We can discuss this if you don't know - what I am talking about. - Xo. kindkw, lowkw, and highkw aren't really necessary I don't think. They should go. - Xo. [minor] I would just use NaN instead of np.NaN. - Xo. the trailing \ for new lines are not necessary for functions since line continuation - is implicit with the open/close parentheses. - Xo. Do you need both remove_bad_data and bad_data? If bad_data is None, then you - don't remove bad_data... - Xo. I think I would change interp_axis to just be axis. This is consistent with many - other functions in numpy. - Xo. The choice of whether axis=0 or axis=-1 by default is a reasonable question. - fft defaults to axis=-1. This is also the faster axis to operate across in the - standard case. It is, however, the opposite of how some people think about - things (columns vs. rows). Talk to Travis O. for his take. Mine is to use axis=-1. - - I think all of this might simplify the interface to the following: - - def interp1d(x, y, new_x, kind='linear', low=NaN, high=NaN, bad_data=None, axis=-1): - -X*. Follow scipy/FORMAT_GUIDLINES.txt in the main scipy directory. - -For example: - - test_callFormat -> test_call_format - - Here are the rules: - - Follow the standard Python formatting rules when writing code for SciPy. Guido - describes them "here":http://www.python.org/doc/essays/styleguide.html. A few - reminders follow: - - Xo Use 4 spaces for indentation levels. Do not use tabs as they can result - in indentation confusion. Most editors have a feature that will insert 4 - spaces when the tab key is hit. Also, many editors will automatically - search/replace leading tabs with 4 spaces. - - o Only 80 characters on a line. - - Xo use all lowercase function names with underscore separated words: - - def set_some_value() - - instead of: - - def setSomeValue() - - - Xo use CamelCase class names: - - def BaseClass() - - instead of: - - def base_class() -X*. I am glad to see your docstrings. - -X*. Move tests into a seprate test directory. - -X*. make_array_safe - I would prefer 'make_array_safe' named atleast_1d_and_contiguous(). This is more specific - and it is immediately clear to other developers what the check does. If you add other checks, - then perhaps come up with a more generic name, but this explicit names, when possible, help - readability. - - Also, numpy has an ascontiguousrarray() function that would simplify the code a line or so. - - Also, this function lives in multiple places, interpolate1d and interpolate_wrapper. - -X*. isinstance(value, str) should be isinstance(value, basestring) so that we handle - both strings and unicode correctly. - -X*. If the input to interp1d is a scalar, the return value should be a scalar. - [add test to handle this.] - This fails in the following: - - In [5]: x = arange(10) - In [6]: y = arange(10)*2. - In [7]: interpolate1d.interp1d(x,y,3.2) - Out[7]: array([ 6.4]) - - \ No newline at end of file Modified: branches/Interpolate1D/fitpack_wrapper.py =================================================================== --- branches/Interpolate1D/fitpack_wrapper.py 2008-08-07 19:31:44 UTC (rev 4608) +++ branches/Interpolate1D/fitpack_wrapper.py 2008-08-07 21:05:37 UTC (rev 4609) @@ -7,6 +7,10 @@ Spline is primarily meant to be called by Interpolate1d or interp1d, but is a stand-alone class in its own right that is not available through these interfaces. + + Spline2d is primarily meant to be called by Interpolate2d + or interp2d, but is a stand-alone class in its own right + that is not available through these interfaces. The code has been modified from an older version of scipy.interpolate, where it was directly called by the @@ -17,6 +21,7 @@ """ import numpy as np +import warnings import _dfitpack # extension module containing FITPACK subroutines in Fortran @@ -167,4 +172,206 @@ assert ier==0,`ier` return z[:m] raise NotImplementedError,\ - 'finding roots unsupported for non-cubic splines' \ No newline at end of file + 'finding roots unsupported for non-cubic splines' + + +############################ +## BELOW THIS POINT IS CODE FOR 2D INTERPOLATION +############################ + +_surfit_messages = {1:""" + The required storage space exceeds the available storage space: nxest + or nyest too small, or s too small. + The weighted least-squares spline corresponds to the current set of + knots.""", + 2:""" + A theoretically impossible result was found during the iteration + process for finding a smoothing spline with fp = s: s too small or + badly chosen eps. + Weighted sum of squared residuals does not satisfy abs(fp-s)/s < tol.""", + 3:""" + the maximal number of iterations maxit (set to 20 by the program) + allowed for finding a smoothing spline with fp=s has been reached: + s too small. + Weighted sum of squared residuals does not satisfy abs(fp-s)/s < tol.""", + 4:""" + No more knots can be added because the number of b-spline coefficients + (nx-kx-1)*(ny-ky-1) already exceeds the number of data points m: + either s or m too small. + The weighted least-squares spline corresponds to the current set of + knots.""", + 5:""" + No more knots can be added because the additional knot would (quasi) + coincide with an old one: s too small or too large a weight to an + inaccurate data point. + The weighted least-squares spline corresponds to the current set of + knots.""", + 10:""" + Error on entry, no approximation returned. The following conditions + must hold: + xb<=x[i]<=xe, yb<=y[i]<=ye, w[i]>0, i=0..m-1 + If iopt==-1, then + xb>> import numpy as np + >>> from interpolate import interpNd + >>> boring_data = np.ones((5,5,5)) + >>> nd.interpNd(boring_data, np.array([[2.3], [1.0], [3.9]])) + 1.0 + """ + return InterpolateNd(data = data, + starting_coords = starting_coords, + spacings = spacings, + kind = kind, + out = out + )(coordinates) + +class InterpolateNd: + """ A callable class for interpolation of 1D, real-valued data. + + Parameters + ----------- + + data -- NumPy array (N-dimensional) or list of lists + indicates the known values of the function. + + Optional Arguments + ------------------- + + starting_coords -- array or list + indicates the point in space + whose value is given by data[0, ..., 0]. + Defaults to being all zeros. + + spacings -- array or list + jth component gives spacing + of points along the jth axis. Defaults + to being all ones. + + kind -- A string or integer + Indicates what interpolation method to perform on + points within the region of interpolation + + 0, 'block' -- block interpolation based on interval midpoints + 1, 'linear' -- linear interpolation + 2, 'quadratic' -- spline order 2 interpolation + 3, 'cubic' -- cubic spline interpolation + 4, 'quartic' -- 4th order spline interpolation + 5, 'quintic' -- 5th order spine interpolation + + out -- string or NaN + Indicates how to extrapolate values at points outside + the region of interpolation. + + NaN -- return NaN for all points out of range + 'nearest' -- return value at nearest valid point + 'constant' -- returns 0 + 'wrap' -- points over one boundary wrap around to the other side + 'reflect' -- out-of-bounds points are reflected into the valid region + + Example + -------- + + >>> import numpy as np + >>> from interpolate import InterpolateNd + >>> boring_data = np.ones((5,5,5)) + >>> nd.InterpolateNd(boring_data)( np.array([[2.3], [1.0], [3.9]]) ) + 1.0 + """ + def __init__(self, data, starting_coords =None, spacings = None, + kind='linear', out=NaN): + """ data = array or list of lists + starting_coords = None, list, 1D array or 2D (nx1) array + spacings = None, list, 1D array or 2D (nx1) array + kind = string or integer + 0 = block extrapolation between midpoints + out = string in 'nearest', 'wrap', 'reflect', 'mirror', 'constant' + or just NaN + """ + + # FIXME : include spline filtering + + # checking format of input + data = array(data) + + # for proper processing later, starting_coords and spacings must be of shape (data.ndim, 1) + if starting_coords == None: + starting_coords = np.zeros(( data.ndim, 1 )) + else: + starting_coords = array(starting_coords) + assert starting_coords.size == data.ndim, "There must be one element of \ + starting_coords per data dimension. Size mismatch." + starting_coords = np.reshape(starting_coords, (data.ndim, 1)) + if spacings == None: + spacings = np.ones(( data.ndim, 1 )) + else: + spacings = array(spacings) + assert starting_coords.size == data.ndim, "There must be one element of \ + starting_coords per data dimension" + spacings = np.reshape(spacings, (data.ndim, 1)) + + # determining the order + order_dict = \ + { 0:0, + '0':0, + 'block':0, + 1:1, + '1':1, + 'linear':1, + 'Linear':1, + 2:2, + '2':2, + 'quadratic':2, + 'quad':2, + 'Quadratic':2, + 'Quad':2, + 3:3, + '3':3, + 'spline':3, + 'Spline':3, + 'cubic':3, + 'Cubic':3, + 4:4, + '4':4, + 'quartic':4, + 'Quartic':4, + 5:5, + '5':5, + 'quintic':5, + 'quint':5, + 'Quintic':5, + 'Quint':5 + } + if order_dict.has_key(kind): + self.order = order_dict[kind] + elif isinstance(kind, int): + raise ValueError, "Only spline orders 0, 1, ..., 5 are supported" + else: + raise ValueError, "argument kind = %s not recognized" % str(kind) + + # storing relevant data + self._data_array = data + self.ndim = data.ndim + self._shape = np.shape(data) + self._spacings = spacings + self._min_coords = starting_coords + self._max_coords = self._min_coords + self._shape*self._spacings + self.out = out + + def __call__(self, coordinates): + """ coordinates is an n x L array, where n is the dimensionality of the data + and L is number of points. That is, each column of coordinates + indicates a point at which to interpolate. + """ + + # format checking + coordinates = array(coordinates) + if coordinates.ndim == 1: # passed in a single point + coordinates = np.reshape(coordinates, ( self.ndim, 1)) + assert coordinates.ndim == 2, "Coordinates must be 1 or 2 dimensional" + n, num_points = coordinates.shape + assert n == self.ndim, "The first dimension of the input \ + must be as long as the dimensionality of the space" + + # converting from points in ND space to array indices + indices = (coordinates - self._min_coords)/self._spacings + + if self.out in ['nearest', 'wrap', 'reflect', 'mirror', 'constant']: + # out of bounds can be performed by _interpolate_array_entry + result = self._interpolate_array_entry(self._data_array, indices, self.order, out = self.out) + else: + # need to return NaN when entry is out of bounds + in_bounds_mask = self._index_in_bounds(indices) + in_bounds = indices[:, in_bounds_mask] + out_bounds = indices[:, ~in_bounds_mask] + + result = np.zeros(num_points) + result[in_bounds_mask] = \ + self._interpolate_array_entry(self._data_array, indices[:,in_bounds_mask], self.order) + result[~in_bounds_mask] = NaN + + return result + + + def _interpolate_array_entry(self, data_array, indices, order, out='nearest'): + """ indices is nxL matrix, where n is data_array.ndim + returns array of length L giving interpolated entries. + """ + + extrap_code_register = { 'nearest':0, + 'wrap': 1, + 'reflect':2, + 'mirror':3, + 'constant':4, + } + + n, L = np.shape(indices) + + output = np.zeros( L , dtype=np.float64 ) # place to store the data + + # geometric transform takes data_array, interpolates its values at indices, and + # stores those values in output. Other parameters give details of interpolation method. + _nd_image.geometric_transform(data_array, None, indices, None, None, \ + output, order, extrap_code_register[out], 0.0, None, None) + + return output + + def _index_in_bounds(self, indices): + """ return an array of bools saying which + points are in interpolation bounds + """ + shape_as_column_vec = np.reshape(self._shape, (self.ndim, 1)) + + # entry is 1 if that coordinate of a point is in its bounds + index_in_bounds = (0 <= indices) & \ + (indices <= shape_as_column_vec) + + # for each point, number of coordinates that are in bounds + num_indices_in_bounds = np.sum(index_in_bounds, axis=0) + + # True if each coordinate for the point is in bounds + return num_indices_in_bounds == self.ndim + + def _coord_in_bounds(self, coordinates): + """ return an array of bools saying which + points are in interpolation bounds + """ + # entry is 1 if that coordinate of a point is in its bounds + coord_in_bounds = (self._min_coords <= coordinates) & \ + (coordinates <= self._max_coords) + + # for each point, number of coordinates that are in bounds + num_coords_in_bounds = np.sum(coord_in_bounds, axis=0) + + # True if each coordinate for the point is in bounds + return num_coords_in_bounds == self.ndim + + + + + + + + + \ No newline at end of file Deleted: branches/Interpolate1D/ndimage_wrapper.py =================================================================== --- branches/Interpolate1D/ndimage_wrapper.py 2008-08-07 19:31:44 UTC (rev 4608) +++ branches/Interpolate1D/ndimage_wrapper.py 2008-08-07 21:05:37 UTC (rev 4609) @@ -1,191 +0,0 @@ -""" ND Interpolation wrapping using code from NDImage""" - -from numpy import array, arange, NaN -import numpy as np -import _nd_image - -def interpNd(data, coordinates, starting_coords=None, spacings=None, kind='linear',out=NaN): - return Interpolate1d(data = data, - starting_coords = starting_coords, - spacings = spacings, - kind = kind, - out = out - )(coordinates) - -class InterpolateNd: - def __init__(self, data, starting_coords =None, spacings = None, - kind='linear', out=NaN): - """ data = array or list of lists - starting_coords = None, list, 1D array or 2D (nx1) array - spacings = None, list, 1D array or 2D (nx1) array - kind = string or integer - 0 = block extrapolation between midpoints - out = string in 'nearest', 'wrap', 'reflect', 'mirror', 'constant' - or just NaN - """ - - # FIXME : include spline filtering - - # checking format of input - data = array(data) - - # for proper processing later, starting_coords and spacings must be of shape (data.ndim, 1) - if starting_coords == None: - starting_coords = np.zeros(( data.ndim, 1 )) - else: - starting_coords = array(starting_coords) - assert starting_coords.size == data.ndim, "There must be one element of \ - starting_coords per data dimension. Size mismatch." - starting_coords = np.reshape(starting_coords, (data.ndim, 1)) - if spacings == None: - spacings = np.ones(( data.ndim, 1 )) - else: - spacings = array(spacings) - assert starting_coords.size == data.ndim, "There must be one element of \ - starting_coords per data dimension" - spacings = np.reshape(spacings, (data.ndim, 1)) - - # determining the order - order_dict = \ - { 0:0, - '0':0, - 'block':0, - 1:1, - '1':1, - 'linear':1, - 'Linear':1, - 2:2, - '2':2, - 'quadratic':2, - 'quad':2, - 'Quadratic':2, - 'Quad':2, - 3:3, - '3':3, - 'spline':3, - 'Spline':3, - 'cubic':3, - 'Cubic':3, - 4:4, - '4':4, - 'quartic':4, - 'Quartic':4, - 5:5, - '5':5, - 'quintic':5, - 'quint':5, - 'Quintic':5, - 'Quint':5 - } - if order_dict.has_key(kind): - self.order = order_dict[kind] - elif isinstance(kind, int): - raise ValueError, "Only spline orders 0, 1, ..., 5 are supported" - else: - raise ValueError, "argument kind = %s not recognized" % str(kind) - - # storing relevant data - self._data_array = data - self.ndim = data.ndim - self._shape = np.shape(data) - self._spacings = spacings - self._min_coords = starting_coords - self._max_coords = self._min_coords + self._shape*self._spacings - self.out = out - - def __call__(self, coordinates): - """ coordinates is an n x L array, where n is the dimensionality of the data - and L is number of points. That is, each column of coordinates - indicates a point at which to interpolate. - """ - - # format checking - coordinates = array(coordinates) - if coordinates.ndim == 1: # passed in a single point - coordinates = np.reshape(coordinates, ( self.ndim, 1)) - assert coordinates.ndim == 2, "Coordinates must be 1 or 2 dimensional" - n, num_points = coordinates.shape - assert n == self.ndim, "The first dimension of the input \ - must be as long as the dimensionality of the space" - - # converting from points in ND space to array indices - indices = (coordinates - self._min_coords)/self._spacings - - if self.out in ['nearest', 'wrap', 'reflect', 'mirror', 'constant']: - # out of bounds can be performed by _interpolate_array_entry - result = self._interpolate_array_entry(self._data_array, indices, self.order, out = self.out) - else: - # need to return NaN when entry is out of bounds - in_bounds_mask = self._index_in_bounds(indices) - in_bounds = indices[:, in_bounds_mask] - out_bounds = indices[:, ~in_bounds_mask] - - result = np.zeros(num_points) - result[in_bounds_mask] = \ - self._interpolate_array_entry(self._data_array, indices[:,in_bounds_mask], self.order) - result[~in_bounds_mask] = NaN - - return result - - - def _interpolate_array_entry(self, data_array, indices, order, out='nearest'): - """ indices is nxL matrix, where n is data_array.ndim - returns array of length L giving interpolated entries. - """ - - extrap_code_register = { 'nearest':0, - 'wrap': 1, - 'reflect':2, - 'mirror':3, - 'constant':4, - } - - n, L = np.shape(indices) - - output = np.zeros( L , dtype=np.float64 ) # place to store the data - - # geometric transform takes data_array, interpolates its values at indices, and - # stores those values in output. Other parameters give details of interpolation method. - _nd_image.geometric_transform(data_array, None, indices, None, None, \ - output, order, extrap_code_register[out], 0.0, None, None) - - return output - - def _index_in_bounds(self, indices): - """ return an array of bools saying which - points are in interpolation bounds - """ - shape_as_column_vec = np.reshape(self._shape, (self.ndim, 1)) - - # entry is 1 if that coordinate of a point is in its bounds - index_in_bounds = (0 <= indices) & \ - (indices <= shape_as_column_vec) - - # for each point, number of coordinates that are in bounds - num_indices_in_bounds = np.sum(index_in_bounds, axis=0) - - # True if each coordinate for the point is in bounds - return num_indices_in_bounds == self.ndim - - def _coord_in_bounds(self, coordinates): - """ return an array of bools saying which - points are in interpolation bounds - """ - # entry is 1 if that coordinate of a point is in its bounds - coord_in_bounds = (self._min_coords <= coordinates) & \ - (coordinates <= self._max_coords) - - # for each point, number of coordinates that are in bounds - num_coords_in_bounds = np.sum(coord_in_bounds, axis=0) - - # True if each coordinate for the point is in bounds - return num_coords_in_bounds == self.ndim - - - - - - - - - \ No newline at end of file Deleted: branches/Interpolate1D/regression_test.py =================================================================== --- branches/Interpolate1D/regression_test.py 2008-08-07 19:31:44 UTC (rev 4608) +++ branches/Interpolate1D/regression_test.py 2008-08-07 21:05:37 UTC (rev 4609) @@ -1,33 +0,0 @@ -""" - regression test: - - This script runs a simple regression test on the functionality of - the interpolation module. Currently, when run, it times each - unit test in interpolate1d.py and stores those times in a dict - of dicts; outer keys are time test was performed, and inner - keys are names of tests run. - -""" - -import shelve, time -#from tests/test_interpolate1d import Test - -# name of log file to which all data is stored. -filename = 'regression_test.dbm' - -#log_total = shelve.open(filename) -current_time = str(time.localtime()[0:5]) # specified up to the minute - -# run all tests in interpolate1d's test class -#test_list = [name for name in dir(Test) if name.find('test_') == 0] -log_now = {} - -# record time taken for each test -#for test_name in test_list: - # t1 = time.clock() - # eval('Test.%s' % test_name) - #t2 = time.clock() - #log_now[test_name] = t2-t1 - -#log_total[current_time] = log_now -#log_total.close() Modified: branches/Interpolate1D/setup.py =================================================================== --- branches/Interpolate1D/setup.py 2008-08-07 19:31:44 UTC (rev 4608) +++ branches/Interpolate1D/setup.py 2008-08-07 21:05:37 UTC (rev 4609) @@ -40,7 +40,6 @@ include_dirs=['ndimage']+[get_include()], ) - # FIXME : add documentation files config.add_data_dir('docs') return config Modified: branches/Interpolate1D/tests/test_fitpack_wrapper2d.py =================================================================== --- branches/Interpolate1D/tests/test_fitpack_wrapper2d.py 2008-08-07 19:31:44 UTC (rev 4608) +++ branches/Interpolate1D/tests/test_fitpack_wrapper2d.py 2008-08-07 21:05:37 UTC (rev 4609) @@ -10,7 +10,7 @@ import time from numpy import arange, allclose, ones, meshgrid, ravel, array import numpy as np -from fitpack_wrapper2d import Spline2d +from fitpack_wrapper import Spline2d class Test(unittest.TestCase): Modified: branches/Interpolate1D/tests/test_ndimage.py =================================================================== --- branches/Interpolate1D/tests/test_ndimage.py 2008-08-07 19:31:44 UTC (rev 4608) +++ branches/Interpolate1D/tests/test_ndimage.py 2008-08-07 21:05:37 UTC (rev 4609) @@ -9,13 +9,20 @@ import time from numpy import arange, allclose, ones, array import numpy as np -import ndimage_wrapper as nd +import interpolateNd as nd class Test (unittest.TestCase): def assertAllclose(self, x, y): self.assert_(np.allclose(x, y)) + def test_interpNd(self): + """ Make sure : the function interpNd works + """ + boring_data = np.ones((5,5,5)) + answer = nd.interpNd(boring_data, np.array([[2.3], [1.0], [3.9]])) + self.assertAllclose( answer , 1.0 ) + def test_linear(self): """ Make sure : basic linear works """ From scipy-svn at scipy.org Thu Aug 7 17:25:34 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Thu, 7 Aug 2008 16:25:34 -0500 (CDT) Subject: [Scipy-svn] r4610 - in branches/Interpolate1D: . extensions extensions/fitpack extensions/fitpack/fitpack Message-ID: <20080807212534.D9A3E39C502@scipy.org> Author: fcady Date: 2008-08-07 16:25:16 -0500 (Thu, 07 Aug 2008) New Revision: 4610 Added: branches/Interpolate1D/extensions/ branches/Interpolate1D/extensions/_fitpack.pyf branches/Interpolate1D/extensions/_interpolate.cpp branches/Interpolate1D/extensions/fitpack/ branches/Interpolate1D/extensions/fitpack/fitpack/ branches/Interpolate1D/extensions/interpolate.h branches/Interpolate1D/extensions/multipack.h branches/Interpolate1D/extensions/ndimage/ Removed: branches/Interpolate1D/_fitpack.pyf branches/Interpolate1D/_interpolate.cpp branches/Interpolate1D/extensions/fitpack/fitpack/Makefile branches/Interpolate1D/extensions/fitpack/fitpack/README branches/Interpolate1D/extensions/fitpack/fitpack/bispev.f branches/Interpolate1D/extensions/fitpack/fitpack/clocur.f branches/Interpolate1D/extensions/fitpack/fitpack/cocosp.f branches/Interpolate1D/extensions/fitpack/fitpack/concon.f branches/Interpolate1D/extensions/fitpack/fitpack/concur.f branches/Interpolate1D/extensions/fitpack/fitpack/cualde.f branches/Interpolate1D/extensions/fitpack/fitpack/curev.f branches/Interpolate1D/extensions/fitpack/fitpack/curfit.f branches/Interpolate1D/extensions/fitpack/fitpack/dblint.f branches/Interpolate1D/extensions/fitpack/fitpack/evapol.f branches/Interpolate1D/extensions/fitpack/fitpack/fourco.f branches/Interpolate1D/extensions/fitpack/fitpack/fpader.f branches/Interpolate1D/extensions/fitpack/fitpack/fpadno.f branches/Interpolate1D/extensions/fitpack/fitpack/fpadpo.f branches/Interpolate1D/extensions/fitpack/fitpack/fpback.f branches/Interpolate1D/extensions/fitpack/fitpack/fpbacp.f branches/Interpolate1D/extensions/fitpack/fitpack/fpbfout.f branches/Interpolate1D/extensions/fitpack/fitpack/fpbisp.f branches/Interpolate1D/extensions/fitpack/fitpack/fpbspl.f branches/Interpolate1D/extensions/fitpack/fitpack/fpchec.f branches/Interpolate1D/extensions/fitpack/fitpack/fpched.f branches/Interpolate1D/extensions/fitpack/fitpack/fpchep.f branches/Interpolate1D/extensions/fitpack/fitpack/fpclos.f branches/Interpolate1D/extensions/fitpack/fitpack/fpcoco.f branches/Interpolate1D/extensions/fitpack/fitpack/fpcons.f branches/Interpolate1D/extensions/fitpack/fitpack/fpcosp.f branches/Interpolate1D/extensions/fitpack/fitpack/fpcsin.f branches/Interpolate1D/extensions/fitpack/fitpack/fpcurf.f branches/Interpolate1D/extensions/fitpack/fitpack/fpcuro.f branches/Interpolate1D/extensions/fitpack/fitpack/fpcyt1.f branches/Interpolate1D/extensions/fitpack/fitpack/fpcyt2.f branches/Interpolate1D/extensions/fitpack/fitpack/fpdeno.f branches/Interpolate1D/extensions/fitpack/fitpack/fpdisc.f branches/Interpolate1D/extensions/fitpack/fitpack/fpfrno.f branches/Interpolate1D/extensions/fitpack/fitpack/fpgivs.f branches/Interpolate1D/extensions/fitpack/fitpack/fpgrdi.f branches/Interpolate1D/extensions/fitpack/fitpack/fpgrpa.f branches/Interpolate1D/extensions/fitpack/fitpack/fpgrre.f branches/Interpolate1D/extensions/fitpack/fitpack/fpgrsp.f branches/Interpolate1D/extensions/fitpack/fitpack/fpinst.f branches/Interpolate1D/extensions/fitpack/fitpack/fpintb.f branches/Interpolate1D/extensions/fitpack/fitpack/fpknot.f branches/Interpolate1D/extensions/fitpack/fitpack/fpopdi.f branches/Interpolate1D/extensions/fitpack/fitpack/fpopsp.f branches/Interpolate1D/extensions/fitpack/fitpack/fporde.f branches/Interpolate1D/extensions/fitpack/fitpack/fppara.f branches/Interpolate1D/extensions/fitpack/fitpack/fppasu.f branches/Interpolate1D/extensions/fitpack/fitpack/fpperi.f branches/Interpolate1D/extensions/fitpack/fitpack/fppocu.f branches/Interpolate1D/extensions/fitpack/fitpack/fppogr.f branches/Interpolate1D/extensions/fitpack/fitpack/fppola.f branches/Interpolate1D/extensions/fitpack/fitpack/fprank.f branches/Interpolate1D/extensions/fitpack/fitpack/fprati.f branches/Interpolate1D/extensions/fitpack/fitpack/fpregr.f branches/Interpolate1D/extensions/fitpack/fitpack/fprota.f branches/Interpolate1D/extensions/fitpack/fitpack/fprppo.f branches/Interpolate1D/extensions/fitpack/fitpack/fprpsp.f branches/Interpolate1D/extensions/fitpack/fitpack/fpseno.f branches/Interpolate1D/extensions/fitpack/fitpack/fpspgr.f branches/Interpolate1D/extensions/fitpack/fitpack/fpsphe.f branches/Interpolate1D/extensions/fitpack/fitpack/fpsuev.f branches/Interpolate1D/extensions/fitpack/fitpack/fpsurf.f branches/Interpolate1D/extensions/fitpack/fitpack/fpsysy.f branches/Interpolate1D/extensions/fitpack/fitpack/fptrnp.f branches/Interpolate1D/extensions/fitpack/fitpack/fptrpe.f branches/Interpolate1D/extensions/fitpack/fitpack/insert.f branches/Interpolate1D/extensions/fitpack/fitpack/parcur.f branches/Interpolate1D/extensions/fitpack/fitpack/parder.f branches/Interpolate1D/extensions/fitpack/fitpack/parsur.f branches/Interpolate1D/extensions/fitpack/fitpack/percur.f branches/Interpolate1D/extensions/fitpack/fitpack/pogrid.f branches/Interpolate1D/extensions/fitpack/fitpack/polar.f branches/Interpolate1D/extensions/fitpack/fitpack/profil.f branches/Interpolate1D/extensions/fitpack/fitpack/regrid.f branches/Interpolate1D/extensions/fitpack/fitpack/spalde.f branches/Interpolate1D/extensions/fitpack/fitpack/spgrid.f branches/Interpolate1D/extensions/fitpack/fitpack/sphere.f branches/Interpolate1D/extensions/fitpack/fitpack/splder.f branches/Interpolate1D/extensions/fitpack/fitpack/splev.f branches/Interpolate1D/extensions/fitpack/fitpack/splint.f branches/Interpolate1D/extensions/fitpack/fitpack/sproot.f branches/Interpolate1D/extensions/fitpack/fitpack/surev.f branches/Interpolate1D/extensions/fitpack/fitpack/surfit.f branches/Interpolate1D/fitpack/ branches/Interpolate1D/interpolate.h branches/Interpolate1D/multipack.h branches/Interpolate1D/ndimage/ Modified: branches/Interpolate1D/setup.py Log: for cleanness of file, put all under-the-hood extensions into a single directory Deleted: branches/Interpolate1D/_fitpack.pyf =================================================================== --- branches/Interpolate1D/_fitpack.pyf 2008-08-07 21:05:37 UTC (rev 4609) +++ branches/Interpolate1D/_fitpack.pyf 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,479 +0,0 @@ -! -*- f90 -*- -! Author: Pearu Peterson -! -python module _dfitpack ! in - - usercode ''' - -static double dmax(double* seq,int len) { - double val; - int i; - if (len<1) - return -1e308; - val = seq[0]; - for(i=1;ival) val = seq[i]; - return val; -} -static double dmin(double* seq,int len) { - double val; - int i; - if (len<1) - return 1e308; - val = seq[0]; - for(i=1;ival1) return val1; - val1 = dmax(tx,nx); - return val2 - (val1-val2)/nx; -} -static double calc_e(double* x,int m,double* tx,int nx) { - double val1 = dmax(x,m); - double val2 = dmax(tx,nx); - if (val2=8) :: n=len(t) - real*8 dimension(n),depend(n),check(len(c)==n) :: c - real*8 dimension(mest),intent(out),depend(mest) :: zero - integer optional,intent(in),depend(n) :: mest=3*(n-7) - integer intent(out) :: m - integer intent(out) :: ier - end subroutine sproot - - subroutine spalde(t,n,c,k,x,d,ier) - ! d,ier = spalde(t,c,k,x) - - callprotoargument double*,int*,double*,int*,double*,double*,int* - callstatement {int k1=k+1; (*f2py_func)(t,&n,c,&k1,&x,d,&ier); } - - real*8 dimension(n) :: t - integer intent(hide),depend(t) :: n=len(t) - real*8 dimension(n),depend(n),check(len(c)==n) :: c - integer intent(in) :: k - real*8 intent(in) :: x - real*8 dimension(k+1),intent(out),depend(k) :: d - integer intent(out) :: ier - end subroutine spalde - - subroutine curfit(iopt,m,x,y,w,xb,xe,k,s,nest,n,t,c,fp,wrk,lwrk,iwrk,ier) - ! in curfit.f - integer :: iopt - integer intent(hide),depend(x),check(m>k),depend(k) :: m=len(x) - real*8 dimension(m) :: x - real*8 dimension(m),depend(m),check(len(y)==m) :: y - real*8 dimension(m),depend(m),check(len(w)==m) :: w - real*8 optional,depend(x),check(xb<=x[0]) :: xb = x[0] - real*8 optional,depend(x,m),check(xe>=x[m-1]) :: xe = x[m-1] - integer optional,check(1<=k && k <=5),intent(in) :: k=3 - real*8 optional,check(s>=0.0) :: s = 0.0 - integer intent(hide),depend(t) :: nest=len(t) - integer intent(out), depend(nest) :: n=nest - real*8 dimension(nest),intent(inout) :: t - real*8 dimension(n),intent(out) :: c - real*8 intent(out) :: fp - real*8 dimension(lwrk),intent(inout) :: wrk - integer intent(hide),depend(wrk) :: lwrk=len(wrk) - integer dimension(nest),intent(inout) :: iwrk - integer intent(out) :: ier - end subroutine curfit - - subroutine percur(iopt,m,x,y,w,k,s,nest,n,t,c,fp,wrk,lwrk,iwrk,ier) - ! in percur.f - integer :: iopt - integer intent(hide),depend(x),check(m>k),depend(k) :: m=len(x) - real*8 dimension(m) :: x - real*8 dimension(m),depend(m),check(len(y)==m) :: y - real*8 dimension(m),depend(m),check(len(w)==m) :: w - integer optional,check(1<=k && k <=5),intent(in) :: k=3 - real*8 optional,check(s>=0.0) :: s = 0.0 - integer intent(hide),depend(t) :: nest=len(t) - integer intent(out), depend(nest) :: n=nest - real*8 dimension(nest),intent(inout) :: t - real*8 dimension(n),intent(out) :: c - real*8 intent(out) :: fp - real*8 dimension(lwrk),intent(inout) :: wrk - integer intent(hide),depend(wrk) :: lwrk=len(wrk) - integer dimension(nest),intent(inout) :: iwrk - integer intent(out) :: ier - end subroutine percur - - - subroutine parcur(iopt,ipar,idim,m,u,mx,x,w,ub,ue,k,s,nest,n,t,nc,c,fp,wrk,lwrk,iwrk,ier) - ! in parcur.f - integer check(iopt>=-1 && iopt <= 1):: iopt - integer check(ipar == 1 || ipar == 0) :: ipar - integer check(idim > 0 && idim < 11) :: idim - integer intent(hide),depend(u,k),check(m>k) :: m=len(u) - real*8 dimension(m), intent(inout) :: u - integer intent(hide),depend(x,idim,m),check(mx>=idim*m) :: mx=len(x) - real*8 dimension(mx) :: x - real*8 dimension(m) :: w - real*8 :: ub - real*8 :: ue - integer optional, check(1<=k && k<=5) :: k=3.0 - real*8 optional, check(s>=0.0) :: s = 0.0 - integer intent(hide), depend(t) :: nest=len(t) - integer intent(out), depend(nest) :: n=nest - real*8 dimension(nest), intent(inout) :: t - integer intent(hide), depend(c,nest,idim), check(nc>=idim*nest) :: nc=len(c) - real*8 dimension(nc), intent(out) :: c - real*8 intent(out) :: fp - real*8 dimension(lwrk), intent(inout) :: wrk - integer intent(hide),depend(wrk) :: lwrk=len(wrk) - integer dimension(nest), intent(inout) :: iwrk - integer intent(out) :: ier - end subroutine parcur - - - subroutine fpcurf0(iopt,x,y,w,m,xb,xe,k,s,nest,tol,maxit,k1,k2,n,t,c,fp,fpint,wrk,nrdata,ier) - ! x,y,w,xb,xe,k,s,n,t,c,fp,fpint,nrdata,ier = \ - ! fpcurf0(x,y,k,[w,xb,xe,s,nest]) - - fortranname fpcurf - callprotoargument int*,double*,double*,double*,int*,double*,double*,int*,double*,int*,double*,int*,int*,int*,int*,double*,double*,double*,double*,double*,double*,double*,double*,double*,int*,int* - callstatement (*f2py_func)(&iopt,x,y,w,&m,&xb,&xe,&k,&s,&nest,&tol,&maxit,&k1,&k2,&n,t,c,&fp,fpint,wrk,wrk+nest,wrk+nest*k2,wrk+nest*2*k2,wrk+nest*3*k2,nrdata,&ier) - - integer intent(hide) :: iopt = 0 - real*8 dimension(m),intent(in,out) :: x - real*8 dimension(m),depend(m),check(len(y)==m),intent(in,out) :: y - real*8 dimension(m),depend(m),check(len(w)==m),intent(in,out) :: w = 1.0 - integer intent(hide),depend(x),check(m>k),depend(k) :: m=len(x) - real*8 intent(in,out),depend(x),check(xb<=x[0]) :: xb = x[0] - real*8 intent(in,out),depend(x,m),check(xe>=x[m-1]) :: xe = x[m-1] - integer check(1<=k && k<=5),intent(in,out) :: k - real*8 check(s>=0.0),depend(m),intent(in,out) :: s = m - integer intent(in),depend(m,s,k,k1),check(nest>=2*k1) :: nest = (s==0.0?m+k+1:MAX(m/2,2*k1)) - real*8 intent(hide) :: tol = 0.001 - integer intent(hide) :: maxit = 20 - integer intent(hide),depend(k) :: k1=k+1 - integer intent(hide),depend(k) :: k2=k+2 - integer intent(out) :: n - real*8 dimension(nest),intent(out),depend(nest) :: t - real*8 dimension(nest),depend(nest),intent(out) :: c - real*8 intent(out) :: fp - real*8 dimension(nest),depend(nest),intent(out,cache) :: fpint - real*8 dimension(nest*3*k2+m*k1),intent(cache,hide),depend(nest,k1,k2,m) :: wrk - integer dimension(nest),depend(nest),intent(out,cache) :: nrdata - integer intent(out) :: ier - end subroutine fpcurf0 - - subroutine fpcurf1(iopt,x,y,w,m,xb,xe,k,s,nest,tol,maxit,k1,k2,n,t,c,fp,fpint,wrk,nrdata,ier) - ! x,y,w,xb,xe,k,s,n,t,c,fp,fpint,nrdata,ier = \ - ! fpcurf1(x,y,w,xb,xe,k,s,n,t,c,fp,fpint,nrdata,ier) - - fortranname fpcurf - callprotoargument int*,double*,double*,double*,int*,double*,double*,int*,double*,int*,double*,int*,int*,int*,int*,double*,double*,double*,double*,double*,double*,double*,double*,double*,int*,int* - callstatement (*f2py_func)(&iopt,x,y,w,&m,&xb,&xe,&k,&s,&nest,&tol,&maxit,&k1,&k2,&n,t,c,&fp,fpint,wrk,wrk+nest,wrk+nest*k2,wrk+nest*2*k2,wrk+nest*3*k2,nrdata,&ier) - - integer intent(hide) :: iopt = 1 - real*8 dimension(m),intent(in,out,overwrite) :: x - real*8 dimension(m),depend(m),check(len(y)==m),intent(in,out,overwrite) :: y - real*8 dimension(m),depend(m),check(len(w)==m),intent(in,out,overwrite) :: w - integer intent(hide),depend(x),check(m>k),depend(k) :: m=len(x) - real*8 intent(in,out) :: xb - real*8 intent(in,out) :: xe - integer check(1<=k && k<=5),intent(in,out) :: k - real*8 check(s>=0.0),intent(in,out) :: s - integer intent(hide),depend(t) :: nest = len(t) - real*8 intent(hide) :: tol = 0.001 - integer intent(hide) :: maxit = 20 - integer intent(hide),depend(k) :: k1=k+1 - integer intent(hide),depend(k) :: k2=k+2 - integer intent(in,out) :: n - real*8 dimension(nest),intent(in,out,overwrite) :: t - real*8 dimension(nest),depend(nest),check(len(c)==nest),intent(in,out,overwrite) :: c - real*8 intent(in,out) :: fp - real*8 dimension(nest),depend(nest),check(len(fpint)==nest),intent(in,out,cache,overwrite) :: fpint - real*8 dimension(nest*3*k2+m*k1),intent(cache,hide),depend(nest,k1,k2,m) :: wrk - integer dimension(nest),depend(nest),check(len(nrdata)==nest),intent(in,out,cache,overwrite) :: nrdata - integer intent(in,out) :: ier - end subroutine fpcurf1 - - subroutine fpcurfm1(iopt,x,y,w,m,xb,xe,k,s,nest,tol,maxit,k1,k2,n,t,c,fp,fpint,wrk,nrdata,ier) - ! x,y,w,xb,xe,k,s,n,t,c,fp,fpint,nrdata,ier = \ - ! fpcurfm1(x,y,k,t,[w,xb,xe]) - - fortranname fpcurf - callprotoargument int*,double*,double*,double*,int*,double*,double*,int*,double*,int*,double*,int*,int*,int*,int*,double*,double*,double*,double*,double*,double*,double*,double*,double*,int*,int* - callstatement (*f2py_func)(&iopt,x,y,w,&m,&xb,&xe,&k,&s,&nest,&tol,&maxit,&k1,&k2,&n,t,c,&fp,fpint,wrk,wrk+nest,wrk+nest*k2,wrk+nest*2*k2,wrk+nest*3*k2,nrdata,&ier) - - integer intent(hide) :: iopt = -1 - real*8 dimension(m),intent(in,out) :: x - real*8 dimension(m),depend(m),check(len(y)==m),intent(in,out) :: y - real*8 dimension(m),depend(m),check(len(w)==m),intent(in,out) :: w = 1.0 - integer intent(hide),depend(x),check(m>k),depend(k) :: m=len(x) - real*8 intent(in,out),depend(x),check(xb<=x[0]) :: xb = x[0] - real*8 intent(in,out),depend(x,m),check(xe>=x[m-1]) :: xe = x[m-1] - integer check(1<=k && k<=5),intent(in,out) :: k - real*8 intent(out) :: s = -1 - integer intent(hide),depend(n) :: nest = n - real*8 intent(hide) :: tol = 0.001 - integer intent(hide) :: maxit = 20 - integer intent(hide),depend(k) :: k1=k+1 - integer intent(hide),depend(k) :: k2=k+2 - integer intent(out),depend(t) :: n = len(t) - real*8 dimension(n),intent(in,out,overwrite) :: t - real*8 dimension(nest),depend(nest),intent(out) :: c - real*8 intent(out) :: fp - real*8 dimension(nest),depend(nest),intent(out,cache) :: fpint - real*8 dimension(nest*3*k2+m*k1),intent(cache,hide),depend(nest,k1,k2,m) :: wrk - integer dimension(nest),depend(nest),intent(out,cache) :: nrdata - integer intent(out) :: ier - end subroutine fpcurfm1 - - !!!!!!!!!! Bivariate spline !!!!!!!!!!! - - subroutine bispev(tx,nx,ty,ny,c,kx,ky,x,mx,y,my,z,wrk,lwrk,iwrk,kwrk,ier) - ! z,ier = bispev(tx,ty,c,kx,ky,x,y) - real*8 dimension(nx),intent(in) :: tx - integer intent(hide),depend(tx) :: nx=len(tx) - real*8 dimension(ny),intent(in) :: ty - integer intent(hide),depend(ty) :: ny=len(ty) - real*8 intent(in),dimension((nx-kx-1)*(ny-ky-1)),depend(nx,ny,kx,ky),& - check(len(c)==(nx-kx-1)*(ny-ky-1)):: c - integer :: kx - integer :: ky - real*8 intent(in),dimension(mx) :: x - integer intent(hide),depend(x) :: mx=len(x) - real*8 intent(in),dimension(my) :: y - integer intent(hide),depend(y) :: my=len(y) - real*8 dimension(mx,my),depend(mx,my),intent(out,c) :: z - real*8 dimension(lwrk),depend(lwrk),intent(hide,cache) :: wrk - integer intent(hide),depend(mx,kx,my,ky) :: lwrk=mx*(kx+1)+my*(ky+1) - integer dimension(kwrk),depend(kwrk),intent(hide,cache) :: iwrk - integer intent(hide),depend(mx,my) :: kwrk=mx+my - integer intent(out) :: ier - end subroutine bispev - - subroutine surfit_smth(iopt,m,x,y,z,w,xb,xe,yb,ye,kx,ky,s,nxest,nyest,& - nmax,eps,nx,tx,ny,ty,c,fp,wrk1,lwrk1,wrk2,lwrk2,& - iwrk,kwrk,ier) - ! nx,tx,ny,ty,c,fp,ier = surfit_smth(x,y,z,[w,xb,xe,yb,ye,kx,ky,s,eps,lwrk2]) - - fortranname surfit - - integer intent(hide) :: iopt=0 - integer intent(hide),depend(x,kx,ky),check(m>=(kx+1)*(ky+1)) & - :: m=len(x) - real*8 dimension(m) :: x - real*8 dimension(m),depend(m),check(len(y)==m) :: y - real*8 dimension(m),depend(m),check(len(z)==m) :: z - real*8 optional,dimension(m),depend(m),check(len(w)==m) :: w = 1.0 - real*8 optional,depend(x,m) :: xb=dmin(x,m) - real*8 optional,depend(x,m) :: xe=dmax(x,m) - real*8 optional,depend(y,m) :: yb=dmin(y,m) - real*8 optional,depend(y,m) :: ye=dmax(y,m) - integer check(1<=kx && kx<=5) :: kx = 3 - integer check(1<=ky && ky<=5) :: ky = 3 - real*8 optional,check(0.0<=s) :: s = m - integer optional,depend(kx,m),check(nxest>=2*(kx+1)) & - :: nxest = imax(kx+1+sqrt(m/2),2*(kx+1)) - integer optional,depend(ky,m),check(nyest>=2*(ky+1)) & - :: nyest = imax(ky+1+sqrt(m/2),2*(ky+1)) - integer intent(hide),depend(nxest,nyest) :: nmax=MAX(nxest,nyest) - real*8 optional,check(0.0=(kx+1)*(ky+1)) & - :: m=len(x) - real*8 dimension(m) :: x - real*8 dimension(m),depend(m),check(len(y)==m) :: y - real*8 dimension(m),depend(m),check(len(z)==m) :: z - real*8 optional,dimension(m),depend(m),check(len(w)==m) :: w = 1.0 - real*8 optional,depend(x,tx,m,nx) :: xb=calc_b(x,m,tx,nx) - real*8 optional,depend(x,tx,m,nx) :: xe=calc_e(x,m,tx,nx) - real*8 optional,depend(y,ty,m,ny) :: yb=calc_b(y,m,ty,ny) - real*8 optional,depend(y,ty,m,ny) :: ye=calc_e(y,m,ty,ny) - integer check(1<=kx && kx<=5) :: kx = 3 - integer check(1<=ky && ky<=5) :: ky = 3 - real*8 intent(hide) :: s = 0.0 - integer intent(hide),depend(nx) :: nxest = nx - integer intent(hide),depend(ny) :: nyest = ny - integer intent(hide),depend(nx,ny) :: nmax=MAX(nx,ny) - real*8 optional,check(0.0kx) :: mx=len(x) - real*8 dimension(mx) :: x - integer intent(hide),depend(y,ky),check(my>ky) :: my=len(y) - real*8 dimension(my) :: y - real*8 dimension(mx*my),depend(mx,my),check(len(z)==mx*my) :: z - real*8 optional,depend(x,mx) :: xb=dmin(x,mx) - real*8 optional,depend(x,mx) :: xe=dmax(x,mx) - real*8 optional,depend(y,my) :: yb=dmin(y,my) - real*8 optional,depend(y,my) :: ye=dmax(y,my) - integer optional,check(1<=kx && kx<=5) :: kx = 3 - integer optional,check(1<=ky && ky<=5) :: ky = 3 - real*8 optional,check(0.0<=s) :: s = 0.0 - integer intent(hide),depend(kx,mx),check(nxest>=2*(kx+1)) & - :: nxest = mx+kx+1 - integer intent(hide),depend(ky,my),check(nyest>=2*(ky+1)) & - :: nyest = my+ky+1 - integer intent(out) :: nx - real*8 dimension(nxest),intent(out),depend(nxest) :: tx - integer intent(out) :: ny - real*8 dimension(nyest),intent(out),depend(nyest) :: ty - real*8 dimension((nxest-kx-1)*(nyest-ky-1)), & - depend(kx,ky,nxest,nyest),intent(out) :: c - real*8 intent(out) :: fp - real*8 dimension(lwrk),intent(cache,hide),depend(lwrk) :: wrk - integer intent(hide),depend(mx,my,kx,ky,nxest,nyest) & - :: lwrk=calc_regrid_lwrk(mx,my,kx,ky,nxest,nyest) - integer dimension(kwrk),depend(kwrk),intent(cache,hide) :: iwrk - integer intent(hide),depend(mx,my,nxest,nyest) & - :: kwrk=3+mx+my+nxest+nyest - integer intent(out) :: ier - end subroutine regrid_smth - - function dblint(tx,nx,ty,ny,c,kx,ky,xb,xe,yb,ye,wrk) - ! iy = dblint(tx,ty,c,kx,ky,xb,xe,yb,ye) - real*8 dimension(nx),intent(in) :: tx - integer intent(hide),depend(tx) :: nx=len(tx) - real*8 dimension(ny),intent(in) :: ty - integer intent(hide),depend(ty) :: ny=len(ty) - real*8 intent(in),dimension((nx-kx-1)*(ny-ky-1)),depend(nx,ny,kx,ky),& - check(len(c)==(nx-kx-1)*(ny-ky-1)):: c - integer :: kx - integer :: ky - real*8 intent(in) :: xb - real*8 intent(in) :: xe - real*8 intent(in) :: yb - real*8 intent(in) :: ye - real*8 dimension(nx+ny-kx-ky-2),depend(nx,ny,kx,ky),intent(cache,hide) :: wrk - real*8 :: dblint - end function dblint - end interface -end python module _dfitpack - Deleted: branches/Interpolate1D/_interpolate.cpp =================================================================== --- branches/Interpolate1D/_interpolate.cpp 2008-08-07 21:05:37 UTC (rev 4609) +++ branches/Interpolate1D/_interpolate.cpp 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,236 +0,0 @@ -#include "Python.h" -#include - -#include "interpolate.h" -#include "numpy/arrayobject.h" - -using namespace std; - -extern "C" { - -static PyObject* linear_method(PyObject*self, PyObject* args, PyObject* kywds) -{ - static char *kwlist[] = {"x","y","new_x","new_y", NULL}; - PyObject *py_x, *py_y, *py_new_x, *py_new_y; - py_x = py_y = py_new_x = py_new_y = NULL; - PyObject *arr_x, *arr_y, *arr_new_x, *arr_new_y; - arr_x = arr_y = arr_new_x = arr_new_y = NULL; - - if(!PyArg_ParseTupleAndKeywords(args,kywds,"OOOO:linear_dddd",kwlist,&py_x, &py_y, &py_new_x, &py_new_y)) - return NULL; - arr_x = PyArray_FROMANY(py_x, PyArray_DOUBLE, 1, 1, NPY_IN_ARRAY); - if (!arr_x) { - PyErr_SetString(PyExc_ValueError, "x must be a 1-D array of floats"); - goto fail; - } - arr_y = PyArray_FROMANY(py_y, PyArray_DOUBLE, 1, 1, NPY_IN_ARRAY); - if (!arr_y) { - PyErr_SetString(PyExc_ValueError, "y must be a 1-D array of floats"); - goto fail; - } - arr_new_x = PyArray_FROMANY(py_new_x, PyArray_DOUBLE, 1, 1, NPY_IN_ARRAY); - if (!arr_new_x) { - PyErr_SetString(PyExc_ValueError, "new_x must be a 1-D array of floats"); - goto fail; - } - arr_new_y = PyArray_FROMANY(py_new_y, PyArray_DOUBLE, 1, 1, NPY_INOUT_ARRAY); - if (!arr_new_y) { - PyErr_SetString(PyExc_ValueError, "new_y must be a 1-D array of floats"); - goto fail; - } - - linear((double*)PyArray_DATA(arr_x), (double*)PyArray_DATA(arr_y), - PyArray_DIM(arr_x,0), (double*)PyArray_DATA(arr_new_x), - (double*)PyArray_DATA(arr_new_y), PyArray_DIM(arr_new_x,0)); - - Py_DECREF(arr_x); - Py_DECREF(arr_y); - Py_DECREF(arr_new_x); - Py_DECREF(arr_new_y); - - Py_RETURN_NONE; - -fail: - Py_XDECREF(arr_x); - Py_XDECREF(arr_y); - Py_XDECREF(arr_new_x); - Py_XDECREF(arr_new_y); - return NULL; -} - -static PyObject* loginterp_method(PyObject*self, PyObject* args, PyObject* kywds) -{ - static char *kwlist[] = {"x","y","new_x","new_y", NULL}; - PyObject *py_x, *py_y, *py_new_x, *py_new_y; - py_x = py_y = py_new_x = py_new_y = NULL; - PyObject *arr_x, *arr_y, *arr_new_x, *arr_new_y; - arr_x = arr_y = arr_new_x = arr_new_y = NULL; - - if(!PyArg_ParseTupleAndKeywords(args,kywds,"OOOO:loginterp_dddd",kwlist,&py_x, &py_y, &py_new_x, &py_new_y)) - return NULL; - arr_x = PyArray_FROMANY(py_x, PyArray_DOUBLE, 1, 1, NPY_IN_ARRAY); - if (!arr_x) { - PyErr_SetString(PyExc_ValueError, "x must be a 1-D array of floats"); - goto fail; - } - arr_y = PyArray_FROMANY(py_y, PyArray_DOUBLE, 1, 1, NPY_IN_ARRAY); - if (!arr_y) { - PyErr_SetString(PyExc_ValueError, "y must be a 1-D array of floats"); - goto fail; - } - arr_new_x = PyArray_FROMANY(py_new_x, PyArray_DOUBLE, 1, 1, NPY_IN_ARRAY); - if (!arr_new_x) { - PyErr_SetString(PyExc_ValueError, "new_x must be a 1-D array of floats"); - goto fail; - } - arr_new_y = PyArray_FROMANY(py_new_y, PyArray_DOUBLE, 1, 1, NPY_INOUT_ARRAY); - if (!arr_new_y) { - PyErr_SetString(PyExc_ValueError, "new_y must be a 1-D array of floats"); - goto fail; - } - - loginterp((double*)PyArray_DATA(arr_x), (double*)PyArray_DATA(arr_y), - PyArray_DIM(arr_x,0), (double*)PyArray_DATA(arr_new_x), - (double*)PyArray_DATA(arr_new_y), PyArray_DIM(arr_new_x,0)); - - Py_DECREF(arr_x); - Py_DECREF(arr_y); - Py_DECREF(arr_new_x); - Py_DECREF(arr_new_y); - - Py_RETURN_NONE; - -fail: - Py_XDECREF(arr_x); - Py_XDECREF(arr_y); - Py_XDECREF(arr_new_x); - Py_XDECREF(arr_new_y); - return NULL; -} - -static PyObject* window_average_method(PyObject*self, PyObject* args, PyObject* kywds) -{ - static char *kwlist[] = {"x","y","new_x","new_y", NULL}; - PyObject *py_x, *py_y, *py_new_x, *py_new_y; - py_x = py_y = py_new_x = py_new_y = NULL; - PyObject *arr_x, *arr_y, *arr_new_x, *arr_new_y; - arr_x = arr_y = arr_new_x = arr_new_y = NULL; - double width; - - if(!PyArg_ParseTupleAndKeywords(args,kywds,"OOOOd:loginterp_dddd",kwlist,&py_x, &py_y, &py_new_x, &py_new_y, &width)) - return NULL; - arr_x = PyArray_FROMANY(py_x, PyArray_DOUBLE, 1, 1, NPY_IN_ARRAY); - if (!arr_x) { - PyErr_SetString(PyExc_ValueError, "x must be a 1-D array of floats"); - goto fail; - } - arr_y = PyArray_FROMANY(py_y, PyArray_DOUBLE, 1, 1, NPY_IN_ARRAY); - if (!arr_y) { - PyErr_SetString(PyExc_ValueError, "y must be a 1-D array of floats"); - goto fail; - } - arr_new_x = PyArray_FROMANY(py_new_x, PyArray_DOUBLE, 1, 1, NPY_IN_ARRAY); - if (!arr_new_x) { - PyErr_SetString(PyExc_ValueError, "new_x must be a 1-D array of floats"); - goto fail; - } - arr_new_y = PyArray_FROMANY(py_new_y, PyArray_DOUBLE, 1, 1, NPY_INOUT_ARRAY); - if (!arr_new_y) { - PyErr_SetString(PyExc_ValueError, "new_y must be a 1-D array of floats"); - goto fail; - } - - window_average((double*)PyArray_DATA(arr_x), (double*)PyArray_DATA(arr_y), - PyArray_DIM(arr_x,0), (double*)PyArray_DATA(arr_new_x), - (double*)PyArray_DATA(arr_new_y), PyArray_DIM(arr_new_x,0), width); - - Py_DECREF(arr_x); - Py_DECREF(arr_y); - Py_DECREF(arr_new_x); - Py_DECREF(arr_new_y); - - Py_RETURN_NONE; - -fail: - Py_XDECREF(arr_x); - Py_XDECREF(arr_y); - Py_XDECREF(arr_new_x); - Py_XDECREF(arr_new_y); - return NULL; -} - -static PyObject* block_average_above_method(PyObject*self, PyObject* args, PyObject* kywds) -{ - static char *kwlist[] = {"x","y","new_x","new_y", NULL}; - PyObject *py_x, *py_y, *py_new_x, *py_new_y; - py_x = py_y = py_new_x = py_new_y = NULL; - PyObject *arr_x, *arr_y, *arr_new_x, *arr_new_y; - arr_x = arr_y = arr_new_x = arr_new_y = NULL; - - if(!PyArg_ParseTupleAndKeywords(args,kywds,"OOOO:loginterp_dddd",kwlist,&py_x, &py_y, &py_new_x, &py_new_y)) - return NULL; - arr_x = PyArray_FROMANY(py_x, PyArray_DOUBLE, 1, 1, NPY_IN_ARRAY); - if (!arr_x) { - PyErr_SetString(PyExc_ValueError, "x must be a 1-D array of floats"); - goto fail; - } - arr_y = PyArray_FROMANY(py_y, PyArray_DOUBLE, 1, 1, NPY_IN_ARRAY); - if (!arr_y) { - PyErr_SetString(PyExc_ValueError, "y must be a 1-D array of floats"); - goto fail; - } - arr_new_x = PyArray_FROMANY(py_new_x, PyArray_DOUBLE, 1, 1, NPY_IN_ARRAY); - if (!arr_new_x) { - PyErr_SetString(PyExc_ValueError, "new_x must be a 1-D array of floats"); - goto fail; - } - arr_new_y = PyArray_FROMANY(py_new_y, PyArray_DOUBLE, 1, 1, NPY_INOUT_ARRAY); - if (!arr_new_y) { - PyErr_SetString(PyExc_ValueError, "new_y must be a 1-D array of floats"); - goto fail; - } - - block_average_above((double*)PyArray_DATA(arr_x), (double*)PyArray_DATA(arr_y), - PyArray_DIM(arr_x,0), (double*)PyArray_DATA(arr_new_x), - (double*)PyArray_DATA(arr_new_y), PyArray_DIM(arr_new_x,0)); - - Py_DECREF(arr_x); - Py_DECREF(arr_y); - Py_DECREF(arr_new_x); - Py_DECREF(arr_new_y); - - Py_RETURN_NONE; - -fail: - Py_XDECREF(arr_x); - Py_XDECREF(arr_y); - Py_XDECREF(arr_new_x); - Py_XDECREF(arr_new_y); - return NULL; -} - -static PyMethodDef interpolate_methods[] = { - {"linear_dddd", (PyCFunction)linear_method, METH_VARARGS|METH_KEYWORDS, - ""}, - {"loginterp_dddd", (PyCFunction)loginterp_method, METH_VARARGS|METH_KEYWORDS, - ""}, - {"window_average_ddddd", (PyCFunction)window_average_method, METH_VARARGS|METH_KEYWORDS, - ""}, - {"block_average_above_dddd", (PyCFunction)block_average_above_method, METH_VARARGS|METH_KEYWORDS, - ""}, - {NULL, NULL, 0, NULL} -}; - - -PyMODINIT_FUNC init_interpolate(void) -{ - PyObject* m; - m = Py_InitModule3("_interpolate", interpolate_methods, - "A few interpolation routines.\n" - ); - if (m == NULL) - return; - import_array(); -} - -} // extern "C" Copied: branches/Interpolate1D/extensions/_fitpack.pyf (from rev 4591, branches/Interpolate1D/_fitpack.pyf) Copied: branches/Interpolate1D/extensions/_interpolate.cpp (from rev 4587, branches/Interpolate1D/_interpolate.cpp) Copied: branches/Interpolate1D/extensions/fitpack (from rev 4587, branches/Interpolate1D/fitpack) Copied: branches/Interpolate1D/extensions/fitpack/fitpack (from rev 4587, branches/Interpolate1D/fitpack) Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/Makefile =================================================================== --- branches/Interpolate1D/fitpack/Makefile 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/Makefile 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,19 +0,0 @@ -# Makefile that builts a library lib$(LIB).a from all -# of the Fortran files found in the current directory. -# Usage: make LIB= -# Pearu - -OBJ=$(patsubst %.f,%.o,$(shell ls *.f)) -all: lib$(LIB).a -$(OBJ): - $(FC) -c $(FFLAGS) $(FSHARED) $(patsubst %.o,%.f,$(@F)) -o $@ -lib$(LIB).a: $(OBJ) - $(AR) rus lib$(LIB).a $? -clean: - rm *.o - - - - - - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/README =================================================================== --- branches/Interpolate1D/fitpack/README 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/README 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,3 +0,0 @@ -- ddierckx is a 'real*8' version of dierckx - generated by Pearu Peterson . -- dierckx (in netlib) is fitpack by P. Dierckx Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/bispev.f =================================================================== --- branches/Interpolate1D/fitpack/bispev.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/bispev.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,103 +0,0 @@ - subroutine bispev(tx,nx,ty,ny,c,kx,ky,x,mx,y,my,z,wrk,lwrk, - * iwrk,kwrk,ier) -c subroutine bispev evaluates on a grid (x(i),y(j)),i=1,...,mx; j=1,... -c ,my a bivariate spline s(x,y) of degrees kx and ky, given in the -c b-spline representation. -c -c calling sequence: -c call bispev(tx,nx,ty,ny,c,kx,ky,x,mx,y,my,z,wrk,lwrk, -c * iwrk,kwrk,ier) -c -c input parameters: -c tx : real array, length nx, which contains the position of the -c knots in the x-direction. -c nx : integer, giving the total number of knots in the x-direction -c ty : real array, length ny, which contains the position of the -c knots in the y-direction. -c ny : integer, giving the total number of knots in the y-direction -c c : real array, length (nx-kx-1)*(ny-ky-1), which contains the -c b-spline coefficients. -c kx,ky : integer values, giving the degrees of the spline. -c x : real array of dimension (mx). -c before entry x(i) must be set to the x co-ordinate of the -c i-th grid point along the x-axis. -c tx(kx+1)<=x(i-1)<=x(i)<=tx(nx-kx), i=2,...,mx. -c mx : on entry mx must specify the number of grid points along -c the x-axis. mx >=1. -c y : real array of dimension (my). -c before entry y(j) must be set to the y co-ordinate of the -c j-th grid point along the y-axis. -c ty(ky+1)<=y(j-1)<=y(j)<=ty(ny-ky), j=2,...,my. -c my : on entry my must specify the number of grid points along -c the y-axis. my >=1. -c wrk : real array of dimension lwrk. used as workspace. -c lwrk : integer, specifying the dimension of wrk. -c lwrk >= mx*(kx+1)+my*(ky+1) -c iwrk : integer array of dimension kwrk. used as workspace. -c kwrk : integer, specifying the dimension of iwrk. kwrk >= mx+my. -c -c output parameters: -c z : real array of dimension (mx*my). -c on succesful exit z(my*(i-1)+j) contains the value of s(x,y) -c at the point (x(i),y(j)),i=1,...,mx;j=1,...,my. -c ier : integer error flag -c ier=0 : normal return -c ier=10: invalid input data (see restrictions) -c -c restrictions: -c mx >=1, my >=1, lwrk>=mx*(kx+1)+my*(ky+1), kwrk>=mx+my -c tx(kx+1) <= x(i-1) <= x(i) <= tx(nx-kx), i=2,...,mx -c ty(ky+1) <= y(j-1) <= y(j) <= ty(ny-ky), j=2,...,my -c -c other subroutines required: -c fpbisp,fpbspl -c -c references : -c de boor c : on calculating with b-splines, j. approximation theory -c 6 (1972) 50-62. -c cox m.g. : the numerical evaluation of b-splines, j. inst. maths -c applics 10 (1972) 134-149. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author : -c p.dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c latest update : march 1987 -c -c ..scalar arguments.. - integer nx,ny,kx,ky,mx,my,lwrk,kwrk,ier -c ..array arguments.. - integer iwrk(kwrk) - real*8 tx(nx),ty(ny),c((nx-kx-1)*(ny-ky-1)),x(mx),y(my),z(mx*my), - * wrk(lwrk) -c ..local scalars.. - integer i,iw,lwest -c .. -c before starting computations a data check is made. if the input data -c are invalid control is immediately repassed to the calling program. - ier = 10 - lwest = (kx+1)*mx+(ky+1)*my - if(lwrk.lt.lwest) go to 100 - if(kwrk.lt.(mx+my)) go to 100 - if (mx.lt.1) go to 100 - if (mx.eq.1) go to 30 - go to 10 - 10 do 20 i=2,mx - if(x(i).lt.x(i-1)) go to 100 - 20 continue - 30 if (my.lt.1) go to 100 - if (my.eq.1) go to 60 - go to 40 - 40 do 50 i=2,my - if(y(i).lt.y(i-1)) go to 100 - 50 continue - 60 ier = 0 - iw = mx*(kx+1)+1 - call fpbisp(tx,nx,ty,ny,c,kx,ky,x,mx,y,my,z,wrk(1),wrk(iw), - * iwrk(1),iwrk(mx+1)) - 100 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/clocur.f =================================================================== --- branches/Interpolate1D/fitpack/clocur.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/clocur.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,352 +0,0 @@ - subroutine clocur(iopt,ipar,idim,m,u,mx,x,w,k,s,nest,n,t,nc,c,fp, - * wrk,lwrk,iwrk,ier) -c given the ordered set of m points x(i) in the idim-dimensional space -c with x(1)=x(m), and given also a corresponding set of strictly in- -c creasing values u(i) and the set of positive numbers w(i),i=1,2,...,m -c subroutine clocur determines a smooth approximating closed spline -c curve s(u), i.e. -c x1 = s1(u) -c x2 = s2(u) u(1) <= u <= u(m) -c ......... -c xidim = sidim(u) -c with sj(u),j=1,2,...,idim periodic spline functions of degree k with -c common knots t(j),j=1,2,...,n. -c if ipar=1 the values u(i),i=1,2,...,m must be supplied by the user. -c if ipar=0 these values are chosen automatically by clocur as -c v(1) = 0 -c v(i) = v(i-1) + dist(x(i),x(i-1)) ,i=2,3,...,m -c u(i) = v(i)/v(m) ,i=1,2,...,m -c if iopt=-1 clocur calculates the weighted least-squares closed spline -c curve according to a given set of knots. -c if iopt>=0 the number of knots of the splines sj(u) and the position -c t(j),j=1,2,...,n is chosen automatically by the routine. the smooth- -c ness of s(u) is then achieved by minimalizing the discontinuity -c jumps of the k-th derivative of s(u) at the knots t(j),j=k+2,k+3,..., -c n-k-1. the amount of smoothness is determined by the condition that -c f(p)=sum((w(i)*dist(x(i),s(u(i))))**2) be <= s, with s a given non- -c negative constant, called the smoothing factor. -c the fit s(u) is given in the b-spline representation and can be -c evaluated by means of subroutine curev. -c -c calling sequence: -c call clocur(iopt,ipar,idim,m,u,mx,x,w,k,s,nest,n,t,nc,c, -c * fp,wrk,lwrk,iwrk,ier) -c -c parameters: -c iopt : integer flag. on entry iopt must specify whether a weighted -c least-squares closed spline curve (iopt=-1) or a smoothing -c closed spline curve (iopt=0 or 1) must be determined. if -c iopt=0 the routine will start with an initial set of knots -c t(i)=u(1)+(u(m)-u(1))*(i-k-1),i=1,2,...,2*k+2. if iopt=1 the -c routine will continue with the knots found at the last call. -c attention: a call with iopt=1 must always be immediately -c preceded by another call with iopt=1 or iopt=0. -c unchanged on exit. -c ipar : integer flag. on entry ipar must specify whether (ipar=1) -c the user will supply the parameter values u(i),or whether -c (ipar=0) these values are to be calculated by clocur. -c unchanged on exit. -c idim : integer. on entry idim must specify the dimension of the -c curve. 0 < idim < 11. -c unchanged on exit. -c m : integer. on entry m must specify the number of data points. -c m > 1. unchanged on exit. -c u : real array of dimension at least (m). in case ipar=1,before -c entry, u(i) must be set to the i-th value of the parameter -c variable u for i=1,2,...,m. these values must then be -c supplied in strictly ascending order and will be unchanged -c on exit. in case ipar=0, on exit,the array will contain the -c values u(i) as determined by clocur. -c mx : integer. on entry mx must specify the actual dimension of -c the array x as declared in the calling (sub)program. mx must -c not be too small (see x). unchanged on exit. -c x : real array of dimension at least idim*m. -c before entry, x(idim*(i-1)+j) must contain the j-th coord- -c inate of the i-th data point for i=1,2,...,m and j=1,2,..., -c idim. since first and last data point must coincide it -c means that x(j)=x(idim*(m-1)+j),j=1,2,...,idim. -c unchanged on exit. -c w : real array of dimension at least (m). before entry, w(i) -c must be set to the i-th value in the set of weights. the -c w(i) must be strictly positive. w(m) is not used. -c unchanged on exit. see also further comments. -c k : integer. on entry k must specify the degree of the splines. -c 1<=k<=5. it is recommended to use cubic splines (k=3). -c the user is strongly dissuaded from choosing k even,together -c with a small s-value. unchanged on exit. -c s : real.on entry (in case iopt>=0) s must specify the smoothing -c factor. s >=0. unchanged on exit. -c for advice on the choice of s see further comments. -c nest : integer. on entry nest must contain an over-estimate of the -c total number of knots of the splines returned, to indicate -c the storage space available to the routine. nest >=2*k+2. -c in most practical situation nest=m/2 will be sufficient. -c always large enough is nest=m+2*k, the number of knots -c needed for interpolation (s=0). unchanged on exit. -c n : integer. -c unless ier = 10 (in case iopt >=0), n will contain the -c total number of knots of the smoothing spline curve returned -c if the computation mode iopt=1 is used this value of n -c should be left unchanged between subsequent calls. -c in case iopt=-1, the value of n must be specified on entry. -c t : real array of dimension at least (nest). -c on succesful exit, this array will contain the knots of the -c spline curve,i.e. the position of the interior knots t(k+2), -c t(k+3),..,t(n-k-1) as well as the position of the additional -c t(1),t(2),..,t(k+1)=u(1) and u(m)=t(n-k),...,t(n) needed for -c the b-spline representation. -c if the computation mode iopt=1 is used, the values of t(1), -c t(2),...,t(n) should be left unchanged between subsequent -c calls. if the computation mode iopt=-1 is used, the values -c t(k+2),...,t(n-k-1) must be supplied by the user, before -c entry. see also the restrictions (ier=10). -c nc : integer. on entry nc must specify the actual dimension of -c the array c as declared in the calling (sub)program. nc -c must not be too small (see c). unchanged on exit. -c c : real array of dimension at least (nest*idim). -c on succesful exit, this array will contain the coefficients -c in the b-spline representation of the spline curve s(u),i.e. -c the b-spline coefficients of the spline sj(u) will be given -c in c(n*(j-1)+i),i=1,2,...,n-k-1 for j=1,2,...,idim. -c fp : real. unless ier = 10, fp contains the weighted sum of -c squared residuals of the spline curve returned. -c wrk : real array of dimension at least m*(k+1)+nest*(7+idim+5*k). -c used as working space. if the computation mode iopt=1 is -c used, the values wrk(1),...,wrk(n) should be left unchanged -c between subsequent calls. -c lwrk : integer. on entry,lwrk must specify the actual dimension of -c the array wrk as declared in the calling (sub)program. lwrk -c must not be too small (see wrk). unchanged on exit. -c iwrk : integer array of dimension at least (nest). -c used as working space. if the computation mode iopt=1 is -c used,the values iwrk(1),...,iwrk(n) should be left unchanged -c between subsequent calls. -c ier : integer. unless the routine detects an error, ier contains a -c non-positive value on exit, i.e. -c ier=0 : normal return. the close curve returned has a residual -c sum of squares fp such that abs(fp-s)/s <= tol with tol a -c relative tolerance set to 0.001 by the program. -c ier=-1 : normal return. the curve returned is an interpolating -c spline curve (fp=0). -c ier=-2 : normal return. the curve returned is the weighted least- -c squares point,i.e. each spline sj(u) is a constant. in -c this extreme case fp gives the upper bound fp0 for the -c smoothing factor s. -c ier=1 : error. the required storage space exceeds the available -c storage space, as specified by the parameter nest. -c probably causes : nest too small. if nest is already -c large (say nest > m/2), it may also indicate that s is -c too small -c the approximation returned is the least-squares closed -c curve according to the knots t(1),t(2),...,t(n). (n=nest) -c the parameter fp gives the corresponding weighted sum of -c squared residuals (fp>s). -c ier=2 : error. a theoretically impossible result was found during -c the iteration proces for finding a smoothing curve with -c fp = s. probably causes : s too small. -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=3 : error. the maximal number of iterations maxit (set to 20 -c by the program) allowed for finding a smoothing curve -c with fp=s has been reached. probably causes : s too small -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=10 : error. on entry, the input data are controlled on validity -c the following restrictions must be satisfied. -c -1<=iopt<=1, 1<=k<=5, m>1, nest>2*k+2, w(i)>0,i=1,2,...,m -c 0<=ipar<=1, 0=(k+1)*m+nest*(7+idim+5*k), -c nc>=nest*idim, x(j)=x(idim*(m-1)+j), j=1,2,...,idim -c if ipar=0: sum j=1,idim (x(i*idim+j)-x((i-1)*idim+j))**2>0 -c i=1,2,...,m-1. -c if ipar=1: u(1)=0: s>=0 -c if s=0 : nest >= m+2*k -c if one of these conditions is found to be violated,control -c is immediately repassed to the calling program. in that -c case there is no approximation returned. -c -c further comments: -c by means of the parameter s, the user can control the tradeoff -c between closeness of fit and smoothness of fit of the approximation. -c if s is too large, the curve will be too smooth and signal will be -c lost ; if s is too small the curve will pick up too much noise. in -c the extreme cases the program will return an interpolating curve if -c s=0 and the weighted least-squares point if s is very large. -c between these extremes, a properly chosen s will result in a good -c compromise between closeness of fit and smoothness of fit. -c to decide whether an approximation, corresponding to a certain s is -c satisfactory the user is highly recommended to inspect the fits -c graphically. -c recommended values for s depend on the weights w(i). if these are -c taken as 1/d(i) with d(i) an estimate of the standard deviation of -c x(i), a good s-value should be found in the range (m-sqrt(2*m),m+ -c sqrt(2*m)). if nothing is known about the statistical error in x(i) -c each w(i) can be set equal to one and s determined by trial and -c error, taking account of the comments above. the best is then to -c start with a very large value of s ( to determine the weighted -c least-squares point and the upper bound fp0 for s) and then to -c progressively decrease the value of s ( say by a factor 10 in the -c beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the -c approximating curve shows more detail) to obtain closer fits. -c to economize the search for a good s-value the program provides with -c different modes of computation. at the first call of the routine, or -c whenever he wants to restart with the initial set of knots the user -c must set iopt=0. -c if iopt=1 the program will continue with the set of knots found at -c the last call of the routine. this will save a lot of computation -c time if clocur is called repeatedly for different values of s. -c the number of knots of the spline returned and their location will -c depend on the value of s and on the complexity of the shape of the -c curve underlying the data. but, if the computation mode iopt=1 is -c used, the knots returned may also depend on the s-values at previous -c calls (if these were smaller). therefore, if after a number of -c trials with different s-values and iopt=1, the user can finally -c accept a fit as satisfactory, it may be worthwhile for him to call -c clocur once more with the selected value for s but now with iopt=0. -c indeed, clocur may then return an approximation of the same quality -c of fit but with fewer knots and therefore better if data reduction -c is also an important objective for the user. -c -c the form of the approximating curve can strongly be affected by -c the choice of the parameter values u(i). if there is no physical -c reason for choosing a particular parameter u, often good results -c will be obtained with the choice of clocur(in case ipar=0), i.e. -c v(1)=0, v(i)=v(i-1)+q(i), i=2,...,m, u(i)=v(i)/v(m), i=1,..,m -c where -c q(i)= sqrt(sum j=1,idim (xj(i)-xj(i-1))**2 ) -c other possibilities for q(i) are -c q(i)= sum j=1,idim (xj(i)-xj(i-1))**2 -c q(i)= sum j=1,idim abs(xj(i)-xj(i-1)) -c q(i)= max j=1,idim abs(xj(i)-xj(i-1)) -c q(i)= 1 -c -c -c other subroutines required: -c fpbacp,fpbspl,fpchep,fpclos,fpdisc,fpgivs,fpknot,fprati,fprota -c -c references: -c dierckx p. : algorithms for smoothing data with periodic and -c parametric splines, computer graphics and image -c processing 20 (1982) 171-184. -c dierckx p. : algorithms for smoothing data with periodic and param- -c etric splines, report tw55, dept. computer science, -c k.u.leuven, 1981. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author: -c p.dierckx -c dept. computer science, k.u. leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c creation date : may 1979 -c latest update : march 1987 -c -c .. -c ..scalar arguments.. - real*8 s,fp - integer iopt,ipar,idim,m,mx,k,nest,n,nc,lwrk,ier -c ..array arguments.. - real*8 u(m),x(mx),w(m),t(nest),c(nc),wrk(lwrk) - integer iwrk(nest) -c ..local scalars.. - real*8 per,tol,dist - integer i,ia1,ia2,ib,ifp,ig1,ig2,iq,iz,i1,i2,j1,j2,k1,k2,lwest, - * maxit,m1,nmin,ncc,j -c ..function references.. - real*8 sqrt -c we set up the parameters tol and maxit - maxit = 20 - tol = 0.1e-02 -c before starting computations a data check is made. if the input data -c are invalid, control is immediately repassed to the calling program. - ier = 10 - if(iopt.lt.(-1) .or. iopt.gt.1) go to 90 - if(ipar.lt.0 .or. ipar.gt.1) go to 90 - if(idim.le.0 .or. idim.gt.10) go to 90 - if(k.le.0 .or. k.gt.5) go to 90 - k1 = k+1 - k2 = k1+1 - nmin = 2*k1 - if(m.lt.2 .or. nest.lt.nmin) go to 90 - ncc = nest*idim - if(mx.lt.m*idim .or. nc.lt.ncc) go to 90 - lwest = m*k1+nest*(7+idim+5*k) - if(lwrk.lt.lwest) go to 90 - i1 = idim - i2 = m*idim - do 5 j=1,idim - if(x(i1).ne.x(i2)) go to 90 - i1 = i1-1 - i2 = i2-1 - 5 continue - if(ipar.ne.0 .or. iopt.gt.0) go to 40 - i1 = 0 - i2 = idim - u(1) = 0. - do 20 i=2,m - dist = 0. - do 10 j1=1,idim - i1 = i1+1 - i2 = i2+1 - dist = dist+(x(i2)-x(i1))**2 - 10 continue - u(i) = u(i-1)+sqrt(dist) - 20 continue - if(u(m).le.0.) go to 90 - do 30 i=2,m - u(i) = u(i)/u(m) - 30 continue - u(m) = 0.1e+01 - 40 if(w(1).le.0.) go to 90 - m1 = m-1 - do 50 i=1,m1 - if(u(i).ge.u(i+1) .or. w(i).le.0.) go to 90 - 50 continue - if(iopt.ge.0) go to 70 - if(n.le.nmin .or. n.gt.nest) go to 90 - per = u(m)-u(1) - j1 = k1 - t(j1) = u(1) - i1 = n-k - t(i1) = u(m) - j2 = j1 - i2 = i1 - do 60 i=1,k - i1 = i1+1 - i2 = i2-1 - j1 = j1+1 - j2 = j2-1 - t(j2) = t(i2)-per - t(i1) = t(j1)+per - 60 continue - call fpchep(u,m,t,n,k,ier) - if (ier.eq.0) go to 80 - go to 90 - 70 if(s.lt.0.) go to 90 - if(s.eq.0. .and. nest.lt.(m+2*k)) go to 90 - ier = 0 -c we partition the working space and determine the spline approximation. - 80 ifp = 1 - iz = ifp+nest - ia1 = iz+ncc - ia2 = ia1+nest*k1 - ib = ia2+nest*k - ig1 = ib+nest*k2 - ig2 = ig1+nest*k2 - iq = ig2+nest*k1 - call fpclos(iopt,idim,m,u,mx,x,w,k,s,nest,tol,maxit,k1,k2,n,t, - * ncc,c,fp,wrk(ifp),wrk(iz),wrk(ia1),wrk(ia2),wrk(ib),wrk(ig1), - * wrk(ig2),wrk(iq),iwrk,ier) - 90 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/cocosp.f =================================================================== --- branches/Interpolate1D/fitpack/cocosp.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/cocosp.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,180 +0,0 @@ - subroutine cocosp(m,x,y,w,n,t,e,maxtr,maxbin,c,sq,sx,bind,wrk, - * lwrk,iwrk,kwrk,ier) -c given the set of data points (x(i),y(i)) and the set of positive -c numbers w(i),i=1,2,...,m, subroutine cocosp determines the weighted -c least-squares cubic spline s(x) with given knots t(j),j=1,2,...,n -c which satisfies the following concavity/convexity conditions -c s''(t(j+3))*e(j) <= 0, j=1,2,...n-6 -c the fit is given in the b-spline representation( b-spline coef- -c ficients c(j),j=1,2,...n-4) and can be evaluated by means of -c subroutine splev. -c -c calling sequence: -c call cocosp(m,x,y,w,n,t,e,maxtr,maxbin,c,sq,sx,bind,wrk, -c * lwrk,iwrk,kwrk,ier) -c -c parameters: -c m : integer. on entry m must specify the number of data points. -c m > 3. unchanged on exit. -c x : real array of dimension at least (m). before entry, x(i) -c must be set to the i-th value of the independent variable x, -c for i=1,2,...,m. these values must be supplied in strictly -c ascending order. unchanged on exit. -c y : real array of dimension at least (m). before entry, y(i) -c must be set to the i-th value of the dependent variable y, -c for i=1,2,...,m. unchanged on exit. -c w : real array of dimension at least (m). before entry, w(i) -c must be set to the i-th value in the set of weights. the -c w(i) must be strictly positive. unchanged on exit. -c n : integer. on entry n must contain the total number of knots -c of the cubic spline. m+4>=n>=8. unchanged on exit. -c t : real array of dimension at least (n). before entry, this -c array must contain the knots of the spline, i.e. the position -c of the interior knots t(5),t(6),...,t(n-4) as well as the -c position of the boundary knots t(1),t(2),t(3),t(4) and t(n-3) -c t(n-2),t(n-1),t(n) needed for the b-spline representation. -c unchanged on exit. see also the restrictions (ier=10). -c e : real array of dimension at least (n). before entry, e(j) -c must be set to 1 if s(x) must be locally concave at t(j+3), -c to (-1) if s(x) must be locally convex at t(j+3) and to 0 -c if no convexity constraint is imposed at t(j+3),j=1,2,..,n-6. -c e(n-5),...,e(n) are not used. unchanged on exit. -c maxtr : integer. on entry maxtr must contain an over-estimate of the -c total number of records in the used tree structure, to indic- -c ate the storage space available to the routine. maxtr >=1 -c in most practical situation maxtr=100 will be sufficient. -c always large enough is -c n-5 n-6 -c maxtr = ( ) + ( ) with l the greatest -c l l+1 -c integer <= (n-6)/2 . unchanged on exit. -c maxbin: integer. on entry maxbin must contain an over-estimate of the -c number of knots where s(x) will have a zero second derivative -c maxbin >=1. in most practical situation maxbin = 10 will be -c sufficient. always large enough is maxbin=n-6. -c unchanged on exit. -c c : real array of dimension at least (n). -c on succesful exit, this array will contain the coefficients -c c(1),c(2),..,c(n-4) in the b-spline representation of s(x) -c sq : real. on succesful exit, sq contains the weighted sum of -c squared residuals of the spline approximation returned. -c sx : real array of dimension at least m. on succesful exit -c this array will contain the spline values s(x(i)),i=1,...,m -c bind : logical array of dimension at least (n). on succesful exit -c this array will indicate the knots where s''(x)=0, i.e. -c s''(t(j+3)) .eq. 0 if bind(j) = .true. -c s''(t(j+3)) .ne. 0 if bind(j) = .false., j=1,2,...,n-6 -c wrk : real array of dimension at least m*4+n*7+maxbin*(maxbin+n+1) -c used as working space. -c lwrk : integer. on entry,lwrk must specify the actual dimension of -c the array wrk as declared in the calling (sub)program.lwrk -c must not be too small (see wrk). unchanged on exit. -c iwrk : integer array of dimension at least (maxtr*4+2*(maxbin+1)) -c used as working space. -c kwrk : integer. on entry,kwrk must specify the actual dimension of -c the array iwrk as declared in the calling (sub)program. kwrk -c must not be too small (see iwrk). unchanged on exit. -c ier : integer. error flag -c ier=0 : succesful exit. -c ier>0 : abnormal termination: no approximation is returned -c ier=1 : the number of knots where s''(x)=0 exceeds maxbin. -c probably causes : maxbin too small. -c ier=2 : the number of records in the tree structure exceeds -c maxtr. -c probably causes : maxtr too small. -c ier=3 : the algoritm finds no solution to the posed quadratic -c programming problem. -c probably causes : rounding errors. -c ier=10 : on entry, the input data are controlled on validity. -c the following restrictions must be satisfied -c m>3, maxtr>=1, maxbin>=1, 8<=n<=m+4,w(i) > 0, -c x(1)=maxtr*4+2*(maxbin+1), -c lwrk>=m*4+n*7+maxbin*(maxbin+n+1), -c the schoenberg-whitney conditions, i.e. there must -c be a subset of data points xx(j) such that -c t(j) < xx(j) < t(j+4), j=1,2,...,n-4 -c if one of these restrictions is found to be violated -c control is immediately repassed to the calling program -c -c -c other subroutines required: -c fpcosp,fpbspl,fpadno,fpdeno,fpseno,fpfrno,fpchec -c -c references: -c dierckx p. : an algorithm for cubic spline fitting with convexity -c constraints, computing 24 (1980) 349-371. -c dierckx p. : an algorithm for least-squares cubic spline fitting -c with convexity and concavity constraints, report tw39, -c dept. computer science, k.u.leuven, 1978. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author: -c p. dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c creation date : march 1978 -c latest update : march 1987. -c -c .. -c ..scalar arguments.. - real*8 sq - integer m,n,maxtr,maxbin,lwrk,kwrk,ier -c ..array arguments.. - real*8 x(m),y(m),w(m),t(n),e(n),c(n),sx(m),wrk(lwrk) - integer iwrk(kwrk) - logical bind(n) -c ..local scalars.. - integer i,ia,ib,ic,iq,iu,iz,izz,ji,jib,jjb,jl,jr,ju,kwest, - * lwest,mb,nm,n6 - real*8 one -c .. -c set constant - one = 0.1e+01 -c before starting computations a data check is made. if the input data -c are invalid, control is immediately repassed to the calling program. - ier = 10 - if(m.lt.4 .or. n.lt.8) go to 40 - if(maxtr.lt.1 .or. maxbin.lt.1) go to 40 - lwest = 7*n+m*4+maxbin*(1+n+maxbin) - kwest = 4*maxtr+2*(maxbin+1) - if(lwrk.lt.lwest .or. kwrk.lt.kwest) go to 40 - if(w(1).le.0.) go to 40 - do 10 i=2,m - if(x(i-1).ge.x(i) .or. w(i).le.0.) go to 40 - 10 continue - call fpchec(x,m,t,n,3,ier) - if (ier.eq.0) go to 20 - go to 40 -c set numbers e(i) - 20 n6 = n-6 - do 30 i=1,n6 - if(e(i).gt.0.) e(i) = one - if(e(i).lt.0.) e(i) = -one - 30 continue -c we partition the working space and determine the spline approximation - nm = n+maxbin - mb = maxbin+1 - ia = 1 - ib = ia+4*n - ic = ib+nm*maxbin - iz = ic+n - izz = iz+n - iu = izz+n - iq = iu+maxbin - ji = 1 - ju = ji+maxtr - jl = ju+maxtr - jr = jl+maxtr - jjb = jr+maxtr - jib = jjb+mb - call fpcosp(m,x,y,w,n,t,e,maxtr,maxbin,c,sq,sx,bind,nm,mb,wrk(ia), - * - * wrk(ib),wrk(ic),wrk(iz),wrk(izz),wrk(iu),wrk(iq),iwrk(ji), - * iwrk(ju),iwrk(jl),iwrk(jr),iwrk(jjb),iwrk(jib),ier) - 40 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/concon.f =================================================================== --- branches/Interpolate1D/fitpack/concon.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/concon.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,233 +0,0 @@ - subroutine concon(iopt,m,x,y,w,v,s,nest,maxtr,maxbin,n,t,c,sq, - * sx,bind,wrk,lwrk,iwrk,kwrk,ier) -c given the set of data points (x(i),y(i)) and the set of positive -c numbers w(i), i=1,2,...,m,subroutine concon determines a cubic spline -c approximation s(x) which satisfies the following local convexity -c constraints s''(x(i))*v(i) <= 0, i=1,2,...,m. -c the number of knots n and the position t(j),j=1,2,...n is chosen -c automatically by the routine in a way that -c sq = sum((w(i)*(y(i)-s(x(i))))**2) be <= s. -c the fit is given in the b-spline representation (b-spline coef- -c ficients c(j),j=1,2,...n-4) and can be evaluated by means of -c subroutine splev. -c -c calling sequence: -c -c call concon(iopt,m,x,y,w,v,s,nest,maxtr,maxbin,n,t,c,sq, -c * sx,bind,wrk,lwrk,iwrk,kwrk,ier) -c -c parameters: -c iopt: integer flag. -c if iopt=0, the routine will start with the minimal number of -c knots to guarantee that the convexity conditions will be -c satisfied. if iopt=1, the routine will continue with the set -c of knots found at the last call of the routine. -c attention: a call with iopt=1 must always be immediately -c preceded by another call with iopt=1 or iopt=0. -c unchanged on exit. -c m : integer. on entry m must specify the number of data points. -c m > 3. unchanged on exit. -c x : real array of dimension at least (m). before entry, x(i) -c must be set to the i-th value of the independent variable x, -c for i=1,2,...,m. these values must be supplied in strictly -c ascending order. unchanged on exit. -c y : real array of dimension at least (m). before entry, y(i) -c must be set to the i-th value of the dependent variable y, -c for i=1,2,...,m. unchanged on exit. -c w : real array of dimension at least (m). before entry, w(i) -c must be set to the i-th value in the set of weights. the -c w(i) must be strictly positive. unchanged on exit. -c v : real array of dimension at least (m). before entry, v(i) -c must be set to 1 if s(x) must be locally concave at x(i), -c to (-1) if s(x) must be locally convex at x(i) and to 0 -c if no convexity constraint is imposed at x(i). -c s : real. on entry s must specify an over-estimate for the -c the weighted sum of squared residuals sq of the requested -c spline. s >=0. unchanged on exit. -c nest : integer. on entry nest must contain an over-estimate of the -c total number of knots of the spline returned, to indicate -c the storage space available to the routine. nest >=8. -c in most practical situation nest=m/2 will be sufficient. -c always large enough is nest=m+4. unchanged on exit. -c maxtr : integer. on entry maxtr must contain an over-estimate of the -c total number of records in the used tree structure, to indic- -c ate the storage space available to the routine. maxtr >=1 -c in most practical situation maxtr=100 will be sufficient. -c always large enough is -c nest-5 nest-6 -c maxtr = ( ) + ( ) with l the greatest -c l l+1 -c integer <= (nest-6)/2 . unchanged on exit. -c maxbin: integer. on entry maxbin must contain an over-estimate of the -c number of knots where s(x) will have a zero second derivative -c maxbin >=1. in most practical situation maxbin = 10 will be -c sufficient. always large enough is maxbin=nest-6. -c unchanged on exit. -c n : integer. -c on exit with ier <=0, n will contain the total number of -c knots of the spline approximation returned. if the comput- -c ation mode iopt=1 is used this value of n should be left -c unchanged between subsequent calls. -c t : real array of dimension at least (nest). -c on exit with ier<=0, this array will contain the knots of the -c spline,i.e. the position of the interior knots t(5),t(6),..., -c t(n-4) as well as the position of the additional knots -c t(1)=t(2)=t(3)=t(4)=x(1) and t(n-3)=t(n-2)=t(n-1)=t(n)=x(m) -c needed for the the b-spline representation. -c if the computation mode iopt=1 is used, the values of t(1), -c t(2),...,t(n) should be left unchanged between subsequent -c calls. -c c : real array of dimension at least (nest). -c on succesful exit, this array will contain the coefficients -c c(1),c(2),..,c(n-4) in the b-spline representation of s(x) -c sq : real. unless ier>0 , sq contains the weighted sum of -c squared residuals of the spline approximation returned. -c sx : real array of dimension at least m. on exit with ier<=0 -c this array will contain the spline values s(x(i)),i=1,...,m -c if the computation mode iopt=1 is used, the values of sx(1), -c sx(2),...,sx(m) should be left unchanged between subsequent -c calls. -c bind: logical array of dimension at least nest. on exit with ier<=0 -c this array will indicate the knots where s''(x)=0, i.e. -c s''(t(j+3)) .eq. 0 if bind(j) = .true. -c s''(t(j+3)) .ne. 0 if bind(j) = .false., j=1,2,...,n-6 -c if the computation mode iopt=1 is used, the values of bind(1) -c ,...,bind(n-6) should be left unchanged between subsequent -c calls. -c wrk : real array of dimension at least (m*4+nest*8+maxbin*(maxbin+ -c nest+1)). used as working space. -c lwrk : integer. on entry,lwrk must specify the actual dimension of -c the array wrk as declared in the calling (sub)program.lwrk -c must not be too small (see wrk). unchanged on exit. -c iwrk : integer array of dimension at least (maxtr*4+2*(maxbin+1)) -c used as working space. -c kwrk : integer. on entry,kwrk must specify the actual dimension of -c the array iwrk as declared in the calling (sub)program. kwrk -c must not be too small (see iwrk). unchanged on exit. -c ier : integer. error flag -c ier=0 : normal return, s(x) satisfies the concavity/convexity -c constraints and sq <= s. -c ier<0 : abnormal termination: s(x) satisfies the concavity/ -c convexity constraints but sq > s. -c ier=-3 : the requested storage space exceeds the available -c storage space as specified by the parameter nest. -c probably causes: nest too small. if nest is already -c large (say nest > m/2), it may also indicate that s -c is too small. -c the approximation returned is the least-squares cubic -c spline according to the knots t(1),...,t(n) (n=nest) -c which satisfies the convexity constraints. -c ier=-2 : the maximal number of knots n=m+4 has been reached. -c probably causes: s too small. -c ier=-1 : the number of knots n is less than the maximal number -c m+4 but concon finds that adding one or more knots -c will not further reduce the value of sq. -c probably causes : s too small. -c ier>0 : abnormal termination: no approximation is returned -c ier=1 : the number of knots where s''(x)=0 exceeds maxbin. -c probably causes : maxbin too small. -c ier=2 : the number of records in the tree structure exceeds -c maxtr. -c probably causes : maxtr too small. -c ier=3 : the algoritm finds no solution to the posed quadratic -c programming problem. -c probably causes : rounding errors. -c ier=4 : the minimum number of knots (given by n) to guarantee -c that the concavity/convexity conditions will be -c satisfied is greater than nest. -c probably causes: nest too small. -c ier=5 : the minimum number of knots (given by n) to guarantee -c that the concavity/convexity conditions will be -c satisfied is greater than m+4. -c probably causes: strongly alternating convexity and -c concavity conditions. normally the situation can be -c coped with by adding n-m-4 extra data points (found -c by linear interpolation e.g.) with a small weight w(i) -c and a v(i) number equal to zero. -c ier=10 : on entry, the input data are controlled on validity. -c the following restrictions must be satisfied -c 0<=iopt<=1, m>3, nest>=8, s>=0, maxtr>=1, maxbin>=1, -c kwrk>=maxtr*4+2*(maxbin+1), w(i)>0, x(i) < x(i+1), -c lwrk>=m*4+nest*8+maxbin*(maxbin+nest+1) -c if one of these restrictions is found to be violated -c control is immediately repassed to the calling program -c -c further comments: -c as an example of the use of the computation mode iopt=1, the -c following program segment will cause concon to return control -c each time a spline with a new set of knots has been computed. -c ............. -c iopt = 0 -c s = 0.1e+60 (s very large) -c do 10 i=1,m -c call concon(iopt,m,x,y,w,v,s,nest,maxtr,maxbin,n,t,c,sq,sx, -c * bind,wrk,lwrk,iwrk,kwrk,ier) -c ...... -c s = sq -c iopt=1 -c 10 continue -c ............. -c -c other subroutines required: -c fpcoco,fpcosp,fpbspl,fpadno,fpdeno,fpseno,fpfrno -c -c references: -c dierckx p. : an algorithm for cubic spline fitting with convexity -c constraints, computing 24 (1980) 349-371. -c dierckx p. : an algorithm for least-squares cubic spline fitting -c with convexity and concavity constraints, report tw39, -c dept. computer science, k.u.leuven, 1978. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author: -c p. dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c creation date : march 1978 -c latest update : march 1987. -c -c .. -c ..scalar arguments.. - real*8 s,sq - integer iopt,m,nest,maxtr,maxbin,n,lwrk,kwrk,ier -c ..array arguments.. - real*8 x(m),y(m),w(m),v(m),t(nest),c(nest),sx(m),wrk(lwrk) - integer iwrk(kwrk) - logical bind(nest) -c ..local scalars.. - integer i,lwest,kwest,ie,iw,lww - real*8 one -c .. -c set constant - one = 0.1e+01 -c before starting computations a data check is made. if the input data -c are invalid, control is immediately repassed to the calling program. - ier = 10 - if(iopt.lt.0 .or. iopt.gt.1) go to 30 - if(m.lt.4 .or. nest.lt.8) go to 30 - if(s.lt.0.) go to 30 - if(maxtr.lt.1 .or. maxbin.lt.1) go to 30 - lwest = 8*nest+m*4+maxbin*(1+nest+maxbin) - kwest = 4*maxtr+2*(maxbin+1) - if(lwrk.lt.lwest .or. kwrk.lt.kwest) go to 30 - if(iopt.gt.0) go to 20 - if(w(1).le.0.) go to 30 - if(v(1).gt.0.) v(1) = one - if(v(1).lt.0.) v(1) = -one - do 10 i=2,m - if(x(i-1).ge.x(i) .or. w(i).le.0.) go to 30 - if(v(i).gt.0.) v(i) = one - if(v(i).lt.0.) v(i) = -one - 10 continue - 20 ier = 0 -c we partition the working space and determine the spline approximation - ie = 1 - iw = ie+nest - lww = lwrk-nest - call fpcoco(iopt,m,x,y,w,v,s,nest,maxtr,maxbin,n,t,c,sq,sx, - * bind,wrk(ie),wrk(iw),lww,iwrk,kwrk,ier) - 30 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/concur.f =================================================================== --- branches/Interpolate1D/fitpack/concur.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/concur.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,370 +0,0 @@ - subroutine concur(iopt,idim,m,u,mx,x,xx,w,ib,db,nb,ie,de,ne,k,s, - * nest,n,t,nc,c,np,cp,fp,wrk,lwrk,iwrk,ier) -c given the ordered set of m points x(i) in the idim-dimensional space -c and given also a corresponding set of strictly increasing values u(i) -c and the set of positive numbers w(i),i=1,2,...,m, subroutine concur -c determines a smooth approximating spline curve s(u), i.e. -c x1 = s1(u) -c x2 = s2(u) ub = u(1) <= u <= u(m) = ue -c ......... -c xidim = sidim(u) -c with sj(u),j=1,2,...,idim spline functions of odd degree k with -c common knots t(j),j=1,2,...,n. -c in addition these splines will satisfy the following boundary -c constraints (l) -c if ib > 0 : sj (u(1)) = db(idim*l+j) ,l=0,1,...,ib-1 -c and (l) -c if ie > 0 : sj (u(m)) = de(idim*l+j) ,l=0,1,...,ie-1. -c if iopt=-1 concur calculates the weighted least-squares spline curve -c according to a given set of knots. -c if iopt>=0 the number of knots of the splines sj(u) and the position -c t(j),j=1,2,...,n is chosen automatically by the routine. the smooth- -c ness of s(u) is then achieved by minimalizing the discontinuity -c jumps of the k-th derivative of s(u) at the knots t(j),j=k+2,k+3,..., -c n-k-1. the amount of smoothness is determined by the condition that -c f(p)=sum((w(i)*dist(x(i),s(u(i))))**2) be <= s, with s a given non- -c negative constant, called the smoothing factor. -c the fit s(u) is given in the b-spline representation and can be -c evaluated by means of subroutine curev. -c -c calling sequence: -c call concur(iopt,idim,m,u,mx,x,xx,w,ib,db,nb,ie,de,ne,k,s,nest,n, -c * t,nc,c,np,cp,fp,wrk,lwrk,iwrk,ier) -c -c parameters: -c iopt : integer flag. on entry iopt must specify whether a weighted -c least-squares spline curve (iopt=-1) or a smoothing spline -c curve (iopt=0 or 1) must be determined.if iopt=0 the routine -c will start with an initial set of knots t(i)=ub,t(i+k+1)=ue, -c i=1,2,...,k+1. if iopt=1 the routine will continue with the -c knots found at the last call of the routine. -c attention: a call with iopt=1 must always be immediately -c preceded by another call with iopt=1 or iopt=0. -c unchanged on exit. -c idim : integer. on entry idim must specify the dimension of the -c curve. 0 < idim < 11. -c unchanged on exit. -c m : integer. on entry m must specify the number of data points. -c m > k-max(ib-1,0)-max(ie-1,0). unchanged on exit. -c u : real array of dimension at least (m). before entry, -c u(i) must be set to the i-th value of the parameter variable -c u for i=1,2,...,m. these values must be supplied in -c strictly ascending order and will be unchanged on exit. -c mx : integer. on entry mx must specify the actual dimension of -c the arrays x and xx as declared in the calling (sub)program -c mx must not be too small (see x). unchanged on exit. -c x : real array of dimension at least idim*m. -c before entry, x(idim*(i-1)+j) must contain the j-th coord- -c inate of the i-th data point for i=1,2,...,m and j=1,2,..., -c idim. unchanged on exit. -c xx : real array of dimension at least idim*m. -c used as working space. on exit xx contains the coordinates -c of the data points to which a spline curve with zero deriv- -c ative constraints has been determined. -c if the computation mode iopt =1 is used xx should be left -c unchanged between calls. -c w : real array of dimension at least (m). before entry, w(i) -c must be set to the i-th value in the set of weights. the -c w(i) must be strictly positive. unchanged on exit. -c see also further comments. -c ib : integer. on entry ib must specify the number of derivative -c constraints for the curve at the begin point. 0<=ib<=(k+1)/2 -c unchanged on exit. -c db : real array of dimension nb. before entry db(idim*l+j) must -c contain the l-th order derivative of sj(u) at u=u(1) for -c j=1,2,...,idim and l=0,1,...,ib-1 (if ib>0). -c unchanged on exit. -c nb : integer, specifying the dimension of db. nb>=max(1,idim*ib) -c unchanged on exit. -c ie : integer. on entry ie must specify the number of derivative -c constraints for the curve at the end point. 0<=ie<=(k+1)/2 -c unchanged on exit. -c de : real array of dimension ne. before entry de(idim*l+j) must -c contain the l-th order derivative of sj(u) at u=u(m) for -c j=1,2,...,idim and l=0,1,...,ie-1 (if ie>0). -c unchanged on exit. -c ne : integer, specifying the dimension of de. ne>=max(1,idim*ie) -c unchanged on exit. -c k : integer. on entry k must specify the degree of the splines. -c k=1,3 or 5. -c unchanged on exit. -c s : real.on entry (in case iopt>=0) s must specify the smoothing -c factor. s >=0. unchanged on exit. -c for advice on the choice of s see further comments. -c nest : integer. on entry nest must contain an over-estimate of the -c total number of knots of the splines returned, to indicate -c the storage space available to the routine. nest >=2*k+2. -c in most practical situation nest=m/2 will be sufficient. -c always large enough is nest=m+k+1+max(0,ib-1)+max(0,ie-1), -c the number of knots needed for interpolation (s=0). -c unchanged on exit. -c n : integer. -c unless ier = 10 (in case iopt >=0), n will contain the -c total number of knots of the smoothing spline curve returned -c if the computation mode iopt=1 is used this value of n -c should be left unchanged between subsequent calls. -c in case iopt=-1, the value of n must be specified on entry. -c t : real array of dimension at least (nest). -c on succesful exit, this array will contain the knots of the -c spline curve,i.e. the position of the interior knots t(k+2), -c t(k+3),..,t(n-k-1) as well as the position of the additional -c t(1)=t(2)=...=t(k+1)=ub and t(n-k)=...=t(n)=ue needed for -c the b-spline representation. -c if the computation mode iopt=1 is used, the values of t(1), -c t(2),...,t(n) should be left unchanged between subsequent -c calls. if the computation mode iopt=-1 is used, the values -c t(k+2),...,t(n-k-1) must be supplied by the user, before -c entry. see also the restrictions (ier=10). -c nc : integer. on entry nc must specify the actual dimension of -c the array c as declared in the calling (sub)program. nc -c must not be too small (see c). unchanged on exit. -c c : real array of dimension at least (nest*idim). -c on succesful exit, this array will contain the coefficients -c in the b-spline representation of the spline curve s(u),i.e. -c the b-spline coefficients of the spline sj(u) will be given -c in c(n*(j-1)+i),i=1,2,...,n-k-1 for j=1,2,...,idim. -c cp : real array of dimension at least 2*(k+1)*idim. -c on exit cp will contain the b-spline coefficients of a -c polynomial curve which satisfies the boundary constraints. -c if the computation mode iopt =1 is used cp should be left -c unchanged between calls. -c np : integer. on entry np must specify the actual dimension of -c the array cp as declared in the calling (sub)program. np -c must not be too small (see cp). unchanged on exit. -c fp : real. unless ier = 10, fp contains the weighted sum of -c squared residuals of the spline curve returned. -c wrk : real array of dimension at least m*(k+1)+nest*(6+idim+3*k). -c used as working space. if the computation mode iopt=1 is -c used, the values wrk(1),...,wrk(n) should be left unchanged -c between subsequent calls. -c lwrk : integer. on entry,lwrk must specify the actual dimension of -c the array wrk as declared in the calling (sub)program. lwrk -c must not be too small (see wrk). unchanged on exit. -c iwrk : integer array of dimension at least (nest). -c used as working space. if the computation mode iopt=1 is -c used,the values iwrk(1),...,iwrk(n) should be left unchanged -c between subsequent calls. -c ier : integer. unless the routine detects an error, ier contains a -c non-positive value on exit, i.e. -c ier=0 : normal return. the curve returned has a residual sum of -c squares fp such that abs(fp-s)/s <= tol with tol a relat- -c ive tolerance set to 0.001 by the program. -c ier=-1 : normal return. the curve returned is an interpolating -c spline curve, satisfying the constraints (fp=0). -c ier=-2 : normal return. the curve returned is the weighted least- -c squares polynomial curve of degree k, satisfying the -c constraints. in this extreme case fp gives the upper -c bound fp0 for the smoothing factor s. -c ier=1 : error. the required storage space exceeds the available -c storage space, as specified by the parameter nest. -c probably causes : nest too small. if nest is already -c large (say nest > m/2), it may also indicate that s is -c too small -c the approximation returned is the least-squares spline -c curve according to the knots t(1),t(2),...,t(n). (n=nest) -c the parameter fp gives the corresponding weighted sum of -c squared residuals (fp>s). -c ier=2 : error. a theoretically impossible result was found during -c the iteration proces for finding a smoothing spline curve -c with fp = s. probably causes : s too small. -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=3 : error. the maximal number of iterations maxit (set to 20 -c by the program) allowed for finding a smoothing curve -c with fp=s has been reached. probably causes : s too small -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=10 : error. on entry, the input data are controlled on validity -c the following restrictions must be satisfied. -c -1<=iopt<=1, k = 1,3 or 5, m>k-max(0,ib-1)-max(0,ie-1), -c nest>=2k+2, 0=(k+1)*m+nest*(6+idim+3*k), -c nc >=nest*idim ,u(1)0 i=1,2,...,m, -c mx>=idim*m,0<=ib<=(k+1)/2,0<=ie<=(k+1)/2,nb>=1,ne>=1, -c nb>=ib*idim,ne>=ib*idim,np>=2*(k+1)*idim, -c if iopt=-1:2*k+2<=n<=min(nest,mmax) with mmax = m+k+1+ -c max(0,ib-1)+max(0,ie-1) -c u(1)=0: s>=0 -c if s=0 : nest >=mmax (see above) -c if one of these conditions is found to be violated,control -c is immediately repassed to the calling program. in that -c case there is no approximation returned. -c -c further comments: -c by means of the parameter s, the user can control the tradeoff -c between closeness of fit and smoothness of fit of the approximation. -c if s is too large, the curve will be too smooth and signal will be -c lost ; if s is too small the curve will pick up too much noise. in -c the extreme cases the program will return an interpolating curve if -c s=0 and the least-squares polynomial curve of degree k if s is -c very large. between these extremes, a properly chosen s will result -c in a good compromise between closeness of fit and smoothness of fit. -c to decide whether an approximation, corresponding to a certain s is -c satisfactory the user is highly recommended to inspect the fits -c graphically. -c recommended values for s depend on the weights w(i). if these are -c taken as 1/d(i) with d(i) an estimate of the standard deviation of -c x(i), a good s-value should be found in the range (m-sqrt(2*m),m+ -c sqrt(2*m)). if nothing is known about the statistical error in x(i) -c each w(i) can be set equal to one and s determined by trial and -c error, taking account of the comments above. the best is then to -c start with a very large value of s ( to determine the least-squares -c polynomial curve and the upper bound fp0 for s) and then to -c progressively decrease the value of s ( say by a factor 10 in the -c beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the -c approximating curve shows more detail) to obtain closer fits. -c to economize the search for a good s-value the program provides with -c different modes of computation. at the first call of the routine, or -c whenever he wants to restart with the initial set of knots the user -c must set iopt=0. -c if iopt=1 the program will continue with the set of knots found at -c the last call of the routine. this will save a lot of computation -c time if concur is called repeatedly for different values of s. -c the number of knots of the spline returned and their location will -c depend on the value of s and on the complexity of the shape of the -c curve underlying the data. but, if the computation mode iopt=1 is -c used, the knots returned may also depend on the s-values at previous -c calls (if these were smaller). therefore, if after a number of -c trials with different s-values and iopt=1, the user can finally -c accept a fit as satisfactory, it may be worthwhile for him to call -c concur once more with the selected value for s but now with iopt=0. -c indeed, concur may then return an approximation of the same quality -c of fit but with fewer knots and therefore better if data reduction -c is also an important objective for the user. -c -c the form of the approximating curve can strongly be affected by -c the choice of the parameter values u(i). if there is no physical -c reason for choosing a particular parameter u, often good results -c will be obtained with the choice -c v(1)=0, v(i)=v(i-1)+q(i), i=2,...,m, u(i)=v(i)/v(m), i=1,..,m -c where -c q(i)= sqrt(sum j=1,idim (xj(i)-xj(i-1))**2 ) -c other possibilities for q(i) are -c q(i)= sum j=1,idim (xj(i)-xj(i-1))**2 -c q(i)= sum j=1,idim abs(xj(i)-xj(i-1)) -c q(i)= max j=1,idim abs(xj(i)-xj(i-1)) -c q(i)= 1 -c -c other subroutines required: -c fpback,fpbspl,fpched,fpcons,fpdisc,fpgivs,fpknot,fprati,fprota -c curev,fppocu,fpadpo,fpinst -c -c references: -c dierckx p. : algorithms for smoothing data with periodic and -c parametric splines, computer graphics and image -c processing 20 (1982) 171-184. -c dierckx p. : algorithms for smoothing data with periodic and param- -c etric splines, report tw55, dept. computer science, -c k.u.leuven, 1981. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author: -c p.dierckx -c dept. computer science, k.u. leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c creation date : may 1979 -c latest update : march 1987 -c -c .. -c ..scalar arguments.. - real*8 s,fp - integer iopt,idim,m,mx,ib,nb,ie,ne,k,nest,n,nc,np,lwrk,ier -c ..array arguments.. - real*8 u(m),x(mx),xx(mx),db(nb),de(ne),w(m),t(nest),c(nc),wrk(lwrk - *) - real*8 cp(np) - integer iwrk(nest) -c ..local scalars.. - real*8 tol,dist - integer i,ib1,ie1,ja,jb,jfp,jg,jq,jz,j,k1,k2,lwest,maxit,nmin, - * ncc,kk,mmin,nmax,mxx -c ..function references - integer max0 -c .. -c we set up the parameters tol and maxit - maxit = 20 - tol = 0.1e-02 -c before starting computations a data check is made. if the input data -c are invalid, control is immediately repassed to the calling program. - ier = 10 - if(iopt.lt.(-1) .or. iopt.gt.1) go to 90 - if(idim.le.0 .or. idim.gt.10) go to 90 - if(k.le.0 .or. k.gt.5) go to 90 - k1 = k+1 - kk = k1/2 - if(kk*2.ne.k1) go to 90 - k2 = k1+1 - if(ib.lt.0 .or. ib.gt.kk) go to 90 - if(ie.lt.0 .or. ie.gt.kk) go to 90 - nmin = 2*k1 - ib1 = max0(0,ib-1) - ie1 = max0(0,ie-1) - mmin = k1-ib1-ie1 - if(m.lt.mmin .or. nest.lt.nmin) go to 90 - if(nb.lt.(idim*ib) .or. ne.lt.(idim*ie)) go to 90 - if(np.lt.(2*k1*idim)) go to 90 - mxx = m*idim - ncc = nest*idim - if(mx.lt.mxx .or. nc.lt.ncc) go to 90 - lwest = m*k1+nest*(6+idim+3*k) - if(lwrk.lt.lwest) go to 90 - if(w(1).le.0.) go to 90 - do 10 i=2,m - if(u(i-1).ge.u(i) .or. w(i).le.0.) go to 90 - 10 continue - if(iopt.ge.0) go to 30 - if(n.lt.nmin .or. n.gt.nest) go to 90 - j = n - do 20 i=1,k1 - t(i) = u(1) - t(j) = u(m) - j = j-1 - 20 continue - call fpched(u,m,t,n,k,ib,ie,ier) - if (ier.eq.0) go to 40 - go to 90 - 30 if(s.lt.0.) go to 90 - nmax = m+k1+ib1+ie1 - if(s.eq.0. .and. nest.lt.nmax) go to 90 - ier = 0 - if(iopt.gt.0) go to 70 -c we determine a polynomial curve satisfying the boundary constraints. - 40 call fppocu(idim,k,u(1),u(m),ib,db,nb,ie,de,ne,cp,np) -c we generate new data points which will be approximated by a spline -c with zero derivative constraints. - j = nmin - do 50 i=1,k1 - wrk(i) = u(1) - wrk(j) = u(m) - j = j-1 - 50 continue -c evaluate the polynomial curve - call curev(idim,wrk,nmin,cp,np,k,u,m,xx,mxx,ier) -c substract from the old data, the values of the polynomial curve - do 60 i=1,mxx - xx(i) = x(i)-xx(i) - 60 continue -c we partition the working space and determine the spline curve. - 70 jfp = 1 - jz = jfp+nest - ja = jz+ncc - jb = ja+nest*k1 - jg = jb+nest*k2 - jq = jg+nest*k2 - call fpcons(iopt,idim,m,u,mxx,xx,w,ib,ie,k,s,nest,tol,maxit,k1, - * k2,n,t,ncc,c,fp,wrk(jfp),wrk(jz),wrk(ja),wrk(jb),wrk(jg),wrk(jq), - * - * iwrk,ier) -c add the polynomial curve to the calculated spline. - call fpadpo(idim,t,n,c,ncc,k,cp,np,wrk(jz),wrk(ja),wrk(jb)) - 90 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/cualde.f =================================================================== --- branches/Interpolate1D/fitpack/cualde.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/cualde.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,91 +0,0 @@ - subroutine cualde(idim,t,n,c,nc,k1,u,d,nd,ier) -c subroutine cualde evaluates at the point u all the derivatives -c (l) -c d(idim*l+j) = sj (u) ,l=0,1,...,k, j=1,2,...,idim -c of a spline curve s(u) of order k1 (degree k=k1-1) and dimension idim -c given in its b-spline representation. -c -c calling sequence: -c call cualde(idim,t,n,c,nc,k1,u,d,nd,ier) -c -c input parameters: -c idim : integer, giving the dimension of the spline curve. -c t : array,length n, which contains the position of the knots. -c n : integer, giving the total number of knots of s(u). -c c : array,length nc, which contains the b-spline coefficients. -c nc : integer, giving the total number of coefficients of s(u). -c k1 : integer, giving the order of s(u) (order=degree+1). -c u : real, which contains the point where the derivatives must -c be evaluated. -c nd : integer, giving the dimension of the array d. nd >= k1*idim -c -c output parameters: -c d : array,length nd,giving the different curve derivatives. -c d(idim*l+j) will contain the j-th coordinate of the l-th -c derivative of the curve at the point u. -c ier : error flag -c ier = 0 : normal return -c ier =10 : invalid input data (see restrictions) -c -c restrictions: -c nd >= k1*idim -c t(k1) <= u <= t(n-k1+1) -c -c further comments: -c if u coincides with a knot, right derivatives are computed -c ( left derivatives if u = t(n-k1+1) ). -c -c other subroutines required: fpader. -c -c references : -c de boor c : on calculating with b-splines, j. approximation theory -c 6 (1972) 50-62. -c cox m.g. : the numerical evaluation of b-splines, j. inst. maths -c applics 10 (1972) 134-149. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author : -c p.dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c latest update : march 1987 -c -c ..scalar arguments.. - integer idim,n,nc,k1,nd,ier - real*8 u -c ..array arguments.. - real*8 t(n),c(nc),d(nd) -c ..local scalars.. - integer i,j,kk,l,m,nk1 -c ..local array.. - real*8 h(6) -c .. -c before starting computations a data check is made. if the input data -c are invalid control is immediately repassed to the calling program. - ier = 10 - if(nd.lt.(k1*idim)) go to 500 - nk1 = n-k1 - if(u.lt.t(k1) .or. u.gt.t(nk1+1)) go to 500 -c search for knot interval t(l) <= u < t(l+1) - l = k1 - 100 if(u.lt.t(l+1) .or. l.eq.nk1) go to 200 - l = l+1 - go to 100 - 200 if(t(l).ge.t(l+1)) go to 500 - ier = 0 -c calculate the derivatives. - j = 1 - do 400 i=1,idim - call fpader(t,n,c(j),k1,u,l,h) - m = i - do 300 kk=1,k1 - d(m) = h(kk) - m = m+idim - 300 continue - j = j+n - 400 continue - 500 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/curev.f =================================================================== --- branches/Interpolate1D/fitpack/curev.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/curev.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,110 +0,0 @@ - subroutine curev(idim,t,n,c,nc,k,u,m,x,mx,ier) -c subroutine curev evaluates in a number of points u(i),i=1,2,...,m -c a spline curve s(u) of degree k and dimension idim, given in its -c b-spline representation. -c -c calling sequence: -c call curev(idim,t,n,c,nc,k,u,m,x,mx,ier) -c -c input parameters: -c idim : integer, giving the dimension of the spline curve. -c t : array,length n, which contains the position of the knots. -c n : integer, giving the total number of knots of s(u). -c c : array,length nc, which contains the b-spline coefficients. -c nc : integer, giving the total number of coefficients of s(u). -c k : integer, giving the degree of s(u). -c u : array,length m, which contains the points where s(u) must -c be evaluated. -c m : integer, giving the number of points where s(u) must be -c evaluated. -c mx : integer, giving the dimension of the array x. mx >= m*idim -c -c output parameters: -c x : array,length mx,giving the value of s(u) at the different -c points. x(idim*(i-1)+j) will contain the j-th coordinate -c of the i-th point on the curve. -c ier : error flag -c ier = 0 : normal return -c ier =10 : invalid input data (see restrictions) -c -c restrictions: -c m >= 1 -c mx >= m*idim -c t(k+1) <= u(i) <= u(i+1) <= t(n-k) , i=1,2,...,m-1. -c -c other subroutines required: fpbspl. -c -c references : -c de boor c : on calculating with b-splines, j. approximation theory -c 6 (1972) 50-62. -c cox m.g. : the numerical evaluation of b-splines, j. inst. maths -c applics 10 (1972) 134-149. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author : -c p.dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c latest update : march 1987 -c -c ..scalar arguments.. - integer idim,n,nc,k,m,mx,ier -c ..array arguments.. - real*8 t(n),c(nc),u(m),x(mx) -c ..local scalars.. - integer i,j,jj,j1,k1,l,ll,l1,mm,nk1 - real*8 arg,sp,tb,te -c ..local array.. - real*8 h(6) -c .. -c before starting computations a data check is made. if the input data -c are invalid control is immediately repassed to the calling program. - ier = 10 - if (m.lt.1) go to 100 - if (m.eq.1) go to 30 - go to 10 - 10 do 20 i=2,m - if(u(i).lt.u(i-1)) go to 100 - 20 continue - 30 if(mx.lt.(m*idim)) go to 100 - ier = 0 -c fetch tb and te, the boundaries of the approximation interval. - k1 = k+1 - nk1 = n-k1 - tb = t(k1) - te = t(nk1+1) - l = k1 - l1 = l+1 -c main loop for the different points. - mm = 0 - do 80 i=1,m -c fetch a new u-value arg. - arg = u(i) - if(arg.lt.tb) arg = tb - if(arg.gt.te) arg = te -c search for knot interval t(l) <= arg < t(l+1) - 40 if(arg.lt.t(l1) .or. l.eq.nk1) go to 50 - l = l1 - l1 = l+1 - go to 40 -c evaluate the non-zero b-splines at arg. - 50 call fpbspl(t,n,k,arg,l,h) -c find the value of s(u) at u=arg. - ll = l-k1 - do 70 j1=1,idim - jj = ll - sp = 0. - do 60 j=1,k1 - jj = jj+1 - sp = sp+c(jj)*h(j) - 60 continue - mm = mm+1 - x(mm) = sp - ll = ll+n - 70 continue - 80 continue - 100 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/curfit.f =================================================================== --- branches/Interpolate1D/fitpack/curfit.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/curfit.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,261 +0,0 @@ - subroutine curfit(iopt,m,x,y,w,xb,xe,k,s,nest,n,t,c,fp, - * wrk,lwrk,iwrk,ier) -c given the set of data points (x(i),y(i)) and the set of positive -c numbers w(i),i=1,2,...,m,subroutine curfit determines a smooth spline -c approximation of degree k on the interval xb <= x <= xe. -c if iopt=-1 curfit calculates the weighted least-squares spline -c according to a given set of knots. -c if iopt>=0 the number of knots of the spline s(x) and the position -c t(j),j=1,2,...,n is chosen automatically by the routine. the smooth- -c ness of s(x) is then achieved by minimalizing the discontinuity -c jumps of the k-th derivative of s(x) at the knots t(j),j=k+2,k+3,..., -c n-k-1. the amount of smoothness is determined by the condition that -c f(p)=sum((w(i)*(y(i)-s(x(i))))**2) be <= s, with s a given non- -c negative constant, called the smoothing factor. -c the fit s(x) is given in the b-spline representation (b-spline coef- -c ficients c(j),j=1,2,...,n-k-1) and can be evaluated by means of -c subroutine splev. -c -c calling sequence: -c call curfit(iopt,m,x,y,w,xb,xe,k,s,nest,n,t,c,fp,wrk, -c * lwrk,iwrk,ier) -c -c parameters: -c iopt : integer flag. on entry iopt must specify whether a weighted -c least-squares spline (iopt=-1) or a smoothing spline (iopt= -c 0 or 1) must be determined. if iopt=0 the routine will start -c with an initial set of knots t(i)=xb, t(i+k+1)=xe, i=1,2,... -c k+1. if iopt=1 the routine will continue with the knots -c found at the last call of the routine. -c attention: a call with iopt=1 must always be immediately -c preceded by another call with iopt=1 or iopt=0. -c unchanged on exit. -c m : integer. on entry m must specify the number of data points. -c m > k. unchanged on exit. -c x : real array of dimension at least (m). before entry, x(i) -c must be set to the i-th value of the independent variable x, -c for i=1,2,...,m. these values must be supplied in strictly -c ascending order. unchanged on exit. -c y : real array of dimension at least (m). before entry, y(i) -c must be set to the i-th value of the dependent variable y, -c for i=1,2,...,m. unchanged on exit. -c w : real array of dimension at least (m). before entry, w(i) -c must be set to the i-th value in the set of weights. the -c w(i) must be strictly positive. unchanged on exit. -c see also further comments. -c xb,xe : real values. on entry xb and xe must specify the boundaries -c of the approximation interval. xb<=x(1), xe>=x(m). -c unchanged on exit. -c k : integer. on entry k must specify the degree of the spline. -c 1<=k<=5. it is recommended to use cubic splines (k=3). -c the user is strongly dissuaded from choosing k even,together -c with a small s-value. unchanged on exit. -c s : real.on entry (in case iopt>=0) s must specify the smoothing -c factor. s >=0. unchanged on exit. -c for advice on the choice of s see further comments. -c nest : integer. on entry nest must contain an over-estimate of the -c total number of knots of the spline returned, to indicate -c the storage space available to the routine. nest >=2*k+2. -c in most practical situation nest=m/2 will be sufficient. -c always large enough is nest=m+k+1, the number of knots -c needed for interpolation (s=0). unchanged on exit. -c n : integer. -c unless ier =10 (in case iopt >=0), n will contain the -c total number of knots of the spline approximation returned. -c if the computation mode iopt=1 is used this value of n -c should be left unchanged between subsequent calls. -c in case iopt=-1, the value of n must be specified on entry. -c t : real array of dimension at least (nest). -c on succesful exit, this array will contain the knots of the -c spline,i.e. the position of the interior knots t(k+2),t(k+3) -c ...,t(n-k-1) as well as the position of the additional knots -c t(1)=t(2)=...=t(k+1)=xb and t(n-k)=...=t(n)=xe needed for -c the b-spline representation. -c if the computation mode iopt=1 is used, the values of t(1), -c t(2),...,t(n) should be left unchanged between subsequent -c calls. if the computation mode iopt=-1 is used, the values -c t(k+2),...,t(n-k-1) must be supplied by the user, before -c entry. see also the restrictions (ier=10). -c c : real array of dimension at least (nest). -c on succesful exit, this array will contain the coefficients -c c(1),c(2),..,c(n-k-1) in the b-spline representation of s(x) -c fp : real. unless ier=10, fp contains the weighted sum of -c squared residuals of the spline approximation returned. -c wrk : real array of dimension at least (m*(k+1)+nest*(7+3*k)). -c used as working space. if the computation mode iopt=1 is -c used, the values wrk(1),...,wrk(n) should be left unchanged -c between subsequent calls. -c lwrk : integer. on entry,lwrk must specify the actual dimension of -c the array wrk as declared in the calling (sub)program.lwrk -c must not be too small (see wrk). unchanged on exit. -c iwrk : integer array of dimension at least (nest). -c used as working space. if the computation mode iopt=1 is -c used,the values iwrk(1),...,iwrk(n) should be left unchanged -c between subsequent calls. -c ier : integer. unless the routine detects an error, ier contains a -c non-positive value on exit, i.e. -c ier=0 : normal return. the spline returned has a residual sum of -c squares fp such that abs(fp-s)/s <= tol with tol a relat- -c ive tolerance set to 0.001 by the program. -c ier=-1 : normal return. the spline returned is an interpolating -c spline (fp=0). -c ier=-2 : normal return. the spline returned is the weighted least- -c squares polynomial of degree k. in this extreme case fp -c gives the upper bound fp0 for the smoothing factor s. -c ier=1 : error. the required storage space exceeds the available -c storage space, as specified by the parameter nest. -c probably causes : nest too small. if nest is already -c large (say nest > m/2), it may also indicate that s is -c too small -c the approximation returned is the weighted least-squares -c spline according to the knots t(1),t(2),...,t(n). (n=nest) -c the parameter fp gives the corresponding weighted sum of -c squared residuals (fp>s). -c ier=2 : error. a theoretically impossible result was found during -c the iteration proces for finding a smoothing spline with -c fp = s. probably causes : s too small. -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=3 : error. the maximal number of iterations maxit (set to 20 -c by the program) allowed for finding a smoothing spline -c with fp=s has been reached. probably causes : s too small -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=10 : error. on entry, the input data are controlled on validity -c the following restrictions must be satisfied. -c -1<=iopt<=1, 1<=k<=5, m>k, nest>2*k+2, w(i)>0,i=1,2,...,m -c xb<=x(1)=(k+1)*m+nest*(7+3*k) -c if iopt=-1: 2*k+2<=n<=min(nest,m+k+1) -c xb=0: s>=0 -c if s=0 : nest >= m+k+1 -c if one of these conditions is found to be violated,control -c is immediately repassed to the calling program. in that -c case there is no approximation returned. -c -c further comments: -c by means of the parameter s, the user can control the tradeoff -c between closeness of fit and smoothness of fit of the approximation. -c if s is too large, the spline will be too smooth and signal will be -c lost ; if s is too small the spline will pick up too much noise. in -c the extreme cases the program will return an interpolating spline if -c s=0 and the weighted least-squares polynomial of degree k if s is -c very large. between these extremes, a properly chosen s will result -c in a good compromise between closeness of fit and smoothness of fit. -c to decide whether an approximation, corresponding to a certain s is -c satisfactory the user is highly recommended to inspect the fits -c graphically. -c recommended values for s depend on the weights w(i). if these are -c taken as 1/d(i) with d(i) an estimate of the standard deviation of -c y(i), a good s-value should be found in the range (m-sqrt(2*m),m+ -c sqrt(2*m)). if nothing is known about the statistical error in y(i) -c each w(i) can be set equal to one and s determined by trial and -c error, taking account of the comments above. the best is then to -c start with a very large value of s ( to determine the least-squares -c polynomial and the corresponding upper bound fp0 for s) and then to -c progressively decrease the value of s ( say by a factor 10 in the -c beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the -c approximation shows more detail) to obtain closer fits. -c to economize the search for a good s-value the program provides with -c different modes of computation. at the first call of the routine, or -c whenever he wants to restart with the initial set of knots the user -c must set iopt=0. -c if iopt=1 the program will continue with the set of knots found at -c the last call of the routine. this will save a lot of computation -c time if curfit is called repeatedly for different values of s. -c the number of knots of the spline returned and their location will -c depend on the value of s and on the complexity of the shape of the -c function underlying the data. but, if the computation mode iopt=1 -c is used, the knots returned may also depend on the s-values at -c previous calls (if these were smaller). therefore, if after a number -c of trials with different s-values and iopt=1, the user can finally -c accept a fit as satisfactory, it may be worthwhile for him to call -c curfit once more with the selected value for s but now with iopt=0. -c indeed, curfit may then return an approximation of the same quality -c of fit but with fewer knots and therefore better if data reduction -c is also an important objective for the user. -c -c other subroutines required: -c fpback,fpbspl,fpchec,fpcurf,fpdisc,fpgivs,fpknot,fprati,fprota -c -c references: -c dierckx p. : an algorithm for smoothing, differentiation and integ- -c ration of experimental data using spline functions, -c j.comp.appl.maths 1 (1975) 165-184. -c dierckx p. : a fast algorithm for smoothing data on a rectangular -c grid while using spline functions, siam j.numer.anal. -c 19 (1982) 1286-1304. -c dierckx p. : an improved algorithm for curve fitting with spline -c functions, report tw54, dept. computer science,k.u. -c leuven, 1981. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author: -c p.dierckx -c dept. computer science, k.u. leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c creation date : may 1979 -c latest update : march 1987 -c -c .. -c ..scalar arguments.. - real*8 xb,xe,s,fp - integer iopt,m,k,nest,n,lwrk,ier -c ..array arguments.. - real*8 x(m),y(m),w(m),t(nest),c(nest),wrk(lwrk) - integer iwrk(nest) -c ..local scalars.. - real*8 tol - integer i,ia,ib,ifp,ig,iq,iz,j,k1,k2,lwest,maxit,nmin -c .. -c we set up the parameters tol and maxit - maxit = 20 - tol = 0.1d-02 -c before starting computations a data check is made. if the input data -c are invalid, control is immediately repassed to the calling program. - ier = 10 - if(k.le.0 .or. k.gt.5) go to 50 - k1 = k+1 - k2 = k1+1 - if(iopt.lt.(-1) .or. iopt.gt.1) go to 50 - nmin = 2*k1 - if(m.lt.k1 .or. nest.lt.nmin) go to 50 - lwest = m*k1+nest*(7+3*k) - if(lwrk.lt.lwest) go to 50 - if(xb.gt.x(1) .or. xe.lt.x(m) .or. w(1).le.0.) go to 50 - do 10 i=2,m - if(x(i-1).ge.x(i) .or. w(i).le.0.) go to 50 - 10 continue - if(iopt.ge.0) go to 30 - if(n.lt.nmin .or. n.gt.nest) go to 50 - j = n - do 20 i=1,k1 - t(i) = xb - t(j) = xe - j = j-1 - 20 continue - call fpchec(x,m,t,n,k,ier) - if (ier.eq.0) go to 40 - go to 50 - 30 if(s.lt.0.) go to 50 - if(s.eq.0. .and. nest.lt.(m+k1)) go to 50 - ier = 0 -c we partition the working space and determine the spline approximation. - 40 ifp = 1 - iz = ifp+nest - ia = iz+nest - ib = ia+nest*k1 - ig = ib+nest*k2 - iq = ig+nest*k2 - call fpcurf(iopt,x,y,w,m,xb,xe,k,s,nest,tol,maxit,k1,k2,n,t,c,fp, - * wrk(ifp),wrk(iz),wrk(ia),wrk(ib),wrk(ig),wrk(iq),iwrk,ier) - 50 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/dblint.f =================================================================== --- branches/Interpolate1D/fitpack/dblint.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/dblint.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,88 +0,0 @@ - real*8 function dblint(tx,nx,ty,ny,c,kx,ky,xb,xe,yb,ye,wrk) -c function dblint calculates the double integral -c / xe / ye -c | | s(x,y) dx dy -c xb / yb / -c with s(x,y) a bivariate spline of degrees kx and ky, given in the -c b-spline representation. -c -c calling sequence: -c aint = dblint(tx,nx,ty,ny,c,kx,ky,xb,xe,yb,ye,wrk) -c -c input parameters: -c tx : real array, length nx, which contains the position of the -c knots in the x-direction. -c nx : integer, giving the total number of knots in the x-direction -c ty : real array, length ny, which contains the position of the -c knots in the y-direction. -c ny : integer, giving the total number of knots in the y-direction -c c : real array, length (nx-kx-1)*(ny-ky-1), which contains the -c b-spline coefficients. -c kx,ky : integer values, giving the degrees of the spline. -c xb,xe : real values, containing the boundaries of the integration -c yb,ye domain. s(x,y) is considered to be identically zero out- -c side the rectangle (tx(kx+1),tx(nx-kx))*(ty(ky+1),ty(ny-ky)) -c -c output parameters: -c aint : real , containing the double integral of s(x,y). -c wrk : real array of dimension at least (nx+ny-kx-ky-2). -c used as working space. -c on exit, wrk(i) will contain the integral -c / xe -c | ni,kx+1(x) dx , i=1,2,...,nx-kx-1 -c xb / -c with ni,kx+1(x) the normalized b-spline defined on -c the knots tx(i),...,tx(i+kx+1) -c wrk(j+nx-kx-1) will contain the integral -c / ye -c | nj,ky+1(y) dy , j=1,2,...,ny-ky-1 -c yb / -c with nj,ky+1(y) the normalized b-spline defined on -c the knots ty(j),...,ty(j+ky+1) -c -c other subroutines required: fpintb -c -c references : -c gaffney p.w. : the calculation of indefinite integrals of b-splines -c j. inst. maths applics 17 (1976) 37-41. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author : -c p.dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c latest update : march 1989 -c -c ..scalar arguments.. - integer nx,ny,kx,ky - real*8 xb,xe,yb,ye -c ..array arguments.. - real*8 tx(nx),ty(ny),c((nx-kx-1)*(ny-ky-1)),wrk(nx+ny-kx-ky-2) -c ..local scalars.. - integer i,j,l,m,nkx1,nky1 - real*8 res -c .. - nkx1 = nx-kx-1 - nky1 = ny-ky-1 -c we calculate the integrals of the normalized b-splines ni,kx+1(x) - call fpintb(tx,nx,wrk,nkx1,xb,xe) -c we calculate the integrals of the normalized b-splines nj,ky+1(y) - call fpintb(ty,ny,wrk(nkx1+1),nky1,yb,ye) -c calculate the integral of s(x,y) - dblint = 0. - do 200 i=1,nkx1 - res = wrk(i) - if(res.eq.0.) go to 200 - m = (i-1)*nky1 - l = nkx1 - do 100 j=1,nky1 - m = m+1 - l = l+1 - dblint = dblint+res*wrk(l)*c(m) - 100 continue - 200 continue - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/evapol.f =================================================================== --- branches/Interpolate1D/fitpack/evapol.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/evapol.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,82 +0,0 @@ - real*8 function evapol(tu,nu,tv,nv,c,rad,x,y) -c function program evacir evaluates the function f(x,y) = s(u,v), -c defined through the transformation -c x = u*rad(v)*cos(v) y = u*rad(v)*sin(v) -c and where s(u,v) is a bicubic spline ( 0<=u<=1 , -pi<=v<=pi ), given -c in its standard b-spline representation. -c -c calling sequence: -c f = evapol(tu,nu,tv,nv,c,rad,x,y) -c -c input parameters: -c tu : real array, length nu, which contains the position of the -c knots in the u-direction. -c nu : integer, giving the total number of knots in the u-direction -c tv : real array, length nv, which contains the position of the -c knots in the v-direction. -c nv : integer, giving the total number of knots in the v-direction -c c : real array, length (nu-4)*(nv-4), which contains the -c b-spline coefficients. -c rad : real function subprogram, defining the boundary of the -c approximation domain. must be declared external in the -c calling (sub)-program -c x,y : real values. -c before entry x and y must be set to the co-ordinates of -c the point where f(x,y) must be evaluated. -c -c output parameter: -c f : real -c on exit f contains the value of f(x,y) -c -c other subroutines required: -c bispev,fpbisp,fpbspl -c -c references : -c de boor c : on calculating with b-splines, j. approximation theory -c 6 (1972) 50-62. -c cox m.g. : the numerical evaluation of b-splines, j. inst. maths -c applics 10 (1972) 134-149. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author : -c p.dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c latest update : march 1989 -c -c ..scalar arguments.. - integer nu,nv - real*8 x,y -c ..array arguments.. - real*8 tu(nu),tv(nv),c((nu-4)*(nv-4)) -c ..user specified function - real*8 rad -c ..local scalars.. - integer ier - real*8 u,v,r,f,one,dist -c ..local arrays - real*8 wrk(8) - integer iwrk(2) -c ..function references - real*8 atan2,sqrt -c .. -c calculate the (u,v)-coordinates of the given point. - one = 1 - u = 0. - v = 0. - dist = x**2+y**2 - if(dist.le.0.) go to 10 - v = atan2(y,x) - r = rad(v) - if(r.le.0.) go to 10 - u = sqrt(dist)/r - if(u.gt.one) u = one -c evaluate s(u,v) - 10 call bispev(tu,nu,tv,nv,c,3,3,u,1,v,1,f,wrk,8,iwrk,2,ier) - evapol = f - return - end - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fourco.f =================================================================== --- branches/Interpolate1D/fitpack/fourco.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fourco.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,96 +0,0 @@ - subroutine fourco(t,n,c,alfa,m,ress,resc,wrk1,wrk2,ier) -c subroutine fourco calculates the integrals -c /t(n-3) -c ress(i) = ! s(x)*sin(alfa(i)*x) dx and -c t(4)/ -c /t(n-3) -c resc(i) = ! s(x)*cos(alfa(i)*x) dx, i=1,...,m, -c t(4)/ -c where s(x) denotes a cubic spline which is given in its -c b-spline representation. -c -c calling sequence: -c call fourco(t,n,c,alfa,m,ress,resc,wrk1,wrk2,ier) -c -c input parameters: -c t : real array,length n, containing the knots of s(x). -c n : integer, containing the total number of knots. n>=10. -c c : real array,length n, containing the b-spline coefficients. -c alfa : real array,length m, containing the parameters alfa(i). -c m : integer, specifying the number of integrals to be computed. -c wrk1 : real array,length n. used as working space -c wrk2 : real array,length n. used as working space -c -c output parameters: -c ress : real array,length m, containing the integrals ress(i). -c resc : real array,length m, containing the integrals resc(i). -c ier : error flag: -c ier=0 : normal return. -c ier=10: invalid input data (see restrictions). -c -c restrictions: -c n >= 10 -c t(4) < t(5) < ... < t(n-4) < t(n-3). -c t(1) <= t(2) <= t(3) <= t(4). -c t(n-3) <= t(n-2) <= t(n-1) <= t(n). -c -c other subroutines required: fpbfou,fpcsin -c -c references : -c dierckx p. : calculation of fouriercoefficients of discrete -c functions using cubic splines. j. computational -c and applied mathematics 3 (1977) 207-209. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author : -c p.dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c latest update : march 1987 -c -c ..scalar arguments.. - integer n,m,ier -c ..array arguments.. - real*8 t(n),c(n),wrk1(n),wrk2(n),alfa(m),ress(m),resc(m) -c ..local scalars.. - integer i,j,n4 - real*8 rs,rc -c .. - n4 = n-4 -c before starting computations a data check is made. in the input data -c are invalid, control is immediately repassed to the calling program. - ier = 10 - if(n.lt.10) go to 50 - j = n - do 10 i=1,3 - if(t(i).gt.t(i+1)) go to 50 - if(t(j).lt.t(j-1)) go to 50 - j = j-1 - 10 continue - do 20 i=4,n4 - if(t(i).ge.t(i+1)) go to 50 - 20 continue - ier = 0 -c main loop for the different alfa(i). - do 40 i=1,m -c calculate the integrals -c wrk1(j) = integral(nj,4(x)*sin(alfa*x)) and -c wrk2(j) = integral(nj,4(x)*cos(alfa*x)), j=1,2,...,n-4, -c where nj,4(x) denotes the normalised cubic b-spline defined on the -c knots t(j),t(j+1),...,t(j+4). - call fpbfou(t,n,alfa(i),wrk1,wrk2) -c calculate the integrals ress(i) and resc(i). - rs = 0. - rc = 0. - do 30 j=1,n4 - rs = rs+c(j)*wrk1(j) - rc = rc+c(j)*wrk2(j) - 30 continue - ress(i) = rs - resc(i) = rc - 40 continue - 50 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpader.f =================================================================== --- branches/Interpolate1D/fitpack/fpader.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpader.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,57 +0,0 @@ - subroutine fpader(t,n,c,k1,x,l,d) -c subroutine fpader calculates the derivatives -c (j-1) -c d(j) = s (x) , j=1,2,...,k1 -c of a spline of order k1 at the point t(l)<=x= 10, t(4) < t(5) < ... < t(n-4) < t(n-3). -c .. -c ..scalar arguments.. - integer n - real*8 par -c ..array arguments.. - real*8 t(n),ress(n),resc(n) -c ..local scalars.. - integer i,ic,ipj,is,j,jj,jp1,jp4,k,li,lj,ll,nmj,nm3,nm7 - real*8 ak,beta,con1,con2,c1,c2,delta,eps,fac,f1,f2,f3,one,quart, - * sign,six,s1,s2,term -c ..local arrays.. - real*8 co(5),si(5),hs(5),hc(5),rs(3),rc(3) -c ..function references.. - real*8 cos,sin,abs -c .. -c initialization. - one = 0.1e+01 - six = 0.6e+01 - eps = 0.1e-07 - quart = 0.25e0 - con1 = 0.5e-01 - con2 = 0.12e+03 - nm3 = n-3 - nm7 = n-7 - if(par.ne.0.) term = six/par - beta = par*t(4) - co(1) = cos(beta) - si(1) = sin(beta) -c calculate the integrals ress(j) and resc(j), j=1,2,3 by setting up -c a divided difference table. - do 30 j=1,3 - jp1 = j+1 - jp4 = j+4 - beta = par*t(jp4) - co(jp1) = cos(beta) - si(jp1) = sin(beta) - call fpcsin(t(4),t(jp4),par,si(1),co(1),si(jp1),co(jp1), - * rs(j),rc(j)) - i = 5-j - hs(i) = 0. - hc(i) = 0. - do 10 jj=1,j - ipj = i+jj - hs(ipj) = rs(jj) - hc(ipj) = rc(jj) - 10 continue - do 20 jj=1,3 - if(i.lt.jj) i = jj - k = 5 - li = jp4 - do 20 ll=i,4 - lj = li-jj - fac = t(li)-t(lj) - hs(k) = (hs(k)-hs(k-1))/fac - hc(k) = (hc(k)-hc(k-1))/fac - k = k-1 - li = li-1 - 20 continue - ress(j) = hs(5)-hs(4) - resc(j) = hc(5)-hc(4) - 30 continue - if(nm7.lt.4) go to 160 -c calculate the integrals ress(j) and resc(j),j=4,5,...,n-7. - do 150 j=4,nm7 - jp4 = j+4 - beta = par*t(jp4) - co(5) = cos(beta) - si(5) = sin(beta) - delta = t(jp4)-t(j) -c the way of computing ress(j) and resc(j) depends on the value of -c beta = par*(t(j+4)-t(j)). - beta = delta*par - if(abs(beta).le.one) go to 60 -c if !beta! > 1 the integrals are calculated by setting up a divided -c difference table. - do 40 k=1,5 - hs(k) = si(k) - hc(k) = co(k) - 40 continue - do 50 jj=1,3 - k = 5 - li = jp4 - do 50 ll=jj,4 - lj = li-jj - fac = par*(t(li)-t(lj)) - hs(k) = (hs(k)-hs(k-1))/fac - hc(k) = (hc(k)-hc(k-1))/fac - k = k-1 - li = li-1 - 50 continue - s2 = (hs(5)-hs(4))*term - c2 = (hc(5)-hc(4))*term - go to 130 -c if !beta! <= 1 the integrals are calculated by evaluating a series -c expansion. - 60 f3 = 0. - do 70 i=1,4 - ipj = i+j - hs(i) = par*(t(ipj)-t(j)) - hc(i) = hs(i) - f3 = f3+hs(i) - 70 continue - f3 = f3*con1 - c1 = quart - s1 = f3 - if(abs(f3).le.eps) go to 120 - sign = one - fac = con2 - k = 5 - is = 0 - do 110 ic=1,20 - k = k+1 - ak = k - fac = fac*ak - f1 = 0. - f3 = 0. - do 80 i=1,4 - f1 = f1+hc(i) - f2 = f1*hs(i) - hc(i) = f2 - f3 = f3+f2 - 80 continue - f3 = f3*six/fac - if(is.eq.0) go to 90 - is = 0 - s1 = s1+f3*sign - go to 100 - 90 sign = -sign - is = 1 - c1 = c1+f3*sign - 100 if(abs(f3).le.eps) go to 120 - 110 continue - 120 s2 = delta*(co(1)*s1+si(1)*c1) - c2 = delta*(co(1)*c1-si(1)*s1) - 130 ress(j) = s2 - resc(j) = c2 - do 140 i=1,4 - co(i) = co(i+1) - si(i) = si(i+1) - 140 continue - 150 continue -c calculate the integrals ress(j) and resc(j),j=n-6,n-5,n-4 by setting -c up a divided difference table. - 160 do 190 j=1,3 - nmj = nm3-j - i = 5-j - call fpcsin(t(nm3),t(nmj),par,si(4),co(4),si(i-1),co(i-1), - * rs(j),rc(j)) - hs(i) = 0. - hc(i) = 0. - do 170 jj=1,j - ipj = i+jj - hc(ipj) = rc(jj) - hs(ipj) = rs(jj) - 170 continue - do 180 jj=1,3 - if(i.lt.jj) i = jj - k = 5 - li = nmj - do 180 ll=i,4 - lj = li+jj - fac = t(lj)-t(li) - hs(k) = (hs(k-1)-hs(k))/fac - hc(k) = (hc(k-1)-hc(k))/fac - k = k-1 - li = li+1 - 180 continue - ress(nmj) = hs(4)-hs(5) - resc(nmj) = hc(4)-hc(5) - 190 continue - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpbisp.f =================================================================== --- branches/Interpolate1D/fitpack/fpbisp.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpbisp.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,79 +0,0 @@ - subroutine fpbisp(tx,nx,ty,ny,c,kx,ky,x,mx,y,my,z,wx,wy,lx,ly) -c ..scalar arguments.. - integer nx,ny,kx,ky,mx,my -c ..array arguments.. - integer lx(mx),ly(my) - real*8 tx(nx),ty(ny),c((nx-kx-1)*(ny-ky-1)),x(mx),y(my),z(mx*my), - * wx(mx,kx+1),wy(my,ky+1) -c ..local scalars.. - integer kx1,ky1,l,l1,l2,m,nkx1,nky1 - real*8 arg,sp,tb,te -c ..local arrays.. - real*8 h(6) -c ..subroutine references.. -c fpbspl -c .. - kx1 = kx+1 - nkx1 = nx-kx1 - tb = tx(kx1) - te = tx(nkx1+1) - l = kx1 - l1 = l+1 - do 40 i=1,mx - arg = x(i) - if(arg.lt.tb) arg = tb - if(arg.gt.te) arg = te - 10 if(arg.lt.tx(l1) .or. l.eq.nkx1) go to 20 - l = l1 - l1 = l+1 - go to 10 - 20 call fpbspl(tx,nx,kx,arg,l,h) - lx(i) = l-kx1 - do 30 j=1,kx1 - wx(i,j) = h(j) - 30 continue - 40 continue - ky1 = ky+1 - nky1 = ny-ky1 - tb = ty(ky1) - te = ty(nky1+1) - l = ky1 - l1 = l+1 - do 80 i=1,my - arg = y(i) - if(arg.lt.tb) arg = tb - if(arg.gt.te) arg = te - 50 if(arg.lt.ty(l1) .or. l.eq.nky1) go to 60 - l = l1 - l1 = l+1 - go to 50 - 60 call fpbspl(ty,ny,ky,arg,l,h) - ly(i) = l-ky1 - do 70 j=1,ky1 - wy(i,j) = h(j) - 70 continue - 80 continue - m = 0 - do 130 i=1,mx - l = lx(i)*nky1 - do 90 i1=1,kx1 - h(i1) = wx(i,i1) - 90 continue - do 120 j=1,my - l1 = l+ly(j) - sp = 0. - do 110 i1=1,kx1 - l2 = l1 - do 100 j1=1,ky1 - l2 = l2+1 - sp = sp+c(l2)*h(i1)*wy(j,j1) - 100 continue - l1 = l1+nky1 - 110 continue - m = m+1 - z(m) = sp - 120 continue - 130 continue - return - end - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpbspl.f =================================================================== --- branches/Interpolate1D/fitpack/fpbspl.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpbspl.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,42 +0,0 @@ - subroutine fpbspl(t,n,k,x,l,h) -c subroutine fpbspl evaluates the (k+1) non-zero b-splines of -c degree k at t(l) <= x < t(l+1) using the stable recurrence -c relation of de boor and cox. -c Travis Oliphant 2007 -c changed so that weighting of 0 is used when knots with -c multiplicity are present. -c Also, notice that l+k <= n and 1 <= l+1-k -c or else the routine will be accessing memory outside t -c Thus it is imperative that that k <= l <= n-k but this -c is not checked. -c .. -c ..scalar arguments.. - real*8 x - integer n,k,l -c ..array arguments.. - real*8 t(n),h(20) -c ..local scalars.. - real*8 f,one - integer i,j,li,lj -c ..local arrays.. - real*8 hh(19) -c .. - one = 0.1d+01 - h(1) = one - do 20 j=1,k - do 10 i=1,j - hh(i) = h(i) - 10 continue - h(1) = 0.0d0 - do 20 i=1,j - li = l+i - lj = li-j - if (t(li).ne.t(lj)) goto 15 - h(i+1) = 0.0d0 - goto 20 - 15 f = hh(i)/(t(li)-t(lj)) - h(i) = h(i)+f*(t(li)-x) - h(i+1) = f*(x-t(lj)) - 20 continue - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpchec.f =================================================================== --- branches/Interpolate1D/fitpack/fpchec.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpchec.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,62 +0,0 @@ - subroutine fpchec(x,m,t,n,k,ier) -c subroutine fpchec verifies the number and the position of the knots -c t(j),j=1,2,...,n of a spline of degree k, in relation to the number -c and the position of the data points x(i),i=1,2,...,m. if all of the -c following conditions are fulfilled, the error parameter ier is set -c to zero. if one of the conditions is violated ier is set to ten. -c 1) k+1 <= n-k-1 <= m -c 2) t(1) <= t(2) <= ... <= t(k+1) -c t(n-k) <= t(n-k+1) <= ... <= t(n) -c 3) t(k+1) < t(k+2) < ... < t(n-k) -c 4) t(k+1) <= x(i) <= t(n-k) -c 5) the conditions specified by schoenberg and whitney must hold -c for at least one subset of data points, i.e. there must be a -c subset of data points y(j) such that -c t(j) < y(j) < t(j+k+1), j=1,2,...,n-k-1 -c .. -c ..scalar arguments.. - integer m,n,k,ier -c ..array arguments.. - real*8 x(m),t(n) -c ..local scalars.. - integer i,j,k1,k2,l,nk1,nk2,nk3 - real*8 tj,tl -c .. - k1 = k+1 - k2 = k1+1 - nk1 = n-k1 - nk2 = nk1+1 - ier = 10 -c check condition no 1 - if(nk1.lt.k1 .or. nk1.gt.m) go to 80 -c check condition no 2 - j = n - do 20 i=1,k - if(t(i).gt.t(i+1)) go to 80 - if(t(j).lt.t(j-1)) go to 80 - j = j-1 - 20 continue -c check condition no 3 - do 30 i=k2,nk2 - if(t(i).le.t(i-1)) go to 80 - 30 continue -c check condition no 4 - if(x(1).lt.t(k1) .or. x(m).gt.t(nk2)) go to 80 -c check condition no 5 - if(x(1).ge.t(k2) .or. x(m).le.t(nk1)) go to 80 - i = 1 - l = k2 - nk3 = nk1-1 - if(nk3.lt.2) go to 70 - do 60 j=2,nk3 - tj = t(j) - l = l+1 - tl = t(l) - 40 i = i+1 - if(i.ge.m) go to 80 - if(x(i).le.tj) go to 40 - if(x(i).ge.tl) go to 80 - 60 continue - 70 ier = 0 - 80 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpched.f =================================================================== --- branches/Interpolate1D/fitpack/fpched.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpched.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,69 +0,0 @@ - subroutine fpched(x,m,t,n,k,ib,ie,ier) -c subroutine fpched verifies the number and the position of the knots -c t(j),j=1,2,...,n of a spline of degree k,with ib derative constraints -c at x(1) and ie constraints at x(m), in relation to the number and -c the position of the data points x(i),i=1,2,...,m. if all of the -c following conditions are fulfilled, the error parameter ier is set -c to zero. if one of the conditions is violated ier is set to ten. -c 1) k+1 <= n-k-1 <= m + max(0,ib-1) + max(0,ie-1) -c 2) t(1) <= t(2) <= ... <= t(k+1) -c t(n-k) <= t(n-k+1) <= ... <= t(n) -c 3) t(k+1) < t(k+2) < ... < t(n-k) -c 4) t(k+1) <= x(i) <= t(n-k) -c 5) the conditions specified by schoenberg and whitney must hold -c for at least one subset of data points, i.e. there must be a -c subset of data points y(j) such that -c t(j) < y(j) < t(j+k+1), j=1+ib1,2+ib1,...,n-k-1-ie1 -c with ib1 = max(0,ib-1), ie1 = max(0,ie-1) -c .. -c ..scalar arguments.. - integer m,n,k,ib,ie,ier -c ..array arguments.. - real*8 x(m),t(n) -c ..local scalars.. - integer i,ib1,ie1,j,jj,k1,k2,l,nk1,nk2,nk3 - real*8 tj,tl -c .. - k1 = k+1 - k2 = k1+1 - nk1 = n-k1 - nk2 = nk1+1 - ib1 = ib-1 - if(ib1.lt.0) ib1 = 0 - ie1 = ie-1 - if(ie1.lt.0) ie1 = 0 - ier = 10 -c check condition no 1 - if(nk1.lt.k1 .or. nk1.gt.(m+ib1+ie1)) go to 80 -c check condition no 2 - j = n - do 20 i=1,k - if(t(i).gt.t(i+1)) go to 80 - if(t(j).lt.t(j-1)) go to 80 - j = j-1 - 20 continue -c check condition no 3 - do 30 i=k2,nk2 - if(t(i).le.t(i-1)) go to 80 - 30 continue -c check condition no 4 - if(x(1).lt.t(k1) .or. x(m).gt.t(nk2)) go to 80 -c check condition no 5 - if(x(1).ge.t(k2) .or. x(m).le.t(nk1)) go to 80 - i = 1 - jj = 2+ib1 - l = jj+k - nk3 = nk1-1-ie1 - if(nk3.lt.jj) go to 70 - do 60 j=jj,nk3 - tj = t(j) - l = l+1 - tl = t(l) - 40 i = i+1 - if(i.ge.m) go to 80 - if(x(i).le.tj) go to 40 - if(x(i).ge.tl) go to 80 - 60 continue - 70 ier = 0 - 80 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpchep.f =================================================================== --- branches/Interpolate1D/fitpack/fpchep.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpchep.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,81 +0,0 @@ - subroutine fpchep(x,m,t,n,k,ier) -c subroutine fpchep verifies the number and the position of the knots -c t(j),j=1,2,...,n of a periodic spline of degree k, in relation to -c the number and the position of the data points x(i),i=1,2,...,m. -c if all of the following conditions are fulfilled, ier is set -c to zero. if one of the conditions is violated ier is set to ten. -c 1) k+1 <= n-k-1 <= m+k-1 -c 2) t(1) <= t(2) <= ... <= t(k+1) -c t(n-k) <= t(n-k+1) <= ... <= t(n) -c 3) t(k+1) < t(k+2) < ... < t(n-k) -c 4) t(k+1) <= x(i) <= t(n-k) -c 5) the conditions specified by schoenberg and whitney must hold -c for at least one subset of data points, i.e. there must be a -c subset of data points y(j) such that -c t(j) < y(j) < t(j+k+1), j=k+1,...,n-k-1 -c .. -c ..scalar arguments.. - integer m,n,k,ier -c ..array arguments.. - real*8 x(m),t(n) -c ..local scalars.. - integer i,i1,i2,j,j1,k1,k2,l,l1,l2,mm,m1,nk1,nk2 - real*8 per,tj,tl,xi -c .. - k1 = k+1 - k2 = k1+1 - nk1 = n-k1 - nk2 = nk1+1 - m1 = m-1 - ier = 10 -c check condition no 1 - if(nk1.lt.k1 .or. n.gt.m+2*k) go to 130 -c check condition no 2 - j = n - do 20 i=1,k - if(t(i).gt.t(i+1)) go to 130 - if(t(j).lt.t(j-1)) go to 130 - j = j-1 - 20 continue -c check condition no 3 - do 30 i=k2,nk2 - if(t(i).le.t(i-1)) go to 130 - 30 continue -c check condition no 4 - if(x(1).lt.t(k1) .or. x(m).gt.t(nk2)) go to 130 -c check condition no 5 - l1 = k1 - l2 = 1 - do 50 l=1,m - xi = x(l) - 40 if(xi.lt.t(l1+1) .or. l.eq.nk1) go to 50 - l1 = l1+1 - l2 = l2+1 - if(l2.gt.k1) go to 60 - go to 40 - 50 continue - l = m - 60 per = t(nk2)-t(k1) - do 120 i1=2,l - i = i1-1 - mm = i+m1 - do 110 j=k1,nk1 - tj = t(j) - j1 = j+k1 - tl = t(j1) - 70 i = i+1 - if(i.gt.mm) go to 120 - i2 = i-m1 - if (i2.le.0) go to 80 - go to 90 - 80 xi = x(i) - go to 100 - 90 xi = x(i2)+per - 100 if(xi.le.tj) go to 70 - if(xi.ge.tl) go to 120 - 110 continue - ier = 0 - go to 130 - 120 continue - 130 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpclos.f =================================================================== --- branches/Interpolate1D/fitpack/fpclos.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpclos.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,714 +0,0 @@ - subroutine fpclos(iopt,idim,m,u,mx,x,w,k,s,nest,tol,maxit,k1,k2, - * n,t,nc,c,fp,fpint,z,a1,a2,b,g1,g2,q,nrdata,ier) -c .. -c ..scalar arguments.. - real*8 s,tol,fp - integer iopt,idim,m,mx,k,nest,maxit,k1,k2,n,nc,ier -c ..array arguments.. - real*8 u(m),x(mx),w(m),t(nest),c(nc),fpint(nest),z(nc),a1(nest,k1) - *, - * a2(nest,k),b(nest,k2),g1(nest,k2),g2(nest,k1),q(m,k1) - integer nrdata(nest) -c ..local scalars.. - real*8 acc,cos,d1,fac,fpart,fpms,fpold,fp0,f1,f2,f3,p,per,pinv,piv - *, - * p1,p2,p3,sin,store,term,ui,wi,rn,one,con1,con4,con9,half - integer i,ich1,ich3,ij,ik,it,iter,i1,i2,i3,j,jj,jk,jper,j1,j2,kk, - * kk1,k3,l,l0,l1,l5,mm,m1,new,nk1,nk2,nmax,nmin,nplus,npl1, - * nrint,n10,n11,n7,n8 -c ..local arrays.. - real*8 h(6),h1(7),h2(6),xi(10) -c ..function references.. - real*8 abs,fprati - integer max0,min0 -c ..subroutine references.. -c fpbacp,fpbspl,fpgivs,fpdisc,fpknot,fprota -c .. -c set constants - one = 0.1e+01 - con1 = 0.1e0 - con9 = 0.9e0 - con4 = 0.4e-01 - half = 0.5e0 -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 1: determination of the number of knots and their position c -c ************************************************************** c -c given a set of knots we compute the least-squares closed curve c -c sinf(u). if the sum f(p=inf) <= s we accept the choice of knots. c -c if iopt=-1 sinf(u) is the requested curve c -c if iopt=0 or iopt=1 we check whether we can accept the knots: c -c if fp <=s we will continue with the current set of knots. c -c if fp > s we will increase the number of knots and compute the c -c corresponding least-squares curve until finally fp<=s. c -c the initial choice of knots depends on the value of s and iopt. c -c if s=0 we have spline interpolation; in that case the number of c -c knots equals nmax = m+2*k. c -c if s > 0 and c -c iopt=0 we first compute the least-squares polynomial curve of c -c degree k; n = nmin = 2*k+2. since s(u) must be periodic we c -c find that s(u) reduces to a fixed point. c -c iopt=1 we start with the set of knots found at the last c -c call of the routine, except for the case that s > fp0; then c -c we compute directly the least-squares polynomial curve. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - m1 = m-1 - kk = k - kk1 = k1 - k3 = 3*k+1 - nmin = 2*k1 -c determine the length of the period of the splines. - per = u(m)-u(1) - if(iopt.lt.0) go to 50 -c calculation of acc, the absolute tolerance for the root of f(p)=s. - acc = tol*s -c determine nmax, the number of knots for periodic spline interpolation - nmax = m+2*k - if(s.gt.0. .or. nmax.eq.nmin) go to 30 -c if s=0, s(u) is an interpolating curve. - n = nmax -c test whether the required storage space exceeds the available one. - if(n.gt.nest) go to 620 -c find the position of the interior knots in case of interpolation. - 5 if((k/2)*2 .eq.k) go to 20 - do 10 i=2,m1 - j = i+k - t(j) = u(i) - 10 continue - if(s.gt.0.) go to 50 - kk = k-1 - kk1 = k - if(kk.gt.0) go to 50 - t(1) = t(m)-per - t(2) = u(1) - t(m+1) = u(m) - t(m+2) = t(3)+per - jj = 0 - do 15 i=1,m1 - j = i - do 12 j1=1,idim - jj = jj+1 - c(j) = x(jj) - j = j+n - 12 continue - 15 continue - jj = 1 - j = m - do 17 j1=1,idim - c(j) = c(jj) - j = j+n - jj = jj+n - 17 continue - fp = 0. - fpint(n) = fp0 - fpint(n-1) = 0. - nrdata(n) = 0 - go to 630 - 20 do 25 i=2,m1 - j = i+k - t(j) = (u(i)+u(i-1))*half - 25 continue - go to 50 -c if s > 0 our initial choice depends on the value of iopt. -c if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares -c polynomial curve. (i.e. a constant point). -c if iopt=1 and fp0>s we start computing the least-squares closed -c curve according the set of knots found at the last call of the -c routine. - 30 if(iopt.eq.0) go to 35 - if(n.eq.nmin) go to 35 - fp0 = fpint(n) - fpold = fpint(n-1) - nplus = nrdata(n) - if(fp0.gt.s) go to 50 -c the case that s(u) is a fixed point is treated separetely. -c fp0 denotes the corresponding sum of squared residuals. - 35 fp0 = 0. - d1 = 0. - do 37 j=1,idim - z(j) = 0. - 37 continue - jj = 0 - do 45 it=1,m1 - wi = w(it) - call fpgivs(wi,d1,cos,sin) - do 40 j=1,idim - jj = jj+1 - fac = wi*x(jj) - call fprota(cos,sin,fac,z(j)) - fp0 = fp0+fac**2 - 40 continue - 45 continue - do 47 j=1,idim - z(j) = z(j)/d1 - 47 continue -c test whether that fixed point is a solution of our problem. - fpms = fp0-s - if(fpms.lt.acc .or. nmax.eq.nmin) go to 640 - fpold = fp0 -c test whether the required storage space exceeds the available one. - if(n.ge.nest) go to 620 -c start computing the least-squares closed curve with one -c interior knot. - nplus = 1 - n = nmin+1 - mm = (m+1)/2 - t(k2) = u(mm) - nrdata(1) = mm-2 - nrdata(2) = m1-mm -c main loop for the different sets of knots. m is a save upper -c bound for the number of trials. - 50 do 340 iter=1,m -c find nrint, the number of knot intervals. - nrint = n-nmin+1 -c find the position of the additional knots which are needed for -c the b-spline representation of s(u). if we take -c t(k+1) = u(1), t(n-k) = u(m) -c t(k+1-j) = t(n-k-j) - per, j=1,2,...k -c t(n-k+j) = t(k+1+j) + per, j=1,2,...k -c then s(u) will be a smooth closed curve if the b-spline -c coefficients satisfy the following conditions -c c((i-1)*n+n7+j) = c((i-1)*n+j), j=1,...k,i=1,2,...,idim (**) -c with n7=n-2*k-1. - t(k1) = u(1) - nk1 = n-k1 - nk2 = nk1+1 - t(nk2) = u(m) - do 60 j=1,k - i1 = nk2+j - i2 = nk2-j - j1 = k1+j - j2 = k1-j - t(i1) = t(j1)+per - t(j2) = t(i2)-per - 60 continue -c compute the b-spline coefficients of the least-squares closed curve -c sinf(u). the observation matrix a is built up row by row while -c taking into account condition (**) and is reduced to triangular -c form by givens transformations . -c at the same time fp=f(p=inf) is computed. -c the n7 x n7 triangularised upper matrix a has the form -c ! a1 ' ! -c a = ! ' a2 ! -c ! 0 ' ! -c with a2 a n7 x k matrix and a1 a n10 x n10 upper triangular -c matrix of bandwith k+1 ( n10 = n7-k). -c initialization. - do 65 i=1,nc - z(i) = 0. - 65 continue - do 70 i=1,nk1 - do 70 j=1,kk1 - a1(i,j) = 0. - 70 continue - n7 = nk1-k - n10 = n7-kk - jper = 0 - fp = 0. - l = k1 - jj = 0 - do 290 it=1,m1 -c fetch the current data point u(it),x(it) - ui = u(it) - wi = w(it) - do 75 j=1,idim - jj = jj+1 - xi(j) = x(jj)*wi - 75 continue -c search for knot interval t(l) <= ui < t(l+1). - 80 if(ui.lt.t(l+1)) go to 85 - l = l+1 - go to 80 -c evaluate the (k+1) non-zero b-splines at ui and store them in q. - 85 call fpbspl(t,n,k,ui,l,h) - do 90 i=1,k1 - q(it,i) = h(i) - h(i) = h(i)*wi - 90 continue - l5 = l-k1 -c test whether the b-splines nj,k+1(u),j=1+n7,...nk1 are all zero at ui - if(l5.lt.n10) go to 285 - if(jper.ne.0) go to 160 -c initialize the matrix a2. - do 95 i=1,n7 - do 95 j=1,kk - a2(i,j) = 0. - 95 continue - jk = n10+1 - do 110 i=1,kk - ik = jk - do 100 j=1,kk1 - if(ik.le.0) go to 105 - a2(ik,i) = a1(ik,j) - ik = ik-1 - 100 continue - 105 jk = jk+1 - 110 continue - jper = 1 -c if one of the b-splines nj,k+1(u),j=n7+1,...nk1 is not zero at ui -c we take account of condition (**) for setting up the new row -c of the observation matrix a. this row is stored in the arrays h1 -c (the part with respect to a1) and h2 (the part with -c respect to a2). - 160 do 170 i=1,kk - h1(i) = 0. - h2(i) = 0. - 170 continue - h1(kk1) = 0. - j = l5-n10 - do 210 i=1,kk1 - j = j+1 - l0 = j - 180 l1 = l0-kk - if(l1.le.0) go to 200 - if(l1.le.n10) go to 190 - l0 = l1-n10 - go to 180 - 190 h1(l1) = h(i) - go to 210 - 200 h2(l0) = h2(l0)+h(i) - 210 continue -c rotate the new row of the observation matrix into triangle -c by givens transformations. - if(n10.le.0) go to 250 -c rotation with the rows 1,2,...n10 of matrix a. - do 240 j=1,n10 - piv = h1(1) - if(piv.ne.0.) go to 214 - do 212 i=1,kk - h1(i) = h1(i+1) - 212 continue - h1(kk1) = 0. - go to 240 -c calculate the parameters of the givens transformation. - 214 call fpgivs(piv,a1(j,1),cos,sin) -c transformation to the right hand side. - j1 = j - do 217 j2=1,idim - call fprota(cos,sin,xi(j2),z(j1)) - j1 = j1+n - 217 continue -c transformations to the left hand side with respect to a2. - do 220 i=1,kk - call fprota(cos,sin,h2(i),a2(j,i)) - 220 continue - if(j.eq.n10) go to 250 - i2 = min0(n10-j,kk) -c transformations to the left hand side with respect to a1. - do 230 i=1,i2 - i1 = i+1 - call fprota(cos,sin,h1(i1),a1(j,i1)) - h1(i) = h1(i1) - 230 continue - h1(i1) = 0. - 240 continue -c rotation with the rows n10+1,...n7 of matrix a. - 250 do 270 j=1,kk - ij = n10+j - if(ij.le.0) go to 270 - piv = h2(j) - if(piv.eq.0.) go to 270 -c calculate the parameters of the givens transformation. - call fpgivs(piv,a2(ij,j),cos,sin) -c transformations to right hand side. - j1 = ij - do 255 j2=1,idim - call fprota(cos,sin,xi(j2),z(j1)) - j1 = j1+n - 255 continue - if(j.eq.kk) go to 280 - j1 = j+1 -c transformations to left hand side. - do 260 i=j1,kk - call fprota(cos,sin,h2(i),a2(ij,i)) - 260 continue - 270 continue -c add contribution of this row to the sum of squares of residual -c right hand sides. - 280 do 282 j2=1,idim - fp = fp+xi(j2)**2 - 282 continue - go to 290 -c rotation of the new row of the observation matrix into -c triangle in case the b-splines nj,k+1(u),j=n7+1,...n-k-1 are all zero -c at ui. - 285 j = l5 - do 140 i=1,kk1 - j = j+1 - piv = h(i) - if(piv.eq.0.) go to 140 -c calculate the parameters of the givens transformation. - call fpgivs(piv,a1(j,1),cos,sin) -c transformations to right hand side. - j1 = j - do 125 j2=1,idim - call fprota(cos,sin,xi(j2),z(j1)) - j1 = j1+n - 125 continue - if(i.eq.kk1) go to 150 - i2 = 1 - i3 = i+1 -c transformations to left hand side. - do 130 i1=i3,kk1 - i2 = i2+1 - call fprota(cos,sin,h(i1),a1(j,i2)) - 130 continue - 140 continue -c add contribution of this row to the sum of squares of residual -c right hand sides. - 150 do 155 j2=1,idim - fp = fp+xi(j2)**2 - 155 continue - 290 continue - fpint(n) = fp0 - fpint(n-1) = fpold - nrdata(n) = nplus -c backward substitution to obtain the b-spline coefficients . - j1 = 1 - do 292 j2=1,idim - call fpbacp(a1,a2,z(j1),n7,kk,c(j1),kk1,nest) - j1 = j1+n - 292 continue -c calculate from condition (**) the remaining coefficients. - do 297 i=1,k - j1 = i - do 295 j=1,idim - j2 = j1+n7 - c(j2) = c(j1) - j1 = j1+n - 295 continue - 297 continue - if(iopt.lt.0) go to 660 -c test whether the approximation sinf(u) is an acceptable solution. - fpms = fp-s - if(abs(fpms).lt.acc) go to 660 -c if f(p=inf) < s accept the choice of knots. - if(fpms.lt.0.) go to 350 -c if n=nmax, sinf(u) is an interpolating curve. - if(n.eq.nmax) go to 630 -c increase the number of knots. -c if n=nest we cannot increase the number of knots because of the -c storage capacity limitation. - if(n.eq.nest) go to 620 -c determine the number of knots nplus we are going to add. - npl1 = nplus*2 - rn = nplus - if(fpold-fp.gt.acc) npl1 = rn*fpms/(fpold-fp) - nplus = min0(nplus*2,max0(npl1,nplus/2,1)) - fpold = fp -c compute the sum of squared residuals for each knot interval -c t(j+k) <= ui <= t(j+k+1) and store it in fpint(j),j=1,2,...nrint. - fpart = 0. - i = 1 - l = k1 - jj = 0 - do 320 it=1,m1 - if(u(it).lt.t(l)) go to 300 - new = 1 - l = l+1 - 300 term = 0. - l0 = l-k2 - do 310 j2=1,idim - fac = 0. - j1 = l0 - do 305 j=1,k1 - j1 = j1+1 - fac = fac+c(j1)*q(it,j) - 305 continue - jj = jj+1 - term = term+(w(it)*(fac-x(jj)))**2 - l0 = l0+n - 310 continue - fpart = fpart+term - if(new.eq.0) go to 320 - if(l.gt.k2) go to 315 - fpint(nrint) = term - new = 0 - go to 320 - 315 store = term*half - fpint(i) = fpart-store - i = i+1 - fpart = store - new = 0 - 320 continue - fpint(nrint) = fpint(nrint)+fpart - do 330 l=1,nplus -c add a new knot - call fpknot(u,m,t,n,fpint,nrdata,nrint,nest,1) -c if n=nmax we locate the knots as for interpolation - if(n.eq.nmax) go to 5 -c test whether we cannot further increase the number of knots. - if(n.eq.nest) go to 340 - 330 continue -c restart the computations with the new set of knots. - 340 continue -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 2: determination of the smoothing closed curve sp(u). c -c ********************************************************** c -c we have determined the number of knots and their position. c -c we now compute the b-spline coefficients of the smoothing curve c -c sp(u). the observation matrix a is extended by the rows of matrix c -c b expressing that the kth derivative discontinuities of sp(u) at c -c the interior knots t(k+2),...t(n-k-1) must be zero. the corres- c -c ponding weights of these additional rows are set to 1/p. c -c iteratively we then have to determine the value of p such that f(p),c -c the sum of squared residuals be = s. we already know that the least-c -c squares polynomial curve corresponds to p=0, and that the least- c -c squares periodic spline curve corresponds to p=infinity. the c -c iteration process which is proposed here, makes use of rational c -c interpolation. since f(p) is a convex and strictly decreasing c -c function of p, it can be approximated by a rational function c -c r(p) = (u*p+v)/(p+w). three values of p(p1,p2,p3) with correspond- c -c ing values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used c -c to calculate the new value of p such that r(p)=s. convergence is c -c guaranteed by taking f1>0 and f3<0. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c evaluate the discontinuity jump of the kth derivative of the -c b-splines at the knots t(l),l=k+2,...n-k-1 and store in b. - 350 call fpdisc(t,n,k2,b,nest) -c initial value for p. - p1 = 0. - f1 = fp0-s - p3 = -one - f3 = fpms - n11 = n10-1 - n8 = n7-1 - p = 0. - l = n7 - do 352 i=1,k - j = k+1-i - p = p+a2(l,j) - l = l-1 - if(l.eq.0) go to 356 - 352 continue - do 354 i=1,n10 - p = p+a1(i,1) - 354 continue - 356 rn = n7 - p = rn/p - ich1 = 0 - ich3 = 0 -c iteration process to find the root of f(p) = s. - do 595 iter=1,maxit -c form the matrix g as the matrix a extended by the rows of matrix b. -c the rows of matrix b with weight 1/p are rotated into -c the triangularised observation matrix a. -c after triangularisation our n7 x n7 matrix g takes the form -c ! g1 ' ! -c g = ! ' g2 ! -c ! 0 ' ! -c with g2 a n7 x (k+1) matrix and g1 a n11 x n11 upper triangular -c matrix of bandwidth k+2. ( n11 = n7-k-1) - pinv = one/p -c store matrix a into g - do 358 i=1,nc - c(i) = z(i) - 358 continue - do 360 i=1,n7 - g1(i,k1) = a1(i,k1) - g1(i,k2) = 0. - g2(i,1) = 0. - do 360 j=1,k - g1(i,j) = a1(i,j) - g2(i,j+1) = a2(i,j) - 360 continue - l = n10 - do 370 j=1,k1 - if(l.le.0) go to 375 - g2(l,1) = a1(l,j) - l = l-1 - 370 continue - 375 do 540 it=1,n8 -c fetch a new row of matrix b and store it in the arrays h1 (the part -c with respect to g1) and h2 (the part with respect to g2). - do 380 j=1,idim - xi(j) = 0. - 380 continue - do 385 i=1,k1 - h1(i) = 0. - h2(i) = 0. - 385 continue - h1(k2) = 0. - if(it.gt.n11) go to 420 - l = it - l0 = it - do 390 j=1,k2 - if(l0.eq.n10) go to 400 - h1(j) = b(it,j)*pinv - l0 = l0+1 - 390 continue - go to 470 - 400 l0 = 1 - do 410 l1=j,k2 - h2(l0) = b(it,l1)*pinv - l0 = l0+1 - 410 continue - go to 470 - 420 l = 1 - i = it-n10 - do 460 j=1,k2 - i = i+1 - l0 = i - 430 l1 = l0-k1 - if(l1.le.0) go to 450 - if(l1.le.n11) go to 440 - l0 = l1-n11 - go to 430 - 440 h1(l1) = b(it,j)*pinv - go to 460 - 450 h2(l0) = h2(l0)+b(it,j)*pinv - 460 continue - if(n11.le.0) go to 510 -c rotate this row into triangle by givens transformations -c rotation with the rows l,l+1,...n11. - 470 do 500 j=l,n11 - piv = h1(1) -c calculate the parameters of the givens transformation. - call fpgivs(piv,g1(j,1),cos,sin) -c transformation to right hand side. - j1 = j - do 475 j2=1,idim - call fprota(cos,sin,xi(j2),c(j1)) - j1 = j1+n - 475 continue -c transformation to the left hand side with respect to g2. - do 480 i=1,k1 - call fprota(cos,sin,h2(i),g2(j,i)) - 480 continue - if(j.eq.n11) go to 510 - i2 = min0(n11-j,k1) -c transformation to the left hand side with respect to g1. - do 490 i=1,i2 - i1 = i+1 - call fprota(cos,sin,h1(i1),g1(j,i1)) - h1(i) = h1(i1) - 490 continue - h1(i1) = 0. - 500 continue -c rotation with the rows n11+1,...n7 - 510 do 530 j=1,k1 - ij = n11+j - if(ij.le.0) go to 530 - piv = h2(j) -c calculate the parameters of the givens transformation - call fpgivs(piv,g2(ij,j),cos,sin) -c transformation to the right hand side. - j1 = ij - do 515 j2=1,idim - call fprota(cos,sin,xi(j2),c(j1)) - j1 = j1+n - 515 continue - if(j.eq.k1) go to 540 - j1 = j+1 -c transformation to the left hand side. - do 520 i=j1,k1 - call fprota(cos,sin,h2(i),g2(ij,i)) - 520 continue - 530 continue - 540 continue -c backward substitution to obtain the b-spline coefficients - j1 = 1 - do 542 j2=1,idim - call fpbacp(g1,g2,c(j1),n7,k1,c(j1),k2,nest) - j1 = j1+n - 542 continue -c calculate from condition (**) the remaining b-spline coefficients. - do 547 i=1,k - j1 = i - do 545 j=1,idim - j2 = j1+n7 - c(j2) = c(j1) - j1 = j1+n - 545 continue - 547 continue -c computation of f(p). - fp = 0. - l = k1 - jj = 0 - do 570 it=1,m1 - if(u(it).lt.t(l)) go to 550 - l = l+1 - 550 l0 = l-k2 - term = 0. - do 565 j2=1,idim - fac = 0. - j1 = l0 - do 560 j=1,k1 - j1 = j1+1 - fac = fac+c(j1)*q(it,j) - 560 continue - jj = jj+1 - term = term+(fac-x(jj))**2 - l0 = l0+n - 565 continue - fp = fp+term*w(it)**2 - 570 continue -c test whether the approximation sp(u) is an acceptable solution. - fpms = fp-s - if(abs(fpms).lt.acc) go to 660 -c test whether the maximal number of iterations is reached. - if(iter.eq.maxit) go to 600 -c carry out one more step of the iteration process. - p2 = p - f2 = fpms - if(ich3.ne.0) go to 580 - if((f2-f3) .gt. acc) go to 575 -c our initial choice of p is too large. - p3 = p2 - f3 = f2 - p = p*con4 - if(p.le.p1) p = p1*con9 +p2*con1 - go to 595 - 575 if(f2.lt.0.) ich3 = 1 - 580 if(ich1.ne.0) go to 590 - if((f1-f2) .gt. acc) go to 585 -c our initial choice of p is too small - p1 = p2 - f1 = f2 - p = p/con4 - if(p3.lt.0.) go to 595 - if(p.ge.p3) p = p2*con1 +p3*con9 - go to 595 - 585 if(f2.gt.0.) ich1 = 1 -c test whether the iteration process proceeds as theoretically -c expected. - 590 if(f2.ge.f1 .or. f2.le.f3) go to 610 -c find the new value for p. - p = fprati(p1,f1,p2,f2,p3,f3) - 595 continue -c error codes and messages. - 600 ier = 3 - go to 660 - 610 ier = 2 - go to 660 - 620 ier = 1 - go to 660 - 630 ier = -1 - go to 660 - 640 ier = -2 -c the point (z(1),z(2),...,z(idim)) is a solution of our problem. -c a constant function is a spline of degree k with all b-spline -c coefficients equal to that constant. - do 650 i=1,k1 - rn = k1-i - t(i) = u(1)-rn*per - j = i+k1 - rn = i-1 - t(j) = u(m)+rn*per - 650 continue - n = nmin - j1 = 0 - do 658 j=1,idim - fac = z(j) - j2 = j1 - do 654 i=1,k1 - j2 = j2+1 - c(j2) = fac - 654 continue - j1 = j1+n - 658 continue - fp = fp0 - fpint(n) = fp0 - fpint(n-1) = 0. - nrdata(n) = 0 - 660 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpcoco.f =================================================================== --- branches/Interpolate1D/fitpack/fpcoco.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpcoco.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,168 +0,0 @@ - subroutine fpcoco(iopt,m,x,y,w,v,s,nest,maxtr,maxbin,n,t,c,sq,sx, - * bind,e,wrk,lwrk,iwrk,kwrk,ier) -c ..scalar arguments.. - real*8 s,sq - integer iopt,m,nest,maxtr,maxbin,n,lwrk,kwrk,ier -c ..array arguments.. - integer iwrk(kwrk) - real*8 x(m),y(m),w(m),v(m),t(nest),c(nest),sx(m),e(nest),wrk(lwrk) - * - logical bind(nest) -c ..local scalars.. - integer i,ia,ib,ic,iq,iu,iz,izz,i1,j,k,l,l1,m1,nmax,nr,n4,n6,n8, - * ji,jib,jjb,jl,jr,ju,mb,nm - real*8 sql,sqmax,term,tj,xi,half -c ..subroutine references.. -c fpcosp,fpbspl,fpadno,fpdeno,fpseno,fpfrno -c .. -c set constant - half = 0.5e0 -c determine the maximal admissible number of knots. - nmax = m+4 -c the initial choice of knots depends on the value of iopt. -c if iopt=0 the program starts with the minimal number of knots -c so that can be guarantied that the concavity/convexity constraints -c will be satisfied. -c if iopt = 1 the program will continue from the point on where she -c left at the foregoing call. - if(iopt.gt.0) go to 80 -c find the minimal number of knots. -c a knot is located at the data point x(i), i=2,3,...m-1 if -c 1) v(i) ^= 0 and -c 2) v(i)*v(i-1) <= 0 or v(i)*v(i+1) <= 0. - m1 = m-1 - n = 4 - do 20 i=2,m1 - if(v(i).eq.0. .or. (v(i)*v(i-1).gt.0. .and. - * v(i)*v(i+1).gt.0.)) go to 20 - n = n+1 -c test whether the required storage space exceeds the available one. - if(n+4.gt.nest) go to 200 - t(n) = x(i) - 20 continue -c find the position of the knots t(1),...t(4) and t(n-3),...t(n) which -c are needed for the b-spline representation of s(x). - do 30 i=1,4 - t(i) = x(1) - n = n+1 - t(n) = x(m) - 30 continue -c test whether the minimum number of knots exceeds the maximum number. - if(n.gt.nmax) go to 210 -c main loop for the different sets of knots. -c find corresponding values e(j) to the knots t(j+3),j=1,2,...n-6 -c e(j) will take the value -1,1, or 0 according to the requirement -c that s(x) must be locally convex or concave at t(j+3) or that the -c sign of s''(x) is unrestricted at that point. - 40 i= 1 - xi = x(1) - j = 4 - tj = t(4) - n6 = n-6 - do 70 l=1,n6 - 50 if(xi.eq.tj) go to 60 - i = i+1 - xi = x(i) - go to 50 - 60 e(l) = v(i) - j = j+1 - tj = t(j) - 70 continue -c we partition the working space - nm = n+maxbin - mb = maxbin+1 - ia = 1 - ib = ia+4*n - ic = ib+nm*maxbin - iz = ic+n - izz = iz+n - iu = izz+n - iq = iu+maxbin - ji = 1 - ju = ji+maxtr - jl = ju+maxtr - jr = jl+maxtr - jjb = jr+maxtr - jib = jjb+mb -c given the set of knots t(j),j=1,2,...n, find the least-squares cubic -c spline which satisfies the imposed concavity/convexity constraints. - call fpcosp(m,x,y,w,n,t,e,maxtr,maxbin,c,sq,sx,bind,nm,mb,wrk(ia), - * - * wrk(ib),wrk(ic),wrk(iz),wrk(izz),wrk(iu),wrk(iq),iwrk(ji), - * iwrk(ju),iwrk(jl),iwrk(jr),iwrk(jjb),iwrk(jib),ier) -c if sq <= s or in case of abnormal exit from fpcosp, control is -c repassed to the driver program. - if(sq.le.s .or. ier.gt.0) go to 300 -c calculate for each knot interval t(l-1) <= xi <= t(l) the -c sum((wi*(yi-s(xi)))**2). -c find the interval t(k-1) <= x <= t(k) for which this sum is maximal -c on the condition that this interval contains at least one interior -c data point x(nr) and that s(x) is not given there by a straight line. - 80 sqmax = 0. - sql = 0. - l = 5 - nr = 0 - i1 = 1 - n4 = n-4 - do 110 i=1,m - term = (w(i)*(sx(i)-y(i)))**2 - if(x(i).lt.t(l) .or. l.gt.n4) go to 100 - term = term*half - sql = sql+term - if(i-i1.le.1 .or. (bind(l-4).and.bind(l-3))) go to 90 - if(sql.le.sqmax) go to 90 - k = l - sqmax = sql - nr = i1+(i-i1)/2 - 90 l = l+1 - i1 = i - sql = 0. - 100 sql = sql+term - 110 continue - if(m-i1.le.1 .or. (bind(l-4).and.bind(l-3))) go to 120 - if(sql.le.sqmax) go to 120 - k = l - nr = i1+(m-i1)/2 -c if no such interval is found, control is repassed to the driver -c program (ier = -1). - 120 if(nr.eq.0) go to 190 -c if s(x) is given by the same straight line in two succeeding knot -c intervals t(l-1) <= x <= t(l) and t(l) <= x <= t(l+1),delete t(l) - n8 = n-8 - l1 = 0 - if(n8.le.0) go to 150 - do 140 i=1,n8 - if(.not. (bind(i).and.bind(i+1).and.bind(i+2))) go to 140 - l = i+4-l1 - if(k.gt.l) k = k-1 - n = n-1 - l1 = l1+1 - do 130 j=l,n - t(j) = t(j+1) - 130 continue - 140 continue -c test whether we cannot further increase the number of knots. - 150 if(n.eq.nmax) go to 180 - if(n.eq.nest) go to 170 -c locate an additional knot at the point x(nr). - j = n - do 160 i=k,n - t(j+1) = t(j) - j = j-1 - 160 continue - t(k) = x(nr) - n = n+1 -c restart the computations with the new set of knots. - go to 40 -c error codes and messages. - 170 ier = -3 - go to 300 - 180 ier = -2 - go to 300 - 190 ier = -1 - go to 300 - 200 ier = 4 - go to 300 - 210 ier = 5 - 300 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpcons.f =================================================================== --- branches/Interpolate1D/fitpack/fpcons.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpcons.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,442 +0,0 @@ - subroutine fpcons(iopt,idim,m,u,mx,x,w,ib,ie,k,s,nest,tol,maxit, - * k1,k2,n,t,nc,c,fp,fpint,z,a,b,g,q,nrdata,ier) -c .. -c ..scalar arguments.. - real*8 s,tol,fp - integer iopt,idim,m,mx,ib,ie,k,nest,maxit,k1,k2,n,nc,ier -c ..array arguments.. - real*8 u(m),x(mx),w(m),t(nest),c(nc),fpint(nest), - * z(nc),a(nest,k1),b(nest,k2),g(nest,k2),q(m,k1) - integer nrdata(nest) -c ..local scalars.. - real*8 acc,con1,con4,con9,cos,fac,fpart,fpms,fpold,fp0,f1,f2,f3, - * half,one,p,pinv,piv,p1,p2,p3,rn,sin,store,term,ui,wi - integer i,ich1,ich3,it,iter,i1,i2,i3,j,jb,je,jj,j1,j2,j3,kbe, - * l,li,lj,l0,mb,me,mm,new,nk1,nmax,nmin,nn,nplus,npl1,nrint,n8 -c ..local arrays.. - real*8 h(7),xi(10) -c ..function references - real*8 abs,fprati - integer max0,min0 -c ..subroutine references.. -c fpbacp,fpbspl,fpgivs,fpdisc,fpknot,fprota -c .. -c set constants - one = 0.1e+01 - con1 = 0.1e0 - con9 = 0.9e0 - con4 = 0.4e-01 - half = 0.5e0 -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 1: determination of the number of knots and their position c -c ************************************************************** c -c given a set of knots we compute the least-squares curve sinf(u), c -c and the corresponding sum of squared residuals fp=f(p=inf). c -c if iopt=-1 sinf(u) is the requested curve. c -c if iopt=0 or iopt=1 we check whether we can accept the knots: c -c if fp <=s we will continue with the current set of knots. c -c if fp > s we will increase the number of knots and compute the c -c corresponding least-squares curve until finally fp<=s. c -c the initial choice of knots depends on the value of s and iopt. c -c if s=0 we have spline interpolation; in that case the number of c -c knots equals nmax = m+k+1-max(0,ib-1)-max(0,ie-1) c -c if s > 0 and c -c iopt=0 we first compute the least-squares polynomial curve of c -c degree k; n = nmin = 2*k+2 c -c iopt=1 we start with the set of knots found at the last c -c call of the routine, except for the case that s > fp0; then c -c we compute directly the polynomial curve of degree k. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c determine nmin, the number of knots for polynomial approximation. - nmin = 2*k1 -c find which data points are to be concidered. - mb = 2 - jb = ib - if(ib.gt.0) go to 10 - mb = 1 - jb = 1 - 10 me = m-1 - je = ie - if(ie.gt.0) go to 20 - me = m - je = 1 - 20 if(iopt.lt.0) go to 60 -c calculation of acc, the absolute tolerance for the root of f(p)=s. - acc = tol*s -c determine nmax, the number of knots for spline interpolation. - kbe = k1-jb-je - mmin = kbe+2 - mm = m-mmin - nmax = nmin+mm - if(s.gt.0.) go to 40 -c if s=0, s(u) is an interpolating curve. -c test whether the required storage space exceeds the available one. - n = nmax - if(nmax.gt.nest) go to 420 -c find the position of the interior knots in case of interpolation. - if(mm.eq.0) go to 60 - 25 i = k2 - j = 3-jb+k/2 - do 30 l=1,mm - t(i) = u(j) - i = i+1 - j = j+1 - 30 continue - go to 60 -c if s>0 our initial choice of knots depends on the value of iopt. -c if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares -c polynomial curve which is a spline curve without interior knots. -c if iopt=1 and fp0>s we start computing the least squares spline curve -c according to the set of knots found at the last call of the routine. - 40 if(iopt.eq.0) go to 50 - if(n.eq.nmin) go to 50 - fp0 = fpint(n) - fpold = fpint(n-1) - nplus = nrdata(n) - if(fp0.gt.s) go to 60 - 50 n = nmin - fpold = 0. - nplus = 0 - nrdata(1) = m-2 -c main loop for the different sets of knots. m is a save upper bound -c for the number of trials. - 60 do 200 iter = 1,m - if(n.eq.nmin) ier = -2 -c find nrint, tne number of knot intervals. - nrint = n-nmin+1 -c find the position of the additional knots which are needed for -c the b-spline representation of s(u). - nk1 = n-k1 - i = n - do 70 j=1,k1 - t(j) = u(1) - t(i) = u(m) - i = i-1 - 70 continue -c compute the b-spline coefficients of the least-squares spline curve -c sinf(u). the observation matrix a is built up row by row and -c reduced to upper triangular form by givens transformations. -c at the same time fp=f(p=inf) is computed. - fp = 0. -c nn denotes the dimension of the splines - nn = nk1-ib-ie -c initialize the b-spline coefficients and the observation matrix a. - do 75 i=1,nc - z(i) = 0. - c(i) = 0. - 75 continue - if(me.lt.mb) go to 134 - if(nn.eq.0) go to 82 - do 80 i=1,nn - do 80 j=1,k1 - a(i,j) = 0. - 80 continue - 82 l = k1 - jj = (mb-1)*idim - do 130 it=mb,me -c fetch the current data point u(it),x(it). - ui = u(it) - wi = w(it) - do 84 j=1,idim - jj = jj+1 - xi(j) = x(jj)*wi - 84 continue -c search for knot interval t(l) <= ui < t(l+1). - 86 if(ui.lt.t(l+1) .or. l.eq.nk1) go to 90 - l = l+1 - go to 86 -c evaluate the (k+1) non-zero b-splines at ui and store them in q. - 90 call fpbspl(t,n,k,ui,l,h) - do 92 i=1,k1 - q(it,i) = h(i) - h(i) = h(i)*wi - 92 continue -c take into account that certain b-spline coefficients must be zero. - lj = k1 - j = nk1-l-ie - if(j.ge.0) go to 94 - lj = lj+j - 94 li = 1 - j = l-k1-ib - if(j.ge.0) go to 96 - li = li-j - j = 0 - 96 if(li.gt.lj) go to 120 -c rotate the new row of the observation matrix into triangle. - do 110 i=li,lj - j = j+1 - piv = h(i) - if(piv.eq.0.) go to 110 -c calculate the parameters of the givens transformation. - call fpgivs(piv,a(j,1),cos,sin) -c transformations to right hand side. - j1 = j - do 98 j2 =1,idim - call fprota(cos,sin,xi(j2),z(j1)) - j1 = j1+n - 98 continue - if(i.eq.lj) go to 120 - i2 = 1 - i3 = i+1 - do 100 i1 = i3,lj - i2 = i2+1 -c transformations to left hand side. - call fprota(cos,sin,h(i1),a(j,i2)) - 100 continue - 110 continue -c add contribution of this row to the sum of squares of residual -c right hand sides. - 120 do 125 j2=1,idim - fp = fp+xi(j2)**2 - 125 continue - 130 continue - if(ier.eq.(-2)) fp0 = fp - fpint(n) = fp0 - fpint(n-1) = fpold - nrdata(n) = nplus -c backward substitution to obtain the b-spline coefficients. - if(nn.eq.0) go to 134 - j1 = 1 - do 132 j2=1,idim - j3 = j1+ib - call fpback(a,z(j1),nn,k1,c(j3),nest) - j1 = j1+n - 132 continue -c test whether the approximation sinf(u) is an acceptable solution. - 134 if(iopt.lt.0) go to 440 - fpms = fp-s - if(abs(fpms).lt.acc) go to 440 -c if f(p=inf) < s accept the choice of knots. - if(fpms.lt.0.) go to 250 -c if n = nmax, sinf(u) is an interpolating spline curve. - if(n.eq.nmax) go to 430 -c increase the number of knots. -c if n=nest we cannot increase the number of knots because of -c the storage capacity limitation. - if(n.eq.nest) go to 420 -c determine the number of knots nplus we are going to add. - if(ier.eq.0) go to 140 - nplus = 1 - ier = 0 - go to 150 - 140 npl1 = nplus*2 - rn = nplus - if(fpold-fp.gt.acc) npl1 = rn*fpms/(fpold-fp) - nplus = min0(nplus*2,max0(npl1,nplus/2,1)) - 150 fpold = fp -c compute the sum of squared residuals for each knot interval -c t(j+k) <= u(i) <= t(j+k+1) and store it in fpint(j),j=1,2,...nrint. - fpart = 0. - i = 1 - l = k2 - new = 0 - jj = (mb-1)*idim - do 180 it=mb,me - if(u(it).lt.t(l) .or. l.gt.nk1) go to 160 - new = 1 - l = l+1 - 160 term = 0. - l0 = l-k2 - do 175 j2=1,idim - fac = 0. - j1 = l0 - do 170 j=1,k1 - j1 = j1+1 - fac = fac+c(j1)*q(it,j) - 170 continue - jj = jj+1 - term = term+(w(it)*(fac-x(jj)))**2 - l0 = l0+n - 175 continue - fpart = fpart+term - if(new.eq.0) go to 180 - store = term*half - fpint(i) = fpart-store - i = i+1 - fpart = store - new = 0 - 180 continue - fpint(nrint) = fpart - do 190 l=1,nplus -c add a new knot. - call fpknot(u,m,t,n,fpint,nrdata,nrint,nest,1) -c if n=nmax we locate the knots as for interpolation - if(n.eq.nmax) go to 25 -c test whether we cannot further increase the number of knots. - if(n.eq.nest) go to 200 - 190 continue -c restart the computations with the new set of knots. - 200 continue -c test whether the least-squares kth degree polynomial curve is a -c solution of our approximation problem. - 250 if(ier.eq.(-2)) go to 440 -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 2: determination of the smoothing spline curve sp(u). c -c ********************************************************** c -c we have determined the number of knots and their position. c -c we now compute the b-spline coefficients of the smoothing curve c -c sp(u). the observation matrix a is extended by the rows of matrix c -c b expressing that the kth derivative discontinuities of sp(u) at c -c the interior knots t(k+2),...t(n-k-1) must be zero. the corres- c -c ponding weights of these additional rows are set to 1/p. c -c iteratively we then have to determine the value of p such that f(p),c -c the sum of squared residuals be = s. we already know that the least c -c squares kth degree polynomial curve corresponds to p=0, and that c -c the least-squares spline curve corresponds to p=infinity. the c -c iteration process which is proposed here, makes use of rational c -c interpolation. since f(p) is a convex and strictly decreasing c -c function of p, it can be approximated by a rational function c -c r(p) = (u*p+v)/(p+w). three values of p(p1,p2,p3) with correspond- c -c ing values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used c -c to calculate the new value of p such that r(p)=s. convergence is c -c guaranteed by taking f1>0 and f3<0. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c evaluate the discontinuity jump of the kth derivative of the -c b-splines at the knots t(l),l=k+2,...n-k-1 and store in b. - call fpdisc(t,n,k2,b,nest) -c initial value for p. - p1 = 0. - f1 = fp0-s - p3 = -one - f3 = fpms - p = 0. - do 252 i=1,nn - p = p+a(i,1) - 252 continue - rn = nn - p = rn/p - ich1 = 0 - ich3 = 0 - n8 = n-nmin -c iteration process to find the root of f(p) = s. - do 360 iter=1,maxit -c the rows of matrix b with weight 1/p are rotated into the -c triangularised observation matrix a which is stored in g. - pinv = one/p - do 255 i=1,nc - c(i) = z(i) - 255 continue - do 260 i=1,nn - g(i,k2) = 0. - do 260 j=1,k1 - g(i,j) = a(i,j) - 260 continue - do 300 it=1,n8 -c the row of matrix b is rotated into triangle by givens transformation - do 264 i=1,k2 - h(i) = b(it,i)*pinv - 264 continue - do 268 j=1,idim - xi(j) = 0. - 268 continue -c take into account that certain b-spline coefficients must be zero. - if(it.gt.ib) go to 274 - j1 = ib-it+2 - j2 = 1 - do 270 i=j1,k2 - h(j2) = h(i) - j2 = j2+1 - 270 continue - do 272 i=j2,k2 - h(i) = 0. - 272 continue - 274 jj = max0(1,it-ib) - do 290 j=jj,nn - piv = h(1) -c calculate the parameters of the givens transformation. - call fpgivs(piv,g(j,1),cos,sin) -c transformations to right hand side. - j1 = j - do 277 j2=1,idim - call fprota(cos,sin,xi(j2),c(j1)) - j1 = j1+n - 277 continue - if(j.eq.nn) go to 300 - i2 = min0(nn-j,k1) - do 280 i=1,i2 -c transformations to left hand side. - i1 = i+1 - call fprota(cos,sin,h(i1),g(j,i1)) - h(i) = h(i1) - 280 continue - h(i2+1) = 0. - 290 continue - 300 continue -c backward substitution to obtain the b-spline coefficients. - j1 = 1 - do 308 j2=1,idim - j3 = j1+ib - call fpback(g,c(j1),nn,k2,c(j3),nest) - if(ib.eq.0) go to 306 - j3 = j1 - do 304 i=1,ib - c(j3) = 0. - j3 = j3+1 - 304 continue - 306 j1 =j1+n - 308 continue -c computation of f(p). - fp = 0. - l = k2 - jj = (mb-1)*idim - do 330 it=mb,me - if(u(it).lt.t(l) .or. l.gt.nk1) go to 310 - l = l+1 - 310 l0 = l-k2 - term = 0. - do 325 j2=1,idim - fac = 0. - j1 = l0 - do 320 j=1,k1 - j1 = j1+1 - fac = fac+c(j1)*q(it,j) - 320 continue - jj = jj+1 - term = term+(fac-x(jj))**2 - l0 = l0+n - 325 continue - fp = fp+term*w(it)**2 - 330 continue -c test whether the approximation sp(u) is an acceptable solution. - fpms = fp-s - if(abs(fpms).lt.acc) go to 440 -c test whether the maximal number of iterations is reached. - if(iter.eq.maxit) go to 400 -c carry out one more step of the iteration process. - p2 = p - f2 = fpms - if(ich3.ne.0) go to 340 - if((f2-f3).gt.acc) go to 335 -c our initial choice of p is too large. - p3 = p2 - f3 = f2 - p = p*con4 - if(p.le.p1) p=p1*con9 + p2*con1 - go to 360 - 335 if(f2.lt.0.) ich3=1 - 340 if(ich1.ne.0) go to 350 - if((f1-f2).gt.acc) go to 345 -c our initial choice of p is too small - p1 = p2 - f1 = f2 - p = p/con4 - if(p3.lt.0.) go to 360 - if(p.ge.p3) p = p2*con1 + p3*con9 - go to 360 - 345 if(f2.gt.0.) ich1=1 -c test whether the iteration process proceeds as theoretically -c expected. - 350 if(f2.ge.f1 .or. f2.le.f3) go to 410 -c find the new value for p. - p = fprati(p1,f1,p2,f2,p3,f3) - 360 continue -c error codes and messages. - 400 ier = 3 - go to 440 - 410 ier = 2 - go to 440 - 420 ier = 1 - go to 440 - 430 ier = -1 - 440 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpcosp.f =================================================================== --- branches/Interpolate1D/fitpack/fpcosp.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpcosp.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,362 +0,0 @@ - subroutine fpcosp(m,x,y,w,n,t,e,maxtr,maxbin,c,sq,sx,bind,nm,mb,a, - * - * b,const,z,zz,u,q,info,up,left,right,jbind,ibind,ier) -c .. -c ..scalar arguments.. - real*8 sq - integer m,n,maxtr,maxbin,nm,mb,ier -c ..array arguments.. - real*8 x(m),y(m),w(m),t(n),e(n),c(n),sx(m),a(n,4),b(nm,maxbin), - * const(n),z(n),zz(n),u(maxbin),q(m,4) - integer info(maxtr),up(maxtr),left(maxtr),right(maxtr),jbind(mb), - * ibind(mb) - logical bind(n) -c ..local scalars.. - integer count,i,i1,j,j1,j2,j3,k,kdim,k1,k2,k3,k4,k5,k6, - * l,lp1,l1,l2,l3,merk,nbind,number,n1,n4,n6 - real*8 f,wi,xi -c ..local array.. - real*8 h(4) -c ..subroutine references.. -c fpbspl,fpadno,fpdeno,fpfrno,fpseno -c .. -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c if we use the b-spline representation of s(x) our approximation c -c problem results in a quadratic programming problem: c -c find the b-spline coefficients c(j),j=1,2,...n-4 such that c -c (1) sumi((wi*(yi-sumj(cj*nj(xi))))**2),i=1,2,...m is minimal c -c (2) sumj(cj*n''j(t(l+3)))*e(l) <= 0, l=1,2,...n-6. c -c to solve this problem we use the theil-van de panne procedure. c -c if the inequality constraints (2) are numbered from 1 to n-6, c -c this algorithm finds a subset of constraints ibind(1)..ibind(nbind) c -c such that the solution of the minimization problem (1) with these c -c constraints in equality form, satisfies all constraints. such a c -c feasible solution is optimal if the lagrange parameters associated c -c with that problem with equality constraints, are all positive. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c determine n6, the number of inequality constraints. - n6 = n-6 -c fix the parameters which determine these constraints. - do 10 i=1,n6 - const(i) = e(i)*(t(i+4)-t(i+1))/(t(i+5)-t(i+2)) - 10 continue -c initialize the triply linked tree which is used to find the subset -c of constraints ibind(1),...ibind(nbind). - count = 1 - info(1) = 0 - left(1) = 0 - right(1) = 0 - up(1) = 1 - merk = 1 -c set up the normal equations n'nc=n'y where n denotes the m x (n-4) -c observation matrix with elements ni,j = wi*nj(xi) and y is the -c column vector with elements yi*wi. -c from the properties of the b-splines nj(x),j=1,2,...n-4, it follows -c that n'n is a (n-4) x (n-4) positive definit bandmatrix of -c bandwidth 7. the matrices n'n and n'y are built up in a and z. - n4 = n-4 -c initialization - do 20 i=1,n4 - z(i) = 0. - do 20 j=1,4 - a(i,j) = 0. - 20 continue - l = 4 - lp1 = l+1 - do 70 i=1,m -c fetch the current row of the observation matrix. - xi = x(i) - wi = w(i)**2 -c search for knot interval t(l) <= xi < t(l+1) - 30 if(xi.lt.t(lp1) .or. l.eq.n4) go to 40 - l = lp1 - lp1 = l+1 - go to 30 -c evaluate the four non-zero cubic b-splines nj(xi),j=l-3,...l. - 40 call fpbspl(t,n,3,xi,l,h) -c store in q these values h(1),h(2),...h(4). - do 50 j=1,4 - q(i,j) = h(j) - 50 continue -c add the contribution of the current row of the observation matrix -c n to the normal equations. - l3 = l-3 - k1 = 0 - do 60 j1 = l3,l - k1 = k1+1 - f = h(k1) - z(j1) = z(j1)+f*wi*y(i) - k2 = k1 - j2 = 4 - do 60 j3 = j1,l - a(j3,j2) = a(j3,j2)+f*wi*h(k2) - k2 = k2+1 - j2 = j2-1 - 60 continue - 70 continue -c since n'n is a symmetric matrix it can be factorized as -c (3) n'n = (r1)'(d1)(r1) -c with d1 a diagonal matrix and r1 an (n-4) x (n-4) unit upper -c triangular matrix of bandwidth 4. the matrices r1 and d1 are built -c up in a. at the same time we solve the systems of equations -c (4) (r1)'(z2) = n'y -c (5) (d1) (z1) = (z2) -c the vectors z2 and z1 are kept in zz and z. - do 140 i=1,n4 - k1 = 1 - if(i.lt.4) k1 = 5-i - k2 = i-4+k1 - k3 = k2 - do 100 j=k1,4 - k4 = j-1 - k5 = 4-j+k1 - f = a(i,j) - if(k1.gt.k4) go to 90 - k6 = k2 - do 80 k=k1,k4 - f = f-a(i,k)*a(k3,k5)*a(k6,4) - k5 = k5+1 - k6 = k6+1 - 80 continue - 90 if(j.eq.4) go to 110 - a(i,j) = f/a(k3,4) - k3 = k3+1 - 100 continue - 110 a(i,4) = f - f = z(i) - if(i.eq.1) go to 130 - k4 = i - do 120 j=k1,3 - k = k1+3-j - k4 = k4-1 - f = f-a(i,k)*z(k4)*a(k4,4) - 120 continue - 130 z(i) = f/a(i,4) - zz(i) = f - 140 continue -c start computing the least-squares cubic spline without taking account -c of any constraint. - nbind = 0 - n1 = 1 - ibind(1) = 0 -c main loop for the least-squares problems with different subsets of -c the constraints (2) in equality form. the resulting b-spline coeff. -c c and lagrange parameters u are the solution of the system -c ! n'n b' ! ! c ! ! n'y ! -c (6) ! ! ! ! = ! ! -c ! b 0 ! ! u ! ! 0 ! -c z1 is stored into array c. - 150 do 160 i=1,n4 - c(i) = z(i) - 160 continue -c if there are no equality constraints, compute the coeff. c directly. - if(nbind.eq.0) go to 370 -c initialization - kdim = n4+nbind - do 170 i=1,nbind - do 170 j=1,kdim - b(j,i) = 0. - 170 continue -c matrix b is built up,expressing that the constraints nrs ibind(1),... -c ibind(nbind) must be satisfied in equality form. - do 180 i=1,nbind - l = ibind(i) - b(l,i) = e(l) - b(l+1,i) = -(e(l)+const(l)) - b(l+2,i) = const(l) - 180 continue -c find the matrix (b1) as the solution of the system of equations -c (7) (r1)'(d1)(b1) = b' -c (b1) is built up in the upper part of the array b(rows 1,...n-4). - do 220 k1=1,nbind - l = ibind(k1) - do 210 i=l,n4 - f = b(i,k1) - if(i.eq.1) go to 200 - k2 = 3 - if(i.lt.4) k2 = i-1 - do 190 k3=1,k2 - l1 = i-k3 - l2 = 4-k3 - f = f-b(l1,k1)*a(i,l2)*a(l1,4) - 190 continue - 200 b(i,k1) = f/a(i,4) - 210 continue - 220 continue -c factorization of the symmetric matrix -(b1)'(d1)(b1) -c (8) -(b1)'(d1)(b1) = (r2)'(d2)(r2) -c with (d2) a diagonal matrix and (r2) an nbind x nbind unit upper -c triangular matrix. the matrices r2 and d2 are built up in the lower -c part of the array b (rows n-3,n-2,...n-4+nbind). - do 270 i=1,nbind - i1 = i-1 - do 260 j=i,nbind - f = 0. - do 230 k=1,n4 - f = f+b(k,i)*b(k,j)*a(k,4) - 230 continue - k1 = n4+1 - if(i1.eq.0) go to 250 - do 240 k=1,i1 - f = f+b(k1,i)*b(k1,j)*b(k1,k) - k1 = k1+1 - 240 continue - 250 b(k1,j) = -f - if(j.eq.i) go to 260 - b(k1,j) = b(k1,j)/b(k1,i) - 260 continue - 270 continue -c according to (3),(7) and (8) the system of equations (6) becomes -c ! (r1)' 0 ! ! (d1) 0 ! ! (r1) (b1) ! ! c ! ! n'y ! -c (9) ! ! ! ! ! ! ! ! = ! ! -c ! (b1)' (r2)'! ! 0 (d2) ! ! 0 (r2) ! ! u ! ! 0 ! -c backward substitution to obtain the b-spline coefficients c(j),j=1,.. -c n-4 and the lagrange parameters u(j),j=1,2,...nbind. -c first step of the backward substitution: solve the system -c ! (r1)'(d1) 0 ! ! (c1) ! ! n'y ! -c (10) ! ! ! ! = ! ! -c ! (b1)'(d1) (r2)'(d2) ! ! (u1) ! ! 0 ! -c from (4) and (5) we know that this is equivalent to -c (11) (c1) = (z1) -c (12) (r2)'(d2)(u1) = -(b1)'(z2) - do 310 i=1,nbind - f = 0. - do 280 j=1,n4 - f = f+b(j,i)*zz(j) - 280 continue - i1 = i-1 - k1 = n4+1 - if(i1.eq.0) go to 300 - do 290 j=1,i1 - f = f+u(j)*b(k1,i)*b(k1,j) - k1 = k1+1 - 290 continue - 300 u(i) = -f/b(k1,i) - 310 continue -c second step of the backward substitution: solve the system -c ! (r1) (b1) ! ! c ! ! c1 ! -c (13) ! ! ! ! = ! ! -c ! 0 (r2) ! ! u ! ! u1 ! - k1 = nbind - k2 = kdim -c find the lagrange parameters u. - do 340 i=1,nbind - f = u(k1) - if(i.eq.1) go to 330 - k3 = k1+1 - do 320 j=k3,nbind - f = f-u(j)*b(k2,j) - 320 continue - 330 u(k1) = f - k1 = k1-1 - k2 = k2-1 - 340 continue -c find the b-spline coefficients c. - do 360 i=1,n4 - f = c(i) - do 350 j=1,nbind - f = f-u(j)*b(i,j) - 350 continue - c(i) = f - 360 continue - 370 k1 = n4 - do 390 i=2,n4 - k1 = k1-1 - f = c(k1) - k2 = 1 - if(i.lt.5) k2 = 5-i - k3 = k1 - l = 3 - do 380 j=k2,3 - k3 = k3+1 - f = f-a(k3,l)*c(k3) - l = l-1 - 380 continue - c(k1) = f - 390 continue -c test whether the solution of the least-squares problem with the -c constraints ibind(1),...ibind(nbind) in equality form, satisfies -c all of the constraints (2). - k = 1 -c number counts the number of violated inequality constraints. - number = 0 - do 440 j=1,n6 - l = ibind(k) - k = k+1 - if(j.eq.l) go to 440 - k = k-1 -c test whether constraint j is satisfied - f = e(j)*(c(j)-c(j+1))+const(j)*(c(j+2)-c(j+1)) - if(f.le.0.) go to 440 -c if constraint j is not satisfied, add a branch of length nbind+1 -c to the tree. the nodes of this branch contain in their information -c field the number of the constraints ibind(1),...ibind(nbind) and j, -c arranged in increasing order. - number = number+1 - k1 = k-1 - if(k1.eq.0) go to 410 - do 400 i=1,k1 - jbind(i) = ibind(i) - 400 continue - 410 jbind(k) = j - if(l.eq.0) go to 430 - do 420 i=k,nbind - jbind(i+1) = ibind(i) - 420 continue - 430 call fpadno(maxtr,up,left,right,info,count,merk,jbind,n1,ier) -c test whether the storage space which is required for the tree,exceeds -c the available storage space. - if(ier.ne.0) go to 560 - 440 continue -c test whether the solution of the least-squares problem with equality -c constraints is a feasible solution. - if(number.eq.0) go to 470 -c test whether there are still cases with nbind constraints in -c equality form to be considered. - 450 if(merk.gt.1) go to 460 - nbind = n1 -c test whether the number of knots where s''(x)=0 exceeds maxbin. - if(nbind.gt.maxbin) go to 550 - n1 = n1+1 - ibind(n1) = 0 -c search which cases with nbind constraints in equality form -c are going to be considered. - call fpdeno(maxtr,up,left,right,nbind,merk) -c test whether the quadratic programming problem has a solution. - if(merk.eq.1) go to 570 -c find a new case with nbind constraints in equality form. - 460 call fpseno(maxtr,up,left,right,info,merk,ibind,nbind) - go to 150 -c test whether the feasible solution is optimal. - 470 ier = 0 - do 480 i=1,n6 - bind(i) = .false. - 480 continue - if(nbind.eq.0) go to 500 - do 490 i=1,nbind - if(u(i).le.0.) go to 450 - j = ibind(i) - bind(j) = .true. - 490 continue -c evaluate s(x) at the data points x(i) and calculate the weighted -c sum of squared residual right hand sides sq. - 500 sq = 0. - l = 4 - lp1 = 5 - do 530 i=1,m - 510 if(x(i).lt.t(lp1) .or. l.eq.n4) go to 520 - l = lp1 - lp1 = l+1 - go to 510 - 520 sx(i) = c(l-3)*q(i,1)+c(l-2)*q(i,2)+c(l-1)*q(i,3)+c(l)*q(i,4) - sq = sq+(w(i)*(y(i)-sx(i)))**2 - 530 continue - go to 600 -c error codes and messages. - 550 ier = 1 - go to 600 - 560 ier = 2 - go to 600 - 570 ier = 3 - 600 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpcsin.f =================================================================== --- branches/Interpolate1D/fitpack/fpcsin.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpcsin.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,56 +0,0 @@ - subroutine fpcsin(a,b,par,sia,coa,sib,cob,ress,resc) -c fpcsin calculates the integrals ress=integral((b-x)**3*sin(par*x)) -c and resc=integral((b-x)**3*cos(par*x)) over the interval (a,b), -c given sia=sin(par*a),coa=cos(par*a),sib=sin(par*b) and cob=cos(par*b) -c .. -c ..scalar arguments.. - real*8 a,b,par,sia,coa,sib,cob,ress,resc -c ..local scalars.. - integer i,j - real*8 ab,ab4,ai,alfa,beta,b2,b4,eps,fac,f1,f2,one,quart,six, - * three,two -c ..function references.. - real*8 abs -c .. - one = 0.1e+01 - two = 0.2e+01 - three = 0.3e+01 - six = 0.6e+01 - quart = 0.25e+0 - eps = 0.1e-09 - ab = b-a - ab4 = ab**4 - alfa = ab*par -c the way of calculating the integrals ress and resc depends on -c the value of alfa = (b-a)*par. - if(abs(alfa).le.one) go to 100 -c integration by parts. - beta = one/alfa - b2 = beta**2 - b4 = six*b2**2 - f1 = three*b2*(one-two*b2) - f2 = beta*(one-six*b2) - ress = ab4*(coa*f2+sia*f1+sib*b4) - resc = ab4*(coa*f1-sia*f2+cob*b4) - go to 400 -c ress and resc are found by evaluating a series expansion. - 100 fac = quart - f1 = fac - f2 = 0. - i = 4 - do 200 j=1,5 - i = i+1 - ai = i - fac = fac*alfa/ai - f2 = f2+fac - if(abs(fac).le.eps) go to 300 - i = i+1 - ai = i - fac = -fac*alfa/ai - f1 = f1+fac - if(abs(fac).le.eps) go to 300 - 200 continue - 300 ress = ab4*(coa*f2+sia*f1) - resc = ab4*(coa*f1-sia*f2) - 400 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpcurf.f =================================================================== --- branches/Interpolate1D/fitpack/fpcurf.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpcurf.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,359 +0,0 @@ - subroutine fpcurf(iopt,x,y,w,m,xb,xe,k,s,nest,tol,maxit,k1,k2, - * n,t,c,fp,fpint,z,a,b,g,q,nrdata,ier) -c .. -c ..scalar arguments.. - real*8 xb,xe,s,tol,fp - integer iopt,m,k,nest,maxit,k1,k2,n,ier -c ..array arguments.. - real*8 x(m),y(m),w(m),t(nest),c(nest),fpint(nest), - * z(nest),a(nest,k1),b(nest,k2),g(nest,k2),q(m,k1) - integer nrdata(nest) -c ..local scalars.. - real*8 acc,con1,con4,con9,cos,half,fpart,fpms,fpold,fp0,f1,f2,f3, - * one,p,pinv,piv,p1,p2,p3,rn,sin,store,term,wi,xi,yi - integer i,ich1,ich3,it,iter,i1,i2,i3,j,k3,l,l0, - * mk1,new,nk1,nmax,nmin,nplus,npl1,nrint,n8 -c ..local arrays.. - real*8 h(7) -c ..function references - real*8 abs,fprati - integer max0,min0 -c ..subroutine references.. -c fpback,fpbspl,fpgivs,fpdisc,fpknot,fprota -c .. -c set constants - one = 0.1d+01 - con1 = 0.1d0 - con9 = 0.9d0 - con4 = 0.4d-01 - half = 0.5d0 -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 1: determination of the number of knots and their position c -c ************************************************************** c -c given a set of knots we compute the least-squares spline sinf(x), c -c and the corresponding sum of squared residuals fp=f(p=inf). c -c if iopt=-1 sinf(x) is the requested approximation. c -c if iopt=0 or iopt=1 we check whether we can accept the knots: c -c if fp <=s we will continue with the current set of knots. c -c if fp > s we will increase the number of knots and compute the c -c corresponding least-squares spline until finally fp<=s. c -c the initial choice of knots depends on the value of s and iopt. c -c if s=0 we have spline interpolation; in that case the number of c -c knots equals nmax = m+k+1. c -c if s > 0 and c -c iopt=0 we first compute the least-squares polynomial of c -c degree k; n = nmin = 2*k+2 c -c iopt=1 we start with the set of knots found at the last c -c call of the routine, except for the case that s > fp0; then c -c we compute directly the least-squares polynomial of degree k. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c determine nmin, the number of knots for polynomial approximation. - nmin = 2*k1 - if(iopt.lt.0) go to 60 -c calculation of acc, the absolute tolerance for the root of f(p)=s. - acc = tol*s -c determine nmax, the number of knots for spline interpolation. - nmax = m+k1 - if(s.gt.0.0d0) go to 45 -c if s=0, s(x) is an interpolating spline. -c test whether the required storage space exceeds the available one. - n = nmax - if(nmax.gt.nest) go to 420 -c find the position of the interior knots in case of interpolation. - 10 mk1 = m-k1 - if(mk1.eq.0) go to 60 - k3 = k/2 - i = k2 - j = k3+2 - if(k3*2.eq.k) go to 30 - do 20 l=1,mk1 - t(i) = x(j) - i = i+1 - j = j+1 - 20 continue - go to 60 - 30 do 40 l=1,mk1 - t(i) = (x(j)+x(j-1))*half - i = i+1 - j = j+1 - 40 continue - go to 60 -c if s>0 our initial choice of knots depends on the value of iopt. -c if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares -c polynomial of degree k which is a spline without interior knots. -c if iopt=1 and fp0>s we start computing the least squares spline -c according to the set of knots found at the last call of the routine. - 45 if(iopt.eq.0) go to 50 - if(n.eq.nmin) go to 50 - fp0 = fpint(n) - fpold = fpint(n-1) - nplus = nrdata(n) - if(fp0.gt.s) go to 60 - 50 n = nmin - fpold = 0.0d0 - nplus = 0 - nrdata(1) = m-2 -c main loop for the different sets of knots. m is a save upper bound -c for the number of trials. - 60 do 200 iter = 1,m - if(n.eq.nmin) ier = -2 -c find nrint, tne number of knot intervals. - nrint = n-nmin+1 -c find the position of the additional knots which are needed for -c the b-spline representation of s(x). - nk1 = n-k1 - i = n - do 70 j=1,k1 - t(j) = xb - t(i) = xe - i = i-1 - 70 continue -c compute the b-spline coefficients of the least-squares spline -c sinf(x). the observation matrix a is built up row by row and -c reduced to upper triangular form by givens transformations. -c at the same time fp=f(p=inf) is computed. - fp = 0.0d0 -c initialize the observation matrix a. - do 80 i=1,nk1 - z(i) = 0.0d0 - do 80 j=1,k1 - a(i,j) = 0.0d0 - 80 continue - l = k1 - do 130 it=1,m -c fetch the current data point x(it),y(it). - xi = x(it) - wi = w(it) - yi = y(it)*wi -c search for knot interval t(l) <= xi < t(l+1). - 85 if(xi.lt.t(l+1) .or. l.eq.nk1) go to 90 - l = l+1 - go to 85 -c evaluate the (k+1) non-zero b-splines at xi and store them in q. - 90 call fpbspl(t,n,k,xi,l,h) - do 95 i=1,k1 - q(it,i) = h(i) - h(i) = h(i)*wi - 95 continue -c rotate the new row of the observation matrix into triangle. - j = l-k1 - do 110 i=1,k1 - j = j+1 - piv = h(i) - if(piv.eq.0.0d0) go to 110 -c calculate the parameters of the givens transformation. - call fpgivs(piv,a(j,1),cos,sin) -c transformations to right hand side. - call fprota(cos,sin,yi,z(j)) - if(i.eq.k1) go to 120 - i2 = 1 - i3 = i+1 - do 100 i1 = i3,k1 - i2 = i2+1 -c transformations to left hand side. - call fprota(cos,sin,h(i1),a(j,i2)) - 100 continue - 110 continue -c add contribution of this row to the sum of squares of residual -c right hand sides. - 120 fp = fp+yi*yi - 130 continue - if(ier.eq.(-2)) fp0 = fp - fpint(n) = fp0 - fpint(n-1) = fpold - nrdata(n) = nplus -c backward substitution to obtain the b-spline coefficients. - call fpback(a,z,nk1,k1,c,nest) -c test whether the approximation sinf(x) is an acceptable solution. - if(iopt.lt.0) go to 440 - fpms = fp-s - if(abs(fpms).lt.acc) go to 440 -c if f(p=inf) < s accept the choice of knots. - if(fpms.lt.0.0d0) go to 250 -c if n = nmax, sinf(x) is an interpolating spline. - if(n.eq.nmax) go to 430 -c increase the number of knots. -c if n=nest we cannot increase the number of knots because of -c the storage capacity limitation. - if(n.eq.nest) go to 420 -c determine the number of knots nplus we are going to add. - if(ier.eq.0) go to 140 - nplus = 1 - ier = 0 - go to 150 - 140 npl1 = nplus*2 - rn = nplus - if(fpold-fp.gt.acc) npl1 = rn*fpms/(fpold-fp) - nplus = min0(nplus*2,max0(npl1,nplus/2,1)) - 150 fpold = fp -c compute the sum((w(i)*(y(i)-s(x(i))))**2) for each knot interval -c t(j+k) <= x(i) <= t(j+k+1) and store it in fpint(j),j=1,2,...nrint. - fpart = 0.0d0 - i = 1 - l = k2 - new = 0 - do 180 it=1,m - if(x(it).lt.t(l) .or. l.gt.nk1) go to 160 - new = 1 - l = l+1 - 160 term = 0.0d0 - l0 = l-k2 - do 170 j=1,k1 - l0 = l0+1 - term = term+c(l0)*q(it,j) - 170 continue - term = (w(it)*(term-y(it)))**2 - fpart = fpart+term - if(new.eq.0) go to 180 - store = term*half - fpint(i) = fpart-store - i = i+1 - fpart = store - new = 0 - 180 continue - fpint(nrint) = fpart - do 190 l=1,nplus -c add a new knot. - call fpknot(x,m,t,n,fpint,nrdata,nrint,nest,1) -c if n=nmax we locate the knots as for interpolation. - if(n.eq.nmax) go to 10 -c test whether we cannot further increase the number of knots. - if(n.eq.nest) go to 200 - 190 continue -c restart the computations with the new set of knots. - 200 continue -c test whether the least-squares kth degree polynomial is a solution -c of our approximation problem. - 250 if(ier.eq.(-2)) go to 440 -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 2: determination of the smoothing spline sp(x). c -c *************************************************** c -c we have determined the number of knots and their position. c -c we now compute the b-spline coefficients of the smoothing spline c -c sp(x). the observation matrix a is extended by the rows of matrix c -c b expressing that the kth derivative discontinuities of sp(x) at c -c the interior knots t(k+2),...t(n-k-1) must be zero. the corres- c -c ponding weights of these additional rows are set to 1/p. c -c iteratively we then have to determine the value of p such that c -c f(p)=sum((w(i)*(y(i)-sp(x(i))))**2) be = s. we already know that c -c the least-squares kth degree polynomial corresponds to p=0, and c -c that the least-squares spline corresponds to p=infinity. the c -c iteration process which is proposed here, makes use of rational c -c interpolation. since f(p) is a convex and strictly decreasing c -c function of p, it can be approximated by a rational function c -c r(p) = (u*p+v)/(p+w). three values of p(p1,p2,p3) with correspond- c -c ing values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used c -c to calculate the new value of p such that r(p)=s. convergence is c -c guaranteed by taking f1>0 and f3<0. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c evaluate the discontinuity jump of the kth derivative of the -c b-splines at the knots t(l),l=k+2,...n-k-1 and store in b. - call fpdisc(t,n,k2,b,nest) -c initial value for p. - p1 = 0.0d0 - f1 = fp0-s - p3 = -one - f3 = fpms - p = 0. - do 255 i=1,nk1 - p = p+a(i,1) - 255 continue - rn = nk1 - p = rn/p - ich1 = 0 - ich3 = 0 - n8 = n-nmin -c iteration process to find the root of f(p) = s. - do 360 iter=1,maxit -c the rows of matrix b with weight 1/p are rotated into the -c triangularised observation matrix a which is stored in g. - pinv = one/p - do 260 i=1,nk1 - c(i) = z(i) - g(i,k2) = 0.0d0 - do 260 j=1,k1 - g(i,j) = a(i,j) - 260 continue - do 300 it=1,n8 -c the row of matrix b is rotated into triangle by givens transformation - do 270 i=1,k2 - h(i) = b(it,i)*pinv - 270 continue - yi = 0.0d0 - do 290 j=it,nk1 - piv = h(1) -c calculate the parameters of the givens transformation. - call fpgivs(piv,g(j,1),cos,sin) -c transformations to right hand side. - call fprota(cos,sin,yi,c(j)) - if(j.eq.nk1) go to 300 - i2 = k1 - if(j.gt.n8) i2 = nk1-j - do 280 i=1,i2 -c transformations to left hand side. - i1 = i+1 - call fprota(cos,sin,h(i1),g(j,i1)) - h(i) = h(i1) - 280 continue - h(i2+1) = 0.0d0 - 290 continue - 300 continue -c backward substitution to obtain the b-spline coefficients. - call fpback(g,c,nk1,k2,c,nest) -c computation of f(p). - fp = 0.0d0 - l = k2 - do 330 it=1,m - if(x(it).lt.t(l) .or. l.gt.nk1) go to 310 - l = l+1 - 310 l0 = l-k2 - term = 0.0d0 - do 320 j=1,k1 - l0 = l0+1 - term = term+c(l0)*q(it,j) - 320 continue - fp = fp+(w(it)*(term-y(it)))**2 - 330 continue -c test whether the approximation sp(x) is an acceptable solution. - fpms = fp-s - if(abs(fpms).lt.acc) go to 440 -c test whether the maximal number of iterations is reached. - if(iter.eq.maxit) go to 400 -c carry out one more step of the iteration process. - p2 = p - f2 = fpms - if(ich3.ne.0) go to 340 - if((f2-f3).gt.acc) go to 335 -c our initial choice of p is too large. - p3 = p2 - f3 = f2 - p = p*con4 - if(p.le.p1) p=p1*con9 + p2*con1 - go to 360 - 335 if(f2.lt.0.0d0) ich3=1 - 340 if(ich1.ne.0) go to 350 - if((f1-f2).gt.acc) go to 345 -c our initial choice of p is too small - p1 = p2 - f1 = f2 - p = p/con4 - if(p3.lt.0.) go to 360 - if(p.ge.p3) p = p2*con1 + p3*con9 - go to 360 - 345 if(f2.gt.0.0d0) ich1=1 -c test whether the iteration process proceeds as theoretically -c expected. - 350 if(f2.ge.f1 .or. f2.le.f3) go to 410 -c find the new value for p. - p = fprati(p1,f1,p2,f2,p3,f3) - 360 continue -c error codes and messages. - 400 ier = 3 - go to 440 - 410 ier = 2 - go to 440 - 420 ier = 1 - go to 440 - 430 ier = -1 - 440 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpcuro.f =================================================================== --- branches/Interpolate1D/fitpack/fpcuro.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpcuro.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,94 +0,0 @@ - subroutine fpcuro(a,b,c,d,x,n) -c subroutine fpcuro finds the real zeros of a cubic polynomial -c p(x) = a*x**3+b*x**2+c*x+d. -c -c calling sequence: -c call fpcuro(a,b,c,d,x,n) -c -c input parameters: -c a,b,c,d: real values, containing the coefficients of p(x). -c -c output parameters: -c x : real array,length 3, which contains the real zeros of p(x) -c n : integer, giving the number of real zeros of p(x). -c .. -c ..scalar arguments.. - real*8 a,b,c,d - integer n -c ..array argument.. - real*8 x(3) -c ..local scalars.. - integer i - real*8 a1,b1,c1,df,disc,d1,e3,f,four,half,ovfl,pi3,p3,q,r, - * step,tent,three,two,u,u1,u2,y -c ..function references.. - real*8 abs,max,datan,atan2,cos,sign,sqrt -c set constants - two = 0.2d+01 - three = 0.3d+01 - four = 0.4d+01 - ovfl =0.1d+05 - half = 0.5d+0 - tent = 0.1d+0 - e3 = tent/0.3d0 - pi3 = datan(0.1d+01)/0.75d0 - a1 = abs(a) - b1 = abs(b) - c1 = abs(c) - d1 = abs(d) -c test whether p(x) is a third degree polynomial. - if(max(b1,c1,d1).lt.a1*ovfl) go to 300 -c test whether p(x) is a second degree polynomial. - if(max(c1,d1).lt.b1*ovfl) go to 200 -c test whether p(x) is a first degree polynomial. - if(d1.lt.c1*ovfl) go to 100 -c p(x) is a constant function. - n = 0 - go to 800 -c p(x) is a first degree polynomial. - 100 n = 1 - x(1) = -d/c - go to 500 -c p(x) is a second degree polynomial. - 200 disc = c*c-four*b*d - n = 0 - if(disc.lt.0.) go to 800 - n = 2 - u = sqrt(disc) - b1 = b+b - x(1) = (-c+u)/b1 - x(2) = (-c-u)/b1 - go to 500 -c p(x) is a third degree polynomial. - 300 b1 = b/a*e3 - c1 = c/a - d1 = d/a - q = c1*e3-b1*b1 - r = b1*b1*b1+(d1-b1*c1)*half - disc = q*q*q+r*r - if(disc.gt.0.) go to 400 - u = sqrt(abs(q)) - if(r.lt.0.) u = -u - p3 = atan2(sqrt(-disc),abs(r))*e3 - u2 = u+u - n = 3 - x(1) = -u2*cos(p3)-b1 - x(2) = u2*cos(pi3-p3)-b1 - x(3) = u2*cos(pi3+p3)-b1 - go to 500 - 400 u = sqrt(disc) - u1 = -r+u - u2 = -r-u - n = 1 - x(1) = sign(abs(u1)**e3,u1)+sign(abs(u2)**e3,u2)-b1 -c apply a newton iteration to improve the accuracy of the roots. - 500 do 700 i=1,n - y = x(i) - f = ((a*y+b)*y+c)*y+d - df = (three*a*y+two*b)*y+c - step = 0. - if(abs(f).lt.abs(df)*tent) step = f/df - x(i) = y-step - 700 continue - 800 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpcyt1.f =================================================================== --- branches/Interpolate1D/fitpack/fpcyt1.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpcyt1.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,53 +0,0 @@ - subroutine fpcyt1(a,n,nn) -c (l u)-decomposition of a cyclic tridiagonal matrix with the non-zero -c elements stored as follows -c -c | a(1,2) a(1,3) a(1,1) | -c | a(2,1) a(2,2) a(2,3) | -c | a(3,1) a(3,2) a(3,3) | -c | ............... | -c | a(n-1,1) a(n-1,2) a(n-1,3) | -c | a(n,3) a(n,1) a(n,2) | -c -c .. -c ..scalar arguments.. - integer n,nn -c ..array arguments.. - real*8 a(nn,6) -c ..local scalars.. - real*8 aa,beta,gamma,sum,teta,v,one - integer i,n1,n2 -c .. -c set constant - one = 1 - n2 = n-2 - beta = one/a(1,2) - gamma = a(n,3) - teta = a(1,1)*beta - a(1,4) = beta - a(1,5) = gamma - a(1,6) = teta - sum = gamma*teta - do 10 i=2,n2 - v = a(i-1,3)*beta - aa = a(i,1) - beta = one/(a(i,2)-aa*v) - gamma = -gamma*v - teta = -teta*aa*beta - a(i,4) = beta - a(i,5) = gamma - a(i,6) = teta - sum = sum+gamma*teta - 10 continue - n1 = n-1 - v = a(n2,3)*beta - aa = a(n1,1) - beta = one/(a(n1,2)-aa*v) - gamma = a(n,1)-gamma*v - teta = (a(n1,3)-teta*aa)*beta - a(n1,4) = beta - a(n1,5) = gamma - a(n1,6) = teta - a(n,4) = one/(a(n,2)-(sum+gamma*teta)) - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpcyt2.f =================================================================== --- branches/Interpolate1D/fitpack/fpcyt2.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpcyt2.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,32 +0,0 @@ - subroutine fpcyt2(a,n,b,c,nn) -c subroutine fpcyt2 solves a linear n x n system -c a * c = b -c where matrix a is a cyclic tridiagonal matrix, decomposed -c using subroutine fpsyt1. -c .. -c ..scalar arguments.. - integer n,nn -c ..array arguments.. - real*8 a(nn,6),b(n),c(n) -c ..local scalars.. - real*8 cc,sum - integer i,j,j1,n1 -c .. - c(1) = b(1)*a(1,4) - sum = c(1)*a(1,5) - n1 = n-1 - do 10 i=2,n1 - c(i) = (b(i)-a(i,1)*c(i-1))*a(i,4) - sum = sum+c(i)*a(i,5) - 10 continue - cc = (b(n)-sum)*a(n,4) - c(n) = cc - c(n1) = c(n1)-cc*a(n1,6) - j = n1 - do 20 i=3,n - j1 = j-1 - c(j1) = c(j1)-c(j)*a(j1,3)*a(j1,4)-cc*a(j1,6) - j = j1 - 20 continue - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpdeno.f =================================================================== --- branches/Interpolate1D/fitpack/fpdeno.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpdeno.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,55 +0,0 @@ - subroutine fpdeno(maxtr,up,left,right,nbind,merk) -c subroutine fpdeno frees the nodes of all branches of a triply linked -c tree with length < nbind by putting to zero their up field. -c on exit the parameter merk points to the terminal node of the -c most left branch of length nbind or takes the value 1 if there -c is no such branch. -c .. -c ..scalar arguments.. - integer maxtr,nbind,merk -c ..array arguments.. - integer up(maxtr),left(maxtr),right(maxtr) -c ..local scalars .. - integer i,j,k,l,niveau,point -c .. - i = 1 - niveau = 0 - 10 point = i - i = left(point) - if(i.eq.0) go to 20 - niveau = niveau+1 - go to 10 - 20 if(niveau.eq.nbind) go to 70 - 30 i = right(point) - j = up(point) - up(point) = 0 - k = left(j) - if(point.ne.k) go to 50 - if(i.ne.0) go to 40 - niveau = niveau-1 - if(niveau.eq.0) go to 80 - point = j - go to 30 - 40 left(j) = i - go to 10 - 50 l = right(k) - if(point.eq.l) go to 60 - k = l - go to 50 - 60 right(k) = i - point = k - 70 i = right(point) - if(i.ne.0) go to 10 - i = up(point) - niveau = niveau-1 - if(niveau.eq.0) go to 80 - point = i - go to 70 - 80 k = 1 - l = left(k) - if(up(l).eq.0) return - 90 merk = k - k = left(k) - if(k.ne.0) go to 90 - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpdisc.f =================================================================== --- branches/Interpolate1D/fitpack/fpdisc.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpdisc.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,43 +0,0 @@ - subroutine fpdisc(t,n,k2,b,nest) -c subroutine fpdisc calculates the discontinuity jumps of the kth -c derivative of the b-splines of degree k at the knots t(k+2)..t(n-k-1) -c ..scalar arguments.. - integer n,k2,nest -c ..array arguments.. - real*8 t(n),b(nest,k2) -c ..local scalars.. - real*8 an,fac,prod - integer i,ik,j,jk,k,k1,l,lj,lk,lmk,lp,nk1,nrint -c ..local array.. - real*8 h(12) -c .. - k1 = k2-1 - k = k1-1 - nk1 = n-k1 - nrint = nk1-k - an = nrint - fac = an/(t(nk1+1)-t(k1)) - do 40 l=k2,nk1 - lmk = l-k1 - do 10 j=1,k1 - ik = j+k1 - lj = l+j - lk = lj-k2 - h(j) = t(l)-t(lk) - h(ik) = t(l)-t(lj) - 10 continue - lp = lmk - do 30 j=1,k2 - jk = j - prod = h(j) - do 20 i=1,k - jk = jk+1 - prod = prod*h(jk)*fac - 20 continue - lk = lp+k1 - b(lmk,j) = (t(lk)-t(lp))/prod - lp = lp+1 - 30 continue - 40 continue - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpfrno.f =================================================================== --- branches/Interpolate1D/fitpack/fpfrno.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpfrno.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,69 +0,0 @@ - subroutine fpfrno(maxtr,up,left,right,info,point,merk,n1, - * count,ier) -c subroutine fpfrno collects the free nodes (up field zero) of the -c triply linked tree the information of which is kept in the arrays -c up,left,right and info. the maximal length of the branches of the -c tree is given by n1. if no free nodes are found, the error flag -c ier is set to 1. -c .. -c ..scalar arguments.. - integer maxtr,point,merk,n1,count,ier -c ..array arguments.. - integer up(maxtr),left(maxtr),right(maxtr),info(maxtr) -c ..local scalars - integer i,j,k,l,n,niveau -c .. - ier = 1 - if(n1.eq.2) go to 140 - niveau = 1 - count = 2 - 10 j = 0 - i = 1 - 20 if(j.eq.niveau) go to 30 - k = 0 - l = left(i) - if(l.eq.0) go to 110 - i = l - j = j+1 - go to 20 - 30 if (i.lt.count) go to 110 - if (i.eq.count) go to 100 - go to 40 - 40 if(up(count).eq.0) go to 50 - count = count+1 - go to 30 - 50 up(count) = up(i) - left(count) = left(i) - right(count) = right(i) - info(count) = info(i) - if(merk.eq.i) merk = count - if(point.eq.i) point = count - if(k.eq.0) go to 60 - right(k) = count - go to 70 - 60 n = up(i) - left(n) = count - 70 l = left(i) - 80 if(l.eq.0) go to 90 - up(l) = count - l = right(l) - go to 80 - 90 up(i) = 0 - i = count - 100 count = count+1 - 110 l = right(i) - k = i - if(l.eq.0) go to 120 - i = l - go to 20 - 120 l = up(i) - j = j-1 - if(j.eq.0) go to 130 - i = l - go to 110 - 130 niveau = niveau+1 - if(niveau.le.n1) go to 10 - if(count.gt.maxtr) go to 140 - ier = 0 - 140 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpgivs.f =================================================================== --- branches/Interpolate1D/fitpack/fpgivs.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpgivs.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,20 +0,0 @@ - subroutine fpgivs(piv,ww,cos,sin) -c subroutine fpgivs calculates the parameters of a givens -c transformation . -c .. -c ..scalar arguments.. - real*8 piv,ww,cos,sin -c ..local scalars.. - real*8 dd,one,store -c ..function references.. - real*8 abs,sqrt -c .. - one = 0.1e+01 - store = abs(piv) - if(store.ge.ww) dd = store*sqrt(one+(ww/piv)**2) - if(store.lt.ww) dd = ww*sqrt(one+(piv/ww)**2) - cos = ww/dd - sin = piv/dd - ww = dd - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpgrdi.f =================================================================== --- branches/Interpolate1D/fitpack/fpgrdi.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpgrdi.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,600 +0,0 @@ - subroutine fpgrdi(ifsu,ifsv,ifbu,ifbv,iback,u,mu,v,mv,z,mz,dz, - * iop0,iop1,tu,nu,tv,nv,p,c,nc,sq,fp,fpu,fpv,mm,mvnu,spu,spv, - * right,q,au,av1,av2,bu,bv,aa,bb,cc,cosi,nru,nrv) -c .. -c ..scalar arguments.. - real*8 p,sq,fp - integer ifsu,ifsv,ifbu,ifbv,iback,mu,mv,mz,iop0,iop1,nu,nv,nc, - * mm,mvnu -c ..array arguments.. - real*8 u(mu),v(mv),z(mz),dz(3),tu(nu),tv(nv),c(nc),fpu(nu),fpv(nv) - *, - * spu(mu,4),spv(mv,4),right(mm),q(mvnu),au(nu,5),av1(nv,6), - * av2(nv,4),aa(2,mv),bb(2,nv),cc(nv),cosi(2,nv),bu(nu,5),bv(nv,5) - integer nru(mu),nrv(mv) -c ..local scalars.. - real*8 arg,co,dz1,dz2,dz3,fac,fac0,pinv,piv,si,term,one,three,half - * - integer i,ic,ii,ij,ik,iq,irot,it,iz,i0,i1,i2,i3,j,jj,jk,jper, - * j0,j1,k,k1,k2,l,l0,l1,l2,mvv,ncof,nrold,nroldu,nroldv,number, - * numu,numu1,numv,numv1,nuu,nu4,nu7,nu8,nu9,nv11,nv4,nv7,nv8,n1 -c ..local arrays.. - real*8 h(5),h1(5),h2(4) -c ..function references.. - integer min0 - real*8 cos,sin -c ..subroutine references.. -c fpback,fpbspl,fpgivs,fpcyt1,fpcyt2,fpdisc,fpbacp,fprota -c .. -c let -c | (spu) | | (spv) | -c (au) = | ---------- | (av) = | ---------- | -c | (1/p) (bu) | | (1/p) (bv) | -c -c | z ' 0 | -c q = | ------ | -c | 0 ' 0 | -c -c with c : the (nu-4) x (nv-4) matrix which contains the b-spline -c coefficients. -c z : the mu x mv matrix which contains the function values. -c spu,spv: the mu x (nu-4), resp. mv x (nv-4) observation matrices -c according to the least-squares problems in the u-,resp. -c v-direction. -c bu,bv : the (nu-7) x (nu-4),resp. (nv-7) x (nv-4) matrices -c containing the discontinuity jumps of the derivatives -c of the b-splines in the u-,resp.v-variable at the knots -c the b-spline coefficients of the smoothing spline are then calculated -c as the least-squares solution of the following over-determined linear -c system of equations -c -c (1) (av) c (au)' = q -c -c subject to the constraints -c -c (2) c(i,nv-3+j) = c(i,j), j=1,2,3 ; i=1,2,...,nu-4 -c -c (3) if iop0 = 0 c(1,j) = dz(1) -c iop0 = 1 c(1,j) = dz(1) -c c(2,j) = dz(1)+(dz(2)*cosi(1,j)+dz(3)*cosi(2,j))* -c tu(5)/3. = cc(j) , j=1,2,...nv-4 -c -c (4) if iop1 = 1 c(nu-4,j) = 0, j=1,2,...,nv-4. -c -c set constants - one = 1 - three = 3 - half = 0.5 -c initialization - nu4 = nu-4 - nu7 = nu-7 - nu8 = nu-8 - nu9 = nu-9 - nv4 = nv-4 - nv7 = nv-7 - nv8 = nv-8 - nv11 = nv-11 - nuu = nu4-iop0-iop1-1 - if(p.gt.0.) pinv = one/p -c it depends on the value of the flags ifsu,ifsv,ifbu,ifbv and iop0 and -c on the value of p whether the matrices (spu), (spv), (bu), (bv) and -c (cosi) still must be determined. - if(ifsu.ne.0) go to 30 -c calculate the non-zero elements of the matrix (spu) which is the ob- -c servation matrix according to the least-squares spline approximation -c problem in the u-direction. - l = 4 - l1 = 5 - number = 0 - do 25 it=1,mu - arg = u(it) - 10 if(arg.lt.tu(l1) .or. l.eq.nu4) go to 15 - l = l1 - l1 = l+1 - number = number+1 - go to 10 - 15 call fpbspl(tu,nu,3,arg,l,h) - do 20 i=1,4 - spu(it,i) = h(i) - 20 continue - nru(it) = number - 25 continue - ifsu = 1 -c calculate the non-zero elements of the matrix (spv) which is the ob- -c servation matrix according to the least-squares spline approximation -c problem in the v-direction. - 30 if(ifsv.ne.0) go to 85 - l = 4 - l1 = 5 - number = 0 - do 50 it=1,mv - arg = v(it) - 35 if(arg.lt.tv(l1) .or. l.eq.nv4) go to 40 - l = l1 - l1 = l+1 - number = number+1 - go to 35 - 40 call fpbspl(tv,nv,3,arg,l,h) - do 45 i=1,4 - spv(it,i) = h(i) - 45 continue - nrv(it) = number - 50 continue - ifsv = 1 - if(iop0.eq.0) go to 85 -c calculate the coefficients of the interpolating splines for cos(v) -c and sin(v). - do 55 i=1,nv4 - cosi(1,i) = 0. - cosi(2,i) = 0. - 55 continue - if(nv7.lt.4) go to 85 - do 65 i=1,nv7 - l = i+3 - arg = tv(l) - call fpbspl(tv,nv,3,arg,l,h) - do 60 j=1,3 - av1(i,j) = h(j) - 60 continue - cosi(1,i) = cos(arg) - cosi(2,i) = sin(arg) - 65 continue - call fpcyt1(av1,nv7,nv) - do 80 j=1,2 - do 70 i=1,nv7 - right(i) = cosi(j,i) - 70 continue - call fpcyt2(av1,nv7,right,right,nv) - do 75 i=1,nv7 - cosi(j,i+1) = right(i) - 75 continue - cosi(j,1) = cosi(j,nv7+1) - cosi(j,nv7+2) = cosi(j,2) - cosi(j,nv4) = cosi(j,3) - 80 continue - 85 if(p.le.0.) go to 150 -c calculate the non-zero elements of the matrix (bu). - if(ifbu.ne.0 .or. nu8.eq.0) go to 90 - call fpdisc(tu,nu,5,bu,nu) - ifbu = 1 -c calculate the non-zero elements of the matrix (bv). - 90 if(ifbv.ne.0 .or. nv8.eq.0) go to 150 - call fpdisc(tv,nv,5,bv,nv) - ifbv = 1 -c substituting (2),(3) and (4) into (1), we obtain the overdetermined -c system -c (5) (avv) (cr) (auu)' = (qq) -c from which the nuu*nv7 remaining coefficients -c c(i,j) , i=2+iop0,3+iop0,...,nu-4-iop1 ; j=1,2,...,nv-7 , -c the elements of (cr), are then determined in the least-squares sense. -c simultaneously, we compute the resulting sum of squared residuals sq. - 150 dz1 = dz(1) - do 155 i=1,mv - aa(1,i) = dz1 - 155 continue - if(nv8.eq.0 .or. p.le.0.) go to 165 - do 160 i=1,nv8 - bb(1,i) = 0. - 160 continue - 165 mvv = mv - if(iop0.eq.0) go to 220 - fac = tu(5)/three - dz2 = dz(2)*fac - dz3 = dz(3)*fac - do 170 i=1,nv4 - cc(i) = dz1+dz2*cosi(1,i)+dz3*cosi(2,i) - 170 continue - do 190 i=1,mv - number = nrv(i) - fac = 0. - do 180 j=1,4 - number = number+1 - fac = fac+cc(number)*spv(i,j) - 180 continue - aa(2,i) = fac - 190 continue - if(nv8.eq.0 .or. p.le.0.) go to 220 - do 210 i=1,nv8 - number = i - fac = 0. - do 200 j=1,5 - fac = fac+cc(number)*bv(i,j) - number = number+1 - 200 continue - bb(2,i) = fac*pinv - 210 continue - mvv = mvv+nv8 -c we first determine the matrices (auu) and (qq). then we reduce the -c matrix (auu) to upper triangular form (ru) using givens rotations. -c we apply the same transformations to the rows of matrix qq to obtain -c the (mv+nv8) x nuu matrix g. -c we store matrix (ru) into au and g into q. - 220 l = mvv*nuu -c initialization. - sq = 0. - do 230 i=1,l - q(i) = 0. - 230 continue - do 240 i=1,nuu - do 240 j=1,5 - au(i,j) = 0. - 240 continue - l = 0 - nrold = 0 - n1 = nrold+1 - do 420 it=1,mu - number = nru(it) -c find the appropriate column of q. - 250 do 260 j=1,mvv - right(j) = 0. - 260 continue - if(nrold.eq.number) go to 280 - if(p.le.0.) go to 410 -c fetch a new row of matrix (bu). - do 270 j=1,5 - h(j) = bu(n1,j)*pinv - 270 continue - i0 = 1 - i1 = 5 - go to 310 -c fetch a new row of matrix (spu). - 280 do 290 j=1,4 - h(j) = spu(it,j) - 290 continue -c find the appropriate column of q. - do 300 j=1,mv - l = l+1 - right(j) = z(l) - 300 continue - i0 = 1 - i1 = 4 - 310 if(nu7-number .eq. iop1) i1 = i1-1 - j0 = n1 -c take into account that we eliminate the constraints (3) - 320 if(j0-1.gt.iop0) go to 360 - fac0 = h(i0) - do 330 j=1,mv - right(j) = right(j)-fac0*aa(j0,j) - 330 continue - if(mv.eq.mvv) go to 350 - j = mv - do 340 jj=1,nv8 - j = j+1 - right(j) = right(j)-fac0*bb(j0,jj) - 340 continue - 350 j0 = j0+1 - i0 = i0+1 - go to 320 - 360 irot = nrold-iop0-1 - if(irot.lt.0) irot = 0 -c rotate the new row of matrix (auu) into triangle. - do 390 i=i0,i1 - irot = irot+1 - piv = h(i) - if(piv.eq.0.) go to 390 -c calculate the parameters of the givens transformation. - call fpgivs(piv,au(irot,1),co,si) -c apply that transformation to the rows of matrix (qq). - iq = (irot-1)*mvv - do 370 j=1,mvv - iq = iq+1 - call fprota(co,si,right(j),q(iq)) - 370 continue -c apply that transformation to the columns of (auu). - if(i.eq.i1) go to 390 - i2 = 1 - i3 = i+1 - do 380 j=i3,i1 - i2 = i2+1 - call fprota(co,si,h(j),au(irot,i2)) - 380 continue - 390 continue -c we update the sum of squared residuals - do 395 j=1,mvv - sq = sq+right(j)**2 - 395 continue - 400 if(nrold.eq.number) go to 420 - 410 nrold = n1 - n1 = n1+1 - go to 250 - 420 continue -c we determine the matrix (avv) and then we reduce her to -c upper triangular form (rv) using givens rotations. -c we apply the same transformations to the columns of matrix -c g to obtain the (nv-7) x (nu-5-iop0-iop1) matrix h. -c we store matrix (rv) into av1 and av2, h into c. -c the nv7 x nv7 upper triangular matrix (rv) has the form -c | av1 ' | -c (rv) = | ' av2 | -c | 0 ' | -c with (av2) a nv7 x 4 matrix and (av1) a nv11 x nv11 upper -c triangular matrix of bandwidth 5. - ncof = nuu*nv7 -c initialization. - do 430 i=1,ncof - c(i) = 0. - 430 continue - do 440 i=1,nv4 - av1(i,5) = 0. - do 440 j=1,4 - av1(i,j) = 0. - av2(i,j) = 0. - 440 continue - jper = 0 - nrold = 0 - do 770 it=1,mv - number = nrv(it) - 450 if(nrold.eq.number) go to 480 - if(p.le.0.) go to 760 -c fetch a new row of matrix (bv). - n1 = nrold+1 - do 460 j=1,5 - h(j) = bv(n1,j)*pinv - 460 continue -c find the appropiate row of g. - do 465 j=1,nuu - right(j) = 0. - 465 continue - if(mv.eq.mvv) go to 510 - l = mv+n1 - do 470 j=1,nuu - right(j) = q(l) - l = l+mvv - 470 continue - go to 510 -c fetch a new row of matrix (spv) - 480 h(5) = 0. - do 490 j=1,4 - h(j) = spv(it,j) - 490 continue -c find the appropiate row of g. - l = it - do 500 j=1,nuu - right(j) = q(l) - l = l+mvv - 500 continue -c test whether there are non-zero values in the new row of (avv) -c corresponding to the b-splines n(j,v),j=nv7+1,...,nv4. - 510 if(nrold.lt.nv11) go to 710 - if(jper.ne.0) go to 550 -c initialize the matrix (av2). - jk = nv11+1 - do 540 i=1,4 - ik = jk - do 520 j=1,5 - if(ik.le.0) go to 530 - av2(ik,i) = av1(ik,j) - ik = ik-1 - 520 continue - 530 jk = jk+1 - 540 continue - jper = 1 -c if one of the non-zero elements of the new row corresponds to one of -c the b-splines n(j;v),j=nv7+1,...,nv4, we take account of condition -c (2) for setting up this row of (avv). the row is stored in h1( the -c part with respect to av1) and h2 (the part with respect to av2). - 550 do 560 i=1,4 - h1(i) = 0. - h2(i) = 0. - 560 continue - h1(5) = 0. - j = nrold-nv11 - do 600 i=1,5 - j = j+1 - l0 = j - 570 l1 = l0-4 - if(l1.le.0) go to 590 - if(l1.le.nv11) go to 580 - l0 = l1-nv11 - go to 570 - 580 h1(l1) = h(i) - go to 600 - 590 h2(l0) = h2(l0) + h(i) - 600 continue -c rotate the new row of (avv) into triangle. - if(nv11.le.0) go to 670 -c rotations with the rows 1,2,...,nv11 of (avv). - do 660 j=1,nv11 - piv = h1(1) - i2 = min0(nv11-j,4) - if(piv.eq.0.) go to 640 -c calculate the parameters of the givens transformation. - call fpgivs(piv,av1(j,1),co,si) -c apply that transformation to the columns of matrix g. - ic = j - do 610 i=1,nuu - call fprota(co,si,right(i),c(ic)) - ic = ic+nv7 - 610 continue -c apply that transformation to the rows of (avv) with respect to av2. - do 620 i=1,4 - call fprota(co,si,h2(i),av2(j,i)) - 620 continue -c apply that transformation to the rows of (avv) with respect to av1. - if(i2.eq.0) go to 670 - do 630 i=1,i2 - i1 = i+1 - call fprota(co,si,h1(i1),av1(j,i1)) - 630 continue - 640 do 650 i=1,i2 - h1(i) = h1(i+1) - 650 continue - h1(i2+1) = 0. - 660 continue -c rotations with the rows nv11+1,...,nv7 of avv. - 670 do 700 j=1,4 - ij = nv11+j - if(ij.le.0) go to 700 - piv = h2(j) - if(piv.eq.0.) go to 700 -c calculate the parameters of the givens transformation. - call fpgivs(piv,av2(ij,j),co,si) -c apply that transformation to the columns of matrix g. - ic = ij - do 680 i=1,nuu - call fprota(co,si,right(i),c(ic)) - ic = ic+nv7 - 680 continue - if(j.eq.4) go to 700 -c apply that transformation to the rows of (avv) with respect to av2. - j1 = j+1 - do 690 i=j1,4 - call fprota(co,si,h2(i),av2(ij,i)) - 690 continue - 700 continue -c we update the sum of squared residuals - do 705 i=1,nuu - sq = sq+right(i)**2 - 705 continue - go to 750 -c rotation into triangle of the new row of (avv), in case the elements -c corresponding to the b-splines n(j;v),j=nv7+1,...,nv4 are all zero. - 710 irot =nrold - do 740 i=1,5 - irot = irot+1 - piv = h(i) - if(piv.eq.0.) go to 740 -c calculate the parameters of the givens transformation. - call fpgivs(piv,av1(irot,1),co,si) -c apply that transformation to the columns of matrix g. - ic = irot - do 720 j=1,nuu - call fprota(co,si,right(j),c(ic)) - ic = ic+nv7 - 720 continue -c apply that transformation to the rows of (avv). - if(i.eq.5) go to 740 - i2 = 1 - i3 = i+1 - do 730 j=i3,5 - i2 = i2+1 - call fprota(co,si,h(j),av1(irot,i2)) - 730 continue - 740 continue -c we update the sum of squared residuals - do 745 i=1,nuu - sq = sq+right(i)**2 - 745 continue - 750 if(nrold.eq.number) go to 770 - 760 nrold = nrold+1 - go to 450 - 770 continue -c test whether the b-spline coefficients must be determined. - if(iback.ne.0) return -c backward substitution to obtain the b-spline coefficients as the -c solution of the linear system (rv) (cr) (ru)' = h. -c first step: solve the system (rv) (c1) = h. - k = 1 - do 780 i=1,nuu - call fpbacp(av1,av2,c(k),nv7,4,c(k),5,nv) - k = k+nv7 - 780 continue -c second step: solve the system (cr) (ru)' = (c1). - k = 0 - do 800 j=1,nv7 - k = k+1 - l = k - do 790 i=1,nuu - right(i) = c(l) - l = l+nv7 - 790 continue - call fpback(au,right,nuu,5,right,nu) - l = k - do 795 i=1,nuu - c(l) = right(i) - l = l+nv7 - 795 continue - 800 continue -c calculate from the conditions (2)-(3)-(4), the remaining b-spline -c coefficients. - ncof = nu4*nv4 - i = nv4 - j = 0 - do 805 l=1,nv4 - q(l) = dz1 - 805 continue - if(iop0.eq.0) go to 815 - do 810 l=1,nv4 - i = i+1 - q(i) = cc(l) - 810 continue - 815 if(nuu.eq.0) go to 850 - do 840 l=1,nuu - ii = i - do 820 k=1,nv7 - i = i+1 - j = j+1 - q(i) = c(j) - 820 continue - do 830 k=1,3 - ii = ii+1 - i = i+1 - q(i) = q(ii) - 830 continue - 840 continue - 850 if(iop1.eq.0) go to 870 - do 860 l=1,nv4 - i = i+1 - q(i) = 0. - 860 continue - 870 do 880 i=1,ncof - c(i) = q(i) - 880 continue -c calculate the quantities -c res(i,j) = (z(i,j) - s(u(i),v(j)))**2 , i=1,2,..,mu;j=1,2,..,mv -c fp = sumi=1,mu(sumj=1,mv(res(i,j))) -c fpu(r) = sum''i(sumj=1,mv(res(i,j))) , r=1,2,...,nu-7 -c tu(r+3) <= u(i) <= tu(r+4) -c fpv(r) = sumi=1,mu(sum''j(res(i,j))) , r=1,2,...,nv-7 -c tv(r+3) <= v(j) <= tv(r+4) - fp = 0. - do 890 i=1,nu - fpu(i) = 0. - 890 continue - do 900 i=1,nv - fpv(i) = 0. - 900 continue - iz = 0 - nroldu = 0 -c main loop for the different grid points. - do 950 i1=1,mu - numu = nru(i1) - numu1 = numu+1 - nroldv = 0 - do 940 i2=1,mv - numv = nrv(i2) - numv1 = numv+1 - iz = iz+1 -c evaluate s(u,v) at the current grid point by making the sum of the -c cross products of the non-zero b-splines at (u,v), multiplied with -c the appropiate b-spline coefficients. - term = 0. - k1 = numu*nv4+numv - do 920 l1=1,4 - k2 = k1 - fac = spu(i1,l1) - do 910 l2=1,4 - k2 = k2+1 - term = term+fac*spv(i2,l2)*c(k2) - 910 continue - k1 = k1+nv4 - 920 continue -c calculate the squared residual at the current grid point. - term = (z(iz)-term)**2 -c adjust the different parameters. - fp = fp+term - fpu(numu1) = fpu(numu1)+term - fpv(numv1) = fpv(numv1)+term - fac = term*half - if(numv.eq.nroldv) go to 930 - fpv(numv1) = fpv(numv1)-fac - fpv(numv) = fpv(numv)+fac - 930 nroldv = numv - if(numu.eq.nroldu) go to 940 - fpu(numu1) = fpu(numu1)-fac - fpu(numu) = fpu(numu)+fac - 940 continue - nroldu = numu - 950 continue - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpgrpa.f =================================================================== --- branches/Interpolate1D/fitpack/fpgrpa.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpgrpa.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,313 +0,0 @@ - subroutine fpgrpa(ifsu,ifsv,ifbu,ifbv,idim,ipar,u,mu,v,mv,z,mz, - * tu,nu,tv,nv,p,c,nc,fp,fpu,fpv,mm,mvnu,spu,spv,right,q,au,au1, - * av,av1,bu,bv,nru,nrv) -c .. -c ..scalar arguments.. - real*8 p,fp - integer ifsu,ifsv,ifbu,ifbv,idim,mu,mv,mz,nu,nv,nc,mm,mvnu -c ..array arguments.. - real*8 u(mu),v(mv),z(mz*idim),tu(nu),tv(nv),c(nc*idim),fpu(nu), - * fpv(nv),spu(mu,4),spv(mv,4),right(mm*idim),q(mvnu),au(nu,5), - * au1(nu,4),av(nv,5),av1(nv,4),bu(nu,5),bv(nv,5) - integer ipar(2),nru(mu),nrv(mv) -c ..local scalars.. - real*8 arg,fac,term,one,half,value - integer i,id,ii,it,iz,i1,i2,j,jz,k,k1,k2,l,l1,l2,mvv,k0,muu, - * ncof,nroldu,nroldv,number,nmd,numu,numu1,numv,numv1,nuu,nvv, - * nu4,nu7,nu8,nv4,nv7,nv8 -c ..local arrays.. - real*8 h(5) -c ..subroutine references.. -c fpback,fpbspl,fpdisc,fpbacp,fptrnp,fptrpe -c .. -c let -c | (spu) | | (spv) | -c (au) = | ---------- | (av) = | ---------- | -c | (1/p) (bu) | | (1/p) (bv) | -c -c | z ' 0 | -c q = | ------ | -c | 0 ' 0 | -c -c with c : the (nu-4) x (nv-4) matrix which contains the b-spline -c coefficients. -c z : the mu x mv matrix which contains the function values. -c spu,spv: the mu x (nu-4), resp. mv x (nv-4) observation matrices -c according to the least-squares problems in the u-,resp. -c v-direction. -c bu,bv : the (nu-7) x (nu-4),resp. (nv-7) x (nv-4) matrices -c containing the discontinuity jumps of the derivatives -c of the b-splines in the u-,resp.v-variable at the knots -c the b-spline coefficients of the smoothing spline are then calculated -c as the least-squares solution of the following over-determined linear -c system of equations -c -c (1) (av) c (au)' = q -c -c subject to the constraints -c -c (2) c(nu-3+i,j) = c(i,j), i=1,2,3 ; j=1,2,...,nv-4 -c if(ipar(1).ne.0) -c -c (3) c(i,nv-3+j) = c(i,j), j=1,2,3 ; i=1,2,...,nu-4 -c if(ipar(2).ne.0) -c -c set constants - one = 1 - half = 0.5 -c initialization - nu4 = nu-4 - nu7 = nu-7 - nu8 = nu-8 - nv4 = nv-4 - nv7 = nv-7 - nv8 = nv-8 - muu = mu - if(ipar(1).ne.0) muu = mu-1 - mvv = mv - if(ipar(2).ne.0) mvv = mv-1 -c it depends on the value of the flags ifsu,ifsv,ifbu and ibvand -c on the value of p whether the matrices (spu), (spv), (bu) and (bv) -c still must be determined. - if(ifsu.ne.0) go to 50 -c calculate the non-zero elements of the matrix (spu) which is the ob- -c servation matrix according to the least-squares spline approximation -c problem in the u-direction. - l = 4 - l1 = 5 - number = 0 - do 40 it=1,muu - arg = u(it) - 10 if(arg.lt.tu(l1) .or. l.eq.nu4) go to 20 - l = l1 - l1 = l+1 - number = number+1 - go to 10 - 20 call fpbspl(tu,nu,3,arg,l,h) - do 30 i=1,4 - spu(it,i) = h(i) - 30 continue - nru(it) = number - 40 continue - ifsu = 1 -c calculate the non-zero elements of the matrix (spv) which is the ob- -c servation matrix according to the least-squares spline approximation -c problem in the v-direction. - 50 if(ifsv.ne.0) go to 100 - l = 4 - l1 = 5 - number = 0 - do 90 it=1,mvv - arg = v(it) - 60 if(arg.lt.tv(l1) .or. l.eq.nv4) go to 70 - l = l1 - l1 = l+1 - number = number+1 - go to 60 - 70 call fpbspl(tv,nv,3,arg,l,h) - do 80 i=1,4 - spv(it,i) = h(i) - 80 continue - nrv(it) = number - 90 continue - ifsv = 1 - 100 if(p.le.0.) go to 150 -c calculate the non-zero elements of the matrix (bu). - if(ifbu.ne.0 .or. nu8.eq.0) go to 110 - call fpdisc(tu,nu,5,bu,nu) - ifbu = 1 -c calculate the non-zero elements of the matrix (bv). - 110 if(ifbv.ne.0 .or. nv8.eq.0) go to 150 - call fpdisc(tv,nv,5,bv,nv) - ifbv = 1 -c substituting (2) and (3) into (1), we obtain the overdetermined -c system -c (4) (avv) (cr) (auu)' = (qq) -c from which the nuu*nvv remaining coefficients -c c(i,j) , i=1,...,nu-4-3*ipar(1) ; j=1,...,nv-4-3*ipar(2) , -c the elements of (cr), are then determined in the least-squares sense. -c we first determine the matrices (auu) and (qq). then we reduce the -c matrix (auu) to upper triangular form (ru) using givens rotations. -c we apply the same transformations to the rows of matrix qq to obtain -c the (mv) x nuu matrix g. -c we store matrix (ru) into au (and au1 if ipar(1)=1) and g into q. - 150 if(ipar(1).ne.0) go to 160 - nuu = nu4 - call fptrnp(mu,mv,idim,nu,nru,spu,p,bu,z,au,q,right) - go to 180 - 160 nuu = nu7 - call fptrpe(mu,mv,idim,nu,nru,spu,p,bu,z,au,au1,q,right) -c we determine the matrix (avv) and then we reduce this matrix to -c upper triangular form (rv) using givens rotations. -c we apply the same transformations to the columns of matrix -c g to obtain the (nvv) x (nuu) matrix h. -c we store matrix (rv) into av (and av1 if ipar(2)=1) and h into c. - 180 if(ipar(2).ne.0) go to 190 - nvv = nv4 - call fptrnp(mv,nuu,idim,nv,nrv,spv,p,bv,q,av,c,right) - go to 200 - 190 nvv = nv7 - call fptrpe(mv,nuu,idim,nv,nrv,spv,p,bv,q,av,av1,c,right) -c backward substitution to obtain the b-spline coefficients as the -c solution of the linear system (rv) (cr) (ru)' = h. -c first step: solve the system (rv) (c1) = h. - 200 ncof = nuu*nvv - k = 1 - if(ipar(2).ne.0) go to 240 - do 220 ii=1,idim - do 220 i=1,nuu - call fpback(av,c(k),nvv,5,c(k),nv) - k = k+nvv - 220 continue - go to 300 - 240 do 260 ii=1,idim - do 260 i=1,nuu - call fpbacp(av,av1,c(k),nvv,4,c(k),5,nv) - k = k+nvv - 260 continue -c second step: solve the system (cr) (ru)' = (c1). - 300 if(ipar(1).ne.0) go to 400 - do 360 ii=1,idim - k = (ii-1)*ncof - do 360 j=1,nvv - k = k+1 - l = k - do 320 i=1,nuu - right(i) = c(l) - l = l+nvv - 320 continue - call fpback(au,right,nuu,5,right,nu) - l = k - do 340 i=1,nuu - c(l) = right(i) - l = l+nvv - 340 continue - 360 continue - go to 500 - 400 do 460 ii=1,idim - k = (ii-1)*ncof - do 460 j=1,nvv - k = k+1 - l = k - do 420 i=1,nuu - right(i) = c(l) - l = l+nvv - 420 continue - call fpbacp(au,au1,right,nuu,4,right,5,nu) - l = k - do 440 i=1,nuu - c(l) = right(i) - l = l+nvv - 440 continue - 460 continue -c calculate from the conditions (2)-(3), the remaining b-spline -c coefficients. - 500 if(ipar(2).eq.0) go to 600 - i = 0 - j = 0 - do 560 id=1,idim - do 560 l=1,nuu - ii = i - do 520 k=1,nvv - i = i+1 - j = j+1 - q(i) = c(j) - 520 continue - do 540 k=1,3 - ii = ii+1 - i = i+1 - q(i) = q(ii) - 540 continue - 560 continue - ncof = nv4*nuu - nmd = ncof*idim - do 580 i=1,nmd - c(i) = q(i) - 580 continue - 600 if(ipar(1).eq.0) go to 700 - i = 0 - j = 0 - n33 = 3*nv4 - do 660 id=1,idim - ii = i - do 620 k=1,ncof - i = i+1 - j = j+1 - q(i) = c(j) - 620 continue - do 640 k=1,n33 - ii = ii+1 - i = i+1 - q(i) = q(ii) - 640 continue - 660 continue - ncof = nv4*nu4 - nmd = ncof*idim - do 680 i=1,nmd - c(i) = q(i) - 680 continue -c calculate the quantities -c res(i,j) = (z(i,j) - s(u(i),v(j)))**2 , i=1,2,..,mu;j=1,2,..,mv -c fp = sumi=1,mu(sumj=1,mv(res(i,j))) -c fpu(r) = sum''i(sumj=1,mv(res(i,j))) , r=1,2,...,nu-7 -c tu(r+3) <= u(i) <= tu(r+4) -c fpv(r) = sumi=1,mu(sum''j(res(i,j))) , r=1,2,...,nv-7 -c tv(r+3) <= v(j) <= tv(r+4) - 700 fp = 0. - do 720 i=1,nu - fpu(i) = 0. - 720 continue - do 740 i=1,nv - fpv(i) = 0. - 740 continue - nroldu = 0 -c main loop for the different grid points. - do 860 i1=1,muu - numu = nru(i1) - numu1 = numu+1 - nroldv = 0 - iz = (i1-1)*mv - do 840 i2=1,mvv - numv = nrv(i2) - numv1 = numv+1 - iz = iz+1 -c evaluate s(u,v) at the current grid point by making the sum of the -c cross products of the non-zero b-splines at (u,v), multiplied with -c the appropiate b-spline coefficients. - term = 0. - k0 = numu*nv4+numv - jz = iz - do 800 id=1,idim - k1 = k0 - value = 0. - do 780 l1=1,4 - k2 = k1 - fac = spu(i1,l1) - do 760 l2=1,4 - k2 = k2+1 - value = value+fac*spv(i2,l2)*c(k2) - 760 continue - k1 = k1+nv4 - 780 continue -c calculate the squared residual at the current grid point. - term = term+(z(jz)-value)**2 - jz = jz+mz - k0 = k0+ncof - 800 continue -c adjust the different parameters. - fp = fp+term - fpu(numu1) = fpu(numu1)+term - fpv(numv1) = fpv(numv1)+term - fac = term*half - if(numv.eq.nroldv) go to 820 - fpv(numv1) = fpv(numv1)-fac - fpv(numv) = fpv(numv)+fac - 820 nroldv = numv - if(numu.eq.nroldu) go to 840 - fpu(numu1) = fpu(numu1)-fac - fpu(numu) = fpu(numu)+fac - 840 continue - nroldu = numu - 860 continue - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpgrre.f =================================================================== --- branches/Interpolate1D/fitpack/fpgrre.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpgrre.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,328 +0,0 @@ - subroutine fpgrre(ifsx,ifsy,ifbx,ifby,x,mx,y,my,z,mz,kx,ky,tx,nx, - * ty,ny,p,c,nc,fp,fpx,fpy,mm,mynx,kx1,kx2,ky1,ky2,spx,spy,right,q, - * ax,ay,bx,by,nrx,nry) -c .. -c ..scalar arguments.. - real*8 p,fp - integer ifsx,ifsy,ifbx,ifby,mx,my,mz,kx,ky,nx,ny,nc,mm,mynx, - * kx1,kx2,ky1,ky2 -c ..array arguments.. - real*8 x(mx),y(my),z(mz),tx(nx),ty(ny),c(nc),spx(mx,kx1),spy(my,ky - *1) - * ,right(mm),q(mynx),ax(nx,kx2),bx(nx,kx2),ay(ny,ky2),by(ny,ky2), - * fpx(nx),fpy(ny) - integer nrx(mx),nry(my) -c ..local scalars.. - real*8 arg,cos,fac,pinv,piv,sin,term,one,half - integer i,ibandx,ibandy,ic,iq,irot,it,iz,i1,i2,i3,j,k,k1,k2,l, - * l1,l2,ncof,nk1x,nk1y,nrold,nroldx,nroldy,number,numx,numx1, - * numy,numy1,n1 -c ..local arrays.. - real*8 h(7) -c ..subroutine references.. -c fpback,fpbspl,fpgivs,fpdisc,fprota -c .. -c the b-spline coefficients of the smoothing spline are calculated as -c the least-squares solution of the over-determined linear system of -c equations (ay) c (ax)' = q where -c -c | (spx) | | (spy) | -c (ax) = | ---------- | (ay) = | ---------- | -c | (1/p) (bx) | | (1/p) (by) | -c -c | z ' 0 | -c q = | ------ | -c | 0 ' 0 | -c -c with c : the (ny-ky-1) x (nx-kx-1) matrix which contains the -c b-spline coefficients. -c z : the my x mx matrix which contains the function values. -c spx,spy: the mx x (nx-kx-1) and my x (ny-ky-1) observation -c matrices according to the least-squares problems in -c the x- and y-direction. -c bx,by : the (nx-2*kx-1) x (nx-kx-1) and (ny-2*ky-1) x (ny-ky-1) -c matrices which contain the discontinuity jumps of the -c derivatives of the b-splines in the x- and y-direction. - one = 1 - half = 0.5 - nk1x = nx-kx1 - nk1y = ny-ky1 - if(p.gt.0.) pinv = one/p -c it depends on the value of the flags ifsx,ifsy,ifbx and ifby and on -c the value of p whether the matrices (spx),(spy),(bx) and (by) still -c must be determined. - if(ifsx.ne.0) go to 50 -c calculate the non-zero elements of the matrix (spx) which is the -c observation matrix according to the least-squares spline approximat- -c ion problem in the x-direction. - l = kx1 - l1 = kx2 - number = 0 - do 40 it=1,mx - arg = x(it) - 10 if(arg.lt.tx(l1) .or. l.eq.nk1x) go to 20 - l = l1 - l1 = l+1 - number = number+1 - go to 10 - 20 call fpbspl(tx,nx,kx,arg,l,h) - do 30 i=1,kx1 - spx(it,i) = h(i) - 30 continue - nrx(it) = number - 40 continue - ifsx = 1 - 50 if(ifsy.ne.0) go to 100 -c calculate the non-zero elements of the matrix (spy) which is the -c observation matrix according to the least-squares spline approximat- -c ion problem in the y-direction. - l = ky1 - l1 = ky2 - number = 0 - do 90 it=1,my - arg = y(it) - 60 if(arg.lt.ty(l1) .or. l.eq.nk1y) go to 70 - l = l1 - l1 = l+1 - number = number+1 - go to 60 - 70 call fpbspl(ty,ny,ky,arg,l,h) - do 80 i=1,ky1 - spy(it,i) = h(i) - 80 continue - nry(it) = number - 90 continue - ifsy = 1 - 100 if(p.le.0.) go to 120 -c calculate the non-zero elements of the matrix (bx). - if(ifbx.ne.0 .or. nx.eq.2*kx1) go to 110 - call fpdisc(tx,nx,kx2,bx,nx) - ifbx = 1 -c calculate the non-zero elements of the matrix (by). - 110 if(ifby.ne.0 .or. ny.eq.2*ky1) go to 120 - call fpdisc(ty,ny,ky2,by,ny) - ifby = 1 -c reduce the matrix (ax) to upper triangular form (rx) using givens -c rotations. apply the same transformations to the rows of matrix q -c to obtain the my x (nx-kx-1) matrix g. -c store matrix (rx) into (ax) and g into q. - 120 l = my*nk1x -c initialization. - do 130 i=1,l - q(i) = 0. - 130 continue - do 140 i=1,nk1x - do 140 j=1,kx2 - ax(i,j) = 0. - 140 continue - l = 0 - nrold = 0 -c ibandx denotes the bandwidth of the matrices (ax) and (rx). - ibandx = kx1 - do 270 it=1,mx - number = nrx(it) - 150 if(nrold.eq.number) go to 180 - if(p.le.0.) go to 260 - ibandx = kx2 -c fetch a new row of matrix (bx). - n1 = nrold+1 - do 160 j=1,kx2 - h(j) = bx(n1,j)*pinv - 160 continue -c find the appropriate column of q. - do 170 j=1,my - right(j) = 0. - 170 continue - irot = nrold - go to 210 -c fetch a new row of matrix (spx). - 180 h(ibandx) = 0. - do 190 j=1,kx1 - h(j) = spx(it,j) - 190 continue -c find the appropriate column of q. - do 200 j=1,my - l = l+1 - right(j) = z(l) - 200 continue - irot = number -c rotate the new row of matrix (ax) into triangle. - 210 do 240 i=1,ibandx - irot = irot+1 - piv = h(i) - if(piv.eq.0.) go to 240 -c calculate the parameters of the givens transformation. - call fpgivs(piv,ax(irot,1),cos,sin) -c apply that transformation to the rows of matrix q. - iq = (irot-1)*my - do 220 j=1,my - iq = iq+1 - call fprota(cos,sin,right(j),q(iq)) - 220 continue -c apply that transformation to the columns of (ax). - if(i.eq.ibandx) go to 250 - i2 = 1 - i3 = i+1 - do 230 j=i3,ibandx - i2 = i2+1 - call fprota(cos,sin,h(j),ax(irot,i2)) - 230 continue - 240 continue - 250 if(nrold.eq.number) go to 270 - 260 nrold = nrold+1 - go to 150 - 270 continue -c reduce the matrix (ay) to upper triangular form (ry) using givens -c rotations. apply the same transformations to the columns of matrix g -c to obtain the (ny-ky-1) x (nx-kx-1) matrix h. -c store matrix (ry) into (ay) and h into c. - ncof = nk1x*nk1y -c initialization. - do 280 i=1,ncof - c(i) = 0. - 280 continue - do 290 i=1,nk1y - do 290 j=1,ky2 - ay(i,j) = 0. - 290 continue - nrold = 0 -c ibandy denotes the bandwidth of the matrices (ay) and (ry). - ibandy = ky1 - do 420 it=1,my - number = nry(it) - 300 if(nrold.eq.number) go to 330 - if(p.le.0.) go to 410 - ibandy = ky2 -c fetch a new row of matrix (by). - n1 = nrold+1 - do 310 j=1,ky2 - h(j) = by(n1,j)*pinv - 310 continue -c find the appropiate row of g. - do 320 j=1,nk1x - right(j) = 0. - 320 continue - irot = nrold - go to 360 -c fetch a new row of matrix (spy) - 330 h(ibandy) = 0. - do 340 j=1,ky1 - h(j) = spy(it,j) - 340 continue -c find the appropiate row of g. - l = it - do 350 j=1,nk1x - right(j) = q(l) - l = l+my - 350 continue - irot = number -c rotate the new row of matrix (ay) into triangle. - 360 do 390 i=1,ibandy - irot = irot+1 - piv = h(i) - if(piv.eq.0.) go to 390 -c calculate the parameters of the givens transformation. - call fpgivs(piv,ay(irot,1),cos,sin) -c apply that transformation to the colums of matrix g. - ic = irot - do 370 j=1,nk1x - call fprota(cos,sin,right(j),c(ic)) - ic = ic+nk1y - 370 continue -c apply that transformation to the columns of matrix (ay). - if(i.eq.ibandy) go to 400 - i2 = 1 - i3 = i+1 - do 380 j=i3,ibandy - i2 = i2+1 - call fprota(cos,sin,h(j),ay(irot,i2)) - 380 continue - 390 continue - 400 if(nrold.eq.number) go to 420 - 410 nrold = nrold+1 - go to 300 - 420 continue -c backward substitution to obtain the b-spline coefficients as the -c solution of the linear system (ry) c (rx)' = h. -c first step: solve the system (ry) (c1) = h. - k = 1 - do 450 i=1,nk1x - call fpback(ay,c(k),nk1y,ibandy,c(k),ny) - k = k+nk1y - 450 continue -c second step: solve the system c (rx)' = (c1). - k = 0 - do 480 j=1,nk1y - k = k+1 - l = k - do 460 i=1,nk1x - right(i) = c(l) - l = l+nk1y - 460 continue - call fpback(ax,right,nk1x,ibandx,right,nx) - l = k - do 470 i=1,nk1x - c(l) = right(i) - l = l+nk1y - 470 continue - 480 continue -c calculate the quantities -c res(i,j) = (z(i,j) - s(x(i),y(j)))**2 , i=1,2,..,mx;j=1,2,..,my -c fp = sumi=1,mx(sumj=1,my(res(i,j))) -c fpx(r) = sum''i(sumj=1,my(res(i,j))) , r=1,2,...,nx-2*kx-1 -c tx(r+kx) <= x(i) <= tx(r+kx+1) -c fpy(r) = sumi=1,mx(sum''j(res(i,j))) , r=1,2,...,ny-2*ky-1 -c ty(r+ky) <= y(j) <= ty(r+ky+1) - fp = 0. - do 490 i=1,nx - fpx(i) = 0. - 490 continue - do 500 i=1,ny - fpy(i) = 0. - 500 continue - nk1y = ny-ky1 - iz = 0 - nroldx = 0 -c main loop for the different grid points. - do 550 i1=1,mx - numx = nrx(i1) - numx1 = numx+1 - nroldy = 0 - do 540 i2=1,my - numy = nry(i2) - numy1 = numy+1 - iz = iz+1 -c evaluate s(x,y) at the current grid point by making the sum of the -c cross products of the non-zero b-splines at (x,y), multiplied with -c the appropiate b-spline coefficients. - term = 0. - k1 = numx*nk1y+numy - do 520 l1=1,kx1 - k2 = k1 - fac = spx(i1,l1) - do 510 l2=1,ky1 - k2 = k2+1 - term = term+fac*spy(i2,l2)*c(k2) - 510 continue - k1 = k1+nk1y - 520 continue -c calculate the squared residual at the current grid point. - term = (z(iz)-term)**2 -c adjust the different parameters. - fp = fp+term - fpx(numx1) = fpx(numx1)+term - fpy(numy1) = fpy(numy1)+term - fac = term*half - if(numy.eq.nroldy) go to 530 - fpy(numy1) = fpy(numy1)-fac - fpy(numy) = fpy(numy)+fac - 530 nroldy = numy - if(numx.eq.nroldx) go to 540 - fpx(numx1) = fpx(numx1)-fac - fpx(numx) = fpx(numx)+fac - 540 continue - nroldx = numx - 550 continue - return - end - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpgrsp.f =================================================================== --- branches/Interpolate1D/fitpack/fpgrsp.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpgrsp.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,656 +0,0 @@ - subroutine fpgrsp(ifsu,ifsv,ifbu,ifbv,iback,u,mu,v,mv,r,mr,dr, - * iop0,iop1,tu,nu,tv,nv,p,c,nc,sq,fp,fpu,fpv,mm,mvnu,spu,spv, - * right,q,au,av1,av2,bu,bv,a0,a1,b0,b1,c0,c1,cosi,nru,nrv) -c .. -c ..scalar arguments.. - real*8 p,sq,fp - integer ifsu,ifsv,ifbu,ifbv,iback,mu,mv,mr,iop0,iop1,nu,nv,nc, - * mm,mvnu -c ..array arguments.. - real*8 u(mu),v(mv),r(mr),dr(6),tu(nu),tv(nv),c(nc),fpu(nu),fpv(nv) - *, - * spu(mu,4),spv(mv,4),right(mm),q(mvnu),au(nu,5),av1(nv,6),c0(nv), - * av2(nv,4),a0(2,mv),b0(2,nv),cosi(2,nv),bu(nu,5),bv(nv,5),c1(nv), - * a1(2,mv),b1(2,nv) - integer nru(mu),nrv(mv) -c ..local scalars.. - real*8 arg,co,dr01,dr02,dr03,dr11,dr12,dr13,fac,fac0,fac1,pinv,piv - *, - * si,term,one,three,half - integer i,ic,ii,ij,ik,iq,irot,it,ir,i0,i1,i2,i3,j,jj,jk,jper, - * j0,j1,k,k1,k2,l,l0,l1,l2,mvv,ncof,nrold,nroldu,nroldv,number, - * numu,numu1,numv,numv1,nuu,nu4,nu7,nu8,nu9,nv11,nv4,nv7,nv8,n1 -c ..local arrays.. - real*8 h(5),h1(5),h2(4) -c ..function references.. - integer min0 - real*8 cos,sin -c ..subroutine references.. -c fpback,fpbspl,fpgivs,fpcyt1,fpcyt2,fpdisc,fpbacp,fprota -c .. -c let -c | (spu) | | (spv) | -c (au) = | -------------- | (av) = | -------------- | -c | sqrt(1/p) (bu) | | sqrt(1/p) (bv) | -c -c | r ' 0 | -c q = | ------ | -c | 0 ' 0 | -c -c with c : the (nu-4) x (nv-4) matrix which contains the b-spline -c coefficients. -c r : the mu x mv matrix which contains the function values. -c spu,spv: the mu x (nu-4), resp. mv x (nv-4) observation matrices -c according to the least-squares problems in the u-,resp. -c v-direction. -c bu,bv : the (nu-7) x (nu-4),resp. (nv-7) x (nv-4) matrices -c containing the discontinuity jumps of the derivatives -c of the b-splines in the u-,resp.v-variable at the knots -c the b-spline coefficients of the smoothing spline are then calculated -c as the least-squares solution of the following over-determined linear -c system of equations -c -c (1) (av) c (au)' = q -c -c subject to the constraints -c -c (2) c(i,nv-3+j) = c(i,j), j=1,2,3 ; i=1,2,...,nu-4 -c -c (3) if iop0 = 0 c(1,j) = dr(1) -c iop0 = 1 c(1,j) = dr(1) -c c(2,j) = dr(1)+(dr(2)*cosi(1,j)+dr(3)*cosi(2,j))* -c tu(5)/3. = c0(j) , j=1,2,...nv-4 -c -c (4) if iop1 = 0 c(nu-4,j) = dr(4) -c iop1 = 1 c(nu-4,j) = dr(4) -c c(nu-5,j) = dr(4)+(dr(5)*cosi(1,j)+dr(6)*cosi(2,j)) -c *(tu(nu-4)-tu(nu-3))/3. = c1(j) -c -c set constants - one = 1 - three = 3 - half = 0.5 -c initialization - nu4 = nu-4 - nu7 = nu-7 - nu8 = nu-8 - nu9 = nu-9 - nv4 = nv-4 - nv7 = nv-7 - nv8 = nv-8 - nv11 = nv-11 - nuu = nu4-iop0-iop1-2 - if(p.gt.0.) pinv = one/p -c it depends on the value of the flags ifsu,ifsv,ifbu,ifbv,iop0,iop1 -c and on the value of p whether the matrices (spu), (spv), (bu), (bv), -c (cosi) still must be determined. - if(ifsu.ne.0) go to 30 -c calculate the non-zero elements of the matrix (spu) which is the ob- -c servation matrix according to the least-squares spline approximation -c problem in the u-direction. - l = 4 - l1 = 5 - number = 0 - do 25 it=1,mu - arg = u(it) - 10 if(arg.lt.tu(l1) .or. l.eq.nu4) go to 15 - l = l1 - l1 = l+1 - number = number+1 - go to 10 - 15 call fpbspl(tu,nu,3,arg,l,h) - do 20 i=1,4 - spu(it,i) = h(i) - 20 continue - nru(it) = number - 25 continue - ifsu = 1 -c calculate the non-zero elements of the matrix (spv) which is the ob- -c servation matrix according to the least-squares spline approximation -c problem in the v-direction. - 30 if(ifsv.ne.0) go to 85 - l = 4 - l1 = 5 - number = 0 - do 50 it=1,mv - arg = v(it) - 35 if(arg.lt.tv(l1) .or. l.eq.nv4) go to 40 - l = l1 - l1 = l+1 - number = number+1 - go to 35 - 40 call fpbspl(tv,nv,3,arg,l,h) - do 45 i=1,4 - spv(it,i) = h(i) - 45 continue - nrv(it) = number - 50 continue - ifsv = 1 - if(iop0.eq.0 .and. iop1.eq.0) go to 85 -c calculate the coefficients of the interpolating splines for cos(v) -c and sin(v). - do 55 i=1,nv4 - cosi(1,i) = 0. - cosi(2,i) = 0. - 55 continue - if(nv7.lt.4) go to 85 - do 65 i=1,nv7 - l = i+3 - arg = tv(l) - call fpbspl(tv,nv,3,arg,l,h) - do 60 j=1,3 - av1(i,j) = h(j) - 60 continue - cosi(1,i) = cos(arg) - cosi(2,i) = sin(arg) - 65 continue - call fpcyt1(av1,nv7,nv) - do 80 j=1,2 - do 70 i=1,nv7 - right(i) = cosi(j,i) - 70 continue - call fpcyt2(av1,nv7,right,right,nv) - do 75 i=1,nv7 - cosi(j,i+1) = right(i) - 75 continue - cosi(j,1) = cosi(j,nv7+1) - cosi(j,nv7+2) = cosi(j,2) - cosi(j,nv4) = cosi(j,3) - 80 continue - 85 if(p.le.0.) go to 150 -c calculate the non-zero elements of the matrix (bu). - if(ifbu.ne.0 .or. nu8.eq.0) go to 90 - call fpdisc(tu,nu,5,bu,nu) - ifbu = 1 -c calculate the non-zero elements of the matrix (bv). - 90 if(ifbv.ne.0 .or. nv8.eq.0) go to 150 - call fpdisc(tv,nv,5,bv,nv) - ifbv = 1 -c substituting (2),(3) and (4) into (1), we obtain the overdetermined -c system -c (5) (avv) (cc) (auu)' = (qq) -c from which the nuu*nv7 remaining coefficients -c c(i,j) , i=2+iop0,3+iop0,...,nu-5-iop1,j=1,2,...,nv-7. -c the elements of (cc), are then determined in the least-squares sense. -c simultaneously, we compute the resulting sum of squared residuals sq. - 150 dr01 = dr(1) - dr11 = dr(4) - do 155 i=1,mv - a0(1,i) = dr01 - a1(1,i) = dr11 - 155 continue - if(nv8.eq.0 .or. p.le.0.) go to 165 - do 160 i=1,nv8 - b0(1,i) = 0. - b1(1,i) = 0. - 160 continue - 165 mvv = mv - if(iop0.eq.0) go to 195 - fac = (tu(5)-tu(4))/three - dr02 = dr(2)*fac - dr03 = dr(3)*fac - do 170 i=1,nv4 - c0(i) = dr01+dr02*cosi(1,i)+dr03*cosi(2,i) - 170 continue - do 180 i=1,mv - number = nrv(i) - fac = 0. - do 175 j=1,4 - number = number+1 - fac = fac+c0(number)*spv(i,j) - 175 continue - a0(2,i) = fac - 180 continue - if(nv8.eq.0 .or. p.le.0.) go to 195 - do 190 i=1,nv8 - number = i - fac = 0. - do 185 j=1,5 - fac = fac+c0(number)*bv(i,j) - number = number+1 - 185 continue - b0(2,i) = fac*pinv - 190 continue - mvv = mv+nv8 - 195 if(iop1.eq.0) go to 225 - fac = (tu(nu4)-tu(nu4+1))/three - dr12 = dr(5)*fac - dr13 = dr(6)*fac - do 200 i=1,nv4 - c1(i) = dr11+dr12*cosi(1,i)+dr13*cosi(2,i) - 200 continue - do 210 i=1,mv - number = nrv(i) - fac = 0. - do 205 j=1,4 - number = number+1 - fac = fac+c1(number)*spv(i,j) - 205 continue - a1(2,i) = fac - 210 continue - if(nv8.eq.0 .or. p.le.0.) go to 225 - do 220 i=1,nv8 - number = i - fac = 0. - do 215 j=1,5 - fac = fac+c1(number)*bv(i,j) - number = number+1 - 215 continue - b1(2,i) = fac*pinv - 220 continue - mvv = mv+nv8 -c we first determine the matrices (auu) and (qq). then we reduce the -c matrix (auu) to an unit upper triangular form (ru) using givens -c rotations without square roots. we apply the same transformations to -c the rows of matrix qq to obtain the mv x nuu matrix g. -c we store matrix (ru) into au and g into q. - 225 l = mvv*nuu -c initialization. - sq = 0. - if(l.eq.0) go to 245 - do 230 i=1,l - q(i) = 0. - 230 continue - do 240 i=1,nuu - do 240 j=1,5 - au(i,j) = 0. - 240 continue - l = 0 - 245 nrold = 0 - n1 = nrold+1 - do 420 it=1,mu - number = nru(it) -c find the appropriate column of q. - 250 do 260 j=1,mvv - right(j) = 0. - 260 continue - if(nrold.eq.number) go to 280 - if(p.le.0.) go to 410 -c fetch a new row of matrix (bu). - do 270 j=1,5 - h(j) = bu(n1,j)*pinv - 270 continue - i0 = 1 - i1 = 5 - go to 310 -c fetch a new row of matrix (spu). - 280 do 290 j=1,4 - h(j) = spu(it,j) - 290 continue -c find the appropriate column of q. - do 300 j=1,mv - l = l+1 - right(j) = r(l) - 300 continue - i0 = 1 - i1 = 4 - 310 j0 = n1 - j1 = nu7-number -c take into account that we eliminate the constraints (3) - 315 if(j0-1.gt.iop0) go to 335 - fac0 = h(i0) - do 320 j=1,mv - right(j) = right(j)-fac0*a0(j0,j) - 320 continue - if(mv.eq.mvv) go to 330 - j = mv - do 325 jj=1,nv8 - j = j+1 - right(j) = right(j)-fac0*b0(j0,jj) - 325 continue - 330 j0 = j0+1 - i0 = i0+1 - go to 315 -c take into account that we eliminate the constraints (4) - 335 if(j1-1.gt.iop1) go to 360 - fac1 = h(i1) - do 340 j=1,mv - right(j) = right(j)-fac1*a1(j1,j) - 340 continue - if(mv.eq.mvv) go to 350 - j = mv - do 345 jj=1,nv8 - j = j+1 - right(j) = right(j)-fac1*b1(j1,jj) - 345 continue - 350 j1 = j1+1 - i1 = i1-1 - go to 335 - 360 irot = nrold-iop0-1 - if(irot.lt.0) irot = 0 -c rotate the new row of matrix (auu) into triangle. - if(i0.gt.i1) go to 390 - do 385 i=i0,i1 - irot = irot+1 - piv = h(i) - if(piv.eq.0.) go to 385 -c calculate the parameters of the givens transformation. - call fpgivs(piv,au(irot,1),co,si) -c apply that transformation to the rows of matrix (qq). - iq = (irot-1)*mvv - do 370 j=1,mvv - iq = iq+1 - call fprota(co,si,right(j),q(iq)) - 370 continue -c apply that transformation to the columns of (auu). - if(i.eq.i1) go to 385 - i2 = 1 - i3 = i+1 - do 380 j=i3,i1 - i2 = i2+1 - call fprota(co,si,h(j),au(irot,i2)) - 380 continue - 385 continue -c we update the sum of squared residuals. - 390 do 395 j=1,mvv - sq = sq+right(j)**2 - 395 continue - 400 if(nrold.eq.number) go to 420 - 410 nrold = n1 - n1 = n1+1 - go to 250 - 420 continue - if(nuu.eq.0) go to 800 -c we determine the matrix (avv) and then we reduce her to an unit -c upper triangular form (rv) using givens rotations without square -c roots. we apply the same transformations to the columns of matrix -c g to obtain the (nv-7) x (nu-6-iop0-iop1) matrix h. -c we store matrix (rv) into av1 and av2, h into c. -c the nv7 x nv7 triangular unit upper matrix (rv) has the form -c | av1 ' | -c (rv) = | ' av2 | -c | 0 ' | -c with (av2) a nv7 x 4 matrix and (av1) a nv11 x nv11 unit upper -c triangular matrix of bandwidth 5. - ncof = nuu*nv7 -c initialization. - do 430 i=1,ncof - c(i) = 0. - 430 continue - do 440 i=1,nv4 - av1(i,5) = 0. - do 440 j=1,4 - av1(i,j) = 0. - av2(i,j) = 0. - 440 continue - jper = 0 - nrold = 0 - do 770 it=1,mv - number = nrv(it) - 450 if(nrold.eq.number) go to 480 - if(p.le.0.) go to 760 -c fetch a new row of matrix (bv). - n1 = nrold+1 - do 460 j=1,5 - h(j) = bv(n1,j)*pinv - 460 continue -c find the appropiate row of g. - do 465 j=1,nuu - right(j) = 0. - 465 continue - if(mv.eq.mvv) go to 510 - l = mv+n1 - do 470 j=1,nuu - right(j) = q(l) - l = l+mvv - 470 continue - go to 510 -c fetch a new row of matrix (spv) - 480 h(5) = 0. - do 490 j=1,4 - h(j) = spv(it,j) - 490 continue -c find the appropiate row of g. - l = it - do 500 j=1,nuu - right(j) = q(l) - l = l+mvv - 500 continue -c test whether there are non-zero values in the new row of (avv) -c corresponding to the b-splines n(j;v),j=nv7+1,...,nv4. - 510 if(nrold.lt.nv11) go to 710 - if(jper.ne.0) go to 550 -c initialize the matrix (av2). - jk = nv11+1 - do 540 i=1,4 - ik = jk - do 520 j=1,5 - if(ik.le.0) go to 530 - av2(ik,i) = av1(ik,j) - ik = ik-1 - 520 continue - 530 jk = jk+1 - 540 continue - jper = 1 -c if one of the non-zero elements of the new row corresponds to one of -c the b-splines n(j;v),j=nv7+1,...,nv4, we take account of condition -c (2) for setting up this row of (avv). the row is stored in h1( the -c part with respect to av1) and h2 (the part with respect to av2). - 550 do 560 i=1,4 - h1(i) = 0. - h2(i) = 0. - 560 continue - h1(5) = 0. - j = nrold-nv11 - do 600 i=1,5 - j = j+1 - l0 = j - 570 l1 = l0-4 - if(l1.le.0) go to 590 - if(l1.le.nv11) go to 580 - l0 = l1-nv11 - go to 570 - 580 h1(l1) = h(i) - go to 600 - 590 h2(l0) = h2(l0) + h(i) - 600 continue -c rotate the new row of (avv) into triangle. - if(nv11.le.0) go to 670 -c rotations with the rows 1,2,...,nv11 of (avv). - do 660 j=1,nv11 - piv = h1(1) - i2 = min0(nv11-j,4) - if(piv.eq.0.) go to 640 -c calculate the parameters of the givens transformation. - call fpgivs(piv,av1(j,1),co,si) -c apply that transformation to the columns of matrix g. - ic = j - do 610 i=1,nuu - call fprota(co,si,right(i),c(ic)) - ic = ic+nv7 - 610 continue -c apply that transformation to the rows of (avv) with respect to av2. - do 620 i=1,4 - call fprota(co,si,h2(i),av2(j,i)) - 620 continue -c apply that transformation to the rows of (avv) with respect to av1. - if(i2.eq.0) go to 670 - do 630 i=1,i2 - i1 = i+1 - call fprota(co,si,h1(i1),av1(j,i1)) - 630 continue - 640 do 650 i=1,i2 - h1(i) = h1(i+1) - 650 continue - h1(i2+1) = 0. - 660 continue -c rotations with the rows nv11+1,...,nv7 of avv. - 670 do 700 j=1,4 - ij = nv11+j - if(ij.le.0) go to 700 - piv = h2(j) - if(piv.eq.0.) go to 700 -c calculate the parameters of the givens transformation. - call fpgivs(piv,av2(ij,j),co,si) -c apply that transformation to the columns of matrix g. - ic = ij - do 680 i=1,nuu - call fprota(co,si,right(i),c(ic)) - ic = ic+nv7 - 680 continue - if(j.eq.4) go to 700 -c apply that transformation to the rows of (avv) with respect to av2. - j1 = j+1 - do 690 i=j1,4 - call fprota(co,si,h2(i),av2(ij,i)) - 690 continue - 700 continue -c we update the sum of squared residuals. - do 705 i=1,nuu - sq = sq+right(i)**2 - 705 continue - go to 750 -c rotation into triangle of the new row of (avv), in case the elements -c corresponding to the b-splines n(j;v),j=nv7+1,...,nv4 are all zero. - 710 irot =nrold - do 740 i=1,5 - irot = irot+1 - piv = h(i) - if(piv.eq.0.) go to 740 -c calculate the parameters of the givens transformation. - call fpgivs(piv,av1(irot,1),co,si) -c apply that transformation to the columns of matrix g. - ic = irot - do 720 j=1,nuu - call fprota(co,si,right(j),c(ic)) - ic = ic+nv7 - 720 continue -c apply that transformation to the rows of (avv). - if(i.eq.5) go to 740 - i2 = 1 - i3 = i+1 - do 730 j=i3,5 - i2 = i2+1 - call fprota(co,si,h(j),av1(irot,i2)) - 730 continue - 740 continue -c we update the sum of squared residuals. - do 745 i=1,nuu - sq = sq+right(i)**2 - 745 continue - 750 if(nrold.eq.number) go to 770 - 760 nrold = nrold+1 - go to 450 - 770 continue -c test whether the b-spline coefficients must be determined. - if(iback.ne.0) return -c backward substitution to obtain the b-spline coefficients as the -c solution of the linear system (rv) (cr) (ru)' = h. -c first step: solve the system (rv) (c1) = h. - k = 1 - do 780 i=1,nuu - call fpbacp(av1,av2,c(k),nv7,4,c(k),5,nv) - k = k+nv7 - 780 continue -c second step: solve the system (cr) (ru)' = (c1). - k = 0 - do 795 j=1,nv7 - k = k+1 - l = k - do 785 i=1,nuu - right(i) = c(l) - l = l+nv7 - 785 continue - call fpback(au,right,nuu,5,right,nu) - l = k - do 790 i=1,nuu - c(l) = right(i) - l = l+nv7 - 790 continue - 795 continue -c calculate from the conditions (2)-(3)-(4), the remaining b-spline -c coefficients. - 800 ncof = nu4*nv4 - j = ncof - do 805 l=1,nv4 - q(l) = dr01 - q(j) = dr11 - j = j-1 - 805 continue - i = nv4 - j = 0 - if(iop0.eq.0) go to 815 - do 810 l=1,nv4 - i = i+1 - q(i) = c0(l) - 810 continue - 815 if(nuu.eq.0) go to 835 - do 830 l=1,nuu - ii = i - do 820 k=1,nv7 - i = i+1 - j = j+1 - q(i) = c(j) - 820 continue - do 825 k=1,3 - ii = ii+1 - i = i+1 - q(i) = q(ii) - 825 continue - 830 continue - 835 if(iop1.eq.0) go to 845 - do 840 l=1,nv4 - i = i+1 - q(i) = c1(l) - 840 continue - 845 do 850 i=1,ncof - c(i) = q(i) - 850 continue -c calculate the quantities -c res(i,j) = (r(i,j) - s(u(i),v(j)))**2 , i=1,2,..,mu;j=1,2,..,mv -c fp = sumi=1,mu(sumj=1,mv(res(i,j))) -c fpu(r) = sum''i(sumj=1,mv(res(i,j))) , r=1,2,...,nu-7 -c tu(r+3) <= u(i) <= tu(r+4) -c fpv(r) = sumi=1,mu(sum''j(res(i,j))) , r=1,2,...,nv-7 -c tv(r+3) <= v(j) <= tv(r+4) - fp = 0. - do 890 i=1,nu - fpu(i) = 0. - 890 continue - do 900 i=1,nv - fpv(i) = 0. - 900 continue - ir = 0 - nroldu = 0 -c main loop for the different grid points. - do 950 i1=1,mu - numu = nru(i1) - numu1 = numu+1 - nroldv = 0 - do 940 i2=1,mv - numv = nrv(i2) - numv1 = numv+1 - ir = ir+1 -c evaluate s(u,v) at the current grid point by making the sum of the -c cross products of the non-zero b-splines at (u,v), multiplied with -c the appropiate b-spline coefficients. - term = 0. - k1 = numu*nv4+numv - do 920 l1=1,4 - k2 = k1 - fac = spu(i1,l1) - do 910 l2=1,4 - k2 = k2+1 - term = term+fac*spv(i2,l2)*c(k2) - 910 continue - k1 = k1+nv4 - 920 continue -c calculate the squared residual at the current grid point. - term = (r(ir)-term)**2 -c adjust the different parameters. - fp = fp+term - fpu(numu1) = fpu(numu1)+term - fpv(numv1) = fpv(numv1)+term - fac = term*half - if(numv.eq.nroldv) go to 930 - fpv(numv1) = fpv(numv1)-fac - fpv(numv) = fpv(numv)+fac - 930 nroldv = numv - if(numu.eq.nroldu) go to 940 - fpu(numu1) = fpu(numu1)-fac - fpu(numu) = fpu(numu)+fac - 940 continue - nroldu = numu - 950 continue - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpinst.f =================================================================== --- branches/Interpolate1D/fitpack/fpinst.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpinst.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,77 +0,0 @@ - subroutine fpinst(iopt,t,n,c,k,x,l,tt,nn,cc,nest) -c given the b-spline representation (knots t(j),j=1,2,...,n, b-spline -c coefficients c(j),j=1,2,...,n-k-1) of a spline of degree k, fpinst -c calculates the b-spline representation (knots tt(j),j=1,2,...,nn, -c b-spline coefficients cc(j),j=1,2,...,nn-k-1) of the same spline if -c an additional knot is inserted at the point x situated in the inter- -c val t(l)<=x2*k or l0) in such a way that -c - if p tends to infinity, sp(u,v) becomes the least-squares spline -c with given knots, satisfying the constraints. -c - if p tends to zero, sp(u,v) becomes the least-squares polynomial, -c satisfying the constraints. -c - the function f(p)=sumi=1,mu(sumj=1,mv((z(i,j)-sp(u(i),v(j)))**2) -c is continuous and strictly decreasing for p>0. -c -c ..scalar arguments.. - integer ifsu,ifsv,ifbu,ifbv,mu,mv,mz,nu,nv,nuest,nvest, - * nc,lwrk - real*8 z0,p,step,fp -c ..array arguments.. - integer ider(2),nru(mu),nrv(mv),iopt(3) - real*8 u(mu),v(mv),z(mz),dz(3),tu(nu),tv(nv),c(nc),fpu(nu),fpv(nv) - *, - * wrk(lwrk) -c ..local scalars.. - real*8 res,sq,sqq,step1,step2,three - integer i,id0,iop0,iop1,i1,j,l,laa,lau,lav1,lav2,lbb,lbu,lbv, - * lcc,lcs,lq,lri,lsu,lsv,l1,l2,mm,mvnu,number -c ..local arrays.. - integer nr(3) - real*8 delta(3),dzz(3),sum(3),a(6,6),g(6) -c ..function references.. - integer max0 -c ..subroutine references.. -c fpgrdi,fpsysy -c .. -c set constant - three = 3 -c we partition the working space - lsu = 1 - lsv = lsu+4*mu - lri = lsv+4*mv - mm = max0(nuest,mv+nvest) - lq = lri+mm - mvnu = nuest*(mv+nvest-8) - lau = lq+mvnu - lav1 = lau+5*nuest - lav2 = lav1+6*nvest - lbu = lav2+4*nvest - lbv = lbu+5*nuest - laa = lbv+5*nvest - lbb = laa+2*mv - lcc = lbb+2*nvest - lcs = lcc+nvest -c we calculate the smoothing spline sp(u,v) according to the input -c values dz(i),i=1,2,3. - iop0 = iopt(2) - iop1 = iopt(3) - call fpgrdi(ifsu,ifsv,ifbu,ifbv,0,u,mu,v,mv,z,mz,dz, - * iop0,iop1,tu,nu,tv,nv,p,c,nc,sq,fp,fpu,fpv,mm,mvnu, - * wrk(lsu),wrk(lsv),wrk(lri),wrk(lq),wrk(lau),wrk(lav1), - * wrk(lav2),wrk(lbu),wrk(lbv),wrk(laa),wrk(lbb), - * wrk(lcc),wrk(lcs),nru,nrv) - id0 = ider(1) - if(id0.ne.0) go to 5 - res = (z0-dz(1))**2 - fp = fp+res - sq = sq+res -c in case all derivative values dz(i) are given (step<=0) or in case -c we have spline interpolation, we accept this spline as a solution. - 5 if(step.le.0. .or. sq.le.0.) return - dzz(1) = dz(1) - dzz(2) = dz(2) - dzz(3) = dz(3) -c number denotes the number of derivative values dz(i) that still must -c be optimized. let us denote these parameters by g(j),j=1,...,number. - number = 0 - if(id0.gt.0) go to 10 - number = 1 - nr(1) = 1 - delta(1) = step - 10 if(iop0.eq.0) go to 20 - if(ider(2).ne.0) go to 20 - step2 = step*three/tu(5) - nr(number+1) = 2 - nr(number+2) = 3 - delta(number+1) = step2 - delta(number+2) = step2 - number = number+2 - 20 if(number.eq.0) return -c the sum of squared residuals sq is a quadratic polynomial in the -c parameters g(j). we determine the unknown coefficients of this -c polymomial by calculating (number+1)*(number+2)/2 different splines -c according to specific values for g(j). - do 30 i=1,number - l = nr(i) - step1 = delta(i) - dzz(l) = dz(l)+step1 - call fpgrdi(ifsu,ifsv,ifbu,ifbv,1,u,mu,v,mv,z,mz,dzz, - * iop0,iop1,tu,nu,tv,nv,p,c,nc,sum(i),fp,fpu,fpv,mm,mvnu, - * wrk(lsu),wrk(lsv),wrk(lri),wrk(lq),wrk(lau),wrk(lav1), - * wrk(lav2),wrk(lbu),wrk(lbv),wrk(laa),wrk(lbb), - * wrk(lcc),wrk(lcs),nru,nrv) - if(id0.eq.0) sum(i) = sum(i)+(z0-dzz(1))**2 - dzz(l) = dz(l)-step1 - call fpgrdi(ifsu,ifsv,ifbu,ifbv,1,u,mu,v,mv,z,mz,dzz, - * iop0,iop1,tu,nu,tv,nv,p,c,nc,sqq,fp,fpu,fpv,mm,mvnu, - * wrk(lsu),wrk(lsv),wrk(lri),wrk(lq),wrk(lau),wrk(lav1), - * wrk(lav2),wrk(lbu),wrk(lbv),wrk(laa),wrk(lbb), - * wrk(lcc),wrk(lcs),nru,nrv) - if(id0.eq.0) sqq = sqq+(z0-dzz(1))**2 - a(i,i) = (sum(i)+sqq-sq-sq)/step1**2 - if(a(i,i).le.0.) go to 80 - g(i) = (sqq-sum(i))/(step1+step1) - dzz(l) = dz(l) - 30 continue - if(number.eq.1) go to 60 - do 50 i=2,number - l1 = nr(i) - step1 = delta(i) - dzz(l1) = dz(l1)+step1 - i1 = i-1 - do 40 j=1,i1 - l2 = nr(j) - step2 = delta(j) - dzz(l2) = dz(l2)+step2 - call fpgrdi(ifsu,ifsv,ifbu,ifbv,1,u,mu,v,mv,z,mz,dzz, - * iop0,iop1,tu,nu,tv,nv,p,c,nc,sqq,fp,fpu,fpv,mm,mvnu, - * wrk(lsu),wrk(lsv),wrk(lri),wrk(lq),wrk(lau),wrk(lav1), - * wrk(lav2),wrk(lbu),wrk(lbv),wrk(laa),wrk(lbb), - * wrk(lcc),wrk(lcs),nru,nrv) - if(id0.eq.0) sqq = sqq+(z0-dzz(1))**2 - a(i,j) = (sq+sqq-sum(i)-sum(j))/(step1*step2) - dzz(l2) = dz(l2) - 40 continue - dzz(l1) = dz(l1) - 50 continue -c the optimal values g(j) are found as the solution of the system -c d (sq) / d (g(j)) = 0 , j=1,...,number. - 60 call fpsysy(a,number,g) - do 70 i=1,number - l = nr(i) - dz(l) = dz(l)+g(i) - 70 continue -c we determine the spline sp(u,v) according to the optimal values g(j). - 80 call fpgrdi(ifsu,ifsv,ifbu,ifbv,0,u,mu,v,mv,z,mz,dz, - * iop0,iop1,tu,nu,tv,nv,p,c,nc,sq,fp,fpu,fpv,mm,mvnu, - * wrk(lsu),wrk(lsv),wrk(lri),wrk(lq),wrk(lau),wrk(lav1), - * wrk(lav2),wrk(lbu),wrk(lbv),wrk(laa),wrk(lbb), - * wrk(lcc),wrk(lcs),nru,nrv) - if(id0.eq.0) fp = fp+(z0-dz(1))**2 - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpopsp.f =================================================================== --- branches/Interpolate1D/fitpack/fpopsp.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpopsp.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,211 +0,0 @@ - subroutine fpopsp(ifsu,ifsv,ifbu,ifbv,u,mu,v,mv,r,mr,r0,r1,dr, - * iopt,ider,tu,nu,tv,nv,nuest,nvest,p,step,c,nc,fp,fpu,fpv, - * nru,nrv,wrk,lwrk) -c given the set of function values r(i,j) defined on the rectangular -c grid (u(i),v(j)),i=1,2,...,mu;j=1,2,...,mv, fpopsp determines a -c smooth bicubic spline approximation with given knots tu(i),i=1,..,nu -c in the u-direction and tv(j),j=1,2,...,nv in the v-direction. this -c spline sp(u,v) will be periodic in the variable v and will satisfy -c the following constraints -c -c s(tu(1),v) = dr(1) , tv(4) <=v<= tv(nv-3) -c -c s(tu(nu),v) = dr(4) , tv(4) <=v<= tv(nv-3) -c -c and (if iopt(2) = 1) -c -c d s(tu(1),v) -c ------------ = dr(2)*cos(v)+dr(3)*sin(v) , tv(4) <=v<= tv(nv-3) -c d u -c -c and (if iopt(3) = 1) -c -c d s(tu(nu),v) -c ------------- = dr(5)*cos(v)+dr(6)*sin(v) , tv(4) <=v<= tv(nv-3) -c d u -c -c where the parameters dr(i) correspond to the derivative values at the -c poles as defined in subroutine spgrid. -c -c the b-spline coefficients of sp(u,v) are determined as the least- -c squares solution of an overdetermined linear system which depends -c on the value of p and on the values dr(i),i=1,...,6. the correspond- -c ing sum of squared residuals sq is a simple quadratic function in -c the variables dr(i). these may or may not be provided. the values -c dr(i) which are not given will be determined so as to minimize the -c resulting sum of squared residuals sq. in that case the user must -c provide some initial guess dr(i) and some estimate (dr(i)-step, -c dr(i)+step) of the range of possible values for these latter. -c -c sp(u,v) also depends on the parameter p (p>0) in such a way that -c - if p tends to infinity, sp(u,v) becomes the least-squares spline -c with given knots, satisfying the constraints. -c - if p tends to zero, sp(u,v) becomes the least-squares polynomial, -c satisfying the constraints. -c - the function f(p)=sumi=1,mu(sumj=1,mv((r(i,j)-sp(u(i),v(j)))**2) -c is continuous and strictly decreasing for p>0. -c -c ..scalar arguments.. - integer ifsu,ifsv,ifbu,ifbv,mu,mv,mr,nu,nv,nuest,nvest, - * nc,lwrk - real*8 r0,r1,p,fp -c ..array arguments.. - integer ider(4),nru(mu),nrv(mv),iopt(3) - real*8 u(mu),v(mv),r(mr),dr(6),tu(nu),tv(nv),c(nc),fpu(nu),fpv(nv) - *, - * wrk(lwrk),step(2) -c ..local scalars.. - real*8 res,sq,sqq,sq0,sq1,step1,step2,three - integer i,id0,iop0,iop1,i1,j,l,lau,lav1,lav2,la0,la1,lbu,lbv,lb0, - * lb1,lc0,lc1,lcs,lq,lri,lsu,lsv,l1,l2,mm,mvnu,number -c ..local arrays.. - integer nr(6) - real*8 delta(6),drr(6),sum(6),a(6,6),g(6) -c ..function references.. - integer max0 -c ..subroutine references.. -c fpgrsp,fpsysy -c .. -c set constant - three = 3 -c we partition the working space - lsu = 1 - lsv = lsu+4*mu - lri = lsv+4*mv - mm = max0(nuest,mv+nvest) - lq = lri+mm - mvnu = nuest*(mv+nvest-8) - lau = lq+mvnu - lav1 = lau+5*nuest - lav2 = lav1+6*nvest - lbu = lav2+4*nvest - lbv = lbu+5*nuest - la0 = lbv+5*nvest - la1 = la0+2*mv - lb0 = la1+2*mv - lb1 = lb0+2*nvest - lc0 = lb1+2*nvest - lc1 = lc0+nvest - lcs = lc1+nvest -c we calculate the smoothing spline sp(u,v) according to the input -c values dr(i),i=1,...,6. - iop0 = iopt(2) - iop1 = iopt(3) - id0 = ider(1) - id1 = ider(3) - call fpgrsp(ifsu,ifsv,ifbu,ifbv,0,u,mu,v,mv,r,mr,dr, - * iop0,iop1,tu,nu,tv,nv,p,c,nc,sq,fp,fpu,fpv,mm,mvnu, - * wrk(lsu),wrk(lsv),wrk(lri),wrk(lq),wrk(lau),wrk(lav1), - * wrk(lav2),wrk(lbu),wrk(lbv),wrk(la0),wrk(la1),wrk(lb0), - * wrk(lb1),wrk(lc0),wrk(lc1),wrk(lcs),nru,nrv) - sq0 = 0. - sq1 = 0. - if(id0.eq.0) sq0 = (r0-dr(1))**2 - if(id1.eq.0) sq1 = (r1-dr(4))**2 - sq = sq+sq0+sq1 -c in case all derivative values dr(i) are given (step<=0) or in case -c we have spline interpolation, we accept this spline as a solution. - if(sq.le.0.) return - if(step(1).le.0. .and. step(2).le.0.) return - do 10 i=1,6 - drr(i) = dr(i) - 10 continue -c number denotes the number of derivative values dr(i) that still must -c be optimized. let us denote these parameters by g(j),j=1,...,number. - number = 0 - if(id0.gt.0) go to 20 - number = 1 - nr(1) = 1 - delta(1) = step(1) - 20 if(iop0.eq.0) go to 30 - if(ider(2).ne.0) go to 30 - step2 = step(1)*three/(tu(5)-tu(4)) - nr(number+1) = 2 - nr(number+2) = 3 - delta(number+1) = step2 - delta(number+2) = step2 - number = number+2 - 30 if(id1.gt.0) go to 40 - number = number+1 - nr(number) = 4 - delta(number) = step(2) - 40 if(iop1.eq.0) go to 50 - if(ider(4).ne.0) go to 50 - step2 = step(2)*three/(tu(nu)-tu(nu-4)) - nr(number+1) = 5 - nr(number+2) = 6 - delta(number+1) = step2 - delta(number+2) = step2 - number = number+2 - 50 if(number.eq.0) return -c the sum of squared residulas sq is a quadratic polynomial in the -c parameters g(j). we determine the unknown coefficients of this -c polymomial by calculating (number+1)*(number+2)/2 different splines -c according to specific values for g(j). - do 60 i=1,number - l = nr(i) - step1 = delta(i) - drr(l) = dr(l)+step1 - call fpgrsp(ifsu,ifsv,ifbu,ifbv,1,u,mu,v,mv,r,mr,drr, - * iop0,iop1,tu,nu,tv,nv,p,c,nc,sum(i),fp,fpu,fpv,mm,mvnu, - * wrk(lsu),wrk(lsv),wrk(lri),wrk(lq),wrk(lau),wrk(lav1), - * wrk(lav2),wrk(lbu),wrk(lbv),wrk(la0),wrk(la1),wrk(lb0), - * wrk(lb1),wrk(lc0),wrk(lc1),wrk(lcs),nru,nrv) - if(id0.eq.0) sq0 = (r0-drr(1))**2 - if(id1.eq.0) sq1 = (r1-drr(4))**2 - sum(i) = sum(i)+sq0+sq1 - drr(l) = dr(l)-step1 - call fpgrsp(ifsu,ifsv,ifbu,ifbv,1,u,mu,v,mv,r,mr,drr, - * iop0,iop1,tu,nu,tv,nv,p,c,nc,sqq,fp,fpu,fpv,mm,mvnu, - * wrk(lsu),wrk(lsv),wrk(lri),wrk(lq),wrk(lau),wrk(lav1), - * wrk(lav2),wrk(lbu),wrk(lbv),wrk(la0),wrk(la1),wrk(lb0), - * wrk(lb1),wrk(lc0),wrk(lc1),wrk(lcs),nru,nrv) - if(id0.eq.0) sq0 = (r0-drr(1))**2 - if(id1.eq.0) sq1 = (r1-drr(4))**2 - sqq = sqq+sq0+sq1 - drr(l) = dr(l) - a(i,i) = (sum(i)+sqq-sq-sq)/step1**2 - if(a(i,i).le.0.) go to 110 - g(i) = (sqq-sum(i))/(step1+step1) - 60 continue - if(number.eq.1) go to 90 - do 80 i=2,number - l1 = nr(i) - step1 = delta(i) - drr(l1) = dr(l1)+step1 - i1 = i-1 - do 70 j=1,i1 - l2 = nr(j) - step2 = delta(j) - drr(l2) = dr(l2)+step2 - call fpgrsp(ifsu,ifsv,ifbu,ifbv,1,u,mu,v,mv,r,mr,drr, - * iop0,iop1,tu,nu,tv,nv,p,c,nc,sqq,fp,fpu,fpv,mm,mvnu, - * wrk(lsu),wrk(lsv),wrk(lri),wrk(lq),wrk(lau),wrk(lav1), - * wrk(lav2),wrk(lbu),wrk(lbv),wrk(la0),wrk(la1),wrk(lb0), - * wrk(lb1),wrk(lc0),wrk(lc1),wrk(lcs),nru,nrv) - if(id0.eq.0) sq0 = (r0-drr(1))**2 - if(id1.eq.0) sq1 = (r1-drr(4))**2 - sqq = sqq+sq0+sq1 - a(i,j) = (sq+sqq-sum(i)-sum(j))/(step1*step2) - drr(l2) = dr(l2) - 70 continue - drr(l1) = dr(l1) - 80 continue -c the optimal values g(j) are found as the solution of the system -c d (sq) / d (g(j)) = 0 , j=1,...,number. - 90 call fpsysy(a,number,g) - do 100 i=1,number - l = nr(i) - dr(l) = dr(l)+g(i) - 100 continue -c we determine the spline sp(u,v) according to the optimal values g(j). - 110 call fpgrsp(ifsu,ifsv,ifbu,ifbv,0,u,mu,v,mv,r,mr,dr, - * iop0,iop1,tu,nu,tv,nv,p,c,nc,sq,fp,fpu,fpv,mm,mvnu, - * wrk(lsu),wrk(lsv),wrk(lri),wrk(lq),wrk(lau),wrk(lav1), - * wrk(lav2),wrk(lbu),wrk(lbv),wrk(la0),wrk(la1),wrk(lb0), - * wrk(lb1),wrk(lc0),wrk(lc1),wrk(lcs),nru,nrv) - if(id0.eq.0) sq0 = (r0-dr(1))**2 - if(id1.eq.0) sq1 = (r1-dr(4))**2 - sq = sq+sq0+sq1 - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fporde.f =================================================================== --- branches/Interpolate1D/fitpack/fporde.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fporde.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,47 +0,0 @@ - subroutine fporde(x,y,m,kx,ky,tx,nx,ty,ny,nummer,index,nreg) -c subroutine fporde sorts the data points (x(i),y(i)),i=1,2,...,m -c according to the panel tx(l)<=x s we will increase the number of knots and compute the c -c corresponding least-squares curve until finally fp<=s. c -c the initial choice of knots depends on the value of s and iopt. c -c if s=0 we have spline interpolation; in that case the number of c -c knots equals nmax = m+k+1. c -c if s > 0 and c -c iopt=0 we first compute the least-squares polynomial curve of c -c degree k; n = nmin = 2*k+2 c -c iopt=1 we start with the set of knots found at the last c -c call of the routine, except for the case that s > fp0; then c -c we compute directly the polynomial curve of degree k. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c determine nmin, the number of knots for polynomial approximation. - nmin = 2*k1 - if(iopt.lt.0) go to 60 -c calculation of acc, the absolute tolerance for the root of f(p)=s. - acc = tol*s -c determine nmax, the number of knots for spline interpolation. - nmax = m+k1 - if(s.gt.0.) go to 45 -c if s=0, s(u) is an interpolating curve. -c test whether the required storage space exceeds the available one. - n = nmax - if(nmax.gt.nest) go to 420 -c find the position of the interior knots in case of interpolation. - 10 mk1 = m-k1 - if(mk1.eq.0) go to 60 - k3 = k/2 - i = k2 - j = k3+2 - if(k3*2.eq.k) go to 30 - do 20 l=1,mk1 - t(i) = u(j) - i = i+1 - j = j+1 - 20 continue - go to 60 - 30 do 40 l=1,mk1 - t(i) = (u(j)+u(j-1))*half - i = i+1 - j = j+1 - 40 continue - go to 60 -c if s>0 our initial choice of knots depends on the value of iopt. -c if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares -c polynomial curve which is a spline curve without interior knots. -c if iopt=1 and fp0>s we start computing the least squares spline curve -c according to the set of knots found at the last call of the routine. - 45 if(iopt.eq.0) go to 50 - if(n.eq.nmin) go to 50 - fp0 = fpint(n) - fpold = fpint(n-1) - nplus = nrdata(n) - if(fp0.gt.s) go to 60 - 50 n = nmin - fpold = 0. - nplus = 0 - nrdata(1) = m-2 -c main loop for the different sets of knots. m is a save upper bound -c for the number of trials. - 60 do 200 iter = 1,m - if(n.eq.nmin) ier = -2 -c find nrint, tne number of knot intervals. - nrint = n-nmin+1 -c find the position of the additional knots which are needed for -c the b-spline representation of s(u). - nk1 = n-k1 - i = n - do 70 j=1,k1 - t(j) = ub - t(i) = ue - i = i-1 - 70 continue -c compute the b-spline coefficients of the least-squares spline curve -c sinf(u). the observation matrix a is built up row by row and -c reduced to upper triangular form by givens transformations. -c at the same time fp=f(p=inf) is computed. - fp = 0. -c initialize the b-spline coefficients and the observation matrix a. - do 75 i=1,nc - z(i) = 0. - 75 continue - do 80 i=1,nk1 - do 80 j=1,k1 - a(i,j) = 0. - 80 continue - l = k1 - jj = 0 - do 130 it=1,m -c fetch the current data point u(it),x(it). - ui = u(it) - wi = w(it) - do 83 j=1,idim - jj = jj+1 - xi(j) = x(jj)*wi - 83 continue -c search for knot interval t(l) <= ui < t(l+1). - 85 if(ui.lt.t(l+1) .or. l.eq.nk1) go to 90 - l = l+1 - go to 85 -c evaluate the (k+1) non-zero b-splines at ui and store them in q. - 90 call fpbspl(t,n,k,ui,l,h) - do 95 i=1,k1 - q(it,i) = h(i) - h(i) = h(i)*wi - 95 continue -c rotate the new row of the observation matrix into triangle. - j = l-k1 - do 110 i=1,k1 - j = j+1 - piv = h(i) - if(piv.eq.0.) go to 110 -c calculate the parameters of the givens transformation. - call fpgivs(piv,a(j,1),cos,sin) -c transformations to right hand side. - j1 = j - do 97 j2 =1,idim - call fprota(cos,sin,xi(j2),z(j1)) - j1 = j1+n - 97 continue - if(i.eq.k1) go to 120 - i2 = 1 - i3 = i+1 - do 100 i1 = i3,k1 - i2 = i2+1 -c transformations to left hand side. - call fprota(cos,sin,h(i1),a(j,i2)) - 100 continue - 110 continue -c add contribution of this row to the sum of squares of residual -c right hand sides. - 120 do 125 j2=1,idim - fp = fp+xi(j2)**2 - 125 continue - 130 continue - if(ier.eq.(-2)) fp0 = fp - fpint(n) = fp0 - fpint(n-1) = fpold - nrdata(n) = nplus -c backward substitution to obtain the b-spline coefficients. - j1 = 1 - do 135 j2=1,idim - call fpback(a,z(j1),nk1,k1,c(j1),nest) - j1 = j1+n - 135 continue -c test whether the approximation sinf(u) is an acceptable solution. - if(iopt.lt.0) go to 440 - fpms = fp-s - if(abs(fpms).lt.acc) go to 440 -c if f(p=inf) < s accept the choice of knots. - if(fpms.lt.0.) go to 250 -c if n = nmax, sinf(u) is an interpolating spline curve. - if(n.eq.nmax) go to 430 -c increase the number of knots. -c if n=nest we cannot increase the number of knots because of -c the storage capacity limitation. - if(n.eq.nest) go to 420 -c determine the number of knots nplus we are going to add. - if(ier.eq.0) go to 140 - nplus = 1 - ier = 0 - go to 150 - 140 npl1 = nplus*2 - rn = nplus - if(fpold-fp.gt.acc) npl1 = rn*fpms/(fpold-fp) - nplus = min0(nplus*2,max0(npl1,nplus/2,1)) - 150 fpold = fp -c compute the sum of squared residuals for each knot interval -c t(j+k) <= u(i) <= t(j+k+1) and store it in fpint(j),j=1,2,...nrint. - fpart = 0. - i = 1 - l = k2 - new = 0 - jj = 0 - do 180 it=1,m - if(u(it).lt.t(l) .or. l.gt.nk1) go to 160 - new = 1 - l = l+1 - 160 term = 0. - l0 = l-k2 - do 175 j2=1,idim - fac = 0. - j1 = l0 - do 170 j=1,k1 - j1 = j1+1 - fac = fac+c(j1)*q(it,j) - 170 continue - jj = jj+1 - term = term+(w(it)*(fac-x(jj)))**2 - l0 = l0+n - 175 continue - fpart = fpart+term - if(new.eq.0) go to 180 - store = term*half - fpint(i) = fpart-store - i = i+1 - fpart = store - new = 0 - 180 continue - fpint(nrint) = fpart - do 190 l=1,nplus -c add a new knot. - call fpknot(u,m,t,n,fpint,nrdata,nrint,nest,1) -c if n=nmax we locate the knots as for interpolation - if(n.eq.nmax) go to 10 -c test whether we cannot further increase the number of knots. - if(n.eq.nest) go to 200 - 190 continue -c restart the computations with the new set of knots. - 200 continue -c test whether the least-squares kth degree polynomial curve is a -c solution of our approximation problem. - 250 if(ier.eq.(-2)) go to 440 -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 2: determination of the smoothing spline curve sp(u). c -c ********************************************************** c -c we have determined the number of knots and their position. c -c we now compute the b-spline coefficients of the smoothing curve c -c sp(u). the observation matrix a is extended by the rows of matrix c -c b expressing that the kth derivative discontinuities of sp(u) at c -c the interior knots t(k+2),...t(n-k-1) must be zero. the corres- c -c ponding weights of these additional rows are set to 1/p. c -c iteratively we then have to determine the value of p such that f(p),c -c the sum of squared residuals be = s. we already know that the least c -c squares kth degree polynomial curve corresponds to p=0, and that c -c the least-squares spline curve corresponds to p=infinity. the c -c iteration process which is proposed here, makes use of rational c -c interpolation. since f(p) is a convex and strictly decreasing c -c function of p, it can be approximated by a rational function c -c r(p) = (u*p+v)/(p+w). three values of p(p1,p2,p3) with correspond- c -c ing values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used c -c to calculate the new value of p such that r(p)=s. convergence is c -c guaranteed by taking f1>0 and f3<0. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c evaluate the discontinuity jump of the kth derivative of the -c b-splines at the knots t(l),l=k+2,...n-k-1 and store in b. - call fpdisc(t,n,k2,b,nest) -c initial value for p. - p1 = 0. - f1 = fp0-s - p3 = -one - f3 = fpms - p = 0. - do 252 i=1,nk1 - p = p+a(i,1) - 252 continue - rn = nk1 - p = rn/p - ich1 = 0 - ich3 = 0 - n8 = n-nmin -c iteration process to find the root of f(p) = s. - do 360 iter=1,maxit -c the rows of matrix b with weight 1/p are rotated into the -c triangularised observation matrix a which is stored in g. - pinv = one/p - do 255 i=1,nc - c(i) = z(i) - 255 continue - do 260 i=1,nk1 - g(i,k2) = 0. - do 260 j=1,k1 - g(i,j) = a(i,j) - 260 continue - do 300 it=1,n8 -c the row of matrix b is rotated into triangle by givens transformation - do 270 i=1,k2 - h(i) = b(it,i)*pinv - 270 continue - do 275 j=1,idim - xi(j) = 0. - 275 continue - do 290 j=it,nk1 - piv = h(1) -c calculate the parameters of the givens transformation. - call fpgivs(piv,g(j,1),cos,sin) -c transformations to right hand side. - j1 = j - do 277 j2=1,idim - call fprota(cos,sin,xi(j2),c(j1)) - j1 = j1+n - 277 continue - if(j.eq.nk1) go to 300 - i2 = k1 - if(j.gt.n8) i2 = nk1-j - do 280 i=1,i2 -c transformations to left hand side. - i1 = i+1 - call fprota(cos,sin,h(i1),g(j,i1)) - h(i) = h(i1) - 280 continue - h(i2+1) = 0. - 290 continue - 300 continue -c backward substitution to obtain the b-spline coefficients. - j1 = 1 - do 305 j2=1,idim - call fpback(g,c(j1),nk1,k2,c(j1),nest) - j1 =j1+n - 305 continue -c computation of f(p). - fp = 0. - l = k2 - jj = 0 - do 330 it=1,m - if(u(it).lt.t(l) .or. l.gt.nk1) go to 310 - l = l+1 - 310 l0 = l-k2 - term = 0. - do 325 j2=1,idim - fac = 0. - j1 = l0 - do 320 j=1,k1 - j1 = j1+1 - fac = fac+c(j1)*q(it,j) - 320 continue - jj = jj+1 - term = term+(fac-x(jj))**2 - l0 = l0+n - 325 continue - fp = fp+term*w(it)**2 - 330 continue -c test whether the approximation sp(u) is an acceptable solution. - fpms = fp-s - if(abs(fpms).lt.acc) go to 440 -c test whether the maximal number of iterations is reached. - if(iter.eq.maxit) go to 400 -c carry out one more step of the iteration process. - p2 = p - f2 = fpms - if(ich3.ne.0) go to 340 - if((f2-f3).gt.acc) go to 335 -c our initial choice of p is too large. - p3 = p2 - f3 = f2 - p = p*con4 - if(p.le.p1) p=p1*con9 + p2*con1 - go to 360 - 335 if(f2.lt.0.) ich3=1 - 340 if(ich1.ne.0) go to 350 - if((f1-f2).gt.acc) go to 345 -c our initial choice of p is too small - p1 = p2 - f1 = f2 - p = p/con4 - if(p3.lt.0.) go to 360 - if(p.ge.p3) p = p2*con1 + p3*con9 - go to 360 - 345 if(f2.gt.0.) ich1=1 -c test whether the iteration process proceeds as theoretically -c expected. - 350 if(f2.ge.f1 .or. f2.le.f3) go to 410 -c find the new value for p. - p = fprati(p1,f1,p2,f2,p3,f3) - 360 continue -c error codes and messages. - 400 ier = 3 - go to 440 - 410 ier = 2 - go to 440 - 420 ier = 1 - go to 440 - 430 ier = -1 - 440 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fppasu.f =================================================================== --- branches/Interpolate1D/fitpack/fppasu.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fppasu.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,392 +0,0 @@ - subroutine fppasu(iopt,ipar,idim,u,mu,v,mv,z,mz,s,nuest,nvest, - * tol,maxit,nc,nu,tu,nv,tv,c,fp,fp0,fpold,reducu,reducv,fpintu, - * fpintv,lastdi,nplusu,nplusv,nru,nrv,nrdatu,nrdatv,wrk,lwrk,ier) -c .. -c ..scalar arguments.. - real*8 s,tol,fp,fp0,fpold,reducu,reducv - integer iopt,idim,mu,mv,mz,nuest,nvest,maxit,nc,nu,nv,lastdi, - * nplusu,nplusv,lwrk,ier -c ..array arguments.. - real*8 u(mu),v(mv),z(mz*idim),tu(nuest),tv(nvest),c(nc*idim), - * fpintu(nuest),fpintv(nvest),wrk(lwrk) - integer ipar(2),nrdatu(nuest),nrdatv(nvest),nru(mu),nrv(mv) -c ..local scalars - real*8 acc,fpms,f1,f2,f3,p,p1,p2,p3,rn,one,con1,con9,con4, - * peru,perv,ub,ue,vb,ve - integer i,ich1,ich3,ifbu,ifbv,ifsu,ifsv,iter,j,lau1,lav1,laa, - * l,lau,lav,lbu,lbv,lq,lri,lsu,lsv,l1,l2,l3,l4,mm,mpm,mvnu,ncof, - * nk1u,nk1v,nmaxu,nmaxv,nminu,nminv,nplu,nplv,npl1,nrintu, - * nrintv,nue,nuk,nve,nuu,nvv -c ..function references.. - real*8 abs,fprati - integer max0,min0 -c ..subroutine references.. -c fpgrpa,fpknot -c .. -c set constants - one = 1 - con1 = 0.1e0 - con9 = 0.9e0 - con4 = 0.4e-01 -c set boundaries of the approximation domain - ub = u(1) - ue = u(mu) - vb = v(1) - ve = v(mv) -c we partition the working space. - lsu = 1 - lsv = lsu+mu*4 - lri = lsv+mv*4 - mm = max0(nuest,mv) - lq = lri+mm*idim - mvnu = nuest*mv*idim - lau = lq+mvnu - nuk = nuest*5 - lbu = lau+nuk - lav = lbu+nuk - nuk = nvest*5 - lbv = lav+nuk - laa = lbv+nuk - lau1 = lau - if(ipar(1).eq.0) go to 10 - peru = ue-ub - lau1 = laa - laa = laa+4*nuest - 10 lav1 = lav - if(ipar(2).eq.0) go to 20 - perv = ve-vb - lav1 = laa -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 1: determination of the number of knots and their position. c -c **************************************************************** c -c given a set of knots we compute the least-squares spline sinf(u,v), c -c and the corresponding sum of squared residuals fp=f(p=inf). c -c if iopt=-1 sinf(u,v) is the requested approximation. c -c if iopt=0 or iopt=1 we check whether we can accept the knots: c -c if fp <=s we will continue with the current set of knots. c -c if fp > s we will increase the number of knots and compute the c -c corresponding least-squares spline until finally fp<=s. c -c the initial choice of knots depends on the value of s and iopt. c -c if s=0 we have spline interpolation; in that case the number of c -c knots equals nmaxu = mu+4+2*ipar(1) and nmaxv = mv+4+2*ipar(2) c -c if s>0 and c -c *iopt=0 we first compute the least-squares polynomial c -c nu=nminu=8 and nv=nminv=8 c -c *iopt=1 we start with the knots found at the last call of the c -c routine, except for the case that s > fp0; then we can compute c -c the least-squares polynomial directly. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c determine the number of knots for polynomial approximation. - 20 nminu = 8 - nminv = 8 - if(iopt.lt.0) go to 100 -c acc denotes the absolute tolerance for the root of f(p)=s. - acc = tol*s -c find nmaxu and nmaxv which denote the number of knots in u- and v- -c direction in case of spline interpolation. - nmaxu = mu+4+2*ipar(1) - nmaxv = mv+4+2*ipar(2) -c find nue and nve which denote the maximum number of knots -c allowed in each direction - nue = min0(nmaxu,nuest) - nve = min0(nmaxv,nvest) - if(s.gt.0.) go to 60 -c if s = 0, s(u,v) is an interpolating spline. - nu = nmaxu - nv = nmaxv -c test whether the required storage space exceeds the available one. - if(nv.gt.nvest .or. nu.gt.nuest) go to 420 -c find the position of the interior knots in case of interpolation. -c the knots in the u-direction. - nuu = nu-8 - if(nuu.eq.0) go to 40 - i = 5 - j = 3-ipar(1) - do 30 l=1,nuu - tu(i) = u(j) - i = i+1 - j = j+1 - 30 continue -c the knots in the v-direction. - 40 nvv = nv-8 - if(nvv.eq.0) go to 60 - i = 5 - j = 3-ipar(2) - do 50 l=1,nvv - tv(i) = v(j) - i = i+1 - j = j+1 - 50 continue - go to 100 -c if s > 0 our initial choice of knots depends on the value of iopt. - 60 if(iopt.eq.0) go to 90 - if(fp0.le.s) go to 90 -c if iopt=1 and fp0 > s we start computing the least- squares spline -c according to the set of knots found at the last call of the routine. -c we determine the number of grid coordinates u(i) inside each knot -c interval (tu(l),tu(l+1)). - l = 5 - j = 1 - nrdatu(1) = 0 - mpm = mu-1 - do 70 i=2,mpm - nrdatu(j) = nrdatu(j)+1 - if(u(i).lt.tu(l)) go to 70 - nrdatu(j) = nrdatu(j)-1 - l = l+1 - j = j+1 - nrdatu(j) = 0 - 70 continue -c we determine the number of grid coordinates v(i) inside each knot -c interval (tv(l),tv(l+1)). - l = 5 - j = 1 - nrdatv(1) = 0 - mpm = mv-1 - do 80 i=2,mpm - nrdatv(j) = nrdatv(j)+1 - if(v(i).lt.tv(l)) go to 80 - nrdatv(j) = nrdatv(j)-1 - l = l+1 - j = j+1 - nrdatv(j) = 0 - 80 continue - go to 100 -c if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares -c polynomial (which is a spline without interior knots). - 90 nu = nminu - nv = nminv - nrdatu(1) = mu-2 - nrdatv(1) = mv-2 - lastdi = 0 - nplusu = 0 - nplusv = 0 - fp0 = 0. - fpold = 0. - reducu = 0. - reducv = 0. - 100 mpm = mu+mv - ifsu = 0 - ifsv = 0 - ifbu = 0 - ifbv = 0 - p = -one -c main loop for the different sets of knots.mpm=mu+mv is a save upper -c bound for the number of trials. - do 250 iter=1,mpm - if(nu.eq.nminu .and. nv.eq.nminv) ier = -2 -c find nrintu (nrintv) which is the number of knot intervals in the -c u-direction (v-direction). - nrintu = nu-nminu+1 - nrintv = nv-nminv+1 -c find ncof, the number of b-spline coefficients for the current set -c of knots. - nk1u = nu-4 - nk1v = nv-4 - ncof = nk1u*nk1v -c find the position of the additional knots which are needed for the -c b-spline representation of s(u,v). - if(ipar(1).ne.0) go to 110 - i = nu - do 105 j=1,4 - tu(j) = ub - tu(i) = ue - i = i-1 - 105 continue - go to 120 - 110 l1 = 4 - l2 = l1 - l3 = nu-3 - l4 = l3 - tu(l2) = ub - tu(l3) = ue - do 115 j=1,3 - l1 = l1+1 - l2 = l2-1 - l3 = l3+1 - l4 = l4-1 - tu(l2) = tu(l4)-peru - tu(l3) = tu(l1)+peru - 115 continue - 120 if(ipar(2).ne.0) go to 130 - i = nv - do 125 j=1,4 - tv(j) = vb - tv(i) = ve - i = i-1 - 125 continue - go to 140 - 130 l1 = 4 - l2 = l1 - l3 = nv-3 - l4 = l3 - tv(l2) = vb - tv(l3) = ve - do 135 j=1,3 - l1 = l1+1 - l2 = l2-1 - l3 = l3+1 - l4 = l4-1 - tv(l2) = tv(l4)-perv - tv(l3) = tv(l1)+perv - 135 continue -c find the least-squares spline sinf(u,v) and calculate for each knot -c interval tu(j+3)<=u<=tu(j+4) (tv(j+3)<=v<=tv(j+4)) the sum -c of squared residuals fpintu(j),j=1,2,...,nu-7 (fpintv(j),j=1,2,... -c ,nv-7) for the data points having their absciss (ordinate)-value -c belonging to that interval. -c fp gives the total sum of squared residuals. - 140 call fpgrpa(ifsu,ifsv,ifbu,ifbv,idim,ipar,u,mu,v,mv,z,mz,tu, - * nu,tv,nv,p,c,nc,fp,fpintu,fpintv,mm,mvnu,wrk(lsu),wrk(lsv), - * wrk(lri),wrk(lq),wrk(lau),wrk(lau1),wrk(lav),wrk(lav1), - * wrk(lbu),wrk(lbv),nru,nrv) - if(ier.eq.(-2)) fp0 = fp -c test whether the least-squares spline is an acceptable solution. - if(iopt.lt.0) go to 440 - fpms = fp-s - if(abs(fpms) .lt. acc) go to 440 -c if f(p=inf) < s, we accept the choice of knots. - if(fpms.lt.0.) go to 300 -c if nu=nmaxu and nv=nmaxv, sinf(u,v) is an interpolating spline. - if(nu.eq.nmaxu .and. nv.eq.nmaxv) go to 430 -c increase the number of knots. -c if nu=nue and nv=nve we cannot further increase the number of knots -c because of the storage capacity limitation. - if(nu.eq.nue .and. nv.eq.nve) go to 420 - ier = 0 -c adjust the parameter reducu or reducv according to the direction -c in which the last added knots were located. - if (lastdi.lt.0) go to 150 - if (lastdi.eq.0) go to 170 - go to 160 - 150 reducu = fpold-fp - go to 170 - 160 reducv = fpold-fp -c store the sum of squared residuals for the current set of knots. - 170 fpold = fp -c find nplu, the number of knots we should add in the u-direction. - nplu = 1 - if(nu.eq.nminu) go to 180 - npl1 = nplusu*2 - rn = nplusu - if(reducu.gt.acc) npl1 = rn*fpms/reducu - nplu = min0(nplusu*2,max0(npl1,nplusu/2,1)) -c find nplv, the number of knots we should add in the v-direction. - 180 nplv = 1 - if(nv.eq.nminv) go to 190 - npl1 = nplusv*2 - rn = nplusv - if(reducv.gt.acc) npl1 = rn*fpms/reducv - nplv = min0(nplusv*2,max0(npl1,nplusv/2,1)) - 190 if (nplu.lt.nplv) go to 210 - if (nplu.eq.nplv) go to 200 - go to 230 - 200 if(lastdi.lt.0) go to 230 - 210 if(nu.eq.nue) go to 230 -c addition in the u-direction. - lastdi = -1 - nplusu = nplu - ifsu = 0 - do 220 l=1,nplusu -c add a new knot in the u-direction - call fpknot(u,mu,tu,nu,fpintu,nrdatu,nrintu,nuest,1) -c test whether we cannot further increase the number of knots in the -c u-direction. - if(nu.eq.nue) go to 250 - 220 continue - go to 250 - 230 if(nv.eq.nve) go to 210 -c addition in the v-direction. - lastdi = 1 - nplusv = nplv - ifsv = 0 - do 240 l=1,nplusv -c add a new knot in the v-direction. - call fpknot(v,mv,tv,nv,fpintv,nrdatv,nrintv,nvest,1) -c test whether we cannot further increase the number of knots in the -c v-direction. - if(nv.eq.nve) go to 250 - 240 continue -c restart the computations with the new set of knots. - 250 continue -c test whether the least-squares polynomial is a solution of our -c approximation problem. - 300 if(ier.eq.(-2)) go to 440 -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 2: determination of the smoothing spline sp(u,v) c -c ***************************************************** c -c we have determined the number of knots and their position. we now c -c compute the b-spline coefficients of the smoothing spline sp(u,v). c -c this smoothing spline varies with the parameter p in such a way thatc -c f(p)=suml=1,idim(sumi=1,mu(sumj=1,mv((z(i,j,l)-sp(u(i),v(j),l))**2) c -c is a continuous, strictly decreasing function of p. moreover the c -c least-squares polynomial corresponds to p=0 and the least-squares c -c spline to p=infinity. iteratively we then have to determine the c -c positive value of p such that f(p)=s. the process which is proposed c -c here makes use of rational interpolation. f(p) is approximated by a c -c rational function r(p)=(u*p+v)/(p+w); three values of p (p1,p2,p3) c -c with corresponding values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s)c -c are used to calculate the new value of p such that r(p)=s. c -c convergence is guaranteed by taking f1 > 0 and f3 < 0. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c initial value for p. - p1 = 0. - f1 = fp0-s - p3 = -one - f3 = fpms - p = one - ich1 = 0 - ich3 = 0 -c iteration process to find the root of f(p)=s. - do 350 iter = 1,maxit -c find the smoothing spline sp(u,v) and the corresponding sum of -c squared residuals fp. - call fpgrpa(ifsu,ifsv,ifbu,ifbv,idim,ipar,u,mu,v,mv,z,mz,tu, - * nu,tv,nv,p,c,nc,fp,fpintu,fpintv,mm,mvnu,wrk(lsu),wrk(lsv), - * wrk(lri),wrk(lq),wrk(lau),wrk(lau1),wrk(lav),wrk(lav1), - * wrk(lbu),wrk(lbv),nru,nrv) -c test whether the approximation sp(u,v) is an acceptable solution. - fpms = fp-s - if(abs(fpms).lt.acc) go to 440 -c test whether the maximum allowable number of iterations has been -c reached. - if(iter.eq.maxit) go to 400 -c carry out one more step of the iteration process. - p2 = p - f2 = fpms - if(ich3.ne.0) go to 320 - if((f2-f3).gt.acc) go to 310 -c our initial choice of p is too large. - p3 = p2 - f3 = f2 - p = p*con4 - if(p.le.p1) p = p1*con9 + p2*con1 - go to 350 - 310 if(f2.lt.0.) ich3 = 1 - 320 if(ich1.ne.0) go to 340 - if((f1-f2).gt.acc) go to 330 -c our initial choice of p is too small - p1 = p2 - f1 = f2 - p = p/con4 - if(p3.lt.0.) go to 350 - if(p.ge.p3) p = p2*con1 + p3*con9 - go to 350 -c test whether the iteration process proceeds as theoretically -c expected. - 330 if(f2.gt.0.) ich1 = 1 - 340 if(f2.ge.f1 .or. f2.le.f3) go to 410 -c find the new value of p. - p = fprati(p1,f1,p2,f2,p3,f3) - 350 continue -c error codes and messages. - 400 ier = 3 - go to 440 - 410 ier = 2 - go to 440 - 420 ier = 1 - go to 440 - 430 ier = -1 - fp = 0. - 440 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpperi.f =================================================================== --- branches/Interpolate1D/fitpack/fpperi.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpperi.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,616 +0,0 @@ - subroutine fpperi(iopt,x,y,w,m,k,s,nest,tol,maxit,k1,k2,n,t,c, - * fp,fpint,z,a1,a2,b,g1,g2,q,nrdata,ier) -c .. -c ..scalar arguments.. - real*8 s,tol,fp - integer iopt,m,k,nest,maxit,k1,k2,n,ier -c ..array arguments.. - real*8 x(m),y(m),w(m),t(nest),c(nest),fpint(nest),z(nest), - * a1(nest,k1),a2(nest,k),b(nest,k2),g1(nest,k2),g2(nest,k1), - * q(m,k1) - integer nrdata(nest) -c ..local scalars.. - real*8 acc,cos,c1,d1,fpart,fpms,fpold,fp0,f1,f2,f3,p,per,pinv,piv, - * - * p1,p2,p3,sin,store,term,wi,xi,yi,rn,one,con1,con4,con9,half - integer i,ich1,ich3,ij,ik,it,iter,i1,i2,i3,j,jk,jper,j1,j2,kk, - * kk1,k3,l,l0,l1,l5,mm,m1,new,nk1,nk2,nmax,nmin,nplus,npl1, - * nrint,n10,n11,n7,n8 -c ..local arrays.. - real*8 h(6),h1(7),h2(6) -c ..function references.. - real*8 abs,fprati - integer max0,min0 -c ..subroutine references.. -c fpbacp,fpbspl,fpgivs,fpdisc,fpknot,fprota -c .. -c set constants - one = 0.1e+01 - con1 = 0.1e0 - con9 = 0.9e0 - con4 = 0.4e-01 - half = 0.5e0 -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 1: determination of the number of knots and their position c -c ************************************************************** c -c given a set of knots we compute the least-squares periodic spline c -c sinf(x). if the sum f(p=inf) <= s we accept the choice of knots. c -c the initial choice of knots depends on the value of s and iopt. c -c if s=0 we have spline interpolation; in that case the number of c -c knots equals nmax = m+2*k. c -c if s > 0 and c -c iopt=0 we first compute the least-squares polynomial of c -c degree k; n = nmin = 2*k+2. since s(x) must be periodic we c -c find that s(x) is a constant function. c -c iopt=1 we start with the set of knots found at the last c -c call of the routine, except for the case that s > fp0; then c -c we compute directly the least-squares periodic polynomial. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - m1 = m-1 - kk = k - kk1 = k1 - k3 = 3*k+1 - nmin = 2*k1 -c determine the length of the period of s(x). - per = x(m)-x(1) - if(iopt.lt.0) go to 50 -c calculation of acc, the absolute tolerance for the root of f(p)=s. - acc = tol*s -c determine nmax, the number of knots for periodic spline interpolation - nmax = m+2*k - if(s.gt.0. .or. nmax.eq.nmin) go to 30 -c if s=0, s(x) is an interpolating spline. - n = nmax -c test whether the required storage space exceeds the available one. - if(n.gt.nest) go to 620 -c find the position of the interior knots in case of interpolation. - 5 if((k/2)*2 .eq. k) go to 20 - do 10 i=2,m1 - j = i+k - t(j) = x(i) - 10 continue - if(s.gt.0.) go to 50 - kk = k-1 - kk1 = k - if(kk.gt.0) go to 50 - t(1) = t(m)-per - t(2) = x(1) - t(m+1) = x(m) - t(m+2) = t(3)+per - do 15 i=1,m1 - c(i) = y(i) - 15 continue - c(m) = c(1) - fp = 0. - fpint(n) = fp0 - fpint(n-1) = 0. - nrdata(n) = 0 - go to 630 - 20 do 25 i=2,m1 - j = i+k - t(j) = (x(i)+x(i-1))*half - 25 continue - go to 50 -c if s > 0 our initial choice depends on the value of iopt. -c if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares -c periodic polynomial. (i.e. a constant function). -c if iopt=1 and fp0>s we start computing the least-squares periodic -c spline according the set of knots found at the last call of the -c routine. - 30 if(iopt.eq.0) go to 35 - if(n.eq.nmin) go to 35 - fp0 = fpint(n) - fpold = fpint(n-1) - nplus = nrdata(n) - if(fp0.gt.s) go to 50 -c the case that s(x) is a constant function is treated separetely. -c find the least-squares constant c1 and compute fp0 at the same time. - 35 fp0 = 0. - d1 = 0. - c1 = 0. - do 40 it=1,m1 - wi = w(it) - yi = y(it)*wi - call fpgivs(wi,d1,cos,sin) - call fprota(cos,sin,yi,c1) - fp0 = fp0+yi**2 - 40 continue - c1 = c1/d1 -c test whether that constant function is a solution of our problem. - fpms = fp0-s - if(fpms.lt.acc .or. nmax.eq.nmin) go to 640 - fpold = fp0 -c test whether the required storage space exceeds the available one. - if(nmin.ge.nest) go to 620 -c start computing the least-squares periodic spline with one -c interior knot. - nplus = 1 - n = nmin+1 - mm = (m+1)/2 - t(k2) = x(mm) - nrdata(1) = mm-2 - nrdata(2) = m1-mm -c main loop for the different sets of knots. m is a save upper -c bound for the number of trials. - 50 do 340 iter=1,m -c find nrint, the number of knot intervals. - nrint = n-nmin+1 -c find the position of the additional knots which are needed for -c the b-spline representation of s(x). if we take -c t(k+1) = x(1), t(n-k) = x(m) -c t(k+1-j) = t(n-k-j) - per, j=1,2,...k -c t(n-k+j) = t(k+1+j) + per, j=1,2,...k -c then s(x) is a periodic spline with period per if the b-spline -c coefficients satisfy the following conditions -c c(n7+j) = c(j), j=1,...k (**) with n7=n-2*k-1. - t(k1) = x(1) - nk1 = n-k1 - nk2 = nk1+1 - t(nk2) = x(m) - do 60 j=1,k - i1 = nk2+j - i2 = nk2-j - j1 = k1+j - j2 = k1-j - t(i1) = t(j1)+per - t(j2) = t(i2)-per - 60 continue -c compute the b-spline coefficients c(j),j=1,...n7 of the least-squares -c periodic spline sinf(x). the observation matrix a is built up row -c by row while taking into account condition (**) and is reduced to -c triangular form by givens transformations . -c at the same time fp=f(p=inf) is computed. -c the n7 x n7 triangularised upper matrix a has the form -c ! a1 ' ! -c a = ! ' a2 ! -c ! 0 ' ! -c with a2 a n7 x k matrix and a1 a n10 x n10 upper triangular -c matrix of bandwith k+1 ( n10 = n7-k). -c initialization. - do 70 i=1,nk1 - z(i) = 0. - do 70 j=1,kk1 - a1(i,j) = 0. - 70 continue - n7 = nk1-k - n10 = n7-kk - jper = 0 - fp = 0. - l = k1 - do 290 it=1,m1 -c fetch the current data point x(it),y(it) - xi = x(it) - wi = w(it) - yi = y(it)*wi -c search for knot interval t(l) <= xi < t(l+1). - 80 if(xi.lt.t(l+1)) go to 85 - l = l+1 - go to 80 -c evaluate the (k+1) non-zero b-splines at xi and store them in q. - 85 call fpbspl(t,n,k,xi,l,h) - do 90 i=1,k1 - q(it,i) = h(i) - h(i) = h(i)*wi - 90 continue - l5 = l-k1 -c test whether the b-splines nj,k+1(x),j=1+n7,...nk1 are all zero at xi - if(l5.lt.n10) go to 285 - if(jper.ne.0) go to 160 -c initialize the matrix a2. - do 95 i=1,n7 - do 95 j=1,kk - a2(i,j) = 0. - 95 continue - jk = n10+1 - do 110 i=1,kk - ik = jk - do 100 j=1,kk1 - if(ik.le.0) go to 105 - a2(ik,i) = a1(ik,j) - ik = ik-1 - 100 continue - 105 jk = jk+1 - 110 continue - jper = 1 -c if one of the b-splines nj,k+1(x),j=n7+1,...nk1 is not zero at xi -c we take account of condition (**) for setting up the new row -c of the observation matrix a. this row is stored in the arrays h1 -c (the part with respect to a1) and h2 (the part with -c respect to a2). - 160 do 170 i=1,kk - h1(i) = 0. - h2(i) = 0. - 170 continue - h1(kk1) = 0. - j = l5-n10 - do 210 i=1,kk1 - j = j+1 - l0 = j - 180 l1 = l0-kk - if(l1.le.0) go to 200 - if(l1.le.n10) go to 190 - l0 = l1-n10 - go to 180 - 190 h1(l1) = h(i) - go to 210 - 200 h2(l0) = h2(l0)+h(i) - 210 continue -c rotate the new row of the observation matrix into triangle -c by givens transformations. - if(n10.le.0) go to 250 -c rotation with the rows 1,2,...n10 of matrix a. - do 240 j=1,n10 - piv = h1(1) - if(piv.ne.0.) go to 214 - do 212 i=1,kk - h1(i) = h1(i+1) - 212 continue - h1(kk1) = 0. - go to 240 -c calculate the parameters of the givens transformation. - 214 call fpgivs(piv,a1(j,1),cos,sin) -c transformation to the right hand side. - call fprota(cos,sin,yi,z(j)) -c transformations to the left hand side with respect to a2. - do 220 i=1,kk - call fprota(cos,sin,h2(i),a2(j,i)) - 220 continue - if(j.eq.n10) go to 250 - i2 = min0(n10-j,kk) -c transformations to the left hand side with respect to a1. - do 230 i=1,i2 - i1 = i+1 - call fprota(cos,sin,h1(i1),a1(j,i1)) - h1(i) = h1(i1) - 230 continue - h1(i1) = 0. - 240 continue -c rotation with the rows n10+1,...n7 of matrix a. - 250 do 270 j=1,kk - ij = n10+j - if(ij.le.0) go to 270 - piv = h2(j) - if(piv.eq.0.) go to 270 -c calculate the parameters of the givens transformation. - call fpgivs(piv,a2(ij,j),cos,sin) -c transformations to right hand side. - call fprota(cos,sin,yi,z(ij)) - if(j.eq.kk) go to 280 - j1 = j+1 -c transformations to left hand side. - do 260 i=j1,kk - call fprota(cos,sin,h2(i),a2(ij,i)) - 260 continue - 270 continue -c add contribution of this row to the sum of squares of residual -c right hand sides. - 280 fp = fp+yi**2 - go to 290 -c rotation of the new row of the observation matrix into -c triangle in case the b-splines nj,k+1(x),j=n7+1,...n-k-1 are all zero -c at xi. - 285 j = l5 - do 140 i=1,kk1 - j = j+1 - piv = h(i) - if(piv.eq.0.) go to 140 -c calculate the parameters of the givens transformation. - call fpgivs(piv,a1(j,1),cos,sin) -c transformations to right hand side. - call fprota(cos,sin,yi,z(j)) - if(i.eq.kk1) go to 150 - i2 = 1 - i3 = i+1 -c transformations to left hand side. - do 130 i1=i3,kk1 - i2 = i2+1 - call fprota(cos,sin,h(i1),a1(j,i2)) - 130 continue - 140 continue -c add contribution of this row to the sum of squares of residual -c right hand sides. - 150 fp = fp+yi**2 - 290 continue - fpint(n) = fp0 - fpint(n-1) = fpold - nrdata(n) = nplus -c backward substitution to obtain the b-spline coefficients c(j),j=1,.n - call fpbacp(a1,a2,z,n7,kk,c,kk1,nest) -c calculate from condition (**) the coefficients c(j+n7),j=1,2,...k. - do 295 i=1,k - j = i+n7 - c(j) = c(i) - 295 continue - if(iopt.lt.0) go to 660 -c test whether the approximation sinf(x) is an acceptable solution. - fpms = fp-s - if(abs(fpms).lt.acc) go to 660 -c if f(p=inf) < s accept the choice of knots. - if(fpms.lt.0.) go to 350 -c if n=nmax, sinf(x) is an interpolating spline. - if(n.eq.nmax) go to 630 -c increase the number of knots. -c if n=nest we cannot increase the number of knots because of the -c storage capacity limitation. - if(n.eq.nest) go to 620 -c determine the number of knots nplus we are going to add. - npl1 = nplus*2 - rn = nplus - if(fpold-fp.gt.acc) npl1 = rn*fpms/(fpold-fp) - nplus = min0(nplus*2,max0(npl1,nplus/2,1)) - fpold = fp -c compute the sum(wi*(yi-s(xi))**2) for each knot interval -c t(j+k) <= xi <= t(j+k+1) and store it in fpint(j),j=1,2,...nrint. - fpart = 0. - i = 1 - l = k1 - do 320 it=1,m1 - if(x(it).lt.t(l)) go to 300 - new = 1 - l = l+1 - 300 term = 0. - l0 = l-k2 - do 310 j=1,k1 - l0 = l0+1 - term = term+c(l0)*q(it,j) - 310 continue - term = (w(it)*(term-y(it)))**2 - fpart = fpart+term - if(new.eq.0) go to 320 - if(l.gt.k2) go to 315 - fpint(nrint) = term - new = 0 - go to 320 - 315 store = term*half - fpint(i) = fpart-store - i = i+1 - fpart = store - new = 0 - 320 continue - fpint(nrint) = fpint(nrint)+fpart - do 330 l=1,nplus -c add a new knot - call fpknot(x,m,t,n,fpint,nrdata,nrint,nest,1) -c if n=nmax we locate the knots as for interpolation. - if(n.eq.nmax) go to 5 -c test whether we cannot further increase the number of knots. - if(n.eq.nest) go to 340 - 330 continue -c restart the computations with the new set of knots. - 340 continue -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 2: determination of the smoothing periodic spline sp(x). c -c ************************************************************* c -c we have determined the number of knots and their position. c -c we now compute the b-spline coefficients of the smoothing spline c -c sp(x). the observation matrix a is extended by the rows of matrix c -c b expressing that the kth derivative discontinuities of sp(x) at c -c the interior knots t(k+2),...t(n-k-1) must be zero. the corres- c -c ponding weights of these additional rows are set to 1/sqrt(p). c -c iteratively we then have to determine the value of p such that c -c f(p)=sum(w(i)*(y(i)-sp(x(i)))**2) be = s. we already know that c -c the least-squares constant function corresponds to p=0, and that c -c the least-squares periodic spline corresponds to p=infinity. the c -c iteration process which is proposed here, makes use of rational c -c interpolation. since f(p) is a convex and strictly decreasing c -c function of p, it can be approximated by a rational function c -c r(p) = (u*p+v)/(p+w). three values of p(p1,p2,p3) with correspond- c -c ing values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used c -c to calculate the new value of p such that r(p)=s. convergence is c -c guaranteed by taking f1>0 and f3<0. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c evaluate the discontinuity jump of the kth derivative of the -c b-splines at the knots t(l),l=k+2,...n-k-1 and store in b. - 350 call fpdisc(t,n,k2,b,nest) -c initial value for p. - p1 = 0. - f1 = fp0-s - p3 = -one - f3 = fpms - n11 = n10-1 - n8 = n7-1 - p = 0. - l = n7 - do 352 i=1,k - j = k+1-i - p = p+a2(l,j) - l = l-1 - if(l.eq.0) go to 356 - 352 continue - do 354 i=1,n10 - p = p+a1(i,1) - 354 continue - 356 rn = n7 - p = rn/p - ich1 = 0 - ich3 = 0 -c iteration process to find the root of f(p) = s. - do 595 iter=1,maxit -c form the matrix g as the matrix a extended by the rows of matrix b. -c the rows of matrix b with weight 1/p are rotated into -c the triangularised observation matrix a. -c after triangularisation our n7 x n7 matrix g takes the form -c ! g1 ' ! -c g = ! ' g2 ! -c ! 0 ' ! -c with g2 a n7 x (k+1) matrix and g1 a n11 x n11 upper triangular -c matrix of bandwidth k+2. ( n11 = n7-k-1) - pinv = one/p -c store matrix a into g - do 360 i=1,n7 - c(i) = z(i) - g1(i,k1) = a1(i,k1) - g1(i,k2) = 0. - g2(i,1) = 0. - do 360 j=1,k - g1(i,j) = a1(i,j) - g2(i,j+1) = a2(i,j) - 360 continue - l = n10 - do 370 j=1,k1 - if(l.le.0) go to 375 - g2(l,1) = a1(l,j) - l = l-1 - 370 continue - 375 do 540 it=1,n8 -c fetch a new row of matrix b and store it in the arrays h1 (the part -c with respect to g1) and h2 (the part with respect to g2). - yi = 0. - do 380 i=1,k1 - h1(i) = 0. - h2(i) = 0. - 380 continue - h1(k2) = 0. - if(it.gt.n11) go to 420 - l = it - l0 = it - do 390 j=1,k2 - if(l0.eq.n10) go to 400 - h1(j) = b(it,j)*pinv - l0 = l0+1 - 390 continue - go to 470 - 400 l0 = 1 - do 410 l1=j,k2 - h2(l0) = b(it,l1)*pinv - l0 = l0+1 - 410 continue - go to 470 - 420 l = 1 - i = it-n10 - do 460 j=1,k2 - i = i+1 - l0 = i - 430 l1 = l0-k1 - if(l1.le.0) go to 450 - if(l1.le.n11) go to 440 - l0 = l1-n11 - go to 430 - 440 h1(l1) = b(it,j)*pinv - go to 460 - 450 h2(l0) = h2(l0)+b(it,j)*pinv - 460 continue - if(n11.le.0) go to 510 -c rotate this row into triangle by givens transformations without -c square roots. -c rotation with the rows l,l+1,...n11. - 470 do 500 j=l,n11 - piv = h1(1) -c calculate the parameters of the givens transformation. - call fpgivs(piv,g1(j,1),cos,sin) -c transformation to right hand side. - call fprota(cos,sin,yi,c(j)) -c transformation to the left hand side with respect to g2. - do 480 i=1,k1 - call fprota(cos,sin,h2(i),g2(j,i)) - 480 continue - if(j.eq.n11) go to 510 - i2 = min0(n11-j,k1) -c transformation to the left hand side with respect to g1. - do 490 i=1,i2 - i1 = i+1 - call fprota(cos,sin,h1(i1),g1(j,i1)) - h1(i) = h1(i1) - 490 continue - h1(i1) = 0. - 500 continue -c rotation with the rows n11+1,...n7 - 510 do 530 j=1,k1 - ij = n11+j - if(ij.le.0) go to 530 - piv = h2(j) -c calculate the parameters of the givens transformation - call fpgivs(piv,g2(ij,j),cos,sin) -c transformation to the right hand side. - call fprota(cos,sin,yi,c(ij)) - if(j.eq.k1) go to 540 - j1 = j+1 -c transformation to the left hand side. - do 520 i=j1,k1 - call fprota(cos,sin,h2(i),g2(ij,i)) - 520 continue - 530 continue - 540 continue -c backward substitution to obtain the b-spline coefficients -c c(j),j=1,2,...n7 of sp(x). - call fpbacp(g1,g2,c,n7,k1,c,k2,nest) -c calculate from condition (**) the b-spline coefficients c(n7+j),j=1,. - do 545 i=1,k - j = i+n7 - c(j) = c(i) - 545 continue -c computation of f(p). - fp = 0. - l = k1 - do 570 it=1,m1 - if(x(it).lt.t(l)) go to 550 - l = l+1 - 550 l0 = l-k2 - term = 0. - do 560 j=1,k1 - l0 = l0+1 - term = term+c(l0)*q(it,j) - 560 continue - fp = fp+(w(it)*(term-y(it)))**2 - 570 continue -c test whether the approximation sp(x) is an acceptable solution. - fpms = fp-s - if(abs(fpms).lt.acc) go to 660 -c test whether the maximal number of iterations is reached. - if(iter.eq.maxit) go to 600 -c carry out one more step of the iteration process. - p2 = p - f2 = fpms - if(ich3.ne.0) go to 580 - if((f2-f3) .gt. acc) go to 575 -c our initial choice of p is too large. - p3 = p2 - f3 = f2 - p = p*con4 - if(p.le.p1) p = p1*con9 +p2*con1 - go to 595 - 575 if(f2.lt.0.) ich3 = 1 - 580 if(ich1.ne.0) go to 590 - if((f1-f2) .gt. acc) go to 585 -c our initial choice of p is too small - p1 = p2 - f1 = f2 - p = p/con4 - if(p3.lt.0.) go to 595 - if(p.ge.p3) p = p2*con1 +p3*con9 - go to 595 - 585 if(f2.gt.0.) ich1 = 1 -c test whether the iteration process proceeds as theoretically -c expected. - 590 if(f2.ge.f1 .or. f2.le.f3) go to 610 -c find the new value for p. - p = fprati(p1,f1,p2,f2,p3,f3) - 595 continue -c error codes and messages. - 600 ier = 3 - go to 660 - 610 ier = 2 - go to 660 - 620 ier = 1 - go to 660 - 630 ier = -1 - go to 660 - 640 ier = -2 -c the least-squares constant function c1 is a solution of our problem. -c a constant function is a spline of degree k with all b-spline -c coefficients equal to that constant c1. - do 650 i=1,k1 - rn = k1-i - t(i) = x(1)-rn*per - c(i) = c1 - j = i+k1 - rn = i-1 - t(j) = x(m)+rn*per - 650 continue - n = nmin - fp = fp0 - fpint(n) = fp0 - fpint(n-1) = 0. - nrdata(n) = 0 - 660 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fppocu.f =================================================================== --- branches/Interpolate1D/fitpack/fppocu.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fppocu.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,72 +0,0 @@ - subroutine fppocu(idim,k,a,b,ib,db,nb,ie,de,ne,cp,np) -c subroutine fppocu finds a idim-dimensional polynomial curve p(u) = -c (p1(u),p2(u),...,pidim(u)) of degree k, satisfying certain derivative -c constraints at the end points a and b, i.e. -c (l) -c if ib > 0 : pj (a) = db(idim*l+j), l=0,1,...,ib-1 -c (l) -c if ie > 0 : pj (b) = de(idim*l+j), l=0,1,...,ie-1 -c -c the polynomial curve is returned in its b-spline representation -c ( coefficients cp(j), j=1,2,...,np ) -c .. -c ..scalar arguments.. - integer idim,k,ib,nb,ie,ne,np - real*8 a,b -c ..array arguments.. - real*8 db(nb),de(ne),cp(np) -c ..local scalars.. - real*8 ab,aki - integer i,id,j,jj,l,ll,k1,k2 -c ..local array.. - real*8 work(6,6) -c .. - k1 = k+1 - k2 = 2*k1 - ab = b-a - do 110 id=1,idim - do 10 j=1,k1 - work(j,1) = 0. - 10 continue - if(ib.eq.0) go to 50 - l = id - do 20 i=1,ib - work(1,i) = db(l) - l = l+idim - 20 continue - if(ib.eq.1) go to 50 - ll = ib - do 40 j=2,ib - ll = ll-1 - do 30 i=1,ll - aki = k1-i - work(j,i) = ab*work(j-1,i+1)/aki + work(j-1,i) - 30 continue - 40 continue - 50 if(ie.eq.0) go to 90 - l = id - j = k1 - do 60 i=1,ie - work(j,i) = de(l) - l = l+idim - j = j-1 - 60 continue - if(ie.eq.1) go to 90 - ll = ie - do 80 jj=2,ie - ll = ll-1 - j = k1+1-jj - do 70 i=1,ll - aki = k1-i - work(j,i) = work(j+1,i) - ab*work(j,i+1)/aki - j = j-1 - 70 continue - 80 continue - 90 l = (id-1)*k2 - do 100 j=1,k1 - l = l+1 - cp(l) = work(j,1) - 100 continue - 110 continue - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fppogr.f =================================================================== --- branches/Interpolate1D/fitpack/fppogr.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fppogr.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,410 +0,0 @@ - subroutine fppogr(iopt,ider,u,mu,v,mv,z,mz,z0,r,s,nuest,nvest, - * tol,maxit,nc,nu,tu,nv,tv,c,fp,fp0,fpold,reducu,reducv,fpintu, - * fpintv,dz,step,lastdi,nplusu,nplusv,lasttu,nru,nrv,nrdatu, - * nrdatv,wrk,lwrk,ier) -c .. -c ..scalar arguments.. - integer mu,mv,mz,nuest,nvest,maxit,nc,nu,nv,lastdi,nplusu,nplusv, - * lasttu,lwrk,ier - real*8 z0,r,s,tol,fp,fp0,fpold,reducu,reducv,step -c ..array arguments.. - integer iopt(3),ider(2),nrdatu(nuest),nrdatv(nvest),nru(mu), - * nrv(mv) - real*8 u(mu),v(mv),z(mz),tu(nuest),tv(nvest),c(nc),fpintu(nuest), - * fpintv(nvest),dz(3),wrk(lwrk) -c ..local scalars.. - real*8 acc,fpms,f1,f2,f3,p,per,pi,p1,p2,p3,vb,ve,zmax,zmin,rn,one, - * - * con1,con4,con9 - integer i,ich1,ich3,ifbu,ifbv,ifsu,ifsv,istart,iter,i1,i2,j,ju, - * ktu,l,l1,l2,l3,l4,mpm,mumin,mu0,mu1,nn,nplu,nplv,npl1,nrintu, - * nrintv,nue,numax,nve,nvmax -c ..local arrays.. - integer idd(2) - real*8 dzz(3) -c ..function references.. - real*8 abs,datan2,fprati - integer max0,min0 -c ..subroutine references.. -c fpknot,fpopdi -c .. -c set constants - one = 1d0 - con1 = 0.1e0 - con9 = 0.9e0 - con4 = 0.4e-01 -c initialization - ifsu = 0 - ifsv = 0 - ifbu = 0 - ifbv = 0 - p = -one - mumin = 4-iopt(3) - if(ider(1).ge.0) mumin = mumin-1 - if(iopt(2).eq.1 .and. ider(2).eq.1) mumin = mumin-1 - pi = datan2(0d0,-one) - per = pi+pi - vb = v(1) - ve = vb+per -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 1: determination of the number of knots and their position. c -c **************************************************************** c -c given a set of knots we compute the least-squares spline sinf(u,v) c -c and the corresponding sum of squared residuals fp = f(p=inf). c -c if iopt(1)=-1 sinf(u,v) is the requested approximation. c -c if iopt(1)>=0 we check whether we can accept the knots: c -c if fp <= s we will continue with the current set of knots. c -c if fp > s we will increase the number of knots and compute the c -c corresponding least-squares spline until finally fp <= s. c -c the initial choice of knots depends on the value of s and iopt. c -c if s=0 we have spline interpolation; in that case the number of c -c knots in the u-direction equals nu=numax=mu+5+iopt(2)+iopt(3) c -c and in the v-direction nv=nvmax=mv+7. c -c if s>0 and c -c iopt(1)=0 we first compute the least-squares polynomial,i.e. a c -c spline without interior knots : nu=8 ; nv=8. c -c iopt(1)=1 we start with the set of knots found at the last call c -c of the routine, except for the case that s > fp0; then we c -c compute the least-squares polynomial directly. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - if(iopt(1).lt.0) go to 120 -c acc denotes the absolute tolerance for the root of f(p)=s. - acc = tol*s -c numax and nvmax denote the number of knots needed for interpolation. - numax = mu+5+iopt(2)+iopt(3) - nvmax = mv+7 - nue = min0(numax,nuest) - nve = min0(nvmax,nvest) - if(s.gt.0.) go to 100 -c if s = 0, s(u,v) is an interpolating spline. - nu = numax - nv = nvmax -c test whether the required storage space exceeds the available one. - if(nu.gt.nuest .or. nv.gt.nvest) go to 420 -c find the position of the knots in the v-direction. - do 10 l=1,mv - tv(l+3) = v(l) - 10 continue - tv(mv+4) = ve - l1 = mv-2 - l2 = mv+5 - do 20 i=1,3 - tv(i) = v(l1)-per - tv(l2) = v(i+1)+per - l1 = l1+1 - l2 = l2+1 - 20 continue -c if not all the derivative values g(i,j) are given, we will first -c estimate these values by computing a least-squares spline - idd(1) = ider(1) - if(idd(1).eq.0) idd(1) = 1 - if(idd(1).gt.0) dz(1) = z0 - idd(2) = ider(2) - if(ider(1).lt.0) go to 30 - if(iopt(2).eq.0 .or. ider(2).ne.0) go to 70 -c we set up the knots in the u-direction for computing the least-squares -c spline. - 30 i1 = 3 - i2 = mu-2 - nu = 4 - do 40 i=1,mu - if(i1.gt.i2) go to 50 - nu = nu+1 - tu(nu) = u(i1) - i1 = i1+2 - 40 continue - 50 do 60 i=1,4 - tu(i) = 0. - nu = nu+1 - tu(nu) = r - 60 continue -c we compute the least-squares spline for estimating the derivatives. - call fpopdi(ifsu,ifsv,ifbu,ifbv,u,mu,v,mv,z,mz,z0,dz,iopt,idd, - * tu,nu,tv,nv,nuest,nvest,p,step,c,nc,fp,fpintu,fpintv,nru,nrv, - * wrk,lwrk) - ifsu = 0 -c if all the derivatives at the origin are known, we compute the -c interpolating spline. -c we set up the knots in the u-direction, needed for interpolation. - 70 nn = numax-8 - if(nn.eq.0) go to 95 - ju = 2-iopt(2) - do 80 l=1,nn - tu(l+4) = u(ju) - ju = ju+1 - 80 continue - nu = numax - l = nu - do 90 i=1,4 - tu(i) = 0. - tu(l) = r - l = l-1 - 90 continue -c we compute the interpolating spline. - 95 call fpopdi(ifsu,ifsv,ifbu,ifbv,u,mu,v,mv,z,mz,z0,dz,iopt,idd, - * tu,nu,tv,nv,nuest,nvest,p,step,c,nc,fp,fpintu,fpintv,nru,nrv, - * wrk,lwrk) - go to 430 -c if s>0 our initial choice of knots depends on the value of iopt(1). - 100 ier = 0 - if(iopt(1).eq.0) go to 115 - step = -step - if(fp0.le.s) go to 115 -c if iopt(1)=1 and fp0 > s we start computing the least-squares spline -c according to the set of knots found at the last call of the routine. -c we determine the number of grid coordinates u(i) inside each knot -c interval (tu(l),tu(l+1)). - l = 5 - j = 1 - nrdatu(1) = 0 - mu0 = 2-iopt(2) - mu1 = mu-2+iopt(3) - do 105 i=mu0,mu1 - nrdatu(j) = nrdatu(j)+1 - if(u(i).lt.tu(l)) go to 105 - nrdatu(j) = nrdatu(j)-1 - l = l+1 - j = j+1 - nrdatu(j) = 0 - 105 continue -c we determine the number of grid coordinates v(i) inside each knot -c interval (tv(l),tv(l+1)). - l = 5 - j = 1 - nrdatv(1) = 0 - do 110 i=2,mv - nrdatv(j) = nrdatv(j)+1 - if(v(i).lt.tv(l)) go to 110 - nrdatv(j) = nrdatv(j)-1 - l = l+1 - j = j+1 - nrdatv(j) = 0 - 110 continue - idd(1) = ider(1) - idd(2) = ider(2) - go to 120 -c if iopt(1)=0 or iopt(1)=1 and s >= fp0,we start computing the least- -c squares polynomial (which is a spline without interior knots). - 115 ier = -2 - idd(1) = ider(1) - idd(2) = 1 - nu = 8 - nv = 8 - nrdatu(1) = mu-3+iopt(2)+iopt(3) - nrdatv(1) = mv-1 - lastdi = 0 - nplusu = 0 - nplusv = 0 - fp0 = 0. - fpold = 0. - reducu = 0. - reducv = 0. -c main loop for the different sets of knots.mpm=mu+mv is a save upper -c bound for the number of trials. - 120 mpm = mu+mv - do 270 iter=1,mpm -c find nrintu (nrintv) which is the number of knot intervals in the -c u-direction (v-direction). - nrintu = nu-7 - nrintv = nv-7 -c find the position of the additional knots which are needed for the -c b-spline representation of s(u,v). - i = nu - do 130 j=1,4 - tu(j) = 0. - tu(i) = r - i = i-1 - 130 continue - l1 = 4 - l2 = l1 - l3 = nv-3 - l4 = l3 - tv(l2) = vb - tv(l3) = ve - do 140 j=1,3 - l1 = l1+1 - l2 = l2-1 - l3 = l3+1 - l4 = l4-1 - tv(l2) = tv(l4)-per - tv(l3) = tv(l1)+per - 140 continue -c find an estimate of the range of possible values for the optimal -c derivatives at the origin. - ktu = nrdatu(1)+2-iopt(2) - if(nrintu.eq.1) ktu = mu - if(ktu.lt.mumin) ktu = mumin - if(ktu.eq.lasttu) go to 150 - zmin = z0 - zmax = z0 - l = mv*ktu - do 145 i=1,l - if(z(i).lt.zmin) zmin = z(i) - if(z(i).gt.zmax) zmax = z(i) - 145 continue - step = zmax-zmin - lasttu = ktu -c find the least-squares spline sinf(u,v). - 150 call fpopdi(ifsu,ifsv,ifbu,ifbv,u,mu,v,mv,z,mz,z0,dz,iopt,idd, - * tu,nu,tv,nv,nuest,nvest,p,step,c,nc,fp,fpintu,fpintv,nru,nrv, - * wrk,lwrk) - if(step.lt.0.) step = -step - if(ier.eq.(-2)) fp0 = fp -c test whether the least-squares spline is an acceptable solution. - if(iopt(1).lt.0) go to 440 - fpms = fp-s - if(abs(fpms) .lt. acc) go to 440 -c if f(p=inf) < s, we accept the choice of knots. - if(fpms.lt.0.) go to 300 -c if nu=numax and nv=nvmax, sinf(u,v) is an interpolating spline - if(nu.eq.numax .and. nv.eq.nvmax) go to 430 -c increase the number of knots. -c if nu=nue and nv=nve we cannot further increase the number of knots -c because of the storage capacity limitation. - if(nu.eq.nue .and. nv.eq.nve) go to 420 - if(ider(1).eq.0) fpintu(1) = fpintu(1)+(z0-c(1))**2 - ier = 0 -c adjust the parameter reducu or reducv according to the direction -c in which the last added knots were located. - if (lastdi.lt.0) go to 160 - if (lastdi.eq.0) go to 155 - go to 170 - 155 nplv = 3 - idd(2) = ider(2) - fpold = fp - go to 230 - 160 reducu = fpold-fp - go to 175 - 170 reducv = fpold-fp -c store the sum of squared residuals for the current set of knots. - 175 fpold = fp -c find nplu, the number of knots we should add in the u-direction. - nplu = 1 - if(nu.eq.8) go to 180 - npl1 = nplusu*2 - rn = nplusu - if(reducu.gt.acc) npl1 = rn*fpms/reducu - nplu = min0(nplusu*2,max0(npl1,nplusu/2,1)) -c find nplv, the number of knots we should add in the v-direction. - 180 nplv = 3 - if(nv.eq.8) go to 190 - npl1 = nplusv*2 - rn = nplusv - if(reducv.gt.acc) npl1 = rn*fpms/reducv - nplv = min0(nplusv*2,max0(npl1,nplusv/2,1)) -c test whether we are going to add knots in the u- or v-direction. - 190 if (nplu.lt.nplv) go to 210 - if (nplu.eq.nplv) go to 200 - go to 230 - 200 if(lastdi.lt.0) go to 230 - 210 if(nu.eq.nue) go to 230 -c addition in the u-direction. - lastdi = -1 - nplusu = nplu - ifsu = 0 - istart = 0 - if(iopt(2).eq.0) istart = 1 - do 220 l=1,nplusu -c add a new knot in the u-direction - call fpknot(u,mu,tu,nu,fpintu,nrdatu,nrintu,nuest,istart) -c test whether we cannot further increase the number of knots in the -c u-direction. - if(nu.eq.nue) go to 270 - 220 continue - go to 270 - 230 if(nv.eq.nve) go to 210 -c addition in the v-direction. - lastdi = 1 - nplusv = nplv - ifsv = 0 - do 240 l=1,nplusv -c add a new knot in the v-direction. - call fpknot(v,mv,tv,nv,fpintv,nrdatv,nrintv,nvest,1) -c test whether we cannot further increase the number of knots in the -c v-direction. - if(nv.eq.nve) go to 270 - 240 continue -c restart the computations with the new set of knots. - 270 continue -c test whether the least-squares polynomial is a solution of our -c approximation problem. - 300 if(ier.eq.(-2)) go to 440 -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 2: determination of the smoothing spline sp(u,v) c -c ***************************************************** c -c we have determined the number of knots and their position. we now c -c compute the b-spline coefficients of the smoothing spline sp(u,v). c -c this smoothing spline depends on the parameter p in such a way that c -c f(p) = sumi=1,mu(sumj=1,mv((z(i,j)-sp(u(i),v(j)))**2) c -c is a continuous, strictly decreasing function of p. moreover the c -c least-squares polynomial corresponds to p=0 and the least-squares c -c spline to p=infinity. then iteratively we have to determine the c -c positive value of p such that f(p)=s. the process which is proposed c -c here makes use of rational interpolation. f(p) is approximated by a c -c rational function r(p)=(u*p+v)/(p+w); three values of p (p1,p2,p3) c -c with corresponding values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s)c -c are used to calculate the new value of p such that r(p)=s. c -c convergence is guaranteed by taking f1 > 0 and f3 < 0. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c initial value for p. - p1 = 0. - f1 = fp0-s - p3 = -one - f3 = fpms - p = one - dzz(1) = dz(1) - dzz(2) = dz(2) - dzz(3) = dz(3) - ich1 = 0 - ich3 = 0 -c iteration process to find the root of f(p)=s. - do 350 iter = 1,maxit -c find the smoothing spline sp(u,v) and the corresponding sum f(p). - call fpopdi(ifsu,ifsv,ifbu,ifbv,u,mu,v,mv,z,mz,z0,dzz,iopt,idd, - * tu,nu,tv,nv,nuest,nvest,p,step,c,nc,fp,fpintu,fpintv,nru,nrv, - * wrk,lwrk) -c test whether the approximation sp(u,v) is an acceptable solution. - fpms = fp-s - if(abs(fpms).lt.acc) go to 440 -c test whether the maximum allowable number of iterations has been -c reached. - if(iter.eq.maxit) go to 400 -c carry out one more step of the iteration process. - p2 = p - f2 = fpms - if(ich3.ne.0) go to 320 - if((f2-f3).gt.acc) go to 310 -c our initial choice of p is too large. - p3 = p2 - f3 = f2 - p = p*con4 - if(p.le.p1) p = p1*con9 + p2*con1 - go to 350 - 310 if(f2.lt.0.) ich3 = 1 - 320 if(ich1.ne.0) go to 340 - if((f1-f2).gt.acc) go to 330 -c our initial choice of p is too small - p1 = p2 - f1 = f2 - p = p/con4 - if(p3.lt.0.) go to 350 - if(p.ge.p3) p = p2*con1 + p3*con9 - go to 350 -c test whether the iteration process proceeds as theoretically -c expected. - 330 if(f2.gt.0.) ich1 = 1 - 340 if(f2.ge.f1 .or. f2.le.f3) go to 410 -c find the new value of p. - p = fprati(p1,f1,p2,f2,p3,f3) - 350 continue -c error codes and messages. - 400 ier = 3 - go to 440 - 410 ier = 2 - go to 440 - 420 ier = 1 - go to 440 - 430 ier = -1 - fp = 0. - 440 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fppola.f =================================================================== --- branches/Interpolate1D/fitpack/fppola.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fppola.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,840 +0,0 @@ - subroutine fppola(iopt1,iopt2,iopt3,m,u,v,z,w,rad,s,nuest,nvest, - * eta,tol,maxit,ib1,ib3,nc,ncc,intest,nrest,nu,tu,nv,tv,c,fp,sup, - * fpint,coord,f,ff,row,cs,cosi,a,q,bu,bv,spu,spv,h,index,nummer, - * wrk,lwrk,ier) -c ..scalar arguments.. - integer iopt1,iopt2,iopt3,m,nuest,nvest,maxit,ib1,ib3,nc,ncc, - * intest,nrest,nu,nv,lwrk,ier - real*8 s,eta,tol,fp,sup -c ..array arguments.. - integer index(nrest),nummer(m) - real*8 u(m),v(m),z(m),w(m),tu(nuest),tv(nvest),c(nc),fpint(intest) - *, - * coord(intest),f(ncc),ff(nc),row(nvest),cs(nvest),cosi(5,nvest), - * a(ncc,ib1),q(ncc,ib3),bu(nuest,5),bv(nvest,5),spu(m,4),spv(m,4), - * h(ib3),wrk(lwrk) -c ..user supplied function.. - real*8 rad -c ..local scalars.. - real*8 acc,arg,co,c1,c2,c3,c4,dmax,eps,fac,fac1,fac2,fpmax,fpms, - * f1,f2,f3,hui,huj,p,pi,pinv,piv,pi2,p1,p2,p3,r,ratio,si,sigma, - * sq,store,uu,u2,u3,wi,zi,rn,one,two,three,con1,con4,con9,half,ten - integer i,iband,iband3,iband4,ich1,ich3,ii,il,in,ipar,ipar1,irot, - * iter,i1,i2,i3,j,jl,jrot,j1,j2,k,l,la,lf,lh,ll,lu,lv,lwest,l1,l2, - * l3,l4,ncof,ncoff,nvv,nv4,nreg,nrint,nrr,nr1,nuu,nu4,num,num1, - * numin,nvmin,rank,iband1 -c ..local arrays.. - real*8 hu(4),hv(4) -c ..function references.. - real*8 abs,atan,cos,fprati,sin,sqrt - integer min0 -c ..subroutine references.. -c fporde,fpbspl,fpback,fpgivs,fprota,fprank,fpdisc,fprppo -c .. -c set constants - one = 1 - two = 2 - three = 3 - ten = 10 - half = 0.5e0 - con1 = 0.1e0 - con9 = 0.9e0 - con4 = 0.4e-01 - pi = atan(one)*4 - pi2 = pi+pi - ipar = iopt2*(iopt2+3)/2 - ipar1 = ipar+1 - eps = sqrt(eta) - if(iopt1.lt.0) go to 90 - numin = 9 - nvmin = 9+iopt2*(iopt2+1) -c calculation of acc, the absolute tolerance for the root of f(p)=s. - acc = tol*s - if(iopt1.eq.0) go to 10 - if(s.lt.sup) then - if (nv.lt.nvmin) go to 70 - go to 90 - endif -c if iopt1 = 0 we begin by computing the weighted least-squares -c polymomial of the form -c s(u,v) = f(1)*(1-u**3)+f(2)*u**3+f(3)*(u**2-u**3)+f(4)*(u-u**3) -c where f(4) = 0 if iopt2> 0 , f(3) = 0 if iopt2 > 1 and -c f(2) = 0 if iopt3> 0. -c the corresponding weighted sum of squared residuals gives the upper -c bound sup for the smoothing factor s. - 10 sup = 0. - do 20 i=1,4 - f(i) = 0. - do 20 j=1,4 - a(i,j) = 0. - 20 continue - do 50 i=1,m - wi = w(i) - zi = z(i)*wi - uu = u(i) - u2 = uu*uu - u3 = uu*u2 - h(1) = (one-u3)*wi - h(2) = u3*wi - h(3) = u2*(one-uu)*wi - h(4) = uu*(one-u2)*wi - if(iopt3.ne.0) h(2) = 0. - if(iopt2.gt.1) h(3) = 0. - if(iopt2.gt.0) h(4) = 0. - do 40 j=1,4 - piv = h(j) - if(piv.eq.0.) go to 40 - call fpgivs(piv,a(j,1),co,si) - call fprota(co,si,zi,f(j)) - if(j.eq.4) go to 40 - j1 = j+1 - j2 = 1 - do 30 l=j1,4 - j2 = j2+1 - call fprota(co,si,h(l),a(j,j2)) - 30 continue - 40 continue - sup = sup+zi*zi - 50 continue - if(a(4,1).ne.0.) f(4) = f(4)/a(4,1) - if(a(3,1).ne.0.) f(3) = (f(3)-a(3,2)*f(4))/a(3,1) - if(a(2,1).ne.0.) f(2) = (f(2)-a(2,2)*f(3)-a(2,3)*f(4))/a(2,1) - if(a(1,1).ne.0.) - * f(1) = (f(1)-a(1,2)*f(2)-a(1,3)*f(3)-a(1,4)*f(4))/a(1,1) -c find the b-spline representation of this least-squares polynomial - c1 = f(1) - c4 = f(2) - c2 = f(4)/three+c1 - c3 = (f(3)+two*f(4))/three+c1 - nu = 8 - nv = 8 - do 60 i=1,4 - c(i) = c1 - c(i+4) = c2 - c(i+8) = c3 - c(i+12) = c4 - tu(i) = 0. - tu(i+4) = one - rn = 2*i-9 - tv(i) = rn*pi - rn = 2*i-1 - tv(i+4) = rn*pi - 60 continue - fp = sup -c test whether the least-squares polynomial is an acceptable solution - fpms = sup-s - if(fpms.lt.acc) go to 960 -c test whether we cannot further increase the number of knots. - 70 if(nuest.lt.numin .or. nvest.lt.nvmin) go to 950 -c find the initial set of interior knots of the spline in case iopt1=0. - nu = numin - nv = nvmin - tu(5) = half - nvv = nv-8 - rn = nvv+1 - fac = pi2/rn - do 80 i=1,nvv - rn = i - tv(i+4) = rn*fac-pi - 80 continue -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 1 : computation of least-squares bicubic splines. c -c ****************************************************** c -c if iopt1<0 we compute the least-squares bicubic spline according c -c to the given set of knots. c -c if iopt1>=0 we compute least-squares bicubic splines with in- c -c creasing numbers of knots until the corresponding sum f(p=inf)<=s. c -c the initial set of knots then depends on the value of iopt1 c -c if iopt1=0 we start with one interior knot in the u-direction c -c (0.5) and 1+iopt2*(iopt2+1) in the v-direction. c -c if iopt1>0 we start with the set of knots found at the last c -c call of the routine. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c main loop for the different sets of knots. m is a save upper bound -c for the number of trials. - 90 do 570 iter=1,m -c find the position of the additional knots which are needed for the -c b-spline representation of s(u,v). - l1 = 4 - l2 = l1 - l3 = nv-3 - l4 = l3 - tv(l2) = -pi - tv(l3) = pi - do 120 i=1,3 - l1 = l1+1 - l2 = l2-1 - l3 = l3+1 - l4 = l4-1 - tv(l2) = tv(l4)-pi2 - tv(l3) = tv(l1)+pi2 - 120 continue - l = nu - do 130 i=1,4 - tu(i) = 0. - tu(l) = one - l = l-1 - 130 continue -c find nrint, the total number of knot intervals and nreg, the number -c of panels in which the approximation domain is subdivided by the -c intersection of knots. - nuu = nu-7 - nvv = nv-7 - nrr = nvv/2 - nr1 = nrr+1 - nrint = nuu+nvv - nreg = nuu*nvv -c arrange the data points according to the panel they belong to. - call fporde(u,v,m,3,3,tu,nu,tv,nv,nummer,index,nreg) - if(iopt2.eq.0) go to 195 -c find the b-spline coefficients cosi of the cubic spline -c approximations for cr(v)=rad(v)*cos(v) and sr(v) = rad(v)*sin(v) -c if iopt2=1, and additionally also for cr(v)**2,sr(v)**2 and -c 2*cr(v)*sr(v) if iopt2=2 - do 140 i=1,nvv - do 135 j=1,ipar - cosi(j,i) = 0. - 135 continue - do 140 j=1,nvv - a(i,j) = 0. - 140 continue -c the coefficients cosi are obtained from interpolation conditions -c at the knots tv(i),i=4,5,...nv-4. - do 175 i=1,nvv - l2 = i+3 - arg = tv(l2) - call fpbspl(tv,nv,3,arg,l2,hv) - do 145 j=1,nvv - row(j) = 0. - 145 continue - ll = i - do 150 j=1,3 - if(ll.gt.nvv) ll= 1 - row(ll) = row(ll)+hv(j) - ll = ll+1 - 150 continue - co = cos(arg) - si = sin(arg) - r = rad(arg) - cs(1) = co*r - cs(2) = si*r - if(iopt2.eq.1) go to 155 - cs(3) = cs(1)*cs(1) - cs(4) = cs(2)*cs(2) - cs(5) = cs(1)*cs(2) - 155 do 170 j=1,nvv - piv = row(j) - if(piv.eq.0.) go to 170 - call fpgivs(piv,a(j,1),co,si) - do 160 l=1,ipar - call fprota(co,si,cs(l),cosi(l,j)) - 160 continue - if(j.eq.nvv) go to 175 - j1 = j+1 - j2 = 1 - do 165 l=j1,nvv - j2 = j2+1 - call fprota(co,si,row(l),a(j,j2)) - 165 continue - 170 continue - 175 continue - do 190 l=1,ipar - do 180 j=1,nvv - cs(j) = cosi(l,j) - 180 continue - call fpback(a,cs,nvv,nvv,cs,ncc) - do 185 j=1,nvv - cosi(l,j) = cs(j) - 185 continue - 190 continue -c find ncof, the dimension of the spline and ncoff, the number -c of coefficients in the standard b-spline representation. - 195 nu4 = nu-4 - nv4 = nv-4 - ncoff = nu4*nv4 - ncof = ipar1+nvv*(nu4-1-iopt2-iopt3) -c find the bandwidth of the observation matrix a. - iband = 4*nvv - if(nuu-iopt2-iopt3.le.1) iband = ncof - iband1 = iband-1 -c initialize the observation matrix a. - do 200 i=1,ncof - f(i) = 0. - do 200 j=1,iband - a(i,j) = 0. - 200 continue -c initialize the sum of squared residuals. - fp = 0. - ratio = one+tu(6)/tu(5) -c fetch the data points in the new order. main loop for the -c different panels. - do 380 num=1,nreg -c fix certain constants for the current panel; jrot records the column -c number of the first non-zero element in a row of the observation -c matrix according to a data point of the panel. - num1 = num-1 - lu = num1/nvv - l1 = lu+4 - lv = num1-lu*nvv+1 - l2 = lv+3 - jrot = 0 - if(lu.gt.iopt2) jrot = ipar1+(lu-iopt2-1)*nvv - lu = lu+1 -c test whether there are still data points in the current panel. - in = index(num) - 210 if(in.eq.0) go to 380 -c fetch a new data point. - wi = w(in) - zi = z(in)*wi -c evaluate for the u-direction, the 4 non-zero b-splines at u(in) - call fpbspl(tu,nu,3,u(in),l1,hu) -c evaluate for the v-direction, the 4 non-zero b-splines at v(in) - call fpbspl(tv,nv,3,v(in),l2,hv) -c store the value of these b-splines in spu and spv resp. - do 220 i=1,4 - spu(in,i) = hu(i) - spv(in,i) = hv(i) - 220 continue -c initialize the new row of observation matrix. - do 240 i=1,iband - h(i) = 0. - 240 continue -c calculate the non-zero elements of the new row by making the cross -c products of the non-zero b-splines in u- and v-direction and -c by taking into account the conditions of the splines. - do 250 i=1,nvv - row(i) = 0. - 250 continue -c take into account the periodicity condition of the bicubic splines. - ll = lv - do 260 i=1,4 - if(ll.gt.nvv) ll=1 - row(ll) = row(ll)+hv(i) - ll = ll+1 - 260 continue -c take into account the other conditions of the splines. - if(iopt2.eq.0 .or. lu.gt.iopt2+1) go to 280 - do 270 l=1,ipar - cs(l) = 0. - do 270 i=1,nvv - cs(l) = cs(l)+row(i)*cosi(l,i) - 270 continue -c fill in the non-zero elements of the new row. - 280 j1 = 0 - do 330 j =1,4 - jlu = j+lu - huj = hu(j) - if(jlu.gt.iopt2+2) go to 320 - go to (290,290,300,310),jlu - 290 h(1) = huj - j1 = 1 - go to 330 - 300 h(1) = h(1)+huj - h(2) = huj*cs(1) - h(3) = huj*cs(2) - j1 = 3 - go to 330 - 310 h(1) = h(1)+huj - h(2) = h(2)+huj*ratio*cs(1) - h(3) = h(3)+huj*ratio*cs(2) - h(4) = huj*cs(3) - h(5) = huj*cs(4) - h(6) = huj*cs(5) - j1 = 6 - go to 330 - 320 if(jlu.gt.nu4 .and. iopt3.ne.0) go to 330 - do 325 i=1,nvv - j1 = j1+1 - h(j1) = row(i)*huj - 325 continue - 330 continue - do 335 i=1,iband - h(i) = h(i)*wi - 335 continue -c rotate the row into triangle by givens transformations. - irot = jrot - do 350 i=1,iband - irot = irot+1 - piv = h(i) - if(piv.eq.0.) go to 350 -c calculate the parameters of the givens transformation. - call fpgivs(piv,a(irot,1),co,si) -c apply that transformation to the right hand side. - call fprota(co,si,zi,f(irot)) - if(i.eq.iband) go to 360 -c apply that transformation to the left hand side. - i2 = 1 - i3 = i+1 - do 340 j=i3,iband - i2 = i2+1 - call fprota(co,si,h(j),a(irot,i2)) - 340 continue - 350 continue -c add the contribution of the row to the sum of squares of residual -c right hand sides. - 360 fp = fp+zi**2 -c find the number of the next data point in the panel. - 370 in = nummer(in) - go to 210 - 380 continue -c find dmax, the maximum value for the diagonal elements in the reduced -c triangle. - dmax = 0. - do 390 i=1,ncof - if(a(i,1).le.dmax) go to 390 - dmax = a(i,1) - 390 continue -c check whether the observation matrix is rank deficient. - sigma = eps*dmax - do 400 i=1,ncof - if(a(i,1).le.sigma) go to 410 - 400 continue -c backward substitution in case of full rank. - call fpback(a,f,ncof,iband,c,ncc) - rank = ncof - do 405 i=1,ncof - q(i,1) = a(i,1)/dmax - 405 continue - go to 430 -c in case of rank deficiency, find the minimum norm solution. - 410 lwest = ncof*iband+ncof+iband - if(lwrk.lt.lwest) go to 925 - lf = 1 - lh = lf+ncof - la = lh+iband - do 420 i=1,ncof - ff(i) = f(i) - do 420 j=1,iband - q(i,j) = a(i,j) - 420 continue - call fprank(q,ff,ncof,iband,ncc,sigma,c,sq,rank,wrk(la), - * wrk(lf),wrk(lh)) - do 425 i=1,ncof - q(i,1) = q(i,1)/dmax - 425 continue -c add to the sum of squared residuals, the contribution of reducing -c the rank. - fp = fp+sq -c find the coefficients in the standard b-spline representation of -c the spline. - 430 call fprppo(nu,nv,iopt2,iopt3,cosi,ratio,c,ff,ncoff) -c test whether the least-squares spline is an acceptable solution. - if(iopt1.lt.0) then - if (fp.le.0) go to 970 - go to 980 - endif - fpms = fp-s - if(abs(fpms).le.acc) then - if (fp.le.0) go to 970 - go to 980 - endif -c if f(p=inf) < s, accept the choice of knots. - if(fpms.lt.0.) go to 580 -c test whether we cannot further increase the number of knots - if(m.lt.ncof) go to 935 -c search where to add a new knot. -c find for each interval the sum of squared residuals fpint for the -c data points having the coordinate belonging to that knot interval. -c calculate also coord which is the same sum, weighted by the position -c of the data points considered. - 440 do 450 i=1,nrint - fpint(i) = 0. - coord(i) = 0. - 450 continue - do 490 num=1,nreg - num1 = num-1 - lu = num1/nvv - l1 = lu+1 - lv = num1-lu*nvv - l2 = lv+1+nuu - jrot = lu*nv4+lv - in = index(num) - 460 if(in.eq.0) go to 490 - store = 0. - i1 = jrot - do 480 i=1,4 - hui = spu(in,i) - j1 = i1 - do 470 j=1,4 - j1 = j1+1 - store = store+hui*spv(in,j)*c(j1) - 470 continue - i1 = i1+nv4 - 480 continue - store = (w(in)*(z(in)-store))**2 - fpint(l1) = fpint(l1)+store - coord(l1) = coord(l1)+store*u(in) - fpint(l2) = fpint(l2)+store - coord(l2) = coord(l2)+store*v(in) - in = nummer(in) - go to 460 - 490 continue -c bring together the information concerning knot panels which are -c symmetric with respect to the origin. - do 495 i=1,nrr - l1 = nuu+i - l2 = l1+nrr - fpint(l1) = fpint(l1)+fpint(l2) - coord(l1) = coord(l1)+coord(l2)-pi*fpint(l2) - 495 continue -c find the interval for which fpint is maximal on the condition that -c there still can be added a knot. - l1 = 1 - l2 = nuu+nrr - if(nuest.lt.nu+1) l1=nuu+1 - if(nvest.lt.nv+2) l2=nuu -c test whether we cannot further increase the number of knots. - if(l1.gt.l2) go to 950 - 500 fpmax = 0. - l = 0 - do 510 i=l1,l2 - if(fpmax.ge.fpint(i)) go to 510 - l = i - fpmax = fpint(i) - 510 continue - if(l.eq.0) go to 930 -c calculate the position of the new knot. - arg = coord(l)/fpint(l) -c test in what direction the new knot is going to be added. - if(l.gt.nuu) go to 530 -c addition in the u-direction - l4 = l+4 - fpint(l) = 0. - fac1 = tu(l4)-arg - fac2 = arg-tu(l4-1) - if(fac1.gt.(ten*fac2) .or. fac2.gt.(ten*fac1)) go to 500 - j = nu - do 520 i=l4,nu - tu(j+1) = tu(j) - j = j-1 - 520 continue - tu(l4) = arg - nu = nu+1 - go to 570 -c addition in the v-direction - 530 l4 = l+4-nuu - fpint(l) = 0. - fac1 = tv(l4)-arg - fac2 = arg-tv(l4-1) - if(fac1.gt.(ten*fac2) .or. fac2.gt.(ten*fac1)) go to 500 - ll = nrr+4 - j = ll - do 550 i=l4,ll - tv(j+1) = tv(j) - j = j-1 - 550 continue - tv(l4) = arg - nv = nv+2 - nrr = nrr+1 - do 560 i=5,ll - j = i+nrr - tv(j) = tv(i)+pi - 560 continue -c restart the computations with the new set of knots. - 570 continue -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 2: determination of the smoothing bicubic spline. c -c ****************************************************** c -c we have determined the number of knots and their position. we now c -c compute the coefficients of the smoothing spline sp(u,v). c -c the observation matrix a is extended by the rows of a matrix, expres-c -c sing that sp(u,v) must be a constant function in the variable c -c v and a cubic polynomial in the variable u. the corresponding c -c weights of these additional rows are set to 1/(p). iteratively c -c we than have to determine the value of p such that f(p) = sum((w(i)* c -c (z(i)-sp(u(i),v(i))))**2) be = s. c -c we already know that the least-squares polynomial corresponds to p=0,c -c and that the least-squares bicubic spline corresponds to p=infin. c -c the iteration process makes use of rational interpolation. since f(p)c -c is a convex and strictly decreasing function of p, it can be approx- c -c imated by a rational function of the form r(p) = (u*p+v)/(p+w). c -c three values of p (p1,p2,p3) with corresponding values of f(p) (f1= c -c f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used to calculate the new value c -c of p such that r(p)=s. convergence is guaranteed by taking f1>0,f3<0.c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c evaluate the discontinuity jumps of the 3-th order derivative of -c the b-splines at the knots tu(l),l=5,...,nu-4. - 580 call fpdisc(tu,nu,5,bu,nuest) -c evaluate the discontinuity jumps of the 3-th order derivative of -c the b-splines at the knots tv(l),l=5,...,nv-4. - call fpdisc(tv,nv,5,bv,nvest) -c initial value for p. - p1 = 0. - f1 = sup-s - p3 = -one - f3 = fpms - p = 0. - do 590 i=1,ncof - p = p+a(i,1) - 590 continue - rn = ncof - p = rn/p -c find the bandwidth of the extended observation matrix. - iband4 = iband+ipar1 - if(iband4.gt.ncof) iband4 = ncof - iband3 = iband4 -1 - ich1 = 0 - ich3 = 0 - nuu = nu4-iopt3-1 -c iteration process to find the root of f(p)=s. - do 920 iter=1,maxit - pinv = one/p -c store the triangularized observation matrix into q. - do 630 i=1,ncof - ff(i) = f(i) - do 620 j=1,iband4 - q(i,j) = 0. - 620 continue - do 630 j=1,iband - q(i,j) = a(i,j) - 630 continue -c extend the observation matrix with the rows of a matrix, expressing -c that for u=constant sp(u,v) must be a constant function. - do 720 i=5,nv4 - ii = i-4 - do 635 l=1,nvv - row(l) = 0. - 635 continue - ll = ii - do 640 l=1,5 - if(ll.gt.nvv) ll=1 - row(ll) = row(ll)+bv(ii,l) - ll = ll+1 - 640 continue - do 720 j=1,nuu -c initialize the new row. - do 645 l=1,iband - h(l) = 0. - 645 continue -c fill in the non-zero elements of the row. jrot records the column -c number of the first non-zero element in the row. - if(j.gt.iopt2) go to 665 - if(j.eq.2) go to 655 - do 650 k=1,2 - cs(k) = 0. - do 650 l=1,nvv - cs(k) = cs(k)+cosi(k,l)*row(l) - 650 continue - h(1) = cs(1) - h(2) = cs(2) - jrot = 2 - go to 675 - 655 do 660 k=3,5 - cs(k) = 0. - do 660 l=1,nvv - cs(k) = cs(k)+cosi(k,l)*row(l) - 660 continue - h(1) = cs(1)*ratio - h(2) = cs(2)*ratio - h(3) = cs(3) - h(4) = cs(4) - h(5) = cs(5) - jrot = 2 - go to 675 - 665 do 670 l=1,nvv - h(l) = row(l) - 670 continue - jrot = ipar1+1+(j-iopt2-1)*nvv - 675 do 677 l=1,iband - h(l) = h(l)*pinv - 677 continue - zi = 0. -c rotate the new row into triangle by givens transformations. - do 710 irot=jrot,ncof - piv = h(1) - i2 = min0(iband1,ncof-irot) - if(piv.eq.0.) then - if (i2.le.0) go to 720 - go to 690 - endif -c calculate the parameters of the givens transformation. - call fpgivs(piv,q(irot,1),co,si) -c apply that givens transformation to the right hand side. - call fprota(co,si,zi,ff(irot)) - if(i2.eq.0) go to 720 -c apply that givens transformation to the left hand side. - do 680 l=1,i2 - l1 = l+1 - call fprota(co,si,h(l1),q(irot,l1)) - 680 continue - 690 do 700 l=1,i2 - h(l) = h(l+1) - 700 continue - h(i2+1) = 0. - 710 continue - 720 continue -c extend the observation matrix with the rows of a matrix expressing -c that for v=constant. sp(u,v) must be a cubic polynomial. - do 810 i=5,nu4 - ii = i-4 - do 810 j=1,nvv -c initialize the new row - do 730 l=1,iband4 - h(l) = 0. - 730 continue -c fill in the non-zero elements of the row. jrot records the column -c number of the first non-zero element in the row. - j1 = 1 - do 760 l=1,5 - il = ii+l-1 - if(il.eq.nu4 .and. iopt3.ne.0) go to 760 - if(il.gt.iopt2+1) go to 750 - go to (735,740,745),il - 735 h(1) = bu(ii,l) - j1 = j+1 - go to 760 - 740 h(1) = h(1)+bu(ii,l) - h(2) = bu(ii,l)*cosi(1,j) - h(3) = bu(ii,l)*cosi(2,j) - j1 = j+3 - go to 760 - 745 h(1) = h(1)+bu(ii,l) - h(2) = bu(ii,l)*cosi(1,j)*ratio - h(3) = bu(ii,l)*cosi(2,j)*ratio - h(4) = bu(ii,l)*cosi(3,j) - h(5) = bu(ii,l)*cosi(4,j) - h(6) = bu(ii,l)*cosi(5,j) - j1 = j+6 - go to 760 - 750 h(j1) = bu(ii,l) - j1 = j1+nvv - 760 continue - do 765 l=1,iband4 - h(l) = h(l)*pinv - 765 continue - zi = 0. - jrot = 1 - if(ii.gt.iopt2+1) jrot = ipar1+(ii-iopt2-2)*nvv+j -c rotate the new row into triangle by givens transformations. - do 800 irot=jrot,ncof - piv = h(1) - i2 = min0(iband3,ncof-irot) - if(piv.eq.0.) then - if (i2.le.0) go to 810 - go to 780 - endif -c calculate the parameters of the givens transformation. - call fpgivs(piv,q(irot,1),co,si) -c apply that givens transformation to the right hand side. - call fprota(co,si,zi,ff(irot)) - if(i2.eq.0) go to 810 -c apply that givens transformation to the left hand side. - do 770 l=1,i2 - l1 = l+1 - call fprota(co,si,h(l1),q(irot,l1)) - 770 continue - 780 do 790 l=1,i2 - h(l) = h(l+1) - 790 continue - h(i2+1) = 0. - 800 continue - 810 continue -c find dmax, the maximum value for the diagonal elements in the -c reduced triangle. - dmax = 0. - do 820 i=1,ncof - if(q(i,1).le.dmax) go to 820 - dmax = q(i,1) - 820 continue -c check whether the matrix is rank deficient. - sigma = eps*dmax - do 830 i=1,ncof - if(q(i,1).le.sigma) go to 840 - 830 continue -c backward substitution in case of full rank. - call fpback(q,ff,ncof,iband4,c,ncc) - rank = ncof - go to 845 -c in case of rank deficiency, find the minimum norm solution. - 840 lwest = ncof*iband4+ncof+iband4 - if(lwrk.lt.lwest) go to 925 - lf = 1 - lh = lf+ncof - la = lh+iband4 - call fprank(q,ff,ncof,iband4,ncc,sigma,c,sq,rank,wrk(la), - * wrk(lf),wrk(lh)) - 845 do 850 i=1,ncof - q(i,1) = q(i,1)/dmax - 850 continue -c find the coefficients in the standard b-spline representation of -c the polar spline. - call fprppo(nu,nv,iopt2,iopt3,cosi,ratio,c,ff,ncoff) -c compute f(p). - fp = 0. - do 890 num = 1,nreg - num1 = num-1 - lu = num1/nvv - lv = num1-lu*nvv - jrot = lu*nv4+lv - in = index(num) - 860 if(in.eq.0) go to 890 - store = 0. - i1 = jrot - do 880 i=1,4 - hui = spu(in,i) - j1 = i1 - do 870 j=1,4 - j1 = j1+1 - store = store+hui*spv(in,j)*c(j1) - 870 continue - i1 = i1+nv4 - 880 continue - fp = fp+(w(in)*(z(in)-store))**2 - in = nummer(in) - go to 860 - 890 continue -c test whether the approximation sp(u,v) is an acceptable solution - fpms = fp-s - if(abs(fpms).le.acc) go to 980 -c test whether the maximum allowable number of iterations has been -c reached. - if(iter.eq.maxit) go to 940 -c carry out one more step of the iteration process. - p2 = p - f2 = fpms - if(ich3.ne.0) go to 900 - if((f2-f3).gt.acc) go to 895 -c our initial choice of p is too large. - p3 = p2 - f3 = f2 - p = p*con4 - if(p.le.p1) p = p1*con9 + p2*con1 - go to 920 - 895 if(f2.lt.0.) ich3 = 1 - 900 if(ich1.ne.0) go to 910 - if((f1-f2).gt.acc) go to 905 -c our initial choice of p is too small - p1 = p2 - f1 = f2 - p = p/con4 - if(p3.lt.0.) go to 920 - if(p.ge.p3) p = p2*con1 +p3*con9 - go to 920 - 905 if(f2.gt.0.) ich1 = 1 -c test whether the iteration process proceeds as theoretically -c expected. - 910 if(f2.ge.f1 .or. f2.le.f3) go to 945 -c find the new value of p. - p = fprati(p1,f1,p2,f2,p3,f3) - 920 continue -c error codes and messages. - 925 ier = lwest - go to 990 - 930 ier = 5 - go to 990 - 935 ier = 4 - go to 990 - 940 ier = 3 - go to 990 - 945 ier = 2 - go to 990 - 950 ier = 1 - go to 990 - 960 ier = -2 - go to 990 - 970 ier = -1 - fp = 0. - 980 if(ncof.ne.rank) ier = -rank - 990 return - end - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fprank.f =================================================================== --- branches/Interpolate1D/fitpack/fprank.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fprank.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,236 +0,0 @@ - subroutine fprank(a,f,n,m,na,tol,c,sq,rank,aa,ff,h) -c subroutine fprank finds the minimum norm solution of a least- -c squares problem in case of rank deficiency. -c -c input parameters: -c a : array, which contains the non-zero elements of the observation -c matrix after triangularization by givens transformations. -c f : array, which contains the transformed right hand side. -c n : integer,wich contains the dimension of a. -c m : integer, which denotes the bandwidth of a. -c tol : real value, giving a threshold to determine the rank of a. -c -c output parameters: -c c : array, which contains the minimum norm solution. -c sq : real value, giving the contribution of reducing the rank -c to the sum of squared residuals. -c rank : integer, which contains the rank of matrix a. -c -c ..scalar arguments.. - integer n,m,na,rank - real*8 tol,sq -c ..array arguments.. - real*8 a(na,m),f(n),c(n),aa(n,m),ff(n),h(m) -c ..local scalars.. - integer i,ii,ij,i1,i2,j,jj,j1,j2,j3,k,kk,m1,nl - real*8 cos,fac,piv,sin,yi - double precision store,stor1,stor2,stor3 -c ..function references.. - integer min0 -c ..subroutine references.. -c fpgivs,fprota -c .. - m1 = m-1 -c the rank deficiency nl is considered to be the number of sufficient -c small diagonal elements of a. - nl = 0 - sq = 0. - do 90 i=1,n - if(a(i,1).gt.tol) go to 90 -c if a sufficient small diagonal element is found, we put it to -c zero. the remainder of the row corresponding to that zero diagonal -c element is then rotated into triangle by givens rotations . -c the rank deficiency is increased by one. - nl = nl+1 - if(i.eq.n) go to 90 - yi = f(i) - do 10 j=1,m1 - h(j) = a(i,j+1) - 10 continue - h(m) = 0. - i1 = i+1 - do 60 ii=i1,n - i2 = min0(n-ii,m1) - piv = h(1) - if(piv.eq.0.) go to 30 - call fpgivs(piv,a(ii,1),cos,sin) - call fprota(cos,sin,yi,f(ii)) - if(i2.eq.0) go to 70 - do 20 j=1,i2 - j1 = j+1 - call fprota(cos,sin,h(j1),a(ii,j1)) - h(j) = h(j1) - 20 continue - go to 50 - 30 if(i2.eq.0) go to 70 - do 40 j=1,i2 - h(j) = h(j+1) - 40 continue - 50 h(i2+1) = 0. - 60 continue -c add to the sum of squared residuals the contribution of deleting -c the row with small diagonal element. - 70 sq = sq+yi**2 - 90 continue -c rank denotes the rank of a. - rank = n-nl -c let b denote the (rank*n) upper trapezoidal matrix which can be -c obtained from the (n*n) upper triangular matrix a by deleting -c the rows and interchanging the columns corresponding to a zero -c diagonal element. if this matrix is factorized using givens -c transformations as b = (r) (u) where -c r is a (rank*rank) upper triangular matrix, -c u is a (rank*n) orthonormal matrix -c then the minimal least-squares solution c is given by c = b' v, -c where v is the solution of the system (r) (r)' v = g and -c g denotes the vector obtained from the old right hand side f, by -c removing the elements corresponding to a zero diagonal element of a. -c initialization. - do 100 i=1,rank - do 100 j=1,m - aa(i,j) = 0. - 100 continue -c form in aa the upper triangular matrix obtained from a by -c removing rows and columns with zero diagonal elements. form in ff -c the new right hand side by removing the elements of the old right -c hand side corresponding to a deleted row. - ii = 0 - do 120 i=1,n - if(a(i,1).le.tol) go to 120 - ii = ii+1 - ff(ii) = f(i) - aa(ii,1) = a(i,1) - jj = ii - kk = 1 - j = i - j1 = min0(j-1,m1) - if(j1.eq.0) go to 120 - do 110 k=1,j1 - j = j-1 - if(a(j,1).le.tol) go to 110 - kk = kk+1 - jj = jj-1 - aa(jj,kk) = a(j,k+1) - 110 continue - 120 continue -c form successively in h the columns of a with a zero diagonal element. - ii = 0 - do 200 i=1,n - ii = ii+1 - if(a(i,1).gt.tol) go to 200 - ii = ii-1 - if(ii.eq.0) go to 200 - jj = 1 - j = i - j1 = min0(j-1,m1) - do 130 k=1,j1 - j = j-1 - if(a(j,1).le.tol) go to 130 - h(jj) = a(j,k+1) - jj = jj+1 - 130 continue - do 140 kk=jj,m - h(kk) = 0. - 140 continue -c rotate this column into aa by givens transformations. - jj = ii - do 190 i1=1,ii - j1 = min0(jj-1,m1) - piv = h(1) - if(piv.ne.0.) go to 160 - if(j1.eq.0) go to 200 - do 150 j2=1,j1 - j3 = j2+1 - h(j2) = h(j3) - 150 continue - go to 180 - 160 call fpgivs(piv,aa(jj,1),cos,sin) - if(j1.eq.0) go to 200 - kk = jj - do 170 j2=1,j1 - j3 = j2+1 - kk = kk-1 - call fprota(cos,sin,h(j3),aa(kk,j3)) - h(j2) = h(j3) - 170 continue - 180 jj = jj-1 - h(j3) = 0. - 190 continue - 200 continue -c solve the system (aa) (f1) = ff - ff(rank) = ff(rank)/aa(rank,1) - i = rank-1 - if(i.eq.0) go to 230 - do 220 j=2,rank - store = ff(i) - i1 = min0(j-1,m1) - k = i - do 210 ii=1,i1 - k = k+1 - stor1 = ff(k) - stor2 = aa(i,ii+1) - store = store-stor1*stor2 - 210 continue - stor1 = aa(i,1) - ff(i) = store/stor1 - i = i-1 - 220 continue -c solve the system (aa)' (f2) = f1 - 230 ff(1) = ff(1)/aa(1,1) - if(rank.eq.1) go to 260 - do 250 j=2,rank - store = ff(j) - i1 = min0(j-1,m1) - k = j - do 240 ii=1,i1 - k = k-1 - stor1 = ff(k) - stor2 = aa(k,ii+1) - store = store-stor1*stor2 - 240 continue - stor1 = aa(j,1) - ff(j) = store/stor1 - 250 continue -c premultiply f2 by the transpoze of a. - 260 k = 0 - do 280 i=1,n - store = 0. - if(a(i,1).gt.tol) k = k+1 - j1 = min0(i,m) - kk = k - ij = i+1 - do 270 j=1,j1 - ij = ij-1 - if(a(ij,1).le.tol) go to 270 - stor1 = a(ij,j) - stor2 = ff(kk) - store = store+stor1*stor2 - kk = kk-1 - 270 continue - c(i) = store - 280 continue -c add to the sum of squared residuals the contribution of putting -c to zero the small diagonal elements of matrix (a). - stor3 = 0. - do 310 i=1,n - if(a(i,1).gt.tol) go to 310 - store = f(i) - i1 = min0(n-i,m1) - if(i1.eq.0) go to 300 - do 290 j=1,i1 - ij = i+j - stor1 = c(ij) - stor2 = a(i,j+1) - store = store-stor1*stor2 - 290 continue - 300 fac = a(i,1)*c(i) - stor1 = a(i,1) - stor2 = c(i) - stor1 = stor1*stor2 - stor3 = stor3+stor1*(stor1-store-store) - 310 continue - fac = stor3 - sq = sq+fac - return - end - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fprati.f =================================================================== --- branches/Interpolate1D/fitpack/fprati.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fprati.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,29 +0,0 @@ - real*8 function fprati(p1,f1,p2,f2,p3,f3) -c given three points (p1,f1),(p2,f2) and (p3,f3), function fprati -c gives the value of p such that the rational interpolating function -c of the form r(p) = (u*p+v)/(p+w) equals zero at p. -c .. -c ..scalar arguments.. - real*8 p1,f1,p2,f2,p3,f3 -c ..local scalars.. - real*8 h1,h2,h3,p -c .. - if(p3.gt.0.) go to 10 -c value of p in case p3 = infinity. - p = (p1*(f1-f3)*f2-p2*(f2-f3)*f1)/((f1-f2)*f3) - go to 20 -c value of p in case p3 ^= infinity. - 10 h1 = f1*(f2-f3) - h2 = f2*(f3-f1) - h3 = f3*(f1-f2) - p = -(p1*p2*h3+p2*p3*h1+p3*p1*h2)/(p1*h1+p2*h2+p3*h3) -c adjust the value of p1,f1,p3 and f3 such that f1 > 0 and f3 < 0. - 20 if(f2.lt.0.) go to 30 - p1 = p2 - f1 = f2 - go to 40 - 30 p3 = p2 - f3 = f2 - 40 fprati = p - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpregr.f =================================================================== --- branches/Interpolate1D/fitpack/fpregr.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpregr.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,367 +0,0 @@ - subroutine fpregr(iopt,x,mx,y,my,z,mz,xb,xe,yb,ye,kx,ky,s, - * nxest,nyest,tol,maxit,nc,nx,tx,ny,ty,c,fp,fp0,fpold,reducx, - * reducy,fpintx,fpinty,lastdi,nplusx,nplusy,nrx,nry,nrdatx,nrdaty, - * wrk,lwrk,ier) -c .. -c ..scalar arguments.. - real*8 xb,xe,yb,ye,s,tol,fp,fp0,fpold,reducx,reducy - integer iopt,mx,my,mz,kx,ky,nxest,nyest,maxit,nc,nx,ny,lastdi, - * nplusx,nplusy,lwrk,ier -c ..array arguments.. - real*8 x(mx),y(my),z(mz),tx(nxest),ty(nyest),c(nc),fpintx(nxest), - * fpinty(nyest),wrk(lwrk) - integer nrdatx(nxest),nrdaty(nyest),nrx(mx),nry(my) -c ..local scalars - real*8 acc,fpms,f1,f2,f3,p,p1,p2,p3,rn,one,half,con1,con9,con4 - integer i,ich1,ich3,ifbx,ifby,ifsx,ifsy,iter,j,kx1,kx2,ky1,ky2, - * k3,l,lax,lay,lbx,lby,lq,lri,lsx,lsy,mk1,mm,mpm,mynx,ncof, - * nk1x,nk1y,nmaxx,nmaxy,nminx,nminy,nplx,nply,npl1,nrintx, - * nrinty,nxe,nxk,nye -c ..function references.. - real*8 abs,fprati - integer max0,min0 -c ..subroutine references.. -c fpgrre,fpknot -c .. -c set constants - one = 1 - half = 0.5e0 - con1 = 0.1e0 - con9 = 0.9e0 - con4 = 0.4e-01 -c we partition the working space. - kx1 = kx+1 - ky1 = ky+1 - kx2 = kx1+1 - ky2 = ky1+1 - lsx = 1 - lsy = lsx+mx*kx1 - lri = lsy+my*ky1 - mm = max0(nxest,my) - lq = lri+mm - mynx = nxest*my - lax = lq+mynx - nxk = nxest*kx2 - lbx = lax+nxk - lay = lbx+nxk - lby = lay+nyest*ky2 -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 1: determination of the number of knots and their position. c -c **************************************************************** c -c given a set of knots we compute the least-squares spline sinf(x,y), c -c and the corresponding sum of squared residuals fp=f(p=inf). c -c if iopt=-1 sinf(x,y) is the requested approximation. c -c if iopt=0 or iopt=1 we check whether we can accept the knots: c -c if fp <=s we will continue with the current set of knots. c -c if fp > s we will increase the number of knots and compute the c -c corresponding least-squares spline until finally fp<=s. c -c the initial choice of knots depends on the value of s and iopt. c -c if s=0 we have spline interpolation; in that case the number of c -c knots equals nmaxx = mx+kx+1 and nmaxy = my+ky+1. c -c if s>0 and c -c *iopt=0 we first compute the least-squares polynomial of degree c -c kx in x and ky in y; nx=nminx=2*kx+2 and ny=nymin=2*ky+2. c -c *iopt=1 we start with the knots found at the last call of the c -c routine, except for the case that s > fp0; then we can compute c -c the least-squares polynomial directly. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c determine the number of knots for polynomial approximation. - nminx = 2*kx1 - nminy = 2*ky1 - if(iopt.lt.0) go to 120 -c acc denotes the absolute tolerance for the root of f(p)=s. - acc = tol*s -c find nmaxx and nmaxy which denote the number of knots in x- and y- -c direction in case of spline interpolation. - nmaxx = mx+kx1 - nmaxy = my+ky1 -c find nxe and nye which denote the maximum number of knots -c allowed in each direction - nxe = min0(nmaxx,nxest) - nye = min0(nmaxy,nyest) - if(s.gt.0.) go to 100 -c if s = 0, s(x,y) is an interpolating spline. - nx = nmaxx - ny = nmaxy -c test whether the required storage space exceeds the available one. - if(ny.gt.nyest .or. nx.gt.nxest) go to 420 -c find the position of the interior knots in case of interpolation. -c the knots in the x-direction. - mk1 = mx-kx1 - if(mk1.eq.0) go to 60 - k3 = kx/2 - i = kx1+1 - j = k3+2 - if(k3*2.eq.kx) go to 40 - do 30 l=1,mk1 - tx(i) = x(j) - i = i+1 - j = j+1 - 30 continue - go to 60 - 40 do 50 l=1,mk1 - tx(i) = (x(j)+x(j-1))*half - i = i+1 - j = j+1 - 50 continue -c the knots in the y-direction. - 60 mk1 = my-ky1 - if(mk1.eq.0) go to 120 - k3 = ky/2 - i = ky1+1 - j = k3+2 - if(k3*2.eq.ky) go to 80 - do 70 l=1,mk1 - ty(i) = y(j) - i = i+1 - j = j+1 - 70 continue - go to 120 - 80 do 90 l=1,mk1 - ty(i) = (y(j)+y(j-1))*half - i = i+1 - j = j+1 - 90 continue - go to 120 -c if s > 0 our initial choice of knots depends on the value of iopt. - 100 if(iopt.eq.0) go to 115 - if(fp0.le.s) go to 115 -c if iopt=1 and fp0 > s we start computing the least- squares spline -c according to the set of knots found at the last call of the routine. -c we determine the number of grid coordinates x(i) inside each knot -c interval (tx(l),tx(l+1)). - l = kx2 - j = 1 - nrdatx(1) = 0 - mpm = mx-1 - do 105 i=2,mpm - nrdatx(j) = nrdatx(j)+1 - if(x(i).lt.tx(l)) go to 105 - nrdatx(j) = nrdatx(j)-1 - l = l+1 - j = j+1 - nrdatx(j) = 0 - 105 continue -c we determine the number of grid coordinates y(i) inside each knot -c interval (ty(l),ty(l+1)). - l = ky2 - j = 1 - nrdaty(1) = 0 - mpm = my-1 - do 110 i=2,mpm - nrdaty(j) = nrdaty(j)+1 - if(y(i).lt.ty(l)) go to 110 - nrdaty(j) = nrdaty(j)-1 - l = l+1 - j = j+1 - nrdaty(j) = 0 - 110 continue - go to 120 -c if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares -c polynomial of degree kx in x and ky in y (which is a spline without -c interior knots). - 115 nx = nminx - ny = nminy - nrdatx(1) = mx-2 - nrdaty(1) = my-2 - lastdi = 0 - nplusx = 0 - nplusy = 0 - fp0 = 0. - fpold = 0. - reducx = 0. - reducy = 0. - 120 mpm = mx+my - ifsx = 0 - ifsy = 0 - ifbx = 0 - ifby = 0 - p = -one -c main loop for the different sets of knots.mpm=mx+my is a save upper -c bound for the number of trials. - do 250 iter=1,mpm - if(nx.eq.nminx .and. ny.eq.nminy) ier = -2 -c find nrintx (nrinty) which is the number of knot intervals in the -c x-direction (y-direction). - nrintx = nx-nminx+1 - nrinty = ny-nminy+1 -c find ncof, the number of b-spline coefficients for the current set -c of knots. - nk1x = nx-kx1 - nk1y = ny-ky1 - ncof = nk1x*nk1y -c find the position of the additional knots which are needed for the -c b-spline representation of s(x,y). - i = nx - do 130 j=1,kx1 - tx(j) = xb - tx(i) = xe - i = i-1 - 130 continue - i = ny - do 140 j=1,ky1 - ty(j) = yb - ty(i) = ye - i = i-1 - 140 continue -c find the least-squares spline sinf(x,y) and calculate for each knot -c interval tx(j+kx)<=x<=tx(j+kx+1) (ty(j+ky)<=y<=ty(j+ky+1)) the sum -c of squared residuals fpintx(j),j=1,2,...,nx-2*kx-1 (fpinty(j),j=1,2, -c ...,ny-2*ky-1) for the data points having their absciss (ordinate)- -c value belonging to that interval. -c fp gives the total sum of squared residuals. - call fpgrre(ifsx,ifsy,ifbx,ifby,x,mx,y,my,z,mz,kx,ky,tx,nx,ty, - * ny,p,c,nc,fp,fpintx,fpinty,mm,mynx,kx1,kx2,ky1,ky2,wrk(lsx), - * wrk(lsy),wrk(lri),wrk(lq),wrk(lax),wrk(lay),wrk(lbx),wrk(lby), - * nrx,nry) - if(ier.eq.(-2)) fp0 = fp -c test whether the least-squares spline is an acceptable solution. - if(iopt.lt.0) go to 440 - fpms = fp-s - if(abs(fpms) .lt. acc) go to 440 -c if f(p=inf) < s, we accept the choice of knots. - if(fpms.lt.0.) go to 300 -c if nx=nmaxx and ny=nmaxy, sinf(x,y) is an interpolating spline. - if(nx.eq.nmaxx .and. ny.eq.nmaxy) go to 430 -c increase the number of knots. -c if nx=nxe and ny=nye we cannot further increase the number of knots -c because of the storage capacity limitation. - if(nx.eq.nxe .and. ny.eq.nye) go to 420 - ier = 0 -c adjust the parameter reducx or reducy according to the direction -c in which the last added knots were located. - if (lastdi.lt.0) go to 150 - if (lastdi.eq.0) go to 170 - go to 160 - 150 reducx = fpold-fp - go to 170 - 160 reducy = fpold-fp -c store the sum of squared residuals for the current set of knots. - 170 fpold = fp -c find nplx, the number of knots we should add in the x-direction. - nplx = 1 - if(nx.eq.nminx) go to 180 - npl1 = nplusx*2 - rn = nplusx - if(reducx.gt.acc) npl1 = rn*fpms/reducx - nplx = min0(nplusx*2,max0(npl1,nplusx/2,1)) -c find nply, the number of knots we should add in the y-direction. - 180 nply = 1 - if(ny.eq.nminy) go to 190 - npl1 = nplusy*2 - rn = nplusy - if(reducy.gt.acc) npl1 = rn*fpms/reducy - nply = min0(nplusy*2,max0(npl1,nplusy/2,1)) - 190 if (nplx.lt.nply) go to 210 - if (nplx.eq.nply) go to 200 - go to 230 - 200 if(lastdi.lt.0) go to 230 - 210 if(nx.eq.nxe) go to 230 -c addition in the x-direction. - lastdi = -1 - nplusx = nplx - ifsx = 0 - do 220 l=1,nplusx -c add a new knot in the x-direction - call fpknot(x,mx,tx,nx,fpintx,nrdatx,nrintx,nxest,1) -c test whether we cannot further increase the number of knots in the -c x-direction. - if(nx.eq.nxe) go to 250 - 220 continue - go to 250 - 230 if(ny.eq.nye) go to 210 -c addition in the y-direction. - lastdi = 1 - nplusy = nply - ifsy = 0 - do 240 l=1,nplusy -c add a new knot in the y-direction. - call fpknot(y,my,ty,ny,fpinty,nrdaty,nrinty,nyest,1) -c test whether we cannot further increase the number of knots in the -c y-direction. - if(ny.eq.nye) go to 250 - 240 continue -c restart the computations with the new set of knots. - 250 continue -c test whether the least-squares polynomial is a solution of our -c approximation problem. - 300 if(ier.eq.(-2)) go to 440 -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 2: determination of the smoothing spline sp(x,y) c -c ***************************************************** c -c we have determined the number of knots and their position. we now c -c compute the b-spline coefficients of the smoothing spline sp(x,y). c -c this smoothing spline varies with the parameter p in such a way thatc -c f(p) = sumi=1,mx(sumj=1,my((z(i,j)-sp(x(i),y(j)))**2) c -c is a continuous, strictly decreasing function of p. moreover the c -c least-squares polynomial corresponds to p=0 and the least-squares c -c spline to p=infinity. iteratively we then have to determine the c -c positive value of p such that f(p)=s. the process which is proposed c -c here makes use of rational interpolation. f(p) is approximated by a c -c rational function r(p)=(u*p+v)/(p+w); three values of p (p1,p2,p3) c -c with corresponding values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s)c -c are used to calculate the new value of p such that r(p)=s. c -c convergence is guaranteed by taking f1 > 0 and f3 < 0. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c initial value for p. - p1 = 0. - f1 = fp0-s - p3 = -one - f3 = fpms - p = one - ich1 = 0 - ich3 = 0 -c iteration process to find the root of f(p)=s. - do 350 iter = 1,maxit -c find the smoothing spline sp(x,y) and the corresponding sum of -c squared residuals fp. - call fpgrre(ifsx,ifsy,ifbx,ifby,x,mx,y,my,z,mz,kx,ky,tx,nx,ty, - * ny,p,c,nc,fp,fpintx,fpinty,mm,mynx,kx1,kx2,ky1,ky2,wrk(lsx), - * wrk(lsy),wrk(lri),wrk(lq),wrk(lax),wrk(lay),wrk(lbx),wrk(lby), - * nrx,nry) -c test whether the approximation sp(x,y) is an acceptable solution. - fpms = fp-s - if(abs(fpms).lt.acc) go to 440 -c test whether the maximum allowable number of iterations has been -c reached. - if(iter.eq.maxit) go to 400 -c carry out one more step of the iteration process. - p2 = p - f2 = fpms - if(ich3.ne.0) go to 320 - if((f2-f3).gt.acc) go to 310 -c our initial choice of p is too large. - p3 = p2 - f3 = f2 - p = p*con4 - if(p.le.p1) p = p1*con9 + p2*con1 - go to 350 - 310 if(f2.lt.0.) ich3 = 1 - 320 if(ich1.ne.0) go to 340 - if((f1-f2).gt.acc) go to 330 -c our initial choice of p is too small - p1 = p2 - f1 = f2 - p = p/con4 - if(p3.lt.0.) go to 350 - if(p.ge.p3) p = p2*con1 + p3*con9 - go to 350 -c test whether the iteration process proceeds as theoretically -c expected. - 330 if(f2.gt.0.) ich1 = 1 - 340 if(f2.ge.f1 .or. f2.le.f3) go to 410 -c find the new value of p. - p = fprati(p1,f1,p2,f2,p3,f3) - 350 continue -c error codes and messages. - 400 ier = 3 - go to 440 - 410 ier = 2 - go to 440 - 420 ier = 1 - go to 440 - 430 ier = -1 - fp = 0. - 440 return - end - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fprota.f =================================================================== --- branches/Interpolate1D/fitpack/fprota.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fprota.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,14 +0,0 @@ - subroutine fprota(cos,sin,a,b) -c subroutine fprota applies a givens rotation to a and b. -c .. -c ..scalar arguments.. - real*8 cos,sin,a,b -c ..local scalars.. - real*8 stor1,stor2 -c .. - stor1 = a - stor2 = b - b = cos*stor2+sin*stor1 - a = cos*stor1-sin*stor2 - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fprppo.f =================================================================== --- branches/Interpolate1D/fitpack/fprppo.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fprppo.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,61 +0,0 @@ - subroutine fprppo(nu,nv,if1,if2,cosi,ratio,c,f,ncoff) -c given the coefficients of a constrained bicubic spline, as determined -c in subroutine fppola, subroutine fprppo calculates the coefficients -c in the standard b-spline representation of bicubic splines. -c .. -c ..scalar arguments.. - real*8 ratio - integer nu,nv,if1,if2,ncoff -c ..array arguments - real*8 c(ncoff),f(ncoff),cosi(5,nv) -c ..local scalars.. - integer i,iopt,ii,j,k,l,nu4,nvv -c .. - nu4 = nu-4 - nvv = nv-7 - iopt = if1+1 - do 10 i=1,ncoff - f(i) = 0. - 10 continue - i = 0 - do 120 l=1,nu4 - ii = i - if(l.gt.iopt) go to 80 - go to (20,40,60),l - 20 do 30 k=1,nvv - i = i+1 - f(i) = c(1) - 30 continue - j = 1 - go to 100 - 40 do 50 k=1,nvv - i = i+1 - f(i) = c(1)+c(2)*cosi(1,k)+c(3)*cosi(2,k) - 50 continue - j = 3 - go to 100 - 60 do 70 k=1,nvv - i = i+1 - f(i) = c(1)+ratio*(c(2)*cosi(1,k)+c(3)*cosi(2,k))+ - * c(4)*cosi(3,k)+c(5)*cosi(4,k)+c(6)*cosi(5,k) - 70 continue - j = 6 - go to 100 - 80 if(l.eq.nu4 .and. if2.ne.0) go to 120 - do 90 k=1,nvv - i = i+1 - j = j+1 - f(i) = c(j) - 90 continue - 100 do 110 k=1,3 - ii = ii+1 - i = i+1 - f(i) = f(ii) - 110 continue - 120 continue - do 130 i=1,ncoff - c(i) = f(i) - 130 continue - return - end - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fprpsp.f =================================================================== --- branches/Interpolate1D/fitpack/fprpsp.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fprpsp.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,55 +0,0 @@ - subroutine fprpsp(nt,np,co,si,c,f,ncoff) -c given the coefficients of a spherical spline function, subroutine -c fprpsp calculates the coefficients in the standard b-spline re- -c presentation of this bicubic spline. -c .. -c ..scalar arguments - integer nt,np,ncoff -c ..array arguments - real*8 co(np),si(np),c(ncoff),f(ncoff) -c ..local scalars - real*8 cn,c1,c2,c3 - integer i,ii,j,k,l,ncof,npp,np4,nt4 -c .. - nt4 = nt-4 - np4 = np-4 - npp = np4-3 - ncof = 6+npp*(nt4-4) - c1 = c(1) - cn = c(ncof) - j = ncoff - do 10 i=1,np4 - f(i) = c1 - f(j) = cn - j = j-1 - 10 continue - i = np4 - j=1 - do 70 l=3,nt4 - ii = i - if(l.eq.3 .or. l.eq.nt4) go to 30 - do 20 k=1,npp - i = i+1 - j = j+1 - f(i) = c(j) - 20 continue - go to 50 - 30 if(l.eq.nt4) c1 = cn - c2 = c(j+1) - c3 = c(j+2) - j = j+2 - do 40 k=1,npp - i = i+1 - f(i) = c1+c2*co(k)+c3*si(k) - 40 continue - 50 do 60 k=1,3 - ii = ii+1 - i = i+1 - f(i) = f(ii) - 60 continue - 70 continue - do 80 i=1,ncoff - c(i) = f(i) - 80 continue - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpseno.f =================================================================== --- branches/Interpolate1D/fitpack/fpseno.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpseno.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,34 +0,0 @@ - subroutine fpseno(maxtr,up,left,right,info,merk,ibind,nbind) -c subroutine fpseno fetches a branch of a triply linked tree the -c information of which is kept in the arrays up,left,right and info. -c the branch has a specified length nbind and is determined by the -c parameter merk which points to its terminal node. the information -c field of the nodes of this branch is stored in the array ibind. on -c exit merk points to a new branch of length nbind or takes the value -c 1 if no such branch was found. -c .. -c ..scalar arguments.. - integer maxtr,merk,nbind -c ..array arguments.. - integer up(maxtr),left(maxtr),right(maxtr),info(maxtr), - * ibind(nbind) -c ..scalar arguments.. - integer i,j,k -c .. - k = merk - j = nbind - do 10 i=1,nbind - ibind(j) = info(k) - k = up(k) - j = j-1 - 10 continue - 20 k = right(merk) - if(k.ne.0) go to 30 - merk = up(merk) - if (merk.le.1) go to 40 - go to 20 - 30 merk = k - k = left(merk) - if(k.ne.0) go to 30 - 40 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpspgr.f =================================================================== --- branches/Interpolate1D/fitpack/fpspgr.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpspgr.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,439 +0,0 @@ - subroutine fpspgr(iopt,ider,u,mu,v,mv,r,mr,r0,r1,s,nuest,nvest, - * tol,maxit,nc,nu,tu,nv,tv,c,fp,fp0,fpold,reducu,reducv,fpintu, - * fpintv,dr,step,lastdi,nplusu,nplusv,lastu0,lastu1,nru,nrv, - * nrdatu,nrdatv,wrk,lwrk,ier) -c .. -c ..scalar arguments.. - integer mu,mv,mr,nuest,nvest,maxit,nc,nu,nv,lastdi,nplusu,nplusv, - * lastu0,lastu1,lwrk,ier - real*8 r0,r1,s,tol,fp,fp0,fpold,reducu,reducv -c ..array arguments.. - integer iopt(3),ider(4),nrdatu(nuest),nrdatv(nvest),nru(mu), - * nrv(mv) - real*8 u(mu),v(mv),r(mr),tu(nuest),tv(nvest),c(nc),fpintu(nuest), - * fpintv(nvest),dr(6),wrk(lwrk),step(2) -c ..local scalars.. - real*8 acc,fpms,f1,f2,f3,p,per,pi,p1,p2,p3,vb,ve,rmax,rmin,rn,one, - * - * con1,con4,con9 - integer i,ich1,ich3,ifbu,ifbv,ifsu,ifsv,istart,iter,i1,i2,j,ju, - * ktu,l,l1,l2,l3,l4,mpm,mumin,mu0,mu1,nn,nplu,nplv,npl1,nrintu, - * nrintv,nue,numax,nve,nvmax -c ..local arrays.. - integer idd(4) - real*8 drr(6) -c ..function references.. - real*8 abs,datan2,fprati - integer max0,min0 -c ..subroutine references.. -c fpknot,fpopsp -c .. -c set constants - one = 1d0 - con1 = 0.1e0 - con9 = 0.9e0 - con4 = 0.4e-01 -c initialization - ifsu = 0 - ifsv = 0 - ifbu = 0 - ifbv = 0 - p = -one - mumin = 4 - if(ider(1).ge.0) mumin = mumin-1 - if(iopt(2).eq.1 .and. ider(2).eq.1) mumin = mumin-1 - if(ider(3).ge.0) mumin = mumin-1 - if(iopt(3).eq.1 .and. ider(4).eq.1) mumin = mumin-1 - if(mumin.eq.0) mumin = 1 - pi = datan2(0d0,-one) - per = pi+pi - vb = v(1) - ve = vb+per -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 1: determination of the number of knots and their position. c -c **************************************************************** c -c given a set of knots we compute the least-squares spline sinf(u,v) c -c and the corresponding sum of squared residuals fp = f(p=inf). c -c if iopt(1)=-1 sinf(u,v) is the requested approximation. c -c if iopt(1)>=0 we check whether we can accept the knots: c -c if fp <= s we will continue with the current set of knots. c -c if fp > s we will increase the number of knots and compute the c -c corresponding least-squares spline until finally fp <= s. c -c the initial choice of knots depends on the value of s and iopt. c -c if s=0 we have spline interpolation; in that case the number of c -c knots in the u-direction equals nu=numax=mu+6+iopt(2)+iopt(3) c -c and in the v-direction nv=nvmax=mv+7. c -c if s>0 and c -c iopt(1)=0 we first compute the least-squares polynomial,i.e. a c -c spline without interior knots : nu=8 ; nv=8. c -c iopt(1)=1 we start with the set of knots found at the last call c -c of the routine, except for the case that s > fp0; then we c -c compute the least-squares polynomial directly. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - if(iopt(1).lt.0) go to 120 -c acc denotes the absolute tolerance for the root of f(p)=s. - acc = tol*s -c numax and nvmax denote the number of knots needed for interpolation. - numax = mu+6+iopt(2)+iopt(3) - nvmax = mv+7 - nue = min0(numax,nuest) - nve = min0(nvmax,nvest) - if(s.gt.0.) go to 100 -c if s = 0, s(u,v) is an interpolating spline. - nu = numax - nv = nvmax -c test whether the required storage space exceeds the available one. - if(nu.gt.nuest .or. nv.gt.nvest) go to 420 -c find the position of the knots in the v-direction. - do 10 l=1,mv - tv(l+3) = v(l) - 10 continue - tv(mv+4) = ve - l1 = mv-2 - l2 = mv+5 - do 20 i=1,3 - tv(i) = v(l1)-per - tv(l2) = v(i+1)+per - l1 = l1+1 - l2 = l2+1 - 20 continue -c if not all the derivative values g(i,j) are given, we will first -c estimate these values by computing a least-squares spline - idd(1) = ider(1) - if(idd(1).eq.0) idd(1) = 1 - if(idd(1).gt.0) dr(1) = r0 - idd(2) = ider(2) - idd(3) = ider(3) - if(idd(3).eq.0) idd(3) = 1 - if(idd(3).gt.0) dr(4) = r1 - idd(4) = ider(4) - if(ider(1).lt.0 .or. ider(3).lt.0) go to 30 - if(iopt(2).ne.0 .and. ider(2).eq.0) go to 30 - if(iopt(3).eq.0 .or. ider(4).ne.0) go to 70 -c we set up the knots in the u-direction for computing the least-squares -c spline. - 30 i1 = 3 - i2 = mu-2 - nu = 4 - do 40 i=1,mu - if(i1.gt.i2) go to 50 - nu = nu+1 - tu(nu) = u(i1) - i1 = i1+2 - 40 continue - 50 do 60 i=1,4 - tu(i) = 0. - nu = nu+1 - tu(nu) = pi - 60 continue -c we compute the least-squares spline for estimating the derivatives. - call fpopsp(ifsu,ifsv,ifbu,ifbv,u,mu,v,mv,r,mr,r0,r1,dr,iopt,idd, - * tu,nu,tv,nv,nuest,nvest,p,step,c,nc,fp,fpintu,fpintv,nru,nrv, - * wrk,lwrk) - ifsu = 0 -c if all the derivatives at the origin are known, we compute the -c interpolating spline. -c we set up the knots in the u-direction, needed for interpolation. - 70 nn = numax-8 - if(nn.eq.0) go to 95 - ju = 2-iopt(2) - do 80 l=1,nn - tu(l+4) = u(ju) - ju = ju+1 - 80 continue - nu = numax - l = nu - do 90 i=1,4 - tu(i) = 0. - tu(l) = pi - l = l-1 - 90 continue -c we compute the interpolating spline. - 95 call fpopsp(ifsu,ifsv,ifbu,ifbv,u,mu,v,mv,r,mr,r0,r1,dr,iopt,idd, - * tu,nu,tv,nv,nuest,nvest,p,step,c,nc,fp,fpintu,fpintv,nru,nrv, - * wrk,lwrk) - go to 430 -c if s>0 our initial choice of knots depends on the value of iopt(1). - 100 ier = 0 - if(iopt(1).eq.0) go to 115 - step(1) = -step(1) - step(2) = -step(2) - if(fp0.le.s) go to 115 -c if iopt(1)=1 and fp0 > s we start computing the least-squares spline -c according to the set of knots found at the last call of the routine. -c we determine the number of grid coordinates u(i) inside each knot -c interval (tu(l),tu(l+1)). - l = 5 - j = 1 - nrdatu(1) = 0 - mu0 = 2-iopt(2) - mu1 = mu-1+iopt(3) - do 105 i=mu0,mu1 - nrdatu(j) = nrdatu(j)+1 - if(u(i).lt.tu(l)) go to 105 - nrdatu(j) = nrdatu(j)-1 - l = l+1 - j = j+1 - nrdatu(j) = 0 - 105 continue -c we determine the number of grid coordinates v(i) inside each knot -c interval (tv(l),tv(l+1)). - l = 5 - j = 1 - nrdatv(1) = 0 - do 110 i=2,mv - nrdatv(j) = nrdatv(j)+1 - if(v(i).lt.tv(l)) go to 110 - nrdatv(j) = nrdatv(j)-1 - l = l+1 - j = j+1 - nrdatv(j) = 0 - 110 continue - idd(1) = ider(1) - idd(2) = ider(2) - idd(3) = ider(3) - idd(4) = ider(4) - go to 120 -c if iopt(1)=0 or iopt(1)=1 and s >= fp0,we start computing the least- -c squares polynomial (which is a spline without interior knots). - 115 ier = -2 - idd(1) = ider(1) - idd(2) = 1 - idd(3) = ider(3) - idd(4) = 1 - nu = 8 - nv = 8 - nrdatu(1) = mu-2+iopt(2)+iopt(3) - nrdatv(1) = mv-1 - lastdi = 0 - nplusu = 0 - nplusv = 0 - fp0 = 0. - fpold = 0. - reducu = 0. - reducv = 0. -c main loop for the different sets of knots.mpm=mu+mv is a save upper -c bound for the number of trials. - 120 mpm = mu+mv - do 270 iter=1,mpm -c find nrintu (nrintv) which is the number of knot intervals in the -c u-direction (v-direction). - nrintu = nu-7 - nrintv = nv-7 -c find the position of the additional knots which are needed for the -c b-spline representation of s(u,v). - i = nu - do 125 j=1,4 - tu(j) = 0. - tu(i) = pi - i = i-1 - 125 continue - l1 = 4 - l2 = l1 - l3 = nv-3 - l4 = l3 - tv(l2) = vb - tv(l3) = ve - do 130 j=1,3 - l1 = l1+1 - l2 = l2-1 - l3 = l3+1 - l4 = l4-1 - tv(l2) = tv(l4)-per - tv(l3) = tv(l1)+per - 130 continue -c find an estimate of the range of possible values for the optimal -c derivatives at the origin. - ktu = nrdatu(1)+2-iopt(2) - if(ktu.lt.mumin) ktu = mumin - if(ktu.eq.lastu0) go to 140 - rmin = r0 - rmax = r0 - l = mv*ktu - do 135 i=1,l - if(r(i).lt.rmin) rmin = r(i) - if(r(i).gt.rmax) rmax = r(i) - 135 continue - step(1) = rmax-rmin - lastu0 = ktu - 140 ktu = nrdatu(nrintu)+2-iopt(3) - if(ktu.lt.mumin) ktu = mumin - if(ktu.eq.lastu1) go to 150 - rmin = r1 - rmax = r1 - l = mv*ktu - j = mr - do 145 i=1,l - if(r(j).lt.rmin) rmin = r(j) - if(r(j).gt.rmax) rmax = r(j) - j = j-1 - 145 continue - step(2) = rmax-rmin - lastu1 = ktu -c find the least-squares spline sinf(u,v). - 150 call fpopsp(ifsu,ifsv,ifbu,ifbv,u,mu,v,mv,r,mr,r0,r1,dr,iopt, - * idd,tu,nu,tv,nv,nuest,nvest,p,step,c,nc,fp,fpintu,fpintv,nru, - * nrv,wrk,lwrk) - if(step(1).lt.0.) step(1) = -step(1) - if(step(2).lt.0.) step(2) = -step(2) - if(ier.eq.(-2)) fp0 = fp -c test whether the least-squares spline is an acceptable solution. - if(iopt(1).lt.0) go to 440 - fpms = fp-s - if(abs(fpms) .lt. acc) go to 440 -c if f(p=inf) < s, we accept the choice of knots. - if(fpms.lt.0.) go to 300 -c if nu=numax and nv=nvmax, sinf(u,v) is an interpolating spline - if(nu.eq.numax .and. nv.eq.nvmax) go to 430 -c increase the number of knots. -c if nu=nue and nv=nve we cannot further increase the number of knots -c because of the storage capacity limitation. - if(nu.eq.nue .and. nv.eq.nve) go to 420 - if(ider(1).eq.0) fpintu(1) = fpintu(1)+(r0-dr(1))**2 - if(ider(3).eq.0) fpintu(nrintu) = fpintu(nrintu)+(r1-dr(4))**2 - ier = 0 -c adjust the parameter reducu or reducv according to the direction -c in which the last added knots were located. - if (lastdi.lt.0) go to 160 - if (lastdi.eq.0) go to 155 - go to 170 - 155 nplv = 3 - idd(2) = ider(2) - idd(4) = ider(4) - fpold = fp - go to 230 - 160 reducu = fpold-fp - go to 175 - 170 reducv = fpold-fp -c store the sum of squared residuals for the current set of knots. - 175 fpold = fp -c find nplu, the number of knots we should add in the u-direction. - nplu = 1 - if(nu.eq.8) go to 180 - npl1 = nplusu*2 - rn = nplusu - if(reducu.gt.acc) npl1 = rn*fpms/reducu - nplu = min0(nplusu*2,max0(npl1,nplusu/2,1)) -c find nplv, the number of knots we should add in the v-direction. - 180 nplv = 3 - if(nv.eq.8) go to 190 - npl1 = nplusv*2 - rn = nplusv - if(reducv.gt.acc) npl1 = rn*fpms/reducv - nplv = min0(nplusv*2,max0(npl1,nplusv/2,1)) -c test whether we are going to add knots in the u- or v-direction. - 190 if (nplu.lt.nplv) go to 210 - if (nplu.eq.nplv) go to 200 - go to 230 - 200 if(lastdi.lt.0) go to 230 - 210 if(nu.eq.nue) go to 230 -c addition in the u-direction. - lastdi = -1 - nplusu = nplu - ifsu = 0 - istart = 0 - if(iopt(2).eq.0) istart = 1 - do 220 l=1,nplusu -c add a new knot in the u-direction - call fpknot(u,mu,tu,nu,fpintu,nrdatu,nrintu,nuest,istart) -c test whether we cannot further increase the number of knots in the -c u-direction. - if(nu.eq.nue) go to 270 - 220 continue - go to 270 - 230 if(nv.eq.nve) go to 210 -c addition in the v-direction. - lastdi = 1 - nplusv = nplv - ifsv = 0 - do 240 l=1,nplusv -c add a new knot in the v-direction. - call fpknot(v,mv,tv,nv,fpintv,nrdatv,nrintv,nvest,1) -c test whether we cannot further increase the number of knots in the -c v-direction. - if(nv.eq.nve) go to 270 - 240 continue -c restart the computations with the new set of knots. - 270 continue -c test whether the least-squares polynomial is a solution of our -c approximation problem. - 300 if(ier.eq.(-2)) go to 440 -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 2: determination of the smoothing spline sp(u,v) c -c ***************************************************** c -c we have determined the number of knots and their position. we now c -c compute the b-spline coefficients of the smoothing spline sp(u,v). c -c this smoothing spline depends on the parameter p in such a way that c -c f(p) = sumi=1,mu(sumj=1,mv((z(i,j)-sp(u(i),v(j)))**2) c -c is a continuous, strictly decreasing function of p. moreover the c -c least-squares polynomial corresponds to p=0 and the least-squares c -c spline to p=infinity. then iteratively we have to determine the c -c positive value of p such that f(p)=s. the process which is proposed c -c here makes use of rational interpolation. f(p) is approximated by a c -c rational function r(p)=(u*p+v)/(p+w); three values of p (p1,p2,p3) c -c with corresponding values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s)c -c are used to calculate the new value of p such that r(p)=s. c -c convergence is guaranteed by taking f1 > 0 and f3 < 0. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c initial value for p. - p1 = 0. - f1 = fp0-s - p3 = -one - f3 = fpms - p = one - do 305 i=1,6 - drr(i) = dr(i) - 305 continue - ich1 = 0 - ich3 = 0 -c iteration process to find the root of f(p)=s. - do 350 iter = 1,maxit -c find the smoothing spline sp(u,v) and the corresponding sum f(p). - call fpopsp(ifsu,ifsv,ifbu,ifbv,u,mu,v,mv,r,mr,r0,r1,drr,iopt, - * idd,tu,nu,tv,nv,nuest,nvest,p,step,c,nc,fp,fpintu,fpintv,nru, - * nrv,wrk,lwrk) -c test whether the approximation sp(u,v) is an acceptable solution. - fpms = fp-s - if(abs(fpms).lt.acc) go to 440 -c test whether the maximum allowable number of iterations has been -c reached. - if(iter.eq.maxit) go to 400 -c carry out one more step of the iteration process. - p2 = p - f2 = fpms - if(ich3.ne.0) go to 320 - if((f2-f3).gt.acc) go to 310 -c our initial choice of p is too large. - p3 = p2 - f3 = f2 - p = p*con4 - if(p.le.p1) p = p1*con9 + p2*con1 - go to 350 - 310 if(f2.lt.0.) ich3 = 1 - 320 if(ich1.ne.0) go to 340 - if((f1-f2).gt.acc) go to 330 -c our initial choice of p is too small - p1 = p2 - f1 = f2 - p = p/con4 - if(p3.lt.0.) go to 350 - if(p.ge.p3) p = p2*con1 + p3*con9 - go to 350 -c test whether the iteration process proceeds as theoretically -c expected. - 330 if(f2.gt.0.) ich1 = 1 - 340 if(f2.ge.f1 .or. f2.le.f3) go to 410 -c find the new value of p. - p = fprati(p1,f1,p2,f2,p3,f3) - 350 continue -c error codes and messages. - 400 ier = 3 - go to 440 - 410 ier = 2 - go to 440 - 420 ier = 1 - go to 440 - 430 ier = -1 - fp = 0. - 440 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpsphe.f =================================================================== --- branches/Interpolate1D/fitpack/fpsphe.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpsphe.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,764 +0,0 @@ - subroutine fpsphe(iopt,m,teta,phi,r,w,s,ntest,npest,eta,tol,maxit, - * - * ib1,ib3,nc,ncc,intest,nrest,nt,tt,np,tp,c,fp,sup,fpint,coord,f, - * ff,row,coco,cosi,a,q,bt,bp,spt,spp,h,index,nummer,wrk,lwrk,ier) -c .. -c ..scalar arguments.. - integer iopt,m,ntest,npest,maxit,ib1,ib3,nc,ncc,intest,nrest, - * nt,np,lwrk,ier - real*8 s,eta,tol,fp,sup -c ..array arguments.. - real*8 teta(m),phi(m),r(m),w(m),tt(ntest),tp(npest),c(nc), - * fpint(intest),coord(intest),f(ncc),ff(nc),row(npest),coco(npest), - * - * cosi(npest),a(ncc,ib1),q(ncc,ib3),bt(ntest,5),bp(npest,5), - * spt(m,4),spp(m,4),h(ib3),wrk(lwrk) - integer index(nrest),nummer(m) -c ..local scalars.. - real*8 aa,acc,arg,cn,co,c1,dmax,d1,d2,eps,facc,facs,fac1,fac2,fn, - * fpmax,fpms,f1,f2,f3,hti,htj,p,pi,pinv,piv,pi2,p1,p2,p3,ri,si, - * sigma,sq,store,wi,rn,one,con1,con9,con4,half,ten - integer i,iband,iband1,iband3,iband4,ich1,ich3,ii,ij,il,in,irot, - * iter,i1,i2,i3,j,jlt,jrot,j1,j2,l,la,lf,lh,ll,lp,lt,lwest,l1,l2, - * l3,l4,ncof,ncoff,npp,np4,nreg,nrint,nrr,nr1,ntt,nt4,nt6,num, - * num1,rank -c ..local arrays.. - real*8 ht(4),hp(4) -c ..function references.. - real*8 abs,atan,fprati,sqrt,cos,sin - integer min0 -c ..subroutine references.. -c fpback,fpbspl,fpgivs,fpdisc,fporde,fprank,fprota,fprpsp -c .. -c set constants - one = 0.1e+01 - con1 = 0.1e0 - con9 = 0.9e0 - con4 = 0.4e-01 - half = 0.5e0 - ten = 0.1e+02 - pi = atan(one)*4 - pi2 = pi+pi - eps = sqrt(eta) - if(iopt.lt.0) go to 70 -c calculation of acc, the absolute tolerance for the root of f(p)=s. - acc = tol*s - if(iopt.eq.0) go to 10 - if(s.lt.sup) then - if (np.lt.11) go to 60 - go to 70 - endif -c if iopt=0 we begin by computing the weighted least-squares polynomial -c of the form -c s(teta,phi) = c1*f1(teta) + cn*fn(teta) -c where f1(teta) and fn(teta) are the cubic polynomials satisfying -c f1(0) = 1, f1(pi) = f1'(0) = f1'(pi) = 0 ; fn(teta) = 1-f1(teta). -c the corresponding weighted sum of squared residuals gives the upper -c bound sup for the smoothing factor s. - 10 sup = 0. - d1 = 0. - d2 = 0. - c1 = 0. - cn = 0. - fac1 = pi*(one + half) - fac2 = (one + one)/pi**3 - aa = 0. - do 40 i=1,m - wi = w(i) - ri = r(i)*wi - arg = teta(i) - fn = fac2*arg*arg*(fac1-arg) - f1 = (one-fn)*wi - fn = fn*wi - if(fn.eq.0.) go to 20 - call fpgivs(fn,d1,co,si) - call fprota(co,si,f1,aa) - call fprota(co,si,ri,cn) - 20 if(f1.eq.0.) go to 30 - call fpgivs(f1,d2,co,si) - call fprota(co,si,ri,c1) - 30 sup = sup+ri*ri - 40 continue - if(d2.ne.0.) c1 = c1/d2 - if(d1.ne.0.) cn = (cn-aa*c1)/d1 -c find the b-spline representation of this least-squares polynomial - nt = 8 - np = 8 - do 50 i=1,4 - c(i) = c1 - c(i+4) = c1 - c(i+8) = cn - c(i+12) = cn - tt(i) = 0. - tt(i+4) = pi - tp(i) = 0. - tp(i+4) = pi2 - 50 continue - fp = sup -c test whether the least-squares polynomial is an acceptable solution - fpms = sup-s - if(fpms.lt.acc) go to 960 -c test whether we cannot further increase the number of knots. - 60 if(npest.lt.11 .or. ntest.lt.9) go to 950 -c find the initial set of interior knots of the spherical spline in -c case iopt = 0. - np = 11 - tp(5) = pi*half - tp(6) = pi - tp(7) = tp(5)+pi - nt = 9 - tt(5) = tp(5) -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 1 : computation of least-squares spherical splines. c -c ******************************************************** c -c if iopt < 0 we compute the least-squares spherical spline according c -c to the given set of knots. c -c if iopt >=0 we compute least-squares spherical splines with increas-c -c ing numbers of knots until the corresponding sum f(p=inf)<=s. c -c the initial set of knots then depends on the value of iopt: c -c if iopt=0 we start with one interior knot in the teta-direction c -c (pi/2) and three in the phi-direction (pi/2,pi,3*pi/2). c -c if iopt>0 we start with the set of knots found at the last call c -c of the routine. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c main loop for the different sets of knots. m is a save upper bound -c for the number of trials. - 70 do 570 iter=1,m -c find the position of the additional knots which are needed for the -c b-spline representation of s(teta,phi). - l1 = 4 - l2 = l1 - l3 = np-3 - l4 = l3 - tp(l2) = 0. - tp(l3) = pi2 - do 80 i=1,3 - l1 = l1+1 - l2 = l2-1 - l3 = l3+1 - l4 = l4-1 - tp(l2) = tp(l4)-pi2 - tp(l3) = tp(l1)+pi2 - 80 continue - l = nt - do 90 i=1,4 - tt(i) = 0. - tt(l) = pi - l = l-1 - 90 continue -c find nrint, the total number of knot intervals and nreg, the number -c of panels in which the approximation domain is subdivided by the -c intersection of knots. - ntt = nt-7 - npp = np-7 - nrr = npp/2 - nr1 = nrr+1 - nrint = ntt+npp - nreg = ntt*npp -c arrange the data points according to the panel they belong to. - call fporde(teta,phi,m,3,3,tt,nt,tp,np,nummer,index,nreg) -c find the b-spline coefficients coco and cosi of the cubic spline -c approximations sc(phi) and ss(phi) for cos(phi) and sin(phi). - do 100 i=1,npp - coco(i) = 0. - cosi(i) = 0. - do 100 j=1,npp - a(i,j) = 0. - 100 continue -c the coefficients coco and cosi are obtained from the conditions -c sc(tp(i))=cos(tp(i)),resp. ss(tp(i))=sin(tp(i)),i=4,5,...np-4. - do 150 i=1,npp - l2 = i+3 - arg = tp(l2) - call fpbspl(tp,np,3,arg,l2,hp) - do 110 j=1,npp - row(j) = 0. - 110 continue - ll = i - do 120 j=1,3 - if(ll.gt.npp) ll= 1 - row(ll) = row(ll)+hp(j) - ll = ll+1 - 120 continue - facc = cos(arg) - facs = sin(arg) - do 140 j=1,npp - piv = row(j) - if(piv.eq.0.) go to 140 - call fpgivs(piv,a(j,1),co,si) - call fprota(co,si,facc,coco(j)) - call fprota(co,si,facs,cosi(j)) - if(j.eq.npp) go to 150 - j1 = j+1 - i2 = 1 - do 130 l=j1,npp - i2 = i2+1 - call fprota(co,si,row(l),a(j,i2)) - 130 continue - 140 continue - 150 continue - call fpback(a,coco,npp,npp,coco,ncc) - call fpback(a,cosi,npp,npp,cosi,ncc) -c find ncof, the dimension of the spherical spline and ncoff, the -c number of coefficients in the standard b-spline representation. - nt4 = nt-4 - np4 = np-4 - ncoff = nt4*np4 - ncof = 6+npp*(ntt-1) -c find the bandwidth of the observation matrix a. - iband = 4*npp - if(ntt.eq.4) iband = 3*(npp+1) - if(ntt.lt.4) iband = ncof - iband1 = iband-1 -c initialize the observation matrix a. - do 160 i=1,ncof - f(i) = 0. - do 160 j=1,iband - a(i,j) = 0. - 160 continue -c initialize the sum of squared residuals. - fp = 0. -c fetch the data points in the new order. main loop for the -c different panels. - do 340 num=1,nreg -c fix certain constants for the current panel; jrot records the column -c number of the first non-zero element in a row of the observation -c matrix according to a data point of the panel. - num1 = num-1 - lt = num1/npp - l1 = lt+4 - lp = num1-lt*npp+1 - l2 = lp+3 - lt = lt+1 - jrot = 0 - if(lt.gt.2) jrot = 3+(lt-3)*npp -c test whether there are still data points in the current panel. - in = index(num) - 170 if(in.eq.0) go to 340 -c fetch a new data point. - wi = w(in) - ri = r(in)*wi -c evaluate for the teta-direction, the 4 non-zero b-splines at teta(in) - call fpbspl(tt,nt,3,teta(in),l1,ht) -c evaluate for the phi-direction, the 4 non-zero b-splines at phi(in) - call fpbspl(tp,np,3,phi(in),l2,hp) -c store the value of these b-splines in spt and spp resp. - do 180 i=1,4 - spp(in,i) = hp(i) - spt(in,i) = ht(i) - 180 continue -c initialize the new row of observation matrix. - do 190 i=1,iband - h(i) = 0. - 190 continue -c calculate the non-zero elements of the new row by making the cross -c products of the non-zero b-splines in teta- and phi-direction and -c by taking into account the conditions of the spherical splines. - do 200 i=1,npp - row(i) = 0. - 200 continue -c take into account the condition (3) of the spherical splines. - ll = lp - do 210 i=1,4 - if(ll.gt.npp) ll=1 - row(ll) = row(ll)+hp(i) - ll = ll+1 - 210 continue -c take into account the other conditions of the spherical splines. - if(lt.gt.2 .and. lt.lt.(ntt-1)) go to 230 - facc = 0. - facs = 0. - do 220 i=1,npp - facc = facc+row(i)*coco(i) - facs = facs+row(i)*cosi(i) - 220 continue -c fill in the non-zero elements of the new row. - 230 j1 = 0 - do 280 j =1,4 - jlt = j+lt - htj = ht(j) - if(jlt.gt.2 .and. jlt.le.nt4) go to 240 - j1 = j1+1 - h(j1) = h(j1)+htj - go to 280 - 240 if(jlt.eq.3 .or. jlt.eq.nt4) go to 260 - do 250 i=1,npp - j1 = j1+1 - h(j1) = row(i)*htj - 250 continue - go to 280 - 260 if(jlt.eq.3) go to 270 - h(j1+1) = facc*htj - h(j1+2) = facs*htj - h(j1+3) = htj - j1 = j1+2 - go to 280 - 270 h(1) = h(1)+htj - h(2) = facc*htj - h(3) = facs*htj - j1 = 3 - 280 continue - do 290 i=1,iband - h(i) = h(i)*wi - 290 continue -c rotate the row into triangle by givens transformations. - irot = jrot - do 310 i=1,iband - irot = irot+1 - piv = h(i) - if(piv.eq.0.) go to 310 -c calculate the parameters of the givens transformation. - call fpgivs(piv,a(irot,1),co,si) -c apply that transformation to the right hand side. - call fprota(co,si,ri,f(irot)) - if(i.eq.iband) go to 320 -c apply that transformation to the left hand side. - i2 = 1 - i3 = i+1 - do 300 j=i3,iband - i2 = i2+1 - call fprota(co,si,h(j),a(irot,i2)) - 300 continue - 310 continue -c add the contribution of the row to the sum of squares of residual -c right hand sides. - 320 fp = fp+ri**2 -c find the number of the next data point in the panel. - 330 in = nummer(in) - go to 170 - 340 continue -c find dmax, the maximum value for the diagonal elements in the reduced -c triangle. - dmax = 0. - do 350 i=1,ncof - if(a(i,1).le.dmax) go to 350 - dmax = a(i,1) - 350 continue -c check whether the observation matrix is rank deficient. - sigma = eps*dmax - do 360 i=1,ncof - if(a(i,1).le.sigma) go to 370 - 360 continue -c backward substitution in case of full rank. - call fpback(a,f,ncof,iband,c,ncc) - rank = ncof - do 365 i=1,ncof - q(i,1) = a(i,1)/dmax - 365 continue - go to 390 -c in case of rank deficiency, find the minimum norm solution. - 370 lwest = ncof*iband+ncof+iband - if(lwrk.lt.lwest) go to 925 - lf = 1 - lh = lf+ncof - la = lh+iband - do 380 i=1,ncof - ff(i) = f(i) - do 380 j=1,iband - q(i,j) = a(i,j) - 380 continue - call fprank(q,ff,ncof,iband,ncc,sigma,c,sq,rank,wrk(la), - * wrk(lf),wrk(lh)) - do 385 i=1,ncof - q(i,1) = q(i,1)/dmax - 385 continue -c add to the sum of squared residuals, the contribution of reducing -c the rank. - fp = fp+sq -c find the coefficients in the standard b-spline representation of -c the spherical spline. - 390 call fprpsp(nt,np,coco,cosi,c,ff,ncoff) -c test whether the least-squares spline is an acceptable solution. - if(iopt.lt.0) then - if (fp.le.0) go to 970 - go to 980 - endif - fpms = fp-s - if(abs(fpms).le.acc) then - if (fp.le.0) go to 970 - go to 980 - endif -c if f(p=inf) < s, accept the choice of knots. - if(fpms.lt.0.) go to 580 -c test whether we cannot further increase the number of knots. - if(ncof.gt.m) go to 935 -c search where to add a new knot. -c find for each interval the sum of squared residuals fpint for the -c data points having the coordinate belonging to that knot interval. -c calculate also coord which is the same sum, weighted by the position -c of the data points considered. - 440 do 450 i=1,nrint - fpint(i) = 0. - coord(i) = 0. - 450 continue - do 490 num=1,nreg - num1 = num-1 - lt = num1/npp - l1 = lt+1 - lp = num1-lt*npp - l2 = lp+1+ntt - jrot = lt*np4+lp - in = index(num) - 460 if(in.eq.0) go to 490 - store = 0. - i1 = jrot - do 480 i=1,4 - hti = spt(in,i) - j1 = i1 - do 470 j=1,4 - j1 = j1+1 - store = store+hti*spp(in,j)*c(j1) - 470 continue - i1 = i1+np4 - 480 continue - store = (w(in)*(r(in)-store))**2 - fpint(l1) = fpint(l1)+store - coord(l1) = coord(l1)+store*teta(in) - fpint(l2) = fpint(l2)+store - coord(l2) = coord(l2)+store*phi(in) - in = nummer(in) - go to 460 - 490 continue -c find the interval for which fpint is maximal on the condition that -c there still can be added a knot. - l1 = 1 - l2 = nrint - if(ntest.lt.nt+1) l1=ntt+1 - if(npest.lt.np+2) l2=ntt -c test whether we cannot further increase the number of knots. - if(l1.gt.l2) go to 950 - 500 fpmax = 0. - l = 0 - do 510 i=l1,l2 - if(fpmax.ge.fpint(i)) go to 510 - l = i - fpmax = fpint(i) - 510 continue - if(l.eq.0) go to 930 -c calculate the position of the new knot. - arg = coord(l)/fpint(l) -c test in what direction the new knot is going to be added. - if(l.gt.ntt) go to 530 -c addition in the teta-direction - l4 = l+4 - fpint(l) = 0. - fac1 = tt(l4)-arg - fac2 = arg-tt(l4-1) - if(fac1.gt.(ten*fac2) .or. fac2.gt.(ten*fac1)) go to 500 - j = nt - do 520 i=l4,nt - tt(j+1) = tt(j) - j = j-1 - 520 continue - tt(l4) = arg - nt = nt+1 - go to 570 -c addition in the phi-direction - 530 l4 = l+4-ntt - if(arg.lt.pi) go to 540 - arg = arg-pi - l4 = l4-nrr - 540 fpint(l) = 0. - fac1 = tp(l4)-arg - fac2 = arg-tp(l4-1) - if(fac1.gt.(ten*fac2) .or. fac2.gt.(ten*fac1)) go to 500 - ll = nrr+4 - j = ll - do 550 i=l4,ll - tp(j+1) = tp(j) - j = j-1 - 550 continue - tp(l4) = arg - np = np+2 - nrr = nrr+1 - do 560 i=5,ll - j = i+nrr - tp(j) = tp(i)+pi - 560 continue -c restart the computations with the new set of knots. - 570 continue -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 2: determination of the smoothing spherical spline. c -c ******************************************************** c -c we have determined the number of knots and their position. we now c -c compute the coefficients of the smoothing spline sp(teta,phi). c -c the observation matrix a is extended by the rows of a matrix, expres-c -c sing that sp(teta,phi) must be a constant function in the variable c -c phi and a cubic polynomial in the variable teta. the corresponding c -c weights of these additional rows are set to 1/(p). iteratively c -c we than have to determine the value of p such that f(p) = sum((w(i)* c -c (r(i)-sp(teta(i),phi(i))))**2) be = s. c -c we already know that the least-squares polynomial corresponds to p=0,c -c and that the least-squares spherical spline corresponds to p=infin. c -c the iteration process makes use of rational interpolation. since f(p)c -c is a convex and strictly decreasing function of p, it can be approx- c -c imated by a rational function of the form r(p) = (u*p+v)/(p+w). c -c three values of p (p1,p2,p3) with corresponding values of f(p) (f1= c -c f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used to calculate the new value c -c of p such that r(p)=s. convergence is guaranteed by taking f1>0,f3<0.c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c evaluate the discontinuity jumps of the 3-th order derivative of -c the b-splines at the knots tt(l),l=5,...,nt-4. - 580 call fpdisc(tt,nt,5,bt,ntest) -c evaluate the discontinuity jumps of the 3-th order derivative of -c the b-splines at the knots tp(l),l=5,...,np-4. - call fpdisc(tp,np,5,bp,npest) -c initial value for p. - p1 = 0. - f1 = sup-s - p3 = -one - f3 = fpms - p = 0. - do 585 i=1,ncof - p = p+a(i,1) - 585 continue - rn = ncof - p = rn/p -c find the bandwidth of the extended observation matrix. - iband4 = iband+3 - if(ntt.le.4) iband4 = ncof - iband3 = iband4 -1 - ich1 = 0 - ich3 = 0 -c iteration process to find the root of f(p)=s. - do 920 iter=1,maxit - pinv = one/p -c store the triangularized observation matrix into q. - do 600 i=1,ncof - ff(i) = f(i) - do 590 j=1,iband4 - q(i,j) = 0. - 590 continue - do 600 j=1,iband - q(i,j) = a(i,j) - 600 continue -c extend the observation matrix with the rows of a matrix, expressing -c that for teta=cst. sp(teta,phi) must be a constant function. - nt6 = nt-6 - do 720 i=5,np4 - ii = i-4 - do 610 l=1,npp - row(l) = 0. - 610 continue - ll = ii - do 620 l=1,5 - if(ll.gt.npp) ll=1 - row(ll) = row(ll)+bp(ii,l) - ll = ll+1 - 620 continue - facc = 0. - facs = 0. - do 630 l=1,npp - facc = facc+row(l)*coco(l) - facs = facs+row(l)*cosi(l) - 630 continue - do 720 j=1,nt6 -c initialize the new row. - do 640 l=1,iband - h(l) = 0. - 640 continue -c fill in the non-zero elements of the row. jrot records the column -c number of the first non-zero element in the row. - jrot = 4+(j-2)*npp - if(j.gt.1 .and. j.lt.nt6) go to 650 - h(1) = facc - h(2) = facs - if(j.eq.1) jrot = 2 - go to 670 - 650 do 660 l=1,npp - h(l)=row(l) - 660 continue - 670 do 675 l=1,iband - h(l) = h(l)*pinv - 675 continue - ri = 0. -c rotate the new row into triangle by givens transformations. - do 710 irot=jrot,ncof - piv = h(1) - i2 = min0(iband1,ncof-irot) - if(piv.eq.0.) then - if (i2.le.0) go to 720 - go to 690 - endif -c calculate the parameters of the givens transformation. - call fpgivs(piv,q(irot,1),co,si) -c apply that givens transformation to the right hand side. - call fprota(co,si,ri,ff(irot)) - if(i2.eq.0) go to 720 -c apply that givens transformation to the left hand side. - do 680 l=1,i2 - l1 = l+1 - call fprota(co,si,h(l1),q(irot,l1)) - 680 continue - 690 do 700 l=1,i2 - h(l) = h(l+1) - 700 continue - h(i2+1) = 0. - 710 continue - 720 continue -c extend the observation matrix with the rows of a matrix expressing -c that for phi=cst. sp(teta,phi) must be a cubic polynomial. - do 810 i=5,nt4 - ii = i-4 - do 810 j=1,npp -c initialize the new row - do 730 l=1,iband4 - h(l) = 0. - 730 continue -c fill in the non-zero elements of the row. jrot records the column -c number of the first non-zero element in the row. - j1 = 1 - do 760 l=1,5 - il = ii+l - ij = npp - if(il.ne.3 .and. il.ne.nt4) go to 750 - j1 = j1+3-j - j2 = j1-2 - ij = 0 - if(il.ne.3) go to 740 - j1 = 1 - j2 = 2 - ij = j+2 - 740 h(j2) = bt(ii,l)*coco(j) - h(j2+1) = bt(ii,l)*cosi(j) - 750 h(j1) = h(j1)+bt(ii,l) - j1 = j1+ij - 760 continue - do 765 l=1,iband4 - h(l) = h(l)*pinv - 765 continue - ri = 0. - jrot = 1 - if(ii.gt.2) jrot = 3+j+(ii-3)*npp -c rotate the new row into triangle by givens transformations. - do 800 irot=jrot,ncof - piv = h(1) - i2 = min0(iband3,ncof-irot) - if(piv.eq.0.) then - if (i2.le.0) go to 810 - go to 780 - endif -c calculate the parameters of the givens transformation. - call fpgivs(piv,q(irot,1),co,si) -c apply that givens transformation to the right hand side. - call fprota(co,si,ri,ff(irot)) - if(i2.eq.0) go to 810 -c apply that givens transformation to the left hand side. - do 770 l=1,i2 - l1 = l+1 - call fprota(co,si,h(l1),q(irot,l1)) - 770 continue - 780 do 790 l=1,i2 - h(l) = h(l+1) - 790 continue - h(i2+1) = 0. - 800 continue - 810 continue -c find dmax, the maximum value for the diagonal elements in the -c reduced triangle. - dmax = 0. - do 820 i=1,ncof - if(q(i,1).le.dmax) go to 820 - dmax = q(i,1) - 820 continue -c check whether the matrix is rank deficient. - sigma = eps*dmax - do 830 i=1,ncof - if(q(i,1).le.sigma) go to 840 - 830 continue -c backward substitution in case of full rank. - call fpback(q,ff,ncof,iband4,c,ncc) - rank = ncof - go to 845 -c in case of rank deficiency, find the minimum norm solution. - 840 lwest = ncof*iband4+ncof+iband4 - if(lwrk.lt.lwest) go to 925 - lf = 1 - lh = lf+ncof - la = lh+iband4 - call fprank(q,ff,ncof,iband4,ncc,sigma,c,sq,rank,wrk(la), - * wrk(lf),wrk(lh)) - 845 do 850 i=1,ncof - q(i,1) = q(i,1)/dmax - 850 continue -c find the coefficients in the standard b-spline representation of -c the spherical spline. - call fprpsp(nt,np,coco,cosi,c,ff,ncoff) -c compute f(p). - fp = 0. - do 890 num = 1,nreg - num1 = num-1 - lt = num1/npp - lp = num1-lt*npp - jrot = lt*np4+lp - in = index(num) - 860 if(in.eq.0) go to 890 - store = 0. - i1 = jrot - do 880 i=1,4 - hti = spt(in,i) - j1 = i1 - do 870 j=1,4 - j1 = j1+1 - store = store+hti*spp(in,j)*c(j1) - 870 continue - i1 = i1+np4 - 880 continue - fp = fp+(w(in)*(r(in)-store))**2 - in = nummer(in) - go to 860 - 890 continue -c test whether the approximation sp(teta,phi) is an acceptable solution - fpms = fp-s - if(abs(fpms).le.acc) go to 980 -c test whether the maximum allowable number of iterations has been -c reached. - if(iter.eq.maxit) go to 940 -c carry out one more step of the iteration process. - p2 = p - f2 = fpms - if(ich3.ne.0) go to 900 - if((f2-f3).gt.acc) go to 895 -c our initial choice of p is too large. - p3 = p2 - f3 = f2 - p = p*con4 - if(p.le.p1) p = p1*con9 + p2*con1 - go to 920 - 895 if(f2.lt.0.) ich3 = 1 - 900 if(ich1.ne.0) go to 910 - if((f1-f2).gt.acc) go to 905 -c our initial choice of p is too small - p1 = p2 - f1 = f2 - p = p/con4 - if(p3.lt.0.) go to 920 - if(p.ge.p3) p = p2*con1 +p3*con9 - go to 920 - 905 if(f2.gt.0.) ich1 = 1 -c test whether the iteration process proceeds as theoretically -c expected. - 910 if(f2.ge.f1 .or. f2.le.f3) go to 945 -c find the new value of p. - p = fprati(p1,f1,p2,f2,p3,f3) - 920 continue -c error codes and messages. - 925 ier = lwest - go to 990 - 930 ier = 5 - go to 990 - 935 ier = 4 - go to 990 - 940 ier = 3 - go to 990 - 945 ier = 2 - go to 990 - 950 ier = 1 - go to 990 - 960 ier = -2 - go to 990 - 970 ier = -1 - fp = 0. - 980 if(ncof.ne.rank) ier = -rank - 990 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpsuev.f =================================================================== --- branches/Interpolate1D/fitpack/fpsuev.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpsuev.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,80 +0,0 @@ - subroutine fpsuev(idim,tu,nu,tv,nv,c,u,mu,v,mv,f,wu,wv,lu,lv) -c ..scalar arguments.. - integer idim,nu,nv,mu,mv -c ..array arguments.. - integer lu(mu),lv(mv) - real*8 tu(nu),tv(nv),c((nu-4)*(nv-4)*idim),u(mu),v(mv), - * f(mu*mv*idim),wu(mu,4),wv(mv,4) -c ..local scalars.. - integer i,i1,j,j1,k,l,l1,l2,l3,m,nuv,nu4,nv4 - real*8 arg,sp,tb,te -c ..local arrays.. - real*8 h(4) -c ..subroutine references.. -c fpbspl -c .. - nu4 = nu-4 - tb = tu(4) - te = tu(nu4+1) - l = 4 - l1 = l+1 - do 40 i=1,mu - arg = u(i) - if(arg.lt.tb) arg = tb - if(arg.gt.te) arg = te - 10 if(arg.lt.tu(l1) .or. l.eq.nu4) go to 20 - l = l1 - l1 = l+1 - go to 10 - 20 call fpbspl(tu,nu,3,arg,l,h) - lu(i) = l-4 - do 30 j=1,4 - wu(i,j) = h(j) - 30 continue - 40 continue - nv4 = nv-4 - tb = tv(4) - te = tv(nv4+1) - l = 4 - l1 = l+1 - do 80 i=1,mv - arg = v(i) - if(arg.lt.tb) arg = tb - if(arg.gt.te) arg = te - 50 if(arg.lt.tv(l1) .or. l.eq.nv4) go to 60 - l = l1 - l1 = l+1 - go to 50 - 60 call fpbspl(tv,nv,3,arg,l,h) - lv(i) = l-4 - do 70 j=1,4 - wv(i,j) = h(j) - 70 continue - 80 continue - m = 0 - nuv = nu4*nv4 - do 140 k=1,idim - l3 = (k-1)*nuv - do 130 i=1,mu - l = lu(i)*nv4+l3 - do 90 i1=1,4 - h(i1) = wu(i,i1) - 90 continue - do 120 j=1,mv - l1 = l+lv(j) - sp = 0. - do 110 i1=1,4 - l2 = l1 - do 100 j1=1,4 - l2 = l2+1 - sp = sp+c(l2)*h(i1)*wv(j,j1) - 100 continue - l1 = l1+nv4 - 110 continue - m = m+1 - f(m) = sp - 120 continue - 130 continue - 140 continue - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpsurf.f =================================================================== --- branches/Interpolate1D/fitpack/fpsurf.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpsurf.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,680 +0,0 @@ - subroutine fpsurf(iopt,m,x,y,z,w,xb,xe,yb,ye,kxx,kyy,s,nxest, - * nyest,eta,tol,maxit,nmax,km1,km2,ib1,ib3,nc,intest,nrest, - * nx0,tx,ny0,ty,c,fp,fp0,fpint,coord,f,ff,a,q,bx,by,spx,spy,h, - * index,nummer,wrk,lwrk,ier) -c .. -c ..scalar arguments.. - real*8 xb,xe,yb,ye,s,eta,tol,fp,fp0 - integer iopt,m,kxx,kyy,nxest,nyest,maxit,nmax,km1,km2,ib1,ib3, - * nc,intest,nrest,nx0,ny0,lwrk,ier -c ..array arguments.. - real*8 x(m),y(m),z(m),w(m),tx(nmax),ty(nmax),c(nc),fpint(intest), - * coord(intest),f(nc),ff(nc),a(nc,ib1),q(nc,ib3),bx(nmax,km2), - * by(nmax,km2),spx(m,km1),spy(m,km1),h(ib3),wrk(lwrk) - integer index(nrest),nummer(m) -c ..local scalars.. - real*8 acc,arg,cos,dmax,fac1,fac2,fpmax,fpms,f1,f2,f3,hxi,p,pinv, - * piv,p1,p2,p3,sigma,sin,sq,store,wi,x0,x1,y0,y1,zi,eps, - * rn,one,con1,con9,con4,half,ten - integer i,iband,iband1,iband3,iband4,ibb,ichang,ich1,ich3,ii, - * in,irot,iter,i1,i2,i3,j,jrot,jxy,j1,kx,kx1,kx2,ky,ky1,ky2,l, - * la,lf,lh,lwest,lx,ly,l1,l2,n,ncof,nk1x,nk1y,nminx,nminy,nreg, - * nrint,num,num1,nx,nxe,nxx,ny,nye,nyy,n1,rank -c ..local arrays.. - real*8 hx(6),hy(6) -c ..function references.. - real*8 abs,fprati,sqrt - integer min0 -c ..subroutine references.. -c fpback,fpbspl,fpgivs,fpdisc,fporde,fprank,fprota -c .. -c set constants - one = 0.1e+01 - con1 = 0.1e0 - con9 = 0.9e0 - con4 = 0.4e-01 - half = 0.5e0 - ten = 0.1e+02 -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 1: determination of the number of knots and their position. c -c **************************************************************** c -c given a set of knots we compute the least-squares spline sinf(x,y), c -c and the corresponding weighted sum of squared residuals fp=f(p=inf). c -c if iopt=-1 sinf(x,y) is the requested approximation. c -c if iopt=0 or iopt=1 we check whether we can accept the knots: c -c if fp <=s we will continue with the current set of knots. c -c if fp > s we will increase the number of knots and compute the c -c corresponding least-squares spline until finally fp<=s. c -c the initial choice of knots depends on the value of s and iopt. c -c if iopt=0 we first compute the least-squares polynomial of degree c -c kx in x and ky in y; nx=nminx=2*kx+2 and ny=nminy=2*ky+2. c -c fp0=f(0) denotes the corresponding weighted sum of squared c -c residuals c -c if iopt=1 we start with the knots found at the last call of the c -c routine, except for the case that s>=fp0; then we can compute c -c the least-squares polynomial directly. c -c eventually the independent variables x and y (and the corresponding c -c parameters) will be switched if this can reduce the bandwidth of the c -c system to be solved. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c ichang denotes whether(1) or not(-1) the directions have been inter- -c changed. - ichang = -1 - x0 = xb - x1 = xe - y0 = yb - y1 = ye - kx = kxx - ky = kyy - kx1 = kx+1 - ky1 = ky+1 - nxe = nxest - nye = nyest - eps = sqrt(eta) - if(iopt.lt.0) go to 20 -c calculation of acc, the absolute tolerance for the root of f(p)=s. - acc = tol*s - if(iopt.eq.0) go to 10 - if(fp0.gt.s) go to 20 -c initialization for the least-squares polynomial. - 10 nminx = 2*kx1 - nminy = 2*ky1 - nx = nminx - ny = nminy - ier = -2 - go to 30 - 20 nx = nx0 - ny = ny0 -c main loop for the different sets of knots. m is a save upper bound -c for the number of trials. - 30 do 420 iter=1,m -c find the position of the additional knots which are needed for the -c b-spline representation of s(x,y). - l = nx - do 40 i=1,kx1 - tx(i) = x0 - tx(l) = x1 - l = l-1 - 40 continue - l = ny - do 50 i=1,ky1 - ty(i) = y0 - ty(l) = y1 - l = l-1 - 50 continue -c find nrint, the total number of knot intervals and nreg, the number -c of panels in which the approximation domain is subdivided by the -c intersection of knots. - nxx = nx-2*kx1+1 - nyy = ny-2*ky1+1 - nrint = nxx+nyy - nreg = nxx*nyy -c find the bandwidth of the observation matrix a. -c if necessary, interchange the variables x and y, in order to obtain -c a minimal bandwidth. - iband1 = kx*(ny-ky1)+ky - l = ky*(nx-kx1)+kx - if(iband1.le.l) go to 130 - iband1 = l - ichang = -ichang - do 60 i=1,m - store = x(i) - x(i) = y(i) - y(i) = store - 60 continue - store = x0 - x0 = y0 - y0 = store - store = x1 - x1 = y1 - y1 = store - n = min0(nx,ny) - do 70 i=1,n - store = tx(i) - tx(i) = ty(i) - ty(i) = store - 70 continue - n1 = n+1 - if (nx.lt.ny) go to 80 - if (nx.eq.ny) go to 120 - go to 100 - 80 do 90 i=n1,ny - tx(i) = ty(i) - 90 continue - go to 120 - 100 do 110 i=n1,nx - ty(i) = tx(i) - 110 continue - 120 l = nx - nx = ny - ny = l - l = nxe - nxe = nye - nye = l - l = nxx - nxx = nyy - nyy = l - l = kx - kx = ky - ky = l - kx1 = kx+1 - ky1 = ky+1 - 130 iband = iband1+1 -c arrange the data points according to the panel they belong to. - call fporde(x,y,m,kx,ky,tx,nx,ty,ny,nummer,index,nreg) -c find ncof, the number of b-spline coefficients. - nk1x = nx-kx1 - nk1y = ny-ky1 - ncof = nk1x*nk1y -c initialize the observation matrix a. - do 140 i=1,ncof - f(i) = 0. - do 140 j=1,iband - a(i,j) = 0. - 140 continue -c initialize the sum of squared residuals. - fp = 0. -c fetch the data points in the new order. main loop for the -c different panels. - do 250 num=1,nreg -c fix certain constants for the current panel; jrot records the column -c number of the first non-zero element in a row of the observation -c matrix according to a data point of the panel. - num1 = num-1 - lx = num1/nyy - l1 = lx+kx1 - ly = num1-lx*nyy - l2 = ly+ky1 - jrot = lx*nk1y+ly -c test whether there are still data points in the panel. - in = index(num) - 150 if(in.eq.0) go to 250 -c fetch a new data point. - wi = w(in) - zi = z(in)*wi -c evaluate for the x-direction, the (kx+1) non-zero b-splines at x(in). - call fpbspl(tx,nx,kx,x(in),l1,hx) -c evaluate for the y-direction, the (ky+1) non-zero b-splines at y(in). - call fpbspl(ty,ny,ky,y(in),l2,hy) -c store the value of these b-splines in spx and spy respectively. - do 160 i=1,kx1 - spx(in,i) = hx(i) - 160 continue - do 170 i=1,ky1 - spy(in,i) = hy(i) - 170 continue -c initialize the new row of observation matrix. - do 180 i=1,iband - h(i) = 0. - 180 continue -c calculate the non-zero elements of the new row by making the cross -c products of the non-zero b-splines in x- and y-direction. - i1 = 0 - do 200 i=1,kx1 - hxi = hx(i) - j1 = i1 - do 190 j=1,ky1 - j1 = j1+1 - h(j1) = hxi*hy(j)*wi - 190 continue - i1 = i1+nk1y - 200 continue -c rotate the row into triangle by givens transformations . - irot = jrot - do 220 i=1,iband - irot = irot+1 - piv = h(i) - if(piv.eq.0.) go to 220 -c calculate the parameters of the givens transformation. - call fpgivs(piv,a(irot,1),cos,sin) -c apply that transformation to the right hand side. - call fprota(cos,sin,zi,f(irot)) - if(i.eq.iband) go to 230 -c apply that transformation to the left hand side. - i2 = 1 - i3 = i+1 - do 210 j=i3,iband - i2 = i2+1 - call fprota(cos,sin,h(j),a(irot,i2)) - 210 continue - 220 continue -c add the contribution of the row to the sum of squares of residual -c right hand sides. - 230 fp = fp+zi**2 -c find the number of the next data point in the panel. - 240 in = nummer(in) - go to 150 - 250 continue -c find dmax, the maximum value for the diagonal elements in the reduced -c triangle. - dmax = 0. - do 260 i=1,ncof - if(a(i,1).le.dmax) go to 260 - dmax = a(i,1) - 260 continue -c check whether the observation matrix is rank deficient. - sigma = eps*dmax - do 270 i=1,ncof - if(a(i,1).le.sigma) go to 280 - 270 continue -c backward substitution in case of full rank. - call fpback(a,f,ncof,iband,c,nc) - rank = ncof - do 275 i=1,ncof - q(i,1) = a(i,1)/dmax - 275 continue - go to 300 -c in case of rank deficiency, find the minimum norm solution. -c check whether there is sufficient working space - 280 lwest = ncof*iband+ncof+iband - if(lwrk.lt.lwest) go to 780 - do 290 i=1,ncof - ff(i) = f(i) - do 290 j=1,iband - q(i,j) = a(i,j) - 290 continue - lf =1 - lh = lf+ncof - la = lh+iband - call fprank(q,ff,ncof,iband,nc,sigma,c,sq,rank,wrk(la), - * wrk(lf),wrk(lh)) - do 295 i=1,ncof - q(i,1) = q(i,1)/dmax - 295 continue -c add to the sum of squared residuals, the contribution of reducing -c the rank. - fp = fp+sq - 300 if(ier.eq.(-2)) fp0 = fp -c test whether the least-squares spline is an acceptable solution. - if(iopt.lt.0) go to 820 - fpms = fp-s - if(abs(fpms).le.acc) then - if (fp.le.0) go to 815 - go to 820 - endif -c test whether we can accept the choice of knots. - if(fpms.lt.0.) go to 430 -c test whether we cannot further increase the number of knots. - if(ncof.gt.m) go to 790 - ier = 0 -c search where to add a new knot. -c find for each interval the sum of squared residuals fpint for the -c data points having the coordinate belonging to that knot interval. -c calculate also coord which is the same sum, weighted by the position -c of the data points considered. - 310 do 320 i=1,nrint - fpint(i) = 0. - coord(i) = 0. - 320 continue - do 360 num=1,nreg - num1 = num-1 - lx = num1/nyy - l1 = lx+1 - ly = num1-lx*nyy - l2 = ly+1+nxx - jrot = lx*nk1y+ly - in = index(num) - 330 if(in.eq.0) go to 360 - store = 0. - i1 = jrot - do 350 i=1,kx1 - hxi = spx(in,i) - j1 = i1 - do 340 j=1,ky1 - j1 = j1+1 - store = store+hxi*spy(in,j)*c(j1) - 340 continue - i1 = i1+nk1y - 350 continue - store = (w(in)*(z(in)-store))**2 - fpint(l1) = fpint(l1)+store - coord(l1) = coord(l1)+store*x(in) - fpint(l2) = fpint(l2)+store - coord(l2) = coord(l2)+store*y(in) - in = nummer(in) - go to 330 - 360 continue -c find the interval for which fpint is maximal on the condition that -c there still can be added a knot. - 370 l = 0 - fpmax = 0. - l1 = 1 - l2 = nrint - if(nx.eq.nxe) l1 = nxx+1 - if(ny.eq.nye) l2 = nxx - if(l1.gt.l2) go to 810 - do 380 i=l1,l2 - if(fpmax.ge.fpint(i)) go to 380 - l = i - fpmax = fpint(i) - 380 continue -c test whether we cannot further increase the number of knots. - if(l.eq.0) go to 785 -c calculate the position of the new knot. - arg = coord(l)/fpint(l) -c test in what direction the new knot is going to be added. - if(l.gt.nxx) go to 400 -c addition in the x-direction. - jxy = l+kx1 - fpint(l) = 0. - fac1 = tx(jxy)-arg - fac2 = arg-tx(jxy-1) - if(fac1.gt.(ten*fac2) .or. fac2.gt.(ten*fac1)) go to 370 - j = nx - do 390 i=jxy,nx - tx(j+1) = tx(j) - j = j-1 - 390 continue - tx(jxy) = arg - nx = nx+1 - go to 420 -c addition in the y-direction. - 400 jxy = l+ky1-nxx - fpint(l) = 0. - fac1 = ty(jxy)-arg - fac2 = arg-ty(jxy-1) - if(fac1.gt.(ten*fac2) .or. fac2.gt.(ten*fac1)) go to 370 - j = ny - do 410 i=jxy,ny - ty(j+1) = ty(j) - j = j-1 - 410 continue - ty(jxy) = arg - ny = ny+1 -c restart the computations with the new set of knots. - 420 continue -c test whether the least-squares polynomial is a solution of our -c approximation problem. - 430 if(ier.eq.(-2)) go to 830 -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c part 2: determination of the smoothing spline sp(x,y) c -c ***************************************************** c -c we have determined the number of knots and their position. we now c -c compute the b-spline coefficients of the smoothing spline sp(x,y). c -c the observation matrix a is extended by the rows of a matrix, c -c expressing that sp(x,y) must be a polynomial of degree kx in x and c -c ky in y. the corresponding weights of these additional rows are set c -c to 1./p. iteratively we than have to determine the value of p c -c such that f(p)=sum((w(i)*(z(i)-sp(x(i),y(i))))**2) be = s. c -c we already know that the least-squares polynomial corresponds to c -c p=0 and that the least-squares spline corresponds to p=infinity. c -c the iteration process which is proposed here makes use of rational c -c interpolation. since f(p) is a convex and strictly decreasing c -c function of p, it can be approximated by a rational function r(p)= c -c (u*p+v)/(p+w). three values of p(p1,p2,p3) with corresponding values c -c of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used to calculate the c -c new value of p such that r(p)=s. convergence is guaranteed by taking c -c f1 > 0 and f3 < 0. c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - kx2 = kx1+1 -c test whether there are interior knots in the x-direction. - if(nk1x.eq.kx1) go to 440 -c evaluate the discotinuity jumps of the kx-th order derivative of -c the b-splines at the knots tx(l),l=kx+2,...,nx-kx-1. - call fpdisc(tx,nx,kx2,bx,nmax) - 440 ky2 = ky1 + 1 -c test whether there are interior knots in the y-direction. - if(nk1y.eq.ky1) go to 450 -c evaluate the discontinuity jumps of the ky-th order derivative of -c the b-splines at the knots ty(l),l=ky+2,...,ny-ky-1. - call fpdisc(ty,ny,ky2,by,nmax) -c initial value for p. - 450 p1 = 0. - f1 = fp0-s - p3 = -one - f3 = fpms - p = 0. - do 460 i=1,ncof - p = p+a(i,1) - 460 continue - rn = ncof - p = rn/p -c find the bandwidth of the extended observation matrix. - iband3 = kx1*nk1y - iband4 = iband3 +1 - ich1 = 0 - ich3 = 0 -c iteration process to find the root of f(p)=s. - do 770 iter=1,maxit - pinv = one/p -c store the triangularized observation matrix into q. - do 480 i=1,ncof - ff(i) = f(i) - do 470 j=1,iband - q(i,j) = a(i,j) - 470 continue - ibb = iband+1 - do 480 j=ibb,iband4 - q(i,j) = 0. - 480 continue - if(nk1y.eq.ky1) go to 560 -c extend the observation matrix with the rows of a matrix, expressing -c that for x=cst. sp(x,y) must be a polynomial in y of degree ky. - do 550 i=ky2,nk1y - ii = i-ky1 - do 550 j=1,nk1x -c initialize the new row. - do 490 l=1,iband - h(l) = 0. - 490 continue -c fill in the non-zero elements of the row. jrot records the column -c number of the first non-zero element in the row. - do 500 l=1,ky2 - h(l) = by(ii,l)*pinv - 500 continue - zi = 0. - jrot = (j-1)*nk1y+ii -c rotate the new row into triangle by givens transformations without -c square roots. - do 540 irot=jrot,ncof - piv = h(1) - i2 = min0(iband1,ncof-irot) - if(piv.eq.0.) then - if (i2.le.0) go to 550 - go to 520 - endif -c calculate the parameters of the givens transformation. - call fpgivs(piv,q(irot,1),cos,sin) -c apply that givens transformation to the right hand side. - call fprota(cos,sin,zi,ff(irot)) - if(i2.eq.0) go to 550 -c apply that givens transformation to the left hand side. - do 510 l=1,i2 - l1 = l+1 - call fprota(cos,sin,h(l1),q(irot,l1)) - 510 continue - 520 do 530 l=1,i2 - h(l) = h(l+1) - 530 continue - h(i2+1) = 0. - 540 continue - 550 continue - 560 if(nk1x.eq.kx1) go to 640 -c extend the observation matrix with the rows of a matrix expressing -c that for y=cst. sp(x,y) must be a polynomial in x of degree kx. - do 630 i=kx2,nk1x - ii = i-kx1 - do 630 j=1,nk1y -c initialize the new row - do 570 l=1,iband4 - h(l) = 0. - 570 continue -c fill in the non-zero elements of the row. jrot records the column -c number of the first non-zero element in the row. - j1 = 1 - do 580 l=1,kx2 - h(j1) = bx(ii,l)*pinv - j1 = j1+nk1y - 580 continue - zi = 0. - jrot = (i-kx2)*nk1y+j -c rotate the new row into triangle by givens transformations . - do 620 irot=jrot,ncof - piv = h(1) - i2 = min0(iband3,ncof-irot) - if(piv.eq.0.) then - if (i2.le.0) go to 630 - go to 600 - endif -c calculate the parameters of the givens transformation. - call fpgivs(piv,q(irot,1),cos,sin) -c apply that givens transformation to the right hand side. - call fprota(cos,sin,zi,ff(irot)) - if(i2.eq.0) go to 630 -c apply that givens transformation to the left hand side. - do 590 l=1,i2 - l1 = l+1 - call fprota(cos,sin,h(l1),q(irot,l1)) - 590 continue - 600 do 610 l=1,i2 - h(l) = h(l+1) - 610 continue - h(i2+1) = 0. - 620 continue - 630 continue -c find dmax, the maximum value for the diagonal elements in the -c reduced triangle. - 640 dmax = 0. - do 650 i=1,ncof - if(q(i,1).le.dmax) go to 650 - dmax = q(i,1) - 650 continue -c check whether the matrix is rank deficient. - sigma = eps*dmax - do 660 i=1,ncof - if(q(i,1).le.sigma) go to 670 - 660 continue -c backward substitution in case of full rank. - call fpback(q,ff,ncof,iband4,c,nc) - rank = ncof - go to 675 -c in case of rank deficiency, find the minimum norm solution. - 670 lwest = ncof*iband4+ncof+iband4 - if(lwrk.lt.lwest) go to 780 - lf = 1 - lh = lf+ncof - la = lh+iband4 - call fprank(q,ff,ncof,iband4,nc,sigma,c,sq,rank,wrk(la), - * wrk(lf),wrk(lh)) - 675 do 680 i=1,ncof - q(i,1) = q(i,1)/dmax - 680 continue -c compute f(p). - fp = 0. - do 720 num = 1,nreg - num1 = num-1 - lx = num1/nyy - ly = num1-lx*nyy - jrot = lx*nk1y+ly - in = index(num) - 690 if(in.eq.0) go to 720 - store = 0. - i1 = jrot - do 710 i=1,kx1 - hxi = spx(in,i) - j1 = i1 - do 700 j=1,ky1 - j1 = j1+1 - store = store+hxi*spy(in,j)*c(j1) - 700 continue - i1 = i1+nk1y - 710 continue - fp = fp+(w(in)*(z(in)-store))**2 - in = nummer(in) - go to 690 - 720 continue -c test whether the approximation sp(x,y) is an acceptable solution. - fpms = fp-s - if(abs(fpms).le.acc) go to 820 -c test whether the maximum allowable number of iterations has been -c reached. - if(iter.eq.maxit) go to 795 -c carry out one more step of the iteration process. - p2 = p - f2 = fpms - if(ich3.ne.0) go to 740 - if((f2-f3).gt.acc) go to 730 -c our initial choice of p is too large. - p3 = p2 - f3 = f2 - p = p*con4 - if(p.le.p1) p = p1*con9 + p2*con1 - go to 770 - 730 if(f2.lt.0.) ich3 = 1 - 740 if(ich1.ne.0) go to 760 - if((f1-f2).gt.acc) go to 750 -c our initial choice of p is too small - p1 = p2 - f1 = f2 - p = p/con4 - if(p3.lt.0.) go to 770 - if(p.ge.p3) p = p2*con1 + p3*con9 - go to 770 - 750 if(f2.gt.0.) ich1 = 1 -c test whether the iteration process proceeds as theoretically -c expected. - 760 if(f2.ge.f1 .or. f2.le.f3) go to 800 -c find the new value of p. - p = fprati(p1,f1,p2,f2,p3,f3) - 770 continue -c error codes and messages. - 780 ier = lwest - go to 830 - 785 ier = 5 - go to 830 - 790 ier = 4 - go to 830 - 795 ier = 3 - go to 830 - 800 ier = 2 - go to 830 - 810 ier = 1 - go to 830 - 815 ier = -1 - fp = 0. - 820 if(ncof.ne.rank) ier = -rank -c test whether x and y are in the original order. - 830 if(ichang.lt.0) go to 930 -c if not, interchange x and y once more. - l1 = 1 - do 840 i=1,nk1x - l2 = i - do 840 j=1,nk1y - f(l2) = c(l1) - l1 = l1+1 - l2 = l2+nk1x - 840 continue - do 850 i=1,ncof - c(i) = f(i) - 850 continue - do 860 i=1,m - store = x(i) - x(i) = y(i) - y(i) = store - 860 continue - n = min0(nx,ny) - do 870 i=1,n - store = tx(i) - tx(i) = ty(i) - ty(i) = store - 870 continue - n1 = n+1 - if (nx.lt.ny) go to 880 - if (nx.eq.ny) go to 920 - go to 900 - 880 do 890 i=n1,ny - tx(i) = ty(i) - 890 continue - go to 920 - 900 do 910 i=n1,nx - ty(i) = tx(i) - 910 continue - 920 l = nx - nx = ny - ny = l - 930 if(iopt.lt.0) go to 940 - nx0 = nx - ny0 = ny - 940 return - end - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fpsysy.f =================================================================== --- branches/Interpolate1D/fitpack/fpsysy.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fpsysy.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,56 +0,0 @@ - subroutine fpsysy(a,n,g) -c subroutine fpsysy solves a linear n x n symmetric system -c (a) * (b) = (g) -c on input, vector g contains the right hand side ; on output it will -c contain the solution (b). -c .. -c ..scalar arguments.. - integer n -c ..array arguments.. - real*8 a(6,6),g(6) -c ..local scalars.. - real*8 fac - integer i,i1,j,k -c .. - g(1) = g(1)/a(1,1) - if(n.eq.1) return -c decomposition of the symmetric matrix (a) = (l) * (d) *(l)' -c with (l) a unit lower triangular matrix and (d) a diagonal -c matrix - do 10 k=2,n - a(k,1) = a(k,1)/a(1,1) - 10 continue - do 40 i=2,n - i1 = i-1 - do 30 k=i,n - fac = a(k,i) - do 20 j=1,i1 - fac = fac-a(j,j)*a(k,j)*a(i,j) - 20 continue - a(k,i) = fac - if(k.gt.i) a(k,i) = fac/a(i,i) - 30 continue - 40 continue -c solve the system (l)*(d)*(l)'*(b) = (g). -c first step : solve (l)*(d)*(c) = (g). - do 60 i=2,n - i1 = i-1 - fac = g(i) - do 50 j=1,i1 - fac = fac-g(j)*a(j,j)*a(i,j) - 50 continue - g(i) = fac/a(i,i) - 60 continue -c second step : solve (l)'*(b) = (c) - i = n - do 80 j=2,n - i1 = i - i = i-1 - fac = g(i) - do 70 k=i1,n - fac = fac-g(k)*a(k,i) - 70 continue - g(i) = fac - 80 continue - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fptrnp.f =================================================================== --- branches/Interpolate1D/fitpack/fptrnp.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fptrnp.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,106 +0,0 @@ - subroutine fptrnp(m,mm,idim,n,nr,sp,p,b,z,a,q,right) -c subroutine fptrnp reduces the (m+n-7) x (n-4) matrix a to upper -c triangular form and applies the same givens transformations to -c the (m) x (mm) x (idim) matrix z to obtain the (n-4) x (mm) x -c (idim) matrix q -c .. -c ..scalar arguments.. - real*8 p - integer m,mm,idim,n -c ..array arguments.. - real*8 sp(m,4),b(n,5),z(m*mm*idim),a(n,5),q((n-4)*mm*idim), - * right(mm*idim) - integer nr(m) -c ..local scalars.. - real*8 cos,pinv,piv,sin,one - integer i,iband,irot,it,ii,i2,i3,j,jj,l,mid,nmd,m2,m3, - * nrold,n4,number,n1 -c ..local arrays.. - real*8 h(7) -c ..subroutine references.. -c fpgivs,fprota -c .. - one = 1 - if(p.gt.0.) pinv = one/p - n4 = n-4 - mid = mm*idim - m2 = m*mm - m3 = n4*mm -c reduce the matrix (a) to upper triangular form (r) using givens -c rotations. apply the same transformations to the rows of matrix z -c to obtain the mm x (n-4) matrix g. -c store matrix (r) into (a) and g into q. -c initialization. - nmd = n4*mid - do 50 i=1,nmd - q(i) = 0. - 50 continue - do 100 i=1,n4 - do 100 j=1,5 - a(i,j) = 0. - 100 continue - nrold = 0 -c iband denotes the bandwidth of the matrices (a) and (r). - iband = 4 - do 750 it=1,m - number = nr(it) - 150 if(nrold.eq.number) go to 300 - if(p.le.0.) go to 700 - iband = 5 -c fetch a new row of matrix (b). - n1 = nrold+1 - do 200 j=1,5 - h(j) = b(n1,j)*pinv - 200 continue -c find the appropriate column of q. - do 250 j=1,mid - right(j) = 0. - 250 continue - irot = nrold - go to 450 -c fetch a new row of matrix (sp). - 300 h(iband) = 0. - do 350 j=1,4 - h(j) = sp(it,j) - 350 continue -c find the appropriate column of q. - j = 0 - do 400 ii=1,idim - l = (ii-1)*m2+(it-1)*mm - do 400 jj=1,mm - j = j+1 - l = l+1 - right(j) = z(l) - 400 continue - irot = number -c rotate the new row of matrix (a) into triangle. - 450 do 600 i=1,iband - irot = irot+1 - piv = h(i) - if(piv.eq.0.) go to 600 -c calculate the parameters of the givens transformation. - call fpgivs(piv,a(irot,1),cos,sin) -c apply that transformation to the rows of matrix q. - j = 0 - do 500 ii=1,idim - l = (ii-1)*m3+irot - do 500 jj=1,mm - j = j+1 - call fprota(cos,sin,right(j),q(l)) - l = l+n4 - 500 continue -c apply that transformation to the columns of (a). - if(i.eq.iband) go to 650 - i2 = 1 - i3 = i+1 - do 550 j=i3,iband - i2 = i2+1 - call fprota(cos,sin,h(j),a(irot,i2)) - 550 continue - 600 continue - 650 if(nrold.eq.number) go to 750 - 700 nrold = nrold+1 - go to 150 - 750 continue - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/fptrpe.f =================================================================== --- branches/Interpolate1D/fitpack/fptrpe.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/fptrpe.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,212 +0,0 @@ - subroutine fptrpe(m,mm,idim,n,nr,sp,p,b,z,a,aa,q,right) -c subroutine fptrpe reduces the (m+n-7) x (n-7) cyclic bandmatrix a -c to upper triangular form and applies the same givens transformations -c to the (m) x (mm) x (idim) matrix z to obtain the (n-7) x (mm) x -c (idim) matrix q. -c .. -c ..scalar arguments.. - real*8 p - integer m,mm,idim,n -c ..array arguments.. - real*8 sp(m,4),b(n,5),z(m*mm*idim),a(n,5),aa(n,4),q((n-7)*mm*idim) - *, - * right(mm*idim) - integer nr(m) -c ..local scalars.. - real*8 co,pinv,piv,si,one - integer i,iband,irot,it,ii,i2,i3,j,jj,l,mid,nmd,m2,m3, - * nrold,n4,number,n1,n7,n11,m1 -c ..local arrays.. - real*8 h(5),h1(5),h2(4) -c ..subroutine references.. -c fpgivs,fprota -c .. - one = 1 - if(p.gt.0.) pinv = one/p - n4 = n-4 - n7 = n-7 - n11 = n-11 - mid = mm*idim - m2 = m*mm - m3 = n7*mm - m1 = m-1 -c we determine the matrix (a) and then we reduce her to -c upper triangular form (r) using givens rotations. -c we apply the same transformations to the rows of matrix -c z to obtain the (mm) x (n-7) matrix g. -c we store matrix (r) into a and aa, g into q. -c the n7 x n7 upper triangular matrix (r) has the form -c | a1 ' | -c (r) = | ' a2 | -c | 0 ' | -c with (a2) a n7 x 4 matrix and (a1) a n11 x n11 upper -c triangular matrix of bandwidth 5. -c initialization. - nmd = n7*mid - do 50 i=1,nmd - q(i) = 0. - 50 continue - do 100 i=1,n4 - a(i,5) = 0. - do 100 j=1,4 - a(i,j) = 0. - aa(i,j) = 0. - 100 continue - jper = 0 - nrold = 0 - do 760 it=1,m1 - number = nr(it) - 120 if(nrold.eq.number) go to 180 - if(p.le.0.) go to 740 -c fetch a new row of matrix (b). - n1 = nrold+1 - do 140 j=1,5 - h(j) = b(n1,j)*pinv - 140 continue -c find the appropiate row of q. - do 160 j=1,mid - right(j) = 0. - 160 continue - go to 240 -c fetch a new row of matrix (sp) - 180 h(5) = 0. - do 200 j=1,4 - h(j) = sp(it,j) - 200 continue -c find the appropiate row of q. - j = 0 - do 220 ii=1,idim - l = (ii-1)*m2+(it-1)*mm - do 220 jj=1,mm - j = j+1 - l = l+1 - right(j) = z(l) - 220 continue -c test whether there are non-zero values in the new row of (a) -c corresponding to the b-splines n(j,*),j=n7+1,...,n4. - 240 if(nrold.lt.n11) go to 640 - if(jper.ne.0) go to 320 -c initialize the matrix (aa). - jk = n11+1 - do 300 i=1,4 - ik = jk - do 260 j=1,5 - if(ik.le.0) go to 280 - aa(ik,i) = a(ik,j) - ik = ik-1 - 260 continue - 280 jk = jk+1 - 300 continue - jper = 1 -c if one of the non-zero elements of the new row corresponds to one of -c the b-splines n(j;*),j=n7+1,...,n4,we take account of the periodicity -c conditions for setting up this row of (a). - 320 do 340 i=1,4 - h1(i) = 0. - h2(i) = 0. - 340 continue - h1(5) = 0. - j = nrold-n11 - do 420 i=1,5 - j = j+1 - l0 = j - 360 l1 = l0-4 - if(l1.le.0) go to 400 - if(l1.le.n11) go to 380 - l0 = l1-n11 - go to 360 - 380 h1(l1) = h(i) - go to 420 - 400 h2(l0) = h2(l0) + h(i) - 420 continue -c rotate the new row of (a) into triangle. - if(n11.le.0) go to 560 -c rotations with the rows 1,2,...,n11 of (a). - do 540 irot=1,n11 - piv = h1(1) - i2 = min0(n11-irot,4) - if(piv.eq.0.) go to 500 -c calculate the parameters of the givens transformation. - call fpgivs(piv,a(irot,1),co,si) -c apply that transformation to the columns of matrix q. - j = 0 - do 440 ii=1,idim - l = (ii-1)*m3+irot - do 440 jj=1,mm - j = j+1 - call fprota(co,si,right(j),q(l)) - l = l+n7 - 440 continue -c apply that transformation to the rows of (a) with respect to aa. - do 460 i=1,4 - call fprota(co,si,h2(i),aa(irot,i)) - 460 continue -c apply that transformation to the rows of (a) with respect to a. - if(i2.eq.0) go to 560 - do 480 i=1,i2 - i1 = i+1 - call fprota(co,si,h1(i1),a(irot,i1)) - 480 continue - 500 do 520 i=1,i2 - h1(i) = h1(i+1) - 520 continue - h1(i2+1) = 0. - 540 continue -c rotations with the rows n11+1,...,n7 of a. - 560 do 620 irot=1,4 - ij = n11+irot - if(ij.le.0) go to 620 - piv = h2(irot) - if(piv.eq.0.) go to 620 -c calculate the parameters of the givens transformation. - call fpgivs(piv,aa(ij,irot),co,si) -c apply that transformation to the columns of matrix q. - j = 0 - do 580 ii=1,idim - l = (ii-1)*m3+ij - do 580 jj=1,mm - j = j+1 - call fprota(co,si,right(j),q(l)) - l = l+n7 - 580 continue - if(irot.eq.4) go to 620 -c apply that transformation to the rows of (a) with respect to aa. - j1 = irot+1 - do 600 i=j1,4 - call fprota(co,si,h2(i),aa(ij,i)) - 600 continue - 620 continue - go to 720 -c rotation into triangle of the new row of (a), in case the elements -c corresponding to the b-splines n(j;*),j=n7+1,...,n4 are all zero. - 640 irot =nrold - do 700 i=1,5 - irot = irot+1 - piv = h(i) - if(piv.eq.0.) go to 700 -c calculate the parameters of the givens transformation. - call fpgivs(piv,a(irot,1),co,si) -c apply that transformation to the columns of matrix g. - j = 0 - do 660 ii=1,idim - l = (ii-1)*m3+irot - do 660 jj=1,mm - j = j+1 - call fprota(co,si,right(j),q(l)) - l = l+n7 - 660 continue -c apply that transformation to the rows of (a). - if(i.eq.5) go to 700 - i2 = 1 - i3 = i+1 - do 680 j=i3,5 - i2 = i2+1 - call fprota(co,si,h(j),a(irot,i2)) - 680 continue - 700 continue - 720 if(nrold.eq.number) go to 760 - 740 nrold = nrold+1 - go to 120 - 760 continue - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/insert.f =================================================================== --- branches/Interpolate1D/fitpack/insert.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/insert.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,102 +0,0 @@ - subroutine insert(iopt,t,n,c,k,x,tt,nn,cc,nest,ier) -c subroutine insert inserts a new knot x into a spline function s(x) -c of degree k and calculates the b-spline representation of s(x) with -c respect to the new set of knots. in addition, if iopt.ne.0, s(x) -c will be considered as a periodic spline with period per=t(n-k)-t(k+1) -c satisfying the boundary constraints -c t(i+n-2*k-1) = t(i)+per ,i=1,2,...,2*k+1 -c c(i+n-2*k-1) = c(i) ,i=1,2,...,k -c in that case, the knots and b-spline coefficients returned will also -c satisfy these boundary constraints, i.e. -c tt(i+nn-2*k-1) = tt(i)+per ,i=1,2,...,2*k+1 -c cc(i+nn-2*k-1) = cc(i) ,i=1,2,...,k -c -c calling sequence: -c call insert(iopt,t,n,c,k,x,tt,nn,cc,nest,ier) -c -c input parameters: -c iopt : integer flag, specifying whether (iopt.ne.0) or not (iopt=0) -c the given spline must be considered as being periodic. -c t : array,length nest, which contains the position of the knots. -c n : integer, giving the total number of knots of s(x). -c c : array,length nest, which contains the b-spline coefficients. -c k : integer, giving the degree of s(x). -c x : real, which gives the location of the knot to be inserted. -c nest : integer specifying the dimension of the arrays t,c,tt and cc -c nest > n. -c -c output parameters: -c tt : array,length nest, which contains the position of the knots -c after insertion. -c nn : integer, giving the total number of knots after insertion -c cc : array,length nest, which contains the b-spline coefficients -c of s(x) with respect to the new set of knots. -c ier : error flag -c ier = 0 : normal return -c ier =10 : invalid input data (see restrictions) -c -c restrictions: -c nest > n -c t(k+1) <= x <= t(n-k) -c in case of a periodic spline (iopt.ne.0) there must be -c either at least k interior knots t(j) satisfying t(k+1)=0 the number of knots of the splines sj(u) and the position -c t(j),j=1,2,...,n is chosen automatically by the routine. the smooth- -c ness of s(u) is then achieved by minimalizing the discontinuity -c jumps of the k-th derivative of s(u) at the knots t(j),j=k+2,k+3,..., -c n-k-1. the amount of smoothness is determined by the condition that -c f(p)=sum((w(i)*dist(x(i),s(u(i))))**2) be <= s, with s a given non- -c negative constant, called the smoothing factor. -c the fit s(u) is given in the b-spline representation and can be -c evaluated by means of subroutine curev. -c -c calling sequence: -c call parcur(iopt,ipar,idim,m,u,mx,x,w,ub,ue,k,s,nest,n,t,nc,c, -c * fp,wrk,lwrk,iwrk,ier) -c -c parameters: -c iopt : integer flag. on entry iopt must specify whether a weighted -c least-squares spline curve (iopt=-1) or a smoothing spline -c curve (iopt=0 or 1) must be determined.if iopt=0 the routine -c will start with an initial set of knots t(i)=ub,t(i+k+1)=ue, -c i=1,2,...,k+1. if iopt=1 the routine will continue with the -c knots found at the last call of the routine. -c attention: a call with iopt=1 must always be immediately -c preceded by another call with iopt=1 or iopt=0. -c unchanged on exit. -c ipar : integer flag. on entry ipar must specify whether (ipar=1) -c the user will supply the parameter values u(i),ub and ue -c or whether (ipar=0) these values are to be calculated by -c parcur. unchanged on exit. -c idim : integer. on entry idim must specify the dimension of the -c curve. 0 < idim < 11. -c unchanged on exit. -c m : integer. on entry m must specify the number of data points. -c m > k. unchanged on exit. -c u : real array of dimension at least (m). in case ipar=1,before -c entry, u(i) must be set to the i-th value of the parameter -c variable u for i=1,2,...,m. these values must then be -c supplied in strictly ascending order and will be unchanged -c on exit. in case ipar=0, on exit,array u will contain the -c values u(i) as determined by parcur. -c mx : integer. on entry mx must specify the actual dimension of -c the array x as declared in the calling (sub)program. mx must -c not be too small (see x). unchanged on exit. -c x : real array of dimension at least idim*m. -c before entry, x(idim*(i-1)+j) must contain the j-th coord- -c inate of the i-th data point for i=1,2,...,m and j=1,2,..., -c idim. unchanged on exit. -c w : real array of dimension at least (m). before entry, w(i) -c must be set to the i-th value in the set of weights. the -c w(i) must be strictly positive. unchanged on exit. -c see also further comments. -c ub,ue : real values. on entry (in case ipar=1) ub and ue must -c contain the lower and upper bound for the parameter u. -c ub <=u(1), ue>= u(m). if ipar = 0 these values will -c automatically be set to 0 and 1 by parcur. -c k : integer. on entry k must specify the degree of the splines. -c 1<=k<=5. it is recommended to use cubic splines (k=3). -c the user is strongly dissuaded from choosing k even,together -c with a small s-value. unchanged on exit. -c s : real.on entry (in case iopt>=0) s must specify the smoothing -c factor. s >=0. unchanged on exit. -c for advice on the choice of s see further comments. -c nest : integer. on entry nest must contain an over-estimate of the -c total number of knots of the splines returned, to indicate -c the storage space available to the routine. nest >=2*k+2. -c in most practical situation nest=m/2 will be sufficient. -c always large enough is nest=m+k+1, the number of knots -c needed for interpolation (s=0). unchanged on exit. -c n : integer. -c unless ier = 10 (in case iopt >=0), n will contain the -c total number of knots of the smoothing spline curve returned -c if the computation mode iopt=1 is used this value of n -c should be left unchanged between subsequent calls. -c in case iopt=-1, the value of n must be specified on entry. -c t : real array of dimension at least (nest). -c on succesful exit, this array will contain the knots of the -c spline curve,i.e. the position of the interior knots t(k+2), -c t(k+3),..,t(n-k-1) as well as the position of the additional -c t(1)=t(2)=...=t(k+1)=ub and t(n-k)=...=t(n)=ue needed for -c the b-spline representation. -c if the computation mode iopt=1 is used, the values of t(1), -c t(2),...,t(n) should be left unchanged between subsequent -c calls. if the computation mode iopt=-1 is used, the values -c t(k+2),...,t(n-k-1) must be supplied by the user, before -c entry. see also the restrictions (ier=10). -c nc : integer. on entry nc must specify the actual dimension of -c the array c as declared in the calling (sub)program. nc -c must not be too small (see c). unchanged on exit. -c c : real array of dimension at least (nest*idim). -c on succesful exit, this array will contain the coefficients -c in the b-spline representation of the spline curve s(u),i.e. -c the b-spline coefficients of the spline sj(u) will be given -c in c(n*(j-1)+i),i=1,2,...,n-k-1 for j=1,2,...,idim. -c fp : real. unless ier = 10, fp contains the weighted sum of -c squared residuals of the spline curve returned. -c wrk : real array of dimension at least m*(k+1)+nest*(6+idim+3*k). -c used as working space. if the computation mode iopt=1 is -c used, the values wrk(1),...,wrk(n) should be left unchanged -c between subsequent calls. -c lwrk : integer. on entry,lwrk must specify the actual dimension of -c the array wrk as declared in the calling (sub)program. lwrk -c must not be too small (see wrk). unchanged on exit. -c iwrk : integer array of dimension at least (nest). -c used as working space. if the computation mode iopt=1 is -c used,the values iwrk(1),...,iwrk(n) should be left unchanged -c between subsequent calls. -c ier : integer. unless the routine detects an error, ier contains a -c non-positive value on exit, i.e. -c ier=0 : normal return. the curve returned has a residual sum of -c squares fp such that abs(fp-s)/s <= tol with tol a relat- -c ive tolerance set to 0.001 by the program. -c ier=-1 : normal return. the curve returned is an interpolating -c spline curve (fp=0). -c ier=-2 : normal return. the curve returned is the weighted least- -c squares polynomial curve of degree k.in this extreme case -c fp gives the upper bound fp0 for the smoothing factor s. -c ier=1 : error. the required storage space exceeds the available -c storage space, as specified by the parameter nest. -c probably causes : nest too small. if nest is already -c large (say nest > m/2), it may also indicate that s is -c too small -c the approximation returned is the least-squares spline -c curve according to the knots t(1),t(2),...,t(n). (n=nest) -c the parameter fp gives the corresponding weighted sum of -c squared residuals (fp>s). -c ier=2 : error. a theoretically impossible result was found during -c the iteration proces for finding a smoothing spline curve -c with fp = s. probably causes : s too small. -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=3 : error. the maximal number of iterations maxit (set to 20 -c by the program) allowed for finding a smoothing curve -c with fp=s has been reached. probably causes : s too small -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=10 : error. on entry, the input data are controlled on validity -c the following restrictions must be satisfied. -c -1<=iopt<=1, 1<=k<=5, m>k, nest>2*k+2, w(i)>0,i=1,2,...,m -c 0<=ipar<=1, 0=(k+1)*m+nest*(6+idim+3*k), -c nc>=nest*idim -c if ipar=0: sum j=1,idim (x(idim*i+j)-x(idim*(i-1)+j))**2>0 -c i=1,2,...,m-1. -c if ipar=1: ub<=u(1)=0: s>=0 -c if s=0 : nest >= m+k+1 -c if one of these conditions is found to be violated,control -c is immediately repassed to the calling program. in that -c case there is no approximation returned. -c -c further comments: -c by means of the parameter s, the user can control the tradeoff -c between closeness of fit and smoothness of fit of the approximation. -c if s is too large, the curve will be too smooth and signal will be -c lost ; if s is too small the curve will pick up too much noise. in -c the extreme cases the program will return an interpolating curve if -c s=0 and the least-squares polynomial curve of degree k if s is -c very large. between these extremes, a properly chosen s will result -c in a good compromise between closeness of fit and smoothness of fit. -c to decide whether an approximation, corresponding to a certain s is -c satisfactory the user is highly recommended to inspect the fits -c graphically. -c recommended values for s depend on the weights w(i). if these are -c taken as 1/d(i) with d(i) an estimate of the standard deviation of -c x(i), a good s-value should be found in the range (m-sqrt(2*m),m+ -c sqrt(2*m)). if nothing is known about the statistical error in x(i) -c each w(i) can be set equal to one and s determined by trial and -c error, taking account of the comments above. the best is then to -c start with a very large value of s ( to determine the least-squares -c polynomial curve and the upper bound fp0 for s) and then to -c progressively decrease the value of s ( say by a factor 10 in the -c beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the -c approximating curve shows more detail) to obtain closer fits. -c to economize the search for a good s-value the program provides with -c different modes of computation. at the first call of the routine, or -c whenever he wants to restart with the initial set of knots the user -c must set iopt=0. -c if iopt=1 the program will continue with the set of knots found at -c the last call of the routine. this will save a lot of computation -c time if parcur is called repeatedly for different values of s. -c the number of knots of the spline returned and their location will -c depend on the value of s and on the complexity of the shape of the -c curve underlying the data. but, if the computation mode iopt=1 is -c used, the knots returned may also depend on the s-values at previous -c calls (if these were smaller). therefore, if after a number of -c trials with different s-values and iopt=1, the user can finally -c accept a fit as satisfactory, it may be worthwhile for him to call -c parcur once more with the selected value for s but now with iopt=0. -c indeed, parcur may then return an approximation of the same quality -c of fit but with fewer knots and therefore better if data reduction -c is also an important objective for the user. -c -c the form of the approximating curve can strongly be affected by -c the choice of the parameter values u(i). if there is no physical -c reason for choosing a particular parameter u, often good results -c will be obtained with the choice of parcur (in case ipar=0), i.e. -c v(1)=0, v(i)=v(i-1)+q(i), i=2,...,m, u(i)=v(i)/v(m), i=1,..,m -c where -c q(i)= sqrt(sum j=1,idim (xj(i)-xj(i-1))**2 ) -c other possibilities for q(i) are -c q(i)= sum j=1,idim (xj(i)-xj(i-1))**2 -c q(i)= sum j=1,idim abs(xj(i)-xj(i-1)) -c q(i)= max j=1,idim abs(xj(i)-xj(i-1)) -c q(i)= 1 -c -c other subroutines required: -c fpback,fpbspl,fpchec,fppara,fpdisc,fpgivs,fpknot,fprati,fprota -c -c references: -c dierckx p. : algorithms for smoothing data with periodic and -c parametric splines, computer graphics and image -c processing 20 (1982) 171-184. -c dierckx p. : algorithms for smoothing data with periodic and param- -c etric splines, report tw55, dept. computer science, -c k.u.leuven, 1981. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author: -c p.dierckx -c dept. computer science, k.u. leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c creation date : may 1979 -c latest update : march 1987 -c -c .. -c ..scalar arguments.. - real*8 ub,ue,s,fp - integer iopt,ipar,idim,m,mx,k,nest,n,nc,lwrk,ier -c ..array arguments.. - real*8 u(m),x(mx),w(m),t(nest),c(nc),wrk(lwrk) - integer iwrk(nest) -c ..local scalars.. - real*8 tol,dist - integer i,ia,ib,ifp,ig,iq,iz,i1,i2,j,k1,k2,lwest,maxit,nmin,ncc -c ..function references - real*8 sqrt -c .. -c we set up the parameters tol and maxit - maxit = 20 - tol = 0.1e-02 -c before starting computations a data check is made. if the input data -c are invalid, control is immediately repassed to the calling program. - ier = 10 - if(iopt.lt.(-1) .or. iopt.gt.1) go to 90 - if(ipar.lt.0 .or. ipar.gt.1) go to 90 - if(idim.le.0 .or. idim.gt.10) go to 90 - if(k.le.0 .or. k.gt.5) go to 90 - k1 = k+1 - k2 = k1+1 - nmin = 2*k1 - if(m.lt.k1 .or. nest.lt.nmin) go to 90 - ncc = nest*idim - if(mx.lt.m*idim .or. nc.lt.ncc) go to 90 - lwest = m*k1+nest*(6+idim+3*k) - if(lwrk.lt.lwest) go to 90 - if(ipar.ne.0 .or. iopt.gt.0) go to 40 - i1 = 0 - i2 = idim - u(1) = 0. - do 20 i=2,m - dist = 0. - do 10 j=1,idim - i1 = i1+1 - i2 = i2+1 - dist = dist+(x(i2)-x(i1))**2 - 10 continue - u(i) = u(i-1)+sqrt(dist) - 20 continue - if(u(m).le.0.) go to 90 - do 30 i=2,m - u(i) = u(i)/u(m) - 30 continue - ub = 0. - ue = 1. - u(m) = ue - 40 if(ub.gt.u(1) .or. ue.lt.u(m) .or. w(1).le.0.) go to 90 - do 50 i=2,m - if(u(i-1).ge.u(i) .or. w(i).le.0.) go to 90 - 50 continue - if(iopt.ge.0) go to 70 - if(n.lt.nmin .or. n.gt.nest) go to 90 - j = n - do 60 i=1,k1 - t(i) = ub - t(j) = ue - j = j-1 - 60 continue - call fpchec(u,m,t,n,k,ier) - if (ier.eq.0) go to 80 - go to 90 - 70 if(s.lt.0.) go to 90 - if(s.eq.0. .and. nest.lt.(m+k1)) go to 90 - ier = 0 -c we partition the working space and determine the spline curve. - 80 ifp = 1 - iz = ifp+nest - ia = iz+ncc - ib = ia+nest*k1 - ig = ib+nest*k2 - iq = ig+nest*k2 - call fppara(iopt,idim,m,u,mx,x,w,ub,ue,k,s,nest,tol,maxit,k1,k2, - * n,t,ncc,c,fp,wrk(ifp),wrk(iz),wrk(ia),wrk(ib),wrk(ig),wrk(iq), - * iwrk,ier) - 90 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/parder.f =================================================================== --- branches/Interpolate1D/fitpack/parder.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/parder.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,179 +0,0 @@ - subroutine parder(tx,nx,ty,ny,c,kx,ky,nux,nuy,x,mx,y,my,z, - * wrk,lwrk,iwrk,kwrk,ier) -c subroutine parder evaluates on a grid (x(i),y(j)),i=1,...,mx; j=1,... -c ,my the partial derivative ( order nux,nuy) of a bivariate spline -c s(x,y) of degrees kx and ky, given in the b-spline representation. -c -c calling sequence: -c call parder(tx,nx,ty,ny,c,kx,ky,nux,nuy,x,mx,y,my,z,wrk,lwrk, -c * iwrk,kwrk,ier) -c -c input parameters: -c tx : real array, length nx, which contains the position of the -c knots in the x-direction. -c nx : integer, giving the total number of knots in the x-direction -c ty : real array, length ny, which contains the position of the -c knots in the y-direction. -c ny : integer, giving the total number of knots in the y-direction -c c : real array, length (nx-kx-1)*(ny-ky-1), which contains the -c b-spline coefficients. -c kx,ky : integer values, giving the degrees of the spline. -c nux : integer values, specifying the order of the partial -c nuy derivative. 0<=nux=1. -c y : real array of dimension (my). -c before entry y(j) must be set to the y co-ordinate of the -c j-th grid point along the y-axis. -c ty(ky+1)<=y(j-1)<=y(j)<=ty(ny-ky), j=2,...,my. -c my : on entry my must specify the number of grid points along -c the y-axis. my >=1. -c wrk : real array of dimension lwrk. used as workspace. -c lwrk : integer, specifying the dimension of wrk. -c lwrk >= mx*(kx+1-nux)+my*(ky+1-nuy)+(nx-kx-1)*(ny-ky-1) -c iwrk : integer array of dimension kwrk. used as workspace. -c kwrk : integer, specifying the dimension of iwrk. kwrk >= mx+my. -c -c output parameters: -c z : real array of dimension (mx*my). -c on succesful exit z(my*(i-1)+j) contains the value of the -c specified partial derivative of s(x,y) at the point -c (x(i),y(j)),i=1,...,mx;j=1,...,my. -c ier : integer error flag -c ier=0 : normal return -c ier=10: invalid input data (see restrictions) -c -c restrictions: -c mx >=1, my >=1, 0 <= nux < kx, 0 <= nuy < ky, kwrk>=mx+my -c lwrk>=mx*(kx+1-nux)+my*(ky+1-nuy)+(nx-kx-1)*(ny-ky-1), -c tx(kx+1) <= x(i-1) <= x(i) <= tx(nx-kx), i=2,...,mx -c ty(ky+1) <= y(j-1) <= y(j) <= ty(ny-ky), j=2,...,my -c -c other subroutines required: -c fpbisp,fpbspl -c -c references : -c de boor c : on calculating with b-splines, j. approximation theory -c 6 (1972) 50-62. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author : -c p.dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c latest update : march 1989 -c -c ..scalar arguments.. - integer nx,ny,kx,ky,nux,nuy,mx,my,lwrk,kwrk,ier -c ..array arguments.. - integer iwrk(kwrk) - real*8 tx(nx),ty(ny),c((nx-kx-1)*(ny-ky-1)),x(mx),y(my),z(mx*my), - * wrk(lwrk) -c ..local scalars.. - integer i,iwx,iwy,j,kkx,kky,kx1,ky1,lx,ly,lwest,l1,l2,m,m0,m1, - * nc,nkx1,nky1,nxx,nyy - real*8 ak,fac -c .. -c before starting computations a data check is made. if the input data -c are invalid control is immediately repassed to the calling program. - ier = 10 - kx1 = kx+1 - ky1 = ky+1 - nkx1 = nx-kx1 - nky1 = ny-ky1 - nc = nkx1*nky1 - if(nux.lt.0 .or. nux.ge.kx) go to 400 - if(nuy.lt.0 .or. nuy.ge.ky) go to 400 - lwest = nc +(kx1-nux)*mx+(ky1-nuy)*my - if(lwrk.lt.lwest) go to 400 - if(kwrk.lt.(mx+my)) go to 400 - if (mx.lt.1) go to 400 - if (mx.eq.1) go to 30 - go to 10 - 10 do 20 i=2,mx - if(x(i).lt.x(i-1)) go to 400 - 20 continue - 30 if (my.lt.1) go to 400 - if (my.eq.1) go to 60 - go to 40 - 40 do 50 i=2,my - if(y(i).lt.y(i-1)) go to 400 - 50 continue - 60 ier = 0 - nxx = nkx1 - nyy = nky1 - kkx = kx - kky = ky -c the partial derivative of order (nux,nuy) of a bivariate spline of -c degrees kx,ky is a bivariate spline of degrees kx-nux,ky-nuy. -c we calculate the b-spline coefficients of this spline - do 70 i=1,nc - wrk(i) = c(i) - 70 continue - if(nux.eq.0) go to 200 - lx = 1 - do 100 j=1,nux - ak = kkx - nxx = nxx-1 - l1 = lx - m0 = 1 - do 90 i=1,nxx - l1 = l1+1 - l2 = l1+kkx - fac = tx(l2)-tx(l1) - if(fac.le.0.) go to 90 - do 80 m=1,nyy - m1 = m0+nyy - wrk(m0) = (wrk(m1)-wrk(m0))*ak/fac - m0 = m0+1 - 80 continue - 90 continue - lx = lx+1 - kkx = kkx-1 - 100 continue - 200 if(nuy.eq.0) go to 300 - ly = 1 - do 230 j=1,nuy - ak = kky - nyy = nyy-1 - l1 = ly - do 220 i=1,nyy - l1 = l1+1 - l2 = l1+kky - fac = ty(l2)-ty(l1) - if(fac.le.0.) go to 220 - m0 = i - do 210 m=1,nxx - m1 = m0+1 - wrk(m0) = (wrk(m1)-wrk(m0))*ak/fac - m0 = m0+nky1 - 210 continue - 220 continue - ly = ly+1 - kky = kky-1 - 230 continue - m0 = nyy - m1 = nky1 - do 250 m=2,nxx - do 240 i=1,nyy - m0 = m0+1 - m1 = m1+1 - wrk(m0) = wrk(m1) - 240 continue - m1 = m1+nuy - 250 continue -c we partition the working space and evaluate the partial derivative - 300 iwx = 1+nxx*nyy - iwy = iwx+mx*(kx1-nux) - call fpbisp(tx(nux+1),nx-2*nux,ty(nuy+1),ny-2*nuy,wrk,kkx,kky, - * x,mx,y,my,z,wrk(iwx),wrk(iwy),iwrk(1),iwrk(mx+1)) - 400 return - end - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/parsur.f =================================================================== --- branches/Interpolate1D/fitpack/parsur.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/parsur.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,391 +0,0 @@ - subroutine parsur(iopt,ipar,idim,mu,u,mv,v,f,s,nuest,nvest, - * nu,tu,nv,tv,c,fp,wrk,lwrk,iwrk,kwrk,ier) -c given the set of ordered points f(i,j) in the idim-dimensional space, -c corresponding to grid values (u(i),v(j)) ,i=1,...,mu ; j=1,...,mv, -c parsur determines a smooth approximating spline surface s(u,v) , i.e. -c f1 = s1(u,v) -c ... u(1) <= u <= u(mu) ; v(1) <= v <= v(mv) -c fidim = sidim(u,v) -c with sl(u,v), l=1,2,...,idim bicubic spline functions with common -c knots tu(i),i=1,...,nu in the u-variable and tv(j),j=1,...,nv in the -c v-variable. -c in addition, these splines will be periodic in the variable u if -c ipar(1) = 1 and periodic in the variable v if ipar(2) = 1. -c if iopt=-1, parsur determines the least-squares bicubic spline -c surface according to a given set of knots. -c if iopt>=0, the number of knots of s(u,v) and their position -c is chosen automatically by the routine. the smoothness of s(u,v) is -c achieved by minimalizing the discontinuity jumps of the derivatives -c of the splines at the knots. the amount of smoothness of s(u,v) is -c determined by the condition that -c fp=sumi=1,mu(sumj=1,mv(dist(f(i,j)-s(u(i),v(j)))**2))<=s, -c with s a given non-negative constant. -c the fit s(u,v) is given in its b-spline representation and can be -c evaluated by means of routine surev. -c -c calling sequence: -c call parsur(iopt,ipar,idim,mu,u,mv,v,f,s,nuest,nvest,nu,tu, -c * nv,tv,c,fp,wrk,lwrk,iwrk,kwrk,ier) -c -c parameters: -c iopt : integer flag. unchanged on exit. -c on entry iopt must specify whether a least-squares surface -c (iopt=-1) or a smoothing surface (iopt=0 or 1)must be -c determined. -c if iopt=0 the routine will start with the initial set of -c knots needed for determining the least-squares polynomial -c surface. -c if iopt=1 the routine will continue with the set of knots -c found at the last call of the routine. -c attention: a call with iopt=1 must always be immediately -c preceded by another call with iopt = 1 or iopt = 0. -c ipar : integer array of dimension 2. unchanged on exit. -c on entry ipar(1) must specify whether (ipar(1)=1) or not -c (ipar(1)=0) the splines must be periodic in the variable u. -c on entry ipar(2) must specify whether (ipar(2)=1) or not -c (ipar(2)=0) the splines must be periodic in the variable v. -c idim : integer. on entry idim must specify the dimension of the -c surface. 1 <= idim <= 3. unchanged on exit. -c mu : integer. on entry mu must specify the number of grid points -c along the u-axis. unchanged on exit. -c mu >= mumin where mumin=4-2*ipar(1) -c u : real array of dimension at least (mu). before entry, u(i) -c must be set to the u-co-ordinate of the i-th grid point -c along the u-axis, for i=1,2,...,mu. these values must be -c supplied in strictly ascending order. unchanged on exit. -c mv : integer. on entry mv must specify the number of grid points -c along the v-axis. unchanged on exit. -c mv >= mvmin where mvmin=4-2*ipar(2) -c v : real array of dimension at least (mv). before entry, v(j) -c must be set to the v-co-ordinate of the j-th grid point -c along the v-axis, for j=1,2,...,mv. these values must be -c supplied in strictly ascending order. unchanged on exit. -c f : real array of dimension at least (mu*mv*idim). -c before entry, f(mu*mv*(l-1)+mv*(i-1)+j) must be set to the -c l-th co-ordinate of the data point corresponding to the -c the grid point (u(i),v(j)) for l=1,...,idim ,i=1,...,mu -c and j=1,...,mv. unchanged on exit. -c if ipar(1)=1 it is expected that f(mu*mv*(l-1)+mv*(mu-1)+j) -c = f(mu*mv*(l-1)+j), l=1,...,idim ; j=1,...,mv -c if ipar(2)=1 it is expected that f(mu*mv*(l-1)+mv*(i-1)+mv) -c = f(mu*mv*(l-1)+mv*(i-1)+1), l=1,...,idim ; i=1,...,mu -c s : real. on entry (if iopt>=0) s must specify the smoothing -c factor. s >=0. unchanged on exit. -c for advice on the choice of s see further comments -c nuest : integer. unchanged on exit. -c nvest : integer. unchanged on exit. -c on entry, nuest and nvest must specify an upper bound for the -c number of knots required in the u- and v-directions respect. -c these numbers will also determine the storage space needed by -c the routine. nuest >= 8, nvest >= 8. -c in most practical situation nuest = mu/2, nvest=mv/2, will -c be sufficient. always large enough are nuest=mu+4+2*ipar(1), -c nvest = mv+4+2*ipar(2), the number of knots needed for -c interpolation (s=0). see also further comments. -c nu : integer. -c unless ier=10 (in case iopt>=0), nu will contain the total -c number of knots with respect to the u-variable, of the spline -c surface returned. if the computation mode iopt=1 is used, -c the value of nu should be left unchanged between subsequent -c calls. in case iopt=-1, the value of nu should be specified -c on entry. -c tu : real array of dimension at least (nuest). -c on succesful exit, this array will contain the knots of the -c splines with respect to the u-variable, i.e. the position of -c the interior knots tu(5),...,tu(nu-4) as well as the position -c of the additional knots tu(1),...,tu(4) and tu(nu-3),..., -c tu(nu) needed for the b-spline representation. -c if the computation mode iopt=1 is used,the values of tu(1) -c ...,tu(nu) should be left unchanged between subsequent calls. -c if the computation mode iopt=-1 is used, the values tu(5), -c ...tu(nu-4) must be supplied by the user, before entry. -c see also the restrictions (ier=10). -c nv : integer. -c unless ier=10 (in case iopt>=0), nv will contain the total -c number of knots with respect to the v-variable, of the spline -c surface returned. if the computation mode iopt=1 is used, -c the value of nv should be left unchanged between subsequent -c calls. in case iopt=-1, the value of nv should be specified -c on entry. -c tv : real array of dimension at least (nvest). -c on succesful exit, this array will contain the knots of the -c splines with respect to the v-variable, i.e. the position of -c the interior knots tv(5),...,tv(nv-4) as well as the position -c of the additional knots tv(1),...,tv(4) and tv(nv-3),..., -c tv(nv) needed for the b-spline representation. -c if the computation mode iopt=1 is used,the values of tv(1) -c ...,tv(nv) should be left unchanged between subsequent calls. -c if the computation mode iopt=-1 is used, the values tv(5), -c ...tv(nv-4) must be supplied by the user, before entry. -c see also the restrictions (ier=10). -c c : real array of dimension at least (nuest-4)*(nvest-4)*idim. -c on succesful exit, c contains the coefficients of the spline -c approximation s(u,v) -c fp : real. unless ier=10, fp contains the sum of squared -c residuals of the spline surface returned. -c wrk : real array of dimension (lwrk). used as workspace. -c if the computation mode iopt=1 is used the values of -c wrk(1),...,wrk(4) should be left unchanged between subsequent -c calls. -c lwrk : integer. on entry lwrk must specify the actual dimension of -c the array wrk as declared in the calling (sub)program. -c lwrk must not be too small. -c lwrk >= 4+nuest*(mv*idim+11+4*ipar(1))+nvest*(11+4*ipar(2))+ -c 4*(mu+mv)+q*idim where q is the larger of mv and nuest. -c iwrk : integer array of dimension (kwrk). used as workspace. -c if the computation mode iopt=1 is used the values of -c iwrk(1),.,iwrk(3) should be left unchanged between subsequent -c calls. -c kwrk : integer. on entry kwrk must specify the actual dimension of -c the array iwrk as declared in the calling (sub)program. -c kwrk >= 3+mu+mv+nuest+nvest. -c ier : integer. unless the routine detects an error, ier contains a -c non-positive value on exit, i.e. -c ier=0 : normal return. the surface returned has a residual sum of -c squares fp such that abs(fp-s)/s <= tol with tol a relat- -c ive tolerance set to 0.001 by the program. -c ier=-1 : normal return. the spline surface returned is an -c interpolating surface (fp=0). -c ier=-2 : normal return. the surface returned is the least-squares -c polynomial surface. in this extreme case fp gives the -c upper bound for the smoothing factor s. -c ier=1 : error. the required storage space exceeds the available -c storage space, as specified by the parameters nuest and -c nvest. -c probably causes : nuest or nvest too small. if these param- -c eters are already large, it may also indicate that s is -c too small -c the approximation returned is the least-squares surface -c according to the current set of knots. the parameter fp -c gives the corresponding sum of squared residuals (fp>s). -c ier=2 : error. a theoretically impossible result was found during -c the iteration proces for finding a smoothing surface with -c fp = s. probably causes : s too small. -c there is an approximation returned but the corresponding -c sum of squared residuals does not satisfy the condition -c abs(fp-s)/s < tol. -c ier=3 : error. the maximal number of iterations maxit (set to 20 -c by the program) allowed for finding a smoothing surface -c with fp=s has been reached. probably causes : s too small -c there is an approximation returned but the corresponding -c sum of squared residuals does not satisfy the condition -c abs(fp-s)/s < tol. -c ier=10 : error. on entry, the input data are controlled on validity -c the following restrictions must be satisfied. -c -1<=iopt<=1, 0<=ipar(1)<=1, 0<=ipar(2)<=1, 1 <=idim<=3 -c mu >= 4-2*ipar(1),mv >= 4-2*ipar(2), nuest >=8, nvest >= 8, -c kwrk>=3+mu+mv+nuest+nvest, -c lwrk >= 4+nuest*(mv*idim+11+4*ipar(1))+nvest*(11+4*ipar(2)) -c +4*(mu+mv)+max(nuest,mv)*idim -c u(i-1)=0: s>=0 -c if s=0: nuest>=mu+4+2*ipar(1) -c nvest>=mv+4+2*ipar(2) -c if one of these conditions is found to be violated,control -c is immediately repassed to the calling program. in that -c case there is no approximation returned. -c -c further comments: -c by means of the parameter s, the user can control the tradeoff -c between closeness of fit and smoothness of fit of the approximation. -c if s is too large, the surface will be too smooth and signal will be -c lost ; if s is too small the surface will pick up too much noise. in -c the extreme cases the program will return an interpolating surface -c if s=0 and the constrained least-squares polynomial surface if s is -c very large. between these extremes, a properly chosen s will result -c in a good compromise between closeness of fit and smoothness of fit. -c to decide whether an approximation, corresponding to a certain s is -c satisfactory the user is highly recommended to inspect the fits -c graphically. -c recommended values for s depend on the accuracy of the data values. -c if the user has an idea of the statistical errors on the data, he -c can also find a proper estimate for s. for, by assuming that, if he -c specifies the right s, parsur will return a surface s(u,v) which -c exactly reproduces the surface underlying the data he can evaluate -c the sum(dist(f(i,j)-s(u(i),v(j)))**2) to find a good estimate for s. -c for example, if he knows that the statistical errors on his f(i,j)- -c values is not greater than 0.1, he may expect that a good s should -c have a value not larger than mu*mv*(0.1)**2. -c if nothing is known about the statistical error in f(i,j), s must -c be determined by trial and error, taking account of the comments -c above. the best is then to start with a very large value of s (to -c determine the le-sq polynomial surface and the corresponding upper -c bound fp0 for s) and then to progressively decrease the value of s -c ( say by a factor 10 in the beginning, i.e. s=fp0/10,fp0/100,... -c and more carefully as the approximation shows more detail) to -c obtain closer fits. -c to economize the search for a good s-value the program provides with -c different modes of computation. at the first call of the routine, or -c whenever he wants to restart with the initial set of knots the user -c must set iopt=0. -c if iopt = 1 the program will continue with the knots found at -c the last call of the routine. this will save a lot of computation -c time if parsur is called repeatedly for different values of s. -c the number of knots of the surface returned and their location will -c depend on the value of s and on the complexity of the shape of the -c surface underlying the data. if the computation mode iopt = 1 -c is used, the knots returned may also depend on the s-values at -c previous calls (if these were smaller). therefore, if after a number -c of trials with different s-values and iopt=1,the user can finally -c accept a fit as satisfactory, it may be worthwhile for him to call -c parsur once more with the chosen value for s but now with iopt=0. -c indeed, parsur may then return an approximation of the same quality -c of fit but with fewer knots and therefore better if data reduction -c is also an important objective for the user. -c the number of knots may also depend on the upper bounds nuest and -c nvest. indeed, if at a certain stage in parsur the number of knots -c in one direction (say nu) has reached the value of its upper bound -c (nuest), then from that moment on all subsequent knots are added -c in the other (v) direction. this may indicate that the value of -c nuest is too small. on the other hand, it gives the user the option -c of limiting the number of knots the routine locates in any direction -c for example, by setting nuest=8 (the lowest allowable value for -c nuest), the user can indicate that he wants an approximation with -c splines which are simple cubic polynomials in the variable u. -c -c other subroutines required: -c fppasu,fpchec,fpchep,fpknot,fprati,fpgrpa,fptrnp,fpback, -c fpbacp,fpbspl,fptrpe,fpdisc,fpgivs,fprota -c -c author: -c p.dierckx -c dept. computer science, k.u. leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c latest update : march 1989 -c -c .. -c ..scalar arguments.. - real*8 s,fp - integer iopt,idim,mu,mv,nuest,nvest,nu,nv,lwrk,kwrk,ier -c ..array arguments.. - real*8 u(mu),v(mv),f(mu*mv*idim),tu(nuest),tv(nvest), - * c((nuest-4)*(nvest-4)*idim),wrk(lwrk) - integer ipar(2),iwrk(kwrk) -c ..local scalars.. - real*8 tol,ub,ue,vb,ve,peru,perv - integer i,j,jwrk,kndu,kndv,knru,knrv,kwest,l1,l2,l3,l4, - * lfpu,lfpv,lwest,lww,maxit,nc,mf,mumin,mvmin -c ..function references.. - integer max0 -c ..subroutine references.. -c fppasu,fpchec,fpchep -c .. -c we set up the parameters tol and maxit. - maxit = 20 - tol = 0.1e-02 -c before starting computations a data check is made. if the input data -c are invalid, control is immediately repassed to the calling program. - ier = 10 - if(iopt.lt.(-1) .or. iopt.gt.1) go to 200 - if(ipar(1).lt.0 .or. ipar(1).gt.1) go to 200 - if(ipar(2).lt.0 .or. ipar(2).gt.1) go to 200 - if(idim.le.0 .or. idim.gt.3) go to 200 - mumin = 4-2*ipar(1) - if(mu.lt.mumin .or. nuest.lt.8) go to 200 - mvmin = 4-2*ipar(2) - if(mv.lt.mvmin .or. nvest.lt.8) go to 200 - mf = mu*mv - nc = (nuest-4)*(nvest-4) - lwest = 4+nuest*(mv*idim+11+4*ipar(1))+nvest*(11+4*ipar(2))+ - * 4*(mu+mv)+max0(nuest,mv)*idim - kwest = 3+mu+mv+nuest+nvest - if(lwrk.lt.lwest .or. kwrk.lt.kwest) go to 200 - do 10 i=2,mu - if(u(i-1).ge.u(i)) go to 200 - 10 continue - do 20 i=2,mv - if(v(i-1).ge.v(i)) go to 200 - 20 continue - if(iopt.ge.0) go to 100 - if(nu.lt.8 .or. nu.gt.nuest) go to 200 - ub = u(1) - ue = u(mu) - if (ipar(1).ne.0) go to 40 - j = nu - do 30 i=1,4 - tu(i) = ub - tu(j) = ue - j = j-1 - 30 continue - call fpchec(u,mu,tu,nu,3,ier) - if(ier.ne.0) go to 200 - go to 60 - 40 l1 = 4 - l2 = l1 - l3 = nu-3 - l4 = l3 - peru = ue-ub - tu(l2) = ub - tu(l3) = ue - do 50 j=1,3 - l1 = l1+1 - l2 = l2-1 - l3 = l3+1 - l4 = l4-1 - tu(l2) = tu(l4)-peru - tu(l3) = tu(l1)+peru - 50 continue - call fpchep(u,mu,tu,nu,3,ier) - if(ier.ne.0) go to 200 - 60 if(nv.lt.8 .or. nv.gt.nvest) go to 200 - vb = v(1) - ve = v(mv) - if (ipar(2).ne.0) go to 80 - j = nv - do 70 i=1,4 - tv(i) = vb - tv(j) = ve - j = j-1 - 70 continue - call fpchec(v,mv,tv,nv,3,ier) - if(ier.ne.0) go to 200 - go to 150 - 80 l1 = 4 - l2 = l1 - l3 = nv-3 - l4 = l3 - perv = ve-vb - tv(l2) = vb - tv(l3) = ve - do 90 j=1,3 - l1 = l1+1 - l2 = l2-1 - l3 = l3+1 - l4 = l4-1 - tv(l2) = tv(l4)-perv - tv(l3) = tv(l1)+perv - 90 continue - call fpchep(v,mv,tv,nv,3,ier) - if (ier.eq.0) go to 150 - go to 200 - 100 if(s.lt.0.) go to 200 - if(s.eq.0. .and. (nuest.lt.(mu+4+2*ipar(1)) .or. - * nvest.lt.(mv+4+2*ipar(2))) )go to 200 - ier = 0 -c we partition the working space and determine the spline approximation - 150 lfpu = 5 - lfpv = lfpu+nuest - lww = lfpv+nvest - jwrk = lwrk-4-nuest-nvest - knru = 4 - knrv = knru+mu - kndu = knrv+mv - kndv = kndu+nuest - call fppasu(iopt,ipar,idim,u,mu,v,mv,f,mf,s,nuest,nvest, - * tol,maxit,nc,nu,tu,nv,tv,c,fp,wrk(1),wrk(2),wrk(3),wrk(4), - * wrk(lfpu),wrk(lfpv),iwrk(1),iwrk(2),iwrk(3),iwrk(knru), - * iwrk(knrv),iwrk(kndu),iwrk(kndv),wrk(lww),jwrk,ier) - 200 return - end - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/percur.f =================================================================== --- branches/Interpolate1D/fitpack/percur.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/percur.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,274 +0,0 @@ - subroutine percur(iopt,m,x,y,w,k,s,nest,n,t,c,fp, - * wrk,lwrk,iwrk,ier) -c given the set of data points (x(i),y(i)) and the set of positive -c numbers w(i),i=1,2,...,m-1, subroutine percur determines a smooth -c periodic spline approximation of degree k with period per=x(m)-x(1). -c if iopt=-1 percur calculates the weighted least-squares periodic -c spline according to a given set of knots. -c if iopt>=0 the number of knots of the spline s(x) and the position -c t(j),j=1,2,...,n is chosen automatically by the routine. the smooth- -c ness of s(x) is then achieved by minimalizing the discontinuity -c jumps of the k-th derivative of s(x) at the knots t(j),j=k+2,k+3,..., -c n-k-1. the amount of smoothness is determined by the condition that -c f(p)=sum((w(i)*(y(i)-s(x(i))))**2) be <= s, with s a given non- -c negative constant, called the smoothing factor. -c the fit s(x) is given in the b-spline representation (b-spline coef- -c ficients c(j),j=1,2,...,n-k-1) and can be evaluated by means of -c subroutine splev. -c -c calling sequence: -c call percur(iopt,m,x,y,w,k,s,nest,n,t,c,fp,wrk, -c * lwrk,iwrk,ier) -c -c parameters: -c iopt : integer flag. on entry iopt must specify whether a weighted -c least-squares spline (iopt=-1) or a smoothing spline (iopt= -c 0 or 1) must be determined. if iopt=0 the routine will start -c with an initial set of knots t(i)=x(1)+(x(m)-x(1))*(i-k-1), -c i=1,2,...,2*k+2. if iopt=1 the routine will continue with -c the knots found at the last call of the routine. -c attention: a call with iopt=1 must always be immediately -c preceded by another call with iopt=1 or iopt=0. -c unchanged on exit. -c m : integer. on entry m must specify the number of data points. -c m > 1. unchanged on exit. -c x : real array of dimension at least (m). before entry, x(i) -c must be set to the i-th value of the independent variable x, -c for i=1,2,...,m. these values must be supplied in strictly -c ascending order. x(m) only indicates the length of the -c period of the spline, i.e per=x(m)-x(1). -c unchanged on exit. -c y : real array of dimension at least (m). before entry, y(i) -c must be set to the i-th value of the dependent variable y, -c for i=1,2,...,m-1. the element y(m) is not used. -c unchanged on exit. -c w : real array of dimension at least (m). before entry, w(i) -c must be set to the i-th value in the set of weights. the -c w(i) must be strictly positive. w(m) is not used. -c see also further comments. unchanged on exit. -c k : integer. on entry k must specify the degree of the spline. -c 1<=k<=5. it is recommended to use cubic splines (k=3). -c the user is strongly dissuaded from choosing k even,together -c with a small s-value. unchanged on exit. -c s : real.on entry (in case iopt>=0) s must specify the smoothing -c factor. s >=0. unchanged on exit. -c for advice on the choice of s see further comments. -c nest : integer. on entry nest must contain an over-estimate of the -c total number of knots of the spline returned, to indicate -c the storage space available to the routine. nest >=2*k+2. -c in most practical situation nest=m/2 will be sufficient. -c always large enough is nest=m+2*k,the number of knots needed -c for interpolation (s=0). unchanged on exit. -c n : integer. -c unless ier = 10 (in case iopt >=0), n will contain the -c total number of knots of the spline approximation returned. -c if the computation mode iopt=1 is used this value of n -c should be left unchanged between subsequent calls. -c in case iopt=-1, the value of n must be specified on entry. -c t : real array of dimension at least (nest). -c on succesful exit, this array will contain the knots of the -c spline,i.e. the position of the interior knots t(k+2),t(k+3) -c ...,t(n-k-1) as well as the position of the additional knots -c t(1),t(2),...,t(k+1)=x(1) and t(n-k)=x(m),..,t(n) needed for -c the b-spline representation. -c if the computation mode iopt=1 is used, the values of t(1), -c t(2),...,t(n) should be left unchanged between subsequent -c calls. if the computation mode iopt=-1 is used, the values -c t(k+2),...,t(n-k-1) must be supplied by the user, before -c entry. see also the restrictions (ier=10). -c c : real array of dimension at least (nest). -c on succesful exit, this array will contain the coefficients -c c(1),c(2),..,c(n-k-1) in the b-spline representation of s(x) -c fp : real. unless ier = 10, fp contains the weighted sum of -c squared residuals of the spline approximation returned. -c wrk : real array of dimension at least (m*(k+1)+nest*(8+5*k)). -c used as working space. if the computation mode iopt=1 is -c used, the values wrk(1),...,wrk(n) should be left unchanged -c between subsequent calls. -c lwrk : integer. on entry,lwrk must specify the actual dimension of -c the array wrk as declared in the calling (sub)program. lwrk -c must not be too small (see wrk). unchanged on exit. -c iwrk : integer array of dimension at least (nest). -c used as working space. if the computation mode iopt=1 is -c used,the values iwrk(1),...,iwrk(n) should be left unchanged -c between subsequent calls. -c ier : integer. unless the routine detects an error, ier contains a -c non-positive value on exit, i.e. -c ier=0 : normal return. the spline returned has a residual sum of -c squares fp such that abs(fp-s)/s <= tol with tol a relat- -c ive tolerance set to 0.001 by the program. -c ier=-1 : normal return. the spline returned is an interpolating -c periodic spline (fp=0). -c ier=-2 : normal return. the spline returned is the weighted least- -c squares constant. in this extreme case fp gives the upper -c bound fp0 for the smoothing factor s. -c ier=1 : error. the required storage space exceeds the available -c storage space, as specified by the parameter nest. -c probably causes : nest too small. if nest is already -c large (say nest > m/2), it may also indicate that s is -c too small -c the approximation returned is the least-squares periodic -c spline according to the knots t(1),t(2),...,t(n). (n=nest) -c the parameter fp gives the corresponding weighted sum of -c squared residuals (fp>s). -c ier=2 : error. a theoretically impossible result was found during -c the iteration proces for finding a smoothing spline with -c fp = s. probably causes : s too small. -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=3 : error. the maximal number of iterations maxit (set to 20 -c by the program) allowed for finding a smoothing spline -c with fp=s has been reached. probably causes : s too small -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=10 : error. on entry, the input data are controlled on validity -c the following restrictions must be satisfied. -c -1<=iopt<=1, 1<=k<=5, m>1, nest>2*k+2, w(i)>0,i=1,...,m-1 -c x(1)=(k+1)*m+nest*(8+5*k) -c if iopt=-1: 2*k+2<=n<=min(nest,m+2*k) -c x(1)=0: s>=0 -c if s=0 : nest >= m+2*k -c if one of these conditions is found to be violated,control -c is immediately repassed to the calling program. in that -c case there is no approximation returned. -c -c further comments: -c by means of the parameter s, the user can control the tradeoff -c between closeness of fit and smoothness of fit of the approximation. -c if s is too large, the spline will be too smooth and signal will be -c lost ; if s is too small the spline will pick up too much noise. in -c the extreme cases the program will return an interpolating periodic -c spline if s=0 and the weighted least-squares constant if s is very -c large. between these extremes, a properly chosen s will result in -c a good compromise between closeness of fit and smoothness of fit. -c to decide whether an approximation, corresponding to a certain s is -c satisfactory the user is highly recommended to inspect the fits -c graphically. -c recommended values for s depend on the weights w(i). if these are -c taken as 1/d(i) with d(i) an estimate of the standard deviation of -c y(i), a good s-value should be found in the range (m-sqrt(2*m),m+ -c sqrt(2*m)). if nothing is known about the statistical error in y(i) -c each w(i) can be set equal to one and s determined by trial and -c error, taking account of the comments above. the best is then to -c start with a very large value of s ( to determine the least-squares -c constant and the corresponding upper bound fp0 for s) and then to -c progressively decrease the value of s ( say by a factor 10 in the -c beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the -c approximation shows more detail) to obtain closer fits. -c to economize the search for a good s-value the program provides with -c different modes of computation. at the first call of the routine, or -c whenever he wants to restart with the initial set of knots the user -c must set iopt=0. -c if iopt=1 the program will continue with the set of knots found at -c the last call of the routine. this will save a lot of computation -c time if percur is called repeatedly for different values of s. -c the number of knots of the spline returned and their location will -c depend on the value of s and on the complexity of the shape of the -c function underlying the data. but, if the computation mode iopt=1 -c is used, the knots returned may also depend on the s-values at -c previous calls (if these were smaller). therefore, if after a number -c of trials with different s-values and iopt=1, the user can finally -c accept a fit as satisfactory, it may be worthwhile for him to call -c percur once more with the selected value for s but now with iopt=0. -c indeed, percur may then return an approximation of the same quality -c of fit but with fewer knots and therefore better if data reduction -c is also an important objective for the user. -c -c other subroutines required: -c fpbacp,fpbspl,fpchep,fpperi,fpdisc,fpgivs,fpknot,fprati,fprota -c -c references: -c dierckx p. : algorithms for smoothing data with periodic and -c parametric splines, computer graphics and image -c processing 20 (1982) 171-184. -c dierckx p. : algorithms for smoothing data with periodic and param- -c etric splines, report tw55, dept. computer science, -c k.u.leuven, 1981. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author: -c p.dierckx -c dept. computer science, k.u. leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c creation date : may 1979 -c latest update : march 1987 -c -c .. -c ..scalar arguments.. - real*8 s,fp - integer iopt,m,k,nest,n,lwrk,ier -c ..array arguments.. - real*8 x(m),y(m),w(m),t(nest),c(nest),wrk(lwrk) - integer iwrk(nest) -c ..local scalars.. - real*8 per,tol - integer i,ia1,ia2,ib,ifp,ig1,ig2,iq,iz,i1,i2,j1,j2,k1,k2,lwest, - * maxit,m1,nmin -c ..subroutine references.. -c perper,pcheck -c .. -c we set up the parameters tol and maxit - maxit = 20 - tol = 0.1e-02 -c before starting computations a data check is made. if the input data -c are invalid, control is immediately repassed to the calling program. - ier = 10 - if(k.le.0 .or. k.gt.5) go to 50 - k1 = k+1 - k2 = k1+1 - if(iopt.lt.(-1) .or. iopt.gt.1) go to 50 - nmin = 2*k1 - if(m.lt.2 .or. nest.lt.nmin) go to 50 - lwest = m*k1+nest*(8+5*k) - if(lwrk.lt.lwest) go to 50 - m1 = m-1 - do 10 i=1,m1 - if(x(i).ge.x(i+1) .or. w(i).le.0.) go to 50 - 10 continue - if(iopt.ge.0) go to 30 - if(n.le.nmin .or. n.gt.nest) go to 50 - per = x(m)-x(1) - j1 = k1 - t(j1) = x(1) - i1 = n-k - t(i1) = x(m) - j2 = j1 - i2 = i1 - do 20 i=1,k - i1 = i1+1 - i2 = i2-1 - j1 = j1+1 - j2 = j2-1 - t(j2) = t(i2)-per - t(i1) = t(j1)+per - 20 continue - call fpchep(x,m,t,n,k,ier) - if (ier.eq.0) go to 40 - go to 50 - 30 if(s.lt.0.) go to 50 - if(s.eq.0. .and. nest.lt.(m+2*k)) go to 50 - ier = 0 -c we partition the working space and determine the spline approximation. - 40 ifp = 1 - iz = ifp+nest - ia1 = iz+nest - ia2 = ia1+nest*k1 - ib = ia2+nest*k - ig1 = ib+nest*k2 - ig2 = ig1+nest*k2 - iq = ig2+nest*k1 - call fpperi(iopt,x,y,w,m,k,s,nest,tol,maxit,k1,k2,n,t,c,fp, - * wrk(ifp),wrk(iz),wrk(ia1),wrk(ia2),wrk(ib),wrk(ig1),wrk(ig2), - * wrk(iq),iwrk,ier) - 50 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/pogrid.f =================================================================== --- branches/Interpolate1D/fitpack/pogrid.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/pogrid.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,466 +0,0 @@ - subroutine pogrid(iopt,ider,mu,u,mv,v,z,z0,r,s,nuest,nvest, - * nu,tu,nv,tv,c,fp,wrk,lwrk,iwrk,kwrk,ier) -c subroutine pogrid fits a function f(x,y) to a set of data points -c z(i,j) given at the nodes (x,y)=(u(i)*cos(v(j)),u(i)*sin(v(j))), -c i=1,...,mu ; j=1,...,mv , of a radius-angle grid over a disc -c x ** 2 + y ** 2 <= r ** 2 . -c -c this approximation problem is reduced to the determination of a -c bicubic spline s(u,v) smoothing the data (u(i),v(j),z(i,j)) on the -c rectangle 0<=u<=r, v(1)<=v<=v(1)+2*pi -c in order to have continuous partial derivatives -c i+j -c d f(0,0) -c g(i,j) = ---------- -c i j -c dx dy -c -c s(u,v)=f(x,y) must satisfy the following conditions -c -c (1) s(0,v) = g(0,0) v(1)<=v<= v(1)+2*pi -c -c d s(0,v) -c (2) -------- = cos(v)*g(1,0)+sin(v)*g(0,1) v(1)<=v<= v(1)+2*pi -c d u -c -c moreover, s(u,v) must be periodic in the variable v, i.e. -c -c j j -c d s(u,vb) d s(u,ve) -c (3) ---------- = --------- 0 <=u<= r, j=0,1,2 , vb=v(1), -c j j ve=vb+2*pi -c d v d v -c -c the number of knots of s(u,v) and their position tu(i),i=1,2,...,nu; -c tv(j),j=1,2,...,nv, is chosen automatically by the routine. the -c smoothness of s(u,v) is achieved by minimalizing the discontinuity -c jumps of the derivatives of the spline at the knots. the amount of -c smoothness of s(u,v) is determined by the condition that -c fp=sumi=1,mu(sumj=1,mv((z(i,j)-s(u(i),v(j)))**2))+(z0-g(0,0))**2<=s, -c with s a given non-negative constant. -c the fit s(u,v) is given in its b-spline representation and can be -c evaluated by means of routine bispev. f(x,y) = s(u,v) can also be -c evaluated by means of function program evapol. -c -c calling sequence: -c call pogrid(iopt,ider,mu,u,mv,v,z,z0,r,s,nuest,nvest,nu,tu, -c * ,nv,tv,c,fp,wrk,lwrk,iwrk,kwrk,ier) -c -c parameters: -c iopt : integer array of dimension 3, specifying different options. -c unchanged on exit. -c iopt(1):on entry iopt(1) must specify whether a least-squares spline -c (iopt(1)=-1) or a smoothing spline (iopt(1)=0 or 1) must be -c determined. -c if iopt(1)=0 the routine will start with an initial set of -c knots tu(i)=0,tu(i+4)=r,i=1,...,4;tv(i)=v(1)+(i-4)*2*pi,i=1,. -c ...,8. -c if iopt(1)=1 the routine will continue with the set of knots -c found at the last call of the routine. -c attention: a call with iopt(1)=1 must always be immediately -c preceded by another call with iopt(1) = 1 or iopt(1) = 0. -c iopt(2):on entry iopt(2) must specify the requested order of conti- -c nuity for f(x,y) at the origin. -c if iopt(2)=0 only condition (1) must be fulfilled and -c if iopt(2)=1 conditions (1)+(2) must be fulfilled. -c iopt(3):on entry iopt(3) must specify whether (iopt(3)=1) or not -c (iopt(3)=0) the approximation f(x,y) must vanish at the -c boundary of the approximation domain. -c ider : integer array of dimension 2, specifying different options. -c unchanged on exit. -c ider(1):on entry ider(1) must specify whether (ider(1)=0 or 1) or not -c (ider(1)=-1) there is a data value z0 at the origin. -c if ider(1)=1, z0 will be considered to be the right function -c value, and it will be fitted exactly (g(0,0)=z0=c(1)). -c if ider(1)=0, z0 will be considered to be a data value just -c like the other data values z(i,j). -c ider(2):on entry ider(2) must specify whether (ider(2)=1) or not -c (ider(2)=0) f(x,y) must have vanishing partial derivatives -c g(1,0) and g(0,1) at the origin. (in case iopt(2)=1) -c mu : integer. on entry mu must specify the number of grid points -c along the u-axis. unchanged on exit. -c mu >= mumin where mumin=4-iopt(3)-ider(2) if ider(1)<0 -c =3-iopt(3)-ider(2) if ider(1)>=0 -c u : real array of dimension at least (mu). before entry, u(i) -c must be set to the u-co-ordinate of the i-th grid point -c along the u-axis, for i=1,2,...,mu. these values must be -c positive and supplied in strictly ascending order. -c unchanged on exit. -c mv : integer. on entry mv must specify the number of grid points -c along the v-axis. mv > 3 . unchanged on exit. -c v : real array of dimension at least (mv). before entry, v(j) -c must be set to the v-co-ordinate of the j-th grid point -c along the v-axis, for j=1,2,...,mv. these values must be -c supplied in strictly ascending order. unchanged on exit. -c -pi <= v(1) < pi , v(mv) < v(1)+2*pi. -c z : real array of dimension at least (mu*mv). -c before entry, z(mv*(i-1)+j) must be set to the data value at -c the grid point (u(i),v(j)) for i=1,...,mu and j=1,...,mv. -c unchanged on exit. -c z0 : real value. on entry (if ider(1) >=0 ) z0 must specify the -c data value at the origin. unchanged on exit. -c r : real value. on entry r must specify the radius of the disk. -c r>=u(mu) (>u(mu) if iopt(3)=1). unchanged on exit. -c s : real. on entry (if iopt(1)>=0) s must specify the smoothing -c factor. s >=0. unchanged on exit. -c for advice on the choice of s see further comments -c nuest : integer. unchanged on exit. -c nvest : integer. unchanged on exit. -c on entry, nuest and nvest must specify an upper bound for the -c number of knots required in the u- and v-directions respect. -c these numbers will also determine the storage space needed by -c the routine. nuest >= 8, nvest >= 8. -c in most practical situation nuest = mu/2, nvest=mv/2, will -c be sufficient. always large enough are nuest=mu+5+iopt(2)+ -c iopt(3), nvest = mv+7, the number of knots needed for -c interpolation (s=0). see also further comments. -c nu : integer. -c unless ier=10 (in case iopt(1)>=0), nu will contain the total -c number of knots with respect to the u-variable, of the spline -c approximation returned. if the computation mode iopt(1)=1 is -c used, the value of nu should be left unchanged between sub- -c sequent calls. in case iopt(1)=-1, the value of nu should be -c specified on entry. -c tu : real array of dimension at least (nuest). -c on succesful exit, this array will contain the knots of the -c spline with respect to the u-variable, i.e. the position of -c the interior knots tu(5),...,tu(nu-4) as well as the position -c of the additional knots tu(1)=...=tu(4)=0 and tu(nu-3)=...= -c tu(nu)=r needed for the b-spline representation. -c if the computation mode iopt(1)=1 is used,the values of tu(1) -c ...,tu(nu) should be left unchanged between subsequent calls. -c if the computation mode iopt(1)=-1 is used, the values tu(5), -c ...tu(nu-4) must be supplied by the user, before entry. -c see also the restrictions (ier=10). -c nv : integer. -c unless ier=10 (in case iopt(1)>=0), nv will contain the total -c number of knots with respect to the v-variable, of the spline -c approximation returned. if the computation mode iopt(1)=1 is -c used, the value of nv should be left unchanged between sub- -c sequent calls. in case iopt(1) = -1, the value of nv should -c be specified on entry. -c tv : real array of dimension at least (nvest). -c on succesful exit, this array will contain the knots of the -c spline with respect to the v-variable, i.e. the position of -c the interior knots tv(5),...,tv(nv-4) as well as the position -c of the additional knots tv(1),...,tv(4) and tv(nv-3),..., -c tv(nv) needed for the b-spline representation. -c if the computation mode iopt(1)=1 is used,the values of tv(1) -c ...,tv(nv) should be left unchanged between subsequent calls. -c if the computation mode iopt(1)=-1 is used, the values tv(5), -c ...tv(nv-4) must be supplied by the user, before entry. -c see also the restrictions (ier=10). -c c : real array of dimension at least (nuest-4)*(nvest-4). -c on succesful exit, c contains the coefficients of the spline -c approximation s(u,v) -c fp : real. unless ier=10, fp contains the sum of squared -c residuals of the spline approximation returned. -c wrk : real array of dimension (lwrk). used as workspace. -c if the computation mode iopt(1)=1 is used the values of -c wrk(1),...,wrk(8) should be left unchanged between subsequent -c calls. -c lwrk : integer. on entry lwrk must specify the actual dimension of -c the array wrk as declared in the calling (sub)program. -c lwrk must not be too small. -c lwrk >= 8+nuest*(mv+nvest+3)+nvest*21+4*mu+6*mv+q -c where q is the larger of (mv+nvest) and nuest. -c iwrk : integer array of dimension (kwrk). used as workspace. -c if the computation mode iopt(1)=1 is used the values of -c iwrk(1),.,iwrk(4) should be left unchanged between subsequent -c calls. -c kwrk : integer. on entry kwrk must specify the actual dimension of -c the array iwrk as declared in the calling (sub)program. -c kwrk >= 4+mu+mv+nuest+nvest. -c ier : integer. unless the routine detects an error, ier contains a -c non-positive value on exit, i.e. -c ier=0 : normal return. the spline returned has a residual sum of -c squares fp such that abs(fp-s)/s <= tol with tol a relat- -c ive tolerance set to 0.001 by the program. -c ier=-1 : normal return. the spline returned is an interpolating -c spline (fp=0). -c ier=-2 : normal return. the spline returned is the least-squares -c constrained polynomial. in this extreme case fp gives the -c upper bound for the smoothing factor s. -c ier=1 : error. the required storage space exceeds the available -c storage space, as specified by the parameters nuest and -c nvest. -c probably causes : nuest or nvest too small. if these param- -c eters are already large, it may also indicate that s is -c too small -c the approximation returned is the least-squares spline -c according to the current set of knots. the parameter fp -c gives the corresponding sum of squared residuals (fp>s). -c ier=2 : error. a theoretically impossible result was found during -c the iteration proces for finding a smoothing spline with -c fp = s. probably causes : s too small. -c there is an approximation returned but the corresponding -c sum of squared residuals does not satisfy the condition -c abs(fp-s)/s < tol. -c ier=3 : error. the maximal number of iterations maxit (set to 20 -c by the program) allowed for finding a smoothing spline -c with fp=s has been reached. probably causes : s too small -c there is an approximation returned but the corresponding -c sum of squared residuals does not satisfy the condition -c abs(fp-s)/s < tol. -c ier=10 : error. on entry, the input data are controlled on validity -c the following restrictions must be satisfied. -c -1<=iopt(1)<=1, 0<=iopt(2)<=1, 0<=iopt(3)<=1, -c -1<=ider(1)<=1, 0<=ider(2)<=1, ider(2)=0 if iopt(2)=0. -c mu >= mumin (see above), mv >= 4, nuest >=8, nvest >= 8, -c kwrk>=4+mu+mv+nuest+nvest, -c lwrk >= 8+nuest*(mv+nvest+3)+nvest*21+4*mu+6*mv+ -c max(nuest,mv+nvest) -c 0< u(i-1)=0: s>=0 -c if s=0: nuest>=mu+5+iopt(2)+iopt(3), nvest>=mv+7 -c if one of these conditions is found to be violated,control -c is immediately repassed to the calling program. in that -c case there is no approximation returned. -c -c further comments: -c pogrid does not allow individual weighting of the data-values. -c so, if these were determined to widely different accuracies, then -c perhaps the general data set routine polar should rather be used -c in spite of efficiency. -c by means of the parameter s, the user can control the tradeoff -c between closeness of fit and smoothness of fit of the approximation. -c if s is too large, the spline will be too smooth and signal will be -c lost ; if s is too small the spline will pick up too much noise. in -c the extreme cases the program will return an interpolating spline if -c s=0 and the constrained least-squares polynomial(degrees 3,0)if s is -c very large. between these extremes, a properly chosen s will result -c in a good compromise between closeness of fit and smoothness of fit. -c to decide whether an approximation, corresponding to a certain s is -c satisfactory the user is highly recommended to inspect the fits -c graphically. -c recommended values for s depend on the accuracy of the data values. -c if the user has an idea of the statistical errors on the data, he -c can also find a proper estimate for s. for, by assuming that, if he -c specifies the right s, pogrid will return a spline s(u,v) which -c exactly reproduces the function underlying the data he can evaluate -c the sum((z(i,j)-s(u(i),v(j)))**2) to find a good estimate for this s -c for example, if he knows that the statistical errors on his z(i,j)- -c values is not greater than 0.1, he may expect that a good s should -c have a value not larger than mu*mv*(0.1)**2. -c if nothing is known about the statistical error in z(i,j), s must -c be determined by trial and error, taking account of the comments -c above. the best is then to start with a very large value of s (to -c determine the least-squares polynomial and the corresponding upper -c bound fp0 for s) and then to progressively decrease the value of s -c ( say by a factor 10 in the beginning, i.e. s=fp0/10,fp0/100,... -c and more carefully as the approximation shows more detail) to -c obtain closer fits. -c to economize the search for a good s-value the program provides with -c different modes of computation. at the first call of the routine, or -c whenever he wants to restart with the initial set of knots the user -c must set iopt(1)=0. -c if iopt(1) = 1 the program will continue with the knots found at -c the last call of the routine. this will save a lot of computation -c time if pogrid is called repeatedly for different values of s. -c the number of knots of the spline returned and their location will -c depend on the value of s and on the complexity of the shape of the -c function underlying the data. if the computation mode iopt(1) = 1 -c is used, the knots returned may also depend on the s-values at -c previous calls (if these were smaller). therefore, if after a number -c of trials with different s-values and iopt(1)=1,the user can finally -c accept a fit as satisfactory, it may be worthwhile for him to call -c pogrid once more with the chosen value for s but now with iopt(1)=0. -c indeed, pogrid may then return an approximation of the same quality -c of fit but with fewer knots and therefore better if data reduction -c is also an important objective for the user. -c the number of knots may also depend on the upper bounds nuest and -c nvest. indeed, if at a certain stage in pogrid the number of knots -c in one direction (say nu) has reached the value of its upper bound -c (nuest), then from that moment on all subsequent knots are added -c in the other (v) direction. this may indicate that the value of -c nuest is too small. on the other hand, it gives the user the option -c of limiting the number of knots the routine locates in any direction -c for example, by setting nuest=8 (the lowest allowable value for -c nuest), the user can indicate that he wants an approximation which -c is a simple cubic polynomial in the variable u. -c -c other subroutines required: -c fppogr,fpchec,fpchep,fpknot,fpopdi,fprati,fpgrdi,fpsysy,fpback, -c fpbacp,fpbspl,fpcyt1,fpcyt2,fpdisc,fpgivs,fprota -c -c references: -c dierckx p. : fast algorithms for smoothing data over a disc or a -c sphere using tensor product splines, in "algorithms -c for approximation", ed. j.c.mason and m.g.cox, -c clarendon press oxford, 1987, pp. 51-65 -c dierckx p. : fast algorithms for smoothing data over a disc or a -c sphere using tensor product splines, report tw73, dept. -c computer science,k.u.leuven, 1985. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author: -c p.dierckx -c dept. computer science, k.u. leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c creation date : july 1985 -c latest update : march 1989 -c -c .. -c ..scalar arguments.. - real*8 z0,r,s,fp - integer mu,mv,nuest,nvest,nu,nv,lwrk,kwrk,ier -c ..array arguments.. - integer iopt(3),ider(2),iwrk(kwrk) - real*8 u(mu),v(mv),z(mu*mv),c((nuest-4)*(nvest-4)),tu(nuest), - * tv(nvest),wrk(lwrk) -c ..local scalars.. - real*8 per,pi,tol,uu,ve,zmax,zmin,one,half,rn,zb - integer i,i1,i2,j,jwrk,j1,j2,kndu,kndv,knru,knrv,kwest,l, - * ldz,lfpu,lfpv,lwest,lww,m,maxit,mumin,muu,nc -c ..function references.. - real*8 datan2 - integer max0 -c ..subroutine references.. -c fpchec,fpchep,fppogr -c .. -c set constants - one = 1d0 - half = 0.5e0 - pi = datan2(0d0,-one) - per = pi+pi - ve = v(1)+per -c we set up the parameters tol and maxit. - maxit = 20 - tol = 0.1e-02 -c before starting computations, a data check is made. if the input data -c are invalid, control is immediately repassed to the calling program. - ier = 10 - if(iopt(1).lt.(-1) .or. iopt(1).gt.1) go to 200 - if(iopt(2).lt.0 .or. iopt(2).gt.1) go to 200 - if(iopt(3).lt.0 .or. iopt(3).gt.1) go to 200 - if(ider(1).lt.(-1) .or. ider(1).gt.1) go to 200 - if(ider(2).lt.0 .or. ider(2).gt.1) go to 200 - if(ider(2).eq.1 .and. iopt(2).eq.0) go to 200 - mumin = 4-iopt(3)-ider(2) - if(ider(1).ge.0) mumin = mumin-1 - if(mu.lt.mumin .or. mv.lt.4) go to 200 - if(nuest.lt.8 .or. nvest.lt.8) go to 200 - m = mu*mv - nc = (nuest-4)*(nvest-4) - lwest = 8+nuest*(mv+nvest+3)+21*nvest+4*mu+6*mv+ - * max0(nuest,mv+nvest) - kwest = 4+mu+mv+nuest+nvest - if(lwrk.lt.lwest .or. kwrk.lt.kwest) go to 200 - if(u(1).le.0. .or. u(mu).gt.r) go to 200 - if(iopt(3).eq.0) go to 10 - if(u(mu).eq.r) go to 200 - 10 if(mu.eq.1) go to 30 - do 20 i=2,mu - if(u(i-1).ge.u(i)) go to 200 - 20 continue - 30 if(v(1).lt. (-pi) .or. v(1).ge.pi ) go to 200 - if(v(mv).ge.v(1)+per) go to 200 - do 40 i=2,mv - if(v(i-1).ge.v(i)) go to 200 - 40 continue - if(iopt(1).gt.0) go to 140 -c if not given, we compute an estimate for z0. - if(ider(1).lt.0) go to 50 - zb = z0 - go to 70 - 50 zb = 0. - do 60 i=1,mv - zb = zb+z(i) - 60 continue - rn = mv - zb = zb/rn -c we determine the range of z-values. - 70 zmin = zb - zmax = zb - do 80 i=1,m - if(z(i).lt.zmin) zmin = z(i) - if(z(i).gt.zmax) zmax = z(i) - 80 continue - wrk(5) = zb - wrk(6) = 0. - wrk(7) = 0. - wrk(8) = zmax -zmin - iwrk(4) = mu - if(iopt(1).eq.0) go to 140 - if(nu.lt.8 .or. nu.gt.nuest) go to 200 - if(nv.lt.11 .or. nv.gt.nvest) go to 200 - j = nu - do 90 i=1,4 - tu(i) = 0. - tu(j) = r - j = j-1 - 90 continue - l = 9 - wrk(l) = 0. - if(iopt(2).eq.0) go to 100 - l = l+1 - uu = u(1) - if(uu.gt.tu(5)) uu = tu(5) - wrk(l) = uu*half - 100 do 110 i=1,mu - l = l+1 - wrk(l) = u(i) - 110 continue - if(iopt(3).eq.0) go to 120 - l = l+1 - wrk(l) = r - 120 muu = l-8 - call fpchec(wrk(9),muu,tu,nu,3,ier) - if(ier.ne.0) go to 200 - j1 = 4 - tv(j1) = v(1) - i1 = nv-3 - tv(i1) = ve - j2 = j1 - i2 = i1 - do 130 i=1,3 - i1 = i1+1 - i2 = i2-1 - j1 = j1+1 - j2 = j2-1 - tv(j2) = tv(i2)-per - tv(i1) = tv(j1)+per - 130 continue - l = 9 - do 135 i=1,mv - wrk(l) = v(i) - l = l+1 - 135 continue - wrk(l) = ve - call fpchep(wrk(9),mv+1,tv,nv,3,ier) - if (ier.eq.0) go to 150 - go to 200 - 140 if(s.lt.0.) go to 200 - if(s.eq.0. .and. (nuest.lt.(mu+5+iopt(2)+iopt(3)) .or. - * nvest.lt.(mv+7)) ) go to 200 -c we partition the working space and determine the spline approximation - 150 ldz = 5 - lfpu = 9 - lfpv = lfpu+nuest - lww = lfpv+nvest - jwrk = lwrk-8-nuest-nvest - knru = 5 - knrv = knru+mu - kndu = knrv+mv - kndv = kndu+nuest - call fppogr(iopt,ider,u,mu,v,mv,z,m,zb,r,s,nuest,nvest,tol,maxit, - * nc,nu,tu,nv,tv,c,fp,wrk(1),wrk(2),wrk(3),wrk(4),wrk(lfpu), - * wrk(lfpv),wrk(ldz),wrk(8),iwrk(1),iwrk(2),iwrk(3),iwrk(4), - * iwrk(knru),iwrk(knrv),iwrk(kndu),iwrk(kndv),wrk(lww),jwrk,ier) - 200 return - end - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/polar.f =================================================================== --- branches/Interpolate1D/fitpack/polar.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/polar.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,450 +0,0 @@ - subroutine polar(iopt,m,x,y,z,w,rad,s,nuest,nvest,eps,nu,tu, - * nv,tv,u,v,c,fp,wrk1,lwrk1,wrk2,lwrk2,iwrk,kwrk,ier) -c subroutine polar fits a smooth function f(x,y) to a set of data -c points (x(i),y(i),z(i)) scattered arbitrarily over an approximation -c domain x**2+y**2 <= rad(atan(y/x))**2. through the transformation -c x = u*rad(v)*cos(v) , y = u*rad(v)*sin(v) -c the approximation problem is reduced to the determination of a bi- -c cubic spline s(u,v) fitting a corresponding set of data points -c (u(i),v(i),z(i)) on the rectangle 0<=u<=1,-pi<=v<=pi. -c in order to have continuous partial derivatives -c i+j -c d f(0,0) -c g(i,j) = ---------- -c i j -c dx dy -c -c s(u,v)=f(x,y) must satisfy the following conditions -c -c (1) s(0,v) = g(0,0) -pi <=v<= pi. -c -c d s(0,v) -c (2) -------- = rad(v)*(cos(v)*g(1,0)+sin(v)*g(0,1)) -c d u -c -pi <=v<= pi -c 2 -c d s(0,v) 2 2 2 -c (3) -------- = rad(v)*(cos(v)*g(2,0)+sin(v)*g(0,2)+sin(2*v)*g(1,1)) -c 2 -c d u -pi <=v<= pi -c -c moreover, s(u,v) must be periodic in the variable v, i.e. -c -c j j -c d s(u,-pi) d s(u,pi) -c (4) ---------- = --------- 0 <=u<= 1, j=0,1,2 -c j j -c d v d v -c -c if iopt(1) < 0 circle calculates a weighted least-squares spline -c according to a given set of knots in u- and v- direction. -c if iopt(1) >=0, the number of knots in each direction and their pos- -c ition tu(j),j=1,2,...,nu ; tv(j),j=1,2,...,nv are chosen automatical- -c ly by the routine. the smoothness of s(u,v) is then achieved by mini- -c malizing the discontinuity jumps of the derivatives of the spline -c at the knots. the amount of smoothness of s(u,v) is determined by -c the condition that fp = sum((w(i)*(z(i)-s(u(i),v(i))))**2) be <= s, -c with s a given non-negative constant. -c the bicubic spline is given in its standard b-spline representation -c and the corresponding function f(x,y) can be evaluated by means of -c function program evapol. -c -c calling sequence: -c call polar(iopt,m,x,y,z,w,rad,s,nuest,nvest,eps,nu,tu, -c * nv,tv,u,v,wrk1,lwrk1,wrk2,lwrk2,iwrk,kwrk,ier) -c -c parameters: -c iopt : integer array of dimension 3, specifying different options. -c unchanged on exit. -c iopt(1):on entry iopt(1) must specify whether a weighted -c least-squares polar spline (iopt(1)=-1) or a smoothing -c polar spline (iopt(1)=0 or 1) must be determined. -c if iopt(1)=0 the routine will start with an initial set of -c knots tu(i)=0,tu(i+4)=1,i=1,...,4;tv(i)=(2*i-9)*pi,i=1,...,8. -c if iopt(1)=1 the routine will continue with the set of knots -c found at the last call of the routine. -c attention: a call with iopt(1)=1 must always be immediately -c preceded by another call with iopt(1) = 1 or iopt(1) = 0. -c iopt(2):on entry iopt(2) must specify the requested order of conti- -c nuity for f(x,y) at the origin. -c if iopt(2)=0 only condition (1) must be fulfilled, -c if iopt(2)=1 conditions (1)+(2) must be fulfilled and -c if iopt(2)=2 conditions (1)+(2)+(3) must be fulfilled. -c iopt(3):on entry iopt(3) must specify whether (iopt(3)=1) or not -c (iopt(3)=0) the approximation f(x,y) must vanish at the -c boundary of the approximation domain. -c m : integer. on entry m must specify the number of data points. -c m >= 4-iopt(2)-iopt(3) unchanged on exit. -c x : real array of dimension at least (m). -c y : real array of dimension at least (m). -c z : real array of dimension at least (m). -c before entry, x(i),y(i),z(i) must be set to the co-ordinates -c of the i-th data point, for i=1,...,m. the order of the data -c points is immaterial. unchanged on exit. -c w : real array of dimension at least (m). before entry, w(i) must -c be set to the i-th value in the set of weights. the w(i) must -c be strictly positive. unchanged on exit. -c rad : real function subprogram defining the boundary of the approx- -c imation domain, i.e x = rad(v)*cos(v) , y = rad(v)*sin(v), -c -pi <= v <= pi. -c must be declared external in the calling (sub)program. -c s : real. on entry (in case iopt(1) >=0) s must specify the -c smoothing factor. s >=0. unchanged on exit. -c for advice on the choice of s see further comments -c nuest : integer. unchanged on exit. -c nvest : integer. unchanged on exit. -c on entry, nuest and nvest must specify an upper bound for the -c number of knots required in the u- and v-directions resp. -c these numbers will also determine the storage space needed by -c the routine. nuest >= 8, nvest >= 8. -c in most practical situation nuest = nvest = 8+sqrt(m/2) will -c be sufficient. see also further comments. -c eps : real. -c on entry, eps must specify a threshold for determining the -c effective rank of an over-determined linear system of equat- -c ions. 0 < eps < 1. if the number of decimal digits in the -c computer representation of a real number is q, then 10**(-q) -c is a suitable value for eps in most practical applications. -c unchanged on exit. -c nu : integer. -c unless ier=10 (in case iopt(1) >=0),nu will contain the total -c number of knots with respect to the u-variable, of the spline -c approximation returned. if the computation mode iopt(1)=1 -c is used, the value of nu should be left unchanged between -c subsequent calls. -c in case iopt(1)=-1,the value of nu must be specified on entry -c tu : real array of dimension at least nuest. -c on succesful exit, this array will contain the knots of the -c spline with respect to the u-variable, i.e. the position -c of the interior knots tu(5),...,tu(nu-4) as well as the -c position of the additional knots tu(1)=...=tu(4)=0 and -c tu(nu-3)=...=tu(nu)=1 needed for the b-spline representation -c if the computation mode iopt(1)=1 is used,the values of -c tu(1),...,tu(nu) should be left unchanged between subsequent -c calls. if the computation mode iopt(1)=-1 is used,the values -c tu(5),...tu(nu-4) must be supplied by the user, before entry. -c see also the restrictions (ier=10). -c nv : integer. -c unless ier=10 (in case iopt(1)>=0), nv will contain the total -c number of knots with respect to the v-variable, of the spline -c approximation returned. if the computation mode iopt(1)=1 -c is used, the value of nv should be left unchanged between -c subsequent calls. in case iopt(1)=-1, the value of nv should -c be specified on entry. -c tv : real array of dimension at least nvest. -c on succesful exit, this array will contain the knots of the -c spline with respect to the v-variable, i.e. the position of -c the interior knots tv(5),...,tv(nv-4) as well as the position -c of the additional knots tv(1),...,tv(4) and tv(nv-3),..., -c tv(nv) needed for the b-spline representation. -c if the computation mode iopt(1)=1 is used, the values of -c tv(1),...,tv(nv) should be left unchanged between subsequent -c calls. if the computation mode iopt(1)=-1 is used,the values -c tv(5),...tv(nv-4) must be supplied by the user, before entry. -c see also the restrictions (ier=10). -c u : real array of dimension at least (m). -c v : real array of dimension at least (m). -c on succesful exit, u(i),v(i) contains the co-ordinates of -c the i-th data point with respect to the transformed rectan- -c gular approximation domain, for i=1,2,...,m. -c if the computation mode iopt(1)=1 is used the values of -c u(i),v(i) should be left unchanged between subsequent calls. -c c : real array of dimension at least (nuest-4)*(nvest-4). -c on succesful exit, c contains the coefficients of the spline -c approximation s(u,v). -c fp : real. unless ier=10, fp contains the weighted sum of -c squared residuals of the spline approximation returned. -c wrk1 : real array of dimension (lwrk1). used as workspace. -c if the computation mode iopt(1)=1 is used the value of -c wrk1(1) should be left unchanged between subsequent calls. -c on exit wrk1(2),wrk1(3),...,wrk1(1+ncof) will contain the -c values d(i)/max(d(i)),i=1,...,ncof=1+iopt(2)*(iopt(2)+3)/2+ -c (nv-7)*(nu-5-iopt(2)-iopt(3)) with d(i) the i-th diagonal el- -c ement of the triangular matrix for calculating the b-spline -c coefficients.it includes those elements whose square is < eps -c which are treated as 0 in the case of rank deficiency(ier=-2) -c lwrk1 : integer. on entry lwrk1 must specify the actual dimension of -c the array wrk1 as declared in the calling (sub)program. -c lwrk1 must not be too small. let -c k = nuest-7, l = nvest-7, p = 1+iopt(2)*(iopt(2)+3)/2, -c q = k+2-iopt(2)-iopt(3) then -c lwrk1 >= 129+10*k+21*l+k*l+(p+l*q)*(1+8*l+p)+8*m -c wrk2 : real array of dimension (lwrk2). used as workspace, but -c only in the case a rank deficient system is encountered. -c lwrk2 : integer. on entry lwrk2 must specify the actual dimension of -c the array wrk2 as declared in the calling (sub)program. -c lwrk2 > 0 . a save upper bound for lwrk2 = (p+l*q+1)*(4*l+p) -c +p+l*q where p,l,q are as above. if there are enough data -c points, scattered uniformly over the approximation domain -c and if the smoothing factor s is not too small, there is a -c good chance that this extra workspace is not needed. a lot -c of memory might therefore be saved by setting lwrk2=1. -c (see also ier > 10) -c iwrk : integer array of dimension (kwrk). used as workspace. -c kwrk : integer. on entry kwrk must specify the actual dimension of -c the array iwrk as declared in the calling (sub)program. -c kwrk >= m+(nuest-7)*(nvest-7). -c ier : integer. unless the routine detects an error, ier contains a -c non-positive value on exit, i.e. -c ier=0 : normal return. the spline returned has a residual sum of -c squares fp such that abs(fp-s)/s <= tol with tol a relat- -c ive tolerance set to 0.001 by the program. -c ier=-1 : normal return. the spline returned is an interpolating -c spline (fp=0). -c ier=-2 : normal return. the spline returned is the weighted least- -c squares constrained polynomial . in this extreme case -c fp gives the upper bound for the smoothing factor s. -c ier<-2 : warning. the coefficients of the spline returned have been -c computed as the minimal norm least-squares solution of a -c (numerically) rank deficient system. (-ier) gives the rank. -c especially if the rank deficiency which can be computed as -c 1+iopt(2)*(iopt(2)+3)/2+(nv-7)*(nu-5-iopt(2)-iopt(3))+ier -c is large the results may be inaccurate. -c they could also seriously depend on the value of eps. -c ier=1 : error. the required storage space exceeds the available -c storage space, as specified by the parameters nuest and -c nvest. -c probably causes : nuest or nvest too small. if these param- -c eters are already large, it may also indicate that s is -c too small -c the approximation returned is the weighted least-squares -c polar spline according to the current set of knots. -c the parameter fp gives the corresponding weighted sum of -c squared residuals (fp>s). -c ier=2 : error. a theoretically impossible result was found during -c the iteration proces for finding a smoothing spline with -c fp = s. probably causes : s too small or badly chosen eps. -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=3 : error. the maximal number of iterations maxit (set to 20 -c by the program) allowed for finding a smoothing spline -c with fp=s has been reached. probably causes : s too small -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=4 : error. no more knots can be added because the dimension -c of the spline 1+iopt(2)*(iopt(2)+3)/2+(nv-7)*(nu-5-iopt(2) -c -iopt(3)) already exceeds the number of data points m. -c probably causes : either s or m too small. -c the approximation returned is the weighted least-squares -c polar spline according to the current set of knots. -c the parameter fp gives the corresponding weighted sum of -c squared residuals (fp>s). -c ier=5 : error. no more knots can be added because the additional -c knot would (quasi) coincide with an old one. -c probably causes : s too small or too large a weight to an -c inaccurate data point. -c the approximation returned is the weighted least-squares -c polar spline according to the current set of knots. -c the parameter fp gives the corresponding weighted sum of -c squared residuals (fp>s). -c ier=10 : error. on entry, the input data are controlled on validity -c the following restrictions must be satisfied. -c -1<=iopt(1)<=1 , 0<=iopt(2)<=2 , 0<=iopt(3)<=1 , -c m>=4-iopt(2)-iopt(3) , nuest>=8 ,nvest >=8, 00, i=1,...,m -c lwrk1 >= 129+10*k+21*l+k*l+(p+l*q)*(1+8*l+p)+8*m -c kwrk >= m+(nuest-7)*(nvest-7) -c if iopt(1)=-1:9<=nu<=nuest,9+iopt(2)*(iopt(2)+1)<=nv<=nvest -c 0=0: s>=0 -c if one of these conditions is found to be violated,control -c is immediately repassed to the calling program. in that -c case there is no approximation returned. -c ier>10 : error. lwrk2 is too small, i.e. there is not enough work- -c space for computing the minimal least-squares solution of -c a rank deficient system of linear equations. ier gives the -c requested value for lwrk2. there is no approximation re- -c turned but, having saved the information contained in nu, -c nv,tu,tv,wrk1,u,v and having adjusted the value of lwrk2 -c and the dimension of the array wrk2 accordingly, the user -c can continue at the point the program was left, by calling -c polar with iopt(1)=1. -c -c further comments: -c by means of the parameter s, the user can control the tradeoff -c between closeness of fit and smoothness of fit of the approximation. -c if s is too large, the spline will be too smooth and signal will be -c lost ; if s is too small the spline will pick up too much noise. in -c the extreme cases the program will return an interpolating spline if -c s=0 and the constrained weighted least-squares polynomial if s is -c very large. between these extremes, a properly chosen s will result -c in a good compromise between closeness of fit and smoothness of fit. -c to decide whether an approximation, corresponding to a certain s is -c satisfactory the user is highly recommended to inspect the fits -c graphically. -c recommended values for s depend on the weights w(i). if these are -c taken as 1/d(i) with d(i) an estimate of the standard deviation of -c z(i), a good s-value should be found in the range (m-sqrt(2*m),m+ -c sqrt(2*m)). if nothing is known about the statistical error in z(i) -c each w(i) can be set equal to one and s determined by trial and -c error, taking account of the comments above. the best is then to -c start with a very large value of s ( to determine the least-squares -c polynomial and the corresponding upper bound fp0 for s) and then to -c progressively decrease the value of s ( say by a factor 10 in the -c beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the -c approximation shows more detail) to obtain closer fits. -c to choose s very small is strongly discouraged. this considerably -c increases computation time and memory requirements. it may also -c cause rank-deficiency (ier<-2) and endager numerical stability. -c to economize the search for a good s-value the program provides with -c different modes of computation. at the first call of the routine, or -c whenever he wants to restart with the initial set of knots the user -c must set iopt(1)=0. -c if iopt(1)=1 the program will continue with the set of knots found -c at the last call of the routine. this will save a lot of computation -c time if polar is called repeatedly for different values of s. -c the number of knots of the spline returned and their location will -c depend on the value of s and on the complexity of the shape of the -c function underlying the data. if the computation mode iopt(1)=1 -c is used, the knots returned may also depend on the s-values at -c previous calls (if these were smaller). therefore, if after a number -c of trials with different s-values and iopt(1)=1,the user can finally -c accept a fit as satisfactory, it may be worthwhile for him to call -c polar once more with the selected value for s but now with iopt(1)=0 -c indeed, polar may then return an approximation of the same quality -c of fit but with fewer knots and therefore better if data reduction -c is also an important objective for the user. -c the number of knots may also depend on the upper bounds nuest and -c nvest. indeed, if at a certain stage in polar the number of knots -c in one direction (say nu) has reached the value of its upper bound -c (nuest), then from that moment on all subsequent knots are added -c in the other (v) direction. this may indicate that the value of -c nuest is too small. on the other hand, it gives the user the option -c of limiting the number of knots the routine locates in any direction -c -c other subroutines required: -c fpback,fpbspl,fppola,fpdisc,fpgivs,fprank,fprati,fprota,fporde, -c fprppo -c -c references: -c dierckx p.: an algorithm for fitting data over a circle using tensor -c product splines,j.comp.appl.maths 15 (1986) 161-173. -c dierckx p.: an algorithm for fitting data on a circle using tensor -c product splines, report tw68, dept. computer science, -c k.u.leuven, 1984. -c dierckx p.: curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author: -c p.dierckx -c dept. computer science, k.u. leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c creation date : june 1984 -c latest update : march 1989 -c -c .. -c ..scalar arguments.. - real*8 s,eps,fp - integer m,nuest,nvest,nu,nv,lwrk1,lwrk2,kwrk,ier -c ..array arguments.. - real*8 x(m),y(m),z(m),w(m),tu(nuest),tv(nvest),u(m),v(m), - * c((nuest-4)*(nvest-4)),wrk1(lwrk1),wrk2(lwrk2) - integer iopt(3),iwrk(kwrk) -c ..user specified function - real*8 rad -c ..local scalars.. - real*8 tol,pi,dist,r,one - integer i,ib1,ib3,ki,kn,kwest,la,lbu,lcc,lcs,lro,j - * lbv,lco,lf,lff,lfp,lh,lq,lsu,lsv,lwest,maxit,ncest,ncc,nuu, - * nvv,nreg,nrint,nu4,nv4,iopt1,iopt2,iopt3,ipar,nvmin -c ..function references.. - real*8 datan2,sqrt - external rad -c ..subroutine references.. -c fppola -c .. -c set up constants - one = 1d0 -c we set up the parameters tol and maxit. - maxit = 20 - tol = 0.1e-02 -c before starting computations a data check is made. if the input data -c are invalid,control is immediately repassed to the calling program. - ier = 10 - if(eps.le.0. .or. eps.ge.1.) go to 60 - iopt1 = iopt(1) - if(iopt1.lt.(-1) .or. iopt1.gt.1) go to 60 - iopt2 = iopt(2) - if(iopt2.lt.0 .or. iopt2.gt.2) go to 60 - iopt3 = iopt(3) - if(iopt3.lt.0 .or. iopt3.gt.1) go to 60 - if(m.lt.(4-iopt2-iopt3)) go to 60 - if(nuest.lt.8 .or. nvest.lt.8) go to 60 - nu4 = nuest-4 - nv4 = nvest-4 - ncest = nu4*nv4 - nuu = nuest-7 - nvv = nvest-7 - ipar = 1+iopt2*(iopt2+3)/2 - ncc = ipar+nvv*(nuest-5-iopt2-iopt3) - nrint = nuu+nvv - nreg = nuu*nvv - ib1 = 4*nvv - ib3 = ib1+ipar - lwest = ncc*(1+ib1+ib3)+2*nrint+ncest+m*8+ib3+5*nuest+12*nvest - kwest = m+nreg - if(lwrk1.lt.lwest .or. kwrk.lt.kwest) go to 60 - if(iopt1.gt.0) go to 40 - do 10 i=1,m - if(w(i).le.0.) go to 60 - dist = x(i)**2+y(i)**2 - u(i) = 0. - v(i) = 0. - if(dist.le.0.) go to 10 - v(i) = datan2(y(i),x(i)) - r = rad(v(i)) - if(r.le.0.) go to 60 - u(i) = sqrt(dist)/r - if(u(i).gt.one) go to 60 - 10 continue - if(iopt1.eq.0) go to 40 - nuu = nu-8 - if(nuu.lt.1 .or. nu.gt.nuest) go to 60 - tu(4) = 0. - do 20 i=1,nuu - j = i+4 - if(tu(j).le.tu(j-1) .or. tu(j).ge.one) go to 60 - 20 continue - nvv = nv-8 - nvmin = 9+iopt2*(iopt2+1) - if(nv.lt.nvmin .or. nv.gt.nvest) go to 60 - pi = datan2(0d0,-one) - tv(4) = -pi - do 30 i=1,nvv - j = i+4 - if(tv(j).le.tv(j-1) .or. tv(j).ge.pi) go to 60 - 30 continue - go to 50 - 40 if(s.lt.0.) go to 60 - 50 ier = 0 -c we partition the working space and determine the spline approximation - kn = 1 - ki = kn+m - lq = 2 - la = lq+ncc*ib3 - lf = la+ncc*ib1 - lff = lf+ncc - lfp = lff+ncest - lco = lfp+nrint - lh = lco+nrint - lbu = lh+ib3 - lbv = lbu+5*nuest - lro = lbv+5*nvest - lcc = lro+nvest - lcs = lcc+nvest - lsu = lcs+nvest*5 - lsv = lsu+m*4 - call fppola(iopt1,iopt2,iopt3,m,u,v,z,w,rad,s,nuest,nvest,eps,tol, - * - * maxit,ib1,ib3,ncest,ncc,nrint,nreg,nu,tu,nv,tv,c,fp,wrk1(1), - * wrk1(lfp),wrk1(lco),wrk1(lf),wrk1(lff),wrk1(lro),wrk1(lcc), - * wrk1(lcs),wrk1(la),wrk1(lq),wrk1(lbu),wrk1(lbv),wrk1(lsu), - * wrk1(lsv),wrk1(lh),iwrk(ki),iwrk(kn),wrk2,lwrk2,ier) - 60 return - end - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/profil.f =================================================================== --- branches/Interpolate1D/fitpack/profil.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/profil.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,117 +0,0 @@ - subroutine profil(iopt,tx,nx,ty,ny,c,kx,ky,u,nu,cu,ier) -c if iopt=0 subroutine profil calculates the b-spline coefficients of -c the univariate spline f(y) = s(u,y) with s(x,y) a bivariate spline of -c degrees kx and ky, given in the b-spline representation. -c if iopt = 1 it calculates the b-spline coefficients of the univariate -c spline g(x) = s(x,u) -c -c calling sequence: -c call profil(iopt,tx,nx,ty,ny,c,kx,ky,u,nu,cu,ier) -c -c input parameters: -c iopt : integer flag, specifying whether the profile f(y) (iopt=0) -c or the profile g(x) (iopt=1) must be determined. -c tx : real array, length nx, which contains the position of the -c knots in the x-direction. -c nx : integer, giving the total number of knots in the x-direction -c ty : real array, length ny, which contains the position of the -c knots in the y-direction. -c ny : integer, giving the total number of knots in the y-direction -c c : real array, length (nx-kx-1)*(ny-ky-1), which contains the -c b-spline coefficients. -c kx,ky : integer values, giving the degrees of the spline. -c u : real value, specifying the requested profile. -c tx(kx+1)<=u<=tx(nx-kx), if iopt=0. -c ty(ky+1)<=u<=ty(ny-ky), if iopt=1. -c nu : on entry nu must specify the dimension of the array cu. -c nu >= ny if iopt=0, nu >= nx if iopt=1. -c -c output parameters: -c cu : real array of dimension (nu). -c on succesful exit this array contains the b-spline -c ier : integer error flag -c ier=0 : normal return -c ier=10: invalid input data (see restrictions) -c -c restrictions: -c if iopt=0 : tx(kx+1) <= u <= tx(nx-kx), nu >=ny. -c if iopt=1 : ty(ky+1) <= u <= ty(ny-ky), nu >=nx. -c -c other subroutines required: -c fpbspl -c -c author : -c p.dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c latest update : march 1987 -c -c ..scalar arguments.. - integer iopt,nx,ny,kx,ky,nu,ier - real*8 u -c ..array arguments.. - real*8 tx(nx),ty(ny),c((nx-kx-1)*(ny-ky-1)),cu(nu) -c ..local scalars.. - integer i,j,kx1,ky1,l,l1,m,m0,nkx1,nky1 - real*8 sum -c ..local array - real*8 h(6) -c .. -c before starting computations a data check is made. if the input data -c are invalid control is immediately repassed to the calling program. - kx1 = kx+1 - ky1 = ky+1 - nkx1 = nx-kx1 - nky1 = ny-ky1 - ier = 10 - if(iopt.ne.0) go to 200 - if(nu.lt.ny) go to 300 - if(u.lt.tx(kx1) .or. u.gt.tx(nkx1+1)) go to 300 -c the b-splinecoefficients of f(y) = s(u,y). - ier = 0 - l = kx1 - l1 = l+1 - 110 if(u.lt.tx(l1) .or. l.eq.nkx1) go to 120 - l = l1 - l1 = l+1 - go to 110 - 120 call fpbspl(tx,nx,kx,u,l,h) - m0 = (l-kx1)*nky1+1 - do 140 i=1,nky1 - m = m0 - sum = 0. - do 130 j=1,kx1 - sum = sum+h(j)*c(m) - m = m+nky1 - 130 continue - cu(i) = sum - m0 = m0+1 - 140 continue - go to 300 - 200 if(nu.lt.nx) go to 300 - if(u.lt.ty(ky1) .or. u.gt.ty(nky1+1)) go to 300 -c the b-splinecoefficients of g(x) = s(x,u). - ier = 0 - l = ky1 - l1 = l+1 - 210 if(u.lt.ty(l1) .or. l.eq.nky1) go to 220 - l = l1 - l1 = l+1 - go to 210 - 220 call fpbspl(ty,ny,ky,u,l,h) - m0 = l-ky - do 240 i=1,nkx1 - m = m0 - sum = 0. - do 230 j=1,ky1 - sum = sum+h(j)*c(m) - m = m+1 - 230 continue - cu(i) = sum - m0 = m0+nky1 - 240 continue - 300 return - end - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/regrid.f =================================================================== --- branches/Interpolate1D/fitpack/regrid.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/regrid.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,353 +0,0 @@ - subroutine regrid(iopt,mx,x,my,y,z,xb,xe,yb,ye,kx,ky,s, - * nxest,nyest,nx,tx,ny,ty,c,fp,wrk,lwrk,iwrk,kwrk,ier) -c given the set of values z(i,j) on the rectangular grid (x(i),y(j)), -c i=1,...,mx;j=1,...,my, subroutine regrid determines a smooth bivar- -c iate spline approximation s(x,y) of degrees kx and ky on the rect- -c angle xb <= x <= xe, yb <= y <= ye. -c if iopt = -1 regrid calculates the least-squares spline according -c to a given set of knots. -c if iopt >= 0 the total numbers nx and ny of these knots and their -c position tx(j),j=1,...,nx and ty(j),j=1,...,ny are chosen automatic- -c ally by the routine. the smoothness of s(x,y) is then achieved by -c minimalizing the discontinuity jumps in the derivatives of s(x,y) -c across the boundaries of the subpanels (tx(i),tx(i+1))*(ty(j),ty(j+1). -c the amounth of smoothness is determined by the condition that f(p) = -c sum ((z(i,j)-s(x(i),y(j))))**2) be <= s, with s a given non-negative -c constant, called the smoothing factor. -c the fit is given in the b-spline representation (b-spline coefficients -c c((ny-ky-1)*(i-1)+j),i=1,...,nx-kx-1;j=1,...,ny-ky-1) and can be eval- -c uated by means of subroutine bispev. -c -c calling sequence: -c call regrid(iopt,mx,x,my,y,z,xb,xe,yb,ye,kx,ky,s,nxest,nyest, -c * nx,tx,ny,ty,c,fp,wrk,lwrk,iwrk,kwrk,ier) -c -c parameters: -c iopt : integer flag. on entry iopt must specify whether a least- -c squares spline (iopt=-1) or a smoothing spline (iopt=0 or 1) -c must be determined. -c if iopt=0 the routine will start with an initial set of knots -c tx(i)=xb,tx(i+kx+1)=xe,i=1,...,kx+1;ty(i)=yb,ty(i+ky+1)=ye,i= -c 1,...,ky+1. if iopt=1 the routine will continue with the set -c of knots found at the last call of the routine. -c attention: a call with iopt=1 must always be immediately pre- -c ceded by another call with iopt=1 or iopt=0 and -c s.ne.0. -c unchanged on exit. -c mx : integer. on entry mx must specify the number of grid points -c along the x-axis. mx > kx . unchanged on exit. -c x : real array of dimension at least (mx). before entry, x(i) -c must be set to the x-co-ordinate of the i-th grid point -c along the x-axis, for i=1,2,...,mx. these values must be -c supplied in strictly ascending order. unchanged on exit. -c my : integer. on entry my must specify the number of grid points -c along the y-axis. my > ky . unchanged on exit. -c y : real array of dimension at least (my). before entry, y(j) -c must be set to the y-co-ordinate of the j-th grid point -c along the y-axis, for j=1,2,...,my. these values must be -c supplied in strictly ascending order. unchanged on exit. -c z : real array of dimension at least (mx*my). -c before entry, z(my*(i-1)+j) must be set to the data value at -c the grid point (x(i),y(j)) for i=1,...,mx and j=1,...,my. -c unchanged on exit. -c xb,xe : real values. on entry xb,xe,yb and ye must specify the bound- -c yb,ye aries of the rectangular approximation domain. -c xb<=x(i)<=xe,i=1,...,mx; yb<=y(j)<=ye,j=1,...,my. -c unchanged on exit. -c kx,ky : integer values. on entry kx and ky must specify the degrees -c of the spline. 1<=kx,ky<=5. it is recommended to use bicubic -c (kx=ky=3) splines. unchanged on exit. -c s : real. on entry (in case iopt>=0) s must specify the smoothing -c factor. s >=0. unchanged on exit. -c for advice on the choice of s see further comments -c nxest : integer. unchanged on exit. -c nyest : integer. unchanged on exit. -c on entry, nxest and nyest must specify an upper bound for the -c number of knots required in the x- and y-directions respect. -c these numbers will also determine the storage space needed by -c the routine. nxest >= 2*(kx+1), nyest >= 2*(ky+1). -c in most practical situation nxest = mx/2, nyest=my/2, will -c be sufficient. always large enough are nxest=mx+kx+1, nyest= -c my+ky+1, the number of knots needed for interpolation (s=0). -c see also further comments. -c nx : integer. -c unless ier=10 (in case iopt >=0), nx will contain the total -c number of knots with respect to the x-variable, of the spline -c approximation returned. if the computation mode iopt=1 is -c used, the value of nx should be left unchanged between sub- -c sequent calls. -c in case iopt=-1, the value of nx should be specified on entry -c tx : real array of dimension nmax. -c on succesful exit, this array will contain the knots of the -c spline with respect to the x-variable, i.e. the position of -c the interior knots tx(kx+2),...,tx(nx-kx-1) as well as the -c position of the additional knots tx(1)=...=tx(kx+1)=xb and -c tx(nx-kx)=...=tx(nx)=xe needed for the b-spline representat. -c if the computation mode iopt=1 is used, the values of tx(1), -c ...,tx(nx) should be left unchanged between subsequent calls. -c if the computation mode iopt=-1 is used, the values tx(kx+2), -c ...tx(nx-kx-1) must be supplied by the user, before entry. -c see also the restrictions (ier=10). -c ny : integer. -c unless ier=10 (in case iopt >=0), ny will contain the total -c number of knots with respect to the y-variable, of the spline -c approximation returned. if the computation mode iopt=1 is -c used, the value of ny should be left unchanged between sub- -c sequent calls. -c in case iopt=-1, the value of ny should be specified on entry -c ty : real array of dimension nmax. -c on succesful exit, this array will contain the knots of the -c spline with respect to the y-variable, i.e. the position of -c the interior knots ty(ky+2),...,ty(ny-ky-1) as well as the -c position of the additional knots ty(1)=...=ty(ky+1)=yb and -c ty(ny-ky)=...=ty(ny)=ye needed for the b-spline representat. -c if the computation mode iopt=1 is used, the values of ty(1), -c ...,ty(ny) should be left unchanged between subsequent calls. -c if the computation mode iopt=-1 is used, the values ty(ky+2), -c ...ty(ny-ky-1) must be supplied by the user, before entry. -c see also the restrictions (ier=10). -c c : real array of dimension at least (nxest-kx-1)*(nyest-ky-1). -c on succesful exit, c contains the coefficients of the spline -c approximation s(x,y) -c fp : real. unless ier=10, fp contains the sum of squared -c residuals of the spline approximation returned. -c wrk : real array of dimension (lwrk). used as workspace. -c if the computation mode iopt=1 is used the values of wrk(1), -c ...,wrk(4) should be left unchanged between subsequent calls. -c lwrk : integer. on entry lwrk must specify the actual dimension of -c the array wrk as declared in the calling (sub)program. -c lwrk must not be too small. -c lwrk >= 4+nxest*(my+2*kx+5)+nyest*(2*ky+5)+mx*(kx+1)+ -c my*(ky+1) +u -c where u is the larger of my and nxest. -c iwrk : integer array of dimension (kwrk). used as workspace. -c if the computation mode iopt=1 is used the values of iwrk(1), -c ...,iwrk(3) should be left unchanged between subsequent calls -c kwrk : integer. on entry kwrk must specify the actual dimension of -c the array iwrk as declared in the calling (sub)program. -c kwrk >= 3+mx+my+nxest+nyest. -c ier : integer. unless the routine detects an error, ier contains a -c non-positive value on exit, i.e. -c ier=0 : normal return. the spline returned has a residual sum of -c squares fp such that abs(fp-s)/s <= tol with tol a relat- -c ive tolerance set to 0.001 by the program. -c ier=-1 : normal return. the spline returned is an interpolating -c spline (fp=0). -c ier=-2 : normal return. the spline returned is the least-squares -c polynomial of degrees kx and ky. in this extreme case fp -c gives the upper bound for the smoothing factor s. -c ier=1 : error. the required storage space exceeds the available -c storage space, as specified by the parameters nxest and -c nyest. -c probably causes : nxest or nyest too small. if these param- -c eters are already large, it may also indicate that s is -c too small -c the approximation returned is the least-squares spline -c according to the current set of knots. the parameter fp -c gives the corresponding sum of squared residuals (fp>s). -c ier=2 : error. a theoretically impossible result was found during -c the iteration proces for finding a smoothing spline with -c fp = s. probably causes : s too small. -c there is an approximation returned but the corresponding -c sum of squared residuals does not satisfy the condition -c abs(fp-s)/s < tol. -c ier=3 : error. the maximal number of iterations maxit (set to 20 -c by the program) allowed for finding a smoothing spline -c with fp=s has been reached. probably causes : s too small -c there is an approximation returned but the corresponding -c sum of squared residuals does not satisfy the condition -c abs(fp-s)/s < tol. -c ier=10 : error. on entry, the input data are controlled on validity -c the following restrictions must be satisfied. -c -1<=iopt<=1, 1<=kx,ky<=5, mx>kx, my>ky, nxest>=2*kx+2, -c nyest>=2*ky+2, kwrk>=3+mx+my+nxest+nyest, -c lwrk >= 4+nxest*(my+2*kx+5)+nyest*(2*ky+5)+mx*(kx+1)+ -c my*(ky+1) +max(my,nxest), -c xb<=x(i-1)=0: s>=0 -c if s=0 : nxest>=mx+kx+1, nyest>=my+ky+1 -c if one of these conditions is found to be violated,control -c is immediately repassed to the calling program. in that -c case there is no approximation returned. -c -c further comments: -c regrid does not allow individual weighting of the data-values. -c so, if these were determined to widely different accuracies, then -c perhaps the general data set routine surfit should rather be used -c in spite of efficiency. -c by means of the parameter s, the user can control the tradeoff -c between closeness of fit and smoothness of fit of the approximation. -c if s is too large, the spline will be too smooth and signal will be -c lost ; if s is too small the spline will pick up too much noise. in -c the extreme cases the program will return an interpolating spline if -c s=0 and the least-squares polynomial (degrees kx,ky) if s is -c very large. between these extremes, a properly chosen s will result -c in a good compromise between closeness of fit and smoothness of fit. -c to decide whether an approximation, corresponding to a certain s is -c satisfactory the user is highly recommended to inspect the fits -c graphically. -c recommended values for s depend on the accuracy of the data values. -c if the user has an idea of the statistical errors on the data, he -c can also find a proper estimate for s. for, by assuming that, if he -c specifies the right s, regrid will return a spline s(x,y) which -c exactly reproduces the function underlying the data he can evaluate -c the sum((z(i,j)-s(x(i),y(j)))**2) to find a good estimate for this s -c for example, if he knows that the statistical errors on his z(i,j)- -c values is not greater than 0.1, he may expect that a good s should -c have a value not larger than mx*my*(0.1)**2. -c if nothing is known about the statistical error in z(i,j), s must -c be determined by trial and error, taking account of the comments -c above. the best is then to start with a very large value of s (to -c determine the least-squares polynomial and the corresponding upper -c bound fp0 for s) and then to progressively decrease the value of s -c ( say by a factor 10 in the beginning, i.e. s=fp0/10,fp0/100,... -c and more carefully as the approximation shows more detail) to -c obtain closer fits. -c to economize the search for a good s-value the program provides with -c different modes of computation. at the first call of the routine, or -c whenever he wants to restart with the initial set of knots the user -c must set iopt=0. -c if iopt=1 the program will continue with the set of knots found at -c the last call of the routine. this will save a lot of computation -c time if regrid is called repeatedly for different values of s. -c the number of knots of the spline returned and their location will -c depend on the value of s and on the complexity of the shape of the -c function underlying the data. if the computation mode iopt=1 -c is used, the knots returned may also depend on the s-values at -c previous calls (if these were smaller). therefore, if after a number -c of trials with different s-values and iopt=1, the user can finally -c accept a fit as satisfactory, it may be worthwhile for him to call -c regrid once more with the selected value for s but now with iopt=0. -c indeed, regrid may then return an approximation of the same quality -c of fit but with fewer knots and therefore better if data reduction -c is also an important objective for the user. -c the number of knots may also depend on the upper bounds nxest and -c nyest. indeed, if at a certain stage in regrid the number of knots -c in one direction (say nx) has reached the value of its upper bound -c (nxest), then from that moment on all subsequent knots are added -c in the other (y) direction. this may indicate that the value of -c nxest is too small. on the other hand, it gives the user the option -c of limiting the number of knots the routine locates in any direction -c for example, by setting nxest=2*kx+2 (the lowest allowable value for -c nxest), the user can indicate that he wants an approximation which -c is a simple polynomial of degree kx in the variable x. -c -c other subroutines required: -c fpback,fpbspl,fpregr,fpdisc,fpgivs,fpgrre,fprati,fprota,fpchec, -c fpknot -c -c references: -c dierckx p. : a fast algorithm for smoothing data on a rectangular -c grid while using spline functions, siam j.numer.anal. -c 19 (1982) 1286-1304. -c dierckx p. : a fast algorithm for smoothing data on a rectangular -c grid while using spline functions, report tw53, dept. -c computer science,k.u.leuven, 1980. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author: -c p.dierckx -c dept. computer science, k.u. leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c creation date : may 1979 -c latest update : march 1989 -c -c .. -c ..scalar arguments.. - real*8 xb,xe,yb,ye,s,fp - integer iopt,mx,my,kx,ky,nxest,nyest,nx,ny,lwrk,kwrk,ier -c ..array arguments.. - real*8 x(mx),y(my),z(mx*my),tx(nxest),ty(nyest), - * c((nxest-kx-1)*(nyest-ky-1)),wrk(lwrk) - integer iwrk(kwrk) -c ..local scalars.. - real*8 tol - integer i,j,jwrk,kndx,kndy,knrx,knry,kwest,kx1,kx2,ky1,ky2, - * lfpx,lfpy,lwest,lww,maxit,nc,nminx,nminy,mz -c ..function references.. - integer max0 -c ..subroutine references.. -c fpregr,fpchec -c .. -c we set up the parameters tol and maxit. - maxit = 20 - tol = 0.1e-02 -c before starting computations a data check is made. if the input data -c are invalid, control is immediately repassed to the calling program. - ier = 10 - if(kx.le.0 .or. kx.gt.5) go to 70 - kx1 = kx+1 - kx2 = kx1+1 - if(ky.le.0 .or. ky.gt.5) go to 70 - ky1 = ky+1 - ky2 = ky1+1 - if(iopt.lt.(-1) .or. iopt.gt.1) go to 70 - nminx = 2*kx1 - if(mx.lt.kx1 .or. nxest.lt.nminx) go to 70 - nminy = 2*ky1 - if(my.lt.ky1 .or. nyest.lt.nminy) go to 70 - mz = mx*my - nc = (nxest-kx1)*(nyest-ky1) - lwest = 4+nxest*(my+2*kx2+1)+nyest*(2*ky2+1)+mx*kx1+ - * my*ky1+max0(nxest,my) - kwest = 3+mx+my+nxest+nyest - if(lwrk.lt.lwest .or. kwrk.lt.kwest) go to 70 - if(xb.gt.x(1) .or. xe.lt.x(mx)) go to 70 - do 10 i=2,mx - if(x(i-1).ge.x(i)) go to 70 - 10 continue - if(yb.gt.y(1) .or. ye.lt.y(my)) go to 70 - do 20 i=2,my - if(y(i-1).ge.y(i)) go to 70 - 20 continue - if(iopt.ge.0) go to 50 - if(nx.lt.nminx .or. nx.gt.nxest) go to 70 - j = nx - do 30 i=1,kx1 - tx(i) = xb - tx(j) = xe - j = j-1 - 30 continue - call fpchec(x,mx,tx,nx,kx,ier) - if(ier.ne.0) go to 70 - if(ny.lt.nminy .or. ny.gt.nyest) go to 70 - j = ny - do 40 i=1,ky1 - ty(i) = yb - ty(j) = ye - j = j-1 - 40 continue - call fpchec(y,my,ty,ny,ky,ier) - if (ier.eq.0) go to 60 - go to 70 - 50 if(s.lt.0.) go to 70 - if(s.eq.0. .and. (nxest.lt.(mx+kx1) .or. nyest.lt.(my+ky1)) ) - * go to 70 - ier = 0 -c we partition the working space and determine the spline approximation - 60 lfpx = 5 - lfpy = lfpx+nxest - lww = lfpy+nyest - jwrk = lwrk-4-nxest-nyest - knrx = 4 - knry = knrx+mx - kndx = knry+my - kndy = kndx+nxest - call fpregr(iopt,x,mx,y,my,z,mz,xb,xe,yb,ye,kx,ky,s,nxest,nyest, - * tol,maxit,nc,nx,tx,ny,ty,c,fp,wrk(1),wrk(2),wrk(3),wrk(4), - * wrk(lfpx),wrk(lfpy),iwrk(1),iwrk(2),iwrk(3),iwrk(knrx), - * iwrk(knry),iwrk(kndx),iwrk(kndy),wrk(lww),jwrk,ier) - 70 return - end - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/spalde.f =================================================================== --- branches/Interpolate1D/fitpack/spalde.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/spalde.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,73 +0,0 @@ - subroutine spalde(t,n,c,k1,x,d,ier) -c subroutine spalde evaluates at a point x all the derivatives -c (j-1) -c d(j) = s (x) , j=1,2,...,k1 -c of a spline s(x) of order k1 (degree k=k1-1), given in its b-spline -c representation. -c -c calling sequence: -c call spalde(t,n,c,k1,x,d,ier) -c -c input parameters: -c t : array,length n, which contains the position of the knots. -c n : integer, giving the total number of knots of s(x). -c c : array,length n, which contains the b-spline coefficients. -c k1 : integer, giving the order of s(x) (order=degree+1) -c x : real, which contains the point where the derivatives must -c be evaluated. -c -c output parameters: -c d : array,length k1, containing the derivative values of s(x). -c ier : error flag -c ier = 0 : normal return -c ier =10 : invalid input data (see restrictions) -c -c restrictions: -c t(k1) <= x <= t(n-k1+1) -c -c further comments: -c if x coincides with a knot, right derivatives are computed -c ( left derivatives if x = t(n-k1+1) ). -c -c other subroutines required: fpader. -c -c references : -c de boor c : on calculating with b-splines, j. approximation theory -c 6 (1972) 50-62. -c cox m.g. : the numerical evaluation of b-splines, j. inst. maths -c applics 10 (1972) 134-149. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author : -c p.dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c latest update : march 1987 -c -c ..scalar arguments.. - integer n,k1,ier - real*8 x -c ..array arguments.. - real*8 t(n),c(n),d(k1) -c ..local scalars.. - integer l,nk1 -c .. -c before starting computations a data check is made. if the input data -c are invalid control is immediately repassed to the calling program. - ier = 10 - nk1 = n-k1 - if(x.lt.t(k1) .or. x.gt.t(nk1+1)) go to 300 -c search for knot interval t(l) <= x < t(l+1) - l = k1 - 100 if(x.lt.t(l+1) .or. l.eq.nk1) go to 200 - l = l+1 - go to 100 - 200 if(t(l).ge.t(l+1)) go to 300 - ier = 0 -c calculate the derivatives. - call fpader(t,n,c,k1,x,l,d) - 300 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/spgrid.f =================================================================== --- branches/Interpolate1D/fitpack/spgrid.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/spgrid.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,501 +0,0 @@ - subroutine spgrid(iopt,ider,mu,u,mv,v,r,r0,r1,s,nuest,nvest, - * nu,tu,nv,tv,c,fp,wrk,lwrk,iwrk,kwrk,ier) -c given the function values r(i,j) on the latitude-longitude grid -c (u(i),v(j)), i=1,...,mu ; j=1,...,mv , spgrid determines a smooth -c bicubic spline approximation on the rectangular domain 0<=u<=pi, -c vb<=v<=ve (vb = v(1), ve=vb+2*pi). -c this approximation s(u,v) will satisfy the properties -c -c (1) s(0,v) = s(0,0) = dr(1) -c -c d s(0,v) d s(0,0) d s(0,pi/2) -c (2) -------- = cos(v)* -------- + sin(v)* ----------- -c d u d u d u -c -c = cos(v)*dr(2)+sin(v)*dr(3) -c vb <= v <= ve -c (3) s(pi,v) = s(pi,0) = dr(4) -c -c d s(pi,v) d s(pi,0) d s(pi,pi/2) -c (4) -------- = cos(v)* --------- + sin(v)* ------------ -c d u d u d u -c -c = cos(v)*dr(5)+sin(v)*dr(6) -c -c and will be periodic in the variable v, i.e. -c -c j j -c d s(u,vb) d s(u,ve) -c (5) --------- = --------- 0 <=u<= pi , j=0,1,2 -c j j -c d v d v -c -c the number of knots of s(u,v) and their position tu(i),i=1,2,...,nu; -c tv(j),j=1,2,...,nv, is chosen automatically by the routine. the -c smoothness of s(u,v) is achieved by minimalizing the discontinuity -c jumps of the derivatives of the spline at the knots. the amount of -c smoothness of s(u,v) is determined by the condition that -c fp=sumi=1,mu(sumj=1,mv((r(i,j)-s(u(i),v(j)))**2))+(r0-s(0,v))**2 -c + (r1-s(pi,v))**2 <= s, with s a given non-negative constant. -c the fit s(u,v) is given in its b-spline representation and can be -c evaluated by means of routine bispev -c -c calling sequence: -c call spgrid(iopt,ider,mu,u,mv,v,r,r0,r1,s,nuest,nvest,nu,tu, -c * ,nv,tv,c,fp,wrk,lwrk,iwrk,kwrk,ier) -c -c parameters: -c iopt : integer array of dimension 3, specifying different options. -c unchanged on exit. -c iopt(1):on entry iopt(1) must specify whether a least-squares spline -c (iopt(1)=-1) or a smoothing spline (iopt(1)=0 or 1) must be -c determined. -c if iopt(1)=0 the routine will start with an initial set of -c knots tu(i)=0,tu(i+4)=pi,i=1,...,4;tv(i)=v(1)+(i-4)*2*pi, -c i=1,...,8. -c if iopt(1)=1 the routine will continue with the set of knots -c found at the last call of the routine. -c attention: a call with iopt(1)=1 must always be immediately -c preceded by another call with iopt(1) = 1 or iopt(1) = 0. -c iopt(2):on entry iopt(2) must specify the requested order of conti- -c nuity at the pole u=0. -c if iopt(2)=0 only condition (1) must be fulfilled and -c if iopt(2)=1 conditions (1)+(2) must be fulfilled. -c iopt(3):on entry iopt(3) must specify the requested order of conti- -c nuity at the pole u=pi. -c if iopt(3)=0 only condition (3) must be fulfilled and -c if iopt(3)=1 conditions (3)+(4) must be fulfilled. -c ider : integer array of dimension 4, specifying different options. -c unchanged on exit. -c ider(1):on entry ider(1) must specify whether (ider(1)=0 or 1) or not -c (ider(1)=-1) there is a data value r0 at the pole u=0. -c if ider(1)=1, r0 will be considered to be the right function -c value, and it will be fitted exactly (s(0,v)=r0). -c if ider(1)=0, r0 will be considered to be a data value just -c like the other data values r(i,j). -c ider(2):on entry ider(2) must specify whether (ider(2)=1) or not -c (ider(2)=0) the approximation has vanishing derivatives -c dr(2) and dr(3) at the pole u=0 (in case iopt(2)=1) -c ider(3):on entry ider(3) must specify whether (ider(3)=0 or 1) or not -c (ider(3)=-1) there is a data value r1 at the pole u=pi. -c if ider(3)=1, r1 will be considered to be the right function -c value, and it will be fitted exactly (s(pi,v)=r1). -c if ider(3)=0, r1 will be considered to be a data value just -c like the other data values r(i,j). -c ider(4):on entry ider(4) must specify whether (ider(4)=1) or not -c (ider(4)=0) the approximation has vanishing derivatives -c dr(5) and dr(6) at the pole u=pi (in case iopt(3)=1) -c mu : integer. on entry mu must specify the number of grid points -c along the u-axis. unchanged on exit. -c mu >= 1, mu >=mumin=4-i0-i1-ider(2)-ider(4) with -c i0=min(1,ider(1)+1), i1=min(1,ider(3)+1) -c u : real array of dimension at least (mu). before entry, u(i) -c must be set to the u-co-ordinate of the i-th grid point -c along the u-axis, for i=1,2,...,mu. these values must be -c supplied in strictly ascending order. unchanged on exit. -c 0 < u(i) < pi. -c mv : integer. on entry mv must specify the number of grid points -c along the v-axis. mv > 3 . unchanged on exit. -c v : real array of dimension at least (mv). before entry, v(j) -c must be set to the v-co-ordinate of the j-th grid point -c along the v-axis, for j=1,2,...,mv. these values must be -c supplied in strictly ascending order. unchanged on exit. -c -pi <= v(1) < pi , v(mv) < v(1)+2*pi. -c r : real array of dimension at least (mu*mv). -c before entry, r(mv*(i-1)+j) must be set to the data value at -c the grid point (u(i),v(j)) for i=1,...,mu and j=1,...,mv. -c unchanged on exit. -c r0 : real value. on entry (if ider(1) >=0 ) r0 must specify the -c data value at the pole u=0. unchanged on exit. -c r1 : real value. on entry (if ider(1) >=0 ) r1 must specify the -c data value at the pole u=pi. unchanged on exit. -c s : real. on entry (if iopt(1)>=0) s must specify the smoothing -c factor. s >=0. unchanged on exit. -c for advice on the choice of s see further comments -c nuest : integer. unchanged on exit. -c nvest : integer. unchanged on exit. -c on entry, nuest and nvest must specify an upper bound for the -c number of knots required in the u- and v-directions respect. -c these numbers will also determine the storage space needed by -c the routine. nuest >= 8, nvest >= 8. -c in most practical situation nuest = mu/2, nvest=mv/2, will -c be sufficient. always large enough are nuest=mu+6+iopt(2)+ -c iopt(3), nvest = mv+7, the number of knots needed for -c interpolation (s=0). see also further comments. -c nu : integer. -c unless ier=10 (in case iopt(1)>=0), nu will contain the total -c number of knots with respect to the u-variable, of the spline -c approximation returned. if the computation mode iopt(1)=1 is -c used, the value of nu should be left unchanged between sub- -c sequent calls. in case iopt(1)=-1, the value of nu should be -c specified on entry. -c tu : real array of dimension at least (nuest). -c on succesful exit, this array will contain the knots of the -c spline with respect to the u-variable, i.e. the position of -c the interior knots tu(5),...,tu(nu-4) as well as the position -c of the additional knots tu(1)=...=tu(4)=0 and tu(nu-3)=...= -c tu(nu)=pi needed for the b-spline representation. -c if the computation mode iopt(1)=1 is used,the values of tu(1) -c ...,tu(nu) should be left unchanged between subsequent calls. -c if the computation mode iopt(1)=-1 is used, the values tu(5), -c ...tu(nu-4) must be supplied by the user, before entry. -c see also the restrictions (ier=10). -c nv : integer. -c unless ier=10 (in case iopt(1)>=0), nv will contain the total -c number of knots with respect to the v-variable, of the spline -c approximation returned. if the computation mode iopt(1)=1 is -c used, the value of nv should be left unchanged between sub- -c sequent calls. in case iopt(1) = -1, the value of nv should -c be specified on entry. -c tv : real array of dimension at least (nvest). -c on succesful exit, this array will contain the knots of the -c spline with respect to the v-variable, i.e. the position of -c the interior knots tv(5),...,tv(nv-4) as well as the position -c of the additional knots tv(1),...,tv(4) and tv(nv-3),..., -c tv(nv) needed for the b-spline representation. -c if the computation mode iopt(1)=1 is used,the values of tv(1) -c ...,tv(nv) should be left unchanged between subsequent calls. -c if the computation mode iopt(1)=-1 is used, the values tv(5), -c ...tv(nv-4) must be supplied by the user, before entry. -c see also the restrictions (ier=10). -c c : real array of dimension at least (nuest-4)*(nvest-4). -c on succesful exit, c contains the coefficients of the spline -c approximation s(u,v) -c fp : real. unless ier=10, fp contains the sum of squared -c residuals of the spline approximation returned. -c wrk : real array of dimension (lwrk). used as workspace. -c if the computation mode iopt(1)=1 is used the values of -c wrk(1),..,wrk(12) should be left unchanged between subsequent -c calls. -c lwrk : integer. on entry lwrk must specify the actual dimension of -c the array wrk as declared in the calling (sub)program. -c lwrk must not be too small. -c lwrk >= 12+nuest*(mv+nvest+3)+nvest*24+4*mu+8*mv+q -c where q is the larger of (mv+nvest) and nuest. -c iwrk : integer array of dimension (kwrk). used as workspace. -c if the computation mode iopt(1)=1 is used the values of -c iwrk(1),.,iwrk(5) should be left unchanged between subsequent -c calls. -c kwrk : integer. on entry kwrk must specify the actual dimension of -c the array iwrk as declared in the calling (sub)program. -c kwrk >= 5+mu+mv+nuest+nvest. -c ier : integer. unless the routine detects an error, ier contains a -c non-positive value on exit, i.e. -c ier=0 : normal return. the spline returned has a residual sum of -c squares fp such that abs(fp-s)/s <= tol with tol a relat- -c ive tolerance set to 0.001 by the program. -c ier=-1 : normal return. the spline returned is an interpolating -c spline (fp=0). -c ier=-2 : normal return. the spline returned is the least-squares -c constrained polynomial. in this extreme case fp gives the -c upper bound for the smoothing factor s. -c ier=1 : error. the required storage space exceeds the available -c storage space, as specified by the parameters nuest and -c nvest. -c probably causes : nuest or nvest too small. if these param- -c eters are already large, it may also indicate that s is -c too small -c the approximation returned is the least-squares spline -c according to the current set of knots. the parameter fp -c gives the corresponding sum of squared residuals (fp>s). -c ier=2 : error. a theoretically impossible result was found during -c the iteration proces for finding a smoothing spline with -c fp = s. probably causes : s too small. -c there is an approximation returned but the corresponding -c sum of squared residuals does not satisfy the condition -c abs(fp-s)/s < tol. -c ier=3 : error. the maximal number of iterations maxit (set to 20 -c by the program) allowed for finding a smoothing spline -c with fp=s has been reached. probably causes : s too small -c there is an approximation returned but the corresponding -c sum of squared residuals does not satisfy the condition -c abs(fp-s)/s < tol. -c ier=10 : error. on entry, the input data are controlled on validity -c the following restrictions must be satisfied. -c -1<=iopt(1)<=1, 0<=iopt(2)<=1, 0<=iopt(3)<=1, -c -1<=ider(1)<=1, 0<=ider(2)<=1, ider(2)=0 if iopt(2)=0. -c -1<=ider(3)<=1, 0<=ider(4)<=1, ider(4)=0 if iopt(3)=0. -c mu >= mumin (see above), mv >= 4, nuest >=8, nvest >= 8, -c kwrk>=5+mu+mv+nuest+nvest, -c lwrk >= 12+nuest*(mv+nvest+3)+nvest*24+4*mu+8*mv+ -c max(nuest,mv+nvest) -c 0< u(i-1)=0: s>=0 -c if s=0: nuest>=mu+6+iopt(2)+iopt(3), nvest>=mv+7 -c if one of these conditions is found to be violated,control -c is immediately repassed to the calling program. in that -c case there is no approximation returned. -c -c further comments: -c spgrid does not allow individual weighting of the data-values. -c so, if these were determined to widely different accuracies, then -c perhaps the general data set routine sphere should rather be used -c in spite of efficiency. -c by means of the parameter s, the user can control the tradeoff -c between closeness of fit and smoothness of fit of the approximation. -c if s is too large, the spline will be too smooth and signal will be -c lost ; if s is too small the spline will pick up too much noise. in -c the extreme cases the program will return an interpolating spline if -c s=0 and the constrained least-squares polynomial(degrees 3,0)if s is -c very large. between these extremes, a properly chosen s will result -c in a good compromise between closeness of fit and smoothness of fit. -c to decide whether an approximation, corresponding to a certain s is -c satisfactory the user is highly recommended to inspect the fits -c graphically. -c recommended values for s depend on the accuracy of the data values. -c if the user has an idea of the statistical errors on the data, he -c can also find a proper estimate for s. for, by assuming that, if he -c specifies the right s, spgrid will return a spline s(u,v) which -c exactly reproduces the function underlying the data he can evaluate -c the sum((r(i,j)-s(u(i),v(j)))**2) to find a good estimate for this s -c for example, if he knows that the statistical errors on his r(i,j)- -c values is not greater than 0.1, he may expect that a good s should -c have a value not larger than mu*mv*(0.1)**2. -c if nothing is known about the statistical error in r(i,j), s must -c be determined by trial and error, taking account of the comments -c above. the best is then to start with a very large value of s (to -c determine the least-squares polynomial and the corresponding upper -c bound fp0 for s) and then to progressively decrease the value of s -c ( say by a factor 10 in the beginning, i.e. s=fp0/10,fp0/100,... -c and more carefully as the approximation shows more detail) to -c obtain closer fits. -c to economize the search for a good s-value the program provides with -c different modes of computation. at the first call of the routine, or -c whenever he wants to restart with the initial set of knots the user -c must set iopt(1)=0. -c if iopt(1) = 1 the program will continue with the knots found at -c the last call of the routine. this will save a lot of computation -c time if spgrid is called repeatedly for different values of s. -c the number of knots of the spline returned and their location will -c depend on the value of s and on the complexity of the shape of the -c function underlying the data. if the computation mode iopt(1) = 1 -c is used, the knots returned may also depend on the s-values at -c previous calls (if these were smaller). therefore, if after a number -c of trials with different s-values and iopt(1)=1,the user can finally -c accept a fit as satisfactory, it may be worthwhile for him to call -c spgrid once more with the chosen value for s but now with iopt(1)=0. -c indeed, spgrid may then return an approximation of the same quality -c of fit but with fewer knots and therefore better if data reduction -c is also an important objective for the user. -c the number of knots may also depend on the upper bounds nuest and -c nvest. indeed, if at a certain stage in spgrid the number of knots -c in one direction (say nu) has reached the value of its upper bound -c (nuest), then from that moment on all subsequent knots are added -c in the other (v) direction. this may indicate that the value of -c nuest is too small. on the other hand, it gives the user the option -c of limiting the number of knots the routine locates in any direction -c for example, by setting nuest=8 (the lowest allowable value for -c nuest), the user can indicate that he wants an approximation which -c is a simple cubic polynomial in the variable u. -c -c other subroutines required: -c fpspgr,fpchec,fpchep,fpknot,fpopsp,fprati,fpgrsp,fpsysy,fpback, -c fpbacp,fpbspl,fpcyt1,fpcyt2,fpdisc,fpgivs,fprota -c -c references: -c dierckx p. : fast algorithms for smoothing data over a disc or a -c sphere using tensor product splines, in "algorithms -c for approximation", ed. j.c.mason and m.g.cox, -c clarendon press oxford, 1987, pp. 51-65 -c dierckx p. : fast algorithms for smoothing data over a disc or a -c sphere using tensor product splines, report tw73, dept. -c computer science,k.u.leuven, 1985. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author: -c p.dierckx -c dept. computer science, k.u. leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c creation date : july 1985 -c latest update : march 1989 -c -c .. -c ..scalar arguments.. - real*8 r0,r1,s,fp - integer mu,mv,nuest,nvest,nu,nv,lwrk,kwrk,ier -c ..array arguments.. - integer iopt(3),ider(4),iwrk(kwrk) - real*8 u(mu),v(mv),r(mu*mv),c((nuest-4)*(nvest-4)),tu(nuest), - * tv(nvest),wrk(lwrk) -c ..local scalars.. - real*8 per,pi,tol,uu,ve,rmax,rmin,one,half,rn,rb,re - integer i,i1,i2,j,jwrk,j1,j2,kndu,kndv,knru,knrv,kwest,l, - * ldr,lfpu,lfpv,lwest,lww,m,maxit,mumin,muu,nc -c ..function references.. - real*8 datan2 - integer max0 -c ..subroutine references.. -c fpchec,fpchep,fpspgr -c .. -c set constants - one = 1d0 - half = 0.5e0 - pi = datan2(0d0,-one) - per = pi+pi - ve = v(1)+per -c we set up the parameters tol and maxit. - maxit = 20 - tol = 0.1e-02 -c before starting computations, a data check is made. if the input data -c are invalid, control is immediately repassed to the calling program. - ier = 10 - if(iopt(1).lt.(-1) .or. iopt(1).gt.1) go to 200 - if(iopt(2).lt.0 .or. iopt(2).gt.1) go to 200 - if(iopt(3).lt.0 .or. iopt(3).gt.1) go to 200 - if(ider(1).lt.(-1) .or. ider(1).gt.1) go to 200 - if(ider(2).lt.0 .or. ider(2).gt.1) go to 200 - if(ider(2).eq.1 .and. iopt(2).eq.0) go to 200 - if(ider(3).lt.(-1) .or. ider(3).gt.1) go to 200 - if(ider(4).lt.0 .or. ider(4).gt.1) go to 200 - if(ider(4).eq.1 .and. iopt(3).eq.0) go to 200 - mumin = 4 - if(ider(1).ge.0) mumin = mumin-1 - if(iopt(2).eq.1 .and. ider(2).eq.1) mumin = mumin-1 - if(ider(3).ge.0) mumin = mumin-1 - if(iopt(3).eq.1 .and. ider(4).eq.1) mumin = mumin-1 - if(mumin.eq.0) mumin = 1 - if(mu.lt.mumin .or. mv.lt.4) go to 200 - if(nuest.lt.8 .or. nvest.lt.8) go to 200 - m = mu*mv - nc = (nuest-4)*(nvest-4) - lwest = 12+nuest*(mv+nvest+3)+24*nvest+4*mu+8*mv+ - * max0(nuest,mv+nvest) - kwest = 5+mu+mv+nuest+nvest - if(lwrk.lt.lwest .or. kwrk.lt.kwest) go to 200 - if(u(1).le.0. .or. u(mu).ge.pi) go to 200 - if(mu.eq.1) go to 30 - do 20 i=2,mu - if(u(i-1).ge.u(i)) go to 200 - 20 continue - 30 if(v(1).lt. (-pi) .or. v(1).ge.pi ) go to 200 - if(v(mv).ge.v(1)+per) go to 200 - do 40 i=2,mv - if(v(i-1).ge.v(i)) go to 200 - 40 continue - if(iopt(1).gt.0) go to 140 -c if not given, we compute an estimate for r0. - rn = mv - if(ider(1).lt.0) go to 45 - rb = r0 - go to 55 - 45 rb = 0. - do 50 i=1,mv - rb = rb+r(i) - 50 continue - rb = rb/rn -c if not given, we compute an estimate for r1. - 55 if(ider(3).lt.0) go to 60 - re = r1 - go to 70 - 60 re = 0. - j = m - do 65 i=1,mv - re = re+r(j) - j = j-1 - 65 continue - re = re/rn -c we determine the range of r-values. - 70 rmin = rb - rmax = re - do 80 i=1,m - if(r(i).lt.rmin) rmin = r(i) - if(r(i).gt.rmax) rmax = r(i) - 80 continue - wrk(5) = rb - wrk(6) = 0. - wrk(7) = 0. - wrk(8) = re - wrk(9) = 0. - wrk(10) = 0. - wrk(11) = rmax -rmin - wrk(12) = wrk(11) - iwrk(4) = mu - iwrk(5) = mu - if(iopt(1).eq.0) go to 140 - if(nu.lt.8 .or. nu.gt.nuest) go to 200 - if(nv.lt.11 .or. nv.gt.nvest) go to 200 - j = nu - do 90 i=1,4 - tu(i) = 0. - tu(j) = pi - j = j-1 - 90 continue - l = 13 - wrk(l) = 0. - if(iopt(2).eq.0) go to 100 - l = l+1 - uu = u(1) - if(uu.gt.tu(5)) uu = tu(5) - wrk(l) = uu*half - 100 do 110 i=1,mu - l = l+1 - wrk(l) = u(i) - 110 continue - if(iopt(3).eq.0) go to 120 - l = l+1 - uu = u(mu) - if(uu.lt.tu(nu-4)) uu = tu(nu-4) - wrk(l) = uu+(pi-uu)*half - 120 l = l+1 - wrk(l) = pi - muu = l-12 - call fpchec(wrk(13),muu,tu,nu,3,ier) - if(ier.ne.0) go to 200 - j1 = 4 - tv(j1) = v(1) - i1 = nv-3 - tv(i1) = ve - j2 = j1 - i2 = i1 - do 130 i=1,3 - i1 = i1+1 - i2 = i2-1 - j1 = j1+1 - j2 = j2-1 - tv(j2) = tv(i2)-per - tv(i1) = tv(j1)+per - 130 continue - l = 13 - do 135 i=1,mv - wrk(l) = v(i) - l = l+1 - 135 continue - wrk(l) = ve - call fpchep(wrk(13),mv+1,tv,nv,3,ier) - if (ier.eq.0) go to 150 - go to 200 - 140 if(s.lt.0.) go to 200 - if(s.eq.0. .and. (nuest.lt.(mu+6+iopt(2)+iopt(3)) .or. - * nvest.lt.(mv+7)) ) go to 200 -c we partition the working space and determine the spline approximation - 150 ldr = 5 - lfpu = 13 - lfpv = lfpu+nuest - lww = lfpv+nvest - jwrk = lwrk-12-nuest-nvest - knru = 6 - knrv = knru+mu - kndu = knrv+mv - kndv = kndu+nuest - call fpspgr(iopt,ider,u,mu,v,mv,r,m,rb,re,s,nuest,nvest,tol,maxit, - * - * nc,nu,tu,nv,tv,c,fp,wrk(1),wrk(2),wrk(3),wrk(4),wrk(lfpu), - * wrk(lfpv),wrk(ldr),wrk(11),iwrk(1),iwrk(2),iwrk(3),iwrk(4), - * iwrk(5),iwrk(knru),iwrk(knrv),iwrk(kndu),iwrk(kndv),wrk(lww), - * jwrk,ier) - 200 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/sphere.f =================================================================== --- branches/Interpolate1D/fitpack/sphere.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/sphere.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,404 +0,0 @@ - subroutine sphere(iopt,m,teta,phi,r,w,s,ntest,npest,eps, - * nt,tt,np,tp,c,fp,wrk1,lwrk1,wrk2,lwrk2,iwrk,kwrk,ier) -c subroutine sphere determines a smooth bicubic spherical spline -c approximation s(teta,phi), 0 <= teta <= pi ; 0 <= phi <= 2*pi -c to a given set of data points (teta(i),phi(i),r(i)),i=1,2,...,m. -c such a spline has the following specific properties -c -c (1) s(0,phi) = constant 0 <=phi<= 2*pi. -c -c (2) s(pi,phi) = constant 0 <=phi<= 2*pi -c -c j j -c d s(teta,0) d s(teta,2*pi) -c (3) ----------- = ------------ 0 <=teta<=pi, j=0,1,2 -c j j -c d phi d phi -c -c d s(0,phi) d s(0,0) d s(0,pi/2) -c (4) ---------- = -------- *cos(phi) + ----------- *sin(phi) -c d teta d teta d teta -c -c d s(pi,phi) d s(pi,0) d s(pi,pi/2) -c (5) ----------- = ---------*cos(phi) + ------------*sin(phi) -c d teta d teta d teta -c -c if iopt =-1 sphere calculates a weighted least-squares spherical -c spline according to a given set of knots in teta- and phi- direction. -c if iopt >=0, the number of knots in each direction and their position -c tt(j),j=1,2,...,nt ; tp(j),j=1,2,...,np are chosen automatically by -c the routine. the smoothness of s(teta,phi) is then achieved by mini- -c malizing the discontinuity jumps of the derivatives of the spline -c at the knots. the amount of smoothness of s(teta,phi) is determined -c by the condition that fp = sum((w(i)*(r(i)-s(teta(i),phi(i))))**2) -c be <= s, with s a given non-negative constant. -c the spherical spline is given in the standard b-spline representation -c of bicubic splines and can be evaluated by means of subroutine bispev -c -c calling sequence: -c call sphere(iopt,m,teta,phi,r,w,s,ntest,npest,eps, -c * nt,tt,np,tp,c,fp,wrk1,lwrk1,wrk2,lwrk2,iwrk,kwrk,ier) -c -c parameters: -c iopt : integer flag. on entry iopt must specify whether a weighted -c least-squares spherical spline (iopt=-1) or a smoothing -c spherical spline (iopt=0 or 1) must be determined. -c if iopt=0 the routine will start with an initial set of knots -c tt(i)=0,tt(i+4)=pi,i=1,...,4;tp(i)=0,tp(i+4)=2*pi,i=1,...,4. -c if iopt=1 the routine will continue with the set of knots -c found at the last call of the routine. -c attention: a call with iopt=1 must always be immediately pre- -c ceded by another call with iopt=1 or iopt=0. -c unchanged on exit. -c m : integer. on entry m must specify the number of data points. -c m >= 2. unchanged on exit. -c teta : real array of dimension at least (m). -c phi : real array of dimension at least (m). -c r : real array of dimension at least (m). -c before entry,teta(i),phi(i),r(i) must be set to the spherical -c co-ordinates of the i-th data point, for i=1,...,m.the order -c of the data points is immaterial. unchanged on exit. -c w : real array of dimension at least (m). before entry, w(i) must -c be set to the i-th value in the set of weights. the w(i) must -c be strictly positive. unchanged on exit. -c s : real. on entry (in case iopt>=0) s must specify the smoothing -c factor. s >=0. unchanged on exit. -c for advice on the choice of s see further comments -c ntest : integer. unchanged on exit. -c npest : integer. unchanged on exit. -c on entry, ntest and npest must specify an upper bound for the -c number of knots required in the teta- and phi-directions. -c these numbers will also determine the storage space needed by -c the routine. ntest >= 8, npest >= 8. -c in most practical situation ntest = npest = 8+sqrt(m/2) will -c be sufficient. see also further comments. -c eps : real. -c on entry, eps must specify a threshold for determining the -c effective rank of an over-determined linear system of equat- -c ions. 0 < eps < 1. if the number of decimal digits in the -c computer representation of a real number is q, then 10**(-q) -c is a suitable value for eps in most practical applications. -c unchanged on exit. -c nt : integer. -c unless ier=10 (in case iopt >=0), nt will contain the total -c number of knots with respect to the teta-variable, of the -c spline approximation returned. if the computation mode iopt=1 -c is used, the value of nt should be left unchanged between -c subsequent calls. -c in case iopt=-1, the value of nt should be specified on entry -c tt : real array of dimension at least ntest. -c on succesful exit, this array will contain the knots of the -c spline with respect to the teta-variable, i.e. the position -c of the interior knots tt(5),...,tt(nt-4) as well as the -c position of the additional knots tt(1)=...=tt(4)=0 and -c tt(nt-3)=...=tt(nt)=pi needed for the b-spline representation -c if the computation mode iopt=1 is used, the values of tt(1), -c ...,tt(nt) should be left unchanged between subsequent calls. -c if the computation mode iopt=-1 is used, the values tt(5), -c ...tt(nt-4) must be supplied by the user, before entry. -c see also the restrictions (ier=10). -c np : integer. -c unless ier=10 (in case iopt >=0), np will contain the total -c number of knots with respect to the phi-variable, of the -c spline approximation returned. if the computation mode iopt=1 -c is used, the value of np should be left unchanged between -c subsequent calls. -c in case iopt=-1, the value of np (>=9) should be specified -c on entry. -c tp : real array of dimension at least npest. -c on succesful exit, this array will contain the knots of the -c spline with respect to the phi-variable, i.e. the position of -c the interior knots tp(5),...,tp(np-4) as well as the position -c of the additional knots tp(1),...,tp(4) and tp(np-3),..., -c tp(np) needed for the b-spline representation. -c if the computation mode iopt=1 is used, the values of tp(1), -c ...,tp(np) should be left unchanged between subsequent calls. -c if the computation mode iopt=-1 is used, the values tp(5), -c ...tp(np-4) must be supplied by the user, before entry. -c see also the restrictions (ier=10). -c c : real array of dimension at least (ntest-4)*(npest-4). -c on succesful exit, c contains the coefficients of the spline -c approximation s(teta,phi). -c fp : real. unless ier=10, fp contains the weighted sum of -c squared residuals of the spline approximation returned. -c wrk1 : real array of dimension (lwrk1). used as workspace. -c if the computation mode iopt=1 is used the value of wrk1(1) -c should be left unchanged between subsequent calls. -c on exit wrk1(2),wrk1(3),...,wrk1(1+ncof) will contain the -c values d(i)/max(d(i)),i=1,...,ncof=6+(np-7)*(nt-8) -c with d(i) the i-th diagonal element of the reduced triangular -c matrix for calculating the b-spline coefficients. it includes -c those elements whose square is less than eps,which are treat- -c ed as 0 in the case of presumed rank deficiency (ier<-2). -c lwrk1 : integer. on entry lwrk1 must specify the actual dimension of -c the array wrk1 as declared in the calling (sub)program. -c lwrk1 must not be too small. let -c u = ntest-7, v = npest-7, then -c lwrk1 >= 185+52*v+10*u+14*u*v+8*(u-1)*v**2+8*m -c wrk2 : real array of dimension (lwrk2). used as workspace, but -c only in the case a rank deficient system is encountered. -c lwrk2 : integer. on entry lwrk2 must specify the actual dimension of -c the array wrk2 as declared in the calling (sub)program. -c lwrk2 > 0 . a save upper bound for lwrk2 = 48+21*v+7*u*v+ -c 4*(u-1)*v**2 where u,v are as above. if there are enough data -c points, scattered uniformly over the approximation domain -c and if the smoothing factor s is not too small, there is a -c good chance that this extra workspace is not needed. a lot -c of memory might therefore be saved by setting lwrk2=1. -c (see also ier > 10) -c iwrk : integer array of dimension (kwrk). used as workspace. -c kwrk : integer. on entry kwrk must specify the actual dimension of -c the array iwrk as declared in the calling (sub)program. -c kwrk >= m+(ntest-7)*(npest-7). -c ier : integer. unless the routine detects an error, ier contains a -c non-positive value on exit, i.e. -c ier=0 : normal return. the spline returned has a residual sum of -c squares fp such that abs(fp-s)/s <= tol with tol a relat- -c ive tolerance set to 0.001 by the program. -c ier=-1 : normal return. the spline returned is a spherical -c interpolating spline (fp=0). -c ier=-2 : normal return. the spline returned is the weighted least- -c squares constrained polynomial . in this extreme case -c fp gives the upper bound for the smoothing factor s. -c ier<-2 : warning. the coefficients of the spline returned have been -c computed as the minimal norm least-squares solution of a -c (numerically) rank deficient system. (-ier) gives the rank. -c especially if the rank deficiency which can be computed as -c 6+(nt-8)*(np-7)+ier, is large the results may be inaccurate -c they could also seriously depend on the value of eps. -c ier=1 : error. the required storage space exceeds the available -c storage space, as specified by the parameters ntest and -c npest. -c probably causes : ntest or npest too small. if these param- -c eters are already large, it may also indicate that s is -c too small -c the approximation returned is the weighted least-squares -c spherical spline according to the current set of knots. -c the parameter fp gives the corresponding weighted sum of -c squared residuals (fp>s). -c ier=2 : error. a theoretically impossible result was found during -c the iteration proces for finding a smoothing spline with -c fp = s. probably causes : s too small or badly chosen eps. -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=3 : error. the maximal number of iterations maxit (set to 20 -c by the program) allowed for finding a smoothing spline -c with fp=s has been reached. probably causes : s too small -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=4 : error. no more knots can be added because the dimension -c of the spherical spline 6+(nt-8)*(np-7) already exceeds -c the number of data points m. -c probably causes : either s or m too small. -c the approximation returned is the weighted least-squares -c spherical spline according to the current set of knots. -c the parameter fp gives the corresponding weighted sum of -c squared residuals (fp>s). -c ier=5 : error. no more knots can be added because the additional -c knot would (quasi) coincide with an old one. -c probably causes : s too small or too large a weight to an -c inaccurate data point. -c the approximation returned is the weighted least-squares -c spherical spline according to the current set of knots. -c the parameter fp gives the corresponding weighted sum of -c squared residuals (fp>s). -c ier=10 : error. on entry, the input data are controlled on validity -c the following restrictions must be satisfied. -c -1<=iopt<=1, m>=2, ntest>=8 ,npest >=8, 00, i=1,...,m -c lwrk1 >= 185+52*v+10*u+14*u*v+8*(u-1)*v**2+8*m -c kwrk >= m+(ntest-7)*(npest-7) -c if iopt=-1: 8<=nt<=ntest , 9<=np<=npest -c 0=0: s>=0 -c if one of these conditions is found to be violated,control -c is immediately repassed to the calling program. in that -c case there is no approximation returned. -c ier>10 : error. lwrk2 is too small, i.e. there is not enough work- -c space for computing the minimal least-squares solution of -c a rank deficient system of linear equations. ier gives the -c requested value for lwrk2. there is no approximation re- -c turned but, having saved the information contained in nt, -c np,tt,tp,wrk1, and having adjusted the value of lwrk2 and -c the dimension of the array wrk2 accordingly, the user can -c continue at the point the program was left, by calling -c sphere with iopt=1. -c -c further comments: -c by means of the parameter s, the user can control the tradeoff -c between closeness of fit and smoothness of fit of the approximation. -c if s is too large, the spline will be too smooth and signal will be -c lost ; if s is too small the spline will pick up too much noise. in -c the extreme cases the program will return an interpolating spline if -c s=0 and the constrained weighted least-squares polynomial if s is -c very large. between these extremes, a properly chosen s will result -c in a good compromise between closeness of fit and smoothness of fit. -c to decide whether an approximation, corresponding to a certain s is -c satisfactory the user is highly recommended to inspect the fits -c graphically. -c recommended values for s depend on the weights w(i). if these are -c taken as 1/d(i) with d(i) an estimate of the standard deviation of -c r(i), a good s-value should be found in the range (m-sqrt(2*m),m+ -c sqrt(2*m)). if nothing is known about the statistical error in r(i) -c each w(i) can be set equal to one and s determined by trial and -c error, taking account of the comments above. the best is then to -c start with a very large value of s ( to determine the least-squares -c polynomial and the corresponding upper bound fp0 for s) and then to -c progressively decrease the value of s ( say by a factor 10 in the -c beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the -c approximation shows more detail) to obtain closer fits. -c to choose s very small is strongly discouraged. this considerably -c increases computation time and memory requirements. it may also -c cause rank-deficiency (ier<-2) and endager numerical stability. -c to economize the search for a good s-value the program provides with -c different modes of computation. at the first call of the routine, or -c whenever he wants to restart with the initial set of knots the user -c must set iopt=0. -c if iopt=1 the program will continue with the set of knots found at -c the last call of the routine. this will save a lot of computation -c time if sphere is called repeatedly for different values of s. -c the number of knots of the spline returned and their location will -c depend on the value of s and on the complexity of the shape of the -c function underlying the data. if the computation mode iopt=1 -c is used, the knots returned may also depend on the s-values at -c previous calls (if these were smaller). therefore, if after a number -c of trials with different s-values and iopt=1, the user can finally -c accept a fit as satisfactory, it may be worthwhile for him to call -c sphere once more with the selected value for s but now with iopt=0. -c indeed, sphere may then return an approximation of the same quality -c of fit but with fewer knots and therefore better if data reduction -c is also an important objective for the user. -c the number of knots may also depend on the upper bounds ntest and -c npest. indeed, if at a certain stage in sphere the number of knots -c in one direction (say nt) has reached the value of its upper bound -c (ntest), then from that moment on all subsequent knots are added -c in the other (phi) direction. this may indicate that the value of -c ntest is too small. on the other hand, it gives the user the option -c of limiting the number of knots the routine locates in any direction -c for example, by setting ntest=8 (the lowest allowable value for -c ntest), the user can indicate that he wants an approximation which -c is a cubic polynomial in the variable teta. -c -c other subroutines required: -c fpback,fpbspl,fpsphe,fpdisc,fpgivs,fprank,fprati,fprota,fporde, -c fprpsp -c -c references: -c dierckx p. : algorithms for smoothing data on the sphere with tensor -c product splines, computing 32 (1984) 319-342. -c dierckx p. : algorithms for smoothing data on the sphere with tensor -c product splines, report tw62, dept. computer science, -c k.u.leuven, 1983. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author: -c p.dierckx -c dept. computer science, k.u. leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c creation date : july 1983 -c latest update : march 1989 -c -c .. -c ..scalar arguments.. - real*8 s,eps,fp - integer iopt,m,ntest,npest,nt,np,lwrk1,lwrk2,kwrk,ier -c ..array arguments.. - real*8 teta(m),phi(m),r(m),w(m),tt(ntest),tp(npest), - * c((ntest-4)*(npest-4)),wrk1(lwrk1),wrk2(lwrk2) - integer iwrk(kwrk) -c ..local scalars.. - real*8 tol,pi,pi2,one - integer i,ib1,ib3,ki,kn,kwest,la,lbt,lcc,lcs,lro,j - * lbp,lco,lf,lff,lfp,lh,lq,lst,lsp,lwest,maxit,ncest,ncc,ntt, - * npp,nreg,nrint,ncof,nt4,np4 -c ..function references.. - real*8 atan -c ..subroutine references.. -c fpsphe -c .. -c set constants - one = 0.1e+01 -c we set up the parameters tol and maxit. - maxit = 20 - tol = 0.1e-02 -c before starting computations a data check is made. if the input data -c are invalid,control is immediately repassed to the calling program. - ier = 10 - if(eps.le.0. .or. eps.ge.1.) go to 80 - if(iopt.lt.(-1) .or. iopt.gt.1) go to 80 - if(m.lt.2) go to 80 - if(ntest.lt.8 .or. npest.lt.8) go to 80 - nt4 = ntest-4 - np4 = npest-4 - ncest = nt4*np4 - ntt = ntest-7 - npp = npest-7 - ncc = 6+npp*(ntt-1) - nrint = ntt+npp - nreg = ntt*npp - ncof = 6+3*npp - ib1 = 4*npp - ib3 = ib1+3 - if(ncof.gt.ib1) ib1 = ncof - if(ncof.gt.ib3) ib3 = ncof - lwest = 185+52*npp+10*ntt+14*ntt*npp+8*(m+(ntt-1)*npp**2) - kwest = m+nreg - if(lwrk1.lt.lwest .or. kwrk.lt.kwest) go to 80 - if(iopt.gt.0) go to 60 - pi = atan(one)*4 - pi2 = pi+pi - do 20 i=1,m - if(w(i).le.0.) go to 80 - if(teta(i).lt.0. .or. teta(i).gt.pi) go to 80 - if(phi(i) .lt.0. .or. phi(i).gt.pi2) go to 80 - 20 continue - if(iopt.eq.0) go to 60 - ntt = nt-8 - if(ntt.lt.0 .or. nt.gt.ntest) go to 80 - if(ntt.eq.0) go to 40 - tt(4) = 0. - do 30 i=1,ntt - j = i+4 - if(tt(j).le.tt(j-1) .or. tt(j).ge.pi) go to 80 - 30 continue - 40 npp = np-8 - if(npp.lt.1 .or. np.gt.npest) go to 80 - tp(4) = 0. - do 50 i=1,npp - j = i+4 - if(tp(j).le.tp(j-1) .or. tp(j).ge.pi2) go to 80 - 50 continue - go to 70 - 60 if(s.lt.0.) go to 80 - 70 ier = 0 -c we partition the working space and determine the spline approximation - kn = 1 - ki = kn+m - lq = 2 - la = lq+ncc*ib3 - lf = la+ncc*ib1 - lff = lf+ncc - lfp = lff+ncest - lco = lfp+nrint - lh = lco+nrint - lbt = lh+ib3 - lbp = lbt+5*ntest - lro = lbp+5*npest - lcc = lro+npest - lcs = lcc+npest - lst = lcs+npest - lsp = lst+m*4 - call fpsphe(iopt,m,teta,phi,r,w,s,ntest,npest,eps,tol,maxit, - * ib1,ib3,ncest,ncc,nrint,nreg,nt,tt,np,tp,c,fp,wrk1(1),wrk1(lfp), - * wrk1(lco),wrk1(lf),wrk1(lff),wrk1(lro),wrk1(lcc),wrk1(lcs), - * wrk1(la),wrk1(lq),wrk1(lbt),wrk1(lbp),wrk1(lst),wrk1(lsp), - * wrk1(lh),iwrk(ki),iwrk(kn),wrk2,lwrk2,ier) - 80 return - end - Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/splder.f =================================================================== --- branches/Interpolate1D/fitpack/splder.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/splder.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,162 +0,0 @@ - subroutine splder(t,n,c,k,nu,x,y,m,wrk,ier) -c subroutine splder evaluates in a number of points x(i),i=1,2,...,m -c the derivative of order nu of a spline s(x) of degree k,given in -c its b-spline representation. -c -c calling sequence: -c call splder(t,n,c,k,nu,x,y,m,wrk,ier) -c -c input parameters: -c t : array,length n, which contains the position of the knots. -c n : integer, giving the total number of knots of s(x). -c c : array,length n, which contains the b-spline coefficients. -c k : integer, giving the degree of s(x). -c nu : integer, specifying the order of the derivative. 0<=nu<=k -c x : array,length m, which contains the points where the deriv- -c ative of s(x) must be evaluated. -c m : integer, giving the number of points where the derivative -c of s(x) must be evaluated -c wrk : real array of dimension n. used as working space. -c -c output parameters: -c y : array,length m, giving the value of the derivative of s(x) -c at the different points. -c ier : error flag -c ier = 0 : normal return -c ier =10 : invalid input data (see restrictions) -c -c restrictions: -c 0 <= nu <= k -c m >= 1 -c t(k+1) <= x(i) <= x(i+1) <= t(n-k) , i=1,2,...,m-1. -c -c other subroutines required: fpbspl -c -c references : -c de boor c : on calculating with b-splines, j. approximation theory -c 6 (1972) 50-62. -c cox m.g. : the numerical evaluation of b-splines, j. inst. maths -c applics 10 (1972) 134-149. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author : -c p.dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c latest update : march 1987 -c -c++ pearu: 13 aug 20003 -c++ - disabled cliping x values to interval [min(t),max(t)] -c++ - removed the restriction of the orderness of x values -c++ - fixed initialization of sp to double precision value -c -c ..scalar arguments.. - integer n,k,nu,m,ier -c ..array arguments.. - real*8 t(n),c(n),x(m),y(m),wrk(n) -c ..local scalars.. - integer i,j,kk,k1,k2,l,ll,l1,l2,nk1,nk2,nn - real*8 ak,arg,fac,sp,tb,te -c++.. - integer k3 -c..++ -c ..local arrays .. - real*8 h(6) -c before starting computations a data check is made. if the input data -c are invalid control is immediately repassed to the calling program. - ier = 10 - if(nu.lt.0 .or. nu.gt.k) go to 200 -c-- if(m-1) 200,30,10 -c++.. - if(m.lt.1) go to 200 -c..++ -c-- 10 do 20 i=2,m -c-- if(x(i).lt.x(i-1)) go to 200 -c-- 20 continue - 30 ier = 0 -c fetch tb and te, the boundaries of the approximation interval. - k1 = k+1 - k3 = k1+1 - nk1 = n-k1 - tb = t(k1) - te = t(nk1+1) -c the derivative of order nu of a spline of degree k is a spline of -c degree k-nu,the b-spline coefficients wrk(i) of which can be found -c using the recurrence scheme of de boor. - l = 1 - kk = k - nn = n - do 40 i=1,nk1 - wrk(i) = c(i) - 40 continue - if(nu.eq.0) go to 100 - nk2 = nk1 - do 60 j=1,nu - ak = kk - nk2 = nk2-1 - l1 = l - do 50 i=1,nk2 - l1 = l1+1 - l2 = l1+kk - fac = t(l2)-t(l1) - if(fac.le.0.) go to 50 - wrk(i) = ak*(wrk(i+1)-wrk(i))/fac - 50 continue - l = l+1 - kk = kk-1 - 60 continue - if(kk.ne.0) go to 100 -c if nu=k the derivative is a piecewise constant function - j = 1 - do 90 i=1,m - arg = x(i) -c++.. - 65 if(arg.ge.t(l) .or. l+1.eq.k2) go to 70 - l1 = l - l = l-1 - j = j-1 - go to 65 -c..++ - 70 if(arg.lt.t(l+1) .or. l.eq.nk1) go to 80 - l = l+1 - j = j+1 - go to 70 - 80 y(i) = wrk(j) - 90 continue - go to 200 - 100 l = k1 - l1 = l+1 - k2 = k1-nu -c main loop for the different points. - do 180 i=1,m -c fetch a new x-value arg. - arg = x(i) -c-- if(arg.lt.tb) arg = tb -c-- if(arg.gt.te) arg = te -c search for knot interval t(l) <= arg < t(l+1) -c++.. - 135 if(arg.ge.t(l) .or. l1.eq.k3) go to 140 - l1 = l - l = l-1 - go to 135 -c..++ - 140 if(arg.lt.t(l1) .or. l.eq.nk1) go to 150 - l = l1 - l1 = l+1 - go to 140 -c evaluate the non-zero b-splines of degree k-nu at arg. - 150 call fpbspl(t,n,kk,arg,l,h) -c find the value of the derivative at x=arg. - sp = 0.0d0 - ll = l-k1 - do 160 j=1,k2 - ll = ll+1 - sp = sp+wrk(ll)*h(j) - 160 continue - y(i) = sp - 180 continue - 200 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/splev.f =================================================================== --- branches/Interpolate1D/fitpack/splev.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/splev.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,115 +0,0 @@ - subroutine splev(t,n,c,k,x,y,m,ier) -c subroutine splev evaluates in a number of points x(i),i=1,2,...,m -c a spline s(x) of degree k, given in its b-spline representation. -c -c calling sequence: -c call splev(t,n,c,k,x,y,m,ier) -c -c input parameters: -c t : array,length n, which contains the position of the knots. -c n : integer, giving the total number of knots of s(x). -c c : array,length n, which contains the b-spline coefficients. -c k : integer, giving the degree of s(x). -c x : array,length m, which contains the points where s(x) must -c be evaluated. -c m : integer, giving the number of points where s(x) must be -c evaluated. -c -c output parameter: -c y : array,length m, giving the value of s(x) at the different -c points. -c ier : error flag -c ier = 0 : normal return -c ier =10 : invalid input data (see restrictions) -c -c restrictions: -c m >= 1 -c-- t(k+1) <= x(i) <= x(i+1) <= t(n-k) , i=1,2,...,m-1. -c -c other subroutines required: fpbspl. -c -c references : -c de boor c : on calculating with b-splines, j. approximation theory -c 6 (1972) 50-62. -c cox m.g. : the numerical evaluation of b-splines, j. inst. maths -c applics 10 (1972) 134-149. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author : -c p.dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c latest update : march 1987 -c -c++ pearu: 11 aug 2003 -c++ - disabled cliping x values to interval [min(t),max(t)] -c++ - removed the restriction of the orderness of x values -c++ - fixed initialization of sp to double precision value -c -c ..scalar arguments.. - integer n,k,m,ier -c ..array arguments.. - real*8 t(n),c(n),x(m),y(m) -c ..local scalars.. - integer i,j,k1,l,ll,l1,nk1 -c++.. - integer k2 -c..++ - real*8 arg,sp,tb,te -c ..local array.. - real*8 h(20) -c .. -c before starting computations a data check is made. if the input data -c are invalid control is immediately repassed to the calling program. - ier = 10 -c-- if(m-1) 100,30,10 -c++.. - if(m.lt.1) go to 100 -c..++ -c-- 10 do 20 i=2,m -c-- if(x(i).lt.x(i-1)) go to 100 -c-- 20 continue - 30 ier = 0 -c fetch tb and te, the boundaries of the approximation interval. - k1 = k+1 -c++.. - k2 = k1+1 -c..++ - nk1 = n-k1 - tb = t(k1) - te = t(nk1+1) - l = k1 - l1 = l+1 -c main loop for the different points. - do 80 i=1,m -c fetch a new x-value arg. - arg = x(i) -c-- if(arg.lt.tb) arg = tb -c-- if(arg.gt.te) arg = te -c search for knot interval t(l) <= arg < t(l+1) -c++.. - 35 if(arg.ge.t(l) .or. l1.eq.k2) go to 40 - l1 = l - l = l-1 - go to 35 -c..++ - 40 if(arg.lt.t(l1) .or. l.eq.nk1) go to 50 - l = l1 - l1 = l+1 - go to 40 -c evaluate the non-zero b-splines at arg. - 50 call fpbspl(t,n,k,arg,l,h) -c find the value of s(x) at x=arg. - sp = 0.0d0 - ll = l-k1 - do 60 j=1,k1 - ll = ll+1 - sp = sp+c(ll)*h(j) - 60 continue - y(i) = sp - 80 continue - 100 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/splint.f =================================================================== --- branches/Interpolate1D/fitpack/splint.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/splint.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,58 +0,0 @@ - real*8 function splint(t,n,c,k,a,b,wrk) -c function splint calculates the integral of a spline function s(x) -c of degree k, which is given in its normalized b-spline representation -c -c calling sequence: -c aint = splint(t,n,c,k,a,b,wrk) -c -c input parameters: -c t : array,length n,which contains the position of the knots -c of s(x). -c n : integer, giving the total number of knots of s(x). -c c : array,length n, containing the b-spline coefficients. -c k : integer, giving the degree of s(x). -c a,b : real values, containing the end points of the integration -c interval. s(x) is considered to be identically zero outside -c the interval (t(k+1),t(n-k)). -c -c output parameter: -c aint : real, containing the integral of s(x) between a and b. -c wrk : real array, length n. used as working space -c on output, wrk will contain the integrals of the normalized -c b-splines defined on the set of knots. -c -c other subroutines required: fpintb. -c -c references : -c gaffney p.w. : the calculation of indefinite integrals of b-splines -c j. inst. maths applics 17 (1976) 37-41. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author : -c p.dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c latest update : march 1987 -c -c ..scalar arguments.. - real*8 a,b - integer n,k -c ..array arguments.. - real*8 t(n),c(n),wrk(n) -c ..local scalars.. - integer i,nk1 -c .. - nk1 = n-k-1 -c calculate the integrals wrk(i) of the normalized b-splines -c ni,k+1(x), i=1,2,...nk1. - call fpintb(t,n,wrk,nk1,a,b) -c calculate the integral of s(x). - splint = 0.0d0 - do 10 i=1,nk1 - splint = splint+c(i)*wrk(i) - 10 continue - return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/sproot.f =================================================================== --- branches/Interpolate1D/fitpack/sproot.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/sproot.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,183 +0,0 @@ - subroutine sproot(t,n,c,zero,mest,m,ier) -c subroutine sproot finds the zeros of a cubic spline s(x),which is -c given in its normalized b-spline representation. -c -c calling sequence: -c call sproot(t,n,c,zero,mest,m,ier) -c -c input parameters: -c t : real array,length n, containing the knots of s(x). -c n : integer, containing the number of knots. n>=8 -c c : real array,length n, containing the b-spline coefficients. -c mest : integer, specifying the dimension of array zero. -c -c output parameters: -c zero : real array,lenth mest, containing the zeros of s(x). -c m : integer,giving the number of zeros. -c ier : error flag: -c ier = 0: normal return. -c ier = 1: the number of zeros exceeds mest. -c ier =10: invalid input data (see restrictions). -c -c other subroutines required: fpcuro -c -c restrictions: -c 1) n>= 8. -c 2) t(4) < t(5) < ... < t(n-4) < t(n-3). -c t(1) <= t(2) <= t(3) <= t(4) -c t(n-3) <= t(n-2) <= t(n-1) <= t(n) -c -c author : -c p.dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c latest update : march 1987 -c -c .. -c ..scalar arguments.. - integer n,mest,m,ier -c ..array arguments.. - real*8 t(n),c(n),zero(mest) -c ..local scalars.. - integer i,j,j1,l,n4 - real*8 ah,a0,a1,a2,a3,bh,b0,b1,c1,c2,c3,c4,c5,d4,d5,h1,h2, - * three,two,t1,t2,t3,t4,t5,zz - logical z0,z1,z2,z3,z4,nz0,nz1,nz2,nz3,nz4 -c ..local array.. - real*8 y(3) -c .. -c set some constants - two = 0.2d+01 - three = 0.3d+01 -c before starting computations a data check is made. if the input data -c are invalid, control is immediately repassed to the calling program. - n4 = n-4 - ier = 10 - if(n.lt.8) go to 800 - j = n - do 10 i=1,3 - if(t(i).gt.t(i+1)) go to 800 - if(t(j).lt.t(j-1)) go to 800 - j = j-1 - 10 continue - do 20 i=4,n4 - if(t(i).ge.t(i+1)) go to 800 - 20 continue -c the problem considered reduces to finding the zeros of the cubic -c polynomials pl(x) which define the cubic spline in each knot -c interval t(l)<=x<=t(l+1). a zero of pl(x) is also a zero of s(x) on -c the condition that it belongs to the knot interval. -c the cubic polynomial pl(x) is determined by computing s(t(l)), -c s'(t(l)),s(t(l+1)) and s'(t(l+1)). in fact we only have to compute -c s(t(l+1)) and s'(t(l+1)); because of the continuity conditions of -c splines and their derivatives, the value of s(t(l)) and s'(t(l)) -c is already known from the foregoing knot interval. - ier = 0 -c evaluate some constants for the first knot interval - h1 = t(4)-t(3) - h2 = t(5)-t(4) - t1 = t(4)-t(2) - t2 = t(5)-t(3) - t3 = t(6)-t(4) - t4 = t(5)-t(2) - t5 = t(6)-t(3) -c calculate a0 = s(t(4)) and ah = s'(t(4)). - c1 = c(1) - c2 = c(2) - c3 = c(3) - c4 = (c2-c1)/t4 - c5 = (c3-c2)/t5 - d4 = (h2*c1+t1*c2)/t4 - d5 = (t3*c2+h1*c3)/t5 - a0 = (h2*d4+h1*d5)/t2 - ah = three*(h2*c4+h1*c5)/t2 - z1 = .true. - if(ah.lt.0.0d0) z1 = .false. - nz1 = .not.z1 - m = 0 -c main loop for the different knot intervals. - do 300 l=4,n4 -c evaluate some constants for the knot interval t(l) <= x <= t(l+1). - h1 = h2 - h2 = t(l+2)-t(l+1) - t1 = t2 - t2 = t3 - t3 = t(l+3)-t(l+1) - t4 = t5 - t5 = t(l+3)-t(l) -c find a0 = s(t(l)), ah = s'(t(l)), b0 = s(t(l+1)) and bh = s'(t(l+1)). - c1 = c2 - c2 = c3 - c3 = c(l) - c4 = c5 - c5 = (c3-c2)/t5 - d4 = (h2*c1+t1*c2)/t4 - d5 = (h1*c3+t3*c2)/t5 - b0 = (h2*d4+h1*d5)/t2 - bh = three*(h2*c4+h1*c5)/t2 -c calculate the coefficients a0,a1,a2 and a3 of the cubic polynomial -c pl(x) = ql(y) = a0+a1*y+a2*y**2+a3*y**3 ; y = (x-t(l))/(t(l+1)-t(l)). - a1 = ah*h1 - b1 = bh*h1 - a2 = three*(b0-a0)-b1-two*a1 - a3 = two*(a0-b0)+b1+a1 -c test whether or not pl(x) could have a zero in the range -c t(l) <= x <= t(l+1). - z3 = .true. - if(b1.lt.0.0d0) z3 = .false. - nz3 = .not.z3 - if(a0*b0.le.0.0d0) go to 100 - z0 = .true. - if(a0.lt.0.0d0) z0 = .false. - nz0 = .not.z0 - z2 = .true. - if(a2.lt.0.) z2 = .false. - nz2 = .not.z2 - z4 = .true. - if(3.0d0*a3+a2.lt.0.0d0) z4 = .false. - nz4 = .not.z4 - if(.not.((z0.and.(nz1.and.(z3.or.z2.and.nz4).or.nz2.and. - * z3.and.z4).or.nz0.and.(z1.and.(nz3.or.nz2.and.z4).or.z2.and. - * nz3.and.nz4))))go to 200 -c find the zeros of ql(y). - 100 call fpcuro(a3,a2,a1,a0,y,j) - if(j.eq.0) go to 200 -c find which zeros of pl(x) are zeros of s(x). - do 150 i=1,j - if(y(i).lt.0.0d0 .or. y(i).gt.1.0d0) go to 150 -c test whether the number of zeros of s(x) exceeds mest. - if(m.ge.mest) go to 700 - m = m+1 - zero(m) = t(l)+h1*y(i) - 150 continue - 200 a0 = b0 - ah = bh - z1 = z3 - nz1 = nz3 - 300 continue -c the zeros of s(x) are arranged in increasing order. - if(m.lt.2) go to 800 - do 400 i=2,m - j = i - 350 j1 = j-1 - if(j1.eq.0) go to 400 - if(zero(j).ge.zero(j1)) go to 400 - zz = zero(j) - zero(j) = zero(j1) - zero(j1) = zz - j = j1 - go to 350 - 400 continue - j = m - m = 1 - do 500 i=2,j - if(zero(i).eq.zero(m)) go to 500 - m = m+1 - zero(m) = zero(i) - 500 continue - go to 800 - 700 ier = 1 - 800 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/surev.f =================================================================== --- branches/Interpolate1D/fitpack/surev.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/surev.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,106 +0,0 @@ - subroutine surev(idim,tu,nu,tv,nv,c,u,mu,v,mv,f,mf,wrk,lwrk, - * iwrk,kwrk,ier) -c subroutine surev evaluates on a grid (u(i),v(j)),i=1,...,mu; j=1,... -c ,mv a bicubic spline surface of dimension idim, given in the -c b-spline representation. -c -c calling sequence: -c call surev(idim,tu,nu,tv,nv,c,u,mu,v,mv,f,mf,wrk,lwrk, -c * iwrk,kwrk,ier) -c -c input parameters: -c idim : integer, specifying the dimension of the spline surface. -c tu : real array, length nu, which contains the position of the -c knots in the u-direction. -c nu : integer, giving the total number of knots in the u-direction -c tv : real array, length nv, which contains the position of the -c knots in the v-direction. -c nv : integer, giving the total number of knots in the v-direction -c c : real array, length (nu-4)*(nv-4)*idim, which contains the -c b-spline coefficients. -c u : real array of dimension (mu). -c before entry u(i) must be set to the u co-ordinate of the -c i-th grid point along the u-axis. -c tu(4)<=u(i-1)<=u(i)<=tu(nu-3), i=2,...,mu. -c mu : on entry mu must specify the number of grid points along -c the u-axis. mu >=1. -c v : real array of dimension (mv). -c before entry v(j) must be set to the v co-ordinate of the -c j-th grid point along the v-axis. -c tv(4)<=v(j-1)<=v(j)<=tv(nv-3), j=2,...,mv. -c mv : on entry mv must specify the number of grid points along -c the v-axis. mv >=1. -c mf : on entry, mf must specify the dimension of the array f. -c mf >= mu*mv*idim -c wrk : real array of dimension lwrk. used as workspace. -c lwrk : integer, specifying the dimension of wrk. -c lwrk >= 4*(mu+mv) -c iwrk : integer array of dimension kwrk. used as workspace. -c kwrk : integer, specifying the dimension of iwrk. kwrk >= mu+mv. -c -c output parameters: -c f : real array of dimension (mf). -c on succesful exit f(mu*mv*(l-1)+mv*(i-1)+j) contains the -c l-th co-ordinate of the bicubic spline surface at the -c point (u(i),v(j)),l=1,...,idim,i=1,...,mu;j=1,...,mv. -c ier : integer error flag -c ier=0 : normal return -c ier=10: invalid input data (see restrictions) -c -c restrictions: -c mu >=1, mv >=1, lwrk>=4*(mu+mv), kwrk>=mu+mv , mf>=mu*mv*idim -c tu(4) <= u(i-1) <= u(i) <= tu(nu-3), i=2,...,mu -c tv(4) <= v(j-1) <= v(j) <= tv(nv-3), j=2,...,mv -c -c other subroutines required: -c fpsuev,fpbspl -c -c references : -c de boor c : on calculating with b-splines, j. approximation theory -c 6 (1972) 50-62. -c cox m.g. : the numerical evaluation of b-splines, j. inst. maths -c applics 10 (1972) 134-149. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author : -c p.dierckx -c dept. computer science, k.u.leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c latest update : march 1987 -c -c ..scalar arguments.. - integer idim,nu,nv,mu,mv,mf,lwrk,kwrk,ier -c ..array arguments.. - integer iwrk(kwrk) - real*8 tu(nu),tv(nv),c((nu-4)*(nv-4)*idim),u(mu),v(mv),f(mf), - * wrk(lwrk) -c ..local scalars.. - integer i,muv -c .. -c before starting computations a data check is made. if the input data -c are invalid control is immediately repassed to the calling program. - ier = 10 - if(mf.lt.mu*mv*idim) go to 100 - muv = mu+mv - if(lwrk.lt.4*muv) go to 100 - if(kwrk.lt.muv) go to 100 - if (mu.lt.1) go to 100 - if (mu.eq.1) go to 30 - go to 10 - 10 do 20 i=2,mu - if(u(i).lt.u(i-1)) go to 100 - 20 continue - 30 if (mv.lt.1) go to 100 - if (mv.eq.1) go to 60 - go to 40 - 40 do 50 i=2,mv - if(v(i).lt.v(i-1)) go to 100 - 50 continue - 60 ier = 0 - call fpsuev(idim,tu,nu,tv,nv,c,u,mu,v,mv,f,wrk(1),wrk(4*mu+1), - * iwrk(1),iwrk(mu+1)) - 100 return - end Deleted: branches/Interpolate1D/extensions/fitpack/fitpack/surfit.f =================================================================== --- branches/Interpolate1D/fitpack/surfit.f 2008-07-31 19:09:00 UTC (rev 4587) +++ branches/Interpolate1D/extensions/fitpack/fitpack/surfit.f 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,412 +0,0 @@ - subroutine surfit(iopt,m,x,y,z,w,xb,xe,yb,ye,kx,ky,s,nxest,nyest, - * nmax,eps,nx,tx,ny,ty,c,fp,wrk1,lwrk1,wrk2,lwrk2,iwrk,kwrk,ier) -c given the set of data points (x(i),y(i),z(i)) and the set of positive -c numbers w(i),i=1,...,m, subroutine surfit determines a smooth bivar- -c iate spline approximation s(x,y) of degrees kx and ky on the rect- -c angle xb <= x <= xe, yb <= y <= ye. -c if iopt = -1 surfit calculates the weighted least-squares spline -c according to a given set of knots. -c if iopt >= 0 the total numbers nx and ny of these knots and their -c position tx(j),j=1,...,nx and ty(j),j=1,...,ny are chosen automatic- -c ally by the routine. the smoothness of s(x,y) is then achieved by -c minimalizing the discontinuity jumps in the derivatives of s(x,y) -c across the boundaries of the subpanels (tx(i),tx(i+1))*(ty(j),ty(j+1). -c the amounth of smoothness is determined by the condition that f(p) = -c sum ((w(i)*(z(i)-s(x(i),y(i))))**2) be <= s, with s a given non-neg- -c ative constant, called the smoothing factor. -c the fit is given in the b-spline representation (b-spline coefficients -c c((ny-ky-1)*(i-1)+j),i=1,...,nx-kx-1;j=1,...,ny-ky-1) and can be eval- -c uated by means of subroutine bispev. -c -c calling sequence: -c call surfit(iopt,m,x,y,z,w,xb,xe,yb,ye,kx,ky,s,nxest,nyest, -c * nmax,eps,nx,tx,ny,ty,c,fp,wrk1,lwrk1,wrk2,lwrk2,iwrk,kwrk,ier) -c -c parameters: -c iopt : integer flag. on entry iopt must specify whether a weighted -c least-squares spline (iopt=-1) or a smoothing spline (iopt=0 -c or 1) must be determined. -c if iopt=0 the routine will start with an initial set of knots -c tx(i)=xb,tx(i+kx+1)=xe,i=1,...,kx+1;ty(i)=yb,ty(i+ky+1)=ye,i= -c 1,...,ky+1. if iopt=1 the routine will continue with the set -c of knots found at the last call of the routine. -c attention: a call with iopt=1 must always be immediately pre- -c ceded by another call with iopt=1 or iopt=0. -c unchanged on exit. -c m : integer. on entry m must specify the number of data points. -c m >= (kx+1)*(ky+1). unchanged on exit. -c x : real array of dimension at least (m). -c y : real array of dimension at least (m). -c z : real array of dimension at least (m). -c before entry, x(i),y(i),z(i) must be set to the co-ordinates -c of the i-th data point, for i=1,...,m. the order of the data -c points is immaterial. unchanged on exit. -c w : real array of dimension at least (m). before entry, w(i) must -c be set to the i-th value in the set of weights. the w(i) must -c be strictly positive. unchanged on exit. -c xb,xe : real values. on entry xb,xe,yb and ye must specify the bound- -c yb,ye aries of the rectangular approximation domain. -c xb<=x(i)<=xe,yb<=y(i)<=ye,i=1,...,m. unchanged on exit. -c kx,ky : integer values. on entry kx and ky must specify the degrees -c of the spline. 1<=kx,ky<=5. it is recommended to use bicubic -c (kx=ky=3) splines. unchanged on exit. -c s : real. on entry (in case iopt>=0) s must specify the smoothing -c factor. s >=0. unchanged on exit. -c for advice on the choice of s see further comments -c nxest : integer. unchanged on exit. -c nyest : integer. unchanged on exit. -c on entry, nxest and nyest must specify an upper bound for the -c number of knots required in the x- and y-directions respect. -c these numbers will also determine the storage space needed by -c the routine. nxest >= 2*(kx+1), nyest >= 2*(ky+1). -c in most practical situation nxest = kx+1+sqrt(m/2), nyest = -c ky+1+sqrt(m/2) will be sufficient. see also further comments. -c nmax : integer. on entry nmax must specify the actual dimension of -c the arrays tx and ty. nmax >= nxest, nmax >=nyest. -c unchanged on exit. -c eps : real. -c on entry, eps must specify a threshold for determining the -c effective rank of an over-determined linear system of equat- -c ions. 0 < eps < 1. if the number of decimal digits in the -c computer representation of a real number is q, then 10**(-q) -c is a suitable value for eps in most practical applications. -c unchanged on exit. -c nx : integer. -c unless ier=10 (in case iopt >=0), nx will contain the total -c number of knots with respect to the x-variable, of the spline -c approximation returned. if the computation mode iopt=1 is -c used, the value of nx should be left unchanged between sub- -c sequent calls. -c in case iopt=-1, the value of nx should be specified on entry -c tx : real array of dimension nmax. -c on succesful exit, this array will contain the knots of the -c spline with respect to the x-variable, i.e. the position of -c the interior knots tx(kx+2),...,tx(nx-kx-1) as well as the -c position of the additional knots tx(1)=...=tx(kx+1)=xb and -c tx(nx-kx)=...=tx(nx)=xe needed for the b-spline representat. -c if the computation mode iopt=1 is used, the values of tx(1), -c ...,tx(nx) should be left unchanged between subsequent calls. -c if the computation mode iopt=-1 is used, the values tx(kx+2), -c ...tx(nx-kx-1) must be supplied by the user, before entry. -c see also the restrictions (ier=10). -c ny : integer. -c unless ier=10 (in case iopt >=0), ny will contain the total -c number of knots with respect to the y-variable, of the spline -c approximation returned. if the computation mode iopt=1 is -c used, the value of ny should be left unchanged between sub- -c sequent calls. -c in case iopt=-1, the value of ny should be specified on entry -c ty : real array of dimension nmax. -c on succesful exit, this array will contain the knots of the -c spline with respect to the y-variable, i.e. the position of -c the interior knots ty(ky+2),...,ty(ny-ky-1) as well as the -c position of the additional knots ty(1)=...=ty(ky+1)=yb and -c ty(ny-ky)=...=ty(ny)=ye needed for the b-spline representat. -c if the computation mode iopt=1 is used, the values of ty(1), -c ...,ty(ny) should be left unchanged between subsequent calls. -c if the computation mode iopt=-1 is used, the values ty(ky+2), -c ...ty(ny-ky-1) must be supplied by the user, before entry. -c see also the restrictions (ier=10). -c c : real array of dimension at least (nxest-kx-1)*(nyest-ky-1). -c on succesful exit, c contains the coefficients of the spline -c approximation s(x,y) -c fp : real. unless ier=10, fp contains the weighted sum of -c squared residuals of the spline approximation returned. -c wrk1 : real array of dimension (lwrk1). used as workspace. -c if the computation mode iopt=1 is used the value of wrk1(1) -c should be left unchanged between subsequent calls. -c on exit wrk1(2),wrk1(3),...,wrk1(1+(nx-kx-1)*(ny-ky-1)) will -c contain the values d(i)/max(d(i)),i=1,...,(nx-kx-1)*(ny-ky-1) -c with d(i) the i-th diagonal element of the reduced triangular -c matrix for calculating the b-spline coefficients. it includes -c those elements whose square is less than eps,which are treat- -c ed as 0 in the case of presumed rank deficiency (ier<-2). -c lwrk1 : integer. on entry lwrk1 must specify the actual dimension of -c the array wrk1 as declared in the calling (sub)program. -c lwrk1 must not be too small. let -c u = nxest-kx-1, v = nyest-ky-1, km = max(kx,ky)+1, -c ne = max(nxest,nyest), bx = kx*v+ky+1, by = ky*u+kx+1, -c if(bx.le.by) b1 = bx, b2 = b1+v-ky -c if(bx.gt.by) b1 = by, b2 = b1+u-kx then -c lwrk1 >= u*v*(2+b1+b2)+2*(u+v+km*(m+ne)+ne-kx-ky)+b2+1 -c wrk2 : real array of dimension (lwrk2). used as workspace, but -c only in the case a rank deficient system is encountered. -c lwrk2 : integer. on entry lwrk2 must specify the actual dimension of -c the array wrk2 as declared in the calling (sub)program. -c lwrk2 > 0 . a save upper boundfor lwrk2 = u*v*(b2+1)+b2 -c where u,v and b2 are as above. if there are enough data -c points, scattered uniformly over the approximation domain -c and if the smoothing factor s is not too small, there is a -c good chance that this extra workspace is not needed. a lot -c of memory might therefore be saved by setting lwrk2=1. -c (see also ier > 10) -c iwrk : integer array of dimension (kwrk). used as workspace. -c kwrk : integer. on entry kwrk must specify the actual dimension of -c the array iwrk as declared in the calling (sub)program. -c kwrk >= m+(nxest-2*kx-1)*(nyest-2*ky-1). -c ier : integer. unless the routine detects an error, ier contains a -c non-positive value on exit, i.e. -c ier=0 : normal return. the spline returned has a residual sum of -c squares fp such that abs(fp-s)/s <= tol with tol a relat- -c ive tolerance set to 0.001 by the program. -c ier=-1 : normal return. the spline returned is an interpolating -c spline (fp=0). -c ier=-2 : normal return. the spline returned is the weighted least- -c squares polynomial of degrees kx and ky. in this extreme -c case fp gives the upper bound for the smoothing factor s. -c ier<-2 : warning. the coefficients of the spline returned have been -c computed as the minimal norm least-squares solution of a -c (numerically) rank deficient system. (-ier) gives the rank. -c especially if the rank deficiency which can be computed as -c (nx-kx-1)*(ny-ky-1)+ier, is large the results may be inac- -c curate. they could also seriously depend on the value of -c eps. -c ier=1 : error. the required storage space exceeds the available -c storage space, as specified by the parameters nxest and -c nyest. -c probably causes : nxest or nyest too small. if these param- -c eters are already large, it may also indicate that s is -c too small -c the approximation returned is the weighted least-squares -c spline according to the current set of knots. -c the parameter fp gives the corresponding weighted sum of -c squared residuals (fp>s). -c ier=2 : error. a theoretically impossible result was found during -c the iteration proces for finding a smoothing spline with -c fp = s. probably causes : s too small or badly chosen eps. -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=3 : error. the maximal number of iterations maxit (set to 20 -c by the program) allowed for finding a smoothing spline -c with fp=s has been reached. probably causes : s too small -c there is an approximation returned but the corresponding -c weighted sum of squared residuals does not satisfy the -c condition abs(fp-s)/s < tol. -c ier=4 : error. no more knots can be added because the number of -c b-spline coefficients (nx-kx-1)*(ny-ky-1) already exceeds -c the number of data points m. -c probably causes : either s or m too small. -c the approximation returned is the weighted least-squares -c spline according to the current set of knots. -c the parameter fp gives the corresponding weighted sum of -c squared residuals (fp>s). -c ier=5 : error. no more knots can be added because the additional -c knot would (quasi) coincide with an old one. -c probably causes : s too small or too large a weight to an -c inaccurate data point. -c the approximation returned is the weighted least-squares -c spline according to the current set of knots. -c the parameter fp gives the corresponding weighted sum of -c squared residuals (fp>s). -c ier=10 : error. on entry, the input data are controlled on validity -c the following restrictions must be satisfied. -c -1<=iopt<=1, 1<=kx,ky<=5, m>=(kx+1)*(ky+1), nxest>=2*kx+2, -c nyest>=2*ky+2, 0=nxest, nmax>=nyest, -c xb<=x(i)<=xe, yb<=y(i)<=ye, w(i)>0, i=1,...,m -c lwrk1 >= u*v*(2+b1+b2)+2*(u+v+km*(m+ne)+ne-kx-ky)+b2+1 -c kwrk >= m+(nxest-2*kx-1)*(nyest-2*ky-1) -c if iopt=-1: 2*kx+2<=nx<=nxest -c xb=0: s>=0 -c if one of these conditions is found to be violated,control -c is immediately repassed to the calling program. in that -c case there is no approximation returned. -c ier>10 : error. lwrk2 is too small, i.e. there is not enough work- -c space for computing the minimal least-squares solution of -c a rank deficient system of linear equations. ier gives the -c requested value for lwrk2. there is no approximation re- -c turned but, having saved the information contained in nx, -c ny,tx,ty,wrk1, and having adjusted the value of lwrk2 and -c the dimension of the array wrk2 accordingly, the user can -c continue at the point the program was left, by calling -c surfit with iopt=1. -c -c further comments: -c by means of the parameter s, the user can control the tradeoff -c between closeness of fit and smoothness of fit of the approximation. -c if s is too large, the spline will be too smooth and signal will be -c lost ; if s is too small the spline will pick up too much noise. in -c the extreme cases the program will return an interpolating spline if -c s=0 and the weighted least-squares polynomial (degrees kx,ky)if s is -c very large. between these extremes, a properly chosen s will result -c in a good compromise between closeness of fit and smoothness of fit. -c to decide whether an approximation, corresponding to a certain s is -c satisfactory the user is highly recommended to inspect the fits -c graphically. -c recommended values for s depend on the weights w(i). if these are -c taken as 1/d(i) with d(i) an estimate of the standard deviation of -c z(i), a good s-value should be found in the range (m-sqrt(2*m),m+ -c sqrt(2*m)). if nothing is known about the statistical error in z(i) -c each w(i) can be set equal to one and s determined by trial and -c error, taking account of the comments above. the best is then to -c start with a very large value of s ( to determine the least-squares -c polynomial and the corresponding upper bound fp0 for s) and then to -c progressively decrease the value of s ( say by a factor 10 in the -c beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the -c approximation shows more detail) to obtain closer fits. -c to choose s very small is strongly discouraged. this considerably -c increases computation time and memory requirements. it may also -c cause rank-deficiency (ier<-2) and endager numerical stability. -c to economize the search for a good s-value the program provides with -c different modes of computation. at the first call of the routine, or -c whenever he wants to restart with the initial set of knots the user -c must set iopt=0. -c if iopt=1 the program will continue with the set of knots found at -c the last call of the routine. this will save a lot of computation -c time if surfit is called repeatedly for different values of s. -c the number of knots of the spline returned and their location will -c depend on the value of s and on the complexity of the shape of the -c function underlying the data. if the computation mode iopt=1 -c is used, the knots returned may also depend on the s-values at -c previous calls (if these were smaller). therefore, if after a number -c of trials with different s-values and iopt=1, the user can finally -c accept a fit as satisfactory, it may be worthwhile for him to call -c surfit once more with the selected value for s but now with iopt=0. -c indeed, surfit may then return an approximation of the same quality -c of fit but with fewer knots and therefore better if data reduction -c is also an important objective for the user. -c the number of knots may also depend on the upper bounds nxest and -c nyest. indeed, if at a certain stage in surfit the number of knots -c in one direction (say nx) has reached the value of its upper bound -c (nxest), then from that moment on all subsequent knots are added -c in the other (y) direction. this may indicate that the value of -c nxest is too small. on the other hand, it gives the user the option -c of limiting the number of knots the routine locates in any direction -c for example, by setting nxest=2*kx+2 (the lowest allowable value for -c nxest), the user can indicate that he wants an approximation which -c is a simple polynomial of degree kx in the variable x. -c -c other subroutines required: -c fpback,fpbspl,fpsurf,fpdisc,fpgivs,fprank,fprati,fprota,fporde -c -c references: -c dierckx p. : an algorithm for surface fitting with spline functions -c ima j. numer. anal. 1 (1981) 267-283. -c dierckx p. : an algorithm for surface fitting with spline functions -c report tw50, dept. computer science,k.u.leuven, 1980. -c dierckx p. : curve and surface fitting with splines, monographs on -c numerical analysis, oxford university press, 1993. -c -c author: -c p.dierckx -c dept. computer science, k.u. leuven -c celestijnenlaan 200a, b-3001 heverlee, belgium. -c e-mail : Paul.Dierckx at cs.kuleuven.ac.be -c -c creation date : may 1979 -c latest update : march 1987 -c -c .. -c ..scalar arguments.. - real*8 xb,xe,yb,ye,s,eps,fp - integer iopt,m,kx,ky,nxest,nyest,nmax,nx,ny,lwrk1,lwrk2,kwrk,ier -c ..array arguments.. - real*8 x(m),y(m),z(m),w(m),tx(nmax),ty(nmax), - * c((nxest-kx-1)*(nyest-ky-1)),wrk1(lwrk1),wrk2(lwrk2) - integer iwrk(kwrk) -c ..local scalars.. - real*8 tol - integer i,ib1,ib3,jb1,ki,kmax,km1,km2,kn,kwest,kx1,ky1,la,lbx, - * lby,lco,lf,lff,lfp,lh,lq,lsx,lsy,lwest,maxit,ncest,nest,nek, - * nminx,nminy,nmx,nmy,nreg,nrint,nxk,nyk -c ..function references.. - integer max0 -c ..subroutine references.. -c fpsurf -c .. -c we set up the parameters tol and maxit. - maxit = 20 - tol = 0.1e-02 -c before starting computations a data check is made. if the input data -c are invalid,control is immediately repassed to the calling program. - ier = 10 - if(eps.le.0. .or. eps.ge.1.) go to 71 - if(kx.le.0 .or. kx.gt.5) go to 71 - kx1 = kx+1 - if(ky.le.0 .or. ky.gt.5) go to 71 - ky1 = ky+1 - kmax = max0(kx,ky) - km1 = kmax+1 - km2 = km1+1 - if(iopt.lt.(-1) .or. iopt.gt.1) go to 71 - if(m.lt.(kx1*ky1)) go to 71 - nminx = 2*kx1 - if(nxest.lt.nminx .or. nxest.gt.nmax) go to 71 - nminy = 2*ky1 - if(nyest.lt.nminy .or. nyest.gt.nmax) go to 71 - nest = max0(nxest,nyest) - nxk = nxest-kx1 - nyk = nyest-ky1 - ncest = nxk*nyk - nmx = nxest-nminx+1 - nmy = nyest-nminy+1 - nrint = nmx+nmy - nreg = nmx*nmy - ib1 = kx*nyk+ky1 - jb1 = ky*nxk+kx1 - ib3 = kx1*nyk+1 - if(ib1.le.jb1) go to 10 - ib1 = jb1 - ib3 = ky1*nxk+1 - 10 lwest = ncest*(2+ib1+ib3)+2*(nrint+nest*km2+m*km1)+ib3 - kwest = m+nreg - if(lwrk1.lt.lwest .or. kwrk.lt.kwest) go to 71 - if(xb.ge.xe .or. yb.ge.ye) go to 71 - do 20 i=1,m - if(w(i).le.0.) go to 70 - if(x(i).lt.xb .or. x(i).gt.xe) go to 71 - if(y(i).lt.yb .or. y(i).gt.ye) go to 71 - 20 continue - if(iopt.ge.0) go to 50 - if(nx.lt.nminx .or. nx.gt.nxest) go to 71 - nxk = nx-kx1 - tx(kx1) = xb - tx(nxk+1) = xe - do 30 i=kx1,nxk - if(tx(i+1).le.tx(i)) go to 72 - 30 continue - if(ny.lt.nminy .or. ny.gt.nyest) go to 71 - nyk = ny-ky1 - ty(ky1) = yb - ty(nyk+1) = ye - do 40 i=ky1,nyk - if(ty(i+1).le.ty(i)) go to 73 - 40 continue - go to 60 - 50 if(s.lt.0.) go to 71 - 60 ier = 0 -c we partition the working space and determine the spline approximation - kn = 1 - ki = kn+m - lq = 2 - la = lq+ncest*ib3 - lf = la+ncest*ib1 - lff = lf+ncest - lfp = lff+ncest - lco = lfp+nrint - lh = lco+nrint - lbx = lh+ib3 - nek = nest*km2 - lby = lbx+nek - lsx = lby+nek - lsy = lsx+m*km1 - call fpsurf(iopt,m,x,y,z,w,xb,xe,yb,ye,kx,ky,s,nxest,nyest, - * eps,tol,maxit,nest,km1,km2,ib1,ib3,ncest,nrint,nreg,nx,tx, - * ny,ty,c,fp,wrk1(1),wrk1(lfp),wrk1(lco),wrk1(lf),wrk1(lff), - * wrk1(la),wrk1(lq),wrk1(lbx),wrk1(lby),wrk1(lsx),wrk1(lsy), - * wrk1(lh),iwrk(ki),iwrk(kn),wrk2,lwrk2,ier) - 70 return - 71 print*,"iopt,kx,ky,m=",iopt,kx,ky,m - print*,"nxest,nyest,nmax=",nxest,nyest,nmax - print*,"lwrk1,lwrk2,kwrk=",lwrk1,lwrk2,kwrk - print*,"xb,xe,yb,ye=",xb,xe,yb,ye - print*,"eps,s",eps,s - return - 72 print*,"tx=",tx - return - 73 print*,"ty=",ty - return - end Copied: branches/Interpolate1D/extensions/interpolate.h (from rev 4587, branches/Interpolate1D/interpolate.h) Copied: branches/Interpolate1D/extensions/multipack.h (from rev 4587, branches/Interpolate1D/multipack.h) Copied: branches/Interpolate1D/extensions/ndimage (from rev 4601, branches/Interpolate1D/ndimage) Deleted: branches/Interpolate1D/interpolate.h =================================================================== --- branches/Interpolate1D/interpolate.h 2008-08-07 21:05:37 UTC (rev 4609) +++ branches/Interpolate1D/interpolate.h 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,206 +0,0 @@ -#include -#include -#include -#include - -template -void linear(T* x_vec, T* y_vec, int len, - T* new_x_vec, T* new_y_vec, int new_len) -{ - for (int i=0;i=x_vec[len-1]) - index = len-2; - else - { - T* which = std::lower_bound(x_vec, x_vec+len, new_x); - index = which - x_vec-1; - } - - if(new_x == x_vec[index]) - { - // exact value - new_y_vec[i] = y_vec[index]; - } - else - { - //interpolate - double x_lo = x_vec[index]; - double x_hi = x_vec[index+1]; - double y_lo = y_vec[index]; - double y_hi = y_vec[index+1]; - double slope = (y_hi-y_lo)/(x_hi-x_lo); - new_y_vec[i] = slope * (new_x-x_lo) + y_lo; - } - } -} - -template -void loginterp(T* x_vec, T* y_vec, int len, - T* new_x_vec, T* new_y_vec, int new_len) -{ - for (int i=0;i=x_vec[len-1]) - index = len-2; - else - { - T* which = std::lower_bound(x_vec, x_vec+len, new_x); - index = which - x_vec-1; - } - - if(new_x == x_vec[index]) - { - // exact value - new_y_vec[i] = y_vec[index]; - } - else - { - //interpolate - double x_lo = x_vec[index]; - double x_hi = x_vec[index+1]; - double y_lo = log10(y_vec[index]); - double y_hi = log10(y_vec[index+1]); - double slope = (y_hi-y_lo)/(x_hi-x_lo); - new_y_vec[i] = pow(10.0, (slope * (new_x-x_lo) + y_lo)); - } - } -} - -template -int block_average_above(T* x_vec, T* y_vec, int len, - T* new_x_vec, T* new_y_vec, int new_len) -{ - int bad_index = -1; - int start_index = 0; - T last_y = 0.0; - T thickness = 0.0; - - for(int i=0;i x_vec[len-1])) - { - bad_index = i; - break; - } - else if (new_x == x_vec[0]) - { - // for the first sample, just return the cooresponding y value - new_y_vec[i] = y_vec[0]; - } - else - { - T* which = std::lower_bound(x_vec, x_vec+len, new_x); - int index = which - x_vec-1; - - // calculate weighted average - - // Start off with "residue" from last interval in case last x - // was between to samples. - T weighted_y_sum = last_y * thickness; - T thickness_sum = thickness; - for(int j=start_index; j<=index; j++) - { - T next_x; - if (x_vec[j+1] < new_x) - thickness = x_vec[j+1] - x_vec[j]; - else - thickness = new_x -x_vec[j]; - weighted_y_sum += y_vec[j] * thickness; - thickness_sum += thickness; - } - new_y_vec[i] = weighted_y_sum/thickness_sum; - - // Store the thickness between the x value and the next sample - // to add to the next weighted average. - last_y = y_vec[index]; - thickness = x_vec[index+1] - new_x; - - // start next weighted average at next sample - start_index =index+1; - } - } - return bad_index; -} - -template -int window_average(T* x_vec, T* y_vec, int len, - T* new_x_vec, T* new_y_vec, int new_len, - T width) -{ - for(int i=0;i= len) - { - //top = x_vec[len-1]; - top_index = len-1; - } - //std::cout << std::endl; - //std::cout << bottom_index << " " << top_index << std::endl; - //std::cout << bottom << " " << top << std::endl; - // calculate weighted average - T thickness =0.0; - T thickness_sum =0.0; - T weighted_y_sum =0.0; - for(int j=bottom_index; j < top_index; j++) - { - thickness = x_vec[j+1] - bottom; - weighted_y_sum += y_vec[j] * thickness; - thickness_sum += thickness; - bottom = x_vec[j+1]; - /* - std::cout << "iter: " << j - bottom_index << " " << - "index: " << j << " " << - "bottom: " << bottom << " " << - "x+1: " << x_vec[j+1] << " " << - "x: " << x_vec[j] << " " << - "y: " << y_vec[j] << " " << - "weighted_sum: " << weighted_y_sum << - "thickness: " << thickness << " " << - "thickness_sum: " << thickness_sum << std::endl; - */ - //std::cout << x_vec[j] << " "; - //std::cout << thickness << " "; - } - - // last element - thickness = top - bottom; - weighted_y_sum += y_vec[top_index] * thickness; - thickness_sum += thickness; - /* - std::cout << "iter: last" << " " << - "index: " << top_index << " " << - "x: " << x_vec[top_index] << " " << - "y: " << y_vec[top_index] << " " << - "weighted_sum: " << weighted_y_sum << - "thickness: " << thickness << " " << - "thickness_sum: " << thickness_sum << std::endl; - */ - //std::cout << x_vec[top_index] << " " << thickness_sum << std::endl; - new_y_vec[i] = weighted_y_sum/thickness_sum; - } - return -1; -} Deleted: branches/Interpolate1D/multipack.h =================================================================== --- branches/Interpolate1D/multipack.h 2008-08-07 21:05:37 UTC (rev 4609) +++ branches/Interpolate1D/multipack.h 2008-08-07 21:25:16 UTC (rev 4610) @@ -1,211 +0,0 @@ -/* MULTIPACK module by Travis Oliphant - -Copyright (c) 2002 Travis Oliphant all rights reserved -Oliphant.Travis at altavista.net -Permission to use, modify, and distribute this software is given under the -terms of the SciPy (BSD style) license. See LICENSE.txt that came with -this distribution for specifics. - -NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. -*/ - - -/* This extension module is a collection of wrapper functions around -common FORTRAN code in the packages MINPACK, ODEPACK, and QUADPACK plus -some differential algebraic equation solvers. - -The wrappers are meant to be nearly direct translations between the -FORTAN code and Python. Some parameters like sizes do not need to be -passed since they are available from the objects. - -It is anticipated that a pure Python module be written to call these lower -level routines and make a simpler user interface. All of the routines define -default values for little-used parameters so that even the raw routines are -quite useful without a separate wrapper. - -FORTRAN Outputs that are not either an error indicator or the sought-after -results are placed in a dictionary and returned as an optional member of -the result tuple when the full_output argument is non-zero. -*/ - -#include "Python.h" -#include "numpy/arrayobject.h" - -#define PYERR(errobj,message) {PyErr_SetString(errobj,message); goto fail;} -#define PYERR2(errobj,message) {PyErr_Print(); PyErr_SetString(errobj, message); goto fail;} -#define ISCONTIGUOUS(m) ((m)->flags & CONTIGUOUS) - -#define STORE_VARS() PyObject *store_multipack_globals[4]; int store_multipack_globals3; - -#define INIT_FUNC(fun,arg,errobj) { /* Get extra arguments or set to zero length tuple */ \ - store_multipack_globals[0] = multipack_python_function; \ - store_multipack_globals[1] = multipack_extra_arguments; \ - if (arg == NULL) { \ - if ((arg = PyTuple_New(0)) == NULL) goto fail; \ - } \ - else \ - Py_INCREF(arg); /* We decrement on exit. */ \ - if (!PyTuple_Check(arg)) \ - PYERR(errobj,"Extra Arguments must be in a tuple"); \ - /* Set up callback functions */ \ - if (!PyCallable_Check(fun)) \ - PYERR(errobj,"First argument must be a callable function."); \ - multipack_python_function = fun; \ - multipack_extra_arguments = arg; } - -#define INIT_JAC_FUNC(fun,Dfun,arg,col_deriv,errobj) { \ - store_multipack_globals[0] = multipack_python_function; \ - store_multipack_globals[1] = multipack_extra_arguments; \ - store_multipack_globals[2] = multipack_python_jacobian; \ - store_multipack_globals3 = multipack_jac_transpose; \ - if (arg == NULL) { \ - if ((arg = PyTuple_New(0)) == NULL) goto fail; \ - } \ - else \ - Py_INCREF(arg); /* We decrement on exit. */ \ - if (!PyTuple_Check(arg)) \ - PYERR(errobj,"Extra Arguments must be in a tuple"); \ - /* Set up callback functions */ \ - if (!PyCallable_Check(fun) || (Dfun != Py_None && !PyCallable_Check(Dfun))) \ - PYERR(errobj,"The function and its Jacobian must be callable functions."); \ - multipack_python_function = fun; \ - multipack_extra_arguments = arg; \ - multipack_python_jacobian = Dfun; \ - multipack_jac_transpose = !(col_deriv);} - -#define RESTORE_JAC_FUNC() multipack_python_function = store_multipack_globals[0]; \ - multipack_extra_arguments = store_multipack_globals[1]; \ - multipack_python_jacobian = store_multipack_globals[2]; \ - multipack_jac_transpose = store_multipack_globals3; - -#define RESTORE_FUNC() multipack_python_function = store_multipack_globals[0]; \ - multipack_extra_arguments = store_multipack_globals[1]; - -#define SET_DIAG(ap_diag,o_diag,mode) { /* Set the diag vector from input */ \ - if (o_diag == NULL || o_diag == Py_None) { \ - ap_diag = (PyArrayObject *)PyArray_FromDims(1,&n,PyArray_DOUBLE); \ - if (ap_diag == NULL) goto fail; \ - diag = (double *)ap_diag -> data; \ - mode = 1; \ - } \ - else { \ - ap_diag = (PyArrayObject *)PyArray_ContiguousFromObject(o_diag, PyArray_DOUBLE, 1, 1); \ - if (ap_diag == NULL) goto fail; \ - diag = (double *)ap_diag -> data; \ - mode = 2; } } - -#define MATRIXC2F(jac,data,n,m) {double *p1=(double *)(jac), *p2, *p3=(double *)(data);\ -int i,j;\ -for (j=0;j<(m);p3++,j++) \ - for (p2=p3,i=0;i<(n);p2+=(m),i++,p1++) \ - *p1 = *p2; } -/* -static PyObject *multipack_python_function=NULL; -static PyObject *multipack_python_jacobian=NULL; -static PyObject *multipack_extra_arguments=NULL; -static int multipack_jac_transpose=1; -*/ - -static PyArrayObject * my_make_numpy_array(PyObject *y0, int type, int mindim, int maxdim) - /* This is just like PyArray_ContiguousFromObject except it handles - * single numeric datatypes as 1-element, rank-1 arrays instead of as - * scalars. - */ -{ - PyArrayObject *new_array; - PyObject *tmpobj; - - Py_INCREF(y0); - - if (PyInt_Check(y0) || PyFloat_Check(y0)) { - tmpobj = PyList_New(1); - PyList_SET_ITEM(tmpobj, 0, y0); /* reference now belongs to tmpobj */ - } - else - tmpobj = y0; - - new_array = (PyArrayObject *)PyArray_ContiguousFromObject(tmpobj, type, mindim, maxdim); - - Py_DECREF(tmpobj); - return new_array; -} - -static PyObject *call_python_function(PyObject *func, int n, double *x, PyObject *args, int dim, PyObject *error_obj) -{ - /* - This is a generic function to call a python function that takes a 1-D - sequence as a first argument and optional extra_arguments (should be a - zero-length tuple if none desired). The result of the function is - returned in a multiarray object. - -- build sequence object from values in x. - -- add extra arguments (if any) to an argument list. - -- call Python callable object - -- check if error occurred: - if so return NULL - -- if no error, place result of Python code into multiarray object. - */ - - PyArrayObject *sequence = NULL; - PyObject *arglist = NULL, *tmpobj = NULL; - PyObject *arg1 = NULL, *str1 = NULL; - PyObject *result = NULL; - PyArrayObject *result_array = NULL; - - /* Build sequence argument from inputs */ - sequence = (PyArrayObject *)PyArray_FromDimsAndData(1, &n, PyArray_DOUBLE, (char *)x); - if (sequence == NULL) PYERR2(error_obj,"Internal failure to make an array of doubles out of first\n argument to function call."); - - /* Build argument list */ - if ((arg1 = PyTuple_New(1)) == NULL) { - Py_DECREF(sequence); - return NULL; - } - PyTuple_SET_ITEM(arg1, 0, (PyObject *)sequence); - /* arg1 now owns sequence reference */ - if ((arglist = PySequence_Concat( arg1, args)) == NULL) - PYERR2(error_obj,"Internal error constructing argument list."); - - Py_DECREF(arg1); /* arglist has a reference to sequence, now. */ - - - /* Call function object --- variable passed to routine. Extra - arguments are in another passed variable. - */ - if ((result = PyEval_CallObject(func, arglist))==NULL) { - PyErr_Print(); - tmpobj = PyObject_GetAttrString(func, "func_name"); - if (tmpobj == NULL) goto fail; - str1 = PyString_FromString("Error occured while calling the Python function named "); - if (str1 == NULL) { Py_DECREF(tmpobj); goto fail;} - PyString_ConcatAndDel(&str1, tmpobj); - PyErr_SetString(error_obj, PyString_AsString(str1)); - Py_DECREF(str1); - goto fail; - } - - if ((result_array = (PyArrayObject *)PyArray_ContiguousFromObject(result, PyArray_DOUBLE, dim-1, dim))==NULL) - PYERR2(error_obj,"Result from function call is not a proper array of floats."); - - Py_DECREF(result); - Py_DECREF(arglist); - return (PyObject *)result_array; - - fail: - Py_XDECREF(arglist); - Py_XDECREF(result); - Py_XDECREF(arg1); - return NULL; -} - - - - - - - - - - - - - Modified: branches/Interpolate1D/setup.py =================================================================== --- branches/Interpolate1D/setup.py 2008-08-07 21:05:37 UTC (rev 4609) +++ branches/Interpolate1D/setup.py 2008-08-07 21:25:16 UTC (rev 4610) @@ -13,31 +13,31 @@ # C++ extension for several basic interpolation types config.add_extension('_interpolate', - ['_interpolate.cpp'], - include_dirs = ['.'], - depends = ['interpolate.h']) + ['extensions/_interpolate.cpp'], + include_dirs = ['extensions'], + depends = ['extensions/interpolate.h']) # used by dfitpack extension config.add_library('_fitpack', - sources=[join('fitpack', '*.f')], + sources=[join('extensions/fitpack', '*.f')], ) # Fortran routines (collectively "FITPACK" for spline interpolation) config.add_extension('_dfitpack', - sources=['_fitpack.pyf'], + sources=['extensions/_fitpack.pyf'], libraries=['_fitpack'], ) # ND Image routines for ND interpolation config.add_extension('_nd_image', - sources=["ndimage/nd_image.c", - "ndimage/ni_filters.c", - "ndimage/ni_fourier.c", - "ndimage/ni_interpolation.c", - "ndimage/ni_measure.c", - "ndimage/ni_morphology.c", - "ndimage/ni_support.c"], - include_dirs=['ndimage']+[get_include()], + sources=["extensions/ndimage/nd_image.c", + "extensions/ndimage/ni_filters.c", + "extensions/ndimage/ni_fourier.c", + "extensions/ndimage/ni_interpolation.c", + "extensions/ndimage/ni_measure.c", + "extensions/ndimage/ni_morphology.c", + "extensions/ndimage/ni_support.c"], + include_dirs=['extensions/ndimage']+[get_include()], ) config.add_data_dir('docs') From scipy-svn at scipy.org Thu Aug 7 19:42:51 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Thu, 7 Aug 2008 18:42:51 -0500 (CDT) Subject: [Scipy-svn] r4611 - branches/Interpolate1D Message-ID: <20080807234251.A9CE639C502@scipy.org> Author: fcady Date: 2008-08-07 18:42:44 -0500 (Thu, 07 Aug 2008) New Revision: 4611 Modified: branches/Interpolate1D/TODO.txt branches/Interpolate1D/info.py branches/Interpolate1D/interpolateNd.py Log: added prefiltering from ndimage, which it turns out is necessary to get good data with spline order >1. It still needs work to make it pretty and integrated, but it is functional Modified: branches/Interpolate1D/TODO.txt =================================================================== --- branches/Interpolate1D/TODO.txt 2008-08-07 21:25:16 UTC (rev 4610) +++ branches/Interpolate1D/TODO.txt 2008-08-07 23:42:44 UTC (rev 4611) @@ -36,6 +36,15 @@ **include spline pre-filtering in ND interpolation, or understand why we don't need to do that. + + It appears that higher-order splines also smooth the data + increasingly. Yes, I checked and they definitely don't + reproduce perfectly the input; they flatten stuff. + + The pre-filtering definitely improves the output by a whole lot; + I suspect it returns some sort of transform of the data. But I + really wish I knew what it did; why didn't this guy document his + code better than he did?? **README file that describes the architecture of the package and also includes license information. @@ -48,9 +57,13 @@ **allow newx to be in non-sorted order for 1D This requires rethinking the partition of newx into - low, high and mid + low, high and kind -**put all extension files into their own directory + The main hurdle is that I can only really fill and array + using result[mask] = partial_result if I can guarantee + that everything will have the same type. Maybe it is + worth compromising the generality of the function to + allow that. ********* LONGER TERM ************ Modified: branches/Interpolate1D/info.py =================================================================== --- branches/Interpolate1D/info.py 2008-08-07 21:25:16 UTC (rev 4610) +++ branches/Interpolate1D/info.py 2008-08-07 23:42:44 UTC (rev 4611) @@ -27,7 +27,7 @@ The following callable classes are also provided: - Interpolate1d : an object for interpolation of + Interpolate1d : an object for 1D interpolation of various kinds. interp1d is a wrapper around this class. @@ -36,15 +36,21 @@ is used. However, not all functionality of Spline is available through Interpolate1d. - Interpolate2d : + Interpolate2d : an object for 2D interpolation of + various kinds. interp2d is a wrapper + around this class. - Spline 2d : + Spline2d : an object for spline interpolation. Interpolate1d + wraps this class if spline interpolation + is used. However, not all functionality + of Spline2d is available through Interpolate1d. - InterpolateNd : + InterpolateNd : an object for interpolation of ND data. interpNd + is a wrapper around this class. These functions and classes constitute the primary api. However, several - additional functions are also provided (the primary api in many cases calls - these functions): + additional less generic functions are also provided for more direct interpolation. + They don't have as crafted a UI as those above, but they are quick and easy: linear : linear interpolation logarithmic : logarithmic interpolation Modified: branches/Interpolate1D/interpolateNd.py =================================================================== --- branches/Interpolate1D/interpolateNd.py 2008-08-07 21:25:16 UTC (rev 4610) +++ branches/Interpolate1D/interpolateNd.py 2008-08-07 23:42:44 UTC (rev 4611) @@ -132,6 +132,7 @@ """ # FIXME : include spline filtering + # the ndimage module says that it requires pre-filtering for # checking format of input data = array(data) @@ -191,8 +192,16 @@ else: raise ValueError, "argument kind = %s not recognized" % str(kind) + + # This step is done because it is required by the ndimage code that I'm scavenging. + # I don't fully understand why it must do this, and that's a problem. But empirically + # this step is needed in order to get good-looking data. + if self.order >1: + self._data_array = spline_filter(data, self.order) + else: + self._data_array = data + # storing relevant data - self._data_array = data self.ndim = data.ndim self._shape = np.shape(data) self._spacings = spacings @@ -295,4 +304,40 @@ - \ No newline at end of file + +import _ni_support + +def spline_filter1d(input, order = 3, axis = -1, output = np.float64, + output_type = None): + # takes array and everything; we can make input safe if user never touches it + """ Calculates a one-dimensional spline filter along the given axis. + + The lines of the array along the given axis are filtered by a + spline filter. The order of the spline must be >= 2 and <= 5. + """ + if order in [0, 1]: + output[...] = np.array(input) + else: + _nd_image.spline_filter1d(input, order, axis, output) + return output + +def spline_filter(input, order = 3, output = np.float64, + output_type = None): + """ Multi-dimensional spline filter. + + Note: The multi-dimensional filter is implemented as a sequence of + one-dimensional spline filters. The intermediate arrays are stored + in the same data type as the output. Therefore, for output types + with a limited precision, the results may be imprecise because + intermediate results may be stored with insufficient precision. + """ + + output = np.zeros( np.shape(input) , dtype=np.float64 ) # place to store the data + + if order not in [0, 1] and input.ndim > 0: + for axis in range(input.ndim): + spline_filter1d(input, order, axis, output = output) + input = output + else: + output[...] = input[...] + return output \ No newline at end of file From scipy-svn at scipy.org Thu Aug 7 21:29:18 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Thu, 7 Aug 2008 20:29:18 -0500 (CDT) Subject: [Scipy-svn] r4612 - branches/stats_models/tests Message-ID: <20080808012918.D9F4D39C088@scipy.org> Author: tom.waite Date: 2008-08-07 20:29:16 -0500 (Thu, 07 Aug 2008) New Revision: 4612 Modified: branches/stats_models/tests/test_bspline.py Log: weave to c-ext Modified: branches/stats_models/tests/test_bspline.py =================================================================== --- branches/stats_models/tests/test_bspline.py 2008-08-07 23:42:44 UTC (rev 4611) +++ branches/stats_models/tests/test_bspline.py 2008-08-08 01:29:16 UTC (rev 4612) @@ -2,26 +2,39 @@ Test functions for models.bspline """ -import numpy as N +import numpy as np from numpy.testing import * +import scipy.stats.models._bspline as bsp -import scipy.stats.models as S -try: - import scipy.stats.models.bspline as B -except ImportError: - B = None - - class TestBSpline(TestCase): def test1(self): - if B: - b = B.BSpline(N.linspace(0,10,11), x=N.linspace(0,10,101)) - old = b._basisx.shape - b.x = N.linspace(0,10,51) - new = b._basisx.shape - self.assertEqual((old[0], 51), new) + b = bsp.BSpline(np.linspace(0,10,11), x=np.linspace(0,10,101)) + old = b._basisx.shape + b.x = np.linspace(0,10,51) + new = b._basisx.shape + self.assertEqual((old[0], 51), new) + def test2(self): + b = bsp.BSpline(np.linspace(0,1,11)) + x = np.array([0.4, 0.5]) + v = b.basis(x, lower=0, upper=13) + t = np.array([[ 0. , 0. ], + [ 0. , 0. ], + [ 0. , 0. ], + [ 0. , 0. ], + [ 0.16666667, 0. ], + [ 0.66666667, 0.16666667], + [ 0.16666667, 0.66666667], + [ 0. , 0.16666667], + [ 0. , 0. ], + [ 0. , 0. ], + [ 0. , 0. ], + [ 0. , 0. ], + [ 0. , 0. ]]) + assert_array_almost_equal(v, t, decimal=6) + + if __name__ == "__main__": run_module_suite() From scipy-svn at scipy.org Thu Aug 7 21:29:51 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Thu, 7 Aug 2008 20:29:51 -0500 (CDT) Subject: [Scipy-svn] r4613 - branches/stats_models/src Message-ID: <20080808012951.DC49239C088@scipy.org> Author: tom.waite Date: 2008-08-07 20:29:50 -0500 (Thu, 07 Aug 2008) New Revision: 4613 Modified: branches/stats_models/src/bspline_ext.c Log: weave to c-ext Modified: branches/stats_models/src/bspline_ext.c =================================================================== --- branches/stats_models/src/bspline_ext.c 2008-08-08 01:29:16 UTC (rev 4612) +++ branches/stats_models/src/bspline_ext.c 2008-08-08 01:29:50 UTC (rev 4613) @@ -3,7 +3,7 @@ /* function prototypes */ -double *bspline(double*, double*, int, double *, int, int, int, int, int); +double *bspline(double**, double*, int, double *, int, int, int, int, int); void bspline_gram(double **, double *, int, int, int, int); void invband_compute(double **, double *, int, int); @@ -15,8 +15,8 @@ double *L_data; npy_intp *dims_invband; npy_intp *dims_L; - PyObject *L = NULL; - PyObject *invband = NULL; + PyArrayObject *L = NULL; + PyArrayObject *invband = NULL; if(!PyArg_ParseTuple(args, "O", &L)) goto exit; @@ -28,14 +28,12 @@ dims_invband[0] = dims_L[0]; dims_invband[1] = dims_L[1]; - invband = (PyObject*)PyArray_SimpleNew(2, dims_invband, PyArray_DOUBLE); + invband = (PyArrayObject*)PyArray_SimpleNew(2, dims_invband, PyArray_DOUBLE); data = (double *)PyArray_DATA(invband); free(dims_invband); invband_compute(data, L_data, (int)dims_L[0], (int)dims_L[1]); - Py_DECREF(invband); - exit: return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("O", invband); @@ -51,11 +49,11 @@ int dl; int dr; double *knots; - double *data; + double **data; npy_intp *nknots; npy_intp *dims_gram; - PyObject *knots_array = NULL; - PyObject *gram_array = NULL; + PyArrayObject *knots_array = NULL; + PyArrayObject *gram_array = NULL; if(!PyArg_ParseTuple(args, "Oiii", &knots_array, &m, &dl, &dr)) goto exit; @@ -67,14 +65,12 @@ dims_gram[0] = (int)nknots[0] - m; dims_gram[1] = m; - gram_array = (PyObject*)PyArray_SimpleNew(2, dims_gram, PyArray_DOUBLE); - data = (double *)PyArray_DATA(gram_array); + gram_array = (PyArrayObject*)PyArray_SimpleNew(2, dims_gram, PyArray_DOUBLE); + data = (double **)PyArray_DATA(gram_array); free(dims_gram); bspline_gram(data, knots, (int)nknots[0], m, dl, dr); - Py_DECREF(gram_array); - exit: return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("O", gram_array); @@ -85,6 +81,7 @@ static PyObject *BSpline_Evaluate(PyObject *self, PyObject *args) { + int i; int upper; int lower; int m; @@ -94,10 +91,10 @@ double *data; npy_intp *nknots; npy_intp *nx; - npy_intp *dims_basis; - PyObject *knots_array = NULL; - PyObject *x_array = NULL; - PyObject *basis_array = NULL; + npy_intp dims_basis[2]; + PyArrayObject *knots_array = NULL; + PyArrayObject *x_array = NULL; + PyArrayObject *basis_array = NULL; if(!PyArg_ParseTuple(args, "OOiiii", &x_array, &knots_array, &m, &d, &lower, &upper)) goto exit; @@ -108,17 +105,13 @@ knots = (double *)PyArray_DATA(knots_array); x = (double *)PyArray_DATA(x_array); - dims_basis = calloc(2, sizeof(npy_intp)); dims_basis[0] = upper-lower; dims_basis[1] = (int)nx[0]; - basis_array = (PyObject*)PyArray_SimpleNew(2, dims_basis, PyArray_DOUBLE); + basis_array = (PyArrayObject*)PyArray_SimpleNew(2, dims_basis, PyArray_DOUBLE); data = (double *)PyArray_DATA(basis_array); - free(dims_basis); - bspline(data, x, (int)nx[0], knots, (int)nknots[0], m, d, lower, upper); + bspline(&data, x, (int)nx[0], knots, (int)nknots[0], m, d, lower, upper); - Py_DECREF(basis_array); - exit: return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("O", basis_array); @@ -134,7 +127,7 @@ { NULL, NULL, 0, NULL}, }; -PyMODINIT_FUNC init_segment(void) +PyMODINIT_FUNC init_hbspline(void) { Py_InitModule("_hbspline", BSplineMethods); import_array(); From scipy-svn at scipy.org Thu Aug 7 21:30:12 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Thu, 7 Aug 2008 20:30:12 -0500 (CDT) Subject: [Scipy-svn] r4614 - branches/stats_models/src Message-ID: <20080808013012.2624839C088@scipy.org> Author: tom.waite Date: 2008-08-07 20:30:10 -0500 (Thu, 07 Aug 2008) New Revision: 4614 Modified: branches/stats_models/src/bspline_impl.c Log: weave to c-ext Modified: branches/stats_models/src/bspline_impl.c =================================================================== --- branches/stats_models/src/bspline_impl.c 2008-08-08 01:29:50 UTC (rev 4613) +++ branches/stats_models/src/bspline_impl.c 2008-08-08 01:30:10 UTC (rev 4614) @@ -180,7 +180,7 @@ double *result, *bl, *br; int k; - if (fabs(r - l) <= m) { + if (abs(r - l) <= m) { result = (double *) malloc(sizeof(*result) * nx); bl = (double *) malloc(sizeof(*bl) * nx); br = (double *) malloc(sizeof(*br) * nx); From scipy-svn at scipy.org Thu Aug 7 21:30:32 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Thu, 7 Aug 2008 20:30:32 -0500 (CDT) Subject: [Scipy-svn] r4615 - branches/stats_models Message-ID: <20080808013032.B72D739C07C@scipy.org> Author: tom.waite Date: 2008-08-07 20:30:30 -0500 (Thu, 07 Aug 2008) New Revision: 4615 Modified: branches/stats_models/_bspline.py Log: weave to c-ext Modified: branches/stats_models/_bspline.py =================================================================== --- branches/stats_models/_bspline.py 2008-08-08 01:30:10 UTC (rev 4614) +++ branches/stats_models/_bspline.py 2008-08-08 01:30:30 UTC (rev 4615) @@ -20,7 +20,7 @@ from scipy.linalg import solveh_banded from scipy.optimize import golden -from scipy.stats.models import _bspline +from scipy.stats.models import _hbspline # Issue warning regarding heavy development status of this module @@ -198,6 +198,10 @@ Bspline to avoid extra evaluation in the __call__ method ''' + # FIXME: update parameter names, replace single character names + # FIXME: `order` should be actual spline order (implemented as order+1) + ## FIXME: update the use of spline order in extension code (evaluate is recursively called) + # FIXME: eliminate duplicate M and m attributes (m is order, M is related to tau size) def __init__(self, knots, order=4, M=None, coef=None, x=None): @@ -285,7 +289,7 @@ x.shape = (N.product(_shape,axis=0),) if i < self.tau.shape[0] - 1: ## TODO: OWNDATA flags... - v = _bspline.evaluate(x, self.tau, self.m, d, i, i+1) + v = _hbspline.evaluate(x, self.tau, self.m, d, i, i+1) else: return N.zeros(x.shape, N.float64) @@ -329,7 +333,7 @@ d = N.asarray(d) if d.shape == (): - v = _bspline.evaluate(x, self.tau, self.m, int(d), lower, upper) + v = _hbspline.evaluate(x, self.tau, self.m, int(d), lower, upper) else: if d.shape[0] != 2: raise ValueError, "if d is not an integer, expecting a jx2 \ @@ -338,7 +342,7 @@ v = 0 for i in range(d.shape[1]): - v += d[1,i] * _bspline.evaluate(x, self.tau, self.m, d[0,i], lower, upper) + v += d[1,i] * _hbspline.evaluate(x, self.tau, self.m, d[0,i], lower, upper) v.shape = (upper-lower,) + _shape if upper == self.tau.shape[0] - self.m: @@ -381,7 +385,7 @@ d = N.squeeze(d) if N.asarray(d).shape == (): - self.g = _bspline.gram(self.tau, self.m, int(d), int(d)) + self.g = _hbspline.gram(self.tau, self.m, int(d), int(d)) else: d = N.asarray(d) if d.shape[0] != 2: @@ -393,7 +397,7 @@ self.g = 0 for i in range(d.shape[1]): for j in range(d.shape[1]): - self.g += d[1,i]* d[1,j] * _bspline.gram(self.tau, self.m, int(d[0,i]), int(d[0,j])) + self.g += d[1,i]* d[1,j] * _hbspline.gram(self.tau, self.m, int(d[0,i]), int(d[0,j])) self.g = self.g.T self.d = d return N.nan_to_num(self.g) @@ -433,6 +437,8 @@ fhat = ARGMIN_f SUM_i=1^n (y_i-f(x_i))^2 + pen * int f^(2)^2 + int is integral. pen is lambda (from Hastie) + See Chapter 5 of Hastie, Tibshirani and Friedman (2001). "The Elements of Statistical @@ -561,7 +567,7 @@ """ if self.pen > 0: - _invband = _bspline.invband(self.chol.copy()) + _invband = _hbspline.invband(self.chol.copy()) tr = _trace_symbanded(_invband, self.btb, lower=1) return tr else: @@ -655,3 +661,8 @@ return a a = golden(_gcv, args=(y,x), brack=bracket, tol=tol) + + + + + From scipy-svn at scipy.org Fri Aug 8 01:33:12 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 00:33:12 -0500 (CDT) Subject: [Scipy-svn] r4616 - trunk/scipy/cluster/tests Message-ID: <20080808053312.4AF8C39C021@scipy.org> Author: jarrod.millman Date: 2008-08-08 00:33:08 -0500 (Fri, 08 Aug 2008) New Revision: 4616 Modified: trunk/scipy/cluster/tests/test_distance.py trunk/scipy/cluster/tests/test_hierarchy.py trunk/scipy/cluster/tests/test_vq.py Log: cleaning up numpy imports, use numpy.testing Modified: trunk/scipy/cluster/tests/test_distance.py =================================================================== --- trunk/scipy/cluster/tests/test_distance.py 2008-08-08 01:30:30 UTC (rev 4615) +++ trunk/scipy/cluster/tests/test_distance.py 2008-08-08 05:33:08 UTC (rev 4616) @@ -36,13 +36,12 @@ import sys import os.path -from scipy.testing import * + +import numpy as np +from numpy.testing import * from scipy.cluster.hierarchy import squareform, linkage, from_mlab_linkage, numobs_dm, numobs_y, numobs_linkage from scipy.cluster.distance import pdist, matching, jaccard, dice, sokalsneath, rogerstanimoto, russellrao, yule -import numpy -#import math - #from scipy.cluster.hierarchy import pdist, euclidean _filenames = ["iris.txt", @@ -68,7 +67,7 @@ "pdist-chebychev-ml-iris.txt", "random-bool-data.txt"] -_tdist = numpy.array([[0, 662, 877, 255, 412, 996], +_tdist = np.array([[0, 662, 877, 255, 412, 996], [662, 0, 295, 468, 268, 400], [877, 295, 0, 754, 564, 138], [255, 468, 754, 0, 219, 869], @@ -86,17 +85,17 @@ for fn in _filenames: name = fn.replace(".txt", "").replace("-ml", "") fqfn = os.path.join(os.path.dirname(__file__), fn) - eo[name] = numpy.loadtxt(open(fqfn)) + eo[name] = np.loadtxt(open(fqfn)) #print "%s: %s %s" % (name, str(eo[name].shape), str(eo[name].dtype)) - eo['pdist-boolean-inp'] = numpy.bool_(eo['pdist-boolean-inp']) + eo['pdist-boolean-inp'] = np.bool_(eo['pdist-boolean-inp']) load_testing_files() #print eo.keys() -#print numpy.abs(Y_test2 - Y_right).max() -#print numpy.abs(Y_test1 - Y_right).max() +#print np.abs(Y_test2 - Y_right).max() +#print np.abs(Y_test1 - Y_right).max() class TestPdist(TestCase): """ @@ -118,7 +117,7 @@ "Tests pdist(X, 'euclidean') on random data (float32)." eps = 1e-07 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['pdist-double-inp']) + X = np.float32(eo['pdist-double-inp']) Y_right = eo['pdist-euclidean'] Y_test1 = pdist(X, 'euclidean') @@ -147,11 +146,11 @@ "Tests pdist(X, 'euclidean') on the Iris data set. (float32)" eps = 1e-06 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['iris']) + X = np.float32(eo['iris']) Y_right = eo['pdist-euclidean-iris'] Y_test1 = pdist(X, 'euclidean') - print numpy.abs(Y_right - Y_test1).max() + print np.abs(Y_right - Y_test1).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_euclidean_iris_nonC(self): @@ -178,7 +177,7 @@ "Tests pdist(X, 'seuclidean') on random data (float32)." eps = 1e-05 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['pdist-double-inp']) + X = np.float32(eo['pdist-double-inp']) Y_right = eo['pdist-seuclidean'] Y_test1 = pdist(X, 'seuclidean') @@ -207,7 +206,7 @@ "Tests pdist(X, 'seuclidean') on the Iris data set (float32)." eps = 1e-05 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['iris']) + X = np.float32(eo['iris']) Y_right = eo['pdist-seuclidean-iris'] Y_test1 = pdist(X, 'seuclidean') @@ -236,7 +235,7 @@ "Tests pdist(X, 'cosine') on random data. (float32)" eps = 1e-08 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['pdist-double-inp']) + X = np.float32(eo['pdist-double-inp']) Y_right = eo['pdist-cosine'] Y_test1 = pdist(X, 'cosine') @@ -260,19 +259,19 @@ Y_test1 = pdist(X, 'cosine') self.failUnless(within_tol(Y_test1, Y_right, eps)) - #print "cosine-iris", numpy.abs(Y_test1 - Y_right).max() + #print "cosine-iris", np.abs(Y_test1 - Y_right).max() def test_pdist_cosine_iris_float32(self): "Tests pdist(X, 'cosine') on the Iris data set." eps = 1e-07 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['iris']) + X = np.float32(eo['iris']) Y_right = eo['pdist-cosine-iris'] Y_test1 = pdist(X, 'cosine') - print numpy.abs(Y_test1 - Y_right).max() + print np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) - #print "cosine-iris", numpy.abs(Y_test1 - Y_right).max() + #print "cosine-iris", np.abs(Y_test1 - Y_right).max() def test_pdist_cosine_iris_nonC(self): "Tests pdist(X, 'test_cosine') [the non-C implementation] on the Iris data set." @@ -291,17 +290,17 @@ X = eo['pdist-double-inp'] Y_right = eo['pdist-cityblock'] Y_test1 = pdist(X, 'cityblock') - #print "cityblock", numpy.abs(Y_test1 - Y_right).max() + #print "cityblock", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_cityblock_random_float32(self): "Tests pdist(X, 'cityblock') on random data. (float32)" eps = 1e-06 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['pdist-double-inp']) + X = np.float32(eo['pdist-double-inp']) Y_right = eo['pdist-cityblock'] Y_test1 = pdist(X, 'cityblock') - #print "cityblock", numpy.abs(Y_test1 - Y_right).max() + #print "cityblock", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_cityblock_random_nonC(self): @@ -322,17 +321,17 @@ Y_test1 = pdist(X, 'cityblock') self.failUnless(within_tol(Y_test1, Y_right, eps)) - #print "cityblock-iris", numpy.abs(Y_test1 - Y_right).max() + #print "cityblock-iris", np.abs(Y_test1 - Y_right).max() def test_pdist_cityblock_iris_float32(self): "Tests pdist(X, 'cityblock') on the Iris data set. (float32)" eps = 1e-06 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['iris']) + X = np.float32(eo['iris']) Y_right = eo['pdist-cityblock-iris'] Y_test1 = pdist(X, 'cityblock') - print "cityblock-iris-float32", numpy.abs(Y_test1 - Y_right).max() + print "cityblock-iris-float32", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_cityblock_iris_nonC(self): @@ -353,18 +352,18 @@ Y_right = eo['pdist-correlation'] Y_test1 = pdist(X, 'correlation') - #print "correlation", numpy.abs(Y_test1 - Y_right).max() + #print "correlation", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_correlation_random_float32(self): "Tests pdist(X, 'correlation') on random data. (float32)" eps = 1e-07 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['pdist-double-inp']) + X = np.float32(eo['pdist-double-inp']) Y_right = eo['pdist-correlation'] Y_test1 = pdist(X, 'correlation') - #print "correlation", numpy.abs(Y_test1 - Y_right).max() + #print "correlation", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_correlation_random_nonC(self): @@ -384,7 +383,7 @@ Y_right = eo['pdist-correlation-iris'] Y_test1 = pdist(X, 'correlation') - #print "correlation-iris", numpy.abs(Y_test1 - Y_right).max() + #print "correlation-iris", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_correlation_iris_float32(self): @@ -392,10 +391,10 @@ eps = 1e-07 # Get the data: the input matrix and the right output. X = eo['iris'] - Y_right = numpy.float32(eo['pdist-correlation-iris']) + Y_right = np.float32(eo['pdist-correlation-iris']) Y_test1 = pdist(X, 'correlation') - print "correlation-iris", numpy.abs(Y_test1 - Y_right).max() + print "correlation-iris", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_correlation_iris_nonC(self): @@ -405,7 +404,7 @@ X = eo['iris'] Y_right = eo['pdist-correlation-iris'] Y_test2 = pdist(X, 'test_correlation') - #print "test-correlation-iris", numpy.abs(Y_test2 - Y_right).max() + #print "test-correlation-iris", np.abs(Y_test2 - Y_right).max() self.failUnless(within_tol(Y_test2, Y_right, eps)) ################# minkowski @@ -418,18 +417,18 @@ Y_right = eo['pdist-minkowski-3.2'] Y_test1 = pdist(X, 'minkowski', 3.2) - #print "minkowski", numpy.abs(Y_test1 - Y_right).max() + #print "minkowski", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_minkowski_random_float32(self): "Tests pdist(X, 'minkowski') on random data. (float32)" eps = 1e-05 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['pdist-double-inp']) + X = np.float32(eo['pdist-double-inp']) Y_right = eo['pdist-minkowski-3.2'] Y_test1 = pdist(X, 'minkowski', 3.2) - #print "minkowski", numpy.abs(Y_test1 - Y_right).max() + #print "minkowski", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_minkowski_random_nonC(self): @@ -448,17 +447,17 @@ X = eo['iris'] Y_right = eo['pdist-minkowski-3.2-iris'] Y_test1 = pdist(X, 'minkowski', 3.2) - #print "minkowski-iris-3.2", numpy.abs(Y_test1 - Y_right).max() + #print "minkowski-iris-3.2", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_minkowski_iris_float32(self): "Tests pdist(X, 'minkowski') on iris data. (float32)" eps = 1e-07 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['iris']) + X = np.float32(eo['iris']) Y_right = eo['pdist-minkowski-3.2-iris'] Y_test1 = pdist(X, 'minkowski', 3.2) - #print "minkowski-iris-3.2", numpy.abs(Y_test1 - Y_right).max() + #print "minkowski-iris-3.2", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_minkowski_iris_nonC(self): @@ -477,18 +476,18 @@ X = eo['iris'] Y_right = eo['pdist-minkowski-5.8-iris'] Y_test1 = pdist(X, 'minkowski', 5.8) - #print "minkowski-iris-5.8", numpy.abs(Y_test1 - Y_right).max() + #print "minkowski-iris-5.8", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_minkowski_iris_float32(self): "Tests pdist(X, 'minkowski') on iris data. (float32)" eps = 1e-06 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['iris']) + X = np.float32(eo['iris']) Y_right = eo['pdist-minkowski-5.8-iris'] Y_test1 = pdist(X, 'minkowski', 5.8) - print "minkowski-iris-5.8", numpy.abs(Y_test1 - Y_right).max() + print "minkowski-iris-5.8", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_minkowski_iris_nonC(self): @@ -509,18 +508,18 @@ Y_right = eo['pdist-hamming'] Y_test1 = pdist(X, 'hamming') - #print "hamming", numpy.abs(Y_test1 - Y_right).max() + #print "hamming", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_hamming_random_float32(self): "Tests pdist(X, 'hamming') on random data." eps = 1e-07 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['pdist-boolean-inp']) + X = np.float32(eo['pdist-boolean-inp']) Y_right = eo['pdist-hamming'] Y_test1 = pdist(X, 'hamming') - #print "hamming", numpy.abs(Y_test1 - Y_right).max() + #print "hamming", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_hamming_random_nonC(self): @@ -530,7 +529,7 @@ X = eo['pdist-boolean-inp'] Y_right = eo['pdist-hamming'] Y_test2 = pdist(X, 'test_hamming') - #print "test-hamming", numpy.abs(Y_test2 - Y_right).max() + #print "test-hamming", np.abs(Y_test2 - Y_right).max() self.failUnless(within_tol(Y_test2, Y_right, eps)) ################### pdist: hamming (double) @@ -538,30 +537,30 @@ "Tests pdist(X, 'hamming') on random data." eps = 1e-07 # Get the data: the input matrix and the right output. - X = numpy.float64(eo['pdist-boolean-inp']) + X = np.float64(eo['pdist-boolean-inp']) Y_right = eo['pdist-hamming'] Y_test1 = pdist(X, 'hamming') - #print "hamming", numpy.abs(Y_test1 - Y_right).max() + #print "hamming", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_dhamming_random_float32(self): "Tests pdist(X, 'hamming') on random data. (float32)" eps = 1e-07 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['pdist-boolean-inp']) + X = np.float32(eo['pdist-boolean-inp']) Y_right = eo['pdist-hamming'] Y_test1 = pdist(X, 'hamming') - #print "hamming", numpy.abs(Y_test1 - Y_right).max() + #print "hamming", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_dhamming_random_nonC(self): "Tests pdist(X, 'test_hamming') [the non-C implementation] on random data." eps = 1e-07 # Get the data: the input matrix and the right output. - X = numpy.float64(eo['pdist-boolean-inp']) + X = np.float64(eo['pdist-boolean-inp']) Y_right = eo['pdist-hamming'] Y_test2 = pdist(X, 'test_hamming') - #print "test-hamming", numpy.abs(Y_test2 - Y_right).max() + #print "test-hamming", np.abs(Y_test2 - Y_right).max() self.failUnless(within_tol(Y_test2, Y_right, eps)) ################### pdist: jaccard @@ -573,18 +572,18 @@ Y_right = eo['pdist-jaccard'] Y_test1 = pdist(X, 'jaccard') - #print "jaccard", numpy.abs(Y_test1 - Y_right).max() + #print "jaccard", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_jaccard_random_float32(self): "Tests pdist(X, 'jaccard') on random data. (float32)" eps = 1e-08 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['pdist-boolean-inp']) + X = np.float32(eo['pdist-boolean-inp']) Y_right = eo['pdist-jaccard'] Y_test1 = pdist(X, 'jaccard') - #print "jaccard", numpy.abs(Y_test1 - Y_right).max() + #print "jaccard", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_jaccard_random_nonC(self): @@ -594,7 +593,7 @@ X = eo['pdist-boolean-inp'] Y_right = eo['pdist-jaccard'] Y_test2 = pdist(X, 'test_jaccard') - #print "test-jaccard", numpy.abs(Y_test2 - Y_right).max() + #print "test-jaccard", np.abs(Y_test2 - Y_right).max() self.failUnless(within_tol(Y_test2, Y_right, eps)) ################### pdist: jaccard (double) @@ -602,32 +601,32 @@ "Tests pdist(X, 'jaccard') on random data." eps = 1e-08 # Get the data: the input matrix and the right output. - X = numpy.float64(eo['pdist-boolean-inp']) + X = np.float64(eo['pdist-boolean-inp']) Y_right = eo['pdist-jaccard'] Y_test1 = pdist(X, 'jaccard') - #print "jaccard", numpy.abs(Y_test1 - Y_right).max() + #print "jaccard", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_djaccard_random_float32(self): "Tests pdist(X, 'jaccard') on random data. (float32)" eps = 1e-08 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['pdist-boolean-inp']) + X = np.float32(eo['pdist-boolean-inp']) Y_right = eo['pdist-jaccard'] Y_test1 = pdist(X, 'jaccard') - #print "jaccard", numpy.abs(Y_test1 - Y_right).max() + #print "jaccard", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_djaccard_random_nonC(self): "Tests pdist(X, 'test_jaccard') [the non-C implementation] on random data." eps = 1e-08 # Get the data: the input matrix and the right output. - X = numpy.float64(eo['pdist-boolean-inp']) + X = np.float64(eo['pdist-boolean-inp']) Y_right = eo['pdist-jaccard'] Y_test2 = pdist(X, 'test_jaccard') - #print "test-jaccard", numpy.abs(Y_test2 - Y_right).max() + #print "test-jaccard", np.abs(Y_test2 - Y_right).max() self.failUnless(within_tol(Y_test2, Y_right, eps)) ################### pdist: chebychev @@ -639,18 +638,18 @@ Y_right = eo['pdist-chebychev'] Y_test1 = pdist(X, 'chebychev') - #print "chebychev", numpy.abs(Y_test1 - Y_right).max() + #print "chebychev", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_chebychev_random_float32(self): "Tests pdist(X, 'chebychev') on random data. (float32)" eps = 1e-07 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['pdist-double-inp']) + X = np.float32(eo['pdist-double-inp']) Y_right = eo['pdist-chebychev'] Y_test1 = pdist(X, 'chebychev') - print "chebychev", numpy.abs(Y_test1 - Y_right).max() + print "chebychev", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_chebychev_random_nonC(self): @@ -660,7 +659,7 @@ X = eo['pdist-double-inp'] Y_right = eo['pdist-chebychev'] Y_test2 = pdist(X, 'test_chebychev') - #print "test-chebychev", numpy.abs(Y_test2 - Y_right).max() + #print "test-chebychev", np.abs(Y_test2 - Y_right).max() self.failUnless(within_tol(Y_test2, Y_right, eps)) def test_pdist_chebychev_iris(self): @@ -670,17 +669,17 @@ X = eo['iris'] Y_right = eo['pdist-chebychev-iris'] Y_test1 = pdist(X, 'chebychev') - #print "chebychev-iris", numpy.abs(Y_test1 - Y_right).max() + #print "chebychev-iris", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_chebychev_iris_float32(self): "Tests pdist(X, 'chebychev') on the Iris data set. (float32)" eps = 1e-06 # Get the data: the input matrix and the right output. - X = numpy.float32(eo['iris']) + X = np.float32(eo['iris']) Y_right = eo['pdist-chebychev-iris'] Y_test1 = pdist(X, 'chebychev') - print "chebychev-iris", numpy.abs(Y_test1 - Y_right).max() + print "chebychev-iris", np.abs(Y_test1 - Y_right).max() self.failUnless(within_tol(Y_test1, Y_right, eps)) def test_pdist_chebychev_iris_nonC(self): @@ -690,58 +689,58 @@ X = eo['iris'] Y_right = eo['pdist-chebychev-iris'] Y_test2 = pdist(X, 'test_chebychev') - #print "test-chebychev-iris", numpy.abs(Y_test2 - Y_right).max() + #print "test-chebychev-iris", np.abs(Y_test2 - Y_right).max() self.failUnless(within_tol(Y_test2, Y_right, eps)) def test_pdist_matching_mtica1(self): "Tests matching(*,*) with mtica example #1 (nums)." - m = matching(numpy.array([1, 0, 1, 1, 0]), - numpy.array([1, 1, 0, 1, 1])) - m2 = matching(numpy.array([1, 0, 1, 1, 0], dtype=numpy.bool), - numpy.array([1, 1, 0, 1, 1], dtype=numpy.bool)) - self.failUnless(numpy.abs(m - 0.6) <= 1e-10) - self.failUnless(numpy.abs(m2 - 0.6) <= 1e-10) + m = matching(np.array([1, 0, 1, 1, 0]), + np.array([1, 1, 0, 1, 1])) + m2 = matching(np.array([1, 0, 1, 1, 0], dtype=np.bool), + np.array([1, 1, 0, 1, 1], dtype=np.bool)) + self.failUnless(np.abs(m - 0.6) <= 1e-10) + self.failUnless(np.abs(m2 - 0.6) <= 1e-10) def test_pdist_matching_mtica2(self): "Tests matching(*,*) with mtica example #2." - m = matching(numpy.array([1, 0, 1]), - numpy.array([1, 1, 0])) - m2 = matching(numpy.array([1, 0, 1], dtype=numpy.bool), - numpy.array([1, 1, 0], dtype=numpy.bool)) - self.failUnless(numpy.abs(m - (2.0/3.0)) <= 1e-10) - self.failUnless(numpy.abs(m2 - (2.0/3.0)) <= 1e-10) + m = matching(np.array([1, 0, 1]), + np.array([1, 1, 0])) + m2 = matching(np.array([1, 0, 1], dtype=np.bool), + np.array([1, 1, 0], dtype=np.bool)) + self.failUnless(np.abs(m - (2.0/3.0)) <= 1e-10) + self.failUnless(np.abs(m2 - (2.0/3.0)) <= 1e-10) def test_pdist_matching_match(self): "Tests pdist(X, 'matching') to see if the two implementations match on random boolean input data." D = eo['random-bool-data'] - B = numpy.bool_(D) + B = np.bool_(D) print B.shape, B.dtype eps = 1e-10 y1 = pdist(B, "matching") y2 = pdist(B, "test_matching") y3 = pdist(D, "test_matching") - print numpy.abs(y1-y2).max() - print numpy.abs(y1-y3).max() + print np.abs(y1-y2).max() + print np.abs(y1-y3).max() self.failUnless(within_tol(y1, y2, eps)) self.failUnless(within_tol(y2, y3, eps)) def test_pdist_jaccard_mtica1(self): "Tests jaccard(*,*) with mtica example #1." - m = jaccard(numpy.array([1, 0, 1, 1, 0]), - numpy.array([1, 1, 0, 1, 1])) - m2 = jaccard(numpy.array([1, 0, 1, 1, 0], dtype=numpy.bool), - numpy.array([1, 1, 0, 1, 1], dtype=numpy.bool)) - self.failUnless(numpy.abs(m - 0.6) <= 1e-10) - self.failUnless(numpy.abs(m2 - 0.6) <= 1e-10) + m = jaccard(np.array([1, 0, 1, 1, 0]), + np.array([1, 1, 0, 1, 1])) + m2 = jaccard(np.array([1, 0, 1, 1, 0], dtype=np.bool), + np.array([1, 1, 0, 1, 1], dtype=np.bool)) + self.failUnless(np.abs(m - 0.6) <= 1e-10) + self.failUnless(np.abs(m2 - 0.6) <= 1e-10) def test_pdist_jaccard_mtica2(self): "Tests jaccard(*,*) with mtica example #2." - m = jaccard(numpy.array([1, 0, 1]), - numpy.array([1, 1, 0])) - m2 = jaccard(numpy.array([1, 0, 1], dtype=numpy.bool), - numpy.array([1, 1, 0], dtype=numpy.bool)) - self.failUnless(numpy.abs(m - (2.0/3.0)) <= 1e-10) - self.failUnless(numpy.abs(m2 - (2.0/3.0)) <= 1e-10) + m = jaccard(np.array([1, 0, 1]), + np.array([1, 1, 0])) + m2 = jaccard(np.array([1, 0, 1], dtype=np.bool), + np.array([1, 1, 0], dtype=np.bool)) + self.failUnless(np.abs(m - (2.0/3.0)) <= 1e-10) + self.failUnless(np.abs(m2 - (2.0/3.0)) <= 1e-10) def test_pdist_jaccard_match(self): "Tests pdist(X, 'jaccard') to see if the two implementations match on random double input data." @@ -750,31 +749,31 @@ eps = 1e-10 y1 = pdist(D, "jaccard") y2 = pdist(D, "test_jaccard") - y3 = pdist(numpy.bool_(D), "test_jaccard") - print numpy.abs(y1-y2).max() - print numpy.abs(y2-y3).max() + y3 = pdist(np.bool_(D), "test_jaccard") + print np.abs(y1-y2).max() + print np.abs(y2-y3).max() self.failUnless(within_tol(y1, y2, eps)) self.failUnless(within_tol(y2, y3, eps)) def test_pdist_yule_mtica1(self): "Tests yule(*,*) with mtica example #1." - m = yule(numpy.array([1, 0, 1, 1, 0]), - numpy.array([1, 1, 0, 1, 1])) - m2 = yule(numpy.array([1, 0, 1, 1, 0], dtype=numpy.bool), - numpy.array([1, 1, 0, 1, 1], dtype=numpy.bool)) + m = yule(np.array([1, 0, 1, 1, 0]), + np.array([1, 1, 0, 1, 1])) + m2 = yule(np.array([1, 0, 1, 1, 0], dtype=np.bool), + np.array([1, 1, 0, 1, 1], dtype=np.bool)) print m - self.failUnless(numpy.abs(m - 2.0) <= 1e-10) - self.failUnless(numpy.abs(m2 - 2.0) <= 1e-10) + self.failUnless(np.abs(m - 2.0) <= 1e-10) + self.failUnless(np.abs(m2 - 2.0) <= 1e-10) def test_pdist_yule_mtica2(self): "Tests yule(*,*) with mtica example #2." - m = yule(numpy.array([1, 0, 1]), - numpy.array([1, 1, 0])) - m2 = yule(numpy.array([1, 0, 1], dtype=numpy.bool), - numpy.array([1, 1, 0], dtype=numpy.bool)) + m = yule(np.array([1, 0, 1]), + np.array([1, 1, 0])) + m2 = yule(np.array([1, 0, 1], dtype=np.bool), + np.array([1, 1, 0], dtype=np.bool)) print m - self.failUnless(numpy.abs(m - 2.0) <= 1e-10) - self.failUnless(numpy.abs(m2 - 2.0) <= 1e-10) + self.failUnless(np.abs(m - 2.0) <= 1e-10) + self.failUnless(np.abs(m2 - 2.0) <= 1e-10) def test_pdist_yule_match(self): "Tests pdist(X, 'yule') to see if the two implementations match on random double input data." @@ -783,31 +782,31 @@ eps = 1e-10 y1 = pdist(D, "yule") y2 = pdist(D, "test_yule") - y3 = pdist(numpy.bool_(D), "test_yule") - print numpy.abs(y1-y2).max() - print numpy.abs(y2-y3).max() + y3 = pdist(np.bool_(D), "test_yule") + print np.abs(y1-y2).max() + print np.abs(y2-y3).max() self.failUnless(within_tol(y1, y2, eps)) self.failUnless(within_tol(y2, y3, eps)) def test_pdist_dice_mtica1(self): "Tests dice(*,*) with mtica example #1." - m = dice(numpy.array([1, 0, 1, 1, 0]), - numpy.array([1, 1, 0, 1, 1])) - m2 = dice(numpy.array([1, 0, 1, 1, 0], dtype=numpy.bool), - numpy.array([1, 1, 0, 1, 1], dtype=numpy.bool)) + m = dice(np.array([1, 0, 1, 1, 0]), + np.array([1, 1, 0, 1, 1])) + m2 = dice(np.array([1, 0, 1, 1, 0], dtype=np.bool), + np.array([1, 1, 0, 1, 1], dtype=np.bool)) print m - self.failUnless(numpy.abs(m - (3.0/7.0)) <= 1e-10) - self.failUnless(numpy.abs(m2 - (3.0/7.0)) <= 1e-10) + self.failUnless(np.abs(m - (3.0/7.0)) <= 1e-10) + self.failUnless(np.abs(m2 - (3.0/7.0)) <= 1e-10) def test_pdist_dice_mtica2(self): "Tests dice(*,*) with mtica example #2." - m = dice(numpy.array([1, 0, 1]), - numpy.array([1, 1, 0])) - m2 = dice(numpy.array([1, 0, 1], dtype=numpy.bool), - numpy.array([1, 1, 0], dtype=numpy.bool)) + m = dice(np.array([1, 0, 1]), + np.array([1, 1, 0])) + m2 = dice(np.array([1, 0, 1], dtype=np.bool), + np.array([1, 1, 0], dtype=np.bool)) print m - self.failUnless(numpy.abs(m - 0.5) <= 1e-10) - self.failUnless(numpy.abs(m2 - 0.5) <= 1e-10) + self.failUnless(np.abs(m - 0.5) <= 1e-10) + self.failUnless(np.abs(m2 - 0.5) <= 1e-10) def test_pdist_dice_match(self): "Tests pdist(X, 'dice') to see if the two implementations match on random double input data." @@ -817,30 +816,30 @@ y1 = pdist(D, "dice") y2 = pdist(D, "test_dice") y3 = pdist(D, "test_dice") - print numpy.abs(y1-y2).max() - print numpy.abs(y2-y3).max() + print np.abs(y1-y2).max() + print np.abs(y2-y3).max() self.failUnless(within_tol(y1, y2, eps)) self.failUnless(within_tol(y2, y3, eps)) def test_pdist_sokalsneath_mtica1(self): "Tests sokalsneath(*,*) with mtica example #1." - m = sokalsneath(numpy.array([1, 0, 1, 1, 0]), - numpy.array([1, 1, 0, 1, 1])) - m2 = sokalsneath(numpy.array([1, 0, 1, 1, 0], dtype=numpy.bool), - numpy.array([1, 1, 0, 1, 1], dtype=numpy.bool)) + m = sokalsneath(np.array([1, 0, 1, 1, 0]), + np.array([1, 1, 0, 1, 1])) + m2 = sokalsneath(np.array([1, 0, 1, 1, 0], dtype=np.bool), + np.array([1, 1, 0, 1, 1], dtype=np.bool)) print m - self.failUnless(numpy.abs(m - (3.0/4.0)) <= 1e-10) - self.failUnless(numpy.abs(m2 - (3.0/4.0)) <= 1e-10) + self.failUnless(np.abs(m - (3.0/4.0)) <= 1e-10) + self.failUnless(np.abs(m2 - (3.0/4.0)) <= 1e-10) def test_pdist_sokalsneath_mtica2(self): "Tests sokalsneath(*,*) with mtica example #2." - m = sokalsneath(numpy.array([1, 0, 1]), - numpy.array([1, 1, 0])) - m2 = sokalsneath(numpy.array([1, 0, 1], dtype=numpy.bool), - numpy.array([1, 1, 0], dtype=numpy.bool)) + m = sokalsneath(np.array([1, 0, 1]), + np.array([1, 1, 0])) + m2 = sokalsneath(np.array([1, 0, 1], dtype=np.bool), + np.array([1, 1, 0], dtype=np.bool)) print m - self.failUnless(numpy.abs(m - (4.0/5.0)) <= 1e-10) - self.failUnless(numpy.abs(m2 - (4.0/5.0)) <= 1e-10) + self.failUnless(np.abs(m - (4.0/5.0)) <= 1e-10) + self.failUnless(np.abs(m2 - (4.0/5.0)) <= 1e-10) def test_pdist_sokalsneath_match(self): "Tests pdist(X, 'sokalsneath') to see if the two implementations match on random double input data." @@ -849,31 +848,31 @@ eps = 1e-10 y1 = pdist(D, "sokalsneath") y2 = pdist(D, "test_sokalsneath") - y3 = pdist(numpy.bool_(D), "test_sokalsneath") - print numpy.abs(y1-y2).max() - print numpy.abs(y2-y3).max() + y3 = pdist(np.bool_(D), "test_sokalsneath") + print np.abs(y1-y2).max() + print np.abs(y2-y3).max() self.failUnless(within_tol(y1, y2, eps)) self.failUnless(within_tol(y2, y3, eps)) def test_pdist_rogerstanimoto_mtica1(self): "Tests rogerstanimoto(*,*) with mtica example #1." - m = rogerstanimoto(numpy.array([1, 0, 1, 1, 0]), - numpy.array([1, 1, 0, 1, 1])) - m2 = rogerstanimoto(numpy.array([1, 0, 1, 1, 0], dtype=numpy.bool), - numpy.array([1, 1, 0, 1, 1], dtype=numpy.bool)) + m = rogerstanimoto(np.array([1, 0, 1, 1, 0]), + np.array([1, 1, 0, 1, 1])) + m2 = rogerstanimoto(np.array([1, 0, 1, 1, 0], dtype=np.bool), + np.array([1, 1, 0, 1, 1], dtype=np.bool)) print m - self.failUnless(numpy.abs(m - (3.0/4.0)) <= 1e-10) - self.failUnless(numpy.abs(m2 - (3.0/4.0)) <= 1e-10) + self.failUnless(np.abs(m - (3.0/4.0)) <= 1e-10) + self.failUnless(np.abs(m2 - (3.0/4.0)) <= 1e-10) def test_pdist_rogerstanimoto_mtica2(self): "Tests rogerstanimoto(*,*) with mtica example #2." - m = rogerstanimoto(numpy.array([1, 0, 1]), - numpy.array([1, 1, 0])) - m2 = rogerstanimoto(numpy.array([1, 0, 1], dtype=numpy.bool), - numpy.array([1, 1, 0], dtype=numpy.bool)) + m = rogerstanimoto(np.array([1, 0, 1]), + np.array([1, 1, 0])) + m2 = rogerstanimoto(np.array([1, 0, 1], dtype=np.bool), + np.array([1, 1, 0], dtype=np.bool)) print m - self.failUnless(numpy.abs(m - (4.0/5.0)) <= 1e-10) - self.failUnless(numpy.abs(m2 - (4.0/5.0)) <= 1e-10) + self.failUnless(np.abs(m - (4.0/5.0)) <= 1e-10) + self.failUnless(np.abs(m2 - (4.0/5.0)) <= 1e-10) def test_pdist_rogerstanimoto_match(self): "Tests pdist(X, 'rogerstanimoto') to see if the two implementations match on random double input data." @@ -882,31 +881,31 @@ eps = 1e-10 y1 = pdist(D, "rogerstanimoto") y2 = pdist(D, "test_rogerstanimoto") - y3 = pdist(numpy.bool_(D), "test_rogerstanimoto") - print numpy.abs(y1-y2).max() - print numpy.abs(y2-y3).max() + y3 = pdist(np.bool_(D), "test_rogerstanimoto") + print np.abs(y1-y2).max() + print np.abs(y2-y3).max() self.failUnless(within_tol(y1, y2, eps)) self.failUnless(within_tol(y2, y3, eps)) def test_pdist_russellrao_mtica1(self): "Tests russellrao(*,*) with mtica example #1." - m = russellrao(numpy.array([1, 0, 1, 1, 0]), - numpy.array([1, 1, 0, 1, 1])) - m2 = russellrao(numpy.array([1, 0, 1, 1, 0], dtype=numpy.bool), - numpy.array([1, 1, 0, 1, 1], dtype=numpy.bool)) + m = russellrao(np.array([1, 0, 1, 1, 0]), + np.array([1, 1, 0, 1, 1])) + m2 = russellrao(np.array([1, 0, 1, 1, 0], dtype=np.bool), + np.array([1, 1, 0, 1, 1], dtype=np.bool)) print m - self.failUnless(numpy.abs(m - (3.0/5.0)) <= 1e-10) - self.failUnless(numpy.abs(m2 - (3.0/5.0)) <= 1e-10) + self.failUnless(np.abs(m - (3.0/5.0)) <= 1e-10) + self.failUnless(np.abs(m2 - (3.0/5.0)) <= 1e-10) def test_pdist_russellrao_mtica2(self): "Tests russellrao(*,*) with mtica example #2." - m = russellrao(numpy.array([1, 0, 1]), - numpy.array([1, 1, 0])) - m2 = russellrao(numpy.array([1, 0, 1], dtype=numpy.bool), - numpy.array([1, 1, 0], dtype=numpy.bool)) + m = russellrao(np.array([1, 0, 1]), + np.array([1, 1, 0])) + m2 = russellrao(np.array([1, 0, 1], dtype=np.bool), + np.array([1, 1, 0], dtype=np.bool)) print m - self.failUnless(numpy.abs(m - (2.0/3.0)) <= 1e-10) - self.failUnless(numpy.abs(m2 - (2.0/3.0)) <= 1e-10) + self.failUnless(np.abs(m - (2.0/3.0)) <= 1e-10) + self.failUnless(np.abs(m2 - (2.0/3.0)) <= 1e-10) def test_pdist_russellrao_match(self): "Tests pdist(X, 'russellrao') to see if the two implementations match on random double input data." @@ -915,9 +914,9 @@ eps = 1e-10 y1 = pdist(D, "russellrao") y2 = pdist(D, "test_russellrao") - y3 = pdist(numpy.bool_(D), "test_russellrao") - print numpy.abs(y1-y2).max() - print numpy.abs(y2-y3).max() + y3 = pdist(np.bool_(D), "test_russellrao") + print np.abs(y1-y2).max() + print np.abs(y2-y3).max() self.failUnless(within_tol(y1, y2, eps)) self.failUnless(within_tol(y2, y3, eps)) @@ -928,9 +927,9 @@ eps = 1e-10 y1 = pdist(D, "sokalmichener") y2 = pdist(D, "test_sokalmichener") - y3 = pdist(numpy.bool_(D), "test_sokalmichener") - print numpy.abs(y1-y2).max() - print numpy.abs(y2-y3).max() + y3 = pdist(np.bool_(D), "test_sokalmichener") + print np.abs(y1-y2).max() + print np.abs(y2-y3).max() self.failUnless(within_tol(y1, y2, eps)) self.failUnless(within_tol(y2, y3, eps)) @@ -941,9 +940,9 @@ eps = 1e-10 y1 = pdist(D, "kulsinski") y2 = pdist(D, "test_kulsinski") - y3 = pdist(numpy.bool_(D), "test_kulsinski") - print numpy.abs(y1-y2).max() + y3 = pdist(np.bool_(D), "test_kulsinski") + print np.abs(y1-y2).max() self.failUnless(within_tol(y1, y2, eps)) def within_tol(a, b, tol): - return numpy.abs(a - b).max() < tol + return np.abs(a - b).max() < tol Modified: trunk/scipy/cluster/tests/test_hierarchy.py =================================================================== --- trunk/scipy/cluster/tests/test_hierarchy.py 2008-08-08 01:30:30 UTC (rev 4615) +++ trunk/scipy/cluster/tests/test_hierarchy.py 2008-08-08 05:33:08 UTC (rev 4616) @@ -35,13 +35,14 @@ import sys import os.path -import numpy +import numpy as np from numpy.testing import * + from scipy.cluster.hierarchy import squareform, linkage, from_mlab_linkage, numobs_dm, numobs_y, numobs_linkage, inconsistent from scipy.cluster.distance import pdist, matching, jaccard, dice, sokalsneath, rogerstanimoto, russellrao, yule -_tdist = numpy.array([[0, 662, 877, 255, 412, 996], +_tdist = np.array([[0, 662, 877, 255, 412, 996], [662, 0, 295, 468, 268, 400], [877, 295, 0, 754, 564, 138], [255, 468, 754, 0, 219, 869], @@ -79,9 +80,9 @@ for fn in _filenames: name = fn.replace(".txt", "").replace("-ml", "") fqfn = os.path.join(os.path.dirname(__file__), fn) - eo[name] = numpy.loadtxt(open(fqfn)) + eo[name] = np.loadtxt(open(fqfn)) #print "%s: %s %s" % (name, str(eo[name].shape), str(eo[name].dtype)) - #eo['pdist-boolean-inp'] = numpy.bool_(eo['pdist-boolean-inp']) + #eo['pdist-boolean-inp'] = np.bool_(eo['pdist-boolean-inp']) load_testing_files() @@ -90,36 +91,36 @@ ################### squareform def test_squareform_empty_matrix(self): "Tests squareform on an empty matrix." - A = numpy.zeros((0,0)) - rA = squareform(numpy.array(A, dtype='double')) + A = np.zeros((0,0)) + rA = squareform(np.array(A, dtype='double')) self.failUnless(rA.shape == (0,)) def test_squareform_empty_vector(self): - v = numpy.zeros((0,)) - rv = squareform(numpy.array(v, dtype='double')) + v = np.zeros((0,)) + rv = squareform(np.array(v, dtype='double')) self.failUnless(rv.shape == (1,1)) self.failUnless(rv[0, 0] == 0) def test_squareform_1by1_matrix(self): "Tests squareform on a 1x1 matrix." - A = numpy.zeros((1,1)) - rA = squareform(numpy.array(A, dtype='double')) + A = np.zeros((1,1)) + rA = squareform(np.array(A, dtype='double')) self.failUnless(rA.shape == (0,)) def test_squareform_one_vector(self): "Tests squareform on a 1-D array, length=1." - v = numpy.ones((1,)) * 8.3 - rv = squareform(numpy.array(v, dtype='double')) + v = np.ones((1,)) * 8.3 + rv = squareform(np.array(v, dtype='double')) self.failUnless(rv.shape == (2,2)) self.failUnless(rv[0,1] == 8.3) self.failUnless(rv[1,0] == 8.3) def test_squareform_2by2_matrix(self): "Tests squareform on a 2x2 matrix." - A = numpy.zeros((2,2)) + A = np.zeros((2,2)) A[0,1]=0.8 A[1,0]=0.8 - rA = squareform(numpy.array(A, dtype='double')) + rA = squareform(np.array(A, dtype='double')) self.failUnless(rA.shape == (1,)) self.failUnless(rA[0] == 0.8) @@ -129,7 +130,7 @@ yield self.check_squareform_multi_matrix(n) def check_squareform_multi_matrix(self, n): - X = numpy.random.rand(n, 4) + X = np.random.rand(n, 4) Y = pdist(X) self.failUnless(len(Y.shape) == 1) A = squareform(Y) @@ -156,7 +157,7 @@ def test_numobs_dm_multi_matrix(self): "Tests numobs_dm with observation matrices of multiple sizes." for n in xrange(1, 10): - X = numpy.random.rand(n, 4) + X = np.random.rand(n, 4) Y = pdist(X) A = squareform(Y) if verbose >= 3: @@ -166,7 +167,7 @@ def test_numobs_y_multi_matrix(self): "Tests numobs_y with observation matrices of multiple sizes." for n in xrange(2, 10): - X = numpy.random.rand(n, 4) + X = np.random.rand(n, 4) Y = pdist(X) #print A.shape, Y.shape, Yr.shape self.failUnless(numobs_y(Y) == n) @@ -174,7 +175,7 @@ def test_numobs_linkage_multi_matrix(self): "Tests numobs_linkage with observation matrices of multiple sizes." for n in xrange(2, 10): - X = numpy.random.rand(n, 4) + X = np.random.rand(n, 4) Y = pdist(X) Z = linkage(Y) #print Z @@ -206,7 +207,7 @@ Zmlab = eo['linkage-average-tdist'] eps = 1e-05 expectedZ = from_mlab_linkage(Zmlab) - #print Z, expectedZ, numpy.abs(Z - expectedZ).max() + #print Z, expectedZ, np.abs(Z - expectedZ).max() self.failUnless(within_tol(Z, expectedZ, eps)) def test_linkage_weighted_tdist(self): @@ -215,7 +216,7 @@ Zmlab = eo['linkage-weighted-tdist'] eps = 1e-10 expectedZ = from_mlab_linkage(Zmlab) - #print Z, expectedZ, numpy.abs(Z - expectedZ).max() + #print Z, expectedZ, np.abs(Z - expectedZ).max() self.failUnless(within_tol(Z, expectedZ, eps)) class TestInconsistent(TestCase): @@ -230,12 +231,11 @@ R = inconsistent(Z, i) Rright = eo['inconsistent-single-tdist-depth-' + str(i)] eps = 1e-05 - print numpy.abs(R - Rright).max() + print np.abs(R - Rright).max() self.failUnless(within_tol(R, Rright, eps)) def within_tol(a, b, tol): - return numpy.abs(a - b).max() < tol + return np.abs(a - b).max() < tol if __name__ == "__main__": run_module_suite() - Modified: trunk/scipy/cluster/tests/test_vq.py =================================================================== --- trunk/scipy/cluster/tests/test_vq.py 2008-08-08 01:30:30 UTC (rev 4615) +++ trunk/scipy/cluster/tests/test_vq.py 2008-08-08 05:33:08 UTC (rev 4616) @@ -3,15 +3,12 @@ # David Cournapeau # Last Change: Tue Jun 24 04:00 PM 2008 J -# For now, just copy the tests from sandbox.pyem, so we can check that -# kmeans works OK for trivial examples. - import sys import os.path + +import numpy as np from numpy.testing import * -import numpy as N - from scipy.cluster.vq import kmeans, kmeans2, py_vq, py_vq2, _py_vq_1d, vq, ClusterError try: from scipy.cluster import _vq @@ -25,35 +22,35 @@ DATAFILE1 = os.path.join(os.path.dirname(__file__), "data.txt") # Global data -X = N.array([[3.0, 3], [4, 3], [4, 2], +X = np.array([[3.0, 3], [4, 3], [4, 2], [9, 2], [5, 1], [6, 2], [9, 4], [5, 2], [5, 4], [7, 4], [6, 5]]) -CODET1 = N.array([[3.0000, 3.0000], +CODET1 = np.array([[3.0000, 3.0000], [6.2000, 4.0000], [5.8000, 1.8000]]) -CODET2 = N.array([[11.0/3, 8.0/3], +CODET2 = np.array([[11.0/3, 8.0/3], [6.7500, 4.2500], [6.2500, 1.7500]]) -LABEL1 = N.array([0, 1, 2, 2, 2, 2, 1, 2, 1, 1, 1]) +LABEL1 = np.array([0, 1, 2, 2, 2, 2, 1, 2, 1, 1, 1]) class TestVq(TestCase): def test_py_vq(self): - initc = N.concatenate(([[X[0]], [X[1]], [X[2]]])) + initc = np.concatenate(([[X[0]], [X[1]], [X[2]]])) code = initc.copy() label1 = py_vq(X, initc)[0] assert_array_equal(label1, LABEL1) def test_py_vq2(self): - initc = N.concatenate(([[X[0]], [X[1]], [X[2]]])) + initc = np.concatenate(([[X[0]], [X[1]], [X[2]]])) code = initc.copy() label1 = py_vq2(X, initc)[0] assert_array_equal(label1, LABEL1) def test_vq(self): - initc = N.concatenate(([[X[0]], [X[1]], [X[2]]])) + initc = np.concatenate(([[X[0]], [X[1]], [X[2]]])) code = initc.copy() if TESTC: label1, dist = _vq.vq(X, initc) @@ -68,7 +65,7 @@ # initc = data[:3] # code = initc.copy() # a, b = _py_vq_1d(data, initc) - # ta, tb = py_vq(data[:, N.newaxis], initc[:, N.newaxis]) + # ta, tb = py_vq(data[:, np.newaxis], initc[:, np.newaxis]) # assert_array_equal(a, ta) # assert_array_equal(b, tb) @@ -79,7 +76,7 @@ code = initc.copy() if TESTC: a, b = _vq.vq(data, initc) - ta, tb = py_vq(data[:, N.newaxis], initc[:, N.newaxis]) + ta, tb = py_vq(data[:, np.newaxis], initc[:, np.newaxis]) assert_array_equal(a, ta) assert_array_equal(b, tb) else: @@ -87,7 +84,7 @@ class TestKMean(TestCase): def test_kmeans_simple(self): - initc = N.concatenate(([[X[0]], [X[1]], [X[2]]])) + initc = np.concatenate(([[X[0]], [X[1]], [X[2]]])) code = initc.copy() code1 = kmeans(X, code, iter = 1)[0] @@ -95,9 +92,9 @@ def test_kmeans_lost_cluster(self): """This will cause kmean to have a cluster with no points.""" - data = N.fromfile(open(DATAFILE1), sep = ", ") + data = np.fromfile(open(DATAFILE1), sep = ", ") data = data.reshape((200, 2)) - initk = N.array([[-1.8127404, -0.67128041], + initk = np.array([[-1.8127404, -0.67128041], [ 2.04621601, 0.07401111], [-2.31149087,-0.05160469]]) @@ -111,7 +108,7 @@ def test_kmeans2_simple(self): """Testing simple call to kmeans2 and its results.""" - initc = N.concatenate(([[X[0]], [X[1]], [X[2]]])) + initc = np.concatenate(([[X[0]], [X[1]], [X[2]]])) code = initc.copy() code1 = kmeans2(X, code, iter = 1)[0] code2 = kmeans2(X, code, iter = 2)[0] @@ -121,7 +118,7 @@ def test_kmeans2_rank1(self): """Testing simple call to kmeans2 with rank 1 data.""" - data = N.fromfile(open(DATAFILE1), sep = ", ") + data = np.fromfile(open(DATAFILE1), sep = ", ") data = data.reshape((200, 2)) data1 = data[:, 0] data2 = data[:, 1] @@ -133,7 +130,7 @@ def test_kmeans2_rank1_2(self): """Testing simple call to kmeans2 with rank 1 data.""" - data = N.fromfile(open(DATAFILE1), sep = ", ") + data = np.fromfile(open(DATAFILE1), sep = ", ") data = data.reshape((200, 2)) data1 = data[:, 0] @@ -141,7 +138,7 @@ def test_kmeans2_init(self): """Testing that kmeans2 init methods work.""" - data = N.fromfile(open(DATAFILE1), sep = ", ") + data = np.fromfile(open(DATAFILE1), sep = ", ") data = data.reshape((200, 2)) kmeans2(data, 3, minit = 'random') @@ -176,7 +173,7 @@ pass try: - kmeans2(X, N.array([])) + kmeans2(X, np.array([])) raise AssertionError("kmeans2 with 0 clusters should fail.") except ValueError: pass From scipy-svn at scipy.org Fri Aug 8 02:06:27 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 01:06:27 -0500 (CDT) Subject: [Scipy-svn] r4617 - in trunk/scipy: sandbox/cdavid/tests sandbox/spline/tests weave/tests Message-ID: <20080808060627.59FC139C021@scipy.org> Author: jarrod.millman Date: 2008-08-08 01:06:21 -0500 (Fri, 08 Aug 2008) New Revision: 4617 Modified: trunk/scipy/sandbox/cdavid/tests/test_segmentaxis.py trunk/scipy/sandbox/spline/tests/test_fitpack.py trunk/scipy/sandbox/spline/tests/test_spline.py trunk/scipy/weave/tests/test_ast_tools.py trunk/scipy/weave/tests/test_blitz_tools.py trunk/scipy/weave/tests/test_catalog.py trunk/scipy/weave/tests/test_ext_tools.py trunk/scipy/weave/tests/test_inline_tools.py trunk/scipy/weave/tests/test_scxx.py Log: remove old code Modified: trunk/scipy/sandbox/cdavid/tests/test_segmentaxis.py =================================================================== --- trunk/scipy/sandbox/cdavid/tests/test_segmentaxis.py 2008-08-08 05:33:08 UTC (rev 4616) +++ trunk/scipy/sandbox/cdavid/tests/test_segmentaxis.py 2008-08-08 06:06:21 UTC (rev 4617) @@ -3,61 +3,57 @@ from numpy.testing import * -import numpy as N +import numpy as np from scipy.sandbox.cdavid.segmentaxis import segment_axis -# #Optional: -# set_local_path() -# # import modules that are located in the same directory as this file. - class TestSegment(TestCase): def test_simple(self): - assert_equal(segment_axis(N.arange(6),length=3,overlap=0), - N.array([[0,1,2],[3,4,5]])) + assert_equal(segment_axis(np.arange(6),length=3,overlap=0), + np.array([[0,1,2],[3,4,5]])) - assert_equal(segment_axis(N.arange(7),length=3,overlap=1), - N.array([[0,1,2],[2,3,4],[4,5,6]])) + assert_equal(segment_axis(np.arange(7),length=3,overlap=1), + np.array([[0,1,2],[2,3,4],[4,5,6]])) - assert_equal(segment_axis(N.arange(7),length=3,overlap=2), - N.array([[0,1,2],[1,2,3],[2,3,4],[3,4,5],[4,5,6]])) + assert_equal(segment_axis(np.arange(7),length=3,overlap=2), + np.array([[0,1,2],[1,2,3],[2,3,4],[3,4,5],[4,5,6]])) def test_error_checking(self): self.assertRaises(ValueError, - lambda: segment_axis(N.arange(7),length=3,overlap=-1)) + lambda: segment_axis(np.arange(7),length=3,overlap=-1)) self.assertRaises(ValueError, - lambda: segment_axis(N.arange(7),length=0,overlap=0)) + lambda: segment_axis(np.arange(7),length=0,overlap=0)) self.assertRaises(ValueError, - lambda: segment_axis(N.arange(7),length=3,overlap=3)) + lambda: segment_axis(np.arange(7),length=3,overlap=3)) self.assertRaises(ValueError, - lambda: segment_axis(N.arange(7),length=8,overlap=3)) + lambda: segment_axis(np.arange(7),length=8,overlap=3)) def test_ending(self): - assert_equal(segment_axis(N.arange(6),length=3,overlap=1,end='cut'), - N.array([[0,1,2],[2,3,4]])) - assert_equal(segment_axis(N.arange(6),length=3,overlap=1,end='wrap'), - N.array([[0,1,2],[2,3,4],[4,5,0]])) - assert_equal(segment_axis(N.arange(6),length=3,overlap=1,end='pad',endvalue=-17), - N.array([[0,1,2],[2,3,4],[4,5,-17]])) + assert_equal(segment_axis(np.arange(6),length=3,overlap=1,end='cut'), + np.array([[0,1,2],[2,3,4]])) + assert_equal(segment_axis(np.arange(6),length=3,overlap=1,end='wrap'), + np.array([[0,1,2],[2,3,4],[4,5,0]])) + assert_equal(segment_axis(np.arange(6),length=3,overlap=1,end='pad',endvalue=-17), + np.array([[0,1,2],[2,3,4],[4,5,-17]])) def test_multidimensional(self): - assert_equal(segment_axis(N.ones((2,3,4,5,6)),axis=3,length=3,overlap=1).shape, + assert_equal(segment_axis(np.ones((2,3,4,5,6)),axis=3,length=3,overlap=1).shape, (2,3,4,2,3,6)) - assert_equal(segment_axis(N.ones((2,5,4,3,6)).swapaxes(1,3),axis=3,length=3,overlap=1).shape, + assert_equal(segment_axis(np.ones((2,5,4,3,6)).swapaxes(1,3),axis=3,length=3,overlap=1).shape, (2,3,4,2,3,6)) - assert_equal(segment_axis(N.ones((2,3,4,5,6)),axis=2,length=3,overlap=1,end='cut').shape, + assert_equal(segment_axis(np.ones((2,3,4,5,6)),axis=2,length=3,overlap=1,end='cut').shape, (2,3,1,3,5,6)) - assert_equal(segment_axis(N.ones((2,3,4,5,6)),axis=2,length=3,overlap=1,end='wrap').shape, + assert_equal(segment_axis(np.ones((2,3,4,5,6)),axis=2,length=3,overlap=1,end='wrap').shape, (2,3,2,3,5,6)) - assert_equal(segment_axis(N.ones((2,3,4,5,6)),axis=2,length=3,overlap=1,end='pad').shape, + assert_equal(segment_axis(np.ones((2,3,4,5,6)),axis=2,length=3,overlap=1,end='pad').shape, (2,3,2,3,5,6)) if __name__=='__main__': Modified: trunk/scipy/sandbox/spline/tests/test_fitpack.py =================================================================== --- trunk/scipy/sandbox/spline/tests/test_fitpack.py 2008-08-08 05:33:08 UTC (rev 4616) +++ trunk/scipy/sandbox/spline/tests/test_fitpack.py 2008-08-08 06:06:21 UTC (rev 4617) @@ -20,9 +20,7 @@ splint, spalde, bisplev, bisplrep, splprep -set_local_path() from dierckx_test_data import * -restore_path() class TestSplrepSplev(TestCase): def test_curfit_against_dierckx_smth(self): Modified: trunk/scipy/sandbox/spline/tests/test_spline.py =================================================================== --- trunk/scipy/sandbox/spline/tests/test_spline.py 2008-08-08 05:33:08 UTC (rev 4616) +++ trunk/scipy/sandbox/spline/tests/test_spline.py 2008-08-08 06:06:21 UTC (rev 4617) @@ -21,9 +21,7 @@ InterpolatedUnivariateSpline, LSQBivariateSpline, SmoothBivariateSpline,\ RectBivariateSpline -set_local_path() from dierckx_test_data import * -restore_path() class TestUnivariateSpline(TestCase): def test_linear_constant(self): Modified: trunk/scipy/weave/tests/test_ast_tools.py =================================================================== --- trunk/scipy/weave/tests/test_ast_tools.py 2008-08-08 05:33:08 UTC (rev 4616) +++ trunk/scipy/weave/tests/test_ast_tools.py 2008-08-08 06:06:21 UTC (rev 4617) @@ -1,10 +1,7 @@ from numpy.testing import * from scipy.weave import ast_tools - -set_local_path() from weave_test_utils import * -restore_path() class TestHarvestVariables(TestCase): """ Not much testing going on here, but Modified: trunk/scipy/weave/tests/test_blitz_tools.py =================================================================== --- trunk/scipy/weave/tests/test_blitz_tools.py 2008-08-08 05:33:08 UTC (rev 4616) +++ trunk/scipy/weave/tests/test_blitz_tools.py 2008-08-08 06:06:21 UTC (rev 4617) @@ -8,10 +8,7 @@ from scipy.weave import blitz_tools from scipy.weave.ast_tools import harvest_variables - -set_local_path() from weave_test_utils import * -restore_path() class TestAstToBlitzExpr(TestCase): Modified: trunk/scipy/weave/tests/test_catalog.py =================================================================== --- trunk/scipy/weave/tests/test_catalog.py 2008-08-08 05:33:08 UTC (rev 4616) +++ trunk/scipy/weave/tests/test_catalog.py 2008-08-08 06:06:21 UTC (rev 4617) @@ -5,10 +5,7 @@ from numpy.testing import * from scipy.weave import catalog - -set_local_path() from weave_test_utils import * -restore_path() class TestDefaultDir(TestCase): Modified: trunk/scipy/weave/tests/test_ext_tools.py =================================================================== --- trunk/scipy/weave/tests/test_ext_tools.py 2008-08-08 05:33:08 UTC (rev 4616) +++ trunk/scipy/weave/tests/test_ext_tools.py 2008-08-08 06:06:21 UTC (rev 4617) @@ -1,4 +1,3 @@ - import time from numpy.testing import * @@ -10,9 +9,7 @@ pass # requires numpy.numerix -set_local_path() from weave_test_utils import * -restore_path() build_dir = empty_temp_dir() print 'building extensions here:', build_dir Modified: trunk/scipy/weave/tests/test_inline_tools.py =================================================================== --- trunk/scipy/weave/tests/test_inline_tools.py 2008-08-08 05:33:08 UTC (rev 4616) +++ trunk/scipy/weave/tests/test_inline_tools.py 2008-08-08 06:06:21 UTC (rev 4617) @@ -1,13 +1,8 @@ - from numpy import * - from numpy.testing import * from scipy.weave import inline_tools - -set_local_path() from test_scxx import * -restore_path() class TestInline(TestCase): """ These are long running tests... Modified: trunk/scipy/weave/tests/test_scxx.py =================================================================== --- trunk/scipy/weave/tests/test_scxx.py 2008-08-08 05:33:08 UTC (rev 4616) +++ trunk/scipy/weave/tests/test_scxx.py 2008-08-08 06:06:21 UTC (rev 4617) @@ -5,7 +5,6 @@ import os,sys from numpy.testing import * -set_local_path() from test_scxx_object import * from test_scxx_sequence import * from test_scxx_dict import * From scipy-svn at scipy.org Fri Aug 8 02:17:51 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 01:17:51 -0500 (CDT) Subject: [Scipy-svn] r4618 - in trunk/scipy: . cluster integrate interpolate interpolate/tests io/tests ndimage ndimage/tests optimize sandbox/exmplpackage/benchmarks sandbox/mkufunc sandbox/mkufunc/examples sandbox/mkufunc/mkufunc signal signal/tests sparse sparse/linalg/eigen/lobpcg sparse/linalg/isolve sparse/sparsetools sparse/tests special/tests stats Message-ID: <20080808061751.63B9139C021@scipy.org> Author: jarrod.millman Date: 2008-08-08 01:17:26 -0500 (Fri, 08 Aug 2008) New Revision: 4618 Modified: trunk/scipy/__init__.py trunk/scipy/cluster/distance.py trunk/scipy/cluster/info.py trunk/scipy/integrate/odepack.py trunk/scipy/interpolate/fitpack.py trunk/scipy/interpolate/fitpack2.py trunk/scipy/interpolate/info.py trunk/scipy/interpolate/interpolate.py trunk/scipy/interpolate/polyint.py trunk/scipy/interpolate/tests/test_fitpack.py trunk/scipy/interpolate/tests/test_interpolate.py trunk/scipy/interpolate/tests/test_polyint.py trunk/scipy/io/tests/test_mmio.py trunk/scipy/ndimage/_registration.py trunk/scipy/ndimage/tests/test_registration.py trunk/scipy/ndimage/tests/test_regression.py trunk/scipy/optimize/minpack.py trunk/scipy/sandbox/exmplpackage/benchmarks/bench_foo.py trunk/scipy/sandbox/mkufunc/examples/benchmark.py trunk/scipy/sandbox/mkufunc/examples/mandel_c.py trunk/scipy/sandbox/mkufunc/examples/mandel_mkImage.py trunk/scipy/sandbox/mkufunc/examples/mandel_py.py trunk/scipy/sandbox/mkufunc/examples/primes.py trunk/scipy/sandbox/mkufunc/mkufunc/api.py trunk/scipy/sandbox/mkufunc/mkufunc/driver.py trunk/scipy/sandbox/mkufunc/mkufunc/interactive.py trunk/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py trunk/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py trunk/scipy/sandbox/mkufunc/setup.py trunk/scipy/signal/signaltools.py trunk/scipy/signal/tests/test_signaltools.py trunk/scipy/sparse/base.py trunk/scipy/sparse/bsr.py trunk/scipy/sparse/compressed.py trunk/scipy/sparse/construct.py trunk/scipy/sparse/coo.py trunk/scipy/sparse/data.py trunk/scipy/sparse/dia.py trunk/scipy/sparse/extract.py trunk/scipy/sparse/lil.py trunk/scipy/sparse/linalg/eigen/lobpcg/lobpcg.py trunk/scipy/sparse/linalg/isolve/utils.py trunk/scipy/sparse/sparsetools/bsr.py trunk/scipy/sparse/sparsetools/coo.py trunk/scipy/sparse/sparsetools/csc.py trunk/scipy/sparse/sparsetools/csr.py trunk/scipy/sparse/sparsetools/dia.py trunk/scipy/sparse/tests/test_base.py trunk/scipy/special/tests/test_basic.py trunk/scipy/stats/mstats.py Log: ran reindent Modified: trunk/scipy/__init__.py =================================================================== --- trunk/scipy/__init__.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/__init__.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -63,7 +63,7 @@ pkgload = PackageLoader() pkgload(verbose=SCIPY_IMPORT_VERBOSE,postpone=True) -# Remove subpackage names from __all__ such that they are not imported via +# Remove subpackage names from __all__ such that they are not imported via # "from scipy import *". This works around a numpy bug present in < 1.2. subpackages = """cluster constants fftpack integrate interpolate io lib linalg linsolve maxentropy misc ndimage odr optimize sandbox signal sparse special Modified: trunk/scipy/cluster/distance.py =================================================================== --- trunk/scipy/cluster/distance.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/cluster/distance.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -179,7 +179,7 @@ u = np.asarray(u) v = np.asarray(v) return (np.double(np.bitwise_and((u != v), - np.bitwise_or(u != 0, v != 0)).sum()) + np.bitwise_or(u != 0, v != 0)).sum()) / np.double(np.bitwise_or(u != 0, v != 0).sum())) def kulsinski(u, v): @@ -281,7 +281,7 @@ def _nbool_correspond_all(u, v): if u.dtype != v.dtype: raise TypeError("Arrays being compared must be of the same data type.") - + if u.dtype == np.int or u.dtype == np.float_ or u.dtype == np.double: not_u = 1.0 - u not_v = 1.0 - v Modified: trunk/scipy/cluster/info.py =================================================================== --- trunk/scipy/cluster/info.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/cluster/info.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -3,17 +3,17 @@ ============================ Clustering algorithms are useful in information theory, target detection, - communications, compression, and other areas. The vq module only - supports vector quantization and the k-means algorithms. Development + communications, compression, and other areas. The vq module only + supports vector quantization and the k-means algorithms. Development of self-organizing maps (SOM) and other approaches is underway. Hierarchical Clustering ======================= - The hierarchy module provides functions for hierarchical and agglomerative - clustering. Its features include generating hierarchical clusters from - distance matrices, computing distance matrices from observation vectors, - calculating statistics on clusters, cutting linkages to generate flat + The hierarchy module provides functions for hierarchical and agglomerative + clustering. Its features include generating hierarchical clusters from + distance matrices, computing distance matrices from observation vectors, + calculating statistics on clusters, cutting linkages to generate flat clusters, and visualizing clusters with dendrograms. Distance Computation Modified: trunk/scipy/integrate/odepack.py =================================================================== --- trunk/scipy/integrate/odepack.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/integrate/odepack.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -28,7 +28,7 @@ Solves the initial value problem for stiff or non-stiff systems of first order ode-s:: - + dy/dt = func(y,t0,...) where y can be a vector. @@ -59,10 +59,10 @@ y : array, shape (len(y0), len(t)) Array containing the value of y for each desired time in t, with the initial value y0 in the first row. - + infodict : dict, only returned if full_output == True Dictionary containing additional output information - + ======= ============================================================ key meaning ======= ============================================================ @@ -85,7 +85,7 @@ 'mused' a vector of method indicators for each successful time step: 1: adams (nonstiff), 2: bdf (stiff) ======= ============================================================ - + Other Parameters ---------------- ml, mu : integer @@ -100,7 +100,7 @@ The input parameters rtol and atol determine the error control performed by the solver. The solver will control the vector, e, of estimated local errors in y, according to an - inequality of the form:: + inequality of the form:: max-norm of (e / ewt) <= 1 where ewt is a vector of positive error weights computed as:: ewt = rtol * abs(y) + atol @@ -130,7 +130,7 @@ -------- ode : a more object-oriented integrator based on VODE quad : for finding the area under a curve - + """ if ml is None: Modified: trunk/scipy/interpolate/fitpack.py =================================================================== --- trunk/scipy/interpolate/fitpack.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/interpolate/fitpack.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -702,7 +702,7 @@ splprep, splrep, splint, sproot, splev - evaluation, roots, integral UnivariateSpline, BivariateSpline - an alternative wrapping of the FITPACK functions - + Notes: Based on algorithms from: Dierckx P. : An algorithm for surface fitting with spline functions @@ -844,7 +844,7 @@ def dblint(xa,xb,ya,yb,tck): """Evaluate the integral of a spline over area [xa,xb] x [ya,yb]. - + Parameters ---------- xa, xb : float @@ -892,7 +892,7 @@ In case of a periodic spline (per != 0) there must be either at least k interior knots t(j) satisfying t(k+1)1 the polynomial is vector-valued. If None the y values + if R>1 the polynomial is vector-valued. If None the y values will be supplied later. """ self.n = len(xi) @@ -393,19 +393,19 @@ self.wi[:j]*=(self.xi[j]-self.xi[:j]) self.wi[j] = np.multiply.reduce(self.xi[:j]-self.xi[j]) self.wi**=-1 - + def set_yi(self, yi): """Update the y values to be interpolated - The barycentric interpolation algorithm requires the calculation - of weights, but these depend only on the xi. The yi can be changed + The barycentric interpolation algorithm requires the calculation + of weights, but these depend only on the xi. The yi can be changed at any time. Parameters ---------- yi : array-like N by R The y coordinates of the points the polynomial should pass through; - if R>1 the polynomial is vector-valued. If None the y values + if R>1 the polynomial is vector-valued. If None the y values will be supplied later. """ if yi is None: @@ -425,12 +425,12 @@ raise ValueError("yi dimensions do not match xi dimensions") self.yi = yi self.r = r - + def add_xi(self, xi, yi=None): """Add more x values to the set to be interpolated - The barycentric interpolation algorithm allows easy updating by + The barycentric interpolation algorithm allows easy updating by adding more points for the polynomial to pass through. Parameters @@ -439,8 +439,8 @@ The x coordinates of the points the polynomial should pass through yi : array-like N1 by R or None The y coordinates of the points the polynomial should pass through; - if R>1 the polynomial is vector-valued. If None the y values - will be supplied later. The yi should be specified if and only if + if R>1 the polynomial is vector-valued. If None the y values + will be supplied later. The yi should be specified if and only if the interpolator has y values specified. """ if yi is not None: @@ -489,8 +489,8 @@ Notes ----- - Currently the code computes an outer product between x and the - weights, that is, it constructs an intermediate array of size + Currently the code computes an outer product between x and the + weights, that is, it constructs an intermediate array of size N by M, where N is the degree of the polynomial. """ scalar = np.isscalar(x) @@ -516,15 +516,15 @@ """Convenience function for polynomial interpolation Constructs a polynomial that passes through a given set of points, - then evaluates the polynomial. For reasons of numerical stability, + then evaluates the polynomial. For reasons of numerical stability, this function does not compute the coefficients of the polynomial. This function uses a "barycentric interpolation" method that treats the problem as a special case of rational function interpolation. - This algorithm is quite stable, numerically, but even in a world of - exact computation, unless the x coordinates are chosen very - carefully - Chebyshev zeros (e.g. cos(i*pi/n)) are a good choice - - polynomial interpolation itself is a very ill-conditioned process + This algorithm is quite stable, numerically, but even in a world of + exact computation, unless the x coordinates are chosen very + carefully - Chebyshev zeros (e.g. cos(i*pi/n)) are a good choice - + polynomial interpolation itself is a very ill-conditioned process due to the Runge phenomenon. Based on Berrut and Trefethen 2004, "Barycentric Lagrange Interpolation". @@ -547,9 +547,9 @@ Notes ----- - Construction of the interpolation weights is a relatively slow process. - If you want to call this many times with the same xi (but possibly - varying yi or x) you should use the class BarycentricInterpolator. + Construction of the interpolation weights is a relatively slow process. + If you want to call this many times with the same xi (but possibly + varying yi or x) you should use the class BarycentricInterpolator. This is what this function uses internally. """ return BarycentricInterpolator(xi, yi)(x) @@ -558,10 +558,10 @@ class PiecewisePolynomial(object): """Piecewise polynomial curve specified by points and derivatives - This class represents a curve that is a piecewise polynomial. It - passes through a list of points and has specified derivatives at - each point. The degree of the polynomial may very from segment to - segment, as may the number of derivatives available. The degree + This class represents a curve that is a piecewise polynomial. It + passes through a list of points and has specified derivatives at + each point. The degree of the polynomial may very from segment to + segment, as may the number of derivatives available. The degree should not exceed about thirty. Appending points to the end of the curve is efficient. @@ -585,12 +585,12 @@ Notes ----- - If orders is None, or orders[i] is None, then the degree of the + If orders is None, or orders[i] is None, then the degree of the polynomial segment is exactly the degree required to match all i - available derivatives at both endpoints. If orders[i] is not None, - then some derivatives will be ignored. The code will try to use an - equal number of derivatives from each end; if the total number of - derivatives needed is odd, it will prefer the rightmost endpoint. If + available derivatives at both endpoints. If orders[i] is not None, + then some derivatives will be ignored. The code will try to use an + equal number of derivatives from each end; if the total number of + derivatives needed is odd, it will prefer the rightmost endpoint. If not enough derivatives are available, an exception is raised. """ yi0 = np.asarray(yi[0]) @@ -606,7 +606,7 @@ self.xi = [xi[0]] self.yi = [yi0] self.n = 1 - + self.direction = direction self.orders = [] self.polynomials = [] @@ -614,12 +614,12 @@ def _make_polynomial(self,x1,y1,x2,y2,order,direction): """Construct the interpolating polynomial object - + Deduces the number of derivatives to match at each end from order and the number of derivatives available. If - possible it uses the same number of derivatives from + possible it uses the same number of derivatives from each end; if the number is odd it tries to take the - extra one from y2. In any case if not enough derivatives + extra one from y2. In any case if not enough derivatives are available at one end or another it draws enough to make up the total from the other end. """ @@ -647,14 +647,14 @@ def append(self, xi, yi, order=None): """Append a single point with derivatives to the PiecewisePolynomial - + Parameters ---------- xi : float yi : array-like yi is the list of derivatives known at xi order : integer or None - a polynomial order, or instructions to use the highest + a polynomial order, or instructions to use the highest possible order """ @@ -668,7 +668,7 @@ if self.direction is None: self.direction = np.sign(xi-self.xi[-1]) - elif (xi-self.xi[-1])*self.direction < 0: + elif (xi-self.xi[-1])*self.direction < 0: raise ValueError("x coordinates must be in the %d direction: %s" % (self.direction, self.xi)) self.xi.append(xi) @@ -719,7 +719,7 @@ Parameters ---------- x : scalar or array-like of length N - + Returns ------- y : scalar or array-like of length R or length N or N by R @@ -748,31 +748,31 @@ x : scalar or array-like of length N der : integer which single derivative to extract - + Returns ------- y : scalar or array-like of length R or length N or N by R Notes ----- - This currently computes (using self.derivatives()) all derivatives - of the curve segment containing each x but returns only one. + This currently computes (using self.derivatives()) all derivatives + of the curve segment containing each x but returns only one. """ return self.derivatives(x,der=der+1)[der] def derivatives(self, x, der): - """Evaluate a derivative of the piecewise polynomial + """Evaluate a derivative of the piecewise polynomial Parameters ---------- x : scalar or array-like of length N der : integer - how many derivatives (including the function value as + how many derivatives (including the function value as 0th derivative) to extract - + Returns ------- y : array-like of shape der by R or der by N or der by N by R - + """ if np.isscalar(x): pos = np.clip(np.searchsorted(self.xi, x) - 1, 0, self.n-2) @@ -805,19 +805,19 @@ a list of polynomial orders, or a single universal order der : integer which single derivative to extract - + Returns ------- y : scalar or array-like of length R or length M or M by R Notes ----- - If orders is None, or orders[i] is None, then the degree of the + If orders is None, or orders[i] is None, then the degree of the polynomial segment is exactly the degree required to match all i - available derivatives at both endpoints. If orders[i] is not None, - then some derivatives will be ignored. The code will try to use an - equal number of derivatives from each end; if the total number of - derivatives needed is odd, it will prefer the rightmost endpoint. If + available derivatives at both endpoints. If orders[i] is not None, + then some derivatives will be ignored. The code will try to use an + equal number of derivatives from each end; if the total number of + derivatives needed is odd, it will prefer the rightmost endpoint. If not enough derivatives are available, an exception is raised. Construction of these piecewise polynomials can be an expensive process; Modified: trunk/scipy/interpolate/tests/test_fitpack.py =================================================================== --- trunk/scipy/interpolate/tests/test_fitpack.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/interpolate/tests/test_fitpack.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -116,20 +116,20 @@ x = [1,1,1,2,2,2,4,4,4] y = [1,2,3,1,2,3,1,2,3] z = array([0,7,8,3,4,7,1,3,4]) - + lut = SmoothBivariateSpline(x,y,z,kx=1,ky=1,s=0) tx = [1,2,4] ty = [1,2,3] - + tz = lut(tx, ty) trpz = .25*(diff(tx)[:,None]*diff(ty)[None,:] *(tz[:-1,:-1]+tz[1:,:-1]+tz[:-1,1:]+tz[1:,1:])).sum() assert_almost_equal(lut.integral(tx[0], tx[-1], ty[0], ty[-1]), trpz) - + lut2 = SmoothBivariateSpline(x,y,z,kx=2,ky=2,s=0) assert_almost_equal(lut2.integral(tx[0], tx[-1], ty[0], ty[-1]), trpz, decimal=0) # the quadratures give 23.75 and 23.85 - + tz = lut(tx[:-1], ty[:-1]) trpz = .25*(diff(tx[:-1])[:,None]*diff(ty[:-1])[None,:] *(tz[:-1,:-1]+tz[1:,:-1]+tz[:-1,1:]+tz[1:,1:])).sum() Modified: trunk/scipy/interpolate/tests/test_interpolate.py =================================================================== --- trunk/scipy/interpolate/tests/test_interpolate.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/interpolate/tests/test_interpolate.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -29,7 +29,7 @@ self.y210 = np.arange(20.).reshape((2, 10)) self.y102 = np.arange(20.).reshape((10, 2)) - + self.fill_value = -100.0 def test_validation(self): @@ -181,7 +181,7 @@ interp10(np.array([[3.4, 5.6], [2.4, 7.8]])), np.array([[3.4, 5.6], [2.4, 7.8]]), ) - + # Multidimensional outputs. interp210 = interp1d(self.x10, self.y210, kind=kind) assert_array_almost_equal( @@ -217,7 +217,7 @@ np.array([[[6.8, 7.8], [11.2, 12.2]], [[4.8, 5.8], [15.6, 16.6]]]), ) - + # Check large ndim output a = [4, 5, 6, 7] y = np.arange(np.prod(a)).reshape(*a) @@ -225,7 +225,7 @@ x = np.arange(s) z = interp1d(x, y, axis=n, kind=kind) assert_array_almost_equal(z(x), y) - + x2 = np.arange(2*3*1).reshape((2,3,1)) / 12. b = list(a) b[n:n+1] = [2,3,1] Modified: trunk/scipy/interpolate/tests/test_polyint.py =================================================================== --- trunk/scipy/interpolate/tests/test_polyint.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/interpolate/tests/test_polyint.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -11,7 +11,7 @@ class CheckKrogh(TestCase): def setUp(self): self.true_poly = scipy.poly1d([-2,3,1,5,-4]) - self.test_xs = np.linspace(-1,1,100) + self.test_xs = np.linspace(-1,1,100) self.xs = np.linspace(-1,1,5) self.ys = self.true_poly(self.xs) @@ -122,7 +122,7 @@ class CheckBarycentric(TestCase): def setUp(self): self.true_poly = scipy.poly1d([-2,3,1,5,-4]) - self.test_xs = np.linspace(-1,1,100) + self.test_xs = np.linspace(-1,1,100) self.xs = np.linspace(-1,1,5) self.ys = self.true_poly(self.xs) @@ -203,7 +203,7 @@ xs = [0, 1, 2] ys = [[[0,1]],[[1,0],[-1,-1]],[[2,1]]] P = PiecewisePolynomial(xs,ys) - Pi = [PiecewisePolynomial(xs,[[yd[i] for yd in y] for y in ys]) + Pi = [PiecewisePolynomial(xs,[[yd[i] for yd in y] for y in ys]) for i in xrange(len(ys[0][0]))] test_xs = np.linspace(-1,3,100) assert_almost_equal(P(test_xs), Modified: trunk/scipy/io/tests/test_mmio.py =================================================================== --- trunk/scipy/io/tests/test_mmio.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/io/tests/test_mmio.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -293,13 +293,13 @@ def test_sparse_formats(self): mats = [] - + I = array([0, 0, 1, 2, 3, 3, 3, 4]) J = array([0, 3, 1, 2, 1, 3, 4, 4]) V = array([ 1.0, 6.0, 10.5, 0.015, 250.5, -280.0, 33.32, 12.0 ]) mats.append( scipy.sparse.coo_matrix((V,(I,J)),shape=(5,5)) ) - + V = array([ 1.0 + 3j, 6.0 + 2j, 10.50 + 0.9j, 0.015 + -4.4j, 250.5 + 0j, -280.0 + 5j, 33.32 + 6.4j, 12.00 + 0.8j]) mats.append( scipy.sparse.coo_matrix((V,(I,J)),shape=(5,5)) ) @@ -309,7 +309,7 @@ for fmt in ['csr','csc','coo']: fn = mktemp() mmwrite(fn, mat.asformat(fmt)) - + result = mmread(fn).todense() assert_array_almost_equal(result, expected) Modified: trunk/scipy/ndimage/_registration.py =================================================================== --- trunk/scipy/ndimage/_registration.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/ndimage/_registration.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -116,7 +116,7 @@ -------- image = fmri_series[i] x[0:6] = measures[i]['align_rotate'][0:6] - M = get_inverse_mappings(x) + M = get_inverse_mappings(x) # overwrite the fMRI volume with the aligned volume fmri_series[i] = remap_image(image, M, resample='cubic') @@ -175,7 +175,7 @@ def register(image1, image1_mat, image2, image2_mat, multires=[4, 2], histo_fwhm=3, ftype=1, lite=0, smhist=0, method='nmi', opt_method='hybrid', - optimize_function=None): + optimize_function=None): """ parm_vector = register(image1, image1_mat, image2, image2_mat, multires=[4, 2], histo_fwhm=3, @@ -198,7 +198,7 @@ image2_mat is the source image MAT multires: {list}, optional the volume subsample values for each pass of the registration. - the default is 2 passes with subsample 4 in pass 1 and subsample 2 in pass 2 + the default is 2 passes with subsample 4 in pass 1 and subsample 2 in pass 2 histo_fwhm : {int}, optional used for the filter kernel in the low pass filter of the joint histogram ftype : {0, 1}, optional @@ -214,7 +214,7 @@ flag for type of registration metric. nmi is normalized mutual information; mi is mutual information; ecc is entropy cross correlation; ncc is normalized cross correlation. mse is mean - squared error. + squared error. opt_method: {'powell', 'cg', 'hybrid'}, optional registration is two pass. Pass 1 is low res to get close to alignment and pass 2 starts at the pass 1 optimal alignment. In powell pass 1 and @@ -292,12 +292,12 @@ optimize_function = cost_function parm_vector = multires_registration(optimize_function, image1, image1_mat, image2, image2_mat, - multires, histo_fwhm, lite, smhist, method, opt_method) + multires, histo_fwhm, lite, smhist, method, opt_method) return parm_vector def multires_registration(optimize_function, image1, image1_mat, image2, image2_mat, - multires, histo_fwhm, lite, smhist, method, opt_method): + multires, histo_fwhm, lite, smhist, method, opt_method): """ @@ -315,7 +315,7 @@ image2_mat is the source image MAT multires: {list}, optional the volume subsample values for each pass of the registration. - the default is 2 passes with subsample 4 in pass 1 and subsample 2 in pass 2 + the default is 2 passes with subsample 4 in pass 1 and subsample 2 in pass 2 histo_fwhm : {int}, optional used for the filter kernel in the low pass filter of the joint histogram ftype : {0, 1}, optional @@ -331,7 +331,7 @@ flag for type of registration metric. nmi is normalized mutual information; mi is mutual information; ecc is entropy cross correlation; ncc is normalized cross correlation. mse is mean - squared error. + squared error. opt_method: {'powell', 'cg', 'hybrid'}, optional registration is two pass. Pass 1 is low res to get close to alignment and pass 2 starts at the pass 1 optimal alignment. In powell pass 1 and @@ -364,12 +364,12 @@ # the kernel fwhm value for the x and y joint histogram filter fwhm[:] = histo_fwhm for i in loop: - # this is the volume subsample - step[:] = multires[i] - # optfunc_args is specific to the cost_function in this file - # this will need to change if you use another optimize_function. + # this is the volume subsample + step[:] = multires[i] + # optfunc_args is specific to the cost_function in this file + # this will need to change if you use another optimize_function. optfunc_args = (image1, image1_mat, image2, image2_mat, step, histo_fwhm, - lite, smhist, method, ret_histo) + lite, smhist, method, ret_histo) p_args = (optfunc_args,) if opt_method=='powell': print 'POWELL multi-res registration step size ', step @@ -694,7 +694,7 @@ # trilinear interpolation mapping. reg.register_linear_resample(image_F, remap_image_F, composite, sample_vector) cost = (np.square(image_G-remap_image_F)).mean() - # cost is min when G and F are aligned so keep cost positive + # cost is min when G and F are aligned so keep cost positive return cost @@ -718,7 +718,7 @@ hkernel = smooth_kernel(fwhm, x) output=None # 2D filter in 1D separable stages using the same kernel. SPM - # has options for a 2D fwhm kernel yet only uses 1 element + # has options for a 2D fwhm kernel yet only uses 1 element axis = 0 joint_histogram = correlate1d(joint_histogram, hkernel, axis, output) axis = 1 @@ -919,7 +919,7 @@ threshold : float (default 0.999) the value of the normalized integrated histogram - that when reached sets the high threshold index + that when reached sets the high threshold index Returns ------- @@ -927,7 +927,7 @@ the scaled volume ih : {nd_array} the integrated histogram. can be used for image display - purpose (histogram equalization) + purpose (histogram equalization) """ @@ -1011,8 +1011,8 @@ step = np.array([1, 1, 1], dtype=np.int32) optfunc_args = (image1, image1_mat, image2, image2_mat, step, histo_fwhm, lite, - smhist, method, ret_histo) - + smhist, method, ret_histo) + if ret_histo: cost, joint_histogram = cost_function(P, optfunc_args) return cost, joint_histogram Modified: trunk/scipy/ndimage/tests/test_registration.py =================================================================== --- trunk/scipy/ndimage/tests/test_registration.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/ndimage/tests/test_registration.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -62,125 +62,125 @@ class TestRegistration(TestCase): def test_affine_matrix_build_1(self): - "test_affine_matrix_build_1" + "test_affine_matrix_build_1" P = np.zeros(6) - M = reg.build_rotate_matrix(P) - E = np.eye(4) - match = (E==M).all() - assert_equal(match, True) - return + M = reg.build_rotate_matrix(P) + E = np.eye(4) + match = (E==M).all() + assert_equal(match, True) + return def test_affine_matrix_build_2(self): - "test_affine_matrix_build_2" + "test_affine_matrix_build_2" P = np.zeros(6) - P[0] = 1.0 - M = reg.build_rotate_matrix(P) - E = np.array([ - [ 1. , 0. , 0. , 0. ], - [ 0. , 0.9998477 , 0.01745241, 0. ], - [ 0. , -0.01745241, 0.9998477 , 0. ], - [ 0. , 0. , 0. , 1. ] - ]) - assert_array_almost_equal(E, M, decimal=6) - return + P[0] = 1.0 + M = reg.build_rotate_matrix(P) + E = np.array([ + [ 1. , 0. , 0. , 0. ], + [ 0. , 0.9998477 , 0.01745241, 0. ], + [ 0. , -0.01745241, 0.9998477 , 0. ], + [ 0. , 0. , 0. , 1. ] + ]) + assert_array_almost_equal(E, M, decimal=6) + return def test_affine_matrix_build_3(self): - "test_affine_matrix_build_3" + "test_affine_matrix_build_3" P = np.zeros(6) - P[0] = 1.0 - P[1] = 1.0 - P[2] = 1.0 - M = reg.build_rotate_matrix(P) - E = np.array([ + P[0] = 1.0 + P[1] = 1.0 + P[2] = 1.0 + M = reg.build_rotate_matrix(P) + E = np.array([ [ 0.99969541, 0.01744975, 0.01745241, 0. ], [-0.01775429, 0.9996901 , 0.01744975, 0. ], [-0.0171425 , -0.01775429, 0.99969541, 0. ], [ 0. , 0. , 0. , 1. ] - ]) - assert_array_almost_equal(E, M, decimal=6) - return + ]) + assert_array_almost_equal(E, M, decimal=6) + return @dec.slow def test_autoalign_histogram_1(self): - "test_autoalign_histogram_1" - desc = load_desc() - gvol = build_volume(desc) + "test_autoalign_histogram_1" + desc = load_desc() + gvol = build_volume(desc) mat = np.eye(4) - cost, joint = reg.check_alignment(gvol, mat, gvol, mat, ret_histo=1, lite=1) - # confirm that with lite=1 only have non-zero on the main diagonal + cost, joint = reg.check_alignment(gvol, mat, gvol, mat, ret_histo=1, lite=1) + # confirm that with lite=1 only have non-zero on the main diagonal j_diag = joint.diagonal() Z = np.diag(j_diag) W = joint - Z - # clip the near-zero fuzz + # clip the near-zero fuzz W[abs(W) < 1e-10] = 0.0 - assert_equal(W.max(), 0.0) - return + assert_equal(W.max(), 0.0) + return @dec.slow def test_autoalign_histogram_2(self): - "test_autoalign_histogram_2" - desc = load_desc() - gvol = build_volume(desc) + "test_autoalign_histogram_2" + desc = load_desc() + gvol = build_volume(desc) mat = np.eye(4) - cost, joint = reg.check_alignment(gvol, mat, gvol, mat, ret_histo=1, lite=0) - # confirm that with lite=0 DO have non-zero on the main diagonal + cost, joint = reg.check_alignment(gvol, mat, gvol, mat, ret_histo=1, lite=0) + # confirm that with lite=0 DO have non-zero on the main diagonal j_diag = joint.diagonal() Z = np.diag(j_diag) W = joint - Z - # clip the near-zero fuzz + # clip the near-zero fuzz W[abs(W) < 1e-10] = 0.0 - s = (W.max() > 0.0) - # make sure there are off-diagonal values - assert_equal(s, True) - return + s = (W.max() > 0.0) + # make sure there are off-diagonal values + assert_equal(s, True) + return @dec.slow def test_autoalign_ncc_value_1(self): - "test_autoalign_ncc_value_1" - desc = load_desc() - gvol = build_volume(desc) + "test_autoalign_ncc_value_1" + desc = load_desc() + gvol = build_volume(desc) mat = np.eye(4) - cost = reg.check_alignment(gvol, mat, gvol, mat, method='ncc', lite=1) - # confirm the cross correlation is near 1.0 - t = abs(cost) + 0.0001 - s = (t >= 1.0) - assert_equal(s, True) - return + cost = reg.check_alignment(gvol, mat, gvol, mat, method='ncc', lite=1) + # confirm the cross correlation is near 1.0 + t = abs(cost) + 0.0001 + s = (t >= 1.0) + assert_equal(s, True) + return @dec.slow def test_autoalign_ncc_value_2(self): - "test_autoalign_ncc_value_2" - desc = load_desc() - gvol = build_volume(desc) + "test_autoalign_ncc_value_2" + desc = load_desc() + gvol = build_volume(desc) mat = np.eye(4) - cost = reg.check_alignment(gvol, mat, gvol, mat, method='ncc', lite=0) - # confirm the cross correlation is near 1.0 - t = abs(cost) + 0.0001 - s = (t >= 1.0) - assert_equal(s, True) - return + cost = reg.check_alignment(gvol, mat, gvol, mat, method='ncc', lite=0) + # confirm the cross correlation is near 1.0 + t = abs(cost) + 0.0001 + s = (t >= 1.0) + assert_equal(s, True) + return @dec.slow def test_autoalign_nmi_value_1(self): - "test_autoalign_nmi_value_1" - desc = load_desc() - gvol = build_volume(desc) + "test_autoalign_nmi_value_1" + desc = load_desc() + gvol = build_volume(desc) mat = np.eye(4) - cost = reg.check_alignment(gvol, mat, gvol, mat, method='nmi', lite=1) - # confirm the normalized mutual information is near -2.0 - assert_almost_equal(cost, -2.0, decimal=6) - return + cost = reg.check_alignment(gvol, mat, gvol, mat, method='nmi', lite=1) + # confirm the normalized mutual information is near -2.0 + assert_almost_equal(cost, -2.0, decimal=6) + return @dec.slow def test_autoalign_nmi_value_2(self): - "test_autoalign_nmi_value_2" - desc = load_desc() - gvol = build_volume(desc) + "test_autoalign_nmi_value_2" + desc = load_desc() + gvol = build_volume(desc) mat = np.eye(4) - cost = reg.check_alignment(gvol, mat, gvol, mat, method='nmi', lite=0) - # confirm the normalized mutual information is near -2.0 - assert_almost_equal(cost, -1.7973048186515352, decimal=6) - return + cost = reg.check_alignment(gvol, mat, gvol, mat, method='nmi', lite=0) + # confirm the normalized mutual information is near -2.0 + assert_almost_equal(cost, -1.7973048186515352, decimal=6) + return Modified: trunk/scipy/ndimage/tests/test_regression.py =================================================================== --- trunk/scipy/ndimage/tests/test_regression.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/ndimage/tests/test_regression.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -1,6 +1,6 @@ import numpy as np from numpy.testing import * - + import scipy.ndimage as ndimage def test_byte_order_median(): Modified: trunk/scipy/optimize/minpack.py =================================================================== --- trunk/scipy/optimize/minpack.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/optimize/minpack.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -257,7 +257,7 @@ brentq, brenth, ridder, bisect, newton -- one-dimensional root-finding - fixed_point -- scalar and vector fixed-point finder + fixed_point -- scalar and vector fixed-point finder """ x0 = array(x0,ndmin=1) @@ -374,7 +374,7 @@ brentq, brenth, ridder, bisect, newton -- one-dimensional root-finding fixed_point -- scalar and vector fixed-point finder - + """ if fprime is not None: @@ -414,7 +414,7 @@ # Steffensen's Method using Aitken's Del^2 convergence acceleration. def fixed_point(func, x0, args=(), xtol=1e-8, maxiter=500): """Find the point where func(x) == x - + Given a function of one or more variables and a starting point, find a fixed-point of the function: i.e. where func(x)=x. @@ -452,7 +452,7 @@ """ if not isscalar(x0): x0 = asarray(x0) - p0 = x0 + p0 = x0 for iter in range(maxiter): p1 = func(p0, *args) p2 = func(p1, *args) @@ -468,7 +468,7 @@ p1 = func(p0, *args) p2 = func(p1, *args) d = p2 - 2.0 * p1 + p0 - if d == 0.0: + if d == 0.0: return p2 else: p = p0 - (p1 - p0)*(p1-p0) / d Modified: trunk/scipy/sandbox/exmplpackage/benchmarks/bench_foo.py =================================================================== --- trunk/scipy/sandbox/exmplpackage/benchmarks/bench_foo.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sandbox/exmplpackage/benchmarks/bench_foo.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -16,4 +16,3 @@ def bench_simple(self): print 'A long timed benchmark here' - Modified: trunk/scipy/sandbox/mkufunc/examples/benchmark.py =================================================================== --- trunk/scipy/sandbox/mkufunc/examples/benchmark.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sandbox/mkufunc/examples/benchmark.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -28,11 +28,11 @@ char *op = args[1]; n = dimensions[0]; double x; - + for(i = 0; i < n; i++) { x = *(double *)ip0; double *out = (double *)op; - + *out = 4.2 * x*x + 3.7 * x + 1.5; ip0 += is0; Modified: trunk/scipy/sandbox/mkufunc/examples/mandel_c.py =================================================================== --- trunk/scipy/sandbox/mkufunc/examples/mandel_c.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sandbox/mkufunc/examples/mandel_c.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -32,7 +32,7 @@ char *ip1 = args[1]; char *op = args[2]; n = dimensions[0]; - + for(i = 0; i < n; i++) { *(long *)op = iterations(*(double *)ip0, *(double *)ip1); Modified: trunk/scipy/sandbox/mkufunc/examples/mandel_mkImage.py =================================================================== --- trunk/scipy/sandbox/mkufunc/examples/mandel_mkImage.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sandbox/mkufunc/examples/mandel_mkImage.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -14,7 +14,7 @@ @mkufunc(int) def color(i): return (i * 10) % 256 - + n = i % 3 if n == 0: c = (255, 127, 128) @@ -39,7 +39,7 @@ img = color(img) img.dtype = numpy.uint8 img = img.reshape(h, w, 4) - + print img.dtype print img.shape Modified: trunk/scipy/sandbox/mkufunc/examples/mandel_py.py =================================================================== --- trunk/scipy/sandbox/mkufunc/examples/mandel_py.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sandbox/mkufunc/examples/mandel_py.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -20,8 +20,8 @@ else: return -1 - + if __name__ == '__main__': assert mandel(-1, .3) == 36 Modified: trunk/scipy/sandbox/mkufunc/examples/primes.py =================================================================== --- trunk/scipy/sandbox/mkufunc/examples/primes.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sandbox/mkufunc/examples/primes.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -5,9 +5,9 @@ src = 0 if len(sys.argv) == 2 and sys.argv[1] == 's': src = 1 - + from mkufunc.api import mkufunc Modified: trunk/scipy/sandbox/mkufunc/mkufunc/api.py =================================================================== --- trunk/scipy/sandbox/mkufunc/mkufunc/api.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sandbox/mkufunc/mkufunc/api.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -33,16 +33,16 @@ 'pypy_%s.c' % func_hash(f, salt=argtypes)) try: return open(cache_file_name).read() - + except IOError: from interactive import Translation - + t = Translation(f, backend='c') t.annotate(argtypes) t.source() - + os.rename(t.driver.c_source_filename, cache_file_name) - + return translate(f, argtypes) @@ -64,7 +64,7 @@ ... return x * x >>> signature = [int, int] # only the input arguments are used here - + compilation is done upon initialization >>> x = Cfunc(sqr, signature, 123) ... @@ -74,7 +74,7 @@ 1 >>> x.sig [, ] - + Attributes: f -- the Python function object n -- id number @@ -97,9 +97,9 @@ self.nin = f.func_code.co_argcount self.nout = len(self.sig) - self.nin assert self.nout == 1 # for now - + src = translate(f, signature[:self.nin]) - + self._prefix = 'f%i_' % self.n self._allCsrc = src.replace('pypy_', self._prefix + 'pypy_') self.cname = self._prefix + 'pypy_g_' + f.__name__ @@ -116,7 +116,7 @@ \{.*?\n\}\n # function body ending with } in single line ''' % self.cname, re.DOTALL | re.MULTILINE | re.VERBOSE) - + found = p.findall(self._allCsrc) assert len(found) == 1 res = found[0] @@ -125,9 +125,9 @@ print '------------------' print res print '------------------' - + return 'inline %s\n' % res - + def ufunc_support_code(self): # Unfortunately the code in here is very hard to read. # In order to make the code clearer, one would need a real template @@ -139,33 +139,33 @@ def varname(i): return chr(i + ord('a')) - + declargs = ', '.join('%s %s' % (typedict[self.sig[i]].c, varname(i)) for i in xrange(self.nin)) - + args = ', '.join(varname(i) for i in xrange(self.nin)) - + isn_steps = '\n\t'.join('npy_intp is%i = steps[%i];' % (i, i) for i in xrange(self.nin)) - + ipn_args = '\n\t'.join('char *ip%i = args[%i];' % (i, i) for i in xrange(self.nin)) - + body1d_in = '\n\t\t'.join('%s *in%i = (%s *)ip%i;' % (2*(typedict[self.sig[i]].c, i)) for i in xrange(self.nin)) - + body1d_add = '\n\t\t'.join('ip%i += is%i;' % (i, i) for i in xrange(self.nin)) - + ptrargs = ', '.join('*in%i' % i for i in xrange(self.nin)) - + rettype = typedict[self.sig[-1]].c - + return ''' static %(rettype)s wrap_%(cname)s(%(declargs)s) { - return %(cname)s(%(args)s); + return %(cname)s(%(args)s); } typedef %(rettype)s Func_%(n)i(%(declargs)s); @@ -173,23 +173,23 @@ static void PyUFunc_%(n)i(char **args, npy_intp *dimensions, npy_intp *steps, void *func) { - npy_intp i, n; + npy_intp i, n; %(isn_steps)s - npy_intp os = steps[%(nin)s]; + npy_intp os = steps[%(nin)s]; %(ipn_args)s - char *op = args[%(nin)s]; - Func_%(n)i *f = (Func_%(n)i *) func; - n = dimensions[0]; - - for(i = 0; i < n; i++) { - %(body1d_in)s - %(rettype)s *out = (%(rettype)s *)op; - - *out = (%(rettype)s) f(%(ptrargs)s); + char *op = args[%(nin)s]; + Func_%(n)i *f = (Func_%(n)i *) func; + n = dimensions[0]; + for(i = 0; i < n; i++) { + %(body1d_in)s + %(rettype)s *out = (%(rettype)s *)op; + + *out = (%(rettype)s) f(%(ptrargs)s); + %(body1d_add)s op += os; - } + } } ''' % locals() @@ -198,26 +198,26 @@ """ Given a list of Cfunc instances, return the support code for weave. """ acc = cStringIO.StringIO() - + acc.write('/********************* start pypy.h **************/\n\n') acc.write(open(os.path.join(os.path.dirname(__file__), 'pypy.h')).read()) acc.write('/********************** end pypy.h ****************/\n\n') - + for cf in cfuncs: acc.write(cf.cfunc()) acc.write(cf.ufunc_support_code()) - + fname = cfuncs[0].f.__name__ - + pyufuncs = ''.join('\tPyUFunc_%i,\n' % cf.n for cf in cfuncs) - + data = ''.join('\t(void *) wrap_%s,\n' % cf.cname for cf in cfuncs) - + types = ''.join('\t%s /* %i */\n' % (''.join(typedict[t].npy + ', ' for t in cf.sig), cf.n) for cf in cfuncs) - + acc.write(''' static PyUFuncGenericFunction %(fname)s_functions[] = { %(pyufuncs)s}; @@ -233,7 +233,7 @@ print '------------------ start support_code -----------------' print acc.getvalue() print '------------------- end support_code ------------------' - + return acc.getvalue() @@ -244,7 +244,7 @@ ntypes = len(signatures) fname = f.__name__ fhash = func_hash(f) - + res = ''' import_ufunc(); @@ -280,14 +280,14 @@ """ if len(signatures) == 0: raise ValueError("At least one signature needed") - + signatures.sort(key=lambda sig: [numpy.dtype(typ).num for typ in sig]) - + cfuncs = [Cfunc(f, sig, n) for n, sig in enumerate(signatures)] - + ufunc_info = weave.base_info.custom_info() ufunc_info.add_header('"numpy/ufuncobject.h"') - + return weave.inline(code(f, signatures), verbose=verbose, support_code=support_code(cfuncs), @@ -296,7 +296,7 @@ def mkufunc(arg0=[float], src=0): """ Python decorator which returns compiled UFunc of the function given. - + >>> from numpy import arange >>> from mkufunc.api import mkufunc >>> @mkufunc @@ -310,7 +310,7 @@ array([ 6.3, 9.5, 21.1, 41.1, 69.5]) """ class UFunc(object): - + def __init__(self, f): nin = f.func_code.co_argcount nout = 1 @@ -321,7 +321,7 @@ signatures[i] = (nin + nout) * (sig,) else: raise TypeError("no match for %r" % sig) - + for sig in signatures: assert isinstance(sig, tuple) if len(sig) != nin + nout: @@ -331,28 +331,28 @@ for t in sig: if t not in typedict.keys(): raise TypeError("no match for %r" % t) - + self.ufunc = genufunc(f, signatures) - + def __call__(self, *args): return self.ufunc(*args) global showC showC = src - + if isinstance(arg0, FunctionType): f = arg0 signatures = [float] return UFunc(f) - + elif isinstance(arg0, list): signatures = arg0 return UFunc - + elif arg0 in typedict.keys(): signatures = [arg0] return UFunc - + else: raise TypeError("first argument has to be a function, a type, or " "a list of signatures") Modified: trunk/scipy/sandbox/mkufunc/mkufunc/driver.py =================================================================== --- trunk/scipy/sandbox/mkufunc/mkufunc/driver.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sandbox/mkufunc/mkufunc/driver.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -74,7 +74,7 @@ env = os.environ.copy() env['_INSTRUMENT_COUNTERS'] = str(self.datafile) subprocess.call("'%s' %s" % (exe, args), env=env, shell=True) - + def after(self): # xxx os._exit(0) @@ -100,7 +100,7 @@ if setopts is not None: self.config.set(**setopts) - + self.exe_name = exe_name self.extmod_name = extmod_name @@ -112,7 +112,7 @@ default_goal, = self.backend_select_goals([default_goal]) if default_goal in self._maybe_skip(): default_goal = None - + self.default_goal = default_goal self.extra_goals = [] self.exposed = [] @@ -176,7 +176,7 @@ new_goal = cand break else: - raise Exception, "cannot infer complete goal from: %r" % goal + raise Exception, "cannot infer complete goal from: %r" % goal l.append(new_goal) return l @@ -186,8 +186,8 @@ def _maybe_skip(self): maybe_skip = [] if self._disabled: - for goal in self.backend_select_goals(self._disabled): - maybe_skip.extend(self._depending_on_closure(goal)) + for goal in self.backend_select_goals(self._disabled): + maybe_skip.extend(self._depending_on_closure(goal)) return dict.fromkeys(maybe_skip).keys() @@ -228,7 +228,7 @@ raise Exception("instrumentation requires the c backend" " and unix for now") from pypy.tool.udir import udir - + datafile = udir.join('_instrument_counters') makeProfInstrument = lambda compiler: ProfInstrument(datafile, compiler) @@ -299,7 +299,7 @@ policy = self.policy self.log.info('with policy: %s.%s' % (policy.__class__.__module__, policy.__class__.__name__)) - + annmodel.DEBUG = self.config.translation.debug annotator = translator.buildannotator(policy=policy) @@ -447,7 +447,7 @@ from pypy.translator.backendopt.all import backend_optimizations backend_optimizations(self.translator) # - task_backendopt_ootype = taskdef(task_backendopt_ootype, + task_backendopt_ootype = taskdef(task_backendopt_ootype, [OOTYPE], "ootype back-end optimisations") OOBACKENDOPT = 'backendopt_ootype' @@ -456,7 +456,7 @@ from pypy.translator.transform import insert_ll_stackcheck count = insert_ll_stackcheck(self.translator) self.log.info("inserted %d stack checks." % (count,)) - + task_stackcheckinsertion_lltype = taskdef( task_stackcheckinsertion_lltype, ['?'+BACKENDOPT, RTYPE, 'annotate'], @@ -495,10 +495,10 @@ self.database = database # task_database_c = taskdef(task_database_c, - [STACKCHECKINSERTION, '?'+BACKENDOPT, RTYPE, '?annotate'], + [STACKCHECKINSERTION, '?'+BACKENDOPT, RTYPE, '?annotate'], "Creating database for generating c source", earlycheck = possibly_check_for_boehm) - + def task_source_c(self): # xxx messy translator = self.translator cbuilder = self.cbuilder @@ -512,7 +512,7 @@ def task_compile_c(self): # xxx messy cbuilder = self.cbuilder cbuilder.compile() - + if self.standalone: self.c_entryp = cbuilder.executable_name self.create_exe() @@ -520,19 +520,19 @@ self.c_entryp = cbuilder.get_entry_point() # task_compile_c = taskdef(task_compile_c, ['source_c'], "Compiling c source") - - + + def task_run_c(self): self.backend_run('c') # - task_run_c = taskdef(task_run_c, ['compile_c'], + task_run_c = taskdef(task_run_c, ['compile_c'], "Running compiled c source", idemp=True) def task_llinterpret_lltype(self): from pypy.rpython.llinterp import LLInterpreter py.log.setconsumer("llinterp operation", None) - + translator = self.translator interp = LLInterpreter(translator.rtyper) bk = translator.annotator.bookkeeper @@ -543,8 +543,8 @@ log.llinterpret.event("result -> %s" % v) # - task_llinterpret_lltype = taskdef(task_llinterpret_lltype, - [STACKCHECKINSERTION, '?'+BACKENDOPT, RTYPE], + task_llinterpret_lltype = taskdef(task_llinterpret_lltype, + [STACKCHECKINSERTION, '?'+BACKENDOPT, RTYPE], "LLInterpreting") def task_source_llvm(self): @@ -559,8 +559,8 @@ llvm_filename = self.llvmgen.gen_source(self.entry_point) self.log.info("written: %s" % (llvm_filename,)) # - task_source_llvm = taskdef(task_source_llvm, - [STACKCHECKINSERTION, BACKENDOPT, RTYPE], + task_source_llvm = taskdef(task_source_llvm, + [STACKCHECKINSERTION, BACKENDOPT, RTYPE], "Generating llvm source") def task_compile_llvm(self): @@ -572,14 +572,14 @@ else: self.c_module, self.c_entryp = gen.compile_module() # - task_compile_llvm = taskdef(task_compile_llvm, - ['source_llvm'], + task_compile_llvm = taskdef(task_compile_llvm, + ['source_llvm'], "Compiling llvm source") def task_run_llvm(self): self.backend_run('llvm') # - task_run_llvm = taskdef(task_run_llvm, ['compile_llvm'], + task_run_llvm = taskdef(task_run_llvm, ['compile_llvm'], "Running compiled llvm source", idemp=True) @@ -589,7 +589,7 @@ stackless=self.config.translation.stackless) filename = self.gen.write_source() self.log.info("Wrote %s" % (filename,)) - task_source_js = taskdef(task_source_js, + task_source_js = taskdef(task_source_js, [OOTYPE], 'Generating Javascript source') @@ -630,7 +630,7 @@ # restore original os values if hasattr(self, 'old_cli_defs'): unpatch_os(self.old_cli_defs) - + self.log.info("Compiled %s" % filename) if self.standalone and self.exe_name: self.copy_cli_exe() @@ -641,7 +641,7 @@ pass task_run_cli = taskdef(task_run_cli, ['compile_cli'], 'XXX') - + def task_source_jvm(self): from pypy.translator.jvm.genjvm import GenJvm from pypy.translator.jvm.node import EntryPoint @@ -702,7 +702,7 @@ if backend in ('cli', 'jvm'): from pypy.translator.oosupport.support import patch_os driver.old_cli_defs = patch_os() - + target = targetspec_dic['target'] spec = target(driver, args) @@ -712,8 +712,8 @@ entry_point, inputtypes = spec policy = None - driver.setup(entry_point, inputtypes, - policy=policy, + driver.setup(entry_point, inputtypes, + policy=policy, extra=targetspec_dic, empty_translator=empty_translator) @@ -725,4 +725,4 @@ assert 'pypy.rpython.rmodel' not in sys.modules, ( "cannot fork because the rtyper has already been imported") prereq_checkpt_rtype_lltype = prereq_checkpt_rtype - prereq_checkpt_rtype_ootype = prereq_checkpt_rtype + prereq_checkpt_rtype_ootype = prereq_checkpt_rtype Modified: trunk/scipy/sandbox/mkufunc/mkufunc/interactive.py =================================================================== --- trunk/scipy/sandbox/mkufunc/mkufunc/interactive.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sandbox/mkufunc/mkufunc/interactive.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -17,7 +17,7 @@ self.entry_point = entry_point self.context = TranslationContext(config=self.config) - + # hook into driver events driver_own_event = self.driver._event def _event(kind, goal, func): @@ -25,7 +25,7 @@ driver_own_event(kind, goal, func) self.driver._event = _event self.driver_setup = False - + self.update_options(argtypes, kwds) # for t.view() to work just after construction graph = self.context.buildflowgraph(entry_point) @@ -33,8 +33,8 @@ def driver_event(self, kind, goal, func): if kind == 'pre': - self.ensure_setup() - + self.ensure_setup() + def ensure_setup(self, argtypes=None, policy=None, standalone=False): if not self.driver_setup: if standalone: @@ -82,7 +82,7 @@ if self.config.translation.backend is not None: return self.ensure_opt('type_system') return self.ensure_opt('type_system', type_system, 'lltype') - + def ensure_backend(self, backend=None): backend = self.ensure_opt('backend', backend) self.ensure_type_system() @@ -99,7 +99,7 @@ def rtype(self, argtypes=None, **kwds): self.update_options(argtypes, kwds) ts = self.ensure_type_system() - return getattr(self.driver, 'rtype_'+ts)() + return getattr(self.driver, 'rtype_'+ts)() # backend depedent @@ -107,7 +107,7 @@ self.update_options(argtypes, kwds) backend = self.ensure_backend() self.driver.source_c() - + def compile(self, argtypes=None, **kwds): self.update_options(argtypes, kwds) backend = self.ensure_backend() Modified: trunk/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py =================================================================== --- trunk/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -4,42 +4,42 @@ class Tests(unittest.TestCase): - + # These tests are very (Python) version specific. - + def test_simple(self): - + def f(x): return 2.5 * x * x + 4.7 * x - + self.assertEqual(func_hash(f), '5f12e97debf1d2cb9e0a2f92e045b1fb') - - + + def test_extra(self): - + def f(x): return 2.5 * x * x + 4.7 * x - + self.assertEqual(func_hash(f, salt=[(int, int), (float, float)]), 'e637d9825ef20cb56d364041118ca72e') - + def test_const(self): - + def add_a(b): return a + b # a in globals - + self.assertEqual(func_hash(add_a), '9ff237f372bf233470ce940edd58f60d') - + def test_inner(self): - + def foo(x): inner1 = lambda t: t/3.0 def inner2(n): return n + 3 return inner1(x) + inner2(int(x)) - + self.assertEqual(func_hash(foo), '814c113dfc77e7ebb52915dd3ce9c37a') Modified: trunk/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py =================================================================== --- trunk/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -10,10 +10,10 @@ def assertClose(self, x, y): self.assert_(allclose(x, y), '%s != %s' % (x, y)) - + class Internal_Tests(unittest.TestCase, Util): - + def test_Cfunc(self): def sqr(x): return x * x @@ -34,7 +34,7 @@ y = uf(x) self.assertClose(y, [18.1, 19.3]) self.assert_(str(y.dtype).startswith('float')) - + x = array([1, 4]) y = uf(x) self.assertEqual(list(y), [18, 21]) @@ -42,13 +42,13 @@ class Arg_Tests(unittest.TestCase, Util): - + def check_ufunc(self, f): for arg in (array([0.0, 1.0, 2.5]), [0.0, 1.0, 2.5], (0.0, 1.0, 2.5)): self.assertClose(f(arg), [0.0, 1.0, 6.25]) - + self.assertEqual(f(3), 9) self.assert_(f(-2.5) - 6.25 < 1E-10) @@ -57,13 +57,13 @@ def f(x): return x * x self.check_ufunc(f) - + def test_noargs(self): @mkufunc() def f(x): return x * x self.check_ufunc(f) - + def test_varargs(self): for arg in (float, [float], @@ -79,20 +79,20 @@ return x * x self.assertEqual(f(3), 9) self.assert_(isinstance(f(42), int)) - + def test_mixed(self): @mkufunc([(int, float, int), float]) def f(n, x): return n + x * x - + y = f(2, 3.9) # Note that int(2 + 3.9 * 3.9) = 17 self.assertEqual(y, 17) self.assert_(isinstance(y, int)) - + y = f(2.0, 3.9) self.assertClose(y, 17.21) self.assert_(isinstance(y, float)) - + def test_exceptions(self): def f(x): return x @@ -103,10 +103,10 @@ self.assertRaises(TypeError, mkufunc([{}]), f) self.assertRaises(TypeError, mkufunc([(int, {})]), f) self.assertRaises(ValueError, mkufunc([]), f) - + class Math_Tests(unittest.TestCase, Util): - + def assertFuncsEqual(self, uf, f): x = 0.4376 a = uf(x) @@ -116,7 +116,7 @@ a = uf(xx) b = [f(x) for x in xx] self.assertClose(a, b) - + def test_pi(self): @mkufunc def f(x): return math.pi * x @@ -126,7 +126,7 @@ @mkufunc def f(x): return math.e * x self.assertFuncsEqual(f, lambda x: math.e * x) - + def test_exp(self): @mkufunc def f(x): return math.exp(x) @@ -146,22 +146,22 @@ @mkufunc def f(x): return math.sqrt(x) self.assertFuncsEqual(f, math.sqrt) - + def test_cos(self): @mkufunc def f(x): return math.cos(x) self.assertFuncsEqual(f, math.cos) - + def test_sin(self): @mkufunc def f(x): return math.sin(x) self.assertFuncsEqual(f, math.sin) - + def test_tan(self): @mkufunc def f(x): return math.tan(x) self.assertFuncsEqual(f, math.tan) - + def test_cosh(self): @mkufunc def f(x): return math.cosh(x) @@ -171,12 +171,12 @@ @mkufunc def f(x): return math.sinh(x) self.assertFuncsEqual(f, math.sinh) - + def test_tanh(self): @mkufunc def f(x): return math.tanh(x) self.assertFuncsEqual(f, math.tanh) - + def test_acos(self): @mkufunc def f(x): return math.acos(x) @@ -198,7 +198,7 @@ return math.atan2(x, y) self.assertClose(f(4, 5), math.atan2(4, 5)) - + xx = array([1.0, 3.0, -2.4, 3.1, -2.3, -1.0]) yy = array([1.0, 2.0, 7.5, -8.7, 0.0, -3.2]) a = f(xx, yy) @@ -209,28 +209,28 @@ @mkufunc def f(x, y): return math.pow(x, y) - + self.assertClose(f(2, 3), 8) - + xx = array([1.0, 3.0, 2.4, 0.0, 0.0, 0.0, 2.3, 2.0]) yy = array([1.0, 2.0, 7.5, 0.0, 0.5, 1.0, 0.0, -1.0]) a = f(xx, yy) b = [math.pow(x, y) for x, y in zip(xx, yy)] self.assertClose(a, b) - + def test_hypot(self): @mkufunc def f(x, y): return math.hypot(x, y) - + self.assertClose(f(3, 4), 5) - + xx = array([3.0, 2.4, -2.4, 3.1, -2.3, -1.0]) yy = array([4.0, 7.5, 7.5, -8.7, 0.0, -3.2]) a = f(xx, yy) b = [math.hypot(x, y) for x, y in zip(xx, yy)] self.assertClose(a, b) - + def test_arithmetic(self): def f(x): return (4 * x + 2) / (x * x - 7 * x + 1) @@ -242,7 +242,7 @@ @mkufunc(int) def f(i): return i % 5 - + self.assert_(all(f(range(7)) == array([0, 1, 2, 3, 4, 0, 1]))) self.assert_(all(f(arange(8)) == array([0, 1, 2, 3, 4, 0, 1, 2]))) @@ -296,7 +296,7 @@ @mkufunc def f(x): return a * x - + x = arange(0, 1, 0.1) self.assertClose(f(x), a * x) @@ -305,18 +305,18 @@ def test_lambda(self): self.assertRaises(AssertionError, mkufunc, lambda x: x*x + 2) - + def test_angle(self): from math import sin, pi, sqrt @mkufunc def sin_deg(angle): return sin(angle / 180.0 * pi) - + self.assertClose(sin_deg([0, 30, 45, 60, 90, 180, 270, 360]), [0, 0.5, 1/sqrt(2), sqrt(3)/2, 1, 0, -1, 0]) - + if __name__ == '__main__': unittest.main() Modified: trunk/scipy/sandbox/mkufunc/setup.py =================================================================== --- trunk/scipy/sandbox/mkufunc/setup.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sandbox/mkufunc/setup.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -7,7 +7,7 @@ name = "mkufunc", version = "0.1", - + zip_safe = False, package_data = {'': ['*.h']}, packages = find_packages(), Modified: trunk/scipy/signal/signaltools.py =================================================================== --- trunk/scipy/signal/signaltools.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/signal/signaltools.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -1467,10 +1467,10 @@ zi=lfilter_zi(b,a) - #Grow the signal to have edges for stabilizing + #Grow the signal to have edges for stabilizing #the filter with inverted replicas of the signal s=r_[2*x[0]-x[edge:1:-1],x,2*x[-1]-x[-1:-edge:-1]] - #in the case of one go we only need one of the extrems + #in the case of one go we only need one of the extrems # both are needed for filtfilt (y,zf)=lfilter(b,a,s,-1,zi*s[0]) Modified: trunk/scipy/signal/tests/test_signaltools.py =================================================================== --- trunk/scipy/signal/tests/test_signaltools.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/signal/tests/test_signaltools.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -57,4 +57,3 @@ if __name__ == "__main__": run_module_suite() - Modified: trunk/scipy/sparse/base.py =================================================================== --- trunk/scipy/sparse/base.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/base.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -216,7 +216,7 @@ # and operations return in csr format # thus, a new sparse matrix format just needs to define # a tocsr method - + def multiply(self, other): """Point-wise multiplication by another matrix """ @@ -237,7 +237,7 @@ def __rsub__(self, other): # other - self return self.tocsr().__rsub__(other) - + # old __mul__ interfaces def matvec(self, other): return self * other @@ -256,11 +256,11 @@ """ M,N = self.shape - + if isscalarlike(other): # scalar value return self._mul_scalar(other) - + if issparse(other): return self._mul_sparse_matrix(other) @@ -284,7 +284,7 @@ if other.ndim == 2 and other.shape[1] == 1: # If 'other' was an (nx1) column vector, reshape the result result = result.reshape(-1,1) - + return result elif len(other.shape) == 2: @@ -293,7 +293,7 @@ if other.shape[0] != self.shape[1]: raise ValueError('dimension mismatch') - + result = self._mul_dense_matrix(asarray(other)) if isinstance(other, matrix): @@ -414,7 +414,7 @@ def nonzero(self): """nonzero indices - + Returns a tuple of arrays (row,col) containing the indices of the non-zero elements of the matrix. @@ -430,7 +430,7 @@ # convert to COOrdinate format A = self.tocoo() - nz_mask = A.data != 0 + nz_mask = A.data != 0 return (A.row[nz_mask],A.col[nz_mask]) Modified: trunk/scipy/sparse/bsr.py =================================================================== --- trunk/scipy/sparse/bsr.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/bsr.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -296,11 +296,11 @@ result = zeros( self.shape[0], dtype=upcast(self.dtype, other.dtype) ) bsr_matvec(M/R, N/C, R, C, \ - self.indptr, self.indices, self.data.ravel(), + self.indptr, self.indices, self.data.ravel(), other, result) return result - + def _mul_dense_matrix(self,other): R,C = self.blocksize M,N = self.shape @@ -318,7 +318,7 @@ # # TODO make sparse * dense matrix multiplication more efficient # # matvec each column of other # result = hstack( [ self * col.reshape(-1,1) for col in asarray(other).T ] ) - # return result + # return result def _mul_sparse_matrix(self, other): M, K1 = self.shape Modified: trunk/scipy/sparse/compressed.py =================================================================== --- trunk/scipy/sparse/compressed.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/compressed.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -275,11 +275,11 @@ #output array result = zeros( self.shape[0], dtype=upcast(self.dtype,other.dtype) ) - + # csr_matvec or csc_matvec fn = getattr(sparsetools,self.format + '_matvec') fn(M, N, self.indptr, self.indices, self.data, other, result) - + return result @@ -295,7 +295,7 @@ return result - + def _mul_sparse_matrix(self, other): M, K1 = self.shape K2, N = other.shape @@ -319,10 +319,10 @@ indptr, indices, data) return self.__class__((data,indices,indptr),shape=(M,N)) - + def matvec(self,other): return self * other - + def matmat(self,other): return self * other @@ -358,12 +358,12 @@ # elif isdense(other): # # TODO make sparse * dense matrix multiplication more efficient - # + # # # matvec each column of other # result = hstack( [ self * col.reshape(-1,1) for col in asarray(other).T ] ) # if isinstance(other, matrix): # result = asmatrix(result) - # return result + # return result # else: # raise TypeError, "need a dense or sparse matrix" Modified: trunk/scipy/sparse/construct.py =================================================================== --- trunk/scipy/sparse/construct.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/construct.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -61,7 +61,7 @@ def identity(n, dtype='d', format=None): """Identity matrix in sparse format - + Returns an identity matrix with shape (n,n) using a given sparse format and dtype. Modified: trunk/scipy/sparse/coo.py =================================================================== --- trunk/scipy/sparse/coo.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/coo.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -338,7 +338,7 @@ result = zeros( self.shape[0], dtype=upcast(self.dtype,other.dtype) ) coo_matvec(self.nnz, self.row, self.col, self.data, other, result) return result - + def _mul_dense_matrix(self, other): return hstack( [ self._mul_vector(col).reshape(-1,1) for col in other.T ] ) Modified: trunk/scipy/sparse/data.py =================================================================== --- trunk/scipy/sparse/data.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/data.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -66,4 +66,3 @@ def _mul_scalar(self, other): return self._with_data(self.data * other) - Modified: trunk/scipy/sparse/dia.py =================================================================== --- trunk/scipy/sparse/dia.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/dia.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -157,7 +157,7 @@ def _mul_dense_matrix(self, other): return hstack( [ self._mul_vector(col).reshape(-1,1) for col in other.T ] ) - + def todia(self,copy=False): if copy: return self.copy() Modified: trunk/scipy/sparse/extract.py =================================================================== --- trunk/scipy/sparse/extract.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/extract.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -11,7 +11,7 @@ def tril(A, k=0, format=None): """Return the lower triangular portion of a matrix in sparse format - Returns the elements on or below the k-th diagonal of the matrix A. + Returns the elements on or below the k-th diagonal of the matrix A. - k = 0 corresponds to the main diagonal - k > 0 is above the main diagonal - k < 0 is below the main diagonal @@ -77,7 +77,7 @@ def triu(A, k=0, format=None): """Return the upper triangular portion of a matrix in sparse format - Returns the elements on or above the k-th diagonal of the matrix A. + Returns the elements on or above the k-th diagonal of the matrix A. - k = 0 corresponds to the main diagonal - k > 0 is above the main diagonal - k < 0 is below the main diagonal @@ -138,6 +138,3 @@ data = A.data[mask] return coo_matrix( (data,(row,col)), shape=A.shape ).asformat(format) - - - Modified: trunk/scipy/sparse/lil.py =================================================================== --- trunk/scipy/sparse/lil.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/lil.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -332,7 +332,7 @@ new.data = numpy.array([[val*other for val in rowvals] for rowvals in new.data], dtype=object) return new - + def __truediv__(self, other): # self / other if isscalarlike(other): new = self.copy() Modified: trunk/scipy/sparse/linalg/eigen/lobpcg/lobpcg.py =================================================================== --- trunk/scipy/sparse/linalg/eigen/lobpcg/lobpcg.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/linalg/eigen/lobpcg/lobpcg.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -141,7 +141,7 @@ else: return blockVectorV, blockVectorBV -def lobpcg( A, X, +def lobpcg( A, X, B=None, M=None, Y=None, tol= None, maxiter=20, largest = True, verbosityLevel = 0, @@ -151,14 +151,14 @@ This function implements the Locally Optimal Block Preconditioned Conjugate Gradient Method (LOBPCG). - + Parameters ---------- A : {sparse matrix, dense matrix, LinearOperator} - The symmetric linear operator of the problem, usually a + The symmetric linear operator of the problem, usually a sparse matrix. Often called the "stiffness matrix". X : array_like - Initial approximation to the k eigenvectors. If A has + Initial approximation to the k eigenvectors. If A has shape=(n,n) then X should have shape shape=(n,k). Returns Modified: trunk/scipy/sparse/linalg/isolve/utils.py =================================================================== --- trunk/scipy/sparse/linalg/isolve/utils.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/linalg/isolve/utils.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -1,6 +1,6 @@ __docformat__ = "restructuredtext en" -__all__ = [] +__all__ = [] from warnings import warn @@ -54,7 +54,7 @@ b : rank 1 ndarray right hand side postprocess : function - converts the solution vector to the appropriate + converts the solution vector to the appropriate type and dimensions (e.g. (N,1) matrix) """ Modified: trunk/scipy/sparse/sparsetools/bsr.py =================================================================== --- trunk/scipy/sparse/sparsetools/bsr.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/sparsetools/bsr.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -51,484 +51,483 @@ def bsr_diagonal(*args): - """ - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - signed char Ax, signed char Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned char Ax, unsigned char Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - short Ax, short Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned short Ax, unsigned short Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - int Ax, int Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned int Ax, unsigned int Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long long Ax, long long Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned long long Ax, unsigned long long Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - float Ax, float Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - double Ax, double Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long double Ax, long double Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, npy_cfloat_wrapper Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, npy_cdouble_wrapper Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Yx) """ - return _bsr.bsr_diagonal(*args) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + signed char Ax, signed char Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned char Ax, unsigned char Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + short Ax, short Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned short Ax, unsigned short Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + int Ax, int Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned int Ax, unsigned int Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long long Ax, long long Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned long long Ax, unsigned long long Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + float Ax, float Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + double Ax, double Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long double Ax, long double Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, npy_cfloat_wrapper Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, npy_cdouble_wrapper Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Yx) + """ + return _bsr.bsr_diagonal(*args) def bsr_scale_rows(*args): - """ - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - signed char Ax, signed char Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned char Ax, unsigned char Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - short Ax, short Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned short Ax, unsigned short Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - int Ax, int Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned int Ax, unsigned int Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long long Ax, long long Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned long long Ax, unsigned long long Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - float Ax, float Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - double Ax, double Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long double Ax, long double Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx) """ - return _bsr.bsr_scale_rows(*args) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + signed char Ax, signed char Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned char Ax, unsigned char Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + short Ax, short Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned short Ax, unsigned short Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + int Ax, int Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned int Ax, unsigned int Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long long Ax, long long Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned long long Ax, unsigned long long Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + float Ax, float Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + double Ax, double Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long double Ax, long double Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx) + """ + return _bsr.bsr_scale_rows(*args) def bsr_scale_columns(*args): - """ - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - signed char Ax, signed char Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned char Ax, unsigned char Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - short Ax, short Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned short Ax, unsigned short Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - int Ax, int Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned int Ax, unsigned int Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long long Ax, long long Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned long long Ax, unsigned long long Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - float Ax, float Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - double Ax, double Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long double Ax, long double Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx) """ - return _bsr.bsr_scale_columns(*args) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + signed char Ax, signed char Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned char Ax, unsigned char Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + short Ax, short Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned short Ax, unsigned short Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + int Ax, int Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned int Ax, unsigned int Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long long Ax, long long Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned long long Ax, unsigned long long Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + float Ax, float Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + double Ax, double Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long double Ax, long double Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx) + """ + return _bsr.bsr_scale_columns(*args) def bsr_transpose(*args): - """ - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - signed char Ax, int Bp, int Bj, signed char Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned char Ax, int Bp, int Bj, unsigned char Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - short Ax, int Bp, int Bj, short Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned short Ax, int Bp, int Bj, unsigned short Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - int Ax, int Bp, int Bj, int Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned int Ax, int Bp, int Bj, unsigned int Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long long Ax, int Bp, int Bj, long long Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned long long Ax, int Bp, int Bj, unsigned long long Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - float Ax, int Bp, int Bj, float Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - double Ax, int Bp, int Bj, double Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long double Ax, int Bp, int Bj, long double Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, int Bp, int Bj, - npy_clongdouble_wrapper Bx) """ - return _bsr.bsr_transpose(*args) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + signed char Ax, int Bp, int Bj, signed char Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned char Ax, int Bp, int Bj, unsigned char Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + short Ax, int Bp, int Bj, short Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned short Ax, int Bp, int Bj, unsigned short Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + int Ax, int Bp, int Bj, int Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned int Ax, int Bp, int Bj, unsigned int Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long long Ax, int Bp, int Bj, long long Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned long long Ax, int Bp, int Bj, unsigned long long Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + float Ax, int Bp, int Bj, float Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + double Ax, int Bp, int Bj, double Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long double Ax, int Bp, int Bj, long double Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, int Bp, int Bj, + npy_clongdouble_wrapper Bx) + """ + return _bsr.bsr_transpose(*args) def bsr_matmat_pass2(*args): - """ - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, signed char Ax, int Bp, int Bj, signed char Bx, - int Cp, int Cj, signed char Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, unsigned char Ax, int Bp, int Bj, unsigned char Bx, - int Cp, int Cj, unsigned char Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, short Ax, int Bp, int Bj, short Bx, - int Cp, int Cj, short Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, unsigned short Ax, int Bp, int Bj, - unsigned short Bx, int Cp, int Cj, unsigned short Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, int Ax, int Bp, int Bj, int Bx, int Cp, - int Cj, int Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, unsigned int Ax, int Bp, int Bj, unsigned int Bx, - int Cp, int Cj, unsigned int Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, long long Ax, int Bp, int Bj, long long Bx, - int Cp, int Cj, long long Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, unsigned long long Ax, int Bp, int Bj, - unsigned long long Bx, int Cp, int Cj, unsigned long long Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, float Ax, int Bp, int Bj, float Bx, - int Cp, int Cj, float Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, double Ax, int Bp, int Bj, double Bx, - int Cp, int Cj, double Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, long double Ax, int Bp, int Bj, long double Bx, - int Cp, int Cj, long double Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, npy_cfloat_wrapper Ax, int Bp, int Bj, - npy_cfloat_wrapper Bx, int Cp, int Cj, npy_cfloat_wrapper Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, npy_cdouble_wrapper Ax, int Bp, int Bj, - npy_cdouble_wrapper Bx, int Cp, int Cj, - npy_cdouble_wrapper Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, npy_clongdouble_wrapper Ax, int Bp, - int Bj, npy_clongdouble_wrapper Bx, int Cp, - int Cj, npy_clongdouble_wrapper Cx) """ - return _bsr.bsr_matmat_pass2(*args) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, signed char Ax, int Bp, int Bj, signed char Bx, + int Cp, int Cj, signed char Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, unsigned char Ax, int Bp, int Bj, unsigned char Bx, + int Cp, int Cj, unsigned char Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, short Ax, int Bp, int Bj, short Bx, + int Cp, int Cj, short Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, unsigned short Ax, int Bp, int Bj, + unsigned short Bx, int Cp, int Cj, unsigned short Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, int Ax, int Bp, int Bj, int Bx, int Cp, + int Cj, int Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, unsigned int Ax, int Bp, int Bj, unsigned int Bx, + int Cp, int Cj, unsigned int Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, long long Ax, int Bp, int Bj, long long Bx, + int Cp, int Cj, long long Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, unsigned long long Ax, int Bp, int Bj, + unsigned long long Bx, int Cp, int Cj, unsigned long long Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, float Ax, int Bp, int Bj, float Bx, + int Cp, int Cj, float Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, double Ax, int Bp, int Bj, double Bx, + int Cp, int Cj, double Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, long double Ax, int Bp, int Bj, long double Bx, + int Cp, int Cj, long double Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, npy_cfloat_wrapper Ax, int Bp, int Bj, + npy_cfloat_wrapper Bx, int Cp, int Cj, npy_cfloat_wrapper Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, npy_cdouble_wrapper Ax, int Bp, int Bj, + npy_cdouble_wrapper Bx, int Cp, int Cj, + npy_cdouble_wrapper Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, npy_clongdouble_wrapper Ax, int Bp, + int Bj, npy_clongdouble_wrapper Bx, int Cp, + int Cj, npy_clongdouble_wrapper Cx) + """ + return _bsr.bsr_matmat_pass2(*args) def bsr_matvec(*args): - """ - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - signed char Ax, signed char Xx, signed char Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned char Ax, unsigned char Xx, unsigned char Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - short Ax, short Xx, short Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned short Ax, unsigned short Xx, unsigned short Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - int Ax, int Xx, int Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned int Ax, unsigned int Xx, unsigned int Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long long Ax, long long Xx, long long Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned long long Ax, unsigned long long Xx, - unsigned long long Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - float Ax, float Xx, float Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - double Ax, double Xx, double Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long double Ax, long double Xx, long double Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx, - npy_cfloat_wrapper Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx, - npy_cdouble_wrapper Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx, - npy_clongdouble_wrapper Yx) """ - return _bsr.bsr_matvec(*args) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + signed char Ax, signed char Xx, signed char Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned char Ax, unsigned char Xx, unsigned char Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + short Ax, short Xx, short Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned short Ax, unsigned short Xx, unsigned short Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + int Ax, int Xx, int Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned int Ax, unsigned int Xx, unsigned int Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long long Ax, long long Xx, long long Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned long long Ax, unsigned long long Xx, + unsigned long long Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + float Ax, float Xx, float Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + double Ax, double Xx, double Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long double Ax, long double Xx, long double Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx, + npy_cfloat_wrapper Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx, + npy_cdouble_wrapper Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx, + npy_clongdouble_wrapper Yx) + """ + return _bsr.bsr_matvec(*args) def bsr_matvecs(*args): - """ - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, signed char Ax, signed char Xx, - signed char Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, unsigned char Ax, unsigned char Xx, - unsigned char Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, short Ax, short Xx, short Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, unsigned short Ax, unsigned short Xx, - unsigned short Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, int Ax, int Xx, int Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, unsigned int Ax, unsigned int Xx, - unsigned int Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, long long Ax, long long Xx, long long Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, unsigned long long Ax, unsigned long long Xx, - unsigned long long Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, float Ax, float Xx, float Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, double Ax, double Xx, double Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, long double Ax, long double Xx, - long double Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx, - npy_cfloat_wrapper Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx, - npy_cdouble_wrapper Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx, - npy_clongdouble_wrapper Yx) """ - return _bsr.bsr_matvecs(*args) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, signed char Ax, signed char Xx, + signed char Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, unsigned char Ax, unsigned char Xx, + unsigned char Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, short Ax, short Xx, short Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, unsigned short Ax, unsigned short Xx, + unsigned short Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, int Ax, int Xx, int Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, unsigned int Ax, unsigned int Xx, + unsigned int Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, long long Ax, long long Xx, long long Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, unsigned long long Ax, unsigned long long Xx, + unsigned long long Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, float Ax, float Xx, float Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, double Ax, double Xx, double Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, long double Ax, long double Xx, + long double Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx, + npy_cfloat_wrapper Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx, + npy_cdouble_wrapper Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx, + npy_clongdouble_wrapper Yx) + """ + return _bsr.bsr_matvecs(*args) def bsr_elmul_bsr(*args): - """ - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - signed char Ax, int Bp, int Bj, signed char Bx, - int Cp, int Cj, signed char Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned char Ax, int Bp, int Bj, unsigned char Bx, - int Cp, int Cj, unsigned char Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - short Ax, int Bp, int Bj, short Bx, int Cp, - int Cj, short Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned short Ax, int Bp, int Bj, unsigned short Bx, - int Cp, int Cj, unsigned short Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, - int Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned int Ax, int Bp, int Bj, unsigned int Bx, - int Cp, int Cj, unsigned int Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long long Ax, int Bp, int Bj, long long Bx, - int Cp, int Cj, long long Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - float Ax, int Bp, int Bj, float Bx, int Cp, - int Cj, float Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - double Ax, int Bp, int Bj, double Bx, int Cp, - int Cj, double Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long double Ax, int Bp, int Bj, long double Bx, - int Cp, int Cj, long double Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, int Bp, int Bj, - npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - return _bsr.bsr_elmul_bsr(*args) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + signed char Ax, int Bp, int Bj, signed char Bx, + int Cp, int Cj, signed char Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned char Ax, int Bp, int Bj, unsigned char Bx, + int Cp, int Cj, unsigned char Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + short Ax, int Bp, int Bj, short Bx, int Cp, + int Cj, short Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned short Ax, int Bp, int Bj, unsigned short Bx, + int Cp, int Cj, unsigned short Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, + int Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned int Ax, int Bp, int Bj, unsigned int Bx, + int Cp, int Cj, unsigned int Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long long Ax, int Bp, int Bj, long long Bx, + int Cp, int Cj, long long Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + float Ax, int Bp, int Bj, float Bx, int Cp, + int Cj, float Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + double Ax, int Bp, int Bj, double Bx, int Cp, + int Cj, double Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long double Ax, int Bp, int Bj, long double Bx, + int Cp, int Cj, long double Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, int Bp, int Bj, + npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) + """ + return _bsr.bsr_elmul_bsr(*args) def bsr_eldiv_bsr(*args): - """ - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - signed char Ax, int Bp, int Bj, signed char Bx, - int Cp, int Cj, signed char Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned char Ax, int Bp, int Bj, unsigned char Bx, - int Cp, int Cj, unsigned char Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - short Ax, int Bp, int Bj, short Bx, int Cp, - int Cj, short Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned short Ax, int Bp, int Bj, unsigned short Bx, - int Cp, int Cj, unsigned short Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, - int Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned int Ax, int Bp, int Bj, unsigned int Bx, - int Cp, int Cj, unsigned int Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long long Ax, int Bp, int Bj, long long Bx, - int Cp, int Cj, long long Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - float Ax, int Bp, int Bj, float Bx, int Cp, - int Cj, float Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - double Ax, int Bp, int Bj, double Bx, int Cp, - int Cj, double Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long double Ax, int Bp, int Bj, long double Bx, - int Cp, int Cj, long double Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, int Bp, int Bj, - npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - return _bsr.bsr_eldiv_bsr(*args) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + signed char Ax, int Bp, int Bj, signed char Bx, + int Cp, int Cj, signed char Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned char Ax, int Bp, int Bj, unsigned char Bx, + int Cp, int Cj, unsigned char Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + short Ax, int Bp, int Bj, short Bx, int Cp, + int Cj, short Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned short Ax, int Bp, int Bj, unsigned short Bx, + int Cp, int Cj, unsigned short Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, + int Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned int Ax, int Bp, int Bj, unsigned int Bx, + int Cp, int Cj, unsigned int Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long long Ax, int Bp, int Bj, long long Bx, + int Cp, int Cj, long long Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + float Ax, int Bp, int Bj, float Bx, int Cp, + int Cj, float Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + double Ax, int Bp, int Bj, double Bx, int Cp, + int Cj, double Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long double Ax, int Bp, int Bj, long double Bx, + int Cp, int Cj, long double Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, int Bp, int Bj, + npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) + """ + return _bsr.bsr_eldiv_bsr(*args) def bsr_plus_bsr(*args): - """ - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - signed char Ax, int Bp, int Bj, signed char Bx, - int Cp, int Cj, signed char Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned char Ax, int Bp, int Bj, unsigned char Bx, - int Cp, int Cj, unsigned char Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - short Ax, int Bp, int Bj, short Bx, int Cp, - int Cj, short Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned short Ax, int Bp, int Bj, unsigned short Bx, - int Cp, int Cj, unsigned short Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, - int Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned int Ax, int Bp, int Bj, unsigned int Bx, - int Cp, int Cj, unsigned int Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long long Ax, int Bp, int Bj, long long Bx, - int Cp, int Cj, long long Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - float Ax, int Bp, int Bj, float Bx, int Cp, - int Cj, float Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - double Ax, int Bp, int Bj, double Bx, int Cp, - int Cj, double Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long double Ax, int Bp, int Bj, long double Bx, - int Cp, int Cj, long double Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, int Bp, int Bj, - npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - return _bsr.bsr_plus_bsr(*args) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + signed char Ax, int Bp, int Bj, signed char Bx, + int Cp, int Cj, signed char Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned char Ax, int Bp, int Bj, unsigned char Bx, + int Cp, int Cj, unsigned char Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + short Ax, int Bp, int Bj, short Bx, int Cp, + int Cj, short Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned short Ax, int Bp, int Bj, unsigned short Bx, + int Cp, int Cj, unsigned short Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, + int Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned int Ax, int Bp, int Bj, unsigned int Bx, + int Cp, int Cj, unsigned int Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long long Ax, int Bp, int Bj, long long Bx, + int Cp, int Cj, long long Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + float Ax, int Bp, int Bj, float Bx, int Cp, + int Cj, float Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + double Ax, int Bp, int Bj, double Bx, int Cp, + int Cj, double Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long double Ax, int Bp, int Bj, long double Bx, + int Cp, int Cj, long double Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, int Bp, int Bj, + npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) + """ + return _bsr.bsr_plus_bsr(*args) def bsr_minus_bsr(*args): - """ - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - signed char Ax, int Bp, int Bj, signed char Bx, - int Cp, int Cj, signed char Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned char Ax, int Bp, int Bj, unsigned char Bx, - int Cp, int Cj, unsigned char Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - short Ax, int Bp, int Bj, short Bx, int Cp, - int Cj, short Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned short Ax, int Bp, int Bj, unsigned short Bx, - int Cp, int Cj, unsigned short Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, - int Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned int Ax, int Bp, int Bj, unsigned int Bx, - int Cp, int Cj, unsigned int Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long long Ax, int Bp, int Bj, long long Bx, - int Cp, int Cj, long long Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - float Ax, int Bp, int Bj, float Bx, int Cp, - int Cj, float Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - double Ax, int Bp, int Bj, double Bx, int Cp, - int Cj, double Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long double Ax, int Bp, int Bj, long double Bx, - int Cp, int Cj, long double Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, int Bp, int Bj, - npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - return _bsr.bsr_minus_bsr(*args) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + signed char Ax, int Bp, int Bj, signed char Bx, + int Cp, int Cj, signed char Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned char Ax, int Bp, int Bj, unsigned char Bx, + int Cp, int Cj, unsigned char Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + short Ax, int Bp, int Bj, short Bx, int Cp, + int Cj, short Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned short Ax, int Bp, int Bj, unsigned short Bx, + int Cp, int Cj, unsigned short Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, + int Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned int Ax, int Bp, int Bj, unsigned int Bx, + int Cp, int Cj, unsigned int Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long long Ax, int Bp, int Bj, long long Bx, + int Cp, int Cj, long long Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + float Ax, int Bp, int Bj, float Bx, int Cp, + int Cj, float Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + double Ax, int Bp, int Bj, double Bx, int Cp, + int Cj, double Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long double Ax, int Bp, int Bj, long double Bx, + int Cp, int Cj, long double Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, int Bp, int Bj, + npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) + """ + return _bsr.bsr_minus_bsr(*args) def bsr_sort_indices(*args): - """ - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - signed char Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned char Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - short Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned short Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - int Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned int Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long long Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned long long Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - float Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - double Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long double Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax) """ - return _bsr.bsr_sort_indices(*args) - + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + signed char Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned char Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + short Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned short Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + int Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned int Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long long Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned long long Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + float Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + double Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long double Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax) + """ + return _bsr.bsr_sort_indices(*args) Modified: trunk/scipy/sparse/sparsetools/coo.py =================================================================== --- trunk/scipy/sparse/sparsetools/coo.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/sparsetools/coo.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -51,130 +51,129 @@ def coo_tocsr(*args): - """ - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, signed char Ax, - int Bp, int Bj, signed char Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned char Ax, - int Bp, int Bj, unsigned char Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, short Ax, - int Bp, int Bj, short Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned short Ax, - int Bp, int Bj, unsigned short Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, int Ax, - int Bp, int Bj, int Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned int Ax, - int Bp, int Bj, unsigned int Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, long long Ax, - int Bp, int Bj, long long Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned long long Ax, - int Bp, int Bj, unsigned long long Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, float Ax, - int Bp, int Bj, float Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, double Ax, - int Bp, int Bj, double Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, long double Ax, - int Bp, int Bj, long double Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bj, npy_cfloat_wrapper Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bj, npy_cdouble_wrapper Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bj, npy_clongdouble_wrapper Bx) """ - return _coo.coo_tocsr(*args) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, signed char Ax, + int Bp, int Bj, signed char Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned char Ax, + int Bp, int Bj, unsigned char Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, short Ax, + int Bp, int Bj, short Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned short Ax, + int Bp, int Bj, unsigned short Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, int Ax, + int Bp, int Bj, int Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned int Ax, + int Bp, int Bj, unsigned int Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, long long Ax, + int Bp, int Bj, long long Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned long long Ax, + int Bp, int Bj, unsigned long long Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, float Ax, + int Bp, int Bj, float Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, double Ax, + int Bp, int Bj, double Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, long double Ax, + int Bp, int Bj, long double Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bj, npy_cfloat_wrapper Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bj, npy_cdouble_wrapper Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bj, npy_clongdouble_wrapper Bx) + """ + return _coo.coo_tocsr(*args) def coo_tocsc(*args): - """ - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, signed char Ax, - int Bp, int Bi, signed char Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned char Ax, - int Bp, int Bi, unsigned char Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, short Ax, - int Bp, int Bi, short Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned short Ax, - int Bp, int Bi, unsigned short Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, int Ax, - int Bp, int Bi, int Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned int Ax, - int Bp, int Bi, unsigned int Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, long long Ax, - int Bp, int Bi, long long Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned long long Ax, - int Bp, int Bi, unsigned long long Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, float Ax, - int Bp, int Bi, float Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, double Ax, - int Bp, int Bi, double Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, long double Ax, - int Bp, int Bi, long double Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bi, npy_cfloat_wrapper Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bi, npy_cdouble_wrapper Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bi, npy_clongdouble_wrapper Bx) """ - return _coo.coo_tocsc(*args) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, signed char Ax, + int Bp, int Bi, signed char Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned char Ax, + int Bp, int Bi, unsigned char Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, short Ax, + int Bp, int Bi, short Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned short Ax, + int Bp, int Bi, unsigned short Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, int Ax, + int Bp, int Bi, int Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned int Ax, + int Bp, int Bi, unsigned int Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, long long Ax, + int Bp, int Bi, long long Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned long long Ax, + int Bp, int Bi, unsigned long long Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, float Ax, + int Bp, int Bi, float Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, double Ax, + int Bp, int Bi, double Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, long double Ax, + int Bp, int Bi, long double Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bi, npy_cfloat_wrapper Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bi, npy_cdouble_wrapper Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bi, npy_clongdouble_wrapper Bx) + """ + return _coo.coo_tocsc(*args) def coo_todense(*args): - """ - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, signed char Ax, - signed char Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned char Ax, - unsigned char Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, short Ax, - short Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned short Ax, - unsigned short Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, int Ax, - int Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned int Ax, - unsigned int Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, long long Ax, - long long Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned long long Ax, - unsigned long long Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, float Ax, - float Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, double Ax, - double Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, long double Ax, - long double Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Bx) """ - return _coo.coo_todense(*args) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, signed char Ax, + signed char Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned char Ax, + unsigned char Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, short Ax, + short Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned short Ax, + unsigned short Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, int Ax, + int Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned int Ax, + unsigned int Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, long long Ax, + long long Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned long long Ax, + unsigned long long Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, float Ax, + float Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, double Ax, + double Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, long double Ax, + long double Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Bx) + """ + return _coo.coo_todense(*args) def coo_matvec(*args): - """ - coo_matvec(int nnz, int Ai, int Aj, signed char Ax, signed char Xx, - signed char Yx) - coo_matvec(int nnz, int Ai, int Aj, unsigned char Ax, unsigned char Xx, - unsigned char Yx) - coo_matvec(int nnz, int Ai, int Aj, short Ax, short Xx, short Yx) - coo_matvec(int nnz, int Ai, int Aj, unsigned short Ax, unsigned short Xx, - unsigned short Yx) - coo_matvec(int nnz, int Ai, int Aj, int Ax, int Xx, int Yx) - coo_matvec(int nnz, int Ai, int Aj, unsigned int Ax, unsigned int Xx, - unsigned int Yx) - coo_matvec(int nnz, int Ai, int Aj, long long Ax, long long Xx, - long long Yx) - coo_matvec(int nnz, int Ai, int Aj, unsigned long long Ax, unsigned long long Xx, - unsigned long long Yx) - coo_matvec(int nnz, int Ai, int Aj, float Ax, float Xx, float Yx) - coo_matvec(int nnz, int Ai, int Aj, double Ax, double Xx, double Yx) - coo_matvec(int nnz, int Ai, int Aj, long double Ax, long double Xx, - long double Yx) - coo_matvec(int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx, - npy_cfloat_wrapper Yx) - coo_matvec(int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx, - npy_cdouble_wrapper Yx) - coo_matvec(int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Xx, npy_clongdouble_wrapper Yx) """ - return _coo.coo_matvec(*args) - + coo_matvec(int nnz, int Ai, int Aj, signed char Ax, signed char Xx, + signed char Yx) + coo_matvec(int nnz, int Ai, int Aj, unsigned char Ax, unsigned char Xx, + unsigned char Yx) + coo_matvec(int nnz, int Ai, int Aj, short Ax, short Xx, short Yx) + coo_matvec(int nnz, int Ai, int Aj, unsigned short Ax, unsigned short Xx, + unsigned short Yx) + coo_matvec(int nnz, int Ai, int Aj, int Ax, int Xx, int Yx) + coo_matvec(int nnz, int Ai, int Aj, unsigned int Ax, unsigned int Xx, + unsigned int Yx) + coo_matvec(int nnz, int Ai, int Aj, long long Ax, long long Xx, + long long Yx) + coo_matvec(int nnz, int Ai, int Aj, unsigned long long Ax, unsigned long long Xx, + unsigned long long Yx) + coo_matvec(int nnz, int Ai, int Aj, float Ax, float Xx, float Yx) + coo_matvec(int nnz, int Ai, int Aj, double Ax, double Xx, double Yx) + coo_matvec(int nnz, int Ai, int Aj, long double Ax, long double Xx, + long double Yx) + coo_matvec(int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx, + npy_cfloat_wrapper Yx) + coo_matvec(int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx, + npy_cdouble_wrapper Yx) + coo_matvec(int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Xx, npy_clongdouble_wrapper Yx) + """ + return _coo.coo_matvec(*args) Modified: trunk/scipy/sparse/sparsetools/csc.py =================================================================== --- trunk/scipy/sparse/sparsetools/csc.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/sparsetools/csc.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -50,357 +50,356 @@ def csc_matmat_pass1(*args): - """ - csc_matmat_pass1(int n_row, int n_col, int Ap, int Ai, int Bp, int Bi, - int Cp) """ - return _csc.csc_matmat_pass1(*args) + csc_matmat_pass1(int n_row, int n_col, int Ap, int Ai, int Bp, int Bi, + int Cp) + """ + return _csc.csc_matmat_pass1(*args) def csc_diagonal(*args): - """ - csc_diagonal(int n_row, int n_col, int Ap, int Aj, signed char Ax, - signed char Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - unsigned char Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, short Ax, short Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - unsigned short Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, int Ax, int Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - unsigned int Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, long long Ax, - long long Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - unsigned long long Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, float Ax, float Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, double Ax, double Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, long double Ax, - long double Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Yx) """ - return _csc.csc_diagonal(*args) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, signed char Ax, + signed char Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + unsigned char Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, short Ax, short Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + unsigned short Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, int Ax, int Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + unsigned int Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, long long Ax, + long long Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + unsigned long long Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, float Ax, float Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, double Ax, double Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, long double Ax, + long double Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Yx) + """ + return _csc.csc_diagonal(*args) def csc_tocsr(*args): - """ - csc_tocsr(int n_row, int n_col, int Ap, int Ai, signed char Ax, - int Bp, int Bj, signed char Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, - int Bp, int Bj, unsigned char Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, - int Bj, short Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, - int Bp, int Bj, unsigned short Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, - int Bj, int Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, - int Bp, int Bj, unsigned int Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, long long Ax, - int Bp, int Bj, long long Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, - int Bp, int Bj, unsigned long long Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, - int Bj, float Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, - int Bj, double Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, long double Ax, - int Bp, int Bj, long double Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, - int Bp, int Bj, npy_cfloat_wrapper Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, - int Bp, int Bj, npy_cdouble_wrapper Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, - int Bp, int Bj, npy_clongdouble_wrapper Bx) """ - return _csc.csc_tocsr(*args) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, signed char Ax, + int Bp, int Bj, signed char Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, + int Bp, int Bj, unsigned char Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, + int Bj, short Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, + int Bp, int Bj, unsigned short Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, + int Bj, int Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, + int Bp, int Bj, unsigned int Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, long long Ax, + int Bp, int Bj, long long Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, + int Bp, int Bj, unsigned long long Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, + int Bj, float Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, + int Bj, double Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, long double Ax, + int Bp, int Bj, long double Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, + int Bp, int Bj, npy_cfloat_wrapper Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, + int Bp, int Bj, npy_cdouble_wrapper Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, + int Bp, int Bj, npy_clongdouble_wrapper Bx) + """ + return _csc.csc_tocsr(*args) def csc_matmat_pass2(*args): - """ - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, signed char Ax, - int Bp, int Bi, signed char Bx, int Cp, int Ci, - signed char Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, - int Bp, int Bi, unsigned char Bx, int Cp, - int Ci, unsigned char Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, - int Bi, short Bx, int Cp, int Ci, short Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, - int Bp, int Bi, unsigned short Bx, int Cp, - int Ci, unsigned short Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, - int Bi, int Bx, int Cp, int Ci, int Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, - int Bp, int Bi, unsigned int Bx, int Cp, - int Ci, unsigned int Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, long long Ax, - int Bp, int Bi, long long Bx, int Cp, int Ci, - long long Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, - int Bp, int Bi, unsigned long long Bx, - int Cp, int Ci, unsigned long long Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, - int Bi, float Bx, int Cp, int Ci, float Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, - int Bi, double Bx, int Cp, int Ci, double Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, long double Ax, - int Bp, int Bi, long double Bx, int Cp, int Ci, - long double Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, - int Bp, int Bi, npy_cfloat_wrapper Bx, - int Cp, int Ci, npy_cfloat_wrapper Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, - int Bp, int Bi, npy_cdouble_wrapper Bx, - int Cp, int Ci, npy_cdouble_wrapper Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, - int Bp, int Bi, npy_clongdouble_wrapper Bx, - int Cp, int Ci, npy_clongdouble_wrapper Cx) """ - return _csc.csc_matmat_pass2(*args) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, signed char Ax, + int Bp, int Bi, signed char Bx, int Cp, int Ci, + signed char Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, + int Bp, int Bi, unsigned char Bx, int Cp, + int Ci, unsigned char Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, + int Bi, short Bx, int Cp, int Ci, short Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, + int Bp, int Bi, unsigned short Bx, int Cp, + int Ci, unsigned short Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, + int Bi, int Bx, int Cp, int Ci, int Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, + int Bp, int Bi, unsigned int Bx, int Cp, + int Ci, unsigned int Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, long long Ax, + int Bp, int Bi, long long Bx, int Cp, int Ci, + long long Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, + int Bp, int Bi, unsigned long long Bx, + int Cp, int Ci, unsigned long long Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, + int Bi, float Bx, int Cp, int Ci, float Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, + int Bi, double Bx, int Cp, int Ci, double Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, long double Ax, + int Bp, int Bi, long double Bx, int Cp, int Ci, + long double Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, + int Bp, int Bi, npy_cfloat_wrapper Bx, + int Cp, int Ci, npy_cfloat_wrapper Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, + int Bp, int Bi, npy_cdouble_wrapper Bx, + int Cp, int Ci, npy_cdouble_wrapper Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, + int Bp, int Bi, npy_clongdouble_wrapper Bx, + int Cp, int Ci, npy_clongdouble_wrapper Cx) + """ + return _csc.csc_matmat_pass2(*args) def csc_matvec(*args): - """ - csc_matvec(int n_row, int n_col, int Ap, int Ai, signed char Ax, - signed char Xx, signed char Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, - unsigned char Xx, unsigned char Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, short Ax, short Xx, - short Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, - unsigned short Xx, unsigned short Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, int Ax, int Xx, - int Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, - unsigned int Xx, unsigned int Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, long long Ax, - long long Xx, long long Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, - unsigned long long Xx, unsigned long long Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, float Ax, float Xx, - float Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, double Ax, double Xx, - double Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, long double Ax, - long double Xx, long double Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Xx, npy_cfloat_wrapper Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Xx, npy_cdouble_wrapper Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Xx, npy_clongdouble_wrapper Yx) """ - return _csc.csc_matvec(*args) + csc_matvec(int n_row, int n_col, int Ap, int Ai, signed char Ax, + signed char Xx, signed char Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, + unsigned char Xx, unsigned char Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, short Ax, short Xx, + short Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, + unsigned short Xx, unsigned short Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, int Ax, int Xx, + int Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, + unsigned int Xx, unsigned int Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, long long Ax, + long long Xx, long long Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, + unsigned long long Xx, unsigned long long Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, float Ax, float Xx, + float Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, double Ax, double Xx, + double Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, long double Ax, + long double Xx, long double Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Xx, npy_cfloat_wrapper Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Xx, npy_cdouble_wrapper Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Xx, npy_clongdouble_wrapper Yx) + """ + return _csc.csc_matvec(*args) def csc_matvecs(*args): - """ - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, signed char Ax, - signed char Xx, signed char Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned char Ax, - unsigned char Xx, unsigned char Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, short Ax, - short Xx, short Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned short Ax, - unsigned short Xx, unsigned short Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, int Ax, - int Xx, int Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned int Ax, - unsigned int Xx, unsigned int Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, long long Ax, - long long Xx, long long Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned long long Ax, - unsigned long long Xx, - unsigned long long Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, float Ax, - float Xx, float Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, double Ax, - double Xx, double Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, long double Ax, - long double Xx, long double Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Xx, - npy_cfloat_wrapper Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Xx, - npy_cdouble_wrapper Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Xx, - npy_clongdouble_wrapper Yx) """ - return _csc.csc_matvecs(*args) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, signed char Ax, + signed char Xx, signed char Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned char Ax, + unsigned char Xx, unsigned char Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, short Ax, + short Xx, short Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned short Ax, + unsigned short Xx, unsigned short Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, int Ax, + int Xx, int Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned int Ax, + unsigned int Xx, unsigned int Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, long long Ax, + long long Xx, long long Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned long long Ax, + unsigned long long Xx, + unsigned long long Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, float Ax, + float Xx, float Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, double Ax, + double Xx, double Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, long double Ax, + long double Xx, long double Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Xx, + npy_cfloat_wrapper Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Xx, + npy_cdouble_wrapper Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Xx, + npy_clongdouble_wrapper Yx) + """ + return _csc.csc_matvecs(*args) def csc_elmul_csc(*args): - """ - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, - int Bp, int Bi, signed char Bx, int Cp, int Ci, - signed char Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, - int Bp, int Bi, unsigned char Bx, int Cp, - int Ci, unsigned char Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, - int Bi, short Bx, int Cp, int Ci, short Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, - int Bp, int Bi, unsigned short Bx, int Cp, - int Ci, unsigned short Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, - int Bi, int Bx, int Cp, int Ci, int Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, - int Bp, int Bi, unsigned int Bx, int Cp, - int Ci, unsigned int Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, - int Bp, int Bi, long long Bx, int Cp, int Ci, - long long Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, - int Bp, int Bi, unsigned long long Bx, - int Cp, int Ci, unsigned long long Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, - int Bi, float Bx, int Cp, int Ci, float Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, - int Bi, double Bx, int Cp, int Ci, double Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, - int Bp, int Bi, long double Bx, int Cp, int Ci, - long double Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, - int Bp, int Bi, npy_cfloat_wrapper Bx, - int Cp, int Ci, npy_cfloat_wrapper Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, - int Bp, int Bi, npy_cdouble_wrapper Bx, - int Cp, int Ci, npy_cdouble_wrapper Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, - int Bp, int Bi, npy_clongdouble_wrapper Bx, - int Cp, int Ci, npy_clongdouble_wrapper Cx) """ - return _csc.csc_elmul_csc(*args) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, + int Bp, int Bi, signed char Bx, int Cp, int Ci, + signed char Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, + int Bp, int Bi, unsigned char Bx, int Cp, + int Ci, unsigned char Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, + int Bi, short Bx, int Cp, int Ci, short Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, + int Bp, int Bi, unsigned short Bx, int Cp, + int Ci, unsigned short Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, + int Bi, int Bx, int Cp, int Ci, int Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, + int Bp, int Bi, unsigned int Bx, int Cp, + int Ci, unsigned int Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, + int Bp, int Bi, long long Bx, int Cp, int Ci, + long long Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, + int Bp, int Bi, unsigned long long Bx, + int Cp, int Ci, unsigned long long Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, + int Bi, float Bx, int Cp, int Ci, float Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, + int Bi, double Bx, int Cp, int Ci, double Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, + int Bp, int Bi, long double Bx, int Cp, int Ci, + long double Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, + int Bp, int Bi, npy_cfloat_wrapper Bx, + int Cp, int Ci, npy_cfloat_wrapper Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, + int Bp, int Bi, npy_cdouble_wrapper Bx, + int Cp, int Ci, npy_cdouble_wrapper Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, + int Bp, int Bi, npy_clongdouble_wrapper Bx, + int Cp, int Ci, npy_clongdouble_wrapper Cx) + """ + return _csc.csc_elmul_csc(*args) def csc_eldiv_csc(*args): - """ - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, - int Bp, int Bi, signed char Bx, int Cp, int Ci, - signed char Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, - int Bp, int Bi, unsigned char Bx, int Cp, - int Ci, unsigned char Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, - int Bi, short Bx, int Cp, int Ci, short Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, - int Bp, int Bi, unsigned short Bx, int Cp, - int Ci, unsigned short Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, - int Bi, int Bx, int Cp, int Ci, int Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, - int Bp, int Bi, unsigned int Bx, int Cp, - int Ci, unsigned int Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, - int Bp, int Bi, long long Bx, int Cp, int Ci, - long long Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, - int Bp, int Bi, unsigned long long Bx, - int Cp, int Ci, unsigned long long Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, - int Bi, float Bx, int Cp, int Ci, float Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, - int Bi, double Bx, int Cp, int Ci, double Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, - int Bp, int Bi, long double Bx, int Cp, int Ci, - long double Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, - int Bp, int Bi, npy_cfloat_wrapper Bx, - int Cp, int Ci, npy_cfloat_wrapper Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, - int Bp, int Bi, npy_cdouble_wrapper Bx, - int Cp, int Ci, npy_cdouble_wrapper Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, - int Bp, int Bi, npy_clongdouble_wrapper Bx, - int Cp, int Ci, npy_clongdouble_wrapper Cx) """ - return _csc.csc_eldiv_csc(*args) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, + int Bp, int Bi, signed char Bx, int Cp, int Ci, + signed char Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, + int Bp, int Bi, unsigned char Bx, int Cp, + int Ci, unsigned char Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, + int Bi, short Bx, int Cp, int Ci, short Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, + int Bp, int Bi, unsigned short Bx, int Cp, + int Ci, unsigned short Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, + int Bi, int Bx, int Cp, int Ci, int Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, + int Bp, int Bi, unsigned int Bx, int Cp, + int Ci, unsigned int Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, + int Bp, int Bi, long long Bx, int Cp, int Ci, + long long Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, + int Bp, int Bi, unsigned long long Bx, + int Cp, int Ci, unsigned long long Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, + int Bi, float Bx, int Cp, int Ci, float Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, + int Bi, double Bx, int Cp, int Ci, double Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, + int Bp, int Bi, long double Bx, int Cp, int Ci, + long double Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, + int Bp, int Bi, npy_cfloat_wrapper Bx, + int Cp, int Ci, npy_cfloat_wrapper Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, + int Bp, int Bi, npy_cdouble_wrapper Bx, + int Cp, int Ci, npy_cdouble_wrapper Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, + int Bp, int Bi, npy_clongdouble_wrapper Bx, + int Cp, int Ci, npy_clongdouble_wrapper Cx) + """ + return _csc.csc_eldiv_csc(*args) def csc_plus_csc(*args): - """ - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, - int Bp, int Bi, signed char Bx, int Cp, int Ci, - signed char Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, - int Bp, int Bi, unsigned char Bx, int Cp, - int Ci, unsigned char Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, - int Bi, short Bx, int Cp, int Ci, short Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, - int Bp, int Bi, unsigned short Bx, int Cp, - int Ci, unsigned short Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, - int Bi, int Bx, int Cp, int Ci, int Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, - int Bp, int Bi, unsigned int Bx, int Cp, - int Ci, unsigned int Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, - int Bp, int Bi, long long Bx, int Cp, int Ci, - long long Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, - int Bp, int Bi, unsigned long long Bx, - int Cp, int Ci, unsigned long long Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, - int Bi, float Bx, int Cp, int Ci, float Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, - int Bi, double Bx, int Cp, int Ci, double Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, - int Bp, int Bi, long double Bx, int Cp, int Ci, - long double Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, - int Bp, int Bi, npy_cfloat_wrapper Bx, - int Cp, int Ci, npy_cfloat_wrapper Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, - int Bp, int Bi, npy_cdouble_wrapper Bx, - int Cp, int Ci, npy_cdouble_wrapper Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, - int Bp, int Bi, npy_clongdouble_wrapper Bx, - int Cp, int Ci, npy_clongdouble_wrapper Cx) """ - return _csc.csc_plus_csc(*args) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, + int Bp, int Bi, signed char Bx, int Cp, int Ci, + signed char Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, + int Bp, int Bi, unsigned char Bx, int Cp, + int Ci, unsigned char Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, + int Bi, short Bx, int Cp, int Ci, short Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, + int Bp, int Bi, unsigned short Bx, int Cp, + int Ci, unsigned short Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, + int Bi, int Bx, int Cp, int Ci, int Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, + int Bp, int Bi, unsigned int Bx, int Cp, + int Ci, unsigned int Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, + int Bp, int Bi, long long Bx, int Cp, int Ci, + long long Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, + int Bp, int Bi, unsigned long long Bx, + int Cp, int Ci, unsigned long long Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, + int Bi, float Bx, int Cp, int Ci, float Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, + int Bi, double Bx, int Cp, int Ci, double Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, + int Bp, int Bi, long double Bx, int Cp, int Ci, + long double Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, + int Bp, int Bi, npy_cfloat_wrapper Bx, + int Cp, int Ci, npy_cfloat_wrapper Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, + int Bp, int Bi, npy_cdouble_wrapper Bx, + int Cp, int Ci, npy_cdouble_wrapper Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, + int Bp, int Bi, npy_clongdouble_wrapper Bx, + int Cp, int Ci, npy_clongdouble_wrapper Cx) + """ + return _csc.csc_plus_csc(*args) def csc_minus_csc(*args): - """ - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, - int Bp, int Bi, signed char Bx, int Cp, int Ci, - signed char Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, - int Bp, int Bi, unsigned char Bx, int Cp, - int Ci, unsigned char Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, - int Bi, short Bx, int Cp, int Ci, short Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, - int Bp, int Bi, unsigned short Bx, int Cp, - int Ci, unsigned short Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, - int Bi, int Bx, int Cp, int Ci, int Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, - int Bp, int Bi, unsigned int Bx, int Cp, - int Ci, unsigned int Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, - int Bp, int Bi, long long Bx, int Cp, int Ci, - long long Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, - int Bp, int Bi, unsigned long long Bx, - int Cp, int Ci, unsigned long long Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, - int Bi, float Bx, int Cp, int Ci, float Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, - int Bi, double Bx, int Cp, int Ci, double Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, - int Bp, int Bi, long double Bx, int Cp, int Ci, - long double Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, - int Bp, int Bi, npy_cfloat_wrapper Bx, - int Cp, int Ci, npy_cfloat_wrapper Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, - int Bp, int Bi, npy_cdouble_wrapper Bx, - int Cp, int Ci, npy_cdouble_wrapper Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, - int Bp, int Bi, npy_clongdouble_wrapper Bx, - int Cp, int Ci, npy_clongdouble_wrapper Cx) """ - return _csc.csc_minus_csc(*args) - + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, + int Bp, int Bi, signed char Bx, int Cp, int Ci, + signed char Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, + int Bp, int Bi, unsigned char Bx, int Cp, + int Ci, unsigned char Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, + int Bi, short Bx, int Cp, int Ci, short Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, + int Bp, int Bi, unsigned short Bx, int Cp, + int Ci, unsigned short Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, + int Bi, int Bx, int Cp, int Ci, int Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, + int Bp, int Bi, unsigned int Bx, int Cp, + int Ci, unsigned int Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, + int Bp, int Bi, long long Bx, int Cp, int Ci, + long long Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, + int Bp, int Bi, unsigned long long Bx, + int Cp, int Ci, unsigned long long Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, + int Bi, float Bx, int Cp, int Ci, float Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, + int Bi, double Bx, int Cp, int Ci, double Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, + int Bp, int Bi, long double Bx, int Cp, int Ci, + long double Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, + int Bp, int Bi, npy_cfloat_wrapper Bx, + int Cp, int Ci, npy_cfloat_wrapper Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, + int Bp, int Bi, npy_cdouble_wrapper Bx, + int Cp, int Ci, npy_cdouble_wrapper Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, + int Bp, int Bi, npy_clongdouble_wrapper Bx, + int Cp, int Ci, npy_clongdouble_wrapper Cx) + """ + return _csc.csc_minus_csc(*args) Modified: trunk/scipy/sparse/sparsetools/csr.py =================================================================== --- trunk/scipy/sparse/sparsetools/csr.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/sparsetools/csr.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -50,569 +50,568 @@ def expandptr(*args): - """expandptr(int n_row, int Ap, int Bi)""" - return _csr.expandptr(*args) + """expandptr(int n_row, int Ap, int Bi)""" + return _csr.expandptr(*args) def csr_count_blocks(*args): - """csr_count_blocks(int n_row, int n_col, int R, int C, int Ap, int Aj) -> int""" - return _csr.csr_count_blocks(*args) + """csr_count_blocks(int n_row, int n_col, int R, int C, int Ap, int Aj) -> int""" + return _csr.csr_count_blocks(*args) def csr_matmat_pass1(*args): - """ - csr_matmat_pass1(int n_row, int n_col, int Ap, int Aj, int Bp, int Bj, - int Cp) """ - return _csr.csr_matmat_pass1(*args) + csr_matmat_pass1(int n_row, int n_col, int Ap, int Aj, int Bp, int Bj, + int Cp) + """ + return _csr.csr_matmat_pass1(*args) def csr_has_sorted_indices(*args): - """csr_has_sorted_indices(int n_row, int Ap, int Aj) -> bool""" - return _csr.csr_has_sorted_indices(*args) + """csr_has_sorted_indices(int n_row, int Ap, int Aj) -> bool""" + return _csr.csr_has_sorted_indices(*args) def csr_diagonal(*args): - """ - csr_diagonal(int n_row, int n_col, int Ap, int Aj, signed char Ax, - signed char Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - unsigned char Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, short Ax, short Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - unsigned short Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, int Ax, int Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - unsigned int Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, long long Ax, - long long Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - unsigned long long Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, float Ax, float Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, double Ax, double Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, long double Ax, - long double Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Yx) """ - return _csr.csr_diagonal(*args) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, signed char Ax, + signed char Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + unsigned char Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, short Ax, short Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + unsigned short Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, int Ax, int Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + unsigned int Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, long long Ax, + long long Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + unsigned long long Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, float Ax, float Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, double Ax, double Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, long double Ax, + long double Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Yx) + """ + return _csr.csr_diagonal(*args) def csr_scale_rows(*args): - """ - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, signed char Ax, - signed char Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - unsigned char Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, short Ax, short Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - unsigned short Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, int Ax, int Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - unsigned int Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, long long Ax, - long long Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - unsigned long long Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, float Ax, float Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, double Ax, double Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, long double Ax, - long double Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Xx) """ - return _csr.csr_scale_rows(*args) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, signed char Ax, + signed char Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + unsigned char Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, short Ax, short Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + unsigned short Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, int Ax, int Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + unsigned int Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, long long Ax, + long long Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + unsigned long long Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, float Ax, float Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, double Ax, double Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, long double Ax, + long double Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Xx) + """ + return _csr.csr_scale_rows(*args) def csr_scale_columns(*args): - """ - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, signed char Ax, - signed char Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - unsigned char Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, short Ax, short Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - unsigned short Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, int Ax, int Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - unsigned int Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, long long Ax, - long long Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - unsigned long long Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, float Ax, float Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, double Ax, double Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, long double Ax, - long double Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Xx) """ - return _csr.csr_scale_columns(*args) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, signed char Ax, + signed char Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + unsigned char Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, short Ax, short Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + unsigned short Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, int Ax, int Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + unsigned int Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, long long Ax, + long long Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + unsigned long long Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, float Ax, float Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, double Ax, double Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, long double Ax, + long double Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Xx) + """ + return _csr.csr_scale_columns(*args) def csr_tocsc(*args): - """ - csr_tocsc(int n_row, int n_col, int Ap, int Aj, signed char Ax, - int Bp, int Bi, signed char Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - int Bp, int Bi, unsigned char Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, - int Bi, short Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - int Bp, int Bi, unsigned short Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, - int Bi, int Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - int Bp, int Bi, unsigned int Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, long long Ax, - int Bp, int Bi, long long Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - int Bp, int Bi, unsigned long long Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, - int Bi, float Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, - int Bi, double Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, long double Ax, - int Bp, int Bi, long double Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bi, npy_cfloat_wrapper Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bi, npy_cdouble_wrapper Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bi, npy_clongdouble_wrapper Bx) """ - return _csr.csr_tocsc(*args) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, signed char Ax, + int Bp, int Bi, signed char Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + int Bp, int Bi, unsigned char Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, + int Bi, short Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + int Bp, int Bi, unsigned short Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, + int Bi, int Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + int Bp, int Bi, unsigned int Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, long long Ax, + int Bp, int Bi, long long Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + int Bp, int Bi, unsigned long long Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, + int Bi, float Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, + int Bi, double Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, long double Ax, + int Bp, int Bi, long double Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bi, npy_cfloat_wrapper Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bi, npy_cdouble_wrapper Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bi, npy_clongdouble_wrapper Bx) + """ + return _csr.csr_tocsc(*args) def csr_tobsr(*args): - """ - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - signed char Ax, int Bp, int Bj, signed char Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned char Ax, int Bp, int Bj, unsigned char Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - short Ax, int Bp, int Bj, short Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned short Ax, int Bp, int Bj, unsigned short Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - int Ax, int Bp, int Bj, int Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned int Ax, int Bp, int Bj, unsigned int Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long long Ax, int Bp, int Bj, long long Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned long long Ax, int Bp, int Bj, unsigned long long Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - float Ax, int Bp, int Bj, float Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - double Ax, int Bp, int Bj, double Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long double Ax, int Bp, int Bj, long double Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, int Bp, int Bj, - npy_clongdouble_wrapper Bx) """ - return _csr.csr_tobsr(*args) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + signed char Ax, int Bp, int Bj, signed char Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned char Ax, int Bp, int Bj, unsigned char Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + short Ax, int Bp, int Bj, short Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned short Ax, int Bp, int Bj, unsigned short Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + int Ax, int Bp, int Bj, int Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned int Ax, int Bp, int Bj, unsigned int Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long long Ax, int Bp, int Bj, long long Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned long long Ax, int Bp, int Bj, unsigned long long Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + float Ax, int Bp, int Bj, float Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + double Ax, int Bp, int Bj, double Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long double Ax, int Bp, int Bj, long double Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, int Bp, int Bj, + npy_clongdouble_wrapper Bx) + """ + return _csr.csr_tobsr(*args) def csr_matmat_pass2(*args): - """ - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, signed char Ax, - int Bp, int Bj, signed char Bx, int Cp, int Cj, - signed char Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - int Bp, int Bj, unsigned char Bx, int Cp, - int Cj, unsigned char Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, - int Bj, short Bx, int Cp, int Cj, short Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - int Bp, int Bj, unsigned short Bx, int Cp, - int Cj, unsigned short Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, - int Bj, int Bx, int Cp, int Cj, int Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - int Bp, int Bj, unsigned int Bx, int Cp, - int Cj, unsigned int Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, long long Ax, - int Bp, int Bj, long long Bx, int Cp, int Cj, - long long Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, - int Bj, float Bx, int Cp, int Cj, float Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, - int Bj, double Bx, int Cp, int Cj, double Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, long double Ax, - int Bp, int Bj, long double Bx, int Cp, int Cj, - long double Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bj, npy_clongdouble_wrapper Bx, - int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - return _csr.csr_matmat_pass2(*args) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, signed char Ax, + int Bp, int Bj, signed char Bx, int Cp, int Cj, + signed char Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + int Bp, int Bj, unsigned char Bx, int Cp, + int Cj, unsigned char Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, + int Bj, short Bx, int Cp, int Cj, short Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + int Bp, int Bj, unsigned short Bx, int Cp, + int Cj, unsigned short Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, + int Bj, int Bx, int Cp, int Cj, int Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + int Bp, int Bj, unsigned int Bx, int Cp, + int Cj, unsigned int Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, long long Ax, + int Bp, int Bj, long long Bx, int Cp, int Cj, + long long Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, + int Bj, float Bx, int Cp, int Cj, float Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, + int Bj, double Bx, int Cp, int Cj, double Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, long double Ax, + int Bp, int Bj, long double Bx, int Cp, int Cj, + long double Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bj, npy_clongdouble_wrapper Bx, + int Cp, int Cj, npy_clongdouble_wrapper Cx) + """ + return _csr.csr_matmat_pass2(*args) def csr_matvec(*args): - """ - csr_matvec(int n_row, int n_col, int Ap, int Aj, signed char Ax, - signed char Xx, signed char Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - unsigned char Xx, unsigned char Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, short Ax, short Xx, - short Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - unsigned short Xx, unsigned short Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, int Ax, int Xx, - int Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - unsigned int Xx, unsigned int Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, long long Ax, - long long Xx, long long Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - unsigned long long Xx, unsigned long long Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, float Ax, float Xx, - float Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, double Ax, double Xx, - double Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, long double Ax, - long double Xx, long double Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Xx, npy_cfloat_wrapper Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Xx, npy_cdouble_wrapper Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Xx, npy_clongdouble_wrapper Yx) """ - return _csr.csr_matvec(*args) + csr_matvec(int n_row, int n_col, int Ap, int Aj, signed char Ax, + signed char Xx, signed char Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + unsigned char Xx, unsigned char Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, short Ax, short Xx, + short Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + unsigned short Xx, unsigned short Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, int Ax, int Xx, + int Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + unsigned int Xx, unsigned int Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, long long Ax, + long long Xx, long long Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + unsigned long long Xx, unsigned long long Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, float Ax, float Xx, + float Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, double Ax, double Xx, + double Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, long double Ax, + long double Xx, long double Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Xx, npy_cfloat_wrapper Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Xx, npy_cdouble_wrapper Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Xx, npy_clongdouble_wrapper Yx) + """ + return _csr.csr_matvec(*args) def csr_matvecs(*args): - """ - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, signed char Ax, - signed char Xx, signed char Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned char Ax, - unsigned char Xx, unsigned char Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, short Ax, - short Xx, short Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned short Ax, - unsigned short Xx, unsigned short Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, int Ax, - int Xx, int Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned int Ax, - unsigned int Xx, unsigned int Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, long long Ax, - long long Xx, long long Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned long long Ax, - unsigned long long Xx, - unsigned long long Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, float Ax, - float Xx, float Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, double Ax, - double Xx, double Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, long double Ax, - long double Xx, long double Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Xx, - npy_cfloat_wrapper Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Xx, - npy_cdouble_wrapper Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Xx, - npy_clongdouble_wrapper Yx) """ - return _csr.csr_matvecs(*args) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, signed char Ax, + signed char Xx, signed char Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned char Ax, + unsigned char Xx, unsigned char Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, short Ax, + short Xx, short Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned short Ax, + unsigned short Xx, unsigned short Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, int Ax, + int Xx, int Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned int Ax, + unsigned int Xx, unsigned int Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, long long Ax, + long long Xx, long long Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned long long Ax, + unsigned long long Xx, + unsigned long long Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, float Ax, + float Xx, float Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, double Ax, + double Xx, double Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, long double Ax, + long double Xx, long double Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Xx, + npy_cfloat_wrapper Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Xx, + npy_cdouble_wrapper Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Xx, + npy_clongdouble_wrapper Yx) + """ + return _csr.csr_matvecs(*args) def csr_elmul_csr(*args): - """ - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, - int Bp, int Bj, signed char Bx, int Cp, int Cj, - signed char Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - int Bp, int Bj, unsigned char Bx, int Cp, - int Cj, unsigned char Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, - int Bj, short Bx, int Cp, int Cj, short Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - int Bp, int Bj, unsigned short Bx, int Cp, - int Cj, unsigned short Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, - int Bj, int Bx, int Cp, int Cj, int Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - int Bp, int Bj, unsigned int Bx, int Cp, - int Cj, unsigned int Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, - int Bp, int Bj, long long Bx, int Cp, int Cj, - long long Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, - int Bj, float Bx, int Cp, int Cj, float Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, - int Bj, double Bx, int Cp, int Cj, double Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, - int Bp, int Bj, long double Bx, int Cp, int Cj, - long double Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bj, npy_clongdouble_wrapper Bx, - int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - return _csr.csr_elmul_csr(*args) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, + int Bp, int Bj, signed char Bx, int Cp, int Cj, + signed char Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + int Bp, int Bj, unsigned char Bx, int Cp, + int Cj, unsigned char Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, + int Bj, short Bx, int Cp, int Cj, short Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + int Bp, int Bj, unsigned short Bx, int Cp, + int Cj, unsigned short Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, + int Bj, int Bx, int Cp, int Cj, int Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + int Bp, int Bj, unsigned int Bx, int Cp, + int Cj, unsigned int Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, + int Bp, int Bj, long long Bx, int Cp, int Cj, + long long Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, + int Bj, float Bx, int Cp, int Cj, float Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, + int Bj, double Bx, int Cp, int Cj, double Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, + int Bp, int Bj, long double Bx, int Cp, int Cj, + long double Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bj, npy_clongdouble_wrapper Bx, + int Cp, int Cj, npy_clongdouble_wrapper Cx) + """ + return _csr.csr_elmul_csr(*args) def csr_eldiv_csr(*args): - """ - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, - int Bp, int Bj, signed char Bx, int Cp, int Cj, - signed char Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - int Bp, int Bj, unsigned char Bx, int Cp, - int Cj, unsigned char Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, - int Bj, short Bx, int Cp, int Cj, short Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - int Bp, int Bj, unsigned short Bx, int Cp, - int Cj, unsigned short Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, - int Bj, int Bx, int Cp, int Cj, int Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - int Bp, int Bj, unsigned int Bx, int Cp, - int Cj, unsigned int Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, - int Bp, int Bj, long long Bx, int Cp, int Cj, - long long Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, - int Bj, float Bx, int Cp, int Cj, float Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, - int Bj, double Bx, int Cp, int Cj, double Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, - int Bp, int Bj, long double Bx, int Cp, int Cj, - long double Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bj, npy_clongdouble_wrapper Bx, - int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - return _csr.csr_eldiv_csr(*args) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, + int Bp, int Bj, signed char Bx, int Cp, int Cj, + signed char Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + int Bp, int Bj, unsigned char Bx, int Cp, + int Cj, unsigned char Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, + int Bj, short Bx, int Cp, int Cj, short Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + int Bp, int Bj, unsigned short Bx, int Cp, + int Cj, unsigned short Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, + int Bj, int Bx, int Cp, int Cj, int Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + int Bp, int Bj, unsigned int Bx, int Cp, + int Cj, unsigned int Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, + int Bp, int Bj, long long Bx, int Cp, int Cj, + long long Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, + int Bj, float Bx, int Cp, int Cj, float Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, + int Bj, double Bx, int Cp, int Cj, double Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, + int Bp, int Bj, long double Bx, int Cp, int Cj, + long double Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bj, npy_clongdouble_wrapper Bx, + int Cp, int Cj, npy_clongdouble_wrapper Cx) + """ + return _csr.csr_eldiv_csr(*args) def csr_plus_csr(*args): - """ - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, - int Bp, int Bj, signed char Bx, int Cp, int Cj, - signed char Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - int Bp, int Bj, unsigned char Bx, int Cp, - int Cj, unsigned char Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, - int Bj, short Bx, int Cp, int Cj, short Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - int Bp, int Bj, unsigned short Bx, int Cp, - int Cj, unsigned short Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, - int Bj, int Bx, int Cp, int Cj, int Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - int Bp, int Bj, unsigned int Bx, int Cp, - int Cj, unsigned int Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, - int Bp, int Bj, long long Bx, int Cp, int Cj, - long long Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, - int Bj, float Bx, int Cp, int Cj, float Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, - int Bj, double Bx, int Cp, int Cj, double Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, - int Bp, int Bj, long double Bx, int Cp, int Cj, - long double Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bj, npy_clongdouble_wrapper Bx, - int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - return _csr.csr_plus_csr(*args) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, + int Bp, int Bj, signed char Bx, int Cp, int Cj, + signed char Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + int Bp, int Bj, unsigned char Bx, int Cp, + int Cj, unsigned char Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, + int Bj, short Bx, int Cp, int Cj, short Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + int Bp, int Bj, unsigned short Bx, int Cp, + int Cj, unsigned short Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, + int Bj, int Bx, int Cp, int Cj, int Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + int Bp, int Bj, unsigned int Bx, int Cp, + int Cj, unsigned int Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, + int Bp, int Bj, long long Bx, int Cp, int Cj, + long long Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, + int Bj, float Bx, int Cp, int Cj, float Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, + int Bj, double Bx, int Cp, int Cj, double Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, + int Bp, int Bj, long double Bx, int Cp, int Cj, + long double Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bj, npy_clongdouble_wrapper Bx, + int Cp, int Cj, npy_clongdouble_wrapper Cx) + """ + return _csr.csr_plus_csr(*args) def csr_minus_csr(*args): - """ - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, - int Bp, int Bj, signed char Bx, int Cp, int Cj, - signed char Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - int Bp, int Bj, unsigned char Bx, int Cp, - int Cj, unsigned char Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, - int Bj, short Bx, int Cp, int Cj, short Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - int Bp, int Bj, unsigned short Bx, int Cp, - int Cj, unsigned short Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, - int Bj, int Bx, int Cp, int Cj, int Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - int Bp, int Bj, unsigned int Bx, int Cp, - int Cj, unsigned int Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, - int Bp, int Bj, long long Bx, int Cp, int Cj, - long long Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, - int Bj, float Bx, int Cp, int Cj, float Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, - int Bj, double Bx, int Cp, int Cj, double Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, - int Bp, int Bj, long double Bx, int Cp, int Cj, - long double Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bj, npy_clongdouble_wrapper Bx, - int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - return _csr.csr_minus_csr(*args) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, + int Bp, int Bj, signed char Bx, int Cp, int Cj, + signed char Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + int Bp, int Bj, unsigned char Bx, int Cp, + int Cj, unsigned char Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, + int Bj, short Bx, int Cp, int Cj, short Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + int Bp, int Bj, unsigned short Bx, int Cp, + int Cj, unsigned short Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, + int Bj, int Bx, int Cp, int Cj, int Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + int Bp, int Bj, unsigned int Bx, int Cp, + int Cj, unsigned int Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, + int Bp, int Bj, long long Bx, int Cp, int Cj, + long long Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, + int Bj, float Bx, int Cp, int Cj, float Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, + int Bj, double Bx, int Cp, int Cj, double Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, + int Bp, int Bj, long double Bx, int Cp, int Cj, + long double Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bj, npy_clongdouble_wrapper Bx, + int Cp, int Cj, npy_clongdouble_wrapper Cx) + """ + return _csr.csr_minus_csr(*args) def csr_sort_indices(*args): - """ - csr_sort_indices(int n_row, int Ap, int Aj, signed char Ax) - csr_sort_indices(int n_row, int Ap, int Aj, unsigned char Ax) - csr_sort_indices(int n_row, int Ap, int Aj, short Ax) - csr_sort_indices(int n_row, int Ap, int Aj, unsigned short Ax) - csr_sort_indices(int n_row, int Ap, int Aj, int Ax) - csr_sort_indices(int n_row, int Ap, int Aj, unsigned int Ax) - csr_sort_indices(int n_row, int Ap, int Aj, long long Ax) - csr_sort_indices(int n_row, int Ap, int Aj, unsigned long long Ax) - csr_sort_indices(int n_row, int Ap, int Aj, float Ax) - csr_sort_indices(int n_row, int Ap, int Aj, double Ax) - csr_sort_indices(int n_row, int Ap, int Aj, long double Ax) - csr_sort_indices(int n_row, int Ap, int Aj, npy_cfloat_wrapper Ax) - csr_sort_indices(int n_row, int Ap, int Aj, npy_cdouble_wrapper Ax) - csr_sort_indices(int n_row, int Ap, int Aj, npy_clongdouble_wrapper Ax) """ - return _csr.csr_sort_indices(*args) + csr_sort_indices(int n_row, int Ap, int Aj, signed char Ax) + csr_sort_indices(int n_row, int Ap, int Aj, unsigned char Ax) + csr_sort_indices(int n_row, int Ap, int Aj, short Ax) + csr_sort_indices(int n_row, int Ap, int Aj, unsigned short Ax) + csr_sort_indices(int n_row, int Ap, int Aj, int Ax) + csr_sort_indices(int n_row, int Ap, int Aj, unsigned int Ax) + csr_sort_indices(int n_row, int Ap, int Aj, long long Ax) + csr_sort_indices(int n_row, int Ap, int Aj, unsigned long long Ax) + csr_sort_indices(int n_row, int Ap, int Aj, float Ax) + csr_sort_indices(int n_row, int Ap, int Aj, double Ax) + csr_sort_indices(int n_row, int Ap, int Aj, long double Ax) + csr_sort_indices(int n_row, int Ap, int Aj, npy_cfloat_wrapper Ax) + csr_sort_indices(int n_row, int Ap, int Aj, npy_cdouble_wrapper Ax) + csr_sort_indices(int n_row, int Ap, int Aj, npy_clongdouble_wrapper Ax) + """ + return _csr.csr_sort_indices(*args) def csr_eliminate_zeros(*args): - """ - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, signed char Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned char Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, short Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned short Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, int Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned int Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, long long Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, float Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, double Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, long double Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax) """ - return _csr.csr_eliminate_zeros(*args) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, signed char Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned char Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, short Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned short Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, int Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned int Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, long long Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, float Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, double Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, long double Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax) + """ + return _csr.csr_eliminate_zeros(*args) def csr_sum_duplicates(*args): - """ - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, signed char Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned char Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, short Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned short Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, int Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned int Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, long long Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, float Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, double Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, long double Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax) """ - return _csr.csr_sum_duplicates(*args) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, signed char Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned char Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, short Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned short Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, int Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned int Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, long long Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, float Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, double Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, long double Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax) + """ + return _csr.csr_sum_duplicates(*args) def get_csr_submatrix(*args): - """ - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, signed char Ax, - int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(signed char)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(unsigned char)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, short Ax, int ir0, - int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(short)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(unsigned short)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, int Ax, int ir0, - int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(int)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(unsigned int)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, long long Ax, - int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(long long)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - int ir0, int ir1, int ic0, int ic1, - std::vector<(int)> Bp, std::vector<(int)> Bj, - std::vector<(unsigned long long)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, float Ax, int ir0, - int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(float)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, double Ax, int ir0, - int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(double)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, long double Ax, - int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(long double)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - int ir0, int ir1, int ic0, int ic1, - std::vector<(int)> Bp, std::vector<(int)> Bj, - std::vector<(npy_cfloat_wrapper)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - int ir0, int ir1, int ic0, int ic1, - std::vector<(int)> Bp, std::vector<(int)> Bj, - std::vector<(npy_cdouble_wrapper)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - int ir0, int ir1, int ic0, int ic1, - std::vector<(int)> Bp, std::vector<(int)> Bj, - std::vector<(npy_clongdouble_wrapper)> Bx) """ - return _csr.get_csr_submatrix(*args) - + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, signed char Ax, + int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(signed char)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(unsigned char)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, short Ax, int ir0, + int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(short)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(unsigned short)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, int Ax, int ir0, + int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(int)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(unsigned int)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, long long Ax, + int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(long long)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + int ir0, int ir1, int ic0, int ic1, + std::vector<(int)> Bp, std::vector<(int)> Bj, + std::vector<(unsigned long long)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, float Ax, int ir0, + int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(float)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, double Ax, int ir0, + int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(double)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, long double Ax, + int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(long double)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + int ir0, int ir1, int ic0, int ic1, + std::vector<(int)> Bp, std::vector<(int)> Bj, + std::vector<(npy_cfloat_wrapper)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + int ir0, int ir1, int ic0, int ic1, + std::vector<(int)> Bp, std::vector<(int)> Bj, + std::vector<(npy_cdouble_wrapper)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + int ir0, int ir1, int ic0, int ic1, + std::vector<(int)> Bp, std::vector<(int)> Bj, + std::vector<(npy_clongdouble_wrapper)> Bx) + """ + return _csr.get_csr_submatrix(*args) Modified: trunk/scipy/sparse/sparsetools/dia.py =================================================================== --- trunk/scipy/sparse/sparsetools/dia.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/sparsetools/dia.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -51,40 +51,39 @@ def dia_matvec(*args): - """ - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - signed char diags, signed char Xx, signed char Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - unsigned char diags, unsigned char Xx, unsigned char Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - short diags, short Xx, short Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - unsigned short diags, unsigned short Xx, - unsigned short Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - int diags, int Xx, int Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - unsigned int diags, unsigned int Xx, unsigned int Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - long long diags, long long Xx, long long Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - unsigned long long diags, unsigned long long Xx, - unsigned long long Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - float diags, float Xx, float Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - double diags, double Xx, double Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - long double diags, long double Xx, long double Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - npy_cfloat_wrapper diags, npy_cfloat_wrapper Xx, - npy_cfloat_wrapper Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - npy_cdouble_wrapper diags, npy_cdouble_wrapper Xx, - npy_cdouble_wrapper Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - npy_clongdouble_wrapper diags, npy_clongdouble_wrapper Xx, - npy_clongdouble_wrapper Yx) """ - return _dia.dia_matvec(*args) - + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + signed char diags, signed char Xx, signed char Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + unsigned char diags, unsigned char Xx, unsigned char Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + short diags, short Xx, short Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + unsigned short diags, unsigned short Xx, + unsigned short Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + int diags, int Xx, int Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + unsigned int diags, unsigned int Xx, unsigned int Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + long long diags, long long Xx, long long Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + unsigned long long diags, unsigned long long Xx, + unsigned long long Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + float diags, float Xx, float Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + double diags, double Xx, double Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + long double diags, long double Xx, long double Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + npy_cfloat_wrapper diags, npy_cfloat_wrapper Xx, + npy_cfloat_wrapper Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + npy_cdouble_wrapper diags, npy_cdouble_wrapper Xx, + npy_cdouble_wrapper Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + npy_clongdouble_wrapper diags, npy_clongdouble_wrapper Xx, + npy_clongdouble_wrapper Yx) + """ + return _dia.dia_matvec(*args) Modified: trunk/scipy/sparse/tests/test_base.py =================================================================== --- trunk/scipy/sparse/tests/test_base.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/sparse/tests/test_base.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -117,7 +117,7 @@ def test_getrow(self): assert_array_equal(self.datsp.getrow(1).todense(), self.dat[1,:]) - + def test_getcol(self): assert_array_equal(self.datsp.getcol(1).todense(), self.dat[:,1]) @@ -250,8 +250,8 @@ # real/complex assert_almost_equal( Asp.multiply(Dsp).todense(), A*D) #sparse/sparse assert_almost_equal( Asp.multiply(D), A*D) #sparse/dense - + def test_elementwise_divide(self): expected = [[1,0,0,1],[1,0,1,0],[0,1,0,0]] assert_array_equal((self.datsp / self.datsp).todense(),expected) @@ -713,7 +713,7 @@ assert_equal(A[3:4,9].todense(), B[3:4,9]) assert_equal(A[1:4,-5].todense(),B[1:4,-5]) assert_equal(A[2:-1,3].todense(),B[2:-1,3]) - + # [1:2,1:2] assert_equal(A[1:2,1:2].todense(),B[1:2,1:2]) assert_equal(A[4:,3:].todense(), B[4:,3:]) @@ -763,11 +763,11 @@ # Check bug reported by Robert Cimrman: - # http://thread.gmane.org/gmane.comp.python.scientific.devel/7986 + # http://thread.gmane.org/gmane.comp.python.scientific.devel/7986 s = slice(numpy.int8(2),numpy.int8(4),None) assert_equal(A[s,:].todense(), B[2:4,:]) assert_equal(A[:,s].todense(), B[:,2:4]) - + class _TestArithmetic: """ Test real/complex arithmetic @@ -1415,7 +1415,7 @@ A = bsr_matrix( arange(2*3*4*5).reshape(2*4,3*5), blocksize=(4,5) ) x = arange(A.shape[1]*6).reshape(-1,6) assert_equal(A*x, A.todense()*x) - + if __name__ == "__main__": run_module_suite() Modified: trunk/scipy/special/tests/test_basic.py =================================================================== --- trunk/scipy/special/tests/test_basic.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/special/tests/test_basic.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -1179,7 +1179,7 @@ # test contributed by Moritz Deger (2008-05-29) # http://projects.scipy.org/scipy/scipy/ticket/659 - + # reference data obtained from mathematica [ a, b, x, m(a,b,x)]: # produced with test_hyp1f1.nb ref_data = array([[ -8.38132975e+00, -1.28436461e+01, -2.91081397e+01, 1.04178330e+04], Modified: trunk/scipy/stats/mstats.py =================================================================== --- trunk/scipy/stats/mstats.py 2008-08-08 06:06:21 UTC (rev 4617) +++ trunk/scipy/stats/mstats.py 2008-08-08 06:17:26 UTC (rev 4618) @@ -443,7 +443,7 @@ use_missing: {False, True} optional Whether missing data should be allocated a rank of 0 (False) or the average rank (True) - + Returns ------- tau : float @@ -645,7 +645,7 @@ Independent variable. If None, use arange(len(y)) instead. alpha : float Confidence degree. - + Returns ------- medslope : float From scipy-svn at scipy.org Fri Aug 8 03:11:33 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 02:11:33 -0500 (CDT) Subject: [Scipy-svn] r4619 - in trunk/scipy: sparse/linalg/dsolve sparse/linalg/dsolve/umfpack sparse/linalg/dsolve/umfpack/tests sparse/linalg/eigen/arpack/tests stats Message-ID: <20080808071133.53C8839C018@scipy.org> Author: jarrod.millman Date: 2008-08-08 02:11:28 -0500 (Fri, 08 Aug 2008) New Revision: 4619 Modified: trunk/scipy/sparse/linalg/dsolve/linsolve.py trunk/scipy/sparse/linalg/dsolve/umfpack/info.py trunk/scipy/sparse/linalg/dsolve/umfpack/tests/try_umfpack.py trunk/scipy/sparse/linalg/eigen/arpack/tests/test_speigs.py trunk/scipy/stats/morestats.py Log: cleanup Modified: trunk/scipy/sparse/linalg/dsolve/linsolve.py =================================================================== --- trunk/scipy/sparse/linalg/dsolve/linsolve.py 2008-08-08 06:17:26 UTC (rev 4618) +++ trunk/scipy/sparse/linalg/dsolve/linsolve.py 2008-08-08 07:11:28 UTC (rev 4619) @@ -107,9 +107,9 @@ A linear solver, for a sparse, square matrix A, using LU decomposition where L is a lower triangular matrix and U is an upper triagular matrix. - Returns a factored_lu object. (scipy.linsolve._superlu.SciPyLUType) + Returns a factored_lu object. (scipy.sparse.linalg.dsolve._superlu.SciPyLUType) - See scipy.linsolve._superlu.dgstrf for more info. + See scipy.sparse.linalg.dsolve._superlu.dgstrf for more info. """ if not isspmatrix_csc(A): Modified: trunk/scipy/sparse/linalg/dsolve/umfpack/info.py =================================================================== --- trunk/scipy/sparse/linalg/dsolve/umfpack/info.py 2008-08-08 06:17:26 UTC (rev 4618) +++ trunk/scipy/sparse/linalg/dsolve/umfpack/info.py 2008-08-08 07:11:28 UTC (rev 4619) @@ -50,7 +50,7 @@ :Examples: ---------- -Assuming this module imported as um (import scipy.linsolve.umfpack as um) +Assuming this module imported as um (import scipy.sparse.linalg.dsolve.umfpack as um) Sparse matrix in CSR or CSC format: mtx Righthand-side: rhs Modified: trunk/scipy/sparse/linalg/dsolve/umfpack/tests/try_umfpack.py =================================================================== --- trunk/scipy/sparse/linalg/dsolve/umfpack/tests/try_umfpack.py 2008-08-08 06:17:26 UTC (rev 4618) +++ trunk/scipy/sparse/linalg/dsolve/umfpack/tests/try_umfpack.py 2008-08-08 07:11:28 UTC (rev 4619) @@ -4,16 +4,16 @@ """Benchamrks for umfpack module""" from optparse import OptionParser -import scipy.linsolve.umfpack as um -import numpy as nm -#import scipy.io as io -import scipy.sparse as sp -import scipy.linalg as nla -#import pylab import time import urllib import gzip +import numpy as np + +import scipy.sparse as sp +import scipy.sparse.linalg.dsolve.umfpack as um +import scipy.linalg as nla + defaultURL = 'http://www.cise.ufl.edu/research/sparse/HBformat/' usage = """%%prog [options] [, ...] @@ -35,8 +35,8 @@ nRow, nCol = map( int, fd.readline().split() ) nItem = int( fd.readline() ) - ij = nm.zeros( (nItem,2), nm.int32 ) - val = nm.zeros( (nItem,), nm.float64 ) + ij = np.zeros( (nItem,2), np.int32 ) + val = np.zeros( (nItem,), np.float64 ) for ii, row in enumerate( fd.readlines() ): aux = row.split() ij[ii] = int( aux[0] ), int( aux[1] ) @@ -54,7 +54,7 @@ ij, val = io.read_array( fd, columns = [(0,1), (2,)], - atype = (nm.int32, nm.float64), + atype = (np.int32, np.float64), rowsize = nItem ) mtx = sp.csc_matrix( (val, ij), dims = (nRow, nCol), nzmax = nItem ) @@ -137,14 +137,14 @@ sizes.append( mtx.shape ) nnzs.append( mtx.nnz ) - tts = nm.zeros( (2,), dtype = nm.double ) + tts = np.zeros( (2,), dtype = np.double ) times.append( tts ) - err = nm.zeros( (2,2), dtype = nm.double ) + err = np.zeros( (2,2), dtype = np.double ) errors.append( err ) print 'size : %s (%d nnz)' % (mtx.shape, mtx.nnz) - sol0 = nm.ones( (mtx.shape[0],), dtype = nm.double ) + sol0 = np.ones( (mtx.shape[0],), dtype = np.double ) rhs = mtx * sol0 umfpack = um.UmfpackContext() @@ -181,7 +181,7 @@ import pylab except ImportError: raise ImportError, "could not import pylab" - times = nm.array( times ) + times = np.array( times ) print times pylab.plot( times[:,0], 'b-o' ) if options.compare: @@ -196,17 +196,17 @@ xrng = range( len( nnzs ) ) for ii in xrng: yy = y2 + 0.4 * (ax[3] - ax[2])\ - * nm.sin( ii * 2 * nm.pi / (len( xrng ) - 1) ) + * np.sin( ii * 2 * np.pi / (len( xrng ) - 1) ) if options.compare: pylab.text( ii+0.02, yy, '%s\n%.2e err_umf\n%.2e err_sp' - % (sizes[ii], nm.sum( errors[ii][0,:] ), - nm.sum( errors[ii][1,:] )) ) + % (sizes[ii], np.sum( errors[ii][0,:] ), + np.sum( errors[ii][1,:] )) ) else: pylab.text( ii+0.02, yy, '%s\n%.2e err_umf' - % (sizes[ii], nm.sum( errors[ii][0,:] )) ) + % (sizes[ii], np.sum( errors[ii][0,:] )) ) pylab.plot( [ii, ii], [ax[2], ax[3]], 'k:' ) pylab.xticks( xrng, ['%d' % (nnzs[ii] ) for ii in xrng] ) Modified: trunk/scipy/sparse/linalg/eigen/arpack/tests/test_speigs.py =================================================================== --- trunk/scipy/sparse/linalg/eigen/arpack/tests/test_speigs.py 2008-08-08 06:17:26 UTC (rev 4618) +++ trunk/scipy/sparse/linalg/eigen/arpack/tests/test_speigs.py 2008-08-08 07:11:28 UTC (rev 4619) @@ -39,10 +39,10 @@ # class TestGeneigs(TestCase): # def test(self): # import pickle -# import scipy.linsolve +# from scipy.sparse.linalg import dsolve # A,B = pickle.load(file('mats.pickle')) # sigma = 27. -# sigma_solve = scipy.linsolve.splu(A - sigma*B).solve +# sigma_solve = dsolve.splu(A - sigma*B).solve # w = ARPACK_gen_eigs(B.matvec, sigma_solve, B.shape[0], sigma, 10)[0] # assert_array_almost_equal(w, # [27.346442255386375, 49.100299170945405, 56.508474856551544, 56.835800191692492, Modified: trunk/scipy/stats/morestats.py =================================================================== --- trunk/scipy/stats/morestats.py 2008-08-08 06:17:26 UTC (rev 4618) +++ trunk/scipy/stats/morestats.py 2008-08-08 07:11:28 UTC (rev 4619) @@ -16,7 +16,6 @@ import scipy.optimize as optimize import scipy.special as special import futil -import numpy as sb from numpy.testing.decorators import setastest import warnings From scipy-svn at scipy.org Fri Aug 8 12:02:25 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 11:02:25 -0500 (CDT) Subject: [Scipy-svn] r4620 - in branches/Interpolate1D: . tests Message-ID: <20080808160225.6A8E739C018@scipy.org> Author: fcady Date: 2008-08-08 11:02:21 -0500 (Fri, 08 Aug 2008) New Revision: 4620 Modified: branches/Interpolate1D/TODO.txt branches/Interpolate1D/interpolateNd.py branches/Interpolate1D/tests/test_interpolate2d.py branches/Interpolate1D/tests/test_ndimage.py Log: ndimage code more seemlessly incorporated into interpolateNd.py Modified: branches/Interpolate1D/TODO.txt =================================================================== --- branches/Interpolate1D/TODO.txt 2008-08-08 07:11:28 UTC (rev 4619) +++ branches/Interpolate1D/TODO.txt 2008-08-08 16:02:21 UTC (rev 4620) @@ -11,6 +11,11 @@ ************ API and/or MAJOR ISSUES *********** +**better ND interpolation + InterpolateNd works, but the quadratic and higher order splines are + sometimes really ugly. It seems they have a boundary condition that the + derivative must be zero. + **possibly allow interp2d to return a 2d array? Like in the case that x and y are 2d arrays in meshgrid format. Modified: branches/Interpolate1D/interpolateNd.py =================================================================== --- branches/Interpolate1D/interpolateNd.py 2008-08-08 07:11:28 UTC (rev 4619) +++ branches/Interpolate1D/interpolateNd.py 2008-08-08 16:02:21 UTC (rev 4620) @@ -2,7 +2,7 @@ from numpy import array, arange, NaN import numpy as np -import _nd_image +import _nd_image # extension module with interpolation code def interpNd(data, coordinates, starting_coords=None, spacings=None, kind='linear',out=NaN): """ A function for interpolation of 1D, real-valued data. @@ -70,6 +70,10 @@ class InterpolateNd: """ A callable class for interpolation of 1D, real-valued data. + + Under the hood, interpolation is always done with splines. Those + of order 2 or higher have the boundary condition of zero derivative. + This is a potential shortcoming of the package; natural splines would be better. Parameters ----------- @@ -120,6 +124,11 @@ >>> nd.InterpolateNd(boring_data)( np.array([[2.3], [1.0], [3.9]]) ) 1.0 """ + # Under the hood this works by interpolating entries in an array, rather than + # values at points in space. Known data are stored as an array; info on spacings + # and starting coords describes the mapping from the array to ND space. When the + # function is called, the coordinates are first converted into array values. + # The array interpolation is handled by the C extension _nd_image. def __init__(self, data, starting_coords =None, spacings = None, kind='linear', out=NaN): """ data = array or list of lists @@ -131,9 +140,6 @@ or just NaN """ - # FIXME : include spline filtering - # the ndimage module says that it requires pre-filtering for - # checking format of input data = array(data) @@ -192,21 +198,21 @@ else: raise ValueError, "argument kind = %s not recognized" % str(kind) - + # Spline pre-filtering # This step is done because it is required by the ndimage code that I'm scavenging. # I don't fully understand why it must do this, and that's a problem. But empirically # this step is needed in order to get good-looking data. if self.order >1: - self._data_array = spline_filter(data, self.order) + self._data_array = self._spline_filter(data, self.order) else: self._data_array = data # storing relevant data - self.ndim = data.ndim - self._shape = np.shape(data) + self.ndim = self._data_array.ndim + self.shape_as_column_vec = np.reshape(np.shape(self._data_array), + (self.ndim, 1)) self._spacings = spacings self._min_coords = starting_coords - self._max_coords = self._min_coords + self._shape*self._spacings self.out = out def __call__(self, coordinates): @@ -271,73 +277,36 @@ """ return an array of bools saying which points are in interpolation bounds """ - shape_as_column_vec = np.reshape(self._shape, (self.ndim, 1)) # entry is 1 if that coordinate of a point is in its bounds index_in_bounds = (0 <= indices) & \ - (indices <= shape_as_column_vec) + (indices <= self.shape_as_column_vec) # for each point, number of coordinates that are in bounds num_indices_in_bounds = np.sum(index_in_bounds, axis=0) # True if each coordinate for the point is in bounds return num_indices_in_bounds == self.ndim - - def _coord_in_bounds(self, coordinates): - """ return an array of bools saying which - points are in interpolation bounds - """ - # entry is 1 if that coordinate of a point is in its bounds - coord_in_bounds = (self._min_coords <= coordinates) & \ - (coordinates <= self._max_coords) - - # for each point, number of coordinates that are in bounds - num_coords_in_bounds = np.sum(coord_in_bounds, axis=0) - - # True if each coordinate for the point is in bounds - return num_coords_in_bounds == self.ndim - - - - - - - - - -import _ni_support -def spline_filter1d(input, order = 3, axis = -1, output = np.float64, - output_type = None): - # takes array and everything; we can make input safe if user never touches it - """ Calculates a one-dimensional spline filter along the given axis. + def _spline_filter(self, data, order = 3): + """ Multi-dimensional spline filter. - The lines of the array along the given axis are filtered by a - spline filter. The order of the spline must be >= 2 and <= 5. - """ - if order in [0, 1]: - output[...] = np.array(input) - else: - _nd_image.spline_filter1d(input, order, axis, output) - return output - -def spline_filter(input, order = 3, output = np.float64, - output_type = None): - """ Multi-dimensional spline filter. - - Note: The multi-dimensional filter is implemented as a sequence of - one-dimensional spline filters. The intermediate arrays are stored - in the same data type as the output. Therefore, for output types - with a limited precision, the results may be imprecise because - intermediate results may be stored with insufficient precision. - """ - - output = np.zeros( np.shape(input) , dtype=np.float64 ) # place to store the data - - if order not in [0, 1] and input.ndim > 0: - for axis in range(input.ndim): - spline_filter1d(input, order, axis, output = output) - input = output - else: - output[...] = input[...] - return output \ No newline at end of file + Note: The multi-dimensional filter is implemented as a sequence of + one-dimensional spline filters. The intermediate arrays are stored + in the same data type as the output. Therefore, for output types + with a limited precision, the results may be imprecise because + intermediate results may be stored with insufficient precision. + + order must be from 0 to 5 + """ + + # allocate memory in which to put the output + output = np.zeros( np.shape(data) , dtype=np.float64 ) + + if order in [0, 1]: + output = data + else: + for axis in range(data.ndim): + _nd_image.spline_filter1d(data, order, axis, output) + data = output + return output \ No newline at end of file Modified: branches/Interpolate1D/tests/test_interpolate2d.py =================================================================== --- branches/Interpolate1D/tests/test_interpolate2d.py 2008-08-08 07:11:28 UTC (rev 4619) +++ branches/Interpolate1D/tests/test_interpolate2d.py 2008-08-08 16:02:21 UTC (rev 4620) @@ -9,7 +9,7 @@ from numpy import arange, meshgrid, ravel from interpolate2d import interp2d, Interpolate2d, atleast_1d_and_contiguous -from fitpack_wrapper2d import Spline2d +from fitpack_wrapper import Spline2d # unit testing import unittest, time Modified: branches/Interpolate1D/tests/test_ndimage.py =================================================================== --- branches/Interpolate1D/tests/test_ndimage.py 2008-08-08 07:11:28 UTC (rev 4619) +++ branches/Interpolate1D/tests/test_ndimage.py 2008-08-08 16:02:21 UTC (rev 4620) @@ -13,8 +13,8 @@ class Test (unittest.TestCase): - def assertAllclose(self, x, y): - self.assert_(np.allclose(x, y)) + def assertAllclose(self, x, y, err=1.0e-8): + self.assert_(np.allclose(x, y, atol=err)) def test_interpNd(self): """ Make sure : the function interpNd works @@ -67,7 +67,8 @@ X, Y = np.meshgrid(arange(10.), arange(10.)) interesting_data = X+Y interp = nd.InterpolateNd(interesting_data, kind = 2) - self.assertAllclose( interp(np.array([[2.3], [1.0]])) , 3.3 ) + print "quad answer: ", interp(np.array([[2.3], [1.0]])) + self.assertAllclose( interp(np.array([[2.3], [1.0]])) , 3.3 , err=.1 ) def test_order0(self): """ Make sure : block interpolation works @@ -83,7 +84,8 @@ X, Y = np.meshgrid(arange(10.), arange(10.)) interesting_data = X+Y interp = nd.InterpolateNd(interesting_data, kind = 3) - self.assertAllclose( interp(np.array([[4.3], [4.1]])) , 8.4 ) + print "cubi answer: ", interp(np.array([[4.3], [4.1]])) + self.assertAllclose( interp(np.array([[4.3], [4.1]])) , 8.4 , err=.1) def test_out(self): """ Make sure : out-of-bounds returns NaN From scipy-svn at scipy.org Fri Aug 8 13:37:29 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 12:37:29 -0500 (CDT) Subject: [Scipy-svn] r4621 - branches/Interpolate1D/tests Message-ID: <20080808173729.33B3239C02D@scipy.org> Author: fcady Date: 2008-08-08 12:37:26 -0500 (Fri, 08 Aug 2008) New Revision: 4621 Added: branches/Interpolate1D/tests/test_interpolateNd.py Removed: branches/Interpolate1D/tests/test_ndimage.py Modified: branches/Interpolate1D/tests/regression_test.py Log: updated regression test to include higher diensional tests Modified: branches/Interpolate1D/tests/regression_test.py =================================================================== --- branches/Interpolate1D/tests/regression_test.py 2008-08-08 16:02:21 UTC (rev 4620) +++ branches/Interpolate1D/tests/regression_test.py 2008-08-08 17:37:26 UTC (rev 4621) @@ -11,27 +11,59 @@ # hack to test on Field's computer import sys -sys.path.append('c:/home/python/Interpolate1d') +sys.path.append('c:/home/python/Interpolate1d/tests') import shelve, time -from test_interpolate1d import Test +from test_interpolate1d import Test as Test1 +from test_interpolate2d import Test as Test2 +from test_interpolateNd import Test as TestN # name of log file to which all data is stored. filename = 'regression_test.dbm' log_total = shelve.open(filename) current_time = str(time.localtime()[0:5]) # specified up to the minute +current_dict = {} # holds results for each dimensionality # run all tests in interpolate1d's test class -test_list = [name for name in dir(Test) if name.find('test_') == 0] -log_now = {} +if True: + test_list = [name for name in dir(Test1) if name.find('test_') == 0] + Test1_dict = {} -# record time taken for each test -for test_name in test_list: - t1 = time.clock() - eval('Test.%s' % test_name) - t2 = time.clock() - log_now[test_name] = t2-t1 + # record time taken for each test + for test_name in test_list: + t1 = time.clock() + eval('Test1.%s' % test_name) + t2 = time.clock() + Test1_dict[test_name] = t2-t1 -log_total[current_time] = log_now + current_dict['Test1'] = Test1_dict + +if True: + test_list = [name for name in dir(Test2) if name.find('test_') == 0] + Test2_dict = {} + + # record time taken for each test + for test_name in test_list: + t1 = time.clock() + eval('Test2.%s' % test_name) + t2 = time.clock() + Test2_dict[test_name] = t2-t1 + + current_dict['Test2'] = Test2_dict + +if True: + test_list = [name for name in dir(TestN) if name.find('test_') == 0] + TestN_dict = {} + + # record time taken for each test + for test_name in test_list: + t1 = time.clock() + eval('TestN.%s' % test_name) + t2 = time.clock() + TestN_dict[test_name] = t2-t1 + + current_dict['TestN'] = TestN_dict + +log_total[current_time] = current_dict log_total.close() Copied: branches/Interpolate1D/tests/test_interpolateNd.py (from rev 4620, branches/Interpolate1D/tests/test_ndimage.py) Deleted: branches/Interpolate1D/tests/test_ndimage.py =================================================================== --- branches/Interpolate1D/tests/test_ndimage.py 2008-08-08 16:02:21 UTC (rev 4620) +++ branches/Interpolate1D/tests/test_ndimage.py 2008-08-08 17:37:26 UTC (rev 4621) @@ -1,122 +0,0 @@ -""" module for testing ndimage_wrapper -""" - -# hack to test on Field's computer -import sys -sys.path.append('c:/home/python/Interpolate1d') - -import unittest -import time -from numpy import arange, allclose, ones, array -import numpy as np -import interpolateNd as nd - -class Test (unittest.TestCase): - - def assertAllclose(self, x, y, err=1.0e-8): - self.assert_(np.allclose(x, y, atol=err)) - - def test_interpNd(self): - """ Make sure : the function interpNd works - """ - boring_data = np.ones((5,5,5)) - answer = nd.interpNd(boring_data, np.array([[2.3], [1.0], [3.9]])) - self.assertAllclose( answer , 1.0 ) - - def test_linear(self): - """ Make sure : basic linear works - """ - boring_data = np.ones((5,5,5)) - interp = nd.InterpolateNd(boring_data, kind = 'linear') - self.assertAllclose( interp(np.array([[2.3], [1.0], [3.9]])) , 1.0 ) - - def test_linear_not_1(self): - """ Make sure : linear interpolation works on a general dataset - """ - X, Y = np.meshgrid(arange(10.), arange(10.)) - interesting_data = X+Y - interp = nd.InterpolateNd(interesting_data, kind = 'linear') - self.assertAllclose( interp(np.array([[2.3], [1.0]])) , 3.3 ) - - def test_data_is_list(self): - """ Make sure : data can be entered as a list - """ - boring_data = [ [1.0, 1.0, 1.0], - [1.0, 1.0, 1.0], - [1.0, 1.0, 1.0]] - interp = nd.InterpolateNd(boring_data) - self.assertAllclose( interp(np.array([[1.3], [1.0]])) , 1.0 ) - - def test_coords_is_1d(self): - """ Make sure : coordinates for a single point can be entered as a 1D array - """ - boring_data = np.ones((5,5,5)) - interp = nd.InterpolateNd(boring_data) - self.assertAllclose( interp(np.array([2.3, 1.0, 3.9])) , 1.0 ) - - def test_coords_is_list(self): - """ Make sure : coordinates for a single point can be entered as a list - """ - boring_data = np.ones((5,5,5)) - interp = nd.InterpolateNd(boring_data) - self.assertAllclose( interp([2.3, 1.0, 3.9]) , 1.0 ) - - def test_order2(self): - """ Make sure : quadratic interpolation works - """ - X, Y = np.meshgrid(arange(10.), arange(10.)) - interesting_data = X+Y - interp = nd.InterpolateNd(interesting_data, kind = 2) - print "quad answer: ", interp(np.array([[2.3], [1.0]])) - self.assertAllclose( interp(np.array([[2.3], [1.0]])) , 3.3 , err=.1 ) - - def test_order0(self): - """ Make sure : block interpolation works - """ - X, Y = np.meshgrid(arange(10.), arange(10.)) - interesting_data = X+Y - interp = nd.InterpolateNd(interesting_data, kind = 0) - self.assertAllclose( interp(np.array([[2.3], [1.1]])) , 3.0 ) - - def test_order3(self): - """ Make sure : cubic interpolation works - """ - X, Y = np.meshgrid(arange(10.), arange(10.)) - interesting_data = X+Y - interp = nd.InterpolateNd(interesting_data, kind = 3) - print "cubi answer: ", interp(np.array([[4.3], [4.1]])) - self.assertAllclose( interp(np.array([[4.3], [4.1]])) , 8.4 , err=.1) - - def test_out(self): - """ Make sure : out-of-bounds returns NaN - """ - boring_data = np.ones((5,5,5)) - interp = nd.InterpolateNd(boring_data, kind = 'linear') - self.assert_( np.isnan(interp( np.array([[7.3], [1.0], [3.9]]) ))) - - def test_starting_coords(self): - """ Make sure : non-zero starting coordinates work correctly - """ - X, Y = np.meshgrid(arange(10.), arange(10.)) - interesting_data = X+Y - interp = nd.InterpolateNd(interesting_data, starting_coords = array([2, 1])) - self.assertAllclose( interp(np.array([[2.3], [1.0]])) , 0.3 ) - - def test_spacings(self): - """ Make sure : spacings other than 1 work correctly - """ - X, Y = np.meshgrid(arange(10.), arange(10.)) - interesting_data = X+Y - interp = nd.InterpolateNd(interesting_data, spacings = array([2, 1])) - self.assertAllclose( interp(np.array([[2.4], [1.0]])) , 2.2 ) - - def runTest(self): - """ run all tests - """ - test_list = [method_name for method_name in dir(self) if method_name.find('test')==0] - for test_name in test_list: - exec("self.%s()" % test_name) - - -if __name__ == '__main__': - unittest.main() \ No newline at end of file From scipy-svn at scipy.org Fri Aug 8 14:04:47 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 13:04:47 -0500 (CDT) Subject: [Scipy-svn] r4622 - branches/stats_models Message-ID: <20080808180447.2F3EB39C018@scipy.org> Author: chris.burns Date: 2008-08-08 13:04:44 -0500 (Fri, 08 Aug 2008) New Revision: 4622 Added: branches/stats_models/TODO.txt Log: Add a TODO for the stats.models code. Added: branches/stats_models/TODO.txt =================================================================== --- branches/stats_models/TODO.txt 2008-08-08 17:37:26 UTC (rev 4621) +++ branches/stats_models/TODO.txt 2008-08-08 18:04:44 UTC (rev 4622) @@ -0,0 +1,34 @@ +TODO for scipy.stats.models +=========================== + +In converting the bspline.so from a weave build to a C extension, we +found several things that should be fixed or looked into more +thoroughly. Hopefully we can dedicate some time to this effort at the +Scipy Conf 2008. However, many of these items should be addressed +before stats.models goes into a release of scipy. + +Items +----- + +* Run pychecker on the stats.models and fix numerous errors. There + are import errors, undefined globals, undefined attrs, + etc... Running the command below in stats/models produced 140+ + errors.:: + + # Run pychecker on all python modules except __init__.py + $ grind "[a-z|_][a-z]*.py" | xargs pychecker + +* Address the FIXME issues in the code. + +* Determine and cleanup the public API. Functions/classes used + internally should be private (leading underscore). Public functions + should be obvious and documented. Packaging should be reviewed and + cleaned up. + +* Update documentation to scipy standards. Especially adding example + sections showing how to use the public functions. + +* Tests! Robust tests are needed! Of the subset of tests we looked + at, most only checked attribute setting, not the results of applying + the function to data. + From scipy-svn at scipy.org Fri Aug 8 15:03:49 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 14:03:49 -0500 (CDT) Subject: [Scipy-svn] r4623 - branches/stats_models/src Message-ID: <20080808190349.AC55E39C018@scipy.org> Author: chris.burns Date: 2008-08-08 14:03:44 -0500 (Fri, 08 Aug 2008) New Revision: 4623 Modified: branches/stats_models/src/bspline_ext.c Log: Fix pointer reference bug. Modified: branches/stats_models/src/bspline_ext.c =================================================================== --- branches/stats_models/src/bspline_ext.c 2008-08-08 18:04:44 UTC (rev 4622) +++ branches/stats_models/src/bspline_ext.c 2008-08-08 19:03:44 UTC (rev 4623) @@ -32,7 +32,7 @@ data = (double *)PyArray_DATA(invband); free(dims_invband); - invband_compute(data, L_data, (int)dims_L[0], (int)dims_L[1]); + invband_compute(&data, L_data, (int)dims_L[0], (int)dims_L[1]); exit: @@ -49,7 +49,7 @@ int dl; int dr; double *knots; - double **data; + double *data; npy_intp *nknots; npy_intp *dims_gram; PyArrayObject *knots_array = NULL; @@ -66,10 +66,10 @@ dims_gram[1] = m; gram_array = (PyArrayObject*)PyArray_SimpleNew(2, dims_gram, PyArray_DOUBLE); - data = (double **)PyArray_DATA(gram_array); + data = (double *)PyArray_DATA(gram_array); free(dims_gram); - bspline_gram(data, knots, (int)nknots[0], m, dl, dr); + bspline_gram(&data, knots, (int)nknots[0], m, dl, dr); exit: From scipy-svn at scipy.org Fri Aug 8 15:33:40 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 14:33:40 -0500 (CDT) Subject: [Scipy-svn] r4624 - branches/stats_models/src Message-ID: <20080808193340.C77F439C018@scipy.org> Author: chris.burns Date: 2008-08-08 14:33:35 -0500 (Fri, 08 Aug 2008) New Revision: 4624 Modified: branches/stats_models/src/bspline_impl.c Log: Include stdlib for malloc. Modified: branches/stats_models/src/bspline_impl.c =================================================================== --- branches/stats_models/src/bspline_impl.c 2008-08-08 19:03:44 UTC (rev 4623) +++ branches/stats_models/src/bspline_impl.c 2008-08-08 19:33:35 UTC (rev 4624) @@ -1,4 +1,6 @@ +#include + /* function prototypes */ double *bspline(double **, double *, int, double *, int, int, int, int, int); From scipy-svn at scipy.org Fri Aug 8 15:52:21 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 14:52:21 -0500 (CDT) Subject: [Scipy-svn] r4625 - branches/stats_models Message-ID: <20080808195221.1E37339C021@scipy.org> Author: chris.burns Date: 2008-08-08 14:52:18 -0500 (Fri, 08 Aug 2008) New Revision: 4625 Modified: branches/stats_models/bspline.py Log: Undo rename of bspline.py, which would have created test failures for anyone without a clean install. Modified: branches/stats_models/bspline.py =================================================================== --- branches/stats_models/bspline.py 2008-08-08 19:33:35 UTC (rev 4624) +++ branches/stats_models/bspline.py 2008-08-08 19:52:18 UTC (rev 4625) @@ -20,8 +20,16 @@ from scipy.linalg import solveh_banded from scipy.optimize import golden -from scipy.stats.models import _bspline +from scipy.stats.models import _hbspline + +# Issue warning regarding heavy development status of this module +import warnings +_msg = "The bspline code is technology preview and requires significant work\ +on the public API and documentation. The API will likely change in the future" +warnings.warn(_msg, UserWarning) + + def _band2array(a, lower=0, symmetric=False, hermitian=False): """ Take an upper or lower triangular banded matrix and return a @@ -190,6 +198,10 @@ Bspline to avoid extra evaluation in the __call__ method ''' + # FIXME: update parameter names, replace single character names + # FIXME: `order` should be actual spline order (implemented as order+1) + ## FIXME: update the use of spline order in extension code (evaluate is recursively called) + # FIXME: eliminate duplicate M and m attributes (m is order, M is related to tau size) def __init__(self, knots, order=4, M=None, coef=None, x=None): @@ -277,7 +289,7 @@ x.shape = (N.product(_shape,axis=0),) if i < self.tau.shape[0] - 1: ## TODO: OWNDATA flags... - v = _bspline.evaluate(x, self.tau, self.m, d, i, i+1) + v = _hbspline.evaluate(x, self.tau, self.m, d, i, i+1) else: return N.zeros(x.shape, N.float64) @@ -321,7 +333,7 @@ d = N.asarray(d) if d.shape == (): - v = _bspline.evaluate(x, self.tau, self.m, int(d), lower, upper) + v = _hbspline.evaluate(x, self.tau, self.m, int(d), lower, upper) else: if d.shape[0] != 2: raise ValueError, "if d is not an integer, expecting a jx2 \ @@ -330,7 +342,7 @@ v = 0 for i in range(d.shape[1]): - v += d[1,i] * _bspline.evaluate(x, self.tau, self.m, d[0,i], lower, upper) + v += d[1,i] * _hbspline.evaluate(x, self.tau, self.m, d[0,i], lower, upper) v.shape = (upper-lower,) + _shape if upper == self.tau.shape[0] - self.m: @@ -373,7 +385,7 @@ d = N.squeeze(d) if N.asarray(d).shape == (): - self.g = _bspline.gram(self.tau, self.m, int(d), int(d)) + self.g = _hbspline.gram(self.tau, self.m, int(d), int(d)) else: d = N.asarray(d) if d.shape[0] != 2: @@ -385,7 +397,7 @@ self.g = 0 for i in range(d.shape[1]): for j in range(d.shape[1]): - self.g += d[1,i]* d[1,j] * _bspline.gram(self.tau, self.m, int(d[0,i]), int(d[0,j])) + self.g += d[1,i]* d[1,j] * _hbspline.gram(self.tau, self.m, int(d[0,i]), int(d[0,j])) self.g = self.g.T self.d = d return N.nan_to_num(self.g) @@ -425,6 +437,8 @@ fhat = ARGMIN_f SUM_i=1^n (y_i-f(x_i))^2 + pen * int f^(2)^2 + int is integral. pen is lambda (from Hastie) + See Chapter 5 of Hastie, Tibshirani and Friedman (2001). "The Elements of Statistical @@ -553,7 +567,7 @@ """ if self.pen > 0: - _invband = _bspline.invband(self.chol.copy()) + _invband = _hbspline.invband(self.chol.copy()) tr = _trace_symbanded(_invband, self.btb, lower=1) return tr else: From scipy-svn at scipy.org Fri Aug 8 15:55:34 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 14:55:34 -0500 (CDT) Subject: [Scipy-svn] r4626 - in branches/stats_models: . tests Message-ID: <20080808195534.A8A0839C018@scipy.org> Author: chris.burns Date: 2008-08-08 14:55:31 -0500 (Fri, 08 Aug 2008) New Revision: 4626 Removed: branches/stats_models/_bspline.py branches/stats_models/bspline_module.py Modified: branches/stats_models/tests/test_bspline.py Log: Delete old weave code. Fix bspline import in test. Deleted: branches/stats_models/_bspline.py =================================================================== --- branches/stats_models/_bspline.py 2008-08-08 19:52:18 UTC (rev 4625) +++ branches/stats_models/_bspline.py 2008-08-08 19:55:31 UTC (rev 4626) @@ -1,668 +0,0 @@ -''' -Bspines and smoothing splines. - -General references: - - Craven, P. and Wahba, G. (1978) "Smoothing noisy data with spline functions. - Estimating the correct degree of smoothing by - the method of generalized cross-validation." - Numerische Mathematik, 31(4), 377-403. - - Hastie, Tibshirani and Friedman (2001). "The Elements of Statistical - Learning." Springer-Verlag. 536 pages. - - Hutchison, M. and Hoog, F. "Smoothing noisy data with spline functions." - Numerische Mathematik, 47(1), 99-106. -''' - -import numpy as N -import numpy.linalg as L - -from scipy.linalg import solveh_banded -from scipy.optimize import golden -from scipy.stats.models import _hbspline - - -# Issue warning regarding heavy development status of this module -import warnings -_msg = "The bspline code is technology preview and requires significant work\ -on the public API and documentation. The API will likely change in the future" -warnings.warn(_msg, UserWarning) - - -def _band2array(a, lower=0, symmetric=False, hermitian=False): - """ - Take an upper or lower triangular banded matrix and return a - numpy array. - - INPUTS: - a -- a matrix in upper or lower triangular banded matrix - lower -- is the matrix upper or lower triangular? - symmetric -- if True, return the original result plus its transpose - hermitian -- if True (and symmetric False), return the original - result plus its conjugate transposed - - """ - - n = a.shape[1] - r = a.shape[0] - _a = 0 - - if not lower: - for j in range(r): - _b = N.diag(a[r-1-j],k=j)[j:(n+j),j:(n+j)] - _a += _b - if symmetric and j > 0: _a += _b.T - elif hermitian and j > 0: _a += _b.conjugate().T - else: - for j in range(r): - _b = N.diag(a[j],k=j)[0:n,0:n] - _a += _b - if symmetric and j > 0: _a += _b.T - elif hermitian and j > 0: _a += _b.conjugate().T - _a = _a.T - - return _a - - -def _upper2lower(ub): - """ - Convert upper triangular banded matrix to lower banded form. - - INPUTS: - ub -- an upper triangular banded matrix - - OUTPUTS: lb - lb -- a lower triangular banded matrix with same entries - as ub - """ - - lb = N.zeros(ub.shape, ub.dtype) - nrow, ncol = ub.shape - for i in range(ub.shape[0]): - lb[i,0:(ncol-i)] = ub[nrow-1-i,i:ncol] - lb[i,(ncol-i):] = ub[nrow-1-i,0:i] - return lb - -def _lower2upper(lb): - """ - Convert lower triangular banded matrix to upper banded form. - - INPUTS: - lb -- a lower triangular banded matrix - - OUTPUTS: ub - ub -- an upper triangular banded matrix with same entries - as lb - """ - - ub = N.zeros(lb.shape, lb.dtype) - nrow, ncol = lb.shape - for i in range(lb.shape[0]): - ub[nrow-1-i,i:ncol] = lb[i,0:(ncol-i)] - ub[nrow-1-i,0:i] = lb[i,(ncol-i):] - return ub - -def _triangle2unit(tb, lower=0): - """ - Take a banded triangular matrix and return its diagonal and the - unit matrix: the banded triangular matrix with 1's on the diagonal, - i.e. each row is divided by the corresponding entry on the diagonal. - - INPUTS: - tb -- a lower triangular banded matrix - lower -- if True, then tb is assumed to be lower triangular banded, - in which case return value is also lower triangular banded. - - OUTPUTS: d, b - d -- diagonal entries of tb - b -- unit matrix: if lower is False, b is upper triangular - banded and its rows of have been divided by d, - else lower is True, b is lower triangular banded - and its columns have been divieed by d. - - """ - - if lower: d = tb[0].copy() - else: d = tb[-1].copy() - - if lower: return d, (tb / d) - else: - l = _upper2lower(tb) - return d, _lower2upper(l / d) - -def _trace_symbanded(a, b, lower=0): - """ - Compute the trace(ab) for two upper or banded real symmetric matrices - stored either in either upper or lower form. - - INPUTS: - a, b -- two banded real symmetric matrices (either lower or upper) - lower -- if True, a and b are assumed to be the lower half - - - OUTPUTS: trace - trace -- trace(ab) - - """ - - if lower: - t = _zero_triband(a * b, lower=1) - return t[0].sum() + 2 * t[1:].sum() - else: - t = _zero_triband(a * b, lower=0) - return t[-1].sum() + 2 * t[:-1].sum() - - -def _zero_triband(a, lower=0): - """ - Explicitly zero out unused elements of a real symmetric banded matrix. - - INPUTS: - a -- a real symmetric banded matrix (either upper or lower hald) - lower -- if True, a is assumed to be the lower half - - """ - - nrow, ncol = a.shape - if lower: - for i in range(nrow): a[i,(ncol-i):] = 0. - else: - for i in range(nrow): a[i,0:i] = 0. - return a - - -class BSpline(object): - - ''' - - Bsplines of a given order and specified knots. - - Implementation is based on description in Chapter 5 of - - Hastie, Tibshirani and Friedman (2001). "The Elements of Statistical - Learning." Springer-Verlag. 536 pages. - - - INPUTS: - knots -- a sorted array of knots with knots[0] the lower boundary, - knots[1] the upper boundary and knots[1:-1] the internal - knots. - order -- order of the Bspline, default is 4 which yields cubic - splines - M -- number of additional boundary knots, if None it defaults - to order - coef -- an optional array of real-valued coefficients for the Bspline - of shape (knots.shape + 2 * (M - 1) - order,). - x -- an optional set of x values at which to evaluate the - Bspline to avoid extra evaluation in the __call__ method - - ''' - # FIXME: update parameter names, replace single character names - # FIXME: `order` should be actual spline order (implemented as order+1) - ## FIXME: update the use of spline order in extension code (evaluate is recursively called) - # FIXME: eliminate duplicate M and m attributes (m is order, M is related to tau size) - - def __init__(self, knots, order=4, M=None, coef=None, x=None): - - knots = N.squeeze(N.unique(N.asarray(knots))) - - if knots.ndim != 1: - raise ValueError, 'expecting 1d array for knots' - - self.m = order - if M is None: - M = self.m - self.M = M - - self.tau = N.hstack([[knots[0]]*(self.M-1), knots, [knots[-1]]*(self.M-1)]) - - self.K = knots.shape[0] - 2 - if coef is None: - self.coef = N.zeros((self.K + 2 * self.M - self.m), N.float64) - else: - self.coef = N.squeeze(coef) - if self.coef.shape != (self.K + 2 * self.M - self.m): - raise ValueError, 'coefficients of Bspline have incorrect shape' - if x is not None: - self.x = x - - def _setx(self, x): - self._x = x - self._basisx = self.basis(self._x) - - def _getx(self): - return self._x - - x = property(_getx, _setx) - - def __call__(self, *args): - """ - Evaluate the BSpline at a given point, yielding - a matrix B and return - - B * self.coef - - - INPUTS: - args -- optional arguments. If None, it returns self._basisx, - the BSpline evaluated at the x values passed in __init__. - Otherwise, return the BSpline evaluated at the - first argument args[0]. - - OUTPUTS: y - y -- value of Bspline at specified x values - - BUGS: - If self has no attribute x, an exception will be raised - because self has no attribute _basisx. - - """ - - if not args: - b = self._basisx.T - else: - x = args[0] - b = N.asarray(self.basis(x)).T - return N.squeeze(N.dot(b, self.coef)) - - def basis_element(self, x, i, d=0): - """ - Evaluate a particular basis element of the BSpline, - or its derivative. - - INPUTS: - x -- x values at which to evaluate the basis element - i -- which element of the BSpline to return - d -- the order of derivative - - OUTPUTS: y - y -- value of d-th derivative of the i-th basis element - of the BSpline at specified x values - - """ - - x = N.asarray(x, N.float64) - _shape = x.shape - if _shape == (): - x.shape = (1,) - x.shape = (N.product(_shape,axis=0),) - if i < self.tau.shape[0] - 1: - ## TODO: OWNDATA flags... - v = _hbspline.evaluate(x, self.tau, self.m, d, i, i+1) - else: - return N.zeros(x.shape, N.float64) - - if (i == self.tau.shape[0] - self.m): - v = N.where(N.equal(x, self.tau[-1]), 1, v) - v.shape = _shape - return v - - def basis(self, x, d=0, lower=None, upper=None): - """ - Evaluate the basis of the BSpline or its derivative. - If lower or upper is specified, then only - the [lower:upper] elements of the basis are returned. - - INPUTS: - x -- x values at which to evaluate the basis element - i -- which element of the BSpline to return - d -- the order of derivative - lower -- optional lower limit of the set of basis - elements - upper -- optional upper limit of the set of basis - elements - - OUTPUTS: y - y -- value of d-th derivative of the basis elements - of the BSpline at specified x values - - """ - x = N.asarray(x) - _shape = x.shape - if _shape == (): - x.shape = (1,) - x.shape = (N.product(_shape,axis=0),) - - if upper is None: - upper = self.tau.shape[0] - self.m - if lower is None: - lower = 0 - upper = min(upper, self.tau.shape[0] - self.m) - lower = max(0, lower) - - d = N.asarray(d) - if d.shape == (): - v = _hbspline.evaluate(x, self.tau, self.m, int(d), lower, upper) - else: - if d.shape[0] != 2: - raise ValueError, "if d is not an integer, expecting a jx2 \ - array with first row indicating order \ - of derivative, second row coefficient in front." - - v = 0 - for i in range(d.shape[1]): - v += d[1,i] * _hbspline.evaluate(x, self.tau, self.m, d[0,i], lower, upper) - - v.shape = (upper-lower,) + _shape - if upper == self.tau.shape[0] - self.m: - v[-1] = N.where(N.equal(x, self.tau[-1]), 1, v[-1]) - return v - - def gram(self, d=0): - """ - Compute Gram inner product matrix, storing it in lower - triangular banded form. - - The (i,j) entry is - - G_ij = integral b_i^(d) b_j^(d) - - where b_i are the basis elements of the BSpline and (d) is the - d-th derivative. - - If d is a matrix then, it is assumed to specify a differential - operator as follows: the first row represents the order of derivative - with the second row the coefficient corresponding to that order. - - For instance: - - [[2, 3], - [3, 1]] - - represents 3 * f^(2) + 1 * f^(3). - - INPUTS: - d -- which derivative to apply to each basis element, - if d is a matrix, it is assumed to specify - a differential operator as above - - OUTPUTS: gram - gram -- the matrix of inner products of (derivatives) - of the BSpline elements - - """ - - d = N.squeeze(d) - if N.asarray(d).shape == (): - self.g = _hbspline.gram(self.tau, self.m, int(d), int(d)) - else: - d = N.asarray(d) - if d.shape[0] != 2: - raise ValueError, "if d is not an integer, expecting a jx2 \ - array with first row indicating order \ - of derivative, second row coefficient in front." - if d.shape == (2,): - d.shape = (2,1) - self.g = 0 - for i in range(d.shape[1]): - for j in range(d.shape[1]): - self.g += d[1,i]* d[1,j] * _hbspline.gram(self.tau, self.m, int(d[0,i]), int(d[0,j])) - self.g = self.g.T - self.d = d - return N.nan_to_num(self.g) - -class SmoothingSpline(BSpline): - - penmax = 30. - method = "target_df" - target_df = 5 - default_pen = 1.0e-03 - optimize = True - - ''' - A smoothing spline, which can be used to smooth scatterplots, i.e. - a list of (x,y) tuples. - - See fit method for more information. - - ''' - - def fit(self, y, x=None, weights=None, pen=0.): - """ - Fit the smoothing spline to a set of (x,y) pairs. - - INPUTS: - y -- response variable - x -- if None, uses self.x - weights -- optional array of weights - pen -- constant in front of Gram matrix - - OUTPUTS: None - The smoothing spline is determined by self.coef, - subsequent calls of __call__ will be the smoothing spline. - - ALGORITHM: - Formally, this solves a minimization: - - fhat = ARGMIN_f SUM_i=1^n (y_i-f(x_i))^2 + pen * int f^(2)^2 - - int is integral. pen is lambda (from Hastie) - - See Chapter 5 of - - Hastie, Tibshirani and Friedman (2001). "The Elements of Statistical - Learning." Springer-Verlag. 536 pages. - - for more details. - - TODO: - Should add arbitrary derivative penalty instead of just - second derivative. - """ - - banded = True - - if x is None: - x = self._x - bt = self._basisx.copy() - else: - bt = self.basis(x) - - if pen == 0.: # can't use cholesky for singular matrices - banded = False - - if x.shape != y.shape: - raise ValueError, 'x and y shape do not agree, by default x are \ - the Bspline\'s internal knots' - - if pen >= self.penmax: - pen = self.penmax - - - if weights is not None: - self.weights = weights - else: - self.weights = 1. - - _w = N.sqrt(self.weights) - bt *= _w - - # throw out rows with zeros (this happens at boundary points!) - - mask = N.flatnonzero(1 - N.alltrue(N.equal(bt, 0), axis=0)) - - bt = bt[:,mask] - y = y[mask] - - self.df_total = y.shape[0] - - bty = N.squeeze(N.dot(bt, _w * y)) - self.N = y.shape[0] - - if not banded: - self.btb = N.dot(bt, bt.T) - _g = _band2array(self.g, lower=1, symmetric=True) - self.coef, _, self.rank = L.lstsq(self.btb + pen*_g, bty)[0:3] - self.rank = min(self.rank, self.btb.shape[0]) - del(_g) - else: - self.btb = N.zeros(self.g.shape, N.float64) - nband, nbasis = self.g.shape - for i in range(nbasis): - for k in range(min(nband, nbasis-i)): - self.btb[k,i] = (bt[i] * bt[i+k]).sum() - - bty.shape = (1,bty.shape[0]) - self.pen = pen - self.chol, self.coef = solveh_banded(self.btb + - pen*self.g, - bty, lower=1) - - self.coef = N.squeeze(self.coef) - self.resid = y * self.weights - N.dot(self.coef, bt) - self.pen = pen - - del(bty); del(mask); del(bt) - - def smooth(self, y, x=None, weights=None): - - if self.method == "target_df": - if hasattr(self, 'pen'): - self.fit(y, x=x, weights=weights, pen=self.pen) - else: - self.fit_target_df(y, x=x, weights=weights, df=self.target_df) - elif self.method == "optimize_gcv": - self.fit_optimize_gcv(y, x=x, weights=weights) - - - def gcv(self): - """ - Generalized cross-validation score of current fit. - - Craven, P. and Wahba, G. "Smoothing noisy data with spline functions. - Estimating the correct degree of smoothing by - the method of generalized cross-validation." - Numerische Mathematik, 31(4), 377-403. - """ - - norm_resid = (self.resid**2).sum() - return norm_resid / (self.df_total - self.trace()) - - def df_resid(self): - """ - Residual degrees of freedom in the fit. - - self.N - self.trace() - - where self.N is the number of observations of last fit. - """ - - return self.N - self.trace() - - def df_fit(self): - """ - How many degrees of freedom used in the fit? - - self.trace() - - """ - return self.trace() - - def trace(self): - """ - Trace of the smoothing matrix S(pen) - - TODO: addin a reference to Wahba, and whoever else I used. - """ - - if self.pen > 0: - _invband = _hbspline.invband(self.chol.copy()) - tr = _trace_symbanded(_invband, self.btb, lower=1) - return tr - else: - return self.rank - - def fit_target_df(self, y, x=None, df=None, weights=None, tol=1.0e-03, - apen=0, bpen=1.0e-03): - - """ - Fit smoothing spline with approximately df degrees of freedom - used in the fit, i.e. so that self.trace() is approximately df. - - Uses binary search strategy. - - In general, df must be greater than the dimension of the null space - of the Gram inner product. For cubic smoothing splines, this means - that df > 2. - - INPUTS: - y -- response variable - x -- if None, uses self.x - df -- target degrees of freedom - weights -- optional array of weights - tol -- (relative) tolerance for convergence - apen -- lower bound of penalty for binary search - bpen -- upper bound of penalty for binary search - - OUTPUTS: None - The smoothing spline is determined by self.coef, - subsequent calls of __call__ will be the smoothing spline. - - """ - - df = df or self.target_df - - olddf = y.shape[0] - self.m - - if hasattr(self, "pen"): - self.fit(y, x=x, weights=weights, pen=self.pen) - curdf = self.trace() - if N.fabs(curdf - df) / df < tol: - return - if curdf > df: - apen, bpen = self.pen, 2 * self.pen - else: - apen, bpen = 0., self.pen - - while True: - - curpen = 0.5 * (apen + bpen) - self.fit(y, x=x, weights=weights, pen=curpen) - curdf = self.trace() - if curdf > df: - apen, bpen = curpen, 2 * curpen - else: - apen, bpen = apen, curpen - if apen >= self.penmax: - raise ValueError, "penalty too large, try setting penmax \ - higher or decreasing df" - if N.fabs(curdf - df) / df < tol: - break - - def fit_optimize_gcv(self, y, x=None, weights=None, tol=1.0e-03, - brack=(-100,20)): - """ - Fit smoothing spline trying to optimize GCV. - - Try to find a bracketing interval for scipy.optimize.golden - based on bracket. - - It is probably best to use target_df instead, as it is - sometimes difficult to find a bracketing interval. - - INPUTS: - y -- response variable - x -- if None, uses self.x - df -- target degrees of freedom - weights -- optional array of weights - tol -- (relative) tolerance for convergence - brack -- an initial guess at the bracketing interval - - OUTPUTS: None - The smoothing spline is determined by self.coef, - subsequent calls of __call__ will be the smoothing spline. - - """ - - def _gcv(pen, y, x): - self.fit(y, x=x, pen=N.exp(pen)) - a = self.gcv() - return a - - a = golden(_gcv, args=(y,x), brack=bracket, tol=tol) - - - - - Deleted: branches/stats_models/bspline_module.py =================================================================== --- branches/stats_models/bspline_module.py 2008-08-08 19:52:18 UTC (rev 4625) +++ branches/stats_models/bspline_module.py 2008-08-08 19:55:31 UTC (rev 4626) @@ -1,381 +0,0 @@ -import numpy as N -from scipy.weave import ext_tools -import scipy.special.orthogonal - -def setup_bspline_module(): - """ - Builds an extension module with Bspline basis calculators using - weave. - """ - - mod = ext_tools.ext_module('_bspline', compiler='gcc') - knots = N.linspace(0,1,11).astype(N.float64) - nknots = knots.shape[0] - x = N.array([0.4,0.5], N.float64) - nx = x.shape[0] - m = 4 - d = 0 - lower = 0 - upper = 13 - - # Bspline code in C - eval_code = ''' - double *bspline(double **output, double *x, int nx, - double *knots, int nknots, - int m, int d, int lower, int upper) - { - int nbasis; - int index, i, j, k; - double *result, *b, *b0, *b1; - double *f0, *f1; - double denom; - - nbasis = upper - lower; - - result = *((double **) output); - f0 = (double *) malloc(sizeof(*f0) * nx); - f1 = (double *) malloc(sizeof(*f1) * nx); - - if (m == 1) { - for(i=0; i= knots[index]) * (x[k] < knots[index+1]); - result++; - } - } - else { - for (k=0; kdata; - bspline(&data, x, Nx[0], knots, Nknots[0], m, d, lower, upper); - return_val = (PyObject *) basis; - Py_DECREF((PyObject *) basis); - - ''' - - bspline_eval = ext_tools.ext_function('evaluate', - eval_ext_code, - ['x', 'knots', - 'm', 'd', 'lower', 'upper']) - mod.add_function(bspline_eval) - bspline_eval.customize.add_support_code(eval_code) - - nq = 18 - qx, qw = scipy.special.orthogonal.p_roots(nq) - dl = dr = 2 - - gram_code = ''' - - double *bspline_prod(double *x, int nx, double *knots, int nknots, - int m, int l, int r, int dl, int dr) - { - double *result, *bl, *br; - int k; - - if (fabs(r - l) <= m) { - result = (double *) malloc(sizeof(*result) * nx); - bl = (double *) malloc(sizeof(*bl) * nx); - br = (double *) malloc(sizeof(*br) * nx); - - bl = bspline(&bl, x, nx, knots, nknots, m, dl, l, l+1); - br = bspline(&br, x, nx, knots, nknots, m, dr, r, r+1); - - for (k=0; k nknots - 1) { upper = nknots-1; } - - for (k=lower; kdata; - bspline_gram(&data, knots, Nknots[0], m, dl, dr); - return_val = (PyObject *) gram; - Py_DECREF((PyObject *) gram); - - ''' - - bspline_gram = ext_tools.ext_function('gram', - gram_ext_code, - ['knots', - 'm', 'dl', 'dr']) - - bspline_gram.customize.add_support_code(gram_code) - mod.add_function(bspline_gram) - - L = N.zeros((3,10), N.float64) - - invband_support_code = ''' - - void invband_compute(double **dataptr, double *L, int n, int m) { - - /* Note: m is number of bands not including the diagonal so L is of size (m+1)xn */ - - int i,j,k; - int idx, idy; - double *data, *odata; - double diag; - - data = *((double **) dataptr); - - for (i=0; i 0) { data[j*n+i] = 0;} - } - } - - for (i=n-1; i>=0; i--) { - for (j=1; j <= (mdata; - invband_compute(&data, L, NL[1], NL[0]-1); - - return_val = (PyObject *) invband; - Py_DECREF((PyObject *) invband); - - ''' - - invband = ext_tools.ext_function('invband', - invband_ext_code, - ['L']) - invband.customize.add_support_code(invband_support_code) - mod.add_function(invband) - - return mod - -mod = setup_bspline_module() - -def build_bspline_module(): - mod.compile() - -# try: -# import _bspline -# except ImportError: -# build_bspline_module() -# import _bspline - -## if __name__ == '__main__': -## knots = N.hstack([[0]*3, N.linspace(0,1,11).astype(N.float64), [1]*3]) -## x = N.array([0.4,0.5]) -## print bspline_ext.bspline_eval(x, knots, 4, 2, 0, 13) - -## knots = N.hstack([[0]*3, N.linspace(0,1,501).astype(N.float64), [1]*3]) -## nknots = knots.shape[0] -## x = N.linspace(0,1,1000) -## m = 4 -## d = 0 - - -## import time, gc -## t = 0 -## for i in range(100): -## lower = i -## toc = time.time() -## gc.collect() -## y = bspline_ext.bspline_eval(x, knots, m, 2, 0, 503) -## z = bspline_ext.bspline_prod(x, knots, m, 2, 1, 0, 0) -## tic = time.time() -## t += tic-toc -## del(y); del(z) - -## print t / 100 Modified: branches/stats_models/tests/test_bspline.py =================================================================== --- branches/stats_models/tests/test_bspline.py 2008-08-08 19:52:18 UTC (rev 4625) +++ branches/stats_models/tests/test_bspline.py 2008-08-08 19:55:31 UTC (rev 4626) @@ -4,7 +4,7 @@ import numpy as np from numpy.testing import * -import scipy.stats.models._bspline as bsp +import scipy.stats.models.bspline as bsp class TestBSpline(TestCase): From scipy-svn at scipy.org Fri Aug 8 16:06:42 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 15:06:42 -0500 (CDT) Subject: [Scipy-svn] r4627 - branches/stats_models Message-ID: <20080808200642.0236239C021@scipy.org> Author: chris.burns Date: 2008-08-08 15:06:36 -0500 (Fri, 08 Aug 2008) New Revision: 4627 Modified: branches/stats_models/TODO.txt branches/stats_models/smoothers.py Log: Fix invalid imports. Add note to TODO regarding code duplication. Modified: branches/stats_models/TODO.txt =================================================================== --- branches/stats_models/TODO.txt 2008-08-08 19:55:31 UTC (rev 4626) +++ branches/stats_models/TODO.txt 2008-08-08 20:06:36 UTC (rev 4627) @@ -32,3 +32,5 @@ at, most only checked attribute setting, not the results of applying the function to data. +* Remove code duplication. smoothers.py and bspline.py define + SmoothingSpline class. Modified: branches/stats_models/smoothers.py =================================================================== --- branches/stats_models/smoothers.py 2008-08-08 19:55:31 UTC (rev 4626) +++ branches/stats_models/smoothers.py 2008-08-08 20:06:36 UTC (rev 4627) @@ -9,10 +9,9 @@ from scipy.linalg import solveh_banded from scipy.optimize import golden -from scipy.stats.models import _bspline -from scipy.stats.models.bspline import bspline, _band2array +from scipy.stats.models import _hbspline +from scipy.stats.models.bspline import BSpline, _band2array - class PolySmoother: """ Polynomial smoother up to a given order. @@ -61,7 +60,7 @@ _y = y * _w self.coef = N.dot(L.pinv(X).T, _y) -class SmoothingSpline(bspline): +class SmoothingSpline(BSpline): penmax = 30. @@ -153,7 +152,7 @@ """ if self.pen > 0: - _invband = _bspline.invband(self.chol.copy()) + _invband = _hbspline.invband(self.chol.copy()) tr = _trace_symbanded(_invband, self.btb, lower=1) return tr else: @@ -174,7 +173,7 @@ def __init__(self, knots, order=4, coef=None, M=None, target_df=None): if target_df is not None: self.target_df = target_df - bspline.__init__(self, knots, order=order, coef=coef, M=M) + BSpline.__init__(self, knots, order=order, coef=coef, M=M) self.target_reached = False def fit(self, y, x=None, df=None, weights=None, tol=1.0e-03): From scipy-svn at scipy.org Fri Aug 8 17:10:05 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 16:10:05 -0500 (CDT) Subject: [Scipy-svn] r4628 - branches/stats_models/tests Message-ID: <20080808211005.864C639C021@scipy.org> Author: chris.burns Date: 2008-08-08 16:10:03 -0500 (Fri, 08 Aug 2008) New Revision: 4628 Modified: branches/stats_models/tests/test_bspline.py Log: Add a test for gram function. Modified: branches/stats_models/tests/test_bspline.py =================================================================== --- branches/stats_models/tests/test_bspline.py 2008-08-08 20:06:36 UTC (rev 4627) +++ branches/stats_models/tests/test_bspline.py 2008-08-08 21:10:03 UTC (rev 4628) @@ -15,7 +15,9 @@ new = b._basisx.shape self.assertEqual((old[0], 51), new) - def test2(self): + # FIXME: Have no idea what this test does. It's here to simply verify the + # C extension is working (in a technical sense, not functional). + def test_basis(self): b = bsp.BSpline(np.linspace(0,1,11)) x = np.array([0.4, 0.5]) v = b.basis(x, lower=0, upper=13) @@ -34,6 +36,12 @@ [ 0. , 0. ]]) assert_array_almost_equal(v, t, decimal=6) + # FIXME: Have no idea what this test does. It's here to simply verify the + # C extension is working (in a technical sense, not functional). + def test_gram(self): + b = bsp.BSpline(np.linspace(0,1,11)) + grm = b.gram() + assert grm.shape == (4, 13) if __name__ == "__main__": From scipy-svn at scipy.org Fri Aug 8 17:10:50 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 16:10:50 -0500 (CDT) Subject: [Scipy-svn] r4629 - branches/stats_models/tests Message-ID: <20080808211050.78A9739C021@scipy.org> Author: chris.burns Date: 2008-08-08 16:10:46 -0500 (Fri, 08 Aug 2008) New Revision: 4629 Modified: branches/stats_models/tests/test_formula.py branches/stats_models/tests/test_scale.py Log: Add decorators to skip known test failures. Modified: branches/stats_models/tests/test_formula.py =================================================================== --- branches/stats_models/tests/test_formula.py 2008-08-08 21:10:03 UTC (rev 4628) +++ branches/stats_models/tests/test_formula.py 2008-08-08 21:10:46 UTC (rev 4629) @@ -63,6 +63,7 @@ self.formula += self.terms[i] self.formula.namespace = self.namespace + @dec.skipknownfailure def test_namespace(self): space1 = {'X':N.arange(50), 'Y':N.arange(50)*2} space2 = {'X':N.arange(20), 'Y':N.arange(20)*2} Modified: branches/stats_models/tests/test_scale.py =================================================================== --- branches/stats_models/tests/test_scale.py 2008-08-08 21:10:03 UTC (rev 4628) +++ branches/stats_models/tests/test_scale.py 2008-08-08 21:10:46 UTC (rev 4629) @@ -30,11 +30,16 @@ m = scale.MAD(X, axis=-1) self.assertEquals(m.shape, (40,10)) + # FIXME: Fix the axis length bug in stats.models.robust.scale.huber + # Then resolve ticket #587 + @dec.skipknownfailure def test_huber(self): X = W((40,10)) m = scale.huber(X) self.assertEquals(m.shape, (10,)) + # FIXME: Fix the axis length bug in stats.models.robust.scale.huber + @dec.skipknownfailure def test_huberaxes(self): X = W((40,10,30)) m = scale.huber(X, axis=0) From scipy-svn at scipy.org Fri Aug 8 17:35:32 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 16:35:32 -0500 (CDT) Subject: [Scipy-svn] r4630 - in trunk/scipy/stats/models: . src tests Message-ID: <20080808213532.4971A39C021@scipy.org> Author: chris.burns Date: 2008-08-08 16:35:24 -0500 (Fri, 08 Aug 2008) New Revision: 4630 Added: trunk/scipy/stats/models/TODO.txt trunk/scipy/stats/models/src/ trunk/scipy/stats/models/src/bspline_ext.c trunk/scipy/stats/models/src/bspline_impl.c Removed: trunk/scipy/stats/models/_bspline.py trunk/scipy/stats/models/bspline_module.py trunk/scipy/stats/models/src/bspline_ext.c trunk/scipy/stats/models/src/bspline_impl.c Modified: trunk/scipy/stats/models/bspline.py trunk/scipy/stats/models/setup.py trunk/scipy/stats/models/smoothers.py trunk/scipy/stats/models/tests/test_bspline.py trunk/scipy/stats/models/tests/test_formula.py trunk/scipy/stats/models/tests/test_scale.py Log: Merge branch converting models.bspline weave code to a c extension. Suppress known test failures. Copied: trunk/scipy/stats/models/TODO.txt (from rev 4629, branches/stats_models/TODO.txt) Deleted: trunk/scipy/stats/models/_bspline.py =================================================================== --- trunk/scipy/stats/models/_bspline.py 2008-08-08 21:10:46 UTC (rev 4629) +++ trunk/scipy/stats/models/_bspline.py 2008-08-08 21:35:24 UTC (rev 4630) @@ -1,657 +0,0 @@ -''' -Bspines and smoothing splines. - -General references: - - Craven, P. and Wahba, G. (1978) "Smoothing noisy data with spline functions. - Estimating the correct degree of smoothing by - the method of generalized cross-validation." - Numerische Mathematik, 31(4), 377-403. - - Hastie, Tibshirani and Friedman (2001). "The Elements of Statistical - Learning." Springer-Verlag. 536 pages. - - Hutchison, M. and Hoog, F. "Smoothing noisy data with spline functions." - Numerische Mathematik, 47(1), 99-106. -''' - -import numpy as N -import numpy.linalg as L - -from scipy.linalg import solveh_banded -from scipy.optimize import golden -from scipy.stats.models import _bspline - - -# Issue warning regarding heavy development status of this module -import warnings -_msg = "The bspline code is technology preview and requires significant work\ -on the public API and documentation. The API will likely change in the future" -warnings.warn(_msg, UserWarning) - - -def _band2array(a, lower=0, symmetric=False, hermitian=False): - """ - Take an upper or lower triangular banded matrix and return a - numpy array. - - INPUTS: - a -- a matrix in upper or lower triangular banded matrix - lower -- is the matrix upper or lower triangular? - symmetric -- if True, return the original result plus its transpose - hermitian -- if True (and symmetric False), return the original - result plus its conjugate transposed - - """ - - n = a.shape[1] - r = a.shape[0] - _a = 0 - - if not lower: - for j in range(r): - _b = N.diag(a[r-1-j],k=j)[j:(n+j),j:(n+j)] - _a += _b - if symmetric and j > 0: _a += _b.T - elif hermitian and j > 0: _a += _b.conjugate().T - else: - for j in range(r): - _b = N.diag(a[j],k=j)[0:n,0:n] - _a += _b - if symmetric and j > 0: _a += _b.T - elif hermitian and j > 0: _a += _b.conjugate().T - _a = _a.T - - return _a - - -def _upper2lower(ub): - """ - Convert upper triangular banded matrix to lower banded form. - - INPUTS: - ub -- an upper triangular banded matrix - - OUTPUTS: lb - lb -- a lower triangular banded matrix with same entries - as ub - """ - - lb = N.zeros(ub.shape, ub.dtype) - nrow, ncol = ub.shape - for i in range(ub.shape[0]): - lb[i,0:(ncol-i)] = ub[nrow-1-i,i:ncol] - lb[i,(ncol-i):] = ub[nrow-1-i,0:i] - return lb - -def _lower2upper(lb): - """ - Convert lower triangular banded matrix to upper banded form. - - INPUTS: - lb -- a lower triangular banded matrix - - OUTPUTS: ub - ub -- an upper triangular banded matrix with same entries - as lb - """ - - ub = N.zeros(lb.shape, lb.dtype) - nrow, ncol = lb.shape - for i in range(lb.shape[0]): - ub[nrow-1-i,i:ncol] = lb[i,0:(ncol-i)] - ub[nrow-1-i,0:i] = lb[i,(ncol-i):] - return ub - -def _triangle2unit(tb, lower=0): - """ - Take a banded triangular matrix and return its diagonal and the - unit matrix: the banded triangular matrix with 1's on the diagonal, - i.e. each row is divided by the corresponding entry on the diagonal. - - INPUTS: - tb -- a lower triangular banded matrix - lower -- if True, then tb is assumed to be lower triangular banded, - in which case return value is also lower triangular banded. - - OUTPUTS: d, b - d -- diagonal entries of tb - b -- unit matrix: if lower is False, b is upper triangular - banded and its rows of have been divided by d, - else lower is True, b is lower triangular banded - and its columns have been divieed by d. - - """ - - if lower: d = tb[0].copy() - else: d = tb[-1].copy() - - if lower: return d, (tb / d) - else: - l = _upper2lower(tb) - return d, _lower2upper(l / d) - -def _trace_symbanded(a, b, lower=0): - """ - Compute the trace(ab) for two upper or banded real symmetric matrices - stored either in either upper or lower form. - - INPUTS: - a, b -- two banded real symmetric matrices (either lower or upper) - lower -- if True, a and b are assumed to be the lower half - - - OUTPUTS: trace - trace -- trace(ab) - - """ - - if lower: - t = _zero_triband(a * b, lower=1) - return t[0].sum() + 2 * t[1:].sum() - else: - t = _zero_triband(a * b, lower=0) - return t[-1].sum() + 2 * t[:-1].sum() - - -def _zero_triband(a, lower=0): - """ - Explicitly zero out unused elements of a real symmetric banded matrix. - - INPUTS: - a -- a real symmetric banded matrix (either upper or lower hald) - lower -- if True, a is assumed to be the lower half - - """ - - nrow, ncol = a.shape - if lower: - for i in range(nrow): a[i,(ncol-i):] = 0. - else: - for i in range(nrow): a[i,0:i] = 0. - return a - - -class BSpline(object): - - ''' - - Bsplines of a given order and specified knots. - - Implementation is based on description in Chapter 5 of - - Hastie, Tibshirani and Friedman (2001). "The Elements of Statistical - Learning." Springer-Verlag. 536 pages. - - - INPUTS: - knots -- a sorted array of knots with knots[0] the lower boundary, - knots[1] the upper boundary and knots[1:-1] the internal - knots. - order -- order of the Bspline, default is 4 which yields cubic - splines - M -- number of additional boundary knots, if None it defaults - to order - coef -- an optional array of real-valued coefficients for the Bspline - of shape (knots.shape + 2 * (M - 1) - order,). - x -- an optional set of x values at which to evaluate the - Bspline to avoid extra evaluation in the __call__ method - - ''' - - def __init__(self, knots, order=4, M=None, coef=None, x=None): - - knots = N.squeeze(N.unique(N.asarray(knots))) - - if knots.ndim != 1: - raise ValueError, 'expecting 1d array for knots' - - self.m = order - if M is None: - M = self.m - self.M = M - - self.tau = N.hstack([[knots[0]]*(self.M-1), knots, [knots[-1]]*(self.M-1)]) - - self.K = knots.shape[0] - 2 - if coef is None: - self.coef = N.zeros((self.K + 2 * self.M - self.m), N.float64) - else: - self.coef = N.squeeze(coef) - if self.coef.shape != (self.K + 2 * self.M - self.m): - raise ValueError, 'coefficients of Bspline have incorrect shape' - if x is not None: - self.x = x - - def _setx(self, x): - self._x = x - self._basisx = self.basis(self._x) - - def _getx(self): - return self._x - - x = property(_getx, _setx) - - def __call__(self, *args): - """ - Evaluate the BSpline at a given point, yielding - a matrix B and return - - B * self.coef - - - INPUTS: - args -- optional arguments. If None, it returns self._basisx, - the BSpline evaluated at the x values passed in __init__. - Otherwise, return the BSpline evaluated at the - first argument args[0]. - - OUTPUTS: y - y -- value of Bspline at specified x values - - BUGS: - If self has no attribute x, an exception will be raised - because self has no attribute _basisx. - - """ - - if not args: - b = self._basisx.T - else: - x = args[0] - b = N.asarray(self.basis(x)).T - return N.squeeze(N.dot(b, self.coef)) - - def basis_element(self, x, i, d=0): - """ - Evaluate a particular basis element of the BSpline, - or its derivative. - - INPUTS: - x -- x values at which to evaluate the basis element - i -- which element of the BSpline to return - d -- the order of derivative - - OUTPUTS: y - y -- value of d-th derivative of the i-th basis element - of the BSpline at specified x values - - """ - - x = N.asarray(x, N.float64) - _shape = x.shape - if _shape == (): - x.shape = (1,) - x.shape = (N.product(_shape,axis=0),) - if i < self.tau.shape[0] - 1: - ## TODO: OWNDATA flags... - v = _bspline.evaluate(x, self.tau, self.m, d, i, i+1) - else: - return N.zeros(x.shape, N.float64) - - if (i == self.tau.shape[0] - self.m): - v = N.where(N.equal(x, self.tau[-1]), 1, v) - v.shape = _shape - return v - - def basis(self, x, d=0, lower=None, upper=None): - """ - Evaluate the basis of the BSpline or its derivative. - If lower or upper is specified, then only - the [lower:upper] elements of the basis are returned. - - INPUTS: - x -- x values at which to evaluate the basis element - i -- which element of the BSpline to return - d -- the order of derivative - lower -- optional lower limit of the set of basis - elements - upper -- optional upper limit of the set of basis - elements - - OUTPUTS: y - y -- value of d-th derivative of the basis elements - of the BSpline at specified x values - - """ - x = N.asarray(x) - _shape = x.shape - if _shape == (): - x.shape = (1,) - x.shape = (N.product(_shape,axis=0),) - - if upper is None: - upper = self.tau.shape[0] - self.m - if lower is None: - lower = 0 - upper = min(upper, self.tau.shape[0] - self.m) - lower = max(0, lower) - - d = N.asarray(d) - if d.shape == (): - v = _bspline.evaluate(x, self.tau, self.m, int(d), lower, upper) - else: - if d.shape[0] != 2: - raise ValueError, "if d is not an integer, expecting a jx2 \ - array with first row indicating order \ - of derivative, second row coefficient in front." - - v = 0 - for i in range(d.shape[1]): - v += d[1,i] * _bspline.evaluate(x, self.tau, self.m, d[0,i], lower, upper) - - v.shape = (upper-lower,) + _shape - if upper == self.tau.shape[0] - self.m: - v[-1] = N.where(N.equal(x, self.tau[-1]), 1, v[-1]) - return v - - def gram(self, d=0): - """ - Compute Gram inner product matrix, storing it in lower - triangular banded form. - - The (i,j) entry is - - G_ij = integral b_i^(d) b_j^(d) - - where b_i are the basis elements of the BSpline and (d) is the - d-th derivative. - - If d is a matrix then, it is assumed to specify a differential - operator as follows: the first row represents the order of derivative - with the second row the coefficient corresponding to that order. - - For instance: - - [[2, 3], - [3, 1]] - - represents 3 * f^(2) + 1 * f^(3). - - INPUTS: - d -- which derivative to apply to each basis element, - if d is a matrix, it is assumed to specify - a differential operator as above - - OUTPUTS: gram - gram -- the matrix of inner products of (derivatives) - of the BSpline elements - - """ - - d = N.squeeze(d) - if N.asarray(d).shape == (): - self.g = _bspline.gram(self.tau, self.m, int(d), int(d)) - else: - d = N.asarray(d) - if d.shape[0] != 2: - raise ValueError, "if d is not an integer, expecting a jx2 \ - array with first row indicating order \ - of derivative, second row coefficient in front." - if d.shape == (2,): - d.shape = (2,1) - self.g = 0 - for i in range(d.shape[1]): - for j in range(d.shape[1]): - self.g += d[1,i]* d[1,j] * _bspline.gram(self.tau, self.m, int(d[0,i]), int(d[0,j])) - self.g = self.g.T - self.d = d - return N.nan_to_num(self.g) - -class SmoothingSpline(BSpline): - - penmax = 30. - method = "target_df" - target_df = 5 - default_pen = 1.0e-03 - optimize = True - - ''' - A smoothing spline, which can be used to smooth scatterplots, i.e. - a list of (x,y) tuples. - - See fit method for more information. - - ''' - - def fit(self, y, x=None, weights=None, pen=0.): - """ - Fit the smoothing spline to a set of (x,y) pairs. - - INPUTS: - y -- response variable - x -- if None, uses self.x - weights -- optional array of weights - pen -- constant in front of Gram matrix - - OUTPUTS: None - The smoothing spline is determined by self.coef, - subsequent calls of __call__ will be the smoothing spline. - - ALGORITHM: - Formally, this solves a minimization: - - fhat = ARGMIN_f SUM_i=1^n (y_i-f(x_i))^2 + pen * int f^(2)^2 - - See Chapter 5 of - - Hastie, Tibshirani and Friedman (2001). "The Elements of Statistical - Learning." Springer-Verlag. 536 pages. - - for more details. - - TODO: - Should add arbitrary derivative penalty instead of just - second derivative. - """ - - banded = True - - if x is None: - x = self._x - bt = self._basisx.copy() - else: - bt = self.basis(x) - - if pen == 0.: # can't use cholesky for singular matrices - banded = False - - if x.shape != y.shape: - raise ValueError, 'x and y shape do not agree, by default x are \ - the Bspline\'s internal knots' - - if pen >= self.penmax: - pen = self.penmax - - - if weights is not None: - self.weights = weights - else: - self.weights = 1. - - _w = N.sqrt(self.weights) - bt *= _w - - # throw out rows with zeros (this happens at boundary points!) - - mask = N.flatnonzero(1 - N.alltrue(N.equal(bt, 0), axis=0)) - - bt = bt[:,mask] - y = y[mask] - - self.df_total = y.shape[0] - - bty = N.squeeze(N.dot(bt, _w * y)) - self.N = y.shape[0] - - if not banded: - self.btb = N.dot(bt, bt.T) - _g = _band2array(self.g, lower=1, symmetric=True) - self.coef, _, self.rank = L.lstsq(self.btb + pen*_g, bty)[0:3] - self.rank = min(self.rank, self.btb.shape[0]) - del(_g) - else: - self.btb = N.zeros(self.g.shape, N.float64) - nband, nbasis = self.g.shape - for i in range(nbasis): - for k in range(min(nband, nbasis-i)): - self.btb[k,i] = (bt[i] * bt[i+k]).sum() - - bty.shape = (1,bty.shape[0]) - self.pen = pen - self.chol, self.coef = solveh_banded(self.btb + - pen*self.g, - bty, lower=1) - - self.coef = N.squeeze(self.coef) - self.resid = y * self.weights - N.dot(self.coef, bt) - self.pen = pen - - del(bty); del(mask); del(bt) - - def smooth(self, y, x=None, weights=None): - - if self.method == "target_df": - if hasattr(self, 'pen'): - self.fit(y, x=x, weights=weights, pen=self.pen) - else: - self.fit_target_df(y, x=x, weights=weights, df=self.target_df) - elif self.method == "optimize_gcv": - self.fit_optimize_gcv(y, x=x, weights=weights) - - - def gcv(self): - """ - Generalized cross-validation score of current fit. - - Craven, P. and Wahba, G. "Smoothing noisy data with spline functions. - Estimating the correct degree of smoothing by - the method of generalized cross-validation." - Numerische Mathematik, 31(4), 377-403. - """ - - norm_resid = (self.resid**2).sum() - return norm_resid / (self.df_total - self.trace()) - - def df_resid(self): - """ - Residual degrees of freedom in the fit. - - self.N - self.trace() - - where self.N is the number of observations of last fit. - """ - - return self.N - self.trace() - - def df_fit(self): - """ - How many degrees of freedom used in the fit? - - self.trace() - - """ - return self.trace() - - def trace(self): - """ - Trace of the smoothing matrix S(pen) - - TODO: addin a reference to Wahba, and whoever else I used. - """ - - if self.pen > 0: - _invband = _bspline.invband(self.chol.copy()) - tr = _trace_symbanded(_invband, self.btb, lower=1) - return tr - else: - return self.rank - - def fit_target_df(self, y, x=None, df=None, weights=None, tol=1.0e-03, - apen=0, bpen=1.0e-03): - - """ - Fit smoothing spline with approximately df degrees of freedom - used in the fit, i.e. so that self.trace() is approximately df. - - Uses binary search strategy. - - In general, df must be greater than the dimension of the null space - of the Gram inner product. For cubic smoothing splines, this means - that df > 2. - - INPUTS: - y -- response variable - x -- if None, uses self.x - df -- target degrees of freedom - weights -- optional array of weights - tol -- (relative) tolerance for convergence - apen -- lower bound of penalty for binary search - bpen -- upper bound of penalty for binary search - - OUTPUTS: None - The smoothing spline is determined by self.coef, - subsequent calls of __call__ will be the smoothing spline. - - """ - - df = df or self.target_df - - olddf = y.shape[0] - self.m - - if hasattr(self, "pen"): - self.fit(y, x=x, weights=weights, pen=self.pen) - curdf = self.trace() - if N.fabs(curdf - df) / df < tol: - return - if curdf > df: - apen, bpen = self.pen, 2 * self.pen - else: - apen, bpen = 0., self.pen - - while True: - - curpen = 0.5 * (apen + bpen) - self.fit(y, x=x, weights=weights, pen=curpen) - curdf = self.trace() - if curdf > df: - apen, bpen = curpen, 2 * curpen - else: - apen, bpen = apen, curpen - if apen >= self.penmax: - raise ValueError, "penalty too large, try setting penmax \ - higher or decreasing df" - if N.fabs(curdf - df) / df < tol: - break - - def fit_optimize_gcv(self, y, x=None, weights=None, tol=1.0e-03, - brack=(-100,20)): - """ - Fit smoothing spline trying to optimize GCV. - - Try to find a bracketing interval for scipy.optimize.golden - based on bracket. - - It is probably best to use target_df instead, as it is - sometimes difficult to find a bracketing interval. - - INPUTS: - y -- response variable - x -- if None, uses self.x - df -- target degrees of freedom - weights -- optional array of weights - tol -- (relative) tolerance for convergence - brack -- an initial guess at the bracketing interval - - OUTPUTS: None - The smoothing spline is determined by self.coef, - subsequent calls of __call__ will be the smoothing spline. - - """ - - def _gcv(pen, y, x): - self.fit(y, x=x, pen=N.exp(pen)) - a = self.gcv() - return a - - a = golden(_gcv, args=(y,x), brack=bracket, tol=tol) Modified: trunk/scipy/stats/models/bspline.py =================================================================== --- trunk/scipy/stats/models/bspline.py 2008-08-08 21:10:46 UTC (rev 4629) +++ trunk/scipy/stats/models/bspline.py 2008-08-08 21:35:24 UTC (rev 4630) @@ -20,8 +20,16 @@ from scipy.linalg import solveh_banded from scipy.optimize import golden -from scipy.stats.models import _bspline +from scipy.stats.models import _hbspline + +# Issue warning regarding heavy development status of this module +import warnings +_msg = "The bspline code is technology preview and requires significant work\ +on the public API and documentation. The API will likely change in the future" +warnings.warn(_msg, UserWarning) + + def _band2array(a, lower=0, symmetric=False, hermitian=False): """ Take an upper or lower triangular banded matrix and return a @@ -190,6 +198,10 @@ Bspline to avoid extra evaluation in the __call__ method ''' + # FIXME: update parameter names, replace single character names + # FIXME: `order` should be actual spline order (implemented as order+1) + ## FIXME: update the use of spline order in extension code (evaluate is recursively called) + # FIXME: eliminate duplicate M and m attributes (m is order, M is related to tau size) def __init__(self, knots, order=4, M=None, coef=None, x=None): @@ -277,7 +289,7 @@ x.shape = (N.product(_shape,axis=0),) if i < self.tau.shape[0] - 1: ## TODO: OWNDATA flags... - v = _bspline.evaluate(x, self.tau, self.m, d, i, i+1) + v = _hbspline.evaluate(x, self.tau, self.m, d, i, i+1) else: return N.zeros(x.shape, N.float64) @@ -321,7 +333,7 @@ d = N.asarray(d) if d.shape == (): - v = _bspline.evaluate(x, self.tau, self.m, int(d), lower, upper) + v = _hbspline.evaluate(x, self.tau, self.m, int(d), lower, upper) else: if d.shape[0] != 2: raise ValueError, "if d is not an integer, expecting a jx2 \ @@ -330,7 +342,7 @@ v = 0 for i in range(d.shape[1]): - v += d[1,i] * _bspline.evaluate(x, self.tau, self.m, d[0,i], lower, upper) + v += d[1,i] * _hbspline.evaluate(x, self.tau, self.m, d[0,i], lower, upper) v.shape = (upper-lower,) + _shape if upper == self.tau.shape[0] - self.m: @@ -373,7 +385,7 @@ d = N.squeeze(d) if N.asarray(d).shape == (): - self.g = _bspline.gram(self.tau, self.m, int(d), int(d)) + self.g = _hbspline.gram(self.tau, self.m, int(d), int(d)) else: d = N.asarray(d) if d.shape[0] != 2: @@ -385,7 +397,7 @@ self.g = 0 for i in range(d.shape[1]): for j in range(d.shape[1]): - self.g += d[1,i]* d[1,j] * _bspline.gram(self.tau, self.m, int(d[0,i]), int(d[0,j])) + self.g += d[1,i]* d[1,j] * _hbspline.gram(self.tau, self.m, int(d[0,i]), int(d[0,j])) self.g = self.g.T self.d = d return N.nan_to_num(self.g) @@ -425,6 +437,8 @@ fhat = ARGMIN_f SUM_i=1^n (y_i-f(x_i))^2 + pen * int f^(2)^2 + int is integral. pen is lambda (from Hastie) + See Chapter 5 of Hastie, Tibshirani and Friedman (2001). "The Elements of Statistical @@ -553,7 +567,7 @@ """ if self.pen > 0: - _invband = _bspline.invband(self.chol.copy()) + _invband = _hbspline.invband(self.chol.copy()) tr = _trace_symbanded(_invband, self.btb, lower=1) return tr else: Deleted: trunk/scipy/stats/models/bspline_module.py =================================================================== --- trunk/scipy/stats/models/bspline_module.py 2008-08-08 21:10:46 UTC (rev 4629) +++ trunk/scipy/stats/models/bspline_module.py 2008-08-08 21:35:24 UTC (rev 4630) @@ -1,381 +0,0 @@ -import numpy as N -from scipy.weave import ext_tools -import scipy.special.orthogonal - -def setup_bspline_module(): - """ - Builds an extension module with Bspline basis calculators using - weave. - """ - - mod = ext_tools.ext_module('_bspline', compiler='gcc') - knots = N.linspace(0,1,11).astype(N.float64) - nknots = knots.shape[0] - x = N.array([0.4,0.5], N.float64) - nx = x.shape[0] - m = 4 - d = 0 - lower = 0 - upper = 13 - - # Bspline code in C - eval_code = ''' - double *bspline(double **output, double *x, int nx, - double *knots, int nknots, - int m, int d, int lower, int upper) - { - int nbasis; - int index, i, j, k; - double *result, *b, *b0, *b1; - double *f0, *f1; - double denom; - - nbasis = upper - lower; - - result = *((double **) output); - f0 = (double *) malloc(sizeof(*f0) * nx); - f1 = (double *) malloc(sizeof(*f1) * nx); - - if (m == 1) { - for(i=0; i= knots[index]) * (x[k] < knots[index+1]); - result++; - } - } - else { - for (k=0; kdata; - bspline(&data, x, Nx[0], knots, Nknots[0], m, d, lower, upper); - return_val = (PyObject *) basis; - Py_DECREF((PyObject *) basis); - - ''' - - bspline_eval = ext_tools.ext_function('evaluate', - eval_ext_code, - ['x', 'knots', - 'm', 'd', 'lower', 'upper']) - mod.add_function(bspline_eval) - bspline_eval.customize.add_support_code(eval_code) - - nq = 18 - qx, qw = scipy.special.orthogonal.p_roots(nq) - dl = dr = 2 - - gram_code = ''' - - double *bspline_prod(double *x, int nx, double *knots, int nknots, - int m, int l, int r, int dl, int dr) - { - double *result, *bl, *br; - int k; - - if (fabs(r - l) <= m) { - result = (double *) malloc(sizeof(*result) * nx); - bl = (double *) malloc(sizeof(*bl) * nx); - br = (double *) malloc(sizeof(*br) * nx); - - bl = bspline(&bl, x, nx, knots, nknots, m, dl, l, l+1); - br = bspline(&br, x, nx, knots, nknots, m, dr, r, r+1); - - for (k=0; k nknots - 1) { upper = nknots-1; } - - for (k=lower; kdata; - bspline_gram(&data, knots, Nknots[0], m, dl, dr); - return_val = (PyObject *) gram; - Py_DECREF((PyObject *) gram); - - ''' - - bspline_gram = ext_tools.ext_function('gram', - gram_ext_code, - ['knots', - 'm', 'dl', 'dr']) - - bspline_gram.customize.add_support_code(gram_code) - mod.add_function(bspline_gram) - - L = N.zeros((3,10), N.float64) - - invband_support_code = ''' - - void invband_compute(double **dataptr, double *L, int n, int m) { - - /* Note: m is number of bands not including the diagonal so L is of size (m+1)xn */ - - int i,j,k; - int idx, idy; - double *data, *odata; - double diag; - - data = *((double **) dataptr); - - for (i=0; i 0) { data[j*n+i] = 0;} - } - } - - for (i=n-1; i>=0; i--) { - for (j=1; j <= (mdata; - invband_compute(&data, L, NL[1], NL[0]-1); - - return_val = (PyObject *) invband; - Py_DECREF((PyObject *) invband); - - ''' - - invband = ext_tools.ext_function('invband', - invband_ext_code, - ['L']) - invband.customize.add_support_code(invband_support_code) - mod.add_function(invband) - - return mod - -mod = setup_bspline_module() - -def build_bspline_module(): - mod.compile() - -# try: -# import _bspline -# except ImportError: -# build_bspline_module() -# import _bspline - -## if __name__ == '__main__': -## knots = N.hstack([[0]*3, N.linspace(0,1,11).astype(N.float64), [1]*3]) -## x = N.array([0.4,0.5]) -## print bspline_ext.bspline_eval(x, knots, 4, 2, 0, 13) - -## knots = N.hstack([[0]*3, N.linspace(0,1,501).astype(N.float64), [1]*3]) -## nknots = knots.shape[0] -## x = N.linspace(0,1,1000) -## m = 4 -## d = 0 - - -## import time, gc -## t = 0 -## for i in range(100): -## lower = i -## toc = time.time() -## gc.collect() -## y = bspline_ext.bspline_eval(x, knots, m, 2, 0, 503) -## z = bspline_ext.bspline_prod(x, knots, m, 2, 1, 0, 0) -## tic = time.time() -## t += tic-toc -## del(y); del(z) - -## print t / 100 Modified: trunk/scipy/stats/models/setup.py =================================================================== --- trunk/scipy/stats/models/setup.py 2008-08-08 21:10:46 UTC (rev 4629) +++ trunk/scipy/stats/models/setup.py 2008-08-08 21:35:24 UTC (rev 4630) @@ -1,27 +1,21 @@ -def configuration(parent_package='',top_path=None, package_name='models'): +def configuration(parent_package='',top_path=None): from numpy.distutils.misc_util import Configuration - config = Configuration(package_name,parent_package,top_path) + config = Configuration('models',parent_package,top_path) - config.add_subpackage('*') + config.add_subpackage('family') + config.add_subpackage('robust') config.add_data_dir('tests') - try: - from scipy.stats.models.bspline_module import mod - n, s, d = weave_ext(mod) - config.add_extension(n, s, **d) - except ImportError: pass - + config.add_extension('_hbspline', + sources=['src/bspline_ext.c', + 'src/bspline_impl.c'], + ) return config -def weave_ext(mod): - d = mod.setup_extension().__dict__ - n = d['name']; del(d['name']) - s = d['sources']; del(d['sources']) - return n, s, d - if __name__ == '__main__': from numpy.distutils.core import setup - setup(**configuration(top_path='', package_name='scipy.stats.models').todict()) + setup(**configuration(top_path='').todict()) + Modified: trunk/scipy/stats/models/smoothers.py =================================================================== --- trunk/scipy/stats/models/smoothers.py 2008-08-08 21:10:46 UTC (rev 4629) +++ trunk/scipy/stats/models/smoothers.py 2008-08-08 21:35:24 UTC (rev 4630) @@ -9,10 +9,9 @@ from scipy.linalg import solveh_banded from scipy.optimize import golden -from scipy.stats.models import _bspline -from scipy.stats.models.bspline import bspline, _band2array +from scipy.stats.models import _hbspline +from scipy.stats.models.bspline import BSpline, _band2array - class PolySmoother: """ Polynomial smoother up to a given order. @@ -61,7 +60,7 @@ _y = y * _w self.coef = N.dot(L.pinv(X).T, _y) -class SmoothingSpline(bspline): +class SmoothingSpline(BSpline): penmax = 30. @@ -153,7 +152,7 @@ """ if self.pen > 0: - _invband = _bspline.invband(self.chol.copy()) + _invband = _hbspline.invband(self.chol.copy()) tr = _trace_symbanded(_invband, self.btb, lower=1) return tr else: @@ -174,7 +173,7 @@ def __init__(self, knots, order=4, coef=None, M=None, target_df=None): if target_df is not None: self.target_df = target_df - bspline.__init__(self, knots, order=order, coef=coef, M=M) + BSpline.__init__(self, knots, order=order, coef=coef, M=M) self.target_reached = False def fit(self, y, x=None, df=None, weights=None, tol=1.0e-03): Copied: trunk/scipy/stats/models/src (from rev 4629, branches/stats_models/src) Deleted: trunk/scipy/stats/models/src/bspline_ext.c =================================================================== --- branches/stats_models/src/bspline_ext.c 2008-08-08 21:10:46 UTC (rev 4629) +++ trunk/scipy/stats/models/src/bspline_ext.c 2008-08-08 21:35:24 UTC (rev 4630) @@ -1,135 +0,0 @@ -#include "Python.h" -#include "numpy/arrayobject.h" - -/* function prototypes */ - -double *bspline(double**, double*, int, double *, int, int, int, int, int); -void bspline_gram(double **, double *, int, int, int, int); -void invband_compute(double **, double *, int, int); - - -static PyObject *BSpline_Invband(PyObject *self, PyObject *args) -{ - - double *data; - double *L_data; - npy_intp *dims_invband; - npy_intp *dims_L; - PyArrayObject *L = NULL; - PyArrayObject *invband = NULL; - - if(!PyArg_ParseTuple(args, "O", &L)) - goto exit; - - dims_L = PyArray_DIMS(L); - L_data = (double *)PyArray_DATA(L); - - dims_invband = calloc(2, sizeof(npy_intp)); - dims_invband[0] = dims_L[0]; - dims_invband[1] = dims_L[1]; - - invband = (PyArrayObject*)PyArray_SimpleNew(2, dims_invband, PyArray_DOUBLE); - data = (double *)PyArray_DATA(invband); - free(dims_invband); - - invband_compute(&data, L_data, (int)dims_L[0], (int)dims_L[1]); - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("O", invband); - -} - - - -static PyObject *BSpline_Gram(PyObject *self, PyObject *args) -{ - - int m; - int dl; - int dr; - double *knots; - double *data; - npy_intp *nknots; - npy_intp *dims_gram; - PyArrayObject *knots_array = NULL; - PyArrayObject *gram_array = NULL; - - if(!PyArg_ParseTuple(args, "Oiii", &knots_array, &m, &dl, &dr)) - goto exit; - - nknots = PyArray_DIMS(knots_array); - knots = (double *)PyArray_DATA(knots_array); - - dims_gram = calloc(2, sizeof(npy_intp)); - dims_gram[0] = (int)nknots[0] - m; - dims_gram[1] = m; - - gram_array = (PyArrayObject*)PyArray_SimpleNew(2, dims_gram, PyArray_DOUBLE); - data = (double *)PyArray_DATA(gram_array); - free(dims_gram); - - bspline_gram(&data, knots, (int)nknots[0], m, dl, dr); - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("O", gram_array); - -} - - -static PyObject *BSpline_Evaluate(PyObject *self, PyObject *args) -{ - - int i; - int upper; - int lower; - int m; - int d; - double *knots; - double *x; - double *data; - npy_intp *nknots; - npy_intp *nx; - npy_intp dims_basis[2]; - PyArrayObject *knots_array = NULL; - PyArrayObject *x_array = NULL; - PyArrayObject *basis_array = NULL; - - if(!PyArg_ParseTuple(args, "OOiiii", &x_array, &knots_array, &m, &d, &lower, &upper)) - goto exit; - - nknots = PyArray_DIMS(knots_array); - nx = PyArray_DIMS(x_array); - - knots = (double *)PyArray_DATA(knots_array); - x = (double *)PyArray_DATA(x_array); - - dims_basis[0] = upper-lower; - dims_basis[1] = (int)nx[0]; - basis_array = (PyArrayObject*)PyArray_SimpleNew(2, dims_basis, PyArray_DOUBLE); - data = (double *)PyArray_DATA(basis_array); - - bspline(&data, x, (int)nx[0], knots, (int)nknots[0], m, d, lower, upper); - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("O", basis_array); - -} - - -static PyMethodDef BSplineMethods[] = -{ - { "evaluate", BSpline_Evaluate, METH_VARARGS, NULL }, - { "gram", BSpline_Gram, METH_VARARGS, NULL }, - { "invband", BSpline_Invband, METH_VARARGS, NULL }, - { NULL, NULL, 0, NULL}, -}; - -PyMODINIT_FUNC init_hbspline(void) -{ - Py_InitModule("_hbspline", BSplineMethods); - import_array(); -} - Copied: trunk/scipy/stats/models/src/bspline_ext.c (from rev 4629, branches/stats_models/src/bspline_ext.c) Deleted: trunk/scipy/stats/models/src/bspline_impl.c =================================================================== --- branches/stats_models/src/bspline_impl.c 2008-08-08 21:10:46 UTC (rev 4629) +++ trunk/scipy/stats/models/src/bspline_impl.c 2008-08-08 21:35:24 UTC (rev 4630) @@ -1,274 +0,0 @@ - -#include - -/* function prototypes */ - -double *bspline(double **, double *, int, double *, int, int, int, int, int); -double bspline_quad(double *, int, int, int, int, int, int); -double *bspline_prod(double *, int, double *, int, int, int, int, int, int); -void bspline_gram(double **, double *, int, int, int, int); -void invband_compute(double **, double *, int, int); - - -double *bspline(double **output, double *x, int nx, - double *knots, int nknots, - int m, int d, int lower, int upper){ - - int nbasis; - int index, i, j, k; - double *result, *b, *b0, *b1; - double *f0, *f1; - double denom; - - nbasis = upper - lower; - - result = *((double **) output); - f0 = (double *) malloc(sizeof(*f0) * nx); - f1 = (double *) malloc(sizeof(*f1) * nx); - - if (m == 1) { - for(i=0; i= knots[index]) * (x[k] < knots[index+1]); - result++; - } - } - else { - for (k=0; k nknots - 1) { upper = nknots-1; } - - for (k=lower; k 0) { data[j*n+i] = 0;} - } - } - - for (i=n-1; i>=0; i--) { - for (j=1; j <= (m Author: chris.burns Date: 2008-08-08 16:43:17 -0500 (Fri, 08 Aug 2008) New Revision: 4631 Modified: trunk/scipy/stats/models/setupscons.py Log: Fix setupscons.py with new extension code. Modified: trunk/scipy/stats/models/setupscons.py =================================================================== --- trunk/scipy/stats/models/setupscons.py 2008-08-08 21:35:24 UTC (rev 4630) +++ trunk/scipy/stats/models/setupscons.py 2008-08-08 21:43:17 UTC (rev 4631) @@ -1,27 +1,21 @@ -def configuration(parent_package='',top_path=None, package_name='models'): +def configuration(parent_package='',top_path=None): from numpy.distutils.misc_util import Configuration - config = Configuration(package_name,parent_package,top_path) + config = Configuration('models',parent_package,top_path) - config.add_subpackage('*') + config.add_subpackage('family') + config.add_subpackage('robust') config.add_data_dir('tests') - try: - from scipy.stats.models.bspline_module import mod - n, s, d = weave_ext(mod) - config.add_extension(n, s, **d) - except ImportError: pass - + config.add_extension('_hbspline', + sources=['src/bspline_ext.c', + 'src/bspline_impl.c'], + ) return config -def weave_ext(mod): - d = mod.setup_extension().__dict__ - n = d['name']; del(d['name']) - s = d['sources']; del(d['sources']) - return n, s, d - if __name__ == '__main__': from numpy.distutils.core import setup - setup(**configuration(top_path='', package_name='scipy.stats.models').todict()) + setup(**configuration(top_path='').todict()) + From scipy-svn at scipy.org Fri Aug 8 17:44:54 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 16:44:54 -0500 (CDT) Subject: [Scipy-svn] r4632 - trunk/scipy/stats/models Message-ID: <20080808214454.E6C7A39C021@scipy.org> Author: chris.burns Date: 2008-08-08 16:44:49 -0500 (Fri, 08 Aug 2008) New Revision: 4632 Modified: trunk/scipy/stats/models/info.py Log: Remove reference to weave from info.py Modified: trunk/scipy/stats/models/info.py =================================================================== --- trunk/scipy/stats/models/info.py 2008-08-08 21:43:17 UTC (rev 4631) +++ trunk/scipy/stats/models/info.py 2008-08-08 21:44:49 UTC (rev 4632) @@ -20,8 +20,7 @@ """ __docformat__ = 'restructuredtext en' -depends = ['weave', - 'special.orthogonal', +depends = ['special.orthogonal', 'integrate', 'optimize', 'linalg'] From scipy-svn at scipy.org Fri Aug 8 22:32:01 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 8 Aug 2008 21:32:01 -0500 (CDT) Subject: [Scipy-svn] r4633 - branches Message-ID: <20080809023201.1243A39C021@scipy.org> Author: chris.burns Date: 2008-08-08 21:31:58 -0500 (Fri, 08 Aug 2008) New Revision: 4633 Removed: branches/stats_models/ Log: Remove merged branch for stats.models. From scipy-svn at scipy.org Sat Aug 9 15:29:49 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Sat, 9 Aug 2008 14:29:49 -0500 (CDT) Subject: [Scipy-svn] r4634 - in trunk/scipy/ndimage/src: . register segment Message-ID: <20080809192949.DDA2439C05F@scipy.org> Author: cdavid Date: 2008-08-09 14:29:36 -0500 (Sat, 09 Aug 2008) New Revision: 4634 Modified: trunk/scipy/ndimage/src/nd_image.c trunk/scipy/ndimage/src/nd_image.h trunk/scipy/ndimage/src/ni_filters.c trunk/scipy/ndimage/src/ni_filters.h trunk/scipy/ndimage/src/ni_fourier.c trunk/scipy/ndimage/src/ni_fourier.h trunk/scipy/ndimage/src/ni_interpolation.c trunk/scipy/ndimage/src/ni_interpolation.h trunk/scipy/ndimage/src/ni_measure.c trunk/scipy/ndimage/src/ni_measure.h trunk/scipy/ndimage/src/ni_morphology.c trunk/scipy/ndimage/src/ni_morphology.h trunk/scipy/ndimage/src/ni_support.c trunk/scipy/ndimage/src/ni_support.h trunk/scipy/ndimage/src/register/Register_EXT.c trunk/scipy/ndimage/src/register/Register_IMPL.c trunk/scipy/ndimage/src/segment/Segmenter_EXT.c trunk/scipy/ndimage/src/segment/Segmenter_IMPL.c trunk/scipy/ndimage/src/segment/ndImage_Segmenter_structs.h Log: Use unix endline in ndimage (windows EOL break some unix compilers.). Modified: trunk/scipy/ndimage/src/nd_image.c =================================================================== --- trunk/scipy/ndimage/src/nd_image.c 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/nd_image.c 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,1320 +1,1320 @@ -/* Copyright (C) 2003-2005 Peter J. Verveer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define ND_IMPORT_ARRAY -#include "nd_image.h" -#undef ND_IMPORT_ARRAY -#include "ni_support.h" -#include "ni_filters.h" -#include "ni_fourier.h" -#include "ni_morphology.h" -#include "ni_interpolation.h" -#include "ni_measure.h" - -typedef struct { - PyObject *function; - PyObject *extra_arguments; - PyObject *extra_keywords; -} NI_PythonCallbackData; - -/* Convert an input array of any type, not necessarily contiguous */ -static int -NI_ObjectToInputArray(PyObject *object, PyArrayObject **array) -{ - *array = NA_InputArray(object, tAny, NPY_ALIGNED|NPY_NOTSWAPPED); - return *array ? 1 : 0; -} - -/* Convert an input array of any type, not necessarily contiguous */ -static int -NI_ObjectToOptionalInputArray(PyObject *object, PyArrayObject **array) -{ - if (object == Py_None) { - *array = NULL; - return 1; - } else { - *array = NA_InputArray(object, tAny, NPY_ALIGNED|NPY_NOTSWAPPED); - return *array ? 1 : 0; - } -} - -/* Convert an output array of any type, not necessarily contiguous */ -static int -NI_ObjectToOutputArray(PyObject *object, PyArrayObject **array) -{ - *array = NA_OutputArray(object, tAny, NPY_ALIGNED|NPY_NOTSWAPPED); - return *array ? 1 : 0; -} - -/* Convert an output array of any type, not necessarily contiguous */ -static int -NI_ObjectToOptionalOutputArray(PyObject *object, PyArrayObject **array) -{ - if (object == Py_None) { - *array = NULL; - return 1; - } else { - *array = NA_OutputArray(object, tAny, NPY_ALIGNED|NPY_NOTSWAPPED); - return *array ? 1 : 0; - } -} - -/* Convert an input/output array of any type, not necessarily contiguous */ -static int -NI_ObjectToIoArray(PyObject *object, PyArrayObject **array) -{ - *array = NA_IoArray(object, tAny, NPY_ALIGNED|NPY_NOTSWAPPED); - return *array ? 1 : 0; -} - -/* Convert an Long sequence */ -static maybelong -NI_ObjectToLongSequenceAndLength(PyObject *object, maybelong **sequence) -{ - long *pa, ii; - PyArrayObject *array = NA_InputArray(object, PyArray_LONG, NPY_CARRAY); - maybelong length = PyArray_SIZE(array); - - *sequence = (maybelong*)malloc(length * sizeof(maybelong)); - if (!*sequence) { - PyErr_NoMemory(); - Py_XDECREF(array); - return -1; - } - pa = (long*)PyArray_DATA(array); - for(ii = 0; ii < length; ii++) - (*sequence)[ii] = pa[ii]; - Py_XDECREF(array); - return length; -} - -static int -NI_ObjectToLongSequence(PyObject *object, maybelong **sequence) -{ - return NI_ObjectToLongSequenceAndLength(object, sequence) >= 0; -} - -/*********************************************************************/ -/* wrapper functions: */ -/*********************************************************************/ - -static PyObject *Py_Correlate1D(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL, *weights = NULL; - int axis, mode; - long origin; - double cval; - - if (!PyArg_ParseTuple(args, "O&O&iO&idl", NI_ObjectToInputArray, &input, - NI_ObjectToInputArray, &weights, &axis, - NI_ObjectToOutputArray, &output, &mode, &cval, &origin)) - goto exit; - if (!NI_Correlate1D(input, weights, axis, output, - (NI_ExtendMode)mode, cval, origin)) - goto exit; -exit: - Py_XDECREF(input); - Py_XDECREF(weights); - Py_XDECREF(output); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static PyObject *Py_Correlate(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL, *weights = NULL; - maybelong *origin = NULL; - int mode; - double cval; - - if (!PyArg_ParseTuple(args, "O&O&O&idO&", NI_ObjectToInputArray, &input, - NI_ObjectToInputArray, &weights, NI_ObjectToOutputArray, &output, - &mode, &cval, NI_ObjectToLongSequence, &origin)) - goto exit; - if (!NI_Correlate(input, weights, output, (NI_ExtendMode)mode, cval, - origin)) - goto exit; -exit: - Py_XDECREF(input); - Py_XDECREF(weights); - Py_XDECREF(output); - if (origin) - free(origin); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static PyObject *Py_UniformFilter1D(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL; - int axis, mode; - long filter_size, origin; - double cval; - - if (!PyArg_ParseTuple(args, "O&liO&idl", NI_ObjectToInputArray, &input, - &filter_size, &axis, NI_ObjectToOutputArray, &output, - &mode, &cval, &origin)) - goto exit; - if (!NI_UniformFilter1D(input, filter_size, axis, output, - (NI_ExtendMode)mode, cval, origin)) - goto exit; -exit: - Py_XDECREF(input); - Py_XDECREF(output); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static PyObject *Py_MinOrMaxFilter1D(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL; - int axis, mode, minimum; - long filter_size, origin; - double cval; - - if (!PyArg_ParseTuple(args, "O&liO&idli", NI_ObjectToInputArray, &input, - &filter_size, &axis, NI_ObjectToOutputArray, &output, - &mode, &cval, &origin, &minimum)) - goto exit; - if (!NI_MinOrMaxFilter1D(input, filter_size, axis, output, - (NI_ExtendMode)mode, cval, origin, minimum)) - goto exit; -exit: - Py_XDECREF(input); - Py_XDECREF(output); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static PyObject *Py_MinOrMaxFilter(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL, *footprint = NULL; - PyArrayObject *structure = NULL; - maybelong *origin = NULL; - int mode, minimum; - double cval; - - if (!PyArg_ParseTuple(args, "O&O&O&O&idO&i", NI_ObjectToInputArray, - &input, NI_ObjectToInputArray, &footprint, - NI_ObjectToOptionalInputArray, &structure, - NI_ObjectToOutputArray, &output, &mode, &cval, - NI_ObjectToLongSequence, &origin, &minimum)) - goto exit; - if (!NI_MinOrMaxFilter(input, footprint, structure, output, - (NI_ExtendMode)mode, cval, origin, minimum)) - goto exit; -exit: - Py_XDECREF(input); - Py_XDECREF(footprint); - Py_XDECREF(structure); - Py_XDECREF(output); - if (origin) - free(origin); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static PyObject *Py_RankFilter(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL, *footprint = NULL; - maybelong *origin = NULL; - int mode, rank; - double cval; - - if (!PyArg_ParseTuple(args, "O&iO&O&idO&", NI_ObjectToInputArray, - &input, &rank, NI_ObjectToInputArray, &footprint, - NI_ObjectToOutputArray, &output, &mode, &cval, - NI_ObjectToLongSequence, &origin)) - goto exit; - if (!NI_RankFilter(input, rank, footprint, output, (NI_ExtendMode)mode, - cval, origin)) - goto exit; -exit: - Py_XDECREF(input); - Py_XDECREF(footprint); - Py_XDECREF(output); - if (origin) - free(origin); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static int Py_Filter1DFunc(double *iline, maybelong ilen, - double *oline, maybelong olen, void *data) -{ - PyArrayObject *py_ibuffer = NULL, *py_obuffer = NULL; - PyObject *rv = NULL, *args = NULL, *tmp = NULL; - maybelong ii; - double *po = NULL; - NI_PythonCallbackData *cbdata = (NI_PythonCallbackData*)data; - - py_ibuffer = NA_NewArray(iline, PyArray_DOUBLE, 1, &ilen); - py_obuffer = NA_NewArray(NULL, PyArray_DOUBLE, 1, &olen); - if (!py_ibuffer || !py_obuffer) - goto exit; - tmp = Py_BuildValue("(OO)", py_ibuffer, py_obuffer); - if (!tmp) - goto exit; - args = PySequence_Concat(tmp, cbdata->extra_arguments); - if (!args) - goto exit; - rv = PyObject_Call(cbdata->function, args, cbdata->extra_keywords); - if (!rv) - goto exit; - po = (double*)PyArray_DATA(py_obuffer); - for(ii = 0; ii < olen; ii++) - oline[ii] = po[ii]; -exit: - Py_XDECREF(py_ibuffer); - Py_XDECREF(py_obuffer); - Py_XDECREF(rv); - Py_XDECREF(args); - Py_XDECREF(tmp); - return PyErr_Occurred() ? 0 : 1; -} - -static PyObject *Py_GenericFilter1D(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL; - PyObject *fnc = NULL, *extra_arguments = NULL, *extra_keywords = NULL; - void *func = Py_Filter1DFunc, *data = NULL; - NI_PythonCallbackData cbdata; - int axis, mode; - long origin, filter_size; - double cval; - - if (!PyArg_ParseTuple(args, "O&OliO&idlOO", NI_ObjectToInputArray, - &input, &fnc, &filter_size, &axis, NI_ObjectToOutputArray, - &output, &mode, &cval, &origin, &extra_arguments, &extra_keywords)) - goto exit; - if (!PyTuple_Check(extra_arguments)) { - PyErr_SetString(PyExc_RuntimeError, - "extra_arguments must be a tuple"); - goto exit; - } - if (!PyDict_Check(extra_keywords)) { - PyErr_SetString(PyExc_RuntimeError, - "extra_keywords must be a dictionary"); - goto exit; - } - if (PyCObject_Check(fnc)) { - func = PyCObject_AsVoidPtr(fnc); - data = PyCObject_GetDesc(fnc); - } else if (PyCallable_Check(fnc)) { - cbdata.function = fnc; - cbdata.extra_arguments = extra_arguments; - cbdata.extra_keywords = extra_keywords; - data = (void*)&cbdata; - } else { - PyErr_SetString(PyExc_RuntimeError, - "function parameter is not callable"); - goto exit; - } - if (!NI_GenericFilter1D(input, func, data, filter_size, axis, output, - (NI_ExtendMode)mode, cval, origin)) - goto exit; -exit: - Py_XDECREF(input); - Py_XDECREF(output); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static int Py_FilterFunc(double *buffer, maybelong filter_size, - double *output, void *data) -{ - PyArrayObject *py_buffer = NULL; - PyObject *rv = NULL, *args = NULL, *tmp = NULL; - NI_PythonCallbackData *cbdata = (NI_PythonCallbackData*)data; - - py_buffer = NA_NewArray(buffer, PyArray_DOUBLE, 1, &filter_size); - if (!py_buffer) - goto exit; - tmp = Py_BuildValue("(O)", py_buffer); - if (!tmp) - goto exit; - args = PySequence_Concat(tmp, cbdata->extra_arguments); - if (!args) - goto exit; - rv = PyObject_Call(cbdata->function, args, cbdata->extra_keywords); - if (!rv) - goto exit; - *output = PyFloat_AsDouble(rv); -exit: - Py_XDECREF(py_buffer); - Py_XDECREF(rv); - Py_XDECREF(args); - Py_XDECREF(tmp); - return PyErr_Occurred() ? 0 : 1; -} - -static PyObject *Py_GenericFilter(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL, *footprint = NULL; - PyObject *fnc = NULL, *extra_arguments = NULL, *extra_keywords = NULL; - void *func = Py_FilterFunc, *data = NULL; - NI_PythonCallbackData cbdata; - int mode; - maybelong *origin = NULL; - double cval; - - if (!PyArg_ParseTuple(args, "O&OO&O&idO&OO", NI_ObjectToInputArray, - &input, &fnc, NI_ObjectToInputArray, &footprint, - NI_ObjectToOutputArray, &output, &mode, &cval, - NI_ObjectToLongSequence, &origin, - &extra_arguments, &extra_keywords)) - goto exit; - if (!PyTuple_Check(extra_arguments)) { - PyErr_SetString(PyExc_RuntimeError, - "extra_arguments must be a tuple"); - goto exit; - } - if (!PyDict_Check(extra_keywords)) { - PyErr_SetString(PyExc_RuntimeError, - "extra_keywords must be a dictionary"); - goto exit; - } - if (PyCObject_Check(fnc)) { - func = PyCObject_AsVoidPtr(fnc); - data = PyCObject_GetDesc(fnc); - } else if (PyCallable_Check(fnc)) { - cbdata.function = fnc; - cbdata.extra_arguments = extra_arguments; - cbdata.extra_keywords = extra_keywords; - data = (void*)&cbdata; - } else { - PyErr_SetString(PyExc_RuntimeError, - "function parameter is not callable"); - goto exit; - } - if (!NI_GenericFilter(input, func, data, footprint, output, - (NI_ExtendMode)mode, cval, origin)) - goto exit; -exit: - Py_XDECREF(input); - Py_XDECREF(output); - Py_XDECREF(footprint); - if (origin) - free(origin); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static PyObject *Py_FourierFilter(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL, *parameters = NULL; - int axis, filter_type; - long n; - - if (!PyArg_ParseTuple(args, "O&O&liO&i", NI_ObjectToInputArray, &input, - NI_ObjectToInputArray, ¶meters, &n, &axis, - NI_ObjectToOutputArray, &output, &filter_type)) - goto exit; - - if (!NI_FourierFilter(input, parameters, n, axis, output, filter_type)) - goto exit; - -exit: - Py_XDECREF(input); - Py_XDECREF(parameters); - Py_XDECREF(output); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static PyObject *Py_FourierShift(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL, *shifts = NULL; - int axis; - long n; - - if (!PyArg_ParseTuple(args, "O&O&liO&", NI_ObjectToInputArray, &input, - NI_ObjectToInputArray, &shifts, &n, &axis, - NI_ObjectToOutputArray, &output)) - goto exit; - - if (!NI_FourierShift(input, shifts, n, axis, output)) - goto exit; - -exit: - Py_XDECREF(input); - Py_XDECREF(shifts); - Py_XDECREF(output); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static PyObject *Py_SplineFilter1D(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL; - int axis, order; - - if (!PyArg_ParseTuple(args, "O&iiO&", NI_ObjectToInputArray, &input, - &order, &axis, NI_ObjectToOutputArray, &output)) - goto exit; - - if (!NI_SplineFilter1D(input, order, axis, output)) - goto exit; - -exit: - Py_XDECREF(input); - Py_XDECREF(output); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static int Py_Map(maybelong *ocoor, double* icoor, int orank, int irank, - void *data) -{ - PyObject *coors = NULL, *rets = NULL, *args = NULL, *tmp = NULL; - maybelong ii; - NI_PythonCallbackData *cbdata = (NI_PythonCallbackData*)data; - - coors = PyTuple_New(orank); - if (!coors) - goto exit; - for(ii = 0; ii < orank; ii++) { - PyTuple_SetItem(coors, ii, PyInt_FromLong(ocoor[ii])); - if (PyErr_Occurred()) - goto exit; - } - tmp = Py_BuildValue("(O)", coors); - if (!tmp) - goto exit; - args = PySequence_Concat(tmp, cbdata->extra_arguments); - if (!args) - goto exit; - rets = PyObject_Call(cbdata->function, args, cbdata->extra_keywords); - if (!rets) - goto exit; - for(ii = 0; ii < irank; ii++) { - icoor[ii] = PyFloat_AsDouble(PyTuple_GetItem(rets, ii)); - if (PyErr_Occurred()) - goto exit; - } -exit: - Py_XDECREF(coors); - Py_XDECREF(tmp); - Py_XDECREF(rets); - Py_XDECREF(args); - return PyErr_Occurred() ? 0 : 1; -} - - -static PyObject *Py_GeometricTransform(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL; - PyArrayObject *coordinates = NULL, *matrix = NULL, *shift = NULL; - PyObject *fnc = NULL, *extra_arguments = NULL, *extra_keywords = NULL; - int mode, order; - double cval; - void *func = NULL, *data = NULL; - NI_PythonCallbackData cbdata; - - if (!PyArg_ParseTuple(args, "O&OO&O&O&O&iidOO", NI_ObjectToInputArray, - &input, &fnc, NI_ObjectToOptionalInputArray, - &coordinates, NI_ObjectToOptionalInputArray, - &matrix, NI_ObjectToOptionalInputArray, &shift, - NI_ObjectToOutputArray, &output, &order, &mode, - &cval, &extra_arguments, &extra_keywords)) - goto exit; - - if (fnc != Py_None) { - if (!PyTuple_Check(extra_arguments)) { - PyErr_SetString(PyExc_RuntimeError, - "extra_arguments must be a tuple"); - goto exit; - } - if (!PyDict_Check(extra_keywords)) { - PyErr_SetString(PyExc_RuntimeError, - "extra_keywords must be a dictionary"); - goto exit; - } - if (PyCObject_Check(fnc)) { - func = PyCObject_AsVoidPtr(fnc); - data = PyCObject_GetDesc(fnc); - } else if (PyCallable_Check(fnc)) { - func = Py_Map; - cbdata.function = fnc; - cbdata.extra_arguments = extra_arguments; - cbdata.extra_keywords = extra_keywords; - data = (void*)&cbdata; - } else { - PyErr_SetString(PyExc_RuntimeError, - "function parameter is not callable"); - goto exit; - } - } - - if (!NI_GeometricTransform(input, func, data, matrix, shift, coordinates, - output, order, (NI_ExtendMode)mode, cval)) - goto exit; - -exit: - Py_XDECREF(input); - Py_XDECREF(output); - Py_XDECREF(coordinates); - Py_XDECREF(matrix); - Py_XDECREF(shift); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static PyObject *Py_ZoomShift(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL, *shift = NULL; - PyArrayObject *zoom = NULL; - int mode, order; - double cval; - - if (!PyArg_ParseTuple(args, "O&O&O&O&iid", NI_ObjectToInputArray, - &input, NI_ObjectToOptionalInputArray, &zoom, - NI_ObjectToOptionalInputArray, &shift, NI_ObjectToOutputArray, - &output, &order, &mode, &cval)) - goto exit; - - if (!NI_ZoomShift(input, zoom, shift, output, order, (NI_ExtendMode)mode, - cval)) - goto exit; - -exit: - Py_XDECREF(input); - Py_XDECREF(shift); - Py_XDECREF(zoom); - Py_XDECREF(output); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static PyObject *Py_Label(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL, *strct = NULL; - maybelong max_label; - - if (!PyArg_ParseTuple(args, "O&O&O&", NI_ObjectToInputArray, &input, - NI_ObjectToInputArray, &strct, NI_ObjectToOutputArray, &output)) - goto exit; - - if (!NI_Label(input, strct, &max_label, output)) - goto exit; - -exit: - Py_XDECREF(input); - Py_XDECREF(strct); - Py_XDECREF(output); - return PyErr_Occurred() ? NULL : Py_BuildValue("l", (long)max_label); -} - -static PyObject *Py_FindObjects(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL; - PyObject *result = NULL, *tuple = NULL, *start = NULL, *end = NULL; - PyObject *slc = NULL; - int jj; - long max_label; - maybelong ii, *regions = NULL; - - if (!PyArg_ParseTuple(args, "O&l", NI_ObjectToInputArray, &input, - &max_label)) - goto exit; - - if (max_label < 0) - max_label = 0; - if (max_label > 0) { - if (input->nd > 0) { - regions = (maybelong*)malloc(2 * max_label * input->nd * - sizeof(maybelong)); - } else { - regions = (maybelong*)malloc(max_label * sizeof(maybelong)); - } - if (!regions) { - PyErr_NoMemory(); - goto exit; - } - } - - if (!NI_FindObjects(input, max_label, regions)) - goto exit; - - result = PyList_New(max_label); - if (!result) { - PyErr_NoMemory(); - goto exit; - } - - for(ii = 0; ii < max_label; ii++) { - maybelong idx = input->nd > 0 ? 2 * input->nd * ii : ii; - if (regions[idx] >= 0) { - PyObject *tuple = PyTuple_New(input->nd); - if (!tuple) { - PyErr_NoMemory(); - goto exit; - } - for(jj = 0; jj < input->nd; jj++) { - start = PyInt_FromLong(regions[idx + jj]); - end = PyInt_FromLong(regions[idx + jj + input->nd]); - if (!start || !end) { - PyErr_NoMemory(); - goto exit; - } - slc = PySlice_New(start, end, NULL); - if (!slc) { - PyErr_NoMemory(); - goto exit; - } - Py_XDECREF(start); - Py_XDECREF(end); - start = end = NULL; - PyTuple_SetItem(tuple, jj, slc); - slc = NULL; - } - PyList_SetItem(result, ii, tuple); - tuple = NULL; - } else { - Py_INCREF(Py_None); - PyList_SetItem(result, ii, Py_None); - } - } - - Py_INCREF(result); - - exit: - Py_XDECREF(input); - Py_XDECREF(result); - Py_XDECREF(tuple); - Py_XDECREF(start); - Py_XDECREF(end); - Py_XDECREF(slc); - if (regions) - free(regions); - if (PyErr_Occurred()) { - Py_XDECREF(result); - return NULL; - } else { - return result; - } -} - -static PyObject *Py_WatershedIFT(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL, *markers = NULL; - PyArrayObject *strct = NULL; - - if (!PyArg_ParseTuple(args, "O&O&O&O&", NI_ObjectToInputArray, &input, - NI_ObjectToInputArray, &markers, NI_ObjectToInputArray, - &strct, NI_ObjectToOutputArray, &output)) - goto exit; - - if (!NI_WatershedIFT(input, markers, strct, output)) - goto exit; - -exit: - Py_XDECREF(input); - Py_XDECREF(markers); - Py_XDECREF(strct); - Py_XDECREF(output); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static int _NI_GetIndices(PyObject* indices_object, - maybelong** result_indices, maybelong* min_label, - maybelong* max_label, maybelong* n_results) -{ - maybelong *indices = NULL, n_indices, ii; - - if (indices_object == Py_None) { - *min_label = -1; - *n_results = 1; - } else { - n_indices = NI_ObjectToLongSequenceAndLength(indices_object, &indices); - if (n_indices < 0) - goto exit; - if (n_indices < 1) { - PyErr_SetString(PyExc_RuntimeError, "no correct indices provided"); - goto exit; - } else { - *min_label = *max_label = indices[0]; - if (*min_label < 0) { - PyErr_SetString(PyExc_RuntimeError, - "negative indices not allowed"); - goto exit; - } - for(ii = 1; ii < n_indices; ii++) { - if (indices[ii] < 0) { - PyErr_SetString(PyExc_RuntimeError, - "negative indices not allowed"); - goto exit; - } - if (indices[ii] < *min_label) - *min_label = indices[ii]; - if (indices[ii] > *max_label) - *max_label = indices[ii]; - } - *result_indices = (maybelong*)malloc((*max_label - *min_label + 1) * - sizeof(maybelong)); - if (!*result_indices) { - PyErr_NoMemory(); - goto exit; - } - for(ii = 0; ii < *max_label - *min_label + 1; ii++) - (*result_indices)[ii] = -1; - *n_results = 0; - for(ii = 0; ii < n_indices; ii++) { - if ((*result_indices)[indices[ii] - *min_label] >= 0) { - PyErr_SetString(PyExc_RuntimeError, "duplicate index"); - goto exit; - } - (*result_indices)[indices[ii] - *min_label] = ii; - ++(*n_results); - } - } - } - exit: - if (indices) - free(indices); - return PyErr_Occurred() == NULL; -} - - -PyObject* _NI_BuildMeasurementResultArrayObject(maybelong n_results, - PyArrayObject** values) -{ - PyObject *result = NULL; - if (n_results > 1) { - result = PyList_New(n_results); - if (result) { - maybelong ii; - for(ii = 0; ii < n_results; ii++) { - PyList_SET_ITEM(result, ii, (PyObject*)values[ii]); - Py_XINCREF(values[ii]); - } - } - } else { - result = (PyObject*)values[0]; - Py_XINCREF(values[0]); - } - return result; -} - - -PyObject* _NI_BuildMeasurementResultDouble(maybelong n_results, - double* values) -{ - PyObject *result = NULL; - if (n_results > 1) { - result = PyList_New(n_results); - if (result) { - int ii; - for(ii = 0; ii < n_results; ii++) { - PyObject* val = PyFloat_FromDouble(values[ii]); - if (!val) { - Py_XDECREF(result); - return NULL; - } - PyList_SET_ITEM(result, ii, val); - } - } - } else { - result = Py_BuildValue("d", values[0]); - } - return result; -} - - -PyObject* _NI_BuildMeasurementResultDoubleTuple(maybelong n_results, - int tuple_size, double* values) -{ - PyObject *result = NULL; - maybelong ii; - int jj; - - if (n_results > 1) { - result = PyList_New(n_results); - if (result) { - for(ii = 0; ii < n_results; ii++) { - PyObject* val = PyTuple_New(tuple_size); - if (!val) { - Py_XDECREF(result); - return NULL; - } - for(jj = 0; jj < tuple_size; jj++) { - maybelong idx = jj + ii * tuple_size; - PyTuple_SetItem(val, jj, PyFloat_FromDouble(values[idx])); - if (PyErr_Occurred()) { - Py_XDECREF(result); - return NULL; - } - } - PyList_SET_ITEM(result, ii, val); - } - } - } else { - result = PyTuple_New(tuple_size); - if (result) { - for(ii = 0; ii < tuple_size; ii++) { - PyTuple_SetItem(result, ii, PyFloat_FromDouble(values[ii])); - if (PyErr_Occurred()) { - Py_XDECREF(result); - return NULL; - } - } - } - } - return result; -} - - -PyObject* _NI_BuildMeasurementResultInt(maybelong n_results, - maybelong* values) -{ - PyObject *result = NULL; - if (n_results > 1) { - result = PyList_New(n_results); - if (result) { - maybelong ii; - for(ii = 0; ii < n_results; ii++) { - PyObject* val = PyInt_FromLong(values[ii]); - if (!val) { - Py_XDECREF(result); - return NULL; - } - PyList_SET_ITEM(result, ii, val); - } - } - } else { - result = Py_BuildValue("l", values[0]); - } - return result; -} - - -static PyObject *Py_Statistics(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *labels = NULL; - PyObject *indices_object, *result = NULL; - PyObject *res1 = NULL, *res2 = NULL, *res3 = NULL, *res4 = NULL; - double *dresult1 = NULL, *dresult2 = NULL; - maybelong *lresult1 = NULL, *lresult2 = NULL; - maybelong min_label, max_label, *result_indices = NULL, n_results, ii; - int type; - - if (!PyArg_ParseTuple(args, "O&O&Oi", NI_ObjectToInputArray, &input, - NI_ObjectToOptionalInputArray, &labels, &indices_object, &type)) - goto exit; - - if (!_NI_GetIndices(indices_object, &result_indices, &min_label, - &max_label, &n_results)) - goto exit; - - if (type >= 0 && type <= 7) { - dresult1 = (double*)malloc(n_results * sizeof(double)); - if (!dresult1) { - PyErr_NoMemory(); - goto exit; - } - } - if (type == 2 || type == 7) { - dresult2 = (double*)malloc(n_results * sizeof(double)); - if (!dresult2) { - PyErr_NoMemory(); - goto exit; - } - } - if (type == 1 || type == 2 || (type >= 5 && type <= 7)) { - lresult1 = (maybelong*)malloc(n_results * sizeof(maybelong)); - if (!lresult1) { - PyErr_NoMemory(); - goto exit; - } - } - if (type == 7) { - lresult2 = (maybelong*)malloc(n_results * sizeof(maybelong)); - if (!lresult2) { - PyErr_NoMemory(); - goto exit; - } - } - switch(type) { - case 0: - if (!NI_Statistics(input, labels, min_label, max_label, result_indices, - n_results, dresult1, NULL, NULL, NULL, NULL, NULL, NULL)) - goto exit; - result = _NI_BuildMeasurementResultDouble(n_results, dresult1); - break; - case 1: - if (!NI_Statistics(input, labels, min_label, max_label, result_indices, - n_results, dresult1, lresult1, NULL, NULL, NULL, NULL, NULL)) - goto exit; - for(ii = 0; ii < n_results; ii++) - dresult1[ii] = lresult1[ii] > 0 ? dresult1[ii] / lresult1[ii] : 0.0; - - result = _NI_BuildMeasurementResultDouble(n_results, dresult1); - break; - case 2: - if (!NI_Statistics(input, labels, min_label, max_label, result_indices, - n_results, dresult1, lresult1, dresult2, NULL, NULL, NULL, NULL)) - goto exit; - result = _NI_BuildMeasurementResultDouble(n_results, dresult2); - break; - case 3: - if (!NI_Statistics(input, labels, min_label, max_label, result_indices, - n_results, NULL, NULL, NULL, dresult1, NULL, NULL, NULL)) - goto exit; - result = _NI_BuildMeasurementResultDouble(n_results, dresult1); - break; - case 4: - if (!NI_Statistics(input, labels, min_label, max_label, result_indices, - n_results, NULL, NULL, NULL, NULL, dresult1, NULL, NULL)) - goto exit; - result = _NI_BuildMeasurementResultDouble(n_results, dresult1); - break; - case 5: - if (!NI_Statistics(input, labels, min_label, max_label, result_indices, - n_results, NULL, NULL, NULL, dresult1, NULL, lresult1, NULL)) - goto exit; - result = _NI_BuildMeasurementResultInt(n_results, lresult1); - break; - case 6: - if (!NI_Statistics(input, labels, min_label, max_label, result_indices, - n_results, NULL, NULL, NULL, NULL, dresult1, NULL, lresult1)) - goto exit; - result = _NI_BuildMeasurementResultInt(n_results, lresult1); - break; - case 7: - if (!NI_Statistics(input, labels, min_label, max_label, result_indices, - n_results, NULL, NULL, NULL, dresult1, dresult2, - lresult1, lresult2)) - goto exit; - res1 = _NI_BuildMeasurementResultDouble(n_results, dresult1); - res2 = _NI_BuildMeasurementResultDouble(n_results, dresult2); - res3 = _NI_BuildMeasurementResultInt(n_results, lresult1); - res4 = _NI_BuildMeasurementResultInt(n_results, lresult2); - if (!res1 || !res2 || !res3 || !res4) - goto exit; - result = Py_BuildValue("OOOO", res1, res2, res3, res4); - break; - default: - PyErr_SetString(PyExc_RuntimeError, "operation not supported"); - goto exit; - } - - exit: - Py_XDECREF(input); - Py_XDECREF(labels); - if (result_indices) - free(result_indices); - if (dresult1) - free(dresult1); - if (dresult2) - free(dresult2); - if (lresult1) - free(lresult1); - if (lresult2) - free(lresult2); - return result; -} - - -static PyObject *Py_CenterOfMass(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *labels = NULL; - PyObject *indices_object, *result = NULL; - double *center_of_mass = NULL; - maybelong min_label, max_label, *result_indices = NULL, n_results; - - if (!PyArg_ParseTuple(args, "O&O&O", NI_ObjectToInputArray, &input, - NI_ObjectToOptionalInputArray, &labels, &indices_object)) - goto exit; - - if (!_NI_GetIndices(indices_object, &result_indices, &min_label, - &max_label, &n_results)) - goto exit; - - center_of_mass = (double*)malloc(input->nd * n_results * - sizeof(double)); - if (!center_of_mass) { - PyErr_NoMemory(); - goto exit; - } - - if (!NI_CenterOfMass(input, labels, min_label, max_label, - result_indices, n_results, center_of_mass)) - goto exit; - - result = _NI_BuildMeasurementResultDoubleTuple(n_results, input->nd, - center_of_mass); - - exit: - Py_XDECREF(input); - Py_XDECREF(labels); - if (result_indices) - free(result_indices); - if (center_of_mass) - free(center_of_mass); - return result; -} - -static PyObject *Py_Histogram(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *labels = NULL, **histograms = NULL; - PyObject *indices_object, *result = NULL; - maybelong min_label, max_label, *result_indices = NULL, n_results; - maybelong jj, nbins; - long nbins_in; - double min, max; - - if (!PyArg_ParseTuple(args, "O&ddlO&O", NI_ObjectToInputArray, &input, - &min, &max, &nbins_in, NI_ObjectToOptionalInputArray, - &labels, &indices_object)) - goto exit; - nbins = nbins_in; - - if (!_NI_GetIndices(indices_object, &result_indices, &min_label, - &max_label, &n_results)) - goto exit; - - /* Set all pointers to NULL, so that freeing the memory */ - /* doesn't cause problems. */ - histograms = (PyArrayObject**)calloc(input->nd * n_results, - sizeof(PyArrayObject*)); - if (!histograms) { - PyErr_NoMemory(); - goto exit; - } - for(jj = 0; jj < n_results; jj++) { - histograms[jj] = NA_NewArray(NULL, tInt32, 1, &nbins); - if (!histograms[jj]) { - PyErr_NoMemory(); - goto exit; - } - } - - if (!NI_Histogram(input, labels, min_label, max_label, result_indices, - n_results, histograms, min, max, nbins)) - goto exit; - - result = _NI_BuildMeasurementResultArrayObject(n_results, histograms); - - exit: - Py_XDECREF(input); - Py_XDECREF(labels); - if (result_indices) - free(result_indices); - if (histograms) { - for(jj = 0; jj < n_results; jj++) { - Py_XDECREF(histograms[jj]); - } - free(histograms); - } - return result; -} - -static PyObject *Py_DistanceTransformBruteForce(PyObject *obj, - PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL, *features = NULL; - PyArrayObject *sampling = NULL; - int metric; - - if (!PyArg_ParseTuple(args, "O&iO&O&O&", NI_ObjectToInputArray, &input, - &metric, NI_ObjectToOptionalInputArray, &sampling, - NI_ObjectToOptionalOutputArray, &output, - NI_ObjectToOptionalOutputArray, &features)) - goto exit; - if (!NI_DistanceTransformBruteForce(input, metric, sampling, - output, features)) - goto exit; -exit: - Py_XDECREF(input); - Py_XDECREF(sampling); - Py_XDECREF(output); - Py_XDECREF(features); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static PyObject *Py_DistanceTransformOnePass(PyObject *obj, PyObject *args) -{ - PyArrayObject *strct = NULL, *distances = NULL, *features = NULL; - - if (!PyArg_ParseTuple(args, "O&O&O&", NI_ObjectToInputArray, &strct, - NI_ObjectToIoArray, &distances, - NI_ObjectToOptionalOutputArray, &features)) - goto exit; - if (!NI_DistanceTransformOnePass(strct, distances, features)) - goto exit; -exit: - Py_XDECREF(strct); - Py_XDECREF(distances); - Py_XDECREF(features); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static PyObject *Py_EuclideanFeatureTransform(PyObject *obj, - PyObject *args) -{ - PyArrayObject *input = NULL, *features = NULL, *sampling = NULL; - - if (!PyArg_ParseTuple(args, "O&O&O&", NI_ObjectToInputArray, &input, - NI_ObjectToOptionalInputArray, &sampling, - NI_ObjectToOutputArray, &features)) - goto exit; - if (!NI_EuclideanFeatureTransform(input, sampling, features)) - goto exit; -exit: - Py_XDECREF(input); - Py_XDECREF(sampling); - Py_XDECREF(features); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static void _FreeCoordinateList(void* ptr) -{ - NI_FreeCoordinateList((NI_CoordinateList*)ptr); -} - -static PyObject *Py_BinaryErosion(PyObject *obj, PyObject *args) -{ - PyArrayObject *input = NULL, *output = NULL, *strct = NULL; - PyArrayObject *mask = NULL; - PyObject *cobj = NULL; - int border_value, invert, center_is_true; - int changed = 0, return_coordinates; - NI_CoordinateList *coordinate_list = NULL; - maybelong *origins = NULL; - - if (!PyArg_ParseTuple(args, "O&O&O&O&iO&iii", NI_ObjectToInputArray, - &input, NI_ObjectToInputArray, &strct, - NI_ObjectToOptionalInputArray, &mask, - NI_ObjectToOutputArray, &output, &border_value, - NI_ObjectToLongSequence, &origins, &invert, - ¢er_is_true, &return_coordinates)) - goto exit; - if (!NI_BinaryErosion(input, strct, mask, output, border_value, - origins, invert, center_is_true, &changed, - return_coordinates ? &coordinate_list : NULL)) - goto exit; - if (return_coordinates) { - cobj = PyCObject_FromVoidPtr(coordinate_list, _FreeCoordinateList); - } -exit: - Py_XDECREF(input); - Py_XDECREF(strct); - Py_XDECREF(mask); - Py_XDECREF(output); - if (origins) - free(origins); - if (PyErr_Occurred()) { - Py_XDECREF(cobj); - return NULL; - } else { - if (return_coordinates) { - return Py_BuildValue("iN", changed, cobj); - } else { - return Py_BuildValue("i", changed); - } - } -} - -static PyObject *Py_BinaryErosion2(PyObject *obj, PyObject *args) -{ - PyArrayObject *array = NULL, *strct = NULL, *mask = NULL; - PyObject *cobj = NULL; - int invert, niter; - maybelong *origins = NULL; - - if (!PyArg_ParseTuple(args, "O&O&O&iO&iO", NI_ObjectToIoArray, &array, - NI_ObjectToInputArray, &strct, NI_ObjectToOptionalInputArray, - &mask, &niter, NI_ObjectToLongSequence, &origins, &invert, - &cobj)) - goto exit; - - if (PyCObject_Check(cobj)) { - NI_CoordinateList *cobj_data = PyCObject_AsVoidPtr(cobj); - if (!NI_BinaryErosion2(array, strct, mask, niter, origins, invert, - &cobj_data)) - goto exit; - } else { - PyErr_SetString(PyExc_RuntimeError, "cannot convert CObject"); - goto exit; - } -exit: - Py_XDECREF(array); - Py_XDECREF(strct); - Py_XDECREF(mask); - if (origins) free(origins); - return PyErr_Occurred() ? NULL : Py_BuildValue(""); -} - -static PyMethodDef methods[] = { - {"correlate1d", (PyCFunction)Py_Correlate1D, - METH_VARARGS, NULL}, - {"correlate", (PyCFunction)Py_Correlate, - METH_VARARGS, NULL}, - {"uniform_filter1d", (PyCFunction)Py_UniformFilter1D, - METH_VARARGS, NULL}, - {"min_or_max_filter1d", (PyCFunction)Py_MinOrMaxFilter1D, - METH_VARARGS, NULL}, - {"min_or_max_filter", (PyCFunction)Py_MinOrMaxFilter, - METH_VARARGS, NULL}, - {"rank_filter", (PyCFunction)Py_RankFilter, - METH_VARARGS, NULL}, - {"generic_filter", (PyCFunction)Py_GenericFilter, - METH_VARARGS, NULL}, - {"generic_filter1d", (PyCFunction)Py_GenericFilter1D, - METH_VARARGS, NULL}, - {"fourier_filter", (PyCFunction)Py_FourierFilter, - METH_VARARGS, NULL}, - {"fourier_shift", (PyCFunction)Py_FourierShift, - METH_VARARGS, NULL}, - {"spline_filter1d", (PyCFunction)Py_SplineFilter1D, - METH_VARARGS, NULL}, - {"geometric_transform", (PyCFunction)Py_GeometricTransform, - METH_VARARGS, NULL}, - {"zoom_shift", (PyCFunction)Py_ZoomShift, - METH_VARARGS, NULL}, - {"label", (PyCFunction)Py_Label, - METH_VARARGS, NULL}, - {"find_objects", (PyCFunction)Py_FindObjects, - METH_VARARGS, NULL}, - {"watershed_ift", (PyCFunction)Py_WatershedIFT, - METH_VARARGS, NULL}, - {"statistics", (PyCFunction)Py_Statistics, - METH_VARARGS, NULL}, - {"center_of_mass", (PyCFunction)Py_CenterOfMass, - METH_VARARGS, NULL}, - {"histogram", (PyCFunction)Py_Histogram, - METH_VARARGS, NULL}, - {"distance_transform_bf", (PyCFunction)Py_DistanceTransformBruteForce, - METH_VARARGS, NULL}, - {"distance_transform_op", (PyCFunction)Py_DistanceTransformOnePass, - METH_VARARGS, NULL}, - {"euclidean_feature_transform", - (PyCFunction)Py_EuclideanFeatureTransform, - METH_VARARGS, NULL}, - {"binary_erosion", (PyCFunction)Py_BinaryErosion, - METH_VARARGS, NULL}, - {"binary_erosion2", (PyCFunction)Py_BinaryErosion2, - METH_VARARGS, NULL}, - {NULL, NULL, 0, NULL} -}; - -PyMODINIT_FUNC init_nd_image(void) -{ - Py_InitModule("_nd_image", methods); - import_array(); -} +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define ND_IMPORT_ARRAY +#include "nd_image.h" +#undef ND_IMPORT_ARRAY +#include "ni_support.h" +#include "ni_filters.h" +#include "ni_fourier.h" +#include "ni_morphology.h" +#include "ni_interpolation.h" +#include "ni_measure.h" + +typedef struct { + PyObject *function; + PyObject *extra_arguments; + PyObject *extra_keywords; +} NI_PythonCallbackData; + +/* Convert an input array of any type, not necessarily contiguous */ +static int +NI_ObjectToInputArray(PyObject *object, PyArrayObject **array) +{ + *array = NA_InputArray(object, tAny, NPY_ALIGNED|NPY_NOTSWAPPED); + return *array ? 1 : 0; +} + +/* Convert an input array of any type, not necessarily contiguous */ +static int +NI_ObjectToOptionalInputArray(PyObject *object, PyArrayObject **array) +{ + if (object == Py_None) { + *array = NULL; + return 1; + } else { + *array = NA_InputArray(object, tAny, NPY_ALIGNED|NPY_NOTSWAPPED); + return *array ? 1 : 0; + } +} + +/* Convert an output array of any type, not necessarily contiguous */ +static int +NI_ObjectToOutputArray(PyObject *object, PyArrayObject **array) +{ + *array = NA_OutputArray(object, tAny, NPY_ALIGNED|NPY_NOTSWAPPED); + return *array ? 1 : 0; +} + +/* Convert an output array of any type, not necessarily contiguous */ +static int +NI_ObjectToOptionalOutputArray(PyObject *object, PyArrayObject **array) +{ + if (object == Py_None) { + *array = NULL; + return 1; + } else { + *array = NA_OutputArray(object, tAny, NPY_ALIGNED|NPY_NOTSWAPPED); + return *array ? 1 : 0; + } +} + +/* Convert an input/output array of any type, not necessarily contiguous */ +static int +NI_ObjectToIoArray(PyObject *object, PyArrayObject **array) +{ + *array = NA_IoArray(object, tAny, NPY_ALIGNED|NPY_NOTSWAPPED); + return *array ? 1 : 0; +} + +/* Convert an Long sequence */ +static maybelong +NI_ObjectToLongSequenceAndLength(PyObject *object, maybelong **sequence) +{ + long *pa, ii; + PyArrayObject *array = NA_InputArray(object, PyArray_LONG, NPY_CARRAY); + maybelong length = PyArray_SIZE(array); + + *sequence = (maybelong*)malloc(length * sizeof(maybelong)); + if (!*sequence) { + PyErr_NoMemory(); + Py_XDECREF(array); + return -1; + } + pa = (long*)PyArray_DATA(array); + for(ii = 0; ii < length; ii++) + (*sequence)[ii] = pa[ii]; + Py_XDECREF(array); + return length; +} + +static int +NI_ObjectToLongSequence(PyObject *object, maybelong **sequence) +{ + return NI_ObjectToLongSequenceAndLength(object, sequence) >= 0; +} + +/*********************************************************************/ +/* wrapper functions: */ +/*********************************************************************/ + +static PyObject *Py_Correlate1D(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *weights = NULL; + int axis, mode; + long origin; + double cval; + + if (!PyArg_ParseTuple(args, "O&O&iO&idl", NI_ObjectToInputArray, &input, + NI_ObjectToInputArray, &weights, &axis, + NI_ObjectToOutputArray, &output, &mode, &cval, &origin)) + goto exit; + if (!NI_Correlate1D(input, weights, axis, output, + (NI_ExtendMode)mode, cval, origin)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(weights); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_Correlate(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *weights = NULL; + maybelong *origin = NULL; + int mode; + double cval; + + if (!PyArg_ParseTuple(args, "O&O&O&idO&", NI_ObjectToInputArray, &input, + NI_ObjectToInputArray, &weights, NI_ObjectToOutputArray, &output, + &mode, &cval, NI_ObjectToLongSequence, &origin)) + goto exit; + if (!NI_Correlate(input, weights, output, (NI_ExtendMode)mode, cval, + origin)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(weights); + Py_XDECREF(output); + if (origin) + free(origin); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_UniformFilter1D(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL; + int axis, mode; + long filter_size, origin; + double cval; + + if (!PyArg_ParseTuple(args, "O&liO&idl", NI_ObjectToInputArray, &input, + &filter_size, &axis, NI_ObjectToOutputArray, &output, + &mode, &cval, &origin)) + goto exit; + if (!NI_UniformFilter1D(input, filter_size, axis, output, + (NI_ExtendMode)mode, cval, origin)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_MinOrMaxFilter1D(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL; + int axis, mode, minimum; + long filter_size, origin; + double cval; + + if (!PyArg_ParseTuple(args, "O&liO&idli", NI_ObjectToInputArray, &input, + &filter_size, &axis, NI_ObjectToOutputArray, &output, + &mode, &cval, &origin, &minimum)) + goto exit; + if (!NI_MinOrMaxFilter1D(input, filter_size, axis, output, + (NI_ExtendMode)mode, cval, origin, minimum)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_MinOrMaxFilter(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *footprint = NULL; + PyArrayObject *structure = NULL; + maybelong *origin = NULL; + int mode, minimum; + double cval; + + if (!PyArg_ParseTuple(args, "O&O&O&O&idO&i", NI_ObjectToInputArray, + &input, NI_ObjectToInputArray, &footprint, + NI_ObjectToOptionalInputArray, &structure, + NI_ObjectToOutputArray, &output, &mode, &cval, + NI_ObjectToLongSequence, &origin, &minimum)) + goto exit; + if (!NI_MinOrMaxFilter(input, footprint, structure, output, + (NI_ExtendMode)mode, cval, origin, minimum)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(footprint); + Py_XDECREF(structure); + Py_XDECREF(output); + if (origin) + free(origin); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_RankFilter(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *footprint = NULL; + maybelong *origin = NULL; + int mode, rank; + double cval; + + if (!PyArg_ParseTuple(args, "O&iO&O&idO&", NI_ObjectToInputArray, + &input, &rank, NI_ObjectToInputArray, &footprint, + NI_ObjectToOutputArray, &output, &mode, &cval, + NI_ObjectToLongSequence, &origin)) + goto exit; + if (!NI_RankFilter(input, rank, footprint, output, (NI_ExtendMode)mode, + cval, origin)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(footprint); + Py_XDECREF(output); + if (origin) + free(origin); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static int Py_Filter1DFunc(double *iline, maybelong ilen, + double *oline, maybelong olen, void *data) +{ + PyArrayObject *py_ibuffer = NULL, *py_obuffer = NULL; + PyObject *rv = NULL, *args = NULL, *tmp = NULL; + maybelong ii; + double *po = NULL; + NI_PythonCallbackData *cbdata = (NI_PythonCallbackData*)data; + + py_ibuffer = NA_NewArray(iline, PyArray_DOUBLE, 1, &ilen); + py_obuffer = NA_NewArray(NULL, PyArray_DOUBLE, 1, &olen); + if (!py_ibuffer || !py_obuffer) + goto exit; + tmp = Py_BuildValue("(OO)", py_ibuffer, py_obuffer); + if (!tmp) + goto exit; + args = PySequence_Concat(tmp, cbdata->extra_arguments); + if (!args) + goto exit; + rv = PyObject_Call(cbdata->function, args, cbdata->extra_keywords); + if (!rv) + goto exit; + po = (double*)PyArray_DATA(py_obuffer); + for(ii = 0; ii < olen; ii++) + oline[ii] = po[ii]; +exit: + Py_XDECREF(py_ibuffer); + Py_XDECREF(py_obuffer); + Py_XDECREF(rv); + Py_XDECREF(args); + Py_XDECREF(tmp); + return PyErr_Occurred() ? 0 : 1; +} + +static PyObject *Py_GenericFilter1D(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL; + PyObject *fnc = NULL, *extra_arguments = NULL, *extra_keywords = NULL; + void *func = Py_Filter1DFunc, *data = NULL; + NI_PythonCallbackData cbdata; + int axis, mode; + long origin, filter_size; + double cval; + + if (!PyArg_ParseTuple(args, "O&OliO&idlOO", NI_ObjectToInputArray, + &input, &fnc, &filter_size, &axis, NI_ObjectToOutputArray, + &output, &mode, &cval, &origin, &extra_arguments, &extra_keywords)) + goto exit; + if (!PyTuple_Check(extra_arguments)) { + PyErr_SetString(PyExc_RuntimeError, + "extra_arguments must be a tuple"); + goto exit; + } + if (!PyDict_Check(extra_keywords)) { + PyErr_SetString(PyExc_RuntimeError, + "extra_keywords must be a dictionary"); + goto exit; + } + if (PyCObject_Check(fnc)) { + func = PyCObject_AsVoidPtr(fnc); + data = PyCObject_GetDesc(fnc); + } else if (PyCallable_Check(fnc)) { + cbdata.function = fnc; + cbdata.extra_arguments = extra_arguments; + cbdata.extra_keywords = extra_keywords; + data = (void*)&cbdata; + } else { + PyErr_SetString(PyExc_RuntimeError, + "function parameter is not callable"); + goto exit; + } + if (!NI_GenericFilter1D(input, func, data, filter_size, axis, output, + (NI_ExtendMode)mode, cval, origin)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static int Py_FilterFunc(double *buffer, maybelong filter_size, + double *output, void *data) +{ + PyArrayObject *py_buffer = NULL; + PyObject *rv = NULL, *args = NULL, *tmp = NULL; + NI_PythonCallbackData *cbdata = (NI_PythonCallbackData*)data; + + py_buffer = NA_NewArray(buffer, PyArray_DOUBLE, 1, &filter_size); + if (!py_buffer) + goto exit; + tmp = Py_BuildValue("(O)", py_buffer); + if (!tmp) + goto exit; + args = PySequence_Concat(tmp, cbdata->extra_arguments); + if (!args) + goto exit; + rv = PyObject_Call(cbdata->function, args, cbdata->extra_keywords); + if (!rv) + goto exit; + *output = PyFloat_AsDouble(rv); +exit: + Py_XDECREF(py_buffer); + Py_XDECREF(rv); + Py_XDECREF(args); + Py_XDECREF(tmp); + return PyErr_Occurred() ? 0 : 1; +} + +static PyObject *Py_GenericFilter(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *footprint = NULL; + PyObject *fnc = NULL, *extra_arguments = NULL, *extra_keywords = NULL; + void *func = Py_FilterFunc, *data = NULL; + NI_PythonCallbackData cbdata; + int mode; + maybelong *origin = NULL; + double cval; + + if (!PyArg_ParseTuple(args, "O&OO&O&idO&OO", NI_ObjectToInputArray, + &input, &fnc, NI_ObjectToInputArray, &footprint, + NI_ObjectToOutputArray, &output, &mode, &cval, + NI_ObjectToLongSequence, &origin, + &extra_arguments, &extra_keywords)) + goto exit; + if (!PyTuple_Check(extra_arguments)) { + PyErr_SetString(PyExc_RuntimeError, + "extra_arguments must be a tuple"); + goto exit; + } + if (!PyDict_Check(extra_keywords)) { + PyErr_SetString(PyExc_RuntimeError, + "extra_keywords must be a dictionary"); + goto exit; + } + if (PyCObject_Check(fnc)) { + func = PyCObject_AsVoidPtr(fnc); + data = PyCObject_GetDesc(fnc); + } else if (PyCallable_Check(fnc)) { + cbdata.function = fnc; + cbdata.extra_arguments = extra_arguments; + cbdata.extra_keywords = extra_keywords; + data = (void*)&cbdata; + } else { + PyErr_SetString(PyExc_RuntimeError, + "function parameter is not callable"); + goto exit; + } + if (!NI_GenericFilter(input, func, data, footprint, output, + (NI_ExtendMode)mode, cval, origin)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(output); + Py_XDECREF(footprint); + if (origin) + free(origin); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_FourierFilter(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *parameters = NULL; + int axis, filter_type; + long n; + + if (!PyArg_ParseTuple(args, "O&O&liO&i", NI_ObjectToInputArray, &input, + NI_ObjectToInputArray, ¶meters, &n, &axis, + NI_ObjectToOutputArray, &output, &filter_type)) + goto exit; + + if (!NI_FourierFilter(input, parameters, n, axis, output, filter_type)) + goto exit; + +exit: + Py_XDECREF(input); + Py_XDECREF(parameters); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_FourierShift(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *shifts = NULL; + int axis; + long n; + + if (!PyArg_ParseTuple(args, "O&O&liO&", NI_ObjectToInputArray, &input, + NI_ObjectToInputArray, &shifts, &n, &axis, + NI_ObjectToOutputArray, &output)) + goto exit; + + if (!NI_FourierShift(input, shifts, n, axis, output)) + goto exit; + +exit: + Py_XDECREF(input); + Py_XDECREF(shifts); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_SplineFilter1D(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL; + int axis, order; + + if (!PyArg_ParseTuple(args, "O&iiO&", NI_ObjectToInputArray, &input, + &order, &axis, NI_ObjectToOutputArray, &output)) + goto exit; + + if (!NI_SplineFilter1D(input, order, axis, output)) + goto exit; + +exit: + Py_XDECREF(input); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static int Py_Map(maybelong *ocoor, double* icoor, int orank, int irank, + void *data) +{ + PyObject *coors = NULL, *rets = NULL, *args = NULL, *tmp = NULL; + maybelong ii; + NI_PythonCallbackData *cbdata = (NI_PythonCallbackData*)data; + + coors = PyTuple_New(orank); + if (!coors) + goto exit; + for(ii = 0; ii < orank; ii++) { + PyTuple_SetItem(coors, ii, PyInt_FromLong(ocoor[ii])); + if (PyErr_Occurred()) + goto exit; + } + tmp = Py_BuildValue("(O)", coors); + if (!tmp) + goto exit; + args = PySequence_Concat(tmp, cbdata->extra_arguments); + if (!args) + goto exit; + rets = PyObject_Call(cbdata->function, args, cbdata->extra_keywords); + if (!rets) + goto exit; + for(ii = 0; ii < irank; ii++) { + icoor[ii] = PyFloat_AsDouble(PyTuple_GetItem(rets, ii)); + if (PyErr_Occurred()) + goto exit; + } +exit: + Py_XDECREF(coors); + Py_XDECREF(tmp); + Py_XDECREF(rets); + Py_XDECREF(args); + return PyErr_Occurred() ? 0 : 1; +} + + +static PyObject *Py_GeometricTransform(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL; + PyArrayObject *coordinates = NULL, *matrix = NULL, *shift = NULL; + PyObject *fnc = NULL, *extra_arguments = NULL, *extra_keywords = NULL; + int mode, order; + double cval; + void *func = NULL, *data = NULL; + NI_PythonCallbackData cbdata; + + if (!PyArg_ParseTuple(args, "O&OO&O&O&O&iidOO", NI_ObjectToInputArray, + &input, &fnc, NI_ObjectToOptionalInputArray, + &coordinates, NI_ObjectToOptionalInputArray, + &matrix, NI_ObjectToOptionalInputArray, &shift, + NI_ObjectToOutputArray, &output, &order, &mode, + &cval, &extra_arguments, &extra_keywords)) + goto exit; + + if (fnc != Py_None) { + if (!PyTuple_Check(extra_arguments)) { + PyErr_SetString(PyExc_RuntimeError, + "extra_arguments must be a tuple"); + goto exit; + } + if (!PyDict_Check(extra_keywords)) { + PyErr_SetString(PyExc_RuntimeError, + "extra_keywords must be a dictionary"); + goto exit; + } + if (PyCObject_Check(fnc)) { + func = PyCObject_AsVoidPtr(fnc); + data = PyCObject_GetDesc(fnc); + } else if (PyCallable_Check(fnc)) { + func = Py_Map; + cbdata.function = fnc; + cbdata.extra_arguments = extra_arguments; + cbdata.extra_keywords = extra_keywords; + data = (void*)&cbdata; + } else { + PyErr_SetString(PyExc_RuntimeError, + "function parameter is not callable"); + goto exit; + } + } + + if (!NI_GeometricTransform(input, func, data, matrix, shift, coordinates, + output, order, (NI_ExtendMode)mode, cval)) + goto exit; + +exit: + Py_XDECREF(input); + Py_XDECREF(output); + Py_XDECREF(coordinates); + Py_XDECREF(matrix); + Py_XDECREF(shift); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_ZoomShift(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *shift = NULL; + PyArrayObject *zoom = NULL; + int mode, order; + double cval; + + if (!PyArg_ParseTuple(args, "O&O&O&O&iid", NI_ObjectToInputArray, + &input, NI_ObjectToOptionalInputArray, &zoom, + NI_ObjectToOptionalInputArray, &shift, NI_ObjectToOutputArray, + &output, &order, &mode, &cval)) + goto exit; + + if (!NI_ZoomShift(input, zoom, shift, output, order, (NI_ExtendMode)mode, + cval)) + goto exit; + +exit: + Py_XDECREF(input); + Py_XDECREF(shift); + Py_XDECREF(zoom); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_Label(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *strct = NULL; + maybelong max_label; + + if (!PyArg_ParseTuple(args, "O&O&O&", NI_ObjectToInputArray, &input, + NI_ObjectToInputArray, &strct, NI_ObjectToOutputArray, &output)) + goto exit; + + if (!NI_Label(input, strct, &max_label, output)) + goto exit; + +exit: + Py_XDECREF(input); + Py_XDECREF(strct); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue("l", (long)max_label); +} + +static PyObject *Py_FindObjects(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL; + PyObject *result = NULL, *tuple = NULL, *start = NULL, *end = NULL; + PyObject *slc = NULL; + int jj; + long max_label; + maybelong ii, *regions = NULL; + + if (!PyArg_ParseTuple(args, "O&l", NI_ObjectToInputArray, &input, + &max_label)) + goto exit; + + if (max_label < 0) + max_label = 0; + if (max_label > 0) { + if (input->nd > 0) { + regions = (maybelong*)malloc(2 * max_label * input->nd * + sizeof(maybelong)); + } else { + regions = (maybelong*)malloc(max_label * sizeof(maybelong)); + } + if (!regions) { + PyErr_NoMemory(); + goto exit; + } + } + + if (!NI_FindObjects(input, max_label, regions)) + goto exit; + + result = PyList_New(max_label); + if (!result) { + PyErr_NoMemory(); + goto exit; + } + + for(ii = 0; ii < max_label; ii++) { + maybelong idx = input->nd > 0 ? 2 * input->nd * ii : ii; + if (regions[idx] >= 0) { + PyObject *tuple = PyTuple_New(input->nd); + if (!tuple) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < input->nd; jj++) { + start = PyInt_FromLong(regions[idx + jj]); + end = PyInt_FromLong(regions[idx + jj + input->nd]); + if (!start || !end) { + PyErr_NoMemory(); + goto exit; + } + slc = PySlice_New(start, end, NULL); + if (!slc) { + PyErr_NoMemory(); + goto exit; + } + Py_XDECREF(start); + Py_XDECREF(end); + start = end = NULL; + PyTuple_SetItem(tuple, jj, slc); + slc = NULL; + } + PyList_SetItem(result, ii, tuple); + tuple = NULL; + } else { + Py_INCREF(Py_None); + PyList_SetItem(result, ii, Py_None); + } + } + + Py_INCREF(result); + + exit: + Py_XDECREF(input); + Py_XDECREF(result); + Py_XDECREF(tuple); + Py_XDECREF(start); + Py_XDECREF(end); + Py_XDECREF(slc); + if (regions) + free(regions); + if (PyErr_Occurred()) { + Py_XDECREF(result); + return NULL; + } else { + return result; + } +} + +static PyObject *Py_WatershedIFT(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *markers = NULL; + PyArrayObject *strct = NULL; + + if (!PyArg_ParseTuple(args, "O&O&O&O&", NI_ObjectToInputArray, &input, + NI_ObjectToInputArray, &markers, NI_ObjectToInputArray, + &strct, NI_ObjectToOutputArray, &output)) + goto exit; + + if (!NI_WatershedIFT(input, markers, strct, output)) + goto exit; + +exit: + Py_XDECREF(input); + Py_XDECREF(markers); + Py_XDECREF(strct); + Py_XDECREF(output); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static int _NI_GetIndices(PyObject* indices_object, + maybelong** result_indices, maybelong* min_label, + maybelong* max_label, maybelong* n_results) +{ + maybelong *indices = NULL, n_indices, ii; + + if (indices_object == Py_None) { + *min_label = -1; + *n_results = 1; + } else { + n_indices = NI_ObjectToLongSequenceAndLength(indices_object, &indices); + if (n_indices < 0) + goto exit; + if (n_indices < 1) { + PyErr_SetString(PyExc_RuntimeError, "no correct indices provided"); + goto exit; + } else { + *min_label = *max_label = indices[0]; + if (*min_label < 0) { + PyErr_SetString(PyExc_RuntimeError, + "negative indices not allowed"); + goto exit; + } + for(ii = 1; ii < n_indices; ii++) { + if (indices[ii] < 0) { + PyErr_SetString(PyExc_RuntimeError, + "negative indices not allowed"); + goto exit; + } + if (indices[ii] < *min_label) + *min_label = indices[ii]; + if (indices[ii] > *max_label) + *max_label = indices[ii]; + } + *result_indices = (maybelong*)malloc((*max_label - *min_label + 1) * + sizeof(maybelong)); + if (!*result_indices) { + PyErr_NoMemory(); + goto exit; + } + for(ii = 0; ii < *max_label - *min_label + 1; ii++) + (*result_indices)[ii] = -1; + *n_results = 0; + for(ii = 0; ii < n_indices; ii++) { + if ((*result_indices)[indices[ii] - *min_label] >= 0) { + PyErr_SetString(PyExc_RuntimeError, "duplicate index"); + goto exit; + } + (*result_indices)[indices[ii] - *min_label] = ii; + ++(*n_results); + } + } + } + exit: + if (indices) + free(indices); + return PyErr_Occurred() == NULL; +} + + +PyObject* _NI_BuildMeasurementResultArrayObject(maybelong n_results, + PyArrayObject** values) +{ + PyObject *result = NULL; + if (n_results > 1) { + result = PyList_New(n_results); + if (result) { + maybelong ii; + for(ii = 0; ii < n_results; ii++) { + PyList_SET_ITEM(result, ii, (PyObject*)values[ii]); + Py_XINCREF(values[ii]); + } + } + } else { + result = (PyObject*)values[0]; + Py_XINCREF(values[0]); + } + return result; +} + + +PyObject* _NI_BuildMeasurementResultDouble(maybelong n_results, + double* values) +{ + PyObject *result = NULL; + if (n_results > 1) { + result = PyList_New(n_results); + if (result) { + int ii; + for(ii = 0; ii < n_results; ii++) { + PyObject* val = PyFloat_FromDouble(values[ii]); + if (!val) { + Py_XDECREF(result); + return NULL; + } + PyList_SET_ITEM(result, ii, val); + } + } + } else { + result = Py_BuildValue("d", values[0]); + } + return result; +} + + +PyObject* _NI_BuildMeasurementResultDoubleTuple(maybelong n_results, + int tuple_size, double* values) +{ + PyObject *result = NULL; + maybelong ii; + int jj; + + if (n_results > 1) { + result = PyList_New(n_results); + if (result) { + for(ii = 0; ii < n_results; ii++) { + PyObject* val = PyTuple_New(tuple_size); + if (!val) { + Py_XDECREF(result); + return NULL; + } + for(jj = 0; jj < tuple_size; jj++) { + maybelong idx = jj + ii * tuple_size; + PyTuple_SetItem(val, jj, PyFloat_FromDouble(values[idx])); + if (PyErr_Occurred()) { + Py_XDECREF(result); + return NULL; + } + } + PyList_SET_ITEM(result, ii, val); + } + } + } else { + result = PyTuple_New(tuple_size); + if (result) { + for(ii = 0; ii < tuple_size; ii++) { + PyTuple_SetItem(result, ii, PyFloat_FromDouble(values[ii])); + if (PyErr_Occurred()) { + Py_XDECREF(result); + return NULL; + } + } + } + } + return result; +} + + +PyObject* _NI_BuildMeasurementResultInt(maybelong n_results, + maybelong* values) +{ + PyObject *result = NULL; + if (n_results > 1) { + result = PyList_New(n_results); + if (result) { + maybelong ii; + for(ii = 0; ii < n_results; ii++) { + PyObject* val = PyInt_FromLong(values[ii]); + if (!val) { + Py_XDECREF(result); + return NULL; + } + PyList_SET_ITEM(result, ii, val); + } + } + } else { + result = Py_BuildValue("l", values[0]); + } + return result; +} + + +static PyObject *Py_Statistics(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *labels = NULL; + PyObject *indices_object, *result = NULL; + PyObject *res1 = NULL, *res2 = NULL, *res3 = NULL, *res4 = NULL; + double *dresult1 = NULL, *dresult2 = NULL; + maybelong *lresult1 = NULL, *lresult2 = NULL; + maybelong min_label, max_label, *result_indices = NULL, n_results, ii; + int type; + + if (!PyArg_ParseTuple(args, "O&O&Oi", NI_ObjectToInputArray, &input, + NI_ObjectToOptionalInputArray, &labels, &indices_object, &type)) + goto exit; + + if (!_NI_GetIndices(indices_object, &result_indices, &min_label, + &max_label, &n_results)) + goto exit; + + if (type >= 0 && type <= 7) { + dresult1 = (double*)malloc(n_results * sizeof(double)); + if (!dresult1) { + PyErr_NoMemory(); + goto exit; + } + } + if (type == 2 || type == 7) { + dresult2 = (double*)malloc(n_results * sizeof(double)); + if (!dresult2) { + PyErr_NoMemory(); + goto exit; + } + } + if (type == 1 || type == 2 || (type >= 5 && type <= 7)) { + lresult1 = (maybelong*)malloc(n_results * sizeof(maybelong)); + if (!lresult1) { + PyErr_NoMemory(); + goto exit; + } + } + if (type == 7) { + lresult2 = (maybelong*)malloc(n_results * sizeof(maybelong)); + if (!lresult2) { + PyErr_NoMemory(); + goto exit; + } + } + switch(type) { + case 0: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, dresult1, NULL, NULL, NULL, NULL, NULL, NULL)) + goto exit; + result = _NI_BuildMeasurementResultDouble(n_results, dresult1); + break; + case 1: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, dresult1, lresult1, NULL, NULL, NULL, NULL, NULL)) + goto exit; + for(ii = 0; ii < n_results; ii++) + dresult1[ii] = lresult1[ii] > 0 ? dresult1[ii] / lresult1[ii] : 0.0; + + result = _NI_BuildMeasurementResultDouble(n_results, dresult1); + break; + case 2: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, dresult1, lresult1, dresult2, NULL, NULL, NULL, NULL)) + goto exit; + result = _NI_BuildMeasurementResultDouble(n_results, dresult2); + break; + case 3: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, NULL, NULL, NULL, dresult1, NULL, NULL, NULL)) + goto exit; + result = _NI_BuildMeasurementResultDouble(n_results, dresult1); + break; + case 4: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, NULL, NULL, NULL, NULL, dresult1, NULL, NULL)) + goto exit; + result = _NI_BuildMeasurementResultDouble(n_results, dresult1); + break; + case 5: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, NULL, NULL, NULL, dresult1, NULL, lresult1, NULL)) + goto exit; + result = _NI_BuildMeasurementResultInt(n_results, lresult1); + break; + case 6: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, NULL, NULL, NULL, NULL, dresult1, NULL, lresult1)) + goto exit; + result = _NI_BuildMeasurementResultInt(n_results, lresult1); + break; + case 7: + if (!NI_Statistics(input, labels, min_label, max_label, result_indices, + n_results, NULL, NULL, NULL, dresult1, dresult2, + lresult1, lresult2)) + goto exit; + res1 = _NI_BuildMeasurementResultDouble(n_results, dresult1); + res2 = _NI_BuildMeasurementResultDouble(n_results, dresult2); + res3 = _NI_BuildMeasurementResultInt(n_results, lresult1); + res4 = _NI_BuildMeasurementResultInt(n_results, lresult2); + if (!res1 || !res2 || !res3 || !res4) + goto exit; + result = Py_BuildValue("OOOO", res1, res2, res3, res4); + break; + default: + PyErr_SetString(PyExc_RuntimeError, "operation not supported"); + goto exit; + } + + exit: + Py_XDECREF(input); + Py_XDECREF(labels); + if (result_indices) + free(result_indices); + if (dresult1) + free(dresult1); + if (dresult2) + free(dresult2); + if (lresult1) + free(lresult1); + if (lresult2) + free(lresult2); + return result; +} + + +static PyObject *Py_CenterOfMass(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *labels = NULL; + PyObject *indices_object, *result = NULL; + double *center_of_mass = NULL; + maybelong min_label, max_label, *result_indices = NULL, n_results; + + if (!PyArg_ParseTuple(args, "O&O&O", NI_ObjectToInputArray, &input, + NI_ObjectToOptionalInputArray, &labels, &indices_object)) + goto exit; + + if (!_NI_GetIndices(indices_object, &result_indices, &min_label, + &max_label, &n_results)) + goto exit; + + center_of_mass = (double*)malloc(input->nd * n_results * + sizeof(double)); + if (!center_of_mass) { + PyErr_NoMemory(); + goto exit; + } + + if (!NI_CenterOfMass(input, labels, min_label, max_label, + result_indices, n_results, center_of_mass)) + goto exit; + + result = _NI_BuildMeasurementResultDoubleTuple(n_results, input->nd, + center_of_mass); + + exit: + Py_XDECREF(input); + Py_XDECREF(labels); + if (result_indices) + free(result_indices); + if (center_of_mass) + free(center_of_mass); + return result; +} + +static PyObject *Py_Histogram(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *labels = NULL, **histograms = NULL; + PyObject *indices_object, *result = NULL; + maybelong min_label, max_label, *result_indices = NULL, n_results; + maybelong jj, nbins; + long nbins_in; + double min, max; + + if (!PyArg_ParseTuple(args, "O&ddlO&O", NI_ObjectToInputArray, &input, + &min, &max, &nbins_in, NI_ObjectToOptionalInputArray, + &labels, &indices_object)) + goto exit; + nbins = nbins_in; + + if (!_NI_GetIndices(indices_object, &result_indices, &min_label, + &max_label, &n_results)) + goto exit; + + /* Set all pointers to NULL, so that freeing the memory */ + /* doesn't cause problems. */ + histograms = (PyArrayObject**)calloc(input->nd * n_results, + sizeof(PyArrayObject*)); + if (!histograms) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < n_results; jj++) { + histograms[jj] = NA_NewArray(NULL, tInt32, 1, &nbins); + if (!histograms[jj]) { + PyErr_NoMemory(); + goto exit; + } + } + + if (!NI_Histogram(input, labels, min_label, max_label, result_indices, + n_results, histograms, min, max, nbins)) + goto exit; + + result = _NI_BuildMeasurementResultArrayObject(n_results, histograms); + + exit: + Py_XDECREF(input); + Py_XDECREF(labels); + if (result_indices) + free(result_indices); + if (histograms) { + for(jj = 0; jj < n_results; jj++) { + Py_XDECREF(histograms[jj]); + } + free(histograms); + } + return result; +} + +static PyObject *Py_DistanceTransformBruteForce(PyObject *obj, + PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *features = NULL; + PyArrayObject *sampling = NULL; + int metric; + + if (!PyArg_ParseTuple(args, "O&iO&O&O&", NI_ObjectToInputArray, &input, + &metric, NI_ObjectToOptionalInputArray, &sampling, + NI_ObjectToOptionalOutputArray, &output, + NI_ObjectToOptionalOutputArray, &features)) + goto exit; + if (!NI_DistanceTransformBruteForce(input, metric, sampling, + output, features)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(sampling); + Py_XDECREF(output); + Py_XDECREF(features); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_DistanceTransformOnePass(PyObject *obj, PyObject *args) +{ + PyArrayObject *strct = NULL, *distances = NULL, *features = NULL; + + if (!PyArg_ParseTuple(args, "O&O&O&", NI_ObjectToInputArray, &strct, + NI_ObjectToIoArray, &distances, + NI_ObjectToOptionalOutputArray, &features)) + goto exit; + if (!NI_DistanceTransformOnePass(strct, distances, features)) + goto exit; +exit: + Py_XDECREF(strct); + Py_XDECREF(distances); + Py_XDECREF(features); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyObject *Py_EuclideanFeatureTransform(PyObject *obj, + PyObject *args) +{ + PyArrayObject *input = NULL, *features = NULL, *sampling = NULL; + + if (!PyArg_ParseTuple(args, "O&O&O&", NI_ObjectToInputArray, &input, + NI_ObjectToOptionalInputArray, &sampling, + NI_ObjectToOutputArray, &features)) + goto exit; + if (!NI_EuclideanFeatureTransform(input, sampling, features)) + goto exit; +exit: + Py_XDECREF(input); + Py_XDECREF(sampling); + Py_XDECREF(features); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static void _FreeCoordinateList(void* ptr) +{ + NI_FreeCoordinateList((NI_CoordinateList*)ptr); +} + +static PyObject *Py_BinaryErosion(PyObject *obj, PyObject *args) +{ + PyArrayObject *input = NULL, *output = NULL, *strct = NULL; + PyArrayObject *mask = NULL; + PyObject *cobj = NULL; + int border_value, invert, center_is_true; + int changed = 0, return_coordinates; + NI_CoordinateList *coordinate_list = NULL; + maybelong *origins = NULL; + + if (!PyArg_ParseTuple(args, "O&O&O&O&iO&iii", NI_ObjectToInputArray, + &input, NI_ObjectToInputArray, &strct, + NI_ObjectToOptionalInputArray, &mask, + NI_ObjectToOutputArray, &output, &border_value, + NI_ObjectToLongSequence, &origins, &invert, + ¢er_is_true, &return_coordinates)) + goto exit; + if (!NI_BinaryErosion(input, strct, mask, output, border_value, + origins, invert, center_is_true, &changed, + return_coordinates ? &coordinate_list : NULL)) + goto exit; + if (return_coordinates) { + cobj = PyCObject_FromVoidPtr(coordinate_list, _FreeCoordinateList); + } +exit: + Py_XDECREF(input); + Py_XDECREF(strct); + Py_XDECREF(mask); + Py_XDECREF(output); + if (origins) + free(origins); + if (PyErr_Occurred()) { + Py_XDECREF(cobj); + return NULL; + } else { + if (return_coordinates) { + return Py_BuildValue("iN", changed, cobj); + } else { + return Py_BuildValue("i", changed); + } + } +} + +static PyObject *Py_BinaryErosion2(PyObject *obj, PyObject *args) +{ + PyArrayObject *array = NULL, *strct = NULL, *mask = NULL; + PyObject *cobj = NULL; + int invert, niter; + maybelong *origins = NULL; + + if (!PyArg_ParseTuple(args, "O&O&O&iO&iO", NI_ObjectToIoArray, &array, + NI_ObjectToInputArray, &strct, NI_ObjectToOptionalInputArray, + &mask, &niter, NI_ObjectToLongSequence, &origins, &invert, + &cobj)) + goto exit; + + if (PyCObject_Check(cobj)) { + NI_CoordinateList *cobj_data = PyCObject_AsVoidPtr(cobj); + if (!NI_BinaryErosion2(array, strct, mask, niter, origins, invert, + &cobj_data)) + goto exit; + } else { + PyErr_SetString(PyExc_RuntimeError, "cannot convert CObject"); + goto exit; + } +exit: + Py_XDECREF(array); + Py_XDECREF(strct); + Py_XDECREF(mask); + if (origins) free(origins); + return PyErr_Occurred() ? NULL : Py_BuildValue(""); +} + +static PyMethodDef methods[] = { + {"correlate1d", (PyCFunction)Py_Correlate1D, + METH_VARARGS, NULL}, + {"correlate", (PyCFunction)Py_Correlate, + METH_VARARGS, NULL}, + {"uniform_filter1d", (PyCFunction)Py_UniformFilter1D, + METH_VARARGS, NULL}, + {"min_or_max_filter1d", (PyCFunction)Py_MinOrMaxFilter1D, + METH_VARARGS, NULL}, + {"min_or_max_filter", (PyCFunction)Py_MinOrMaxFilter, + METH_VARARGS, NULL}, + {"rank_filter", (PyCFunction)Py_RankFilter, + METH_VARARGS, NULL}, + {"generic_filter", (PyCFunction)Py_GenericFilter, + METH_VARARGS, NULL}, + {"generic_filter1d", (PyCFunction)Py_GenericFilter1D, + METH_VARARGS, NULL}, + {"fourier_filter", (PyCFunction)Py_FourierFilter, + METH_VARARGS, NULL}, + {"fourier_shift", (PyCFunction)Py_FourierShift, + METH_VARARGS, NULL}, + {"spline_filter1d", (PyCFunction)Py_SplineFilter1D, + METH_VARARGS, NULL}, + {"geometric_transform", (PyCFunction)Py_GeometricTransform, + METH_VARARGS, NULL}, + {"zoom_shift", (PyCFunction)Py_ZoomShift, + METH_VARARGS, NULL}, + {"label", (PyCFunction)Py_Label, + METH_VARARGS, NULL}, + {"find_objects", (PyCFunction)Py_FindObjects, + METH_VARARGS, NULL}, + {"watershed_ift", (PyCFunction)Py_WatershedIFT, + METH_VARARGS, NULL}, + {"statistics", (PyCFunction)Py_Statistics, + METH_VARARGS, NULL}, + {"center_of_mass", (PyCFunction)Py_CenterOfMass, + METH_VARARGS, NULL}, + {"histogram", (PyCFunction)Py_Histogram, + METH_VARARGS, NULL}, + {"distance_transform_bf", (PyCFunction)Py_DistanceTransformBruteForce, + METH_VARARGS, NULL}, + {"distance_transform_op", (PyCFunction)Py_DistanceTransformOnePass, + METH_VARARGS, NULL}, + {"euclidean_feature_transform", + (PyCFunction)Py_EuclideanFeatureTransform, + METH_VARARGS, NULL}, + {"binary_erosion", (PyCFunction)Py_BinaryErosion, + METH_VARARGS, NULL}, + {"binary_erosion2", (PyCFunction)Py_BinaryErosion2, + METH_VARARGS, NULL}, + {NULL, NULL, 0, NULL} +}; + +PyMODINIT_FUNC init_nd_image(void) +{ + Py_InitModule("_nd_image", methods); + import_array(); +} Modified: trunk/scipy/ndimage/src/nd_image.h =================================================================== --- trunk/scipy/ndimage/src/nd_image.h 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/nd_image.h 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,278 +1,278 @@ -/* Copyright (C) 2003-2005 Peter J. Verveer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ND_IMAGE_H -#define ND_IMAGE_H - -#include "Python.h" - -#ifndef ND_IMPORT_ARRAY -#define NO_IMPORT_ARRAY -#endif - -#include -#undef NO_IMPORT_ARRAY - -/* Eventually get rid of everything below this line */ - -typedef enum -{ - tAny=-1, - tBool=PyArray_BOOL, - tInt8=PyArray_INT8, - tUInt8=PyArray_UINT8, - tInt16=PyArray_INT16, - tUInt16=PyArray_UINT16, - tInt32=PyArray_INT32, - tUInt32=PyArray_UINT32, - tInt64=PyArray_INT64, - tUInt64=PyArray_UINT64, - tFloat32=PyArray_FLOAT32, - tFloat64=PyArray_FLOAT64, - tComplex64=PyArray_COMPLEX64, - tComplex128=PyArray_COMPLEX128, - tObject=PyArray_OBJECT, /* placeholder... does nothing */ - tMaxType=PyArray_NTYPES, - tDefault=PyArray_FLOAT64, - tLong=PyArray_LONG, -} NumarrayType; - -#define NI_MAXDIM NPY_MAXDIMS - -typedef npy_intp maybelong; -#define MAXDIM NPY_MAXDIMS - -#define HAS_UINT64 1 - - - -#ifdef ND_IMPORT_ARRAY - -/* Numarray Helper Functions */ - -static PyArrayObject* -NA_InputArray(PyObject *a, NumarrayType t, int requires) -{ - PyArray_Descr *descr; - if (t == tAny) descr = NULL; - else descr = PyArray_DescrFromType(t); - return (PyArrayObject *) \ - PyArray_CheckFromAny(a, descr, 0, 0, requires, NULL); -} - -/* satisfies ensures that 'a' meets a set of requirements and matches -the specified type. -*/ -static int -satisfies(PyArrayObject *a, int requirements, NumarrayType t) -{ - int type_ok = (a->descr->type_num == t) || (t == tAny); - - if (PyArray_ISCARRAY(a)) - return type_ok; - if (PyArray_ISBYTESWAPPED(a) && (requirements & NPY_NOTSWAPPED)) - return 0; - if (!PyArray_ISALIGNED(a) && (requirements & NPY_ALIGNED)) - return 0; - if (!PyArray_ISCONTIGUOUS(a) && (requirements & NPY_CONTIGUOUS)) - return 0; - if (!PyArray_ISWRITEABLE(a) && (requirements & NPY_WRITEABLE)) - return 0; - if (requirements & NPY_ENSURECOPY) - return 0; - return type_ok; -} - -static PyArrayObject * -NA_OutputArray(PyObject *a, NumarrayType t, int requires) -{ - PyArray_Descr *dtype; - PyArrayObject *ret; - - if (!PyArray_Check(a) || !PyArray_ISWRITEABLE(a)) { - PyErr_Format(PyExc_TypeError, - "NA_OutputArray: only writeable arrays work for output."); - return NULL; - } - - if (satisfies((PyArrayObject *)a, requires, t)) { - Py_INCREF(a); - return (PyArrayObject *)a; - } - if (t == tAny) { - dtype = PyArray_DESCR(a); - Py_INCREF(dtype); - } - else { - dtype = PyArray_DescrFromType(t); - } - ret = (PyArrayObject *)PyArray_Empty(PyArray_NDIM(a), PyArray_DIMS(a), - dtype, 0); - ret->flags |= NPY_UPDATEIFCOPY; - ret->base = a; - PyArray_FLAGS(a) &= ~NPY_WRITEABLE; - Py_INCREF(a); - return ret; -} - -/* NA_IoArray is a combination of NA_InputArray and NA_OutputArray. - -Unlike NA_OutputArray, if a temporary is required it is initialized to a copy -of the input array. - -Unlike NA_InputArray, deallocating any resulting temporary array results in a -copy from the temporary back to the original. -*/ -static PyArrayObject * -NA_IoArray(PyObject *a, NumarrayType t, int requires) -{ - PyArrayObject *shadow = NA_InputArray(a, t, requires | NPY_UPDATEIFCOPY ); - - if (!shadow) return NULL; - - /* Guard against non-writable, but otherwise satisfying requires. - In this case, shadow == a. - */ - if (!PyArray_ISWRITEABLE(shadow)) { - PyErr_Format(PyExc_TypeError, - "NA_IoArray: I/O array must be writable array"); - PyArray_XDECREF_ERR(shadow); - return NULL; - } - - return shadow; -} - -#define NUM_LITTLE_ENDIAN 0 -#define NUM_BIG_ENDIAN 1 - -static int -NA_ByteOrder(void) -{ - unsigned long byteorder_test; - byteorder_test = 1; - if (*((char *) &byteorder_test)) - return NUM_LITTLE_ENDIAN; - else - return NUM_BIG_ENDIAN; -} - -/* ignores bytestride */ -static PyArrayObject * -NA_NewAllFromBuffer(int ndim, maybelong *shape, NumarrayType type, - PyObject *bufferObject, maybelong byteoffset, maybelong bytestride, - int byteorder, int aligned, int writeable) -{ - PyArrayObject *self = NULL; - PyArray_Descr *dtype; - - if (type == tAny) - type = tDefault; - - dtype = PyArray_DescrFromType(type); - if (dtype == NULL) return NULL; - - if (byteorder != NA_ByteOrder()) { - PyArray_Descr *temp; - temp = PyArray_DescrNewByteorder(dtype, PyArray_SWAP); - Py_DECREF(dtype); - if (temp == NULL) return NULL; - dtype = temp; - } - - if (bufferObject == Py_None || bufferObject == NULL) { - self = (PyArrayObject *) \ - PyArray_NewFromDescr(&PyArray_Type, dtype, - ndim, shape, NULL, NULL, - 0, NULL); - } - else { - npy_intp size = 1; - int i; - PyArrayObject *newself; - PyArray_Dims newdims; - for(i=0; idata, buffer, PyArray_NBYTES(result)); - } else { - memset(result->data, 0, PyArray_NBYTES(result)); - } - } - } - return result; -} - -/* Create a new numarray which is initially a C_array, or which -references a C_array: aligned, !byteswapped, contiguous, ... -Call with buffer==NULL to allocate storage. -*/ -static PyArrayObject * -NA_NewArray(void *buffer, NumarrayType type, int ndim, maybelong *shape) -{ - return (PyArrayObject *) NA_NewAll(ndim, shape, type, buffer, 0, 0, - NA_ByteOrder(), 1, 1); -} - -#endif /* ND_IMPORT_ARRAY */ - -#endif /* ND_IMAGE_H */ +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ND_IMAGE_H +#define ND_IMAGE_H + +#include "Python.h" + +#ifndef ND_IMPORT_ARRAY +#define NO_IMPORT_ARRAY +#endif + +#include +#undef NO_IMPORT_ARRAY + +/* Eventually get rid of everything below this line */ + +typedef enum +{ + tAny=-1, + tBool=PyArray_BOOL, + tInt8=PyArray_INT8, + tUInt8=PyArray_UINT8, + tInt16=PyArray_INT16, + tUInt16=PyArray_UINT16, + tInt32=PyArray_INT32, + tUInt32=PyArray_UINT32, + tInt64=PyArray_INT64, + tUInt64=PyArray_UINT64, + tFloat32=PyArray_FLOAT32, + tFloat64=PyArray_FLOAT64, + tComplex64=PyArray_COMPLEX64, + tComplex128=PyArray_COMPLEX128, + tObject=PyArray_OBJECT, /* placeholder... does nothing */ + tMaxType=PyArray_NTYPES, + tDefault=PyArray_FLOAT64, + tLong=PyArray_LONG, +} NumarrayType; + +#define NI_MAXDIM NPY_MAXDIMS + +typedef npy_intp maybelong; +#define MAXDIM NPY_MAXDIMS + +#define HAS_UINT64 1 + + + +#ifdef ND_IMPORT_ARRAY + +/* Numarray Helper Functions */ + +static PyArrayObject* +NA_InputArray(PyObject *a, NumarrayType t, int requires) +{ + PyArray_Descr *descr; + if (t == tAny) descr = NULL; + else descr = PyArray_DescrFromType(t); + return (PyArrayObject *) \ + PyArray_CheckFromAny(a, descr, 0, 0, requires, NULL); +} + +/* satisfies ensures that 'a' meets a set of requirements and matches +the specified type. +*/ +static int +satisfies(PyArrayObject *a, int requirements, NumarrayType t) +{ + int type_ok = (a->descr->type_num == t) || (t == tAny); + + if (PyArray_ISCARRAY(a)) + return type_ok; + if (PyArray_ISBYTESWAPPED(a) && (requirements & NPY_NOTSWAPPED)) + return 0; + if (!PyArray_ISALIGNED(a) && (requirements & NPY_ALIGNED)) + return 0; + if (!PyArray_ISCONTIGUOUS(a) && (requirements & NPY_CONTIGUOUS)) + return 0; + if (!PyArray_ISWRITEABLE(a) && (requirements & NPY_WRITEABLE)) + return 0; + if (requirements & NPY_ENSURECOPY) + return 0; + return type_ok; +} + +static PyArrayObject * +NA_OutputArray(PyObject *a, NumarrayType t, int requires) +{ + PyArray_Descr *dtype; + PyArrayObject *ret; + + if (!PyArray_Check(a) || !PyArray_ISWRITEABLE(a)) { + PyErr_Format(PyExc_TypeError, + "NA_OutputArray: only writeable arrays work for output."); + return NULL; + } + + if (satisfies((PyArrayObject *)a, requires, t)) { + Py_INCREF(a); + return (PyArrayObject *)a; + } + if (t == tAny) { + dtype = PyArray_DESCR(a); + Py_INCREF(dtype); + } + else { + dtype = PyArray_DescrFromType(t); + } + ret = (PyArrayObject *)PyArray_Empty(PyArray_NDIM(a), PyArray_DIMS(a), + dtype, 0); + ret->flags |= NPY_UPDATEIFCOPY; + ret->base = a; + PyArray_FLAGS(a) &= ~NPY_WRITEABLE; + Py_INCREF(a); + return ret; +} + +/* NA_IoArray is a combination of NA_InputArray and NA_OutputArray. + +Unlike NA_OutputArray, if a temporary is required it is initialized to a copy +of the input array. + +Unlike NA_InputArray, deallocating any resulting temporary array results in a +copy from the temporary back to the original. +*/ +static PyArrayObject * +NA_IoArray(PyObject *a, NumarrayType t, int requires) +{ + PyArrayObject *shadow = NA_InputArray(a, t, requires | NPY_UPDATEIFCOPY ); + + if (!shadow) return NULL; + + /* Guard against non-writable, but otherwise satisfying requires. + In this case, shadow == a. + */ + if (!PyArray_ISWRITEABLE(shadow)) { + PyErr_Format(PyExc_TypeError, + "NA_IoArray: I/O array must be writable array"); + PyArray_XDECREF_ERR(shadow); + return NULL; + } + + return shadow; +} + +#define NUM_LITTLE_ENDIAN 0 +#define NUM_BIG_ENDIAN 1 + +static int +NA_ByteOrder(void) +{ + unsigned long byteorder_test; + byteorder_test = 1; + if (*((char *) &byteorder_test)) + return NUM_LITTLE_ENDIAN; + else + return NUM_BIG_ENDIAN; +} + +/* ignores bytestride */ +static PyArrayObject * +NA_NewAllFromBuffer(int ndim, maybelong *shape, NumarrayType type, + PyObject *bufferObject, maybelong byteoffset, maybelong bytestride, + int byteorder, int aligned, int writeable) +{ + PyArrayObject *self = NULL; + PyArray_Descr *dtype; + + if (type == tAny) + type = tDefault; + + dtype = PyArray_DescrFromType(type); + if (dtype == NULL) return NULL; + + if (byteorder != NA_ByteOrder()) { + PyArray_Descr *temp; + temp = PyArray_DescrNewByteorder(dtype, PyArray_SWAP); + Py_DECREF(dtype); + if (temp == NULL) return NULL; + dtype = temp; + } + + if (bufferObject == Py_None || bufferObject == NULL) { + self = (PyArrayObject *) \ + PyArray_NewFromDescr(&PyArray_Type, dtype, + ndim, shape, NULL, NULL, + 0, NULL); + } + else { + npy_intp size = 1; + int i; + PyArrayObject *newself; + PyArray_Dims newdims; + for(i=0; idata, buffer, PyArray_NBYTES(result)); + } else { + memset(result->data, 0, PyArray_NBYTES(result)); + } + } + } + return result; +} + +/* Create a new numarray which is initially a C_array, or which +references a C_array: aligned, !byteswapped, contiguous, ... +Call with buffer==NULL to allocate storage. +*/ +static PyArrayObject * +NA_NewArray(void *buffer, NumarrayType type, int ndim, maybelong *shape) +{ + return (PyArrayObject *) NA_NewAll(ndim, shape, type, buffer, 0, 0, + NA_ByteOrder(), 1, 1); +} + +#endif /* ND_IMPORT_ARRAY */ + +#endif /* ND_IMAGE_H */ Modified: trunk/scipy/ndimage/src/ni_filters.c =================================================================== --- trunk/scipy/ndimage/src/ni_filters.c 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/ni_filters.c 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,888 +1,888 @@ -/* Copyright (C) 2003-2005 Peter J. Verveer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ni_support.h" -#include "ni_filters.h" -#include -#include - -#define BUFFER_SIZE 256000 - -int NI_Correlate1D(PyArrayObject *input, PyArrayObject *weights, - int axis, PyArrayObject *output, NI_ExtendMode mode, - double cval, maybelong origin) -{ - int symmetric = 0, ii, jj, more; - maybelong ll, lines, length, size1, size2, filter_size; - double *ibuffer = NULL, *obuffer = NULL; - Float64 *fw; - NI_LineBuffer iline_buffer, oline_buffer; - - /* test for symmetry or anti-symmetry: */ - filter_size = weights->dimensions[0]; - size1 = filter_size / 2; - size2 = filter_size - size1 - 1; - fw = (void *)PyArray_DATA(weights); - if (filter_size & 0x1) { - symmetric = 1; - for(ii = 1; ii <= filter_size / 2; ii++) { - if (fabs(fw[ii + size1] - fw[size1 - ii]) > DBL_EPSILON) { - symmetric = 0; - break; - } - } - if (symmetric == 0) { - symmetric = -1; - for(ii = 1; ii <= filter_size / 2; ii++) { - if (fabs(fw[size1 + ii] + fw[size1 - ii]) > DBL_EPSILON) { - symmetric = 0; - break; - } - } - } - } - /* allocate and initialize the line buffers: */ - lines = -1; - if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, - &lines, BUFFER_SIZE, &ibuffer)) - goto exit; - if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, - &obuffer)) - goto exit; - if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, - lines, ibuffer, mode, cval, &iline_buffer)) - goto exit; - if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, - &oline_buffer)) - goto exit; - length = input->nd > 0 ? input->dimensions[axis] : 1; - fw += size1; - /* iterate over all the array lines: */ - do { - /* copy lines from array to buffer: */ - if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) - goto exit; - /* iterate over the lines in the buffers: */ - for(ii = 0; ii < lines; ii++) { - /* get lines: */ - double *iline = NI_GET_LINE(iline_buffer, ii) + size1; - double *oline = NI_GET_LINE(oline_buffer, ii); - /* the correlation calculation: */ - if (symmetric > 0) { - for(ll = 0; ll < length; ll++) { - oline[ll] = iline[0] * fw[0]; - for(jj = -size1 ; jj < 0; jj++) - oline[ll] += (iline[jj] + iline[-jj]) * fw[jj]; - ++iline; - } - } else if (symmetric < 0) { - for(ll = 0; ll < length; ll++) { - oline[ll] = iline[0] * fw[0]; - for(jj = -size1 ; jj < 0; jj++) - oline[ll] += (iline[jj] - iline[-jj]) * fw[jj]; - ++iline; - } - } else { - for(ll = 0; ll < length; ll++) { - oline[ll] = iline[size2] * fw[size2]; - for(jj = -size1; jj < size2; jj++) - oline[ll] += iline[jj] * fw[jj]; - ++iline; - } - } - } - /* copy lines from buffer to array: */ - if (!NI_LineBufferToArray(&oline_buffer)) - goto exit; - } while(more); -exit: - if (ibuffer) free(ibuffer); - if (obuffer) free(obuffer); - return PyErr_Occurred() ? 0 : 1; -} - -#define CASE_CORRELATE_POINT(_pi, _weights, _offsets, _filter_size, \ - _cvalue, _type, _res, _mv) \ -case t ## _type: \ -{ \ - maybelong _ii, _offset; \ - for(_ii = 0; _ii < _filter_size; _ii++) { \ - _offset = _offsets[_ii]; \ - if (_offset == _mv) \ - _res += _weights[_ii] * _cvalue; \ - else \ - _res += _weights[_ii] * (double)*(_type*)(_pi + _offset); \ - } \ -} \ -break - -#define CASE_FILTER_OUT(_po, _tmp, _type) \ -case t ## _type: \ - *(_type*)_po = (_type)_tmp; \ - break - -int NI_Correlate(PyArrayObject* input, PyArrayObject* weights, - PyArrayObject* output, NI_ExtendMode mode, - double cvalue, maybelong *origins) -{ - Bool *pf = NULL; - maybelong fsize, jj, kk, filter_size = 0, border_flag_value; - maybelong *offsets = NULL, *oo, size; - NI_FilterIterator fi; - NI_Iterator ii, io; - char *pi, *po; - Float64 *pw; - Float64 *ww = NULL; - int ll; - - /* get the the footprint: */ - fsize = 1; - for(ll = 0; ll < weights->nd; ll++) - fsize *= weights->dimensions[ll]; - pw = (Float64*)PyArray_DATA(weights); - pf = (Bool*)malloc(fsize * sizeof(Bool)); - if (!pf) { - PyErr_NoMemory(); - goto exit; - } - for(jj = 0; jj < fsize; jj++) { - if (fabs(pw[jj]) > DBL_EPSILON) { - pf[jj] = 1; - ++filter_size; - } else { - pf[jj] = 0; - } - } - /* copy the weights to contiguous memory: */ - ww = (Float64*)malloc(filter_size * sizeof(Float64)); - if (!ww) { - PyErr_NoMemory(); - goto exit; - } - jj = 0; - for(kk = 0; kk < fsize; kk++) { - if (pf[kk]) { - ww[jj++] = pw[kk]; - } - } - /* initialize filter offsets: */ - if (!NI_InitFilterOffsets(input, pf, weights->dimensions, origins, - mode, &offsets, &border_flag_value, NULL)) - goto exit; - /* initialize filter iterator: */ - if (!NI_InitFilterIterator(input->nd, weights->dimensions, filter_size, - input->dimensions, origins, &fi)) - goto exit; - /* initialize input element iterator: */ - if (!NI_InitPointIterator(input, &ii)) - goto exit; - /* initialize output element iterator: */ - if (!NI_InitPointIterator(output, &io)) - goto exit; - /* get data pointers an array size: */ - pi = (void *)PyArray_DATA(input); - po = (void *)PyArray_DATA(output); - size = 1; - for(ll = 0; ll < input->nd; ll++) - size *= input->dimensions[ll]; - /* iterator over the elements: */ - oo = offsets; - for(jj = 0; jj < size; jj++) { - double tmp = 0.0; - switch (input->descr->type_num) { - CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Bool, - tmp, border_flag_value); - CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt8, - tmp, border_flag_value); - CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt16, - tmp, border_flag_value); - CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt32, - tmp, border_flag_value); -#if HAS_UINT64 - CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt64, - tmp, border_flag_value); -#endif - CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int8, - tmp, border_flag_value); - CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int16, - tmp, border_flag_value); - CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int32, - tmp, border_flag_value); - CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int64, - tmp, border_flag_value); - CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Float32, - tmp, border_flag_value); - CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Float64, - tmp, border_flag_value); - default: - PyErr_SetString(PyExc_RuntimeError, "array type not supported"); - goto exit; - } - switch (output->descr->type_num) { - CASE_FILTER_OUT(po, tmp, Bool); - CASE_FILTER_OUT(po, tmp, UInt8); - CASE_FILTER_OUT(po, tmp, UInt16); - CASE_FILTER_OUT(po, tmp, UInt32); -#if HAS_UINT64 - CASE_FILTER_OUT(po, tmp, UInt64); -#endif - CASE_FILTER_OUT(po, tmp, Int8); - CASE_FILTER_OUT(po, tmp, Int16); - CASE_FILTER_OUT(po, tmp, Int32); - CASE_FILTER_OUT(po, tmp, Int64); - CASE_FILTER_OUT(po, tmp, Float32); - CASE_FILTER_OUT(po, tmp, Float64); - default: - PyErr_SetString(PyExc_RuntimeError, "array type not supported"); - goto exit; - } - NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); - } -exit: - if (offsets) free(offsets); - if (ww) free(ww); - if (pf) free(pf); - return PyErr_Occurred() ? 0 : 1; -} - -int -NI_UniformFilter1D(PyArrayObject *input, long filter_size, - int axis, PyArrayObject *output, NI_ExtendMode mode, - double cval, long origin) -{ - maybelong lines, kk, ll, length, size1, size2; - int more; - double *ibuffer = NULL, *obuffer = NULL; - NI_LineBuffer iline_buffer, oline_buffer; - - size1 = filter_size / 2; - size2 = filter_size - size1 - 1; - /* allocate and initialize the line buffers: */ - lines = -1; - if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, - &lines, BUFFER_SIZE, &ibuffer)) - goto exit; - if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, - &obuffer)) - goto exit; - if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, - lines, ibuffer, mode, cval, &iline_buffer)) - goto exit; - if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, - &oline_buffer)) - goto exit; - length = input->nd > 0 ? input->dimensions[axis] : 1; - - /* iterate over all the array lines: */ - do { - /* copy lines from array to buffer: */ - if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) - goto exit; - /* iterate over the lines in the buffers: */ - for(kk = 0; kk < lines; kk++) { - /* get lines: */ - double *iline = NI_GET_LINE(iline_buffer, kk); - double *oline = NI_GET_LINE(oline_buffer, kk); - /* do the uniform filter: */ - double tmp = 0.0; - double *l1 = iline; - double *l2 = iline + filter_size; - for(ll = 0; ll < filter_size; ll++) - tmp += iline[ll]; - tmp /= (double)filter_size; - oline[0] = tmp; - for(ll = 1; ll < length; ll++) { - tmp += (*l2++ - *l1++) / (double)filter_size; - oline[ll] = tmp; - } - } - /* copy lines from buffer to array: */ - if (!NI_LineBufferToArray(&oline_buffer)) - goto exit; - } while(more); - - exit: - if (ibuffer) free(ibuffer); - if (obuffer) free(obuffer); - return PyErr_Occurred() ? 0 : 1; -} - -int -NI_MinOrMaxFilter1D(PyArrayObject *input, long filter_size, - int axis, PyArrayObject *output, NI_ExtendMode mode, - double cval, long origin, int minimum) -{ - maybelong lines, kk, jj, ll, length, size1, size2; - int more; - double *ibuffer = NULL, *obuffer = NULL; - NI_LineBuffer iline_buffer, oline_buffer; - - size1 = filter_size / 2; - size2 = filter_size - size1 - 1; - /* allocate and initialize the line buffers: */ - lines = -1; - if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, - &lines, BUFFER_SIZE, &ibuffer)) - goto exit; - if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, - &obuffer)) - goto exit; - if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, - lines, ibuffer, mode, cval, &iline_buffer)) - goto exit; - if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, - &oline_buffer)) - goto exit; - length = input->nd > 0 ? input->dimensions[axis] : 1; - - /* iterate over all the array lines: */ - do { - /* copy lines from array to buffer: */ - if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) - goto exit; - /* iterate over the lines in the buffers: */ - for(kk = 0; kk < lines; kk++) { - /* get lines: */ - double *iline = NI_GET_LINE(iline_buffer, kk) + size1; - double *oline = NI_GET_LINE(oline_buffer, kk); - for(ll = 0; ll < length; ll++) { - /* find minimum or maximum filter: */ - double val = iline[ll - size1]; - for(jj = -size1 + 1; jj <= size2; jj++) { - double tmp = iline[ll + jj]; - if (minimum) { - if (tmp < val) - val = tmp; - } else { - if (tmp > val) - val = tmp; - } - } - oline[ll] = val; - } - } - /* copy lines from buffer to array: */ - if (!NI_LineBufferToArray(&oline_buffer)) - goto exit; - } while(more); - - exit: - if (ibuffer) free(ibuffer); - if (obuffer) free(obuffer); - return PyErr_Occurred() ? 0 : 1; -} - - -#define CASE_MIN_OR_MAX_POINT(_pi, _offsets, _filter_size, _cval, \ - _type, _minimum, _res, _mv, _ss) \ -case t ## _type: \ -{ \ - maybelong _ii, _oo = *_offsets; \ - _type _cv = (_type)_cval, _tmp; \ - _res = _oo == _mv ? _cv : *(_type*)(_pi + _oo); \ - if (_ss) \ - _res += *_ss; \ - for(_ii = 1; _ii < _filter_size; _ii++) { \ - _oo = _offsets[_ii]; \ - _tmp = _oo == _mv ? _cv : *(_type*)(_pi + _oo); \ - if (_ss) \ - _tmp += _ss[_ii]; \ - if (_minimum) { \ - if (_tmp < _res) \ - _res = (_type)_tmp; \ - } else { \ - if (_tmp > _res) \ - _res = (_type)_tmp; \ - } \ - } \ -} \ -break - -int NI_MinOrMaxFilter(PyArrayObject* input, PyArrayObject* footprint, - PyArrayObject* structure, PyArrayObject* output, - NI_ExtendMode mode, double cvalue, maybelong *origins, int minimum) -{ - Bool *pf = NULL; - maybelong fsize, jj, kk, filter_size = 0, border_flag_value; - maybelong *offsets = NULL, *oo, size; - NI_FilterIterator fi; - NI_Iterator ii, io; - char *pi, *po; - int ll; - double *ss = NULL; - Float64 *ps; - - /* get the the footprint: */ - fsize = 1; - for(ll = 0; ll < footprint->nd; ll++) - fsize *= footprint->dimensions[ll]; - pf = (Bool*)PyArray_DATA(footprint); - for(jj = 0; jj < fsize; jj++) { - if (pf[jj]) { - ++filter_size; - } - } - /* get the structure: */ - if (structure) { - ss = (double*)malloc(filter_size * sizeof(double)); - if (!ss) { - PyErr_NoMemory(); - goto exit; - } - /* copy the weights to contiguous memory: */ - ps = (Float64*)PyArray_DATA(structure); - jj = 0; - for(kk = 0; kk < fsize; kk++) - if (pf[kk]) - ss[jj++] = minimum ? -ps[kk] : ps[kk]; - } - /* initialize filter offsets: */ - if (!NI_InitFilterOffsets(input, pf, footprint->dimensions, origins, - mode, &offsets, &border_flag_value, NULL)) - goto exit; - /* initialize filter iterator: */ - if (!NI_InitFilterIterator(input->nd, footprint->dimensions, - filter_size, input->dimensions, origins, &fi)) - goto exit; - /* initialize input element iterator: */ - if (!NI_InitPointIterator(input, &ii)) - goto exit; - /* initialize output element iterator: */ - if (!NI_InitPointIterator(output, &io)) - goto exit; - /* get data pointers an array size: */ - pi = (void *)PyArray_DATA(input); - po = (void *)PyArray_DATA(output); - size = 1; - for(ll = 0; ll < input->nd; ll++) - size *= input->dimensions[ll]; - /* iterator over the elements: */ - oo = offsets; - for(jj = 0; jj < size; jj++) { - double tmp = 0.0; - switch (input->descr->type_num) { - CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Bool, - minimum, tmp, border_flag_value, ss); - CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt8, - minimum, tmp, border_flag_value, ss); - CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt16, - minimum, tmp, border_flag_value, ss); - CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt32, - minimum, tmp, border_flag_value, ss); -#if HAS_UINT64 - CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt64, - minimum, tmp, border_flag_value, ss); -#endif - CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int8, - minimum, tmp, border_flag_value, ss); - CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int16, - minimum, tmp, border_flag_value, ss); - CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int32, - minimum, tmp, border_flag_value, ss); - CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int64, - minimum, tmp, border_flag_value, ss); - CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Float32, - minimum, tmp, border_flag_value, ss); - CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Float64, - minimum, tmp, border_flag_value, ss); - default: - PyErr_SetString(PyExc_RuntimeError, "array type not supported"); - goto exit; - } - switch (output->descr->type_num) { - CASE_FILTER_OUT(po, tmp, Bool); - CASE_FILTER_OUT(po, tmp, UInt8); - CASE_FILTER_OUT(po, tmp, UInt16); - CASE_FILTER_OUT(po, tmp, UInt32); -#if HAS_UINT64 - CASE_FILTER_OUT(po, tmp, UInt64); -#endif - CASE_FILTER_OUT(po, tmp, Int8); - CASE_FILTER_OUT(po, tmp, Int16); - CASE_FILTER_OUT(po, tmp, Int32); - CASE_FILTER_OUT(po, tmp, Int64); - CASE_FILTER_OUT(po, tmp, Float32); - CASE_FILTER_OUT(po, tmp, Float64); - default: - PyErr_SetString(PyExc_RuntimeError, "array type not supported"); - goto exit; - } - NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); - } -exit: - if (offsets) free(offsets); - if (ss) free(ss); - return PyErr_Occurred() ? 0 : 1; -} - -static double NI_Select(double *buffer, int min, int max, int rank) -{ - int ii, jj; - double x, t; - - if (min == max) - return buffer[min]; - - x = buffer[min]; - ii = min - 1; - jj = max + 1; - for(;;) { - do - jj--; - while(buffer[jj] > x); - do - ii++; - while(buffer[ii] < x); - if (ii < jj) { - t = buffer[ii]; - buffer[ii] = buffer[jj]; - buffer[jj] = t; - } else { - break; - } - } - - ii = jj - min + 1; - if (rank < ii) - return NI_Select(buffer, min, jj, rank); - else - return NI_Select(buffer, jj + 1, max, rank - ii); -} - -#define CASE_RANK_POINT(_pi, _offsets, _filter_size, _cval, _type, \ - _rank, _buffer, _res, _mv) \ -case t ## _type: \ -{ \ - maybelong _ii; \ - for(_ii = 0; _ii < _filter_size; _ii++) { \ - maybelong _offset = _offsets[_ii]; \ - if (_offset == _mv) \ - _buffer[_ii] = (_type)_cval; \ - else \ - _buffer[_ii] = *(_type*)(_pi + _offsets[_ii]); \ - } \ - _res = (_type)NI_Select(_buffer, 0, _filter_size - 1, _rank); \ -} \ -break - -int NI_RankFilter(PyArrayObject* input, int rank, - PyArrayObject* footprint, PyArrayObject* output, - NI_ExtendMode mode, double cvalue, maybelong *origins) -{ - maybelong fsize, jj, filter_size = 0, border_flag_value; - maybelong *offsets = NULL, *oo, size; - NI_FilterIterator fi; - NI_Iterator ii, io; - char *pi, *po; - Bool *pf = NULL; - double *buffer = NULL; - int ll; - - /* get the the footprint: */ - fsize = 1; - for(ll = 0; ll < footprint->nd; ll++) - fsize *= footprint->dimensions[ll]; - pf = (Bool*)PyArray_DATA(footprint); - for(jj = 0; jj < fsize; jj++) { - if (pf[jj]) { - ++filter_size; - } - } - /* buffer for rank calculation: */ - buffer = (double*)malloc(filter_size * sizeof(double)); - if (!buffer) { - PyErr_NoMemory(); - goto exit; - } - /* iterator over the elements: */ - oo = offsets; - /* initialize filter offsets: */ - if (!NI_InitFilterOffsets(input, pf, footprint->dimensions, origins, - mode, &offsets, &border_flag_value, NULL)) - goto exit; - /* initialize filter iterator: */ - if (!NI_InitFilterIterator(input->nd, footprint->dimensions, - filter_size, input->dimensions, origins, &fi)) - goto exit; - /* initialize input element iterator: */ - if (!NI_InitPointIterator(input, &ii)) - goto exit; - /* initialize output element iterator: */ - if (!NI_InitPointIterator(output, &io)) - goto exit; - /* get data pointers an array size: */ - pi = (void *)PyArray_DATA(input); - po = (void *)PyArray_DATA(output); - size = 1; - for(ll = 0; ll < input->nd; ll++) - size *= input->dimensions[ll]; - /* iterator over the elements: */ - oo = offsets; - for(jj = 0; jj < size; jj++) { - double tmp = 0.0; - switch (input->descr->type_num) { - CASE_RANK_POINT(pi, oo, filter_size, cvalue, Bool, - rank, buffer, tmp, border_flag_value); - CASE_RANK_POINT(pi, oo, filter_size, cvalue, UInt8, - rank, buffer, tmp, border_flag_value); - CASE_RANK_POINT(pi, oo, filter_size, cvalue, UInt16, - rank, buffer, tmp, border_flag_value); - CASE_RANK_POINT(pi, oo, filter_size, cvalue, UInt32, - rank, buffer, tmp, border_flag_value); -#if HAS_UINT64 - CASE_RANK_POINT(pi, oo, filter_size, cvalue, UInt64, - rank, buffer, tmp, border_flag_value); -#endif - CASE_RANK_POINT(pi, oo, filter_size, cvalue, Int8, - rank, buffer, tmp, border_flag_value); - CASE_RANK_POINT(pi, oo, filter_size, cvalue, Int16, - rank, buffer, tmp, border_flag_value); - CASE_RANK_POINT(pi, oo, filter_size, cvalue, Int32, - rank, buffer, tmp, border_flag_value); - CASE_RANK_POINT(pi, oo, filter_size, cvalue, Int64, - rank, buffer, tmp, border_flag_value); - CASE_RANK_POINT(pi, oo, filter_size, cvalue, Float32, - rank, buffer, tmp, border_flag_value); - CASE_RANK_POINT(pi, oo, filter_size, cvalue, Float64, - rank, buffer, tmp, border_flag_value); - default: - PyErr_SetString(PyExc_RuntimeError, "array type not supported"); - goto exit; - } - switch (output->descr->type_num) { - CASE_FILTER_OUT(po, tmp, Bool); - CASE_FILTER_OUT(po, tmp, UInt8); - CASE_FILTER_OUT(po, tmp, UInt16); - CASE_FILTER_OUT(po, tmp, UInt32); -#if HAS_UINT64 - CASE_FILTER_OUT(po, tmp, UInt64); -#endif - CASE_FILTER_OUT(po, tmp, Int8); - CASE_FILTER_OUT(po, tmp, Int16); - CASE_FILTER_OUT(po, tmp, Int32); - CASE_FILTER_OUT(po, tmp, Int64); - CASE_FILTER_OUT(po, tmp, Float32); - CASE_FILTER_OUT(po, tmp, Float64); - default: - PyErr_SetString(PyExc_RuntimeError, "array type not supported"); - goto exit; - } - NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); - } -exit: - if (offsets) free(offsets); - if (buffer) free(buffer); - return PyErr_Occurred() ? 0 : 1; -} - -int NI_GenericFilter1D(PyArrayObject *input, - int (*function)(double*, maybelong, double*, maybelong, void*), - void* data, long filter_size, int axis, PyArrayObject *output, - NI_ExtendMode mode, double cval, long origin) -{ - int more; - maybelong ii, lines, length, size1, size2; - double *ibuffer = NULL, *obuffer = NULL; - NI_LineBuffer iline_buffer, oline_buffer; - - /* allocate and initialize the line buffers: */ - size1 = filter_size / 2; - size2 = filter_size - size1 - 1; - lines = -1; - if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, - &lines, BUFFER_SIZE, &ibuffer)) - goto exit; - if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, - &obuffer)) - goto exit; - if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, - lines, ibuffer, mode, cval, &iline_buffer)) - goto exit; - if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, - &oline_buffer)) - goto exit; - length = input->nd > 0 ? input->dimensions[axis] : 1; - /* iterate over all the array lines: */ - do { - /* copy lines from array to buffer: */ - if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) - goto exit; - /* iterate over the lines in the buffers: */ - for(ii = 0; ii < lines; ii++) { - /* get lines: */ - double *iline = NI_GET_LINE(iline_buffer, ii); - double *oline = NI_GET_LINE(oline_buffer, ii); - if (!function(iline, length + size1 + size2, oline, length, data)) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_RuntimeError, - "unknown error in line processing function"); - goto exit; - } - } - /* copy lines from buffer to array: */ - if (!NI_LineBufferToArray(&oline_buffer)) - goto exit; - } while(more); -exit: - if (ibuffer) free(ibuffer); - if (obuffer) free(obuffer); - return PyErr_Occurred() ? 0 : 1; -} - -#define CASE_FILTER_POINT(_pi, _offsets, _filter_size, _cvalue, _type, \ - _res, _mv, _function, _data, _buffer) \ -case t ## _type: \ -{ \ - maybelong _ii, _offset; \ - for(_ii = 0; _ii < _filter_size; _ii++) { \ - _offset = _offsets[_ii]; \ - if (_offset == _mv) \ - _buffer[_ii] = (double)_cvalue; \ - else \ - _buffer[_ii] = (double)*(_type*)(_pi + _offset); \ - } \ - if (!_function(_buffer, _filter_size, &_res, _data)) { \ - if (!PyErr_Occurred()) \ - PyErr_SetString(PyExc_RuntimeError, \ - "unknown error in filter function"); \ - goto exit; \ - } \ -} \ -break - - -int NI_GenericFilter(PyArrayObject* input, - int (*function)(double*, maybelong, double*, void*), void *data, - PyArrayObject* footprint, PyArrayObject* output, - NI_ExtendMode mode, double cvalue, maybelong *origins) -{ - Bool *pf = NULL; - maybelong fsize, jj, filter_size = 0, border_flag_value; - maybelong *offsets = NULL, *oo, size; - NI_FilterIterator fi; - NI_Iterator ii, io; - char *pi, *po; - double *buffer = NULL; - int ll; - - /* get the the footprint: */ - fsize = 1; - for(ll = 0; ll < footprint->nd; ll++) - fsize *= footprint->dimensions[ll]; - pf = (Bool*)PyArray_DATA(footprint); - for(jj = 0; jj < fsize; jj++) { - if (pf[jj]) - ++filter_size; - } - /* initialize filter offsets: */ - if (!NI_InitFilterOffsets(input, pf, footprint->dimensions, origins, - mode, &offsets, &border_flag_value, NULL)) - goto exit; - /* initialize filter iterator: */ - if (!NI_InitFilterIterator(input->nd, footprint->dimensions, - filter_size, input->dimensions, origins, &fi)) - goto exit; - /* initialize input element iterator: */ - if (!NI_InitPointIterator(input, &ii)) - goto exit; - /* initialize output element iterator: */ - if (!NI_InitPointIterator(output, &io)) - goto exit; - /* get data pointers an array size: */ - pi = (void *)PyArray_DATA(input); - po = (void *)PyArray_DATA(output); - size = 1; - for(ll = 0; ll < input->nd; ll++) - size *= input->dimensions[ll]; - /* buffer for filter calculation: */ - buffer = (double*)malloc(filter_size * sizeof(double)); - if (!buffer) { - PyErr_NoMemory(); - goto exit; - } - /* iterate over the elements: */ - oo = offsets; - for(jj = 0; jj < size; jj++) { - double tmp = 0.0; - switch (input->descr->type_num) { - CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Bool, - tmp, border_flag_value, function, data, buffer); - CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt8, - tmp, border_flag_value, function, data, buffer); - CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt16, - tmp, border_flag_value, function, data, buffer); - CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt32, - tmp, border_flag_value, function, data, buffer); -#if HAS_UINT64 - CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt64, - tmp, border_flag_value, function, data, buffer); -#endif - CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int8, - tmp, border_flag_value, function, data, buffer); - CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int16, - tmp, border_flag_value, function, data, buffer); - CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int32, - tmp, border_flag_value, function, data, buffer); - CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int64, - tmp, border_flag_value, function, data, buffer); - CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Float32, - tmp, border_flag_value, function, data, buffer); - CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Float64, - tmp, border_flag_value, function, data, buffer); - default: - PyErr_SetString(PyExc_RuntimeError, "array type not supported"); - goto exit; - } - switch (output->descr->type_num) { - CASE_FILTER_OUT(po, tmp, Bool); - CASE_FILTER_OUT(po, tmp, UInt8); - CASE_FILTER_OUT(po, tmp, UInt16); - CASE_FILTER_OUT(po, tmp, UInt32); -#if HAS_UINT64 - CASE_FILTER_OUT(po, tmp, UInt64); -#endif - CASE_FILTER_OUT(po, tmp, Int8); - CASE_FILTER_OUT(po, tmp, Int16); - CASE_FILTER_OUT(po, tmp, Int32); - CASE_FILTER_OUT(po, tmp, Int64); - CASE_FILTER_OUT(po, tmp, Float32); - CASE_FILTER_OUT(po, tmp, Float64); - default: - PyErr_SetString(PyExc_RuntimeError, "array type not supported"); - goto exit; - } - NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); - } -exit: - if (offsets) free(offsets); - if (buffer) free(buffer); - return PyErr_Occurred() ? 0 : 1; -} +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ni_support.h" +#include "ni_filters.h" +#include +#include + +#define BUFFER_SIZE 256000 + +int NI_Correlate1D(PyArrayObject *input, PyArrayObject *weights, + int axis, PyArrayObject *output, NI_ExtendMode mode, + double cval, maybelong origin) +{ + int symmetric = 0, ii, jj, more; + maybelong ll, lines, length, size1, size2, filter_size; + double *ibuffer = NULL, *obuffer = NULL; + Float64 *fw; + NI_LineBuffer iline_buffer, oline_buffer; + + /* test for symmetry or anti-symmetry: */ + filter_size = weights->dimensions[0]; + size1 = filter_size / 2; + size2 = filter_size - size1 - 1; + fw = (void *)PyArray_DATA(weights); + if (filter_size & 0x1) { + symmetric = 1; + for(ii = 1; ii <= filter_size / 2; ii++) { + if (fabs(fw[ii + size1] - fw[size1 - ii]) > DBL_EPSILON) { + symmetric = 0; + break; + } + } + if (symmetric == 0) { + symmetric = -1; + for(ii = 1; ii <= filter_size / 2; ii++) { + if (fabs(fw[size1 + ii] + fw[size1 - ii]) > DBL_EPSILON) { + symmetric = 0; + break; + } + } + } + } + /* allocate and initialize the line buffers: */ + lines = -1; + if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, + &lines, BUFFER_SIZE, &ibuffer)) + goto exit; + if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, + &obuffer)) + goto exit; + if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, + lines, ibuffer, mode, cval, &iline_buffer)) + goto exit; + if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, + &oline_buffer)) + goto exit; + length = input->nd > 0 ? input->dimensions[axis] : 1; + fw += size1; + /* iterate over all the array lines: */ + do { + /* copy lines from array to buffer: */ + if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) + goto exit; + /* iterate over the lines in the buffers: */ + for(ii = 0; ii < lines; ii++) { + /* get lines: */ + double *iline = NI_GET_LINE(iline_buffer, ii) + size1; + double *oline = NI_GET_LINE(oline_buffer, ii); + /* the correlation calculation: */ + if (symmetric > 0) { + for(ll = 0; ll < length; ll++) { + oline[ll] = iline[0] * fw[0]; + for(jj = -size1 ; jj < 0; jj++) + oline[ll] += (iline[jj] + iline[-jj]) * fw[jj]; + ++iline; + } + } else if (symmetric < 0) { + for(ll = 0; ll < length; ll++) { + oline[ll] = iline[0] * fw[0]; + for(jj = -size1 ; jj < 0; jj++) + oline[ll] += (iline[jj] - iline[-jj]) * fw[jj]; + ++iline; + } + } else { + for(ll = 0; ll < length; ll++) { + oline[ll] = iline[size2] * fw[size2]; + for(jj = -size1; jj < size2; jj++) + oline[ll] += iline[jj] * fw[jj]; + ++iline; + } + } + } + /* copy lines from buffer to array: */ + if (!NI_LineBufferToArray(&oline_buffer)) + goto exit; + } while(more); +exit: + if (ibuffer) free(ibuffer); + if (obuffer) free(obuffer); + return PyErr_Occurred() ? 0 : 1; +} + +#define CASE_CORRELATE_POINT(_pi, _weights, _offsets, _filter_size, \ + _cvalue, _type, _res, _mv) \ +case t ## _type: \ +{ \ + maybelong _ii, _offset; \ + for(_ii = 0; _ii < _filter_size; _ii++) { \ + _offset = _offsets[_ii]; \ + if (_offset == _mv) \ + _res += _weights[_ii] * _cvalue; \ + else \ + _res += _weights[_ii] * (double)*(_type*)(_pi + _offset); \ + } \ +} \ +break + +#define CASE_FILTER_OUT(_po, _tmp, _type) \ +case t ## _type: \ + *(_type*)_po = (_type)_tmp; \ + break + +int NI_Correlate(PyArrayObject* input, PyArrayObject* weights, + PyArrayObject* output, NI_ExtendMode mode, + double cvalue, maybelong *origins) +{ + Bool *pf = NULL; + maybelong fsize, jj, kk, filter_size = 0, border_flag_value; + maybelong *offsets = NULL, *oo, size; + NI_FilterIterator fi; + NI_Iterator ii, io; + char *pi, *po; + Float64 *pw; + Float64 *ww = NULL; + int ll; + + /* get the the footprint: */ + fsize = 1; + for(ll = 0; ll < weights->nd; ll++) + fsize *= weights->dimensions[ll]; + pw = (Float64*)PyArray_DATA(weights); + pf = (Bool*)malloc(fsize * sizeof(Bool)); + if (!pf) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < fsize; jj++) { + if (fabs(pw[jj]) > DBL_EPSILON) { + pf[jj] = 1; + ++filter_size; + } else { + pf[jj] = 0; + } + } + /* copy the weights to contiguous memory: */ + ww = (Float64*)malloc(filter_size * sizeof(Float64)); + if (!ww) { + PyErr_NoMemory(); + goto exit; + } + jj = 0; + for(kk = 0; kk < fsize; kk++) { + if (pf[kk]) { + ww[jj++] = pw[kk]; + } + } + /* initialize filter offsets: */ + if (!NI_InitFilterOffsets(input, pf, weights->dimensions, origins, + mode, &offsets, &border_flag_value, NULL)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(input->nd, weights->dimensions, filter_size, + input->dimensions, origins, &fi)) + goto exit; + /* initialize input element iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* initialize output element iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + /* get data pointers an array size: */ + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(ll = 0; ll < input->nd; ll++) + size *= input->dimensions[ll]; + /* iterator over the elements: */ + oo = offsets; + for(jj = 0; jj < size; jj++) { + double tmp = 0.0; + switch (input->descr->type_num) { + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Bool, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt8, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt16, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt32, + tmp, border_flag_value); +#if HAS_UINT64 + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt64, + tmp, border_flag_value); +#endif + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int8, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int16, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int32, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int64, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Float32, + tmp, border_flag_value); + CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Float64, + tmp, border_flag_value); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_FILTER_OUT(po, tmp, Bool); + CASE_FILTER_OUT(po, tmp, UInt8); + CASE_FILTER_OUT(po, tmp, UInt16); + CASE_FILTER_OUT(po, tmp, UInt32); +#if HAS_UINT64 + CASE_FILTER_OUT(po, tmp, UInt64); +#endif + CASE_FILTER_OUT(po, tmp, Int8); + CASE_FILTER_OUT(po, tmp, Int16); + CASE_FILTER_OUT(po, tmp, Int32); + CASE_FILTER_OUT(po, tmp, Int64); + CASE_FILTER_OUT(po, tmp, Float32); + CASE_FILTER_OUT(po, tmp, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); + } +exit: + if (offsets) free(offsets); + if (ww) free(ww); + if (pf) free(pf); + return PyErr_Occurred() ? 0 : 1; +} + +int +NI_UniformFilter1D(PyArrayObject *input, long filter_size, + int axis, PyArrayObject *output, NI_ExtendMode mode, + double cval, long origin) +{ + maybelong lines, kk, ll, length, size1, size2; + int more; + double *ibuffer = NULL, *obuffer = NULL; + NI_LineBuffer iline_buffer, oline_buffer; + + size1 = filter_size / 2; + size2 = filter_size - size1 - 1; + /* allocate and initialize the line buffers: */ + lines = -1; + if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, + &lines, BUFFER_SIZE, &ibuffer)) + goto exit; + if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, + &obuffer)) + goto exit; + if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, + lines, ibuffer, mode, cval, &iline_buffer)) + goto exit; + if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, + &oline_buffer)) + goto exit; + length = input->nd > 0 ? input->dimensions[axis] : 1; + + /* iterate over all the array lines: */ + do { + /* copy lines from array to buffer: */ + if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) + goto exit; + /* iterate over the lines in the buffers: */ + for(kk = 0; kk < lines; kk++) { + /* get lines: */ + double *iline = NI_GET_LINE(iline_buffer, kk); + double *oline = NI_GET_LINE(oline_buffer, kk); + /* do the uniform filter: */ + double tmp = 0.0; + double *l1 = iline; + double *l2 = iline + filter_size; + for(ll = 0; ll < filter_size; ll++) + tmp += iline[ll]; + tmp /= (double)filter_size; + oline[0] = tmp; + for(ll = 1; ll < length; ll++) { + tmp += (*l2++ - *l1++) / (double)filter_size; + oline[ll] = tmp; + } + } + /* copy lines from buffer to array: */ + if (!NI_LineBufferToArray(&oline_buffer)) + goto exit; + } while(more); + + exit: + if (ibuffer) free(ibuffer); + if (obuffer) free(obuffer); + return PyErr_Occurred() ? 0 : 1; +} + +int +NI_MinOrMaxFilter1D(PyArrayObject *input, long filter_size, + int axis, PyArrayObject *output, NI_ExtendMode mode, + double cval, long origin, int minimum) +{ + maybelong lines, kk, jj, ll, length, size1, size2; + int more; + double *ibuffer = NULL, *obuffer = NULL; + NI_LineBuffer iline_buffer, oline_buffer; + + size1 = filter_size / 2; + size2 = filter_size - size1 - 1; + /* allocate and initialize the line buffers: */ + lines = -1; + if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, + &lines, BUFFER_SIZE, &ibuffer)) + goto exit; + if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, + &obuffer)) + goto exit; + if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, + lines, ibuffer, mode, cval, &iline_buffer)) + goto exit; + if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, + &oline_buffer)) + goto exit; + length = input->nd > 0 ? input->dimensions[axis] : 1; + + /* iterate over all the array lines: */ + do { + /* copy lines from array to buffer: */ + if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) + goto exit; + /* iterate over the lines in the buffers: */ + for(kk = 0; kk < lines; kk++) { + /* get lines: */ + double *iline = NI_GET_LINE(iline_buffer, kk) + size1; + double *oline = NI_GET_LINE(oline_buffer, kk); + for(ll = 0; ll < length; ll++) { + /* find minimum or maximum filter: */ + double val = iline[ll - size1]; + for(jj = -size1 + 1; jj <= size2; jj++) { + double tmp = iline[ll + jj]; + if (minimum) { + if (tmp < val) + val = tmp; + } else { + if (tmp > val) + val = tmp; + } + } + oline[ll] = val; + } + } + /* copy lines from buffer to array: */ + if (!NI_LineBufferToArray(&oline_buffer)) + goto exit; + } while(more); + + exit: + if (ibuffer) free(ibuffer); + if (obuffer) free(obuffer); + return PyErr_Occurred() ? 0 : 1; +} + + +#define CASE_MIN_OR_MAX_POINT(_pi, _offsets, _filter_size, _cval, \ + _type, _minimum, _res, _mv, _ss) \ +case t ## _type: \ +{ \ + maybelong _ii, _oo = *_offsets; \ + _type _cv = (_type)_cval, _tmp; \ + _res = _oo == _mv ? _cv : *(_type*)(_pi + _oo); \ + if (_ss) \ + _res += *_ss; \ + for(_ii = 1; _ii < _filter_size; _ii++) { \ + _oo = _offsets[_ii]; \ + _tmp = _oo == _mv ? _cv : *(_type*)(_pi + _oo); \ + if (_ss) \ + _tmp += _ss[_ii]; \ + if (_minimum) { \ + if (_tmp < _res) \ + _res = (_type)_tmp; \ + } else { \ + if (_tmp > _res) \ + _res = (_type)_tmp; \ + } \ + } \ +} \ +break + +int NI_MinOrMaxFilter(PyArrayObject* input, PyArrayObject* footprint, + PyArrayObject* structure, PyArrayObject* output, + NI_ExtendMode mode, double cvalue, maybelong *origins, int minimum) +{ + Bool *pf = NULL; + maybelong fsize, jj, kk, filter_size = 0, border_flag_value; + maybelong *offsets = NULL, *oo, size; + NI_FilterIterator fi; + NI_Iterator ii, io; + char *pi, *po; + int ll; + double *ss = NULL; + Float64 *ps; + + /* get the the footprint: */ + fsize = 1; + for(ll = 0; ll < footprint->nd; ll++) + fsize *= footprint->dimensions[ll]; + pf = (Bool*)PyArray_DATA(footprint); + for(jj = 0; jj < fsize; jj++) { + if (pf[jj]) { + ++filter_size; + } + } + /* get the structure: */ + if (structure) { + ss = (double*)malloc(filter_size * sizeof(double)); + if (!ss) { + PyErr_NoMemory(); + goto exit; + } + /* copy the weights to contiguous memory: */ + ps = (Float64*)PyArray_DATA(structure); + jj = 0; + for(kk = 0; kk < fsize; kk++) + if (pf[kk]) + ss[jj++] = minimum ? -ps[kk] : ps[kk]; + } + /* initialize filter offsets: */ + if (!NI_InitFilterOffsets(input, pf, footprint->dimensions, origins, + mode, &offsets, &border_flag_value, NULL)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(input->nd, footprint->dimensions, + filter_size, input->dimensions, origins, &fi)) + goto exit; + /* initialize input element iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* initialize output element iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + /* get data pointers an array size: */ + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(ll = 0; ll < input->nd; ll++) + size *= input->dimensions[ll]; + /* iterator over the elements: */ + oo = offsets; + for(jj = 0; jj < size; jj++) { + double tmp = 0.0; + switch (input->descr->type_num) { + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Bool, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt8, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt16, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt32, + minimum, tmp, border_flag_value, ss); +#if HAS_UINT64 + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt64, + minimum, tmp, border_flag_value, ss); +#endif + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int8, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int16, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int32, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int64, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Float32, + minimum, tmp, border_flag_value, ss); + CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Float64, + minimum, tmp, border_flag_value, ss); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_FILTER_OUT(po, tmp, Bool); + CASE_FILTER_OUT(po, tmp, UInt8); + CASE_FILTER_OUT(po, tmp, UInt16); + CASE_FILTER_OUT(po, tmp, UInt32); +#if HAS_UINT64 + CASE_FILTER_OUT(po, tmp, UInt64); +#endif + CASE_FILTER_OUT(po, tmp, Int8); + CASE_FILTER_OUT(po, tmp, Int16); + CASE_FILTER_OUT(po, tmp, Int32); + CASE_FILTER_OUT(po, tmp, Int64); + CASE_FILTER_OUT(po, tmp, Float32); + CASE_FILTER_OUT(po, tmp, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); + } +exit: + if (offsets) free(offsets); + if (ss) free(ss); + return PyErr_Occurred() ? 0 : 1; +} + +static double NI_Select(double *buffer, int min, int max, int rank) +{ + int ii, jj; + double x, t; + + if (min == max) + return buffer[min]; + + x = buffer[min]; + ii = min - 1; + jj = max + 1; + for(;;) { + do + jj--; + while(buffer[jj] > x); + do + ii++; + while(buffer[ii] < x); + if (ii < jj) { + t = buffer[ii]; + buffer[ii] = buffer[jj]; + buffer[jj] = t; + } else { + break; + } + } + + ii = jj - min + 1; + if (rank < ii) + return NI_Select(buffer, min, jj, rank); + else + return NI_Select(buffer, jj + 1, max, rank - ii); +} + +#define CASE_RANK_POINT(_pi, _offsets, _filter_size, _cval, _type, \ + _rank, _buffer, _res, _mv) \ +case t ## _type: \ +{ \ + maybelong _ii; \ + for(_ii = 0; _ii < _filter_size; _ii++) { \ + maybelong _offset = _offsets[_ii]; \ + if (_offset == _mv) \ + _buffer[_ii] = (_type)_cval; \ + else \ + _buffer[_ii] = *(_type*)(_pi + _offsets[_ii]); \ + } \ + _res = (_type)NI_Select(_buffer, 0, _filter_size - 1, _rank); \ +} \ +break + +int NI_RankFilter(PyArrayObject* input, int rank, + PyArrayObject* footprint, PyArrayObject* output, + NI_ExtendMode mode, double cvalue, maybelong *origins) +{ + maybelong fsize, jj, filter_size = 0, border_flag_value; + maybelong *offsets = NULL, *oo, size; + NI_FilterIterator fi; + NI_Iterator ii, io; + char *pi, *po; + Bool *pf = NULL; + double *buffer = NULL; + int ll; + + /* get the the footprint: */ + fsize = 1; + for(ll = 0; ll < footprint->nd; ll++) + fsize *= footprint->dimensions[ll]; + pf = (Bool*)PyArray_DATA(footprint); + for(jj = 0; jj < fsize; jj++) { + if (pf[jj]) { + ++filter_size; + } + } + /* buffer for rank calculation: */ + buffer = (double*)malloc(filter_size * sizeof(double)); + if (!buffer) { + PyErr_NoMemory(); + goto exit; + } + /* iterator over the elements: */ + oo = offsets; + /* initialize filter offsets: */ + if (!NI_InitFilterOffsets(input, pf, footprint->dimensions, origins, + mode, &offsets, &border_flag_value, NULL)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(input->nd, footprint->dimensions, + filter_size, input->dimensions, origins, &fi)) + goto exit; + /* initialize input element iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* initialize output element iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + /* get data pointers an array size: */ + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(ll = 0; ll < input->nd; ll++) + size *= input->dimensions[ll]; + /* iterator over the elements: */ + oo = offsets; + for(jj = 0; jj < size; jj++) { + double tmp = 0.0; + switch (input->descr->type_num) { + CASE_RANK_POINT(pi, oo, filter_size, cvalue, Bool, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, UInt8, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, UInt16, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, UInt32, + rank, buffer, tmp, border_flag_value); +#if HAS_UINT64 + CASE_RANK_POINT(pi, oo, filter_size, cvalue, UInt64, + rank, buffer, tmp, border_flag_value); +#endif + CASE_RANK_POINT(pi, oo, filter_size, cvalue, Int8, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, Int16, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, Int32, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, Int64, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, Float32, + rank, buffer, tmp, border_flag_value); + CASE_RANK_POINT(pi, oo, filter_size, cvalue, Float64, + rank, buffer, tmp, border_flag_value); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_FILTER_OUT(po, tmp, Bool); + CASE_FILTER_OUT(po, tmp, UInt8); + CASE_FILTER_OUT(po, tmp, UInt16); + CASE_FILTER_OUT(po, tmp, UInt32); +#if HAS_UINT64 + CASE_FILTER_OUT(po, tmp, UInt64); +#endif + CASE_FILTER_OUT(po, tmp, Int8); + CASE_FILTER_OUT(po, tmp, Int16); + CASE_FILTER_OUT(po, tmp, Int32); + CASE_FILTER_OUT(po, tmp, Int64); + CASE_FILTER_OUT(po, tmp, Float32); + CASE_FILTER_OUT(po, tmp, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); + } +exit: + if (offsets) free(offsets); + if (buffer) free(buffer); + return PyErr_Occurred() ? 0 : 1; +} + +int NI_GenericFilter1D(PyArrayObject *input, + int (*function)(double*, maybelong, double*, maybelong, void*), + void* data, long filter_size, int axis, PyArrayObject *output, + NI_ExtendMode mode, double cval, long origin) +{ + int more; + maybelong ii, lines, length, size1, size2; + double *ibuffer = NULL, *obuffer = NULL; + NI_LineBuffer iline_buffer, oline_buffer; + + /* allocate and initialize the line buffers: */ + size1 = filter_size / 2; + size2 = filter_size - size1 - 1; + lines = -1; + if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, + &lines, BUFFER_SIZE, &ibuffer)) + goto exit; + if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, + &obuffer)) + goto exit; + if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, + lines, ibuffer, mode, cval, &iline_buffer)) + goto exit; + if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, + &oline_buffer)) + goto exit; + length = input->nd > 0 ? input->dimensions[axis] : 1; + /* iterate over all the array lines: */ + do { + /* copy lines from array to buffer: */ + if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) + goto exit; + /* iterate over the lines in the buffers: */ + for(ii = 0; ii < lines; ii++) { + /* get lines: */ + double *iline = NI_GET_LINE(iline_buffer, ii); + double *oline = NI_GET_LINE(oline_buffer, ii); + if (!function(iline, length + size1 + size2, oline, length, data)) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, + "unknown error in line processing function"); + goto exit; + } + } + /* copy lines from buffer to array: */ + if (!NI_LineBufferToArray(&oline_buffer)) + goto exit; + } while(more); +exit: + if (ibuffer) free(ibuffer); + if (obuffer) free(obuffer); + return PyErr_Occurred() ? 0 : 1; +} + +#define CASE_FILTER_POINT(_pi, _offsets, _filter_size, _cvalue, _type, \ + _res, _mv, _function, _data, _buffer) \ +case t ## _type: \ +{ \ + maybelong _ii, _offset; \ + for(_ii = 0; _ii < _filter_size; _ii++) { \ + _offset = _offsets[_ii]; \ + if (_offset == _mv) \ + _buffer[_ii] = (double)_cvalue; \ + else \ + _buffer[_ii] = (double)*(_type*)(_pi + _offset); \ + } \ + if (!_function(_buffer, _filter_size, &_res, _data)) { \ + if (!PyErr_Occurred()) \ + PyErr_SetString(PyExc_RuntimeError, \ + "unknown error in filter function"); \ + goto exit; \ + } \ +} \ +break + + +int NI_GenericFilter(PyArrayObject* input, + int (*function)(double*, maybelong, double*, void*), void *data, + PyArrayObject* footprint, PyArrayObject* output, + NI_ExtendMode mode, double cvalue, maybelong *origins) +{ + Bool *pf = NULL; + maybelong fsize, jj, filter_size = 0, border_flag_value; + maybelong *offsets = NULL, *oo, size; + NI_FilterIterator fi; + NI_Iterator ii, io; + char *pi, *po; + double *buffer = NULL; + int ll; + + /* get the the footprint: */ + fsize = 1; + for(ll = 0; ll < footprint->nd; ll++) + fsize *= footprint->dimensions[ll]; + pf = (Bool*)PyArray_DATA(footprint); + for(jj = 0; jj < fsize; jj++) { + if (pf[jj]) + ++filter_size; + } + /* initialize filter offsets: */ + if (!NI_InitFilterOffsets(input, pf, footprint->dimensions, origins, + mode, &offsets, &border_flag_value, NULL)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(input->nd, footprint->dimensions, + filter_size, input->dimensions, origins, &fi)) + goto exit; + /* initialize input element iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* initialize output element iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + /* get data pointers an array size: */ + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(ll = 0; ll < input->nd; ll++) + size *= input->dimensions[ll]; + /* buffer for filter calculation: */ + buffer = (double*)malloc(filter_size * sizeof(double)); + if (!buffer) { + PyErr_NoMemory(); + goto exit; + } + /* iterate over the elements: */ + oo = offsets; + for(jj = 0; jj < size; jj++) { + double tmp = 0.0; + switch (input->descr->type_num) { + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Bool, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt8, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt16, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt32, + tmp, border_flag_value, function, data, buffer); +#if HAS_UINT64 + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt64, + tmp, border_flag_value, function, data, buffer); +#endif + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int8, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int16, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int32, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int64, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Float32, + tmp, border_flag_value, function, data, buffer); + CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Float64, + tmp, border_flag_value, function, data, buffer); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_FILTER_OUT(po, tmp, Bool); + CASE_FILTER_OUT(po, tmp, UInt8); + CASE_FILTER_OUT(po, tmp, UInt16); + CASE_FILTER_OUT(po, tmp, UInt32); +#if HAS_UINT64 + CASE_FILTER_OUT(po, tmp, UInt64); +#endif + CASE_FILTER_OUT(po, tmp, Int8); + CASE_FILTER_OUT(po, tmp, Int16); + CASE_FILTER_OUT(po, tmp, Int32); + CASE_FILTER_OUT(po, tmp, Int64); + CASE_FILTER_OUT(po, tmp, Float32); + CASE_FILTER_OUT(po, tmp, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + goto exit; + } + NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); + } +exit: + if (offsets) free(offsets); + if (buffer) free(buffer); + return PyErr_Occurred() ? 0 : 1; +} Modified: trunk/scipy/ndimage/src/ni_filters.h =================================================================== --- trunk/scipy/ndimage/src/ni_filters.h 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/ni_filters.h 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,54 +1,54 @@ -/* Copyright (C) 2003-2005 Peter J. Verveer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef NI_FILTERS_H -#define NI_FILTERS_H - -int NI_Correlate1D(PyArrayObject*, PyArrayObject*, int, PyArrayObject*, - NI_ExtendMode, double, maybelong); -int NI_Correlate(PyArrayObject*, PyArrayObject*, PyArrayObject*, - NI_ExtendMode, double, maybelong*); -int NI_UniformFilter1D(PyArrayObject*, long, int, PyArrayObject*, - NI_ExtendMode, double, long); -int NI_MinOrMaxFilter1D(PyArrayObject*, long, int, PyArrayObject*, - NI_ExtendMode, double, long, int); -int NI_MinOrMaxFilter(PyArrayObject*, PyArrayObject*, PyArrayObject*, - PyArrayObject*, NI_ExtendMode, double, maybelong*, - int); -int NI_RankFilter(PyArrayObject*, int, PyArrayObject*, PyArrayObject*, - NI_ExtendMode, double, maybelong*); -int NI_GenericFilter1D(PyArrayObject*, int (*)(double*, maybelong, - double*, maybelong, void*), void*, long, int, - PyArrayObject*, NI_ExtendMode, double, long); -int NI_GenericFilter(PyArrayObject*, int (*)(double*, maybelong, double*, - void*), void*, PyArrayObject*, PyArrayObject*, - NI_ExtendMode, double, maybelong*); -#endif +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NI_FILTERS_H +#define NI_FILTERS_H + +int NI_Correlate1D(PyArrayObject*, PyArrayObject*, int, PyArrayObject*, + NI_ExtendMode, double, maybelong); +int NI_Correlate(PyArrayObject*, PyArrayObject*, PyArrayObject*, + NI_ExtendMode, double, maybelong*); +int NI_UniformFilter1D(PyArrayObject*, long, int, PyArrayObject*, + NI_ExtendMode, double, long); +int NI_MinOrMaxFilter1D(PyArrayObject*, long, int, PyArrayObject*, + NI_ExtendMode, double, long, int); +int NI_MinOrMaxFilter(PyArrayObject*, PyArrayObject*, PyArrayObject*, + PyArrayObject*, NI_ExtendMode, double, maybelong*, + int); +int NI_RankFilter(PyArrayObject*, int, PyArrayObject*, PyArrayObject*, + NI_ExtendMode, double, maybelong*); +int NI_GenericFilter1D(PyArrayObject*, int (*)(double*, maybelong, + double*, maybelong, void*), void*, long, int, + PyArrayObject*, NI_ExtendMode, double, long); +int NI_GenericFilter(PyArrayObject*, int (*)(double*, maybelong, double*, + void*), void*, PyArrayObject*, PyArrayObject*, + NI_ExtendMode, double, maybelong*); +#endif Modified: trunk/scipy/ndimage/src/ni_fourier.c =================================================================== --- trunk/scipy/ndimage/src/ni_fourier.c 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/ni_fourier.c 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,548 +1,548 @@ -/* Copyright (C) 2003-2005 Peter J. Verveer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ni_support.h" -#include -#include -#include - -#if !defined(M_PI) -#define M_PI 3.14159265358979323846 -#endif - -#define _NI_GAUSSIAN 0 -#define _NI_UNIFORM 1 -#define _NI_ELLIPSOID 2 - -static double polevl(double x, const double coef[], int N) -{ - double ans; - const double *p = coef; - int i = N; - - ans = *p++; - do - ans = ans * x + *p++; - while(--i); - - return ans ; -} - -double p1evl(double x, const double coef[], int N) -{ - double ans; - const double *p = coef; - int i = N - 1; - - ans = x + *p++; - do - ans = ans * x + *p++; - while(--i); - - return ans; -} - -#define THPIO4 2.35619449019234492885 -#define SQ2OPI .79788456080286535588 -#define Z1 1.46819706421238932572E1 -#define Z2 4.92184563216946036703E1 - -static double _bessel_j1(double x) -{ - double w, z, p, q, xn; - const double RP[4] = { - -8.99971225705559398224E8, - 4.52228297998194034323E11, - -7.27494245221818276015E13, - 3.68295732863852883286E15, - }; - const double RQ[8] = { - 6.20836478118054335476E2, - 2.56987256757748830383E5, - 8.35146791431949253037E7, - 2.21511595479792499675E10, - 4.74914122079991414898E12, - 7.84369607876235854894E14, - 8.95222336184627338078E16, - 5.32278620332680085395E18, - }; - const double PP[7] = { - 7.62125616208173112003E-4, - 7.31397056940917570436E-2, - 1.12719608129684925192E0, - 5.11207951146807644818E0, - 8.42404590141772420927E0, - 5.21451598682361504063E0, - 1.00000000000000000254E0, - }; - const double PQ[7] = { - 5.71323128072548699714E-4, - 6.88455908754495404082E-2, - 1.10514232634061696926E0, - 5.07386386128601488557E0, - 8.39985554327604159757E0, - 5.20982848682361821619E0, - 9.99999999999999997461E-1, - }; - const double QP[8] = { - 5.10862594750176621635E-2, - 4.98213872951233449420E0, - 7.58238284132545283818E1, - 3.66779609360150777800E2, - 7.10856304998926107277E2, - 5.97489612400613639965E2, - 2.11688757100572135698E2, - 2.52070205858023719784E1, - }; - const double QQ[7] = { - 7.42373277035675149943E1, - 1.05644886038262816351E3, - 4.98641058337653607651E3, - 9.56231892404756170795E3, - 7.99704160447350683650E3, - 2.82619278517639096600E3, - 3.36093607810698293419E2, - }; - - w = x; - if (x < 0) - w = -x; - - if (w <= 5.0) { - z = x * x; - w = polevl(z, RP, 3) / p1evl(z, RQ, 8); - w = w * x * (z - Z1) * (z - Z2); - return w ; - } - - w = 5.0 / x; - z = w * w; - p = polevl(z, PP, 6) / polevl(z, PQ, 6); - q = polevl(z, QP, 7) / p1evl(z, QQ, 7); - xn = x - THPIO4; - p = p * cos(xn) - w * q * sin(xn); - return p * SQ2OPI / sqrt(x); -} - -#define CASE_FOURIER_OUT_RR(_po, _tmp, _type) \ -case t ## _type: \ - *(_type*)_po = _tmp; \ - break - -#define CASE_FOURIER_OUT_RC(_po, _tmp, _type) \ -case t ## _type: \ - (*(_type*)_po).real = tmp; \ - (*(_type*)_po).imag = 0.0; \ - break - -#define CASE_FOURIER_OUT_CC(_po, _tmp_r, _tmp_i, _type) \ -case t ## _type: \ - (*(_type*)_po).real = _tmp_r; \ - (*(_type*)_po).imag = _tmp_i; \ - break - -#define CASE_FOURIER_FILTER_RC(_pi, _tmp, _tmp_r, _tmp_i, _type) \ -case t ## _type: \ - _tmp_r = (*(_type*)_pi).real * _tmp; \ - _tmp_i = (*(_type*)_pi).imag * _tmp; \ - break; - -#define CASE_FOURIER_FILTER_RR(_pi, _tmp, _type) \ -case t ## _type: \ - _tmp *= *(_type*)_pi; \ - break; - -int NI_FourierFilter(PyArrayObject *input, PyArrayObject* parameter_array, - maybelong n, int axis, PyArrayObject* output, int filter_type) -{ - NI_Iterator ii, io; - char *pi, *po; - double *parameters = NULL, **params = NULL; - maybelong kk, hh, size; - Float64 *iparameters = (void *)PyArray_DATA(parameter_array); - int ll; - - /* precalculate the parameters: */ - parameters = (double*)malloc(input->nd * sizeof(double)); - if (!parameters) { - PyErr_NoMemory(); - goto exit; - } - for(kk = 0; kk < input->nd; kk++) { - /* along the direction of the real transform we must use the given - length of that dimensons, unless a complex transform is assumed - (n < 0): */ - int shape = kk == axis ? - (n < 0 ? input->dimensions[kk] : n) : input->dimensions[kk]; - switch (filter_type) { - case _NI_GAUSSIAN: - parameters[kk] = *iparameters++ * M_PI / (double)shape; - parameters[kk] = -2.0 * parameters[kk] * parameters[kk]; - break; - case _NI_ELLIPSOID: - case _NI_UNIFORM: - parameters[kk] = *iparameters++; - break; - } - } - /* allocate memory for tables: */ - params = (double**) malloc(input->nd * sizeof(double*)); - if (!params) { - PyErr_NoMemory(); - goto exit; - } - for(kk = 0; kk < input->nd; kk++) - params[kk] = NULL; - for(kk = 0; kk < input->nd; kk++) { - if (input->dimensions[kk] > 1) { - params[kk] = (double*)malloc(input->dimensions[kk] * sizeof(double)); - if (!params[kk]) { - PyErr_NoMemory(); - goto exit; - } - } - } - switch (filter_type) { - case _NI_GAUSSIAN: - /* calculate the tables of exponentials: */ - for (hh = 0; hh < input->nd; hh++) { - if (params[hh]) { - if (hh == axis && n >= 0) { - for(kk = 0; kk < input->dimensions[hh]; kk++) { - double tmp = parameters[hh] * kk * kk; - params[hh][kk] = fabs(tmp) > 50.0 ? 0.0 : exp(tmp); - } - } else { - int jj = 0; - for(kk = 0; kk < (input->dimensions[hh] + 1) / 2; kk++) { - double tmp = parameters[hh] * kk * kk; - params[hh][jj++] = fabs(tmp) > 50.0 ? 0.0 : exp(tmp); - } - for(kk = -(input->dimensions[hh] / 2); kk < 0; kk++) { - double tmp = parameters[hh] * kk * kk; - params[hh][jj++] = fabs(tmp) > 50.0 ? 0.0 : exp(tmp); - } - } - } - } - break; - case _NI_UNIFORM: - /* calculate the tables of parameters: */ - for (hh = 0; hh < input->nd; hh++) { - if (params[hh]) { - params[hh][0] = 1.0; - if (hh == axis && n >= 0) { - double tmp = M_PI * parameters[hh] / n; - for(kk = 1; kk < input->dimensions[hh]; kk++) - params[hh][kk] = tmp > 0.0 ? - sin(tmp * kk) / (tmp * kk) : 0.0; - } else { - double tmp = M_PI * parameters[hh] / input->dimensions[hh]; - int jj = 1; - for(kk = 1; kk < (input->dimensions[hh] + 1) / 2; kk++) - params[hh][jj++] = tmp > 0.0 ? - sin(tmp * kk) / (tmp * kk) : 0.0; - for(kk = -(input->dimensions[hh] / 2); kk < 0; kk++) - params[hh][jj++] = tmp > 0.0 ? - sin(tmp * kk) / (tmp * kk) : 0.0; - } - } - } - break; - case _NI_ELLIPSOID: - /* calculate the tables of parameters: */ - for (hh = 0; hh < input->nd; hh++) { - if (params[hh]) { - params[hh][0] = 1.0; - if (hh == axis && n >= 0) { - double tmp = M_PI * parameters[hh] / n; - for(kk = 0; kk < input->dimensions[hh]; kk++) - params[hh][kk] = (double)kk * tmp; - } else { - double tmp = M_PI * parameters[hh] / input->dimensions[hh]; - int jj = 0; - for(kk = 0; kk < (input->dimensions[hh] + 1) / 2; kk++) - params[hh][jj++] = (double)kk * tmp; - for(kk = -(input->dimensions[hh] / 2); kk < 0; kk++) - params[hh][jj++] = (double)kk * tmp; - } - } else if (input->dimensions[hh] > 0) { - params[hh][0] = 1.0; - } - } - if (input->nd > 1) - for(hh = 0; hh < input->nd; hh++) - for(kk = 0; kk < input->dimensions[hh]; kk++) - params[hh][kk] = params[hh][kk] * params[hh][kk]; - break; - default: - break; - } - /* initialize input element iterator: */ - if (!NI_InitPointIterator(input, &ii)) - goto exit; - /* initialize output element iterator: */ - if (!NI_InitPointIterator(output, &io)) - goto exit; - pi = (void *)PyArray_DATA(input); - po = (void *)PyArray_DATA(output); - size = 1; - for(ll = 0; ll < input->nd; ll++) - size *= input->dimensions[ll]; - /* iterator over the elements: */ - for(hh = 0; hh < size; hh++) { - double tmp = 1.0; - switch (filter_type) { - case _NI_GAUSSIAN: - case _NI_UNIFORM: - for(kk = 0; kk < input->nd; kk++) - if (params[kk]) - tmp *= params[kk][ii.coordinates[kk]]; - break; - case _NI_ELLIPSOID: - switch (input->nd) { - case 1: - tmp = params[0][ii.coordinates[0]]; - tmp = tmp > 0.0 ? sin(tmp) / (tmp) : 1.0; - break; - case 2: - tmp = 0.0; - for(kk = 0; kk < 2; kk++) - tmp += params[kk][ii.coordinates[kk]]; - tmp = sqrt(tmp); - tmp = tmp > 0.0 ? 2.0 * _bessel_j1(tmp) / tmp : 1.0; - break; - case 3: - { - double r = 0.0; - for(kk = 0; kk < 3; kk++) - r += params[kk][ii.coordinates[kk]]; - r = sqrt(r); - if (r > 0.0) { - tmp = 3.0 * (sin(r) - r * cos(r)); - tmp /= r * r * r; - } else { - tmp = 1.0; - } - } - break; - } - break; - default: - break; - } - if (input->descr->type_num == tComplex64 || - input->descr->type_num == tComplex128) { - double tmp_r = 0.0, tmp_i = 0.0; - switch (input->descr->type_num) { - CASE_FOURIER_FILTER_RC(pi, tmp, tmp_r, tmp_i, Complex64); - CASE_FOURIER_FILTER_RC(pi, tmp, tmp_r, tmp_i, Complex128); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - switch (output->descr->type_num) { - CASE_FOURIER_OUT_CC(po, tmp_r, tmp_i, Complex64); - CASE_FOURIER_OUT_CC(po, tmp_r, tmp_i, Complex128); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - } else { - switch (input->descr->type_num) { - CASE_FOURIER_FILTER_RR(pi, tmp, Bool) - CASE_FOURIER_FILTER_RR(pi, tmp, UInt8) - CASE_FOURIER_FILTER_RR(pi, tmp, UInt16) - CASE_FOURIER_FILTER_RR(pi, tmp, UInt32) -#if HAS_UINT64 - CASE_FOURIER_FILTER_RR(pi, tmp, UInt64) -#endif - CASE_FOURIER_FILTER_RR(pi, tmp, Int8) - CASE_FOURIER_FILTER_RR(pi, tmp, Int16) - CASE_FOURIER_FILTER_RR(pi, tmp, Int32) - CASE_FOURIER_FILTER_RR(pi, tmp, Int64) - CASE_FOURIER_FILTER_RR(pi, tmp, Float32) - CASE_FOURIER_FILTER_RR(pi, tmp, Float64) - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - switch (output->descr->type_num) { - CASE_FOURIER_OUT_RR(po, tmp, Float32); - CASE_FOURIER_OUT_RR(po, tmp, Float64); - CASE_FOURIER_OUT_RC(po, tmp, Complex64); - CASE_FOURIER_OUT_RC(po, tmp, Complex128); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - } - NI_ITERATOR_NEXT2(ii, io, pi, po); - } - - exit: - if (parameters) free(parameters); - if (params) { - for(kk = 0; kk < input->nd; kk++) - if (params[kk]) free(params[kk]); - free(params); - } - return PyErr_Occurred() ? 0 : 1; -} - -#define CASE_FOURIER_SHIFT_R(_pi, _tmp, _r, _i, _cost, _sint, _type) \ -case t ## _type: \ - _tmp = *(_type*)_pi; \ - _r = _tmp * _cost; \ - _i = _tmp * _sint; \ - break; - -#define CASE_FOURIER_SHIFT_C(_pi, _r, _i, _cost, _sint, _type) \ -case t ## _type: \ - _r = (*(_type*)_pi).real * _cost - (*(_type*)_pi).imag * _sint; \ - _i = (*(_type*)_pi).real * _sint + (*(_type*)_pi).imag * _cost; \ - break; - -int NI_FourierShift(PyArrayObject *input, PyArrayObject* shift_array, - maybelong n, int axis, PyArrayObject* output) -{ - NI_Iterator ii, io; - char *pi, *po; - double *shifts = NULL, **params = NULL; - maybelong kk, hh, size; - Float64 *ishifts = (void *)PyArray_DATA(shift_array); - int ll; - - /* precalculate the shifts: */ - shifts = (double*)malloc(input->nd * sizeof(double)); - if (!shifts) { - PyErr_NoMemory(); - goto exit; - } - for(kk = 0; kk < input->nd; kk++) { - /* along the direction of the real transform we must use the given - length of that dimensons, unless a complex transform is assumed - (n < 0): */ - int shape = kk == axis ? - (n < 0 ? input->dimensions[kk] : n) : input->dimensions[kk]; - shifts[kk] = -2.0 * M_PI * *ishifts++ / (double)shape; - } - /* allocate memory for tables: */ - params = (double**) malloc(input->nd * sizeof(double*)); - if (!params) { - PyErr_NoMemory(); - goto exit; - } - for(kk = 0; kk < input->nd; kk++) - params[kk] = NULL; - for(kk = 0; kk < input->nd; kk++) { - if (input->dimensions[kk] > 1) { - params[kk] = (double*)malloc(input->dimensions[kk] * sizeof(double)); - if (!params[kk]) { - PyErr_NoMemory(); - goto exit; - } - } - } - for (hh = 0; hh < input->nd; hh++) { - if (params[hh]) { - if (hh == axis && n >= 0) { - for(kk = 0; kk < input->dimensions[hh]; kk++) - params[hh][kk] = shifts[hh] * kk; - } else { - int jj = 0; - for(kk = 0; kk < (input->dimensions[hh] + 1) / 2; kk++) { - params[hh][jj++] = shifts[hh] * kk; - } - for(kk = -(input->dimensions[hh] / 2); kk < 0; kk++) { - params[hh][jj++] = shifts[hh] * kk; - } - } - } - } - /* initialize input element iterator: */ - if (!NI_InitPointIterator(input, &ii)) - goto exit; - /* initialize output element iterator: */ - if (!NI_InitPointIterator(output, &io)) - goto exit; - pi = (void *)PyArray_DATA(input); - po = (void *)PyArray_DATA(output); - size = 1; - for(ll = 0; ll < input->nd; ll++) - size *= input->dimensions[ll]; - /* iterator over the elements: */ - for(hh = 0; hh < size; hh++) { - double tmp = 0.0, sint, cost, r = 0.0, i = 0.0; - for(kk = 0; kk < input->nd; kk++) - if (params[kk]) - tmp += params[kk][ii.coordinates[kk]]; - sint = sin(tmp); - cost = cos(tmp); - switch (input->descr->type_num) { - CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Bool) - CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, UInt8) - CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, UInt16) - CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, UInt32) -#if HAS_UINT64 - CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, UInt64) -#endif - CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Int8) - CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Int16) - CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Int32) - CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Int64) - CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Float32) - CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Float64) - CASE_FOURIER_SHIFT_C(pi, r, i, cost, sint, Complex64) - CASE_FOURIER_SHIFT_C(pi, r, i, cost, sint, Complex128) - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - switch (output->descr->type_num) { - CASE_FOURIER_OUT_CC(po, r, i, Complex64); - CASE_FOURIER_OUT_CC(po, r, i, Complex128); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - NI_ITERATOR_NEXT2(ii, io, pi, po); - } - - exit: - if (shifts) free(shifts); - if (params) { - for(kk = 0; kk < input->nd; kk++) - if (params[kk]) free(params[kk]); - free(params); - } - return PyErr_Occurred() ? 0 : 1; -} +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ni_support.h" +#include +#include +#include + +#if !defined(M_PI) +#define M_PI 3.14159265358979323846 +#endif + +#define _NI_GAUSSIAN 0 +#define _NI_UNIFORM 1 +#define _NI_ELLIPSOID 2 + +static double polevl(double x, const double coef[], int N) +{ + double ans; + const double *p = coef; + int i = N; + + ans = *p++; + do + ans = ans * x + *p++; + while(--i); + + return ans ; +} + +double p1evl(double x, const double coef[], int N) +{ + double ans; + const double *p = coef; + int i = N - 1; + + ans = x + *p++; + do + ans = ans * x + *p++; + while(--i); + + return ans; +} + +#define THPIO4 2.35619449019234492885 +#define SQ2OPI .79788456080286535588 +#define Z1 1.46819706421238932572E1 +#define Z2 4.92184563216946036703E1 + +static double _bessel_j1(double x) +{ + double w, z, p, q, xn; + const double RP[4] = { + -8.99971225705559398224E8, + 4.52228297998194034323E11, + -7.27494245221818276015E13, + 3.68295732863852883286E15, + }; + const double RQ[8] = { + 6.20836478118054335476E2, + 2.56987256757748830383E5, + 8.35146791431949253037E7, + 2.21511595479792499675E10, + 4.74914122079991414898E12, + 7.84369607876235854894E14, + 8.95222336184627338078E16, + 5.32278620332680085395E18, + }; + const double PP[7] = { + 7.62125616208173112003E-4, + 7.31397056940917570436E-2, + 1.12719608129684925192E0, + 5.11207951146807644818E0, + 8.42404590141772420927E0, + 5.21451598682361504063E0, + 1.00000000000000000254E0, + }; + const double PQ[7] = { + 5.71323128072548699714E-4, + 6.88455908754495404082E-2, + 1.10514232634061696926E0, + 5.07386386128601488557E0, + 8.39985554327604159757E0, + 5.20982848682361821619E0, + 9.99999999999999997461E-1, + }; + const double QP[8] = { + 5.10862594750176621635E-2, + 4.98213872951233449420E0, + 7.58238284132545283818E1, + 3.66779609360150777800E2, + 7.10856304998926107277E2, + 5.97489612400613639965E2, + 2.11688757100572135698E2, + 2.52070205858023719784E1, + }; + const double QQ[7] = { + 7.42373277035675149943E1, + 1.05644886038262816351E3, + 4.98641058337653607651E3, + 9.56231892404756170795E3, + 7.99704160447350683650E3, + 2.82619278517639096600E3, + 3.36093607810698293419E2, + }; + + w = x; + if (x < 0) + w = -x; + + if (w <= 5.0) { + z = x * x; + w = polevl(z, RP, 3) / p1evl(z, RQ, 8); + w = w * x * (z - Z1) * (z - Z2); + return w ; + } + + w = 5.0 / x; + z = w * w; + p = polevl(z, PP, 6) / polevl(z, PQ, 6); + q = polevl(z, QP, 7) / p1evl(z, QQ, 7); + xn = x - THPIO4; + p = p * cos(xn) - w * q * sin(xn); + return p * SQ2OPI / sqrt(x); +} + +#define CASE_FOURIER_OUT_RR(_po, _tmp, _type) \ +case t ## _type: \ + *(_type*)_po = _tmp; \ + break + +#define CASE_FOURIER_OUT_RC(_po, _tmp, _type) \ +case t ## _type: \ + (*(_type*)_po).real = tmp; \ + (*(_type*)_po).imag = 0.0; \ + break + +#define CASE_FOURIER_OUT_CC(_po, _tmp_r, _tmp_i, _type) \ +case t ## _type: \ + (*(_type*)_po).real = _tmp_r; \ + (*(_type*)_po).imag = _tmp_i; \ + break + +#define CASE_FOURIER_FILTER_RC(_pi, _tmp, _tmp_r, _tmp_i, _type) \ +case t ## _type: \ + _tmp_r = (*(_type*)_pi).real * _tmp; \ + _tmp_i = (*(_type*)_pi).imag * _tmp; \ + break; + +#define CASE_FOURIER_FILTER_RR(_pi, _tmp, _type) \ +case t ## _type: \ + _tmp *= *(_type*)_pi; \ + break; + +int NI_FourierFilter(PyArrayObject *input, PyArrayObject* parameter_array, + maybelong n, int axis, PyArrayObject* output, int filter_type) +{ + NI_Iterator ii, io; + char *pi, *po; + double *parameters = NULL, **params = NULL; + maybelong kk, hh, size; + Float64 *iparameters = (void *)PyArray_DATA(parameter_array); + int ll; + + /* precalculate the parameters: */ + parameters = (double*)malloc(input->nd * sizeof(double)); + if (!parameters) { + PyErr_NoMemory(); + goto exit; + } + for(kk = 0; kk < input->nd; kk++) { + /* along the direction of the real transform we must use the given + length of that dimensons, unless a complex transform is assumed + (n < 0): */ + int shape = kk == axis ? + (n < 0 ? input->dimensions[kk] : n) : input->dimensions[kk]; + switch (filter_type) { + case _NI_GAUSSIAN: + parameters[kk] = *iparameters++ * M_PI / (double)shape; + parameters[kk] = -2.0 * parameters[kk] * parameters[kk]; + break; + case _NI_ELLIPSOID: + case _NI_UNIFORM: + parameters[kk] = *iparameters++; + break; + } + } + /* allocate memory for tables: */ + params = (double**) malloc(input->nd * sizeof(double*)); + if (!params) { + PyErr_NoMemory(); + goto exit; + } + for(kk = 0; kk < input->nd; kk++) + params[kk] = NULL; + for(kk = 0; kk < input->nd; kk++) { + if (input->dimensions[kk] > 1) { + params[kk] = (double*)malloc(input->dimensions[kk] * sizeof(double)); + if (!params[kk]) { + PyErr_NoMemory(); + goto exit; + } + } + } + switch (filter_type) { + case _NI_GAUSSIAN: + /* calculate the tables of exponentials: */ + for (hh = 0; hh < input->nd; hh++) { + if (params[hh]) { + if (hh == axis && n >= 0) { + for(kk = 0; kk < input->dimensions[hh]; kk++) { + double tmp = parameters[hh] * kk * kk; + params[hh][kk] = fabs(tmp) > 50.0 ? 0.0 : exp(tmp); + } + } else { + int jj = 0; + for(kk = 0; kk < (input->dimensions[hh] + 1) / 2; kk++) { + double tmp = parameters[hh] * kk * kk; + params[hh][jj++] = fabs(tmp) > 50.0 ? 0.0 : exp(tmp); + } + for(kk = -(input->dimensions[hh] / 2); kk < 0; kk++) { + double tmp = parameters[hh] * kk * kk; + params[hh][jj++] = fabs(tmp) > 50.0 ? 0.0 : exp(tmp); + } + } + } + } + break; + case _NI_UNIFORM: + /* calculate the tables of parameters: */ + for (hh = 0; hh < input->nd; hh++) { + if (params[hh]) { + params[hh][0] = 1.0; + if (hh == axis && n >= 0) { + double tmp = M_PI * parameters[hh] / n; + for(kk = 1; kk < input->dimensions[hh]; kk++) + params[hh][kk] = tmp > 0.0 ? + sin(tmp * kk) / (tmp * kk) : 0.0; + } else { + double tmp = M_PI * parameters[hh] / input->dimensions[hh]; + int jj = 1; + for(kk = 1; kk < (input->dimensions[hh] + 1) / 2; kk++) + params[hh][jj++] = tmp > 0.0 ? + sin(tmp * kk) / (tmp * kk) : 0.0; + for(kk = -(input->dimensions[hh] / 2); kk < 0; kk++) + params[hh][jj++] = tmp > 0.0 ? + sin(tmp * kk) / (tmp * kk) : 0.0; + } + } + } + break; + case _NI_ELLIPSOID: + /* calculate the tables of parameters: */ + for (hh = 0; hh < input->nd; hh++) { + if (params[hh]) { + params[hh][0] = 1.0; + if (hh == axis && n >= 0) { + double tmp = M_PI * parameters[hh] / n; + for(kk = 0; kk < input->dimensions[hh]; kk++) + params[hh][kk] = (double)kk * tmp; + } else { + double tmp = M_PI * parameters[hh] / input->dimensions[hh]; + int jj = 0; + for(kk = 0; kk < (input->dimensions[hh] + 1) / 2; kk++) + params[hh][jj++] = (double)kk * tmp; + for(kk = -(input->dimensions[hh] / 2); kk < 0; kk++) + params[hh][jj++] = (double)kk * tmp; + } + } else if (input->dimensions[hh] > 0) { + params[hh][0] = 1.0; + } + } + if (input->nd > 1) + for(hh = 0; hh < input->nd; hh++) + for(kk = 0; kk < input->dimensions[hh]; kk++) + params[hh][kk] = params[hh][kk] * params[hh][kk]; + break; + default: + break; + } + /* initialize input element iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* initialize output element iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(ll = 0; ll < input->nd; ll++) + size *= input->dimensions[ll]; + /* iterator over the elements: */ + for(hh = 0; hh < size; hh++) { + double tmp = 1.0; + switch (filter_type) { + case _NI_GAUSSIAN: + case _NI_UNIFORM: + for(kk = 0; kk < input->nd; kk++) + if (params[kk]) + tmp *= params[kk][ii.coordinates[kk]]; + break; + case _NI_ELLIPSOID: + switch (input->nd) { + case 1: + tmp = params[0][ii.coordinates[0]]; + tmp = tmp > 0.0 ? sin(tmp) / (tmp) : 1.0; + break; + case 2: + tmp = 0.0; + for(kk = 0; kk < 2; kk++) + tmp += params[kk][ii.coordinates[kk]]; + tmp = sqrt(tmp); + tmp = tmp > 0.0 ? 2.0 * _bessel_j1(tmp) / tmp : 1.0; + break; + case 3: + { + double r = 0.0; + for(kk = 0; kk < 3; kk++) + r += params[kk][ii.coordinates[kk]]; + r = sqrt(r); + if (r > 0.0) { + tmp = 3.0 * (sin(r) - r * cos(r)); + tmp /= r * r * r; + } else { + tmp = 1.0; + } + } + break; + } + break; + default: + break; + } + if (input->descr->type_num == tComplex64 || + input->descr->type_num == tComplex128) { + double tmp_r = 0.0, tmp_i = 0.0; + switch (input->descr->type_num) { + CASE_FOURIER_FILTER_RC(pi, tmp, tmp_r, tmp_i, Complex64); + CASE_FOURIER_FILTER_RC(pi, tmp, tmp_r, tmp_i, Complex128); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_FOURIER_OUT_CC(po, tmp_r, tmp_i, Complex64); + CASE_FOURIER_OUT_CC(po, tmp_r, tmp_i, Complex128); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + } else { + switch (input->descr->type_num) { + CASE_FOURIER_FILTER_RR(pi, tmp, Bool) + CASE_FOURIER_FILTER_RR(pi, tmp, UInt8) + CASE_FOURIER_FILTER_RR(pi, tmp, UInt16) + CASE_FOURIER_FILTER_RR(pi, tmp, UInt32) +#if HAS_UINT64 + CASE_FOURIER_FILTER_RR(pi, tmp, UInt64) +#endif + CASE_FOURIER_FILTER_RR(pi, tmp, Int8) + CASE_FOURIER_FILTER_RR(pi, tmp, Int16) + CASE_FOURIER_FILTER_RR(pi, tmp, Int32) + CASE_FOURIER_FILTER_RR(pi, tmp, Int64) + CASE_FOURIER_FILTER_RR(pi, tmp, Float32) + CASE_FOURIER_FILTER_RR(pi, tmp, Float64) + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_FOURIER_OUT_RR(po, tmp, Float32); + CASE_FOURIER_OUT_RR(po, tmp, Float64); + CASE_FOURIER_OUT_RC(po, tmp, Complex64); + CASE_FOURIER_OUT_RC(po, tmp, Complex128); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + } + NI_ITERATOR_NEXT2(ii, io, pi, po); + } + + exit: + if (parameters) free(parameters); + if (params) { + for(kk = 0; kk < input->nd; kk++) + if (params[kk]) free(params[kk]); + free(params); + } + return PyErr_Occurred() ? 0 : 1; +} + +#define CASE_FOURIER_SHIFT_R(_pi, _tmp, _r, _i, _cost, _sint, _type) \ +case t ## _type: \ + _tmp = *(_type*)_pi; \ + _r = _tmp * _cost; \ + _i = _tmp * _sint; \ + break; + +#define CASE_FOURIER_SHIFT_C(_pi, _r, _i, _cost, _sint, _type) \ +case t ## _type: \ + _r = (*(_type*)_pi).real * _cost - (*(_type*)_pi).imag * _sint; \ + _i = (*(_type*)_pi).real * _sint + (*(_type*)_pi).imag * _cost; \ + break; + +int NI_FourierShift(PyArrayObject *input, PyArrayObject* shift_array, + maybelong n, int axis, PyArrayObject* output) +{ + NI_Iterator ii, io; + char *pi, *po; + double *shifts = NULL, **params = NULL; + maybelong kk, hh, size; + Float64 *ishifts = (void *)PyArray_DATA(shift_array); + int ll; + + /* precalculate the shifts: */ + shifts = (double*)malloc(input->nd * sizeof(double)); + if (!shifts) { + PyErr_NoMemory(); + goto exit; + } + for(kk = 0; kk < input->nd; kk++) { + /* along the direction of the real transform we must use the given + length of that dimensons, unless a complex transform is assumed + (n < 0): */ + int shape = kk == axis ? + (n < 0 ? input->dimensions[kk] : n) : input->dimensions[kk]; + shifts[kk] = -2.0 * M_PI * *ishifts++ / (double)shape; + } + /* allocate memory for tables: */ + params = (double**) malloc(input->nd * sizeof(double*)); + if (!params) { + PyErr_NoMemory(); + goto exit; + } + for(kk = 0; kk < input->nd; kk++) + params[kk] = NULL; + for(kk = 0; kk < input->nd; kk++) { + if (input->dimensions[kk] > 1) { + params[kk] = (double*)malloc(input->dimensions[kk] * sizeof(double)); + if (!params[kk]) { + PyErr_NoMemory(); + goto exit; + } + } + } + for (hh = 0; hh < input->nd; hh++) { + if (params[hh]) { + if (hh == axis && n >= 0) { + for(kk = 0; kk < input->dimensions[hh]; kk++) + params[hh][kk] = shifts[hh] * kk; + } else { + int jj = 0; + for(kk = 0; kk < (input->dimensions[hh] + 1) / 2; kk++) { + params[hh][jj++] = shifts[hh] * kk; + } + for(kk = -(input->dimensions[hh] / 2); kk < 0; kk++) { + params[hh][jj++] = shifts[hh] * kk; + } + } + } + } + /* initialize input element iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* initialize output element iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(ll = 0; ll < input->nd; ll++) + size *= input->dimensions[ll]; + /* iterator over the elements: */ + for(hh = 0; hh < size; hh++) { + double tmp = 0.0, sint, cost, r = 0.0, i = 0.0; + for(kk = 0; kk < input->nd; kk++) + if (params[kk]) + tmp += params[kk][ii.coordinates[kk]]; + sint = sin(tmp); + cost = cos(tmp); + switch (input->descr->type_num) { + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Bool) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, UInt8) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, UInt16) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, UInt32) +#if HAS_UINT64 + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, UInt64) +#endif + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Int8) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Int16) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Int32) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Int64) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Float32) + CASE_FOURIER_SHIFT_R(pi, tmp, r, i, cost, sint, Float64) + CASE_FOURIER_SHIFT_C(pi, r, i, cost, sint, Complex64) + CASE_FOURIER_SHIFT_C(pi, r, i, cost, sint, Complex128) + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_FOURIER_OUT_CC(po, r, i, Complex64); + CASE_FOURIER_OUT_CC(po, r, i, Complex128); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + NI_ITERATOR_NEXT2(ii, io, pi, po); + } + + exit: + if (shifts) free(shifts); + if (params) { + for(kk = 0; kk < input->nd; kk++) + if (params[kk]) free(params[kk]); + free(params); + } + return PyErr_Occurred() ? 0 : 1; +} Modified: trunk/scipy/ndimage/src/ni_fourier.h =================================================================== --- trunk/scipy/ndimage/src/ni_fourier.h 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/ni_fourier.h 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,40 +1,40 @@ -/* Copyright (C) 2003-2005 Peter J. Verveer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef NI_FOURIER_H -#define NI_FOURIER_H - -int NI_FourierFilter(PyArrayObject*, PyArrayObject*, maybelong, int, - PyArrayObject*, int); -int NI_FourierShift(PyArrayObject*, PyArrayObject*, maybelong, int, - PyArrayObject*); - -#endif +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NI_FOURIER_H +#define NI_FOURIER_H + +int NI_FourierFilter(PyArrayObject*, PyArrayObject*, maybelong, int, + PyArrayObject*, int); +int NI_FourierShift(PyArrayObject*, PyArrayObject*, maybelong, int, + PyArrayObject*); + +#endif Modified: trunk/scipy/ndimage/src/ni_interpolation.c =================================================================== --- trunk/scipy/ndimage/src/ni_interpolation.c 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/ni_interpolation.c 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,966 +1,966 @@ -/* Copyright (C) 2003-2005 Peter J. Verveer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ni_support.h" -#include "ni_interpolation.h" -#include -#include - -/* calculate the B-spline interpolation coefficients for given x: */ -static void -spline_coefficients(double x, int order, double *result) -{ - int hh; - double y, start; - - if (order & 1) { - start = (int)floor(x) - order / 2; - } else { - start = (int)floor(x + 0.5) - order / 2; - } - - for(hh = 0; hh <= order; hh++) { - y = fabs(start - x + hh); - - switch(order) { - case 1: - result[hh] = y > 1.0 ? 0.0 : 1.0 - y; - break; - case 2: - if (y < 0.5) { - result[hh] = 0.75 - y * y; - } else if (y < 1.5) { - y = 1.5 - y; - result[hh] = 0.5 * y * y; - } else { - result[hh] = 0.0; - } - break; - case 3: - if (y < 1.0) { - result[hh] = - (y * y * (y - 2.0) * 3.0 + 4.0) / 6.0; - } else if (y < 2.0) { - y = 2.0 - y; - result[hh] = y * y * y / 6.0; - } else { - result[hh] = 0.0; - } - break; - case 4: - if (y < 0.5) { - y *= y; - result[hh] = y * (y * 0.25 - 0.625) + 115.0 / 192.0; - } else if (y < 1.5) { - result[hh] = y * (y * (y * (5.0 / 6.0 - y / 6.0) - 1.25) + - 5.0 / 24.0) + 55.0 / 96.0; - } else if (y < 2.5) { - y -= 2.5; - y *= y; - result[hh] = y * y / 24.0; - } else { - result[hh] = 0.0; - } - break; - case 5: - if (y < 1.0) { - double f = y * y; - result[hh] = - f * (f * (0.25 - y / 12.0) - 0.5) + 0.55; - } else if (y < 2.0) { - result[hh] = y * (y * (y * (y * (y / 24.0 - 0.375) - + 1.25) - 1.75) + 0.625) + 0.425; - } else if (y < 3.0) { - double f = 3.0 - y; - y = f * f; - result[hh] = f * y * y / 120.0; - } else { - result[hh] = 0.0; - } - break; - } - } -} - -/* map a coordinate outside the borders, according to the requested - boundary condition: */ -static double -map_coordinate(double in, maybelong len, int mode) -{ - if (in < 0) { - switch (mode) { - case NI_EXTEND_MIRROR: - if (len <= 1) { - in = 0; - } else { - maybelong sz2 = 2 * len - 2; - in = sz2 * (maybelong)(-in / sz2) + in; - in = in <= 1 - len ? in + sz2 : -in; - } - break; - case NI_EXTEND_REFLECT: - if (len <= 1) { - in = 0; - } else { - maybelong sz2 = 2 * len; - if (in < -sz2) - in = sz2 * (maybelong)(-in / sz2) + in; - in = in < -len ? in + sz2 : -in - 1; - } - break; - case NI_EXTEND_WRAP: - if (len <= 1) { - in = 0; - } else { - maybelong sz = len - 1; - // Integer division of -in/sz gives (-in mod sz) - // Note that 'in' is negative - in += sz * ((maybelong)(-in / sz) + 1); - } - break; - case NI_EXTEND_NEAREST: - in = 0; - break; - case NI_EXTEND_CONSTANT: - in = -1; - break; - } - } else if (in > len-1) { - switch (mode) { - case NI_EXTEND_MIRROR: - if (len <= 1) { - in = 0; - } else { - maybelong sz2 = 2 * len - 2; - in -= sz2 * (maybelong)(in / sz2); - if (in >= len) - in = sz2 - in; - } - break; - case NI_EXTEND_REFLECT: - if (len <= 1) { - in = 0; - } else { - maybelong sz2 = 2 * len; - in -= sz2 * (maybelong)(in / sz2); - if (in >= len) - in = sz2 - in - 1; - } - break; - case NI_EXTEND_WRAP: - if (len <= 1) { - in = 0; - } else { - maybelong sz = len - 1; - in -= sz * (maybelong)(in / sz); - } - break; - case NI_EXTEND_NEAREST: - in = len - 1; - break; - case NI_EXTEND_CONSTANT: - in = -1; - break; - } - } - - return in; -} - -#define BUFFER_SIZE 256000 -#define TOLERANCE 1e-15 - -/* one-dimensional spline filter: */ -int NI_SplineFilter1D(PyArrayObject *input, int order, int axis, - PyArrayObject *output) -{ - int hh, npoles = 0, more; - maybelong kk, ll, lines, len; - double *buffer = NULL, weight, pole[2]; - NI_LineBuffer iline_buffer, oline_buffer; - - len = input->nd > 0 ? input->dimensions[axis] : 1; - if (len < 1) - goto exit; - - /* these are used in the spline filter calculation below: */ - switch (order) { - case 2: - npoles = 1; - pole[0] = sqrt(8.0) - 3.0; - break; - case 3: - npoles = 1; - pole[0] = sqrt(3.0) - 2.0; - break; - case 4: - npoles = 2; - pole[0] = sqrt(664.0 - sqrt(438976.0)) + sqrt(304.0) - 19.0; - pole[1] = sqrt(664.0 + sqrt(438976.0)) - sqrt(304.0) - 19.0; - break; - case 5: - npoles = 2; - pole[0] = sqrt(67.5 - sqrt(4436.25)) + sqrt(26.25) - 6.5; - pole[1] = sqrt(67.5 + sqrt(4436.25)) - sqrt(26.25) - 6.5; - break; - default: - break; - } - - weight = 1.0; - for(hh = 0; hh < npoles; hh++) - weight *= (1.0 - pole[hh]) * (1.0 - 1.0 / pole[hh]); - - /* allocate an initialize the line buffer, only a single one is used, - because the calculation is in-place: */ - lines = -1; - if (!NI_AllocateLineBuffer(input, axis, 0, 0, &lines, BUFFER_SIZE, - &buffer)) - goto exit; - if (!NI_InitLineBuffer(input, axis, 0, 0, lines, buffer, - NI_EXTEND_DEFAULT, 0.0, &iline_buffer)) - goto exit; - if (!NI_InitLineBuffer(output, axis, 0, 0, lines, buffer, - NI_EXTEND_DEFAULT, 0.0, &oline_buffer)) - goto exit; - - /* iterate over all the array lines: */ - do { - /* copy lines from array to buffer: */ - if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) - goto exit; - /* iterate over the lines in the buffer: */ - for(kk = 0; kk < lines; kk++) { - /* get line: */ - double *ln = NI_GET_LINE(iline_buffer, kk); - /* spline filter: */ - if (len > 1) { - for(ll = 0; ll < len; ll++) - ln[ll] *= weight; - for(hh = 0; hh < npoles; hh++) { - double p = pole[hh]; - int max = (int)ceil(log(TOLERANCE) / log(fabs(p))); - if (max < len) { - double zn = p; - double sum = ln[0]; - for(ll = 1; ll < max; ll++) { - sum += zn * ln[ll]; - zn *= p; - } - ln[0] = sum; - } else { - double zn = p; - double iz = 1.0 / p; - double z2n = pow(p, (double)(len - 1)); - double sum = ln[0] + z2n * ln[len - 1]; - z2n *= z2n * iz; - for(ll = 1; ll <= len - 2; ll++) { - sum += (zn + z2n) * ln[ll]; - zn *= p; - z2n *= iz; - } - ln[0] = sum / (1.0 - zn * zn); - } - for(ll = 1; ll < len; ll++) - ln[ll] += p * ln[ll - 1]; - ln[len-1] = (p / (p * p - 1.0)) * (ln[len-1] + p * ln[len-2]); - for(ll = len - 2; ll >= 0; ll--) - ln[ll] = p * (ln[ll + 1] - ln[ll]); - } - } - } - /* copy lines from buffer to array: */ - if (!NI_LineBufferToArray(&oline_buffer)) - goto exit; - } while(more); - - exit: - if (buffer) free(buffer); - return PyErr_Occurred() ? 0 : 1; -} - -#define CASE_MAP_COORDINATES(_p, _coor, _rank, _stride, _type) \ -case t ## _type: \ -{ \ - int _hh; \ - for(_hh = 0; _hh < _rank; _hh++) { \ - _coor[_hh] = *(_type*)_p; \ - _p += _stride; \ - } \ -} \ -break; - -#define CASE_INTERP_COEFF(_coeff, _pi, _idx, _type) \ -case t ## _type: \ - _coeff = *(_type*)(_pi + _idx); \ - break; - -#define CASE_INTERP_OUT(_po, _t, _type) \ -case t ## _type: \ - *(_type*)_po = (_type)_t; \ - break; - -#define CASE_INTERP_OUT_UINT(_po, _t, _type, type_min, type_max) \ -case t ## _type: \ - _t = _t > 0 ? _t + 0.5 : 0; \ - _t = _t > type_max ? type_max : t; \ - _t = _t < type_min ? type_min : t; \ - *(_type*)_po = (_type)_t; \ - break; - -#define CASE_INTERP_OUT_INT(_po, _t, _type, type_min, type_max) \ -case t ## _type: \ - _t = _t > 0 ? _t + 0.5 : _t - 0.5; \ - _t = _t > type_max ? type_max : t; \ - _t = _t < type_min ? type_min : t; \ - *(_type*)_po = (_type)_t; \ - break; - -int -NI_GeometricTransform(PyArrayObject *input, int (*map)(maybelong*, double*, - int, int, void*), void* map_data, PyArrayObject* matrix_ar, - PyArrayObject* shift_ar, PyArrayObject *coordinates, - PyArrayObject *output, int order, int mode, double cval) -{ - char *po, *pi, *pc = NULL; - maybelong **edge_offsets = NULL, **data_offsets = NULL, filter_size; - maybelong ftmp[MAXDIM], *fcoordinates = NULL, *foffsets = NULL; - maybelong cstride = 0, kk, hh, ll, jj, *idxs = NULL; - maybelong size; - double **splvals = NULL, icoor[MAXDIM]; - double idimensions[MAXDIM], istrides[MAXDIM]; - NI_Iterator io, ic; - Float64 *matrix = matrix_ar ? (Float64*)PyArray_DATA(matrix_ar) : NULL; - Float64 *shift = shift_ar ? (Float64*)PyArray_DATA(shift_ar) : NULL; - int irank = 0, orank, qq; - - for(kk = 0; kk < input->nd; kk++) { - idimensions[kk] = input->dimensions[kk]; - istrides[kk] = input->strides[kk]; - } - irank = input->nd; - orank = output->nd; - - /* if the mapping is from array coordinates: */ - if (coordinates) { - /* initialze a line iterator along the first axis: */ - if (!NI_InitPointIterator(coordinates, &ic)) - goto exit; - cstride = ic.strides[0]; - if (!NI_LineIterator(&ic, 0)) - goto exit; - pc = (void *)(PyArray_DATA(coordinates)); - } - - /* offsets used at the borders: */ - edge_offsets = (maybelong**)malloc(irank * sizeof(maybelong*)); - data_offsets = (maybelong**)malloc(irank * sizeof(maybelong*)); - if (!edge_offsets || !data_offsets) { - PyErr_NoMemory(); - goto exit; - } - for(jj = 0; jj < irank; jj++) - data_offsets[jj] = NULL; - for(jj = 0; jj < irank; jj++) { - data_offsets[jj] = (maybelong*)malloc((order + 1) * sizeof(maybelong)); - if (!data_offsets[jj]) { - PyErr_NoMemory(); - goto exit; - } - } - /* will hold the spline coefficients: */ - splvals = (double**)malloc(irank * sizeof(double*)); - if (!splvals) { - PyErr_NoMemory(); - goto exit; - } - for(jj = 0; jj < irank; jj++) - splvals[jj] = NULL; - for(jj = 0; jj < irank; jj++) { - splvals[jj] = (double*)malloc((order + 1) * sizeof(double)); - if (!splvals[jj]) { - PyErr_NoMemory(); - goto exit; - } - } - - filter_size = 1; - for(jj = 0; jj < irank; jj++) - filter_size *= order + 1; - idxs = (maybelong*)malloc(filter_size * sizeof(idxs)); - if (!idxs) { - PyErr_NoMemory(); - goto exit; - } - - /* initialize output iterator: */ - if (!NI_InitPointIterator(output, &io)) - goto exit; - - /* get data pointers: */ - pi = (void *)PyArray_DATA(input); - po = (void *)PyArray_DATA(output); - - /* make a table of all possible coordinates within the spline filter: */ - fcoordinates = (maybelong*)malloc(irank * filter_size * sizeof(maybelong)); - /* make a table of all offsets within the spline filter: */ - foffsets = (maybelong*)malloc(filter_size * sizeof(maybelong)); - if (!fcoordinates || !foffsets) { - PyErr_NoMemory(); - goto exit; - } - for(jj = 0; jj < irank; jj++) - ftmp[jj] = 0; - kk = 0; - for(hh = 0; hh < filter_size; hh++) { - for(jj = 0; jj < irank; jj++) - fcoordinates[jj + hh * irank] = ftmp[jj]; - foffsets[hh] = kk; - for(jj = irank - 1; jj >= 0; jj--) { - if (ftmp[jj] < order) { - ftmp[jj]++; - kk += istrides[jj]; - break; - } else { - ftmp[jj] = 0; - kk -= istrides[jj] * order; - } - } - } - - size = 1; - for(qq = 0; qq < output->nd; qq++) - size *= output->dimensions[qq]; - for(kk = 0; kk < size; kk++) { - double t = 0.0; - int constant = 0, edge = 0, offset = 0; - if (map) { - /* call mappint functions: */ - if (!map(io.coordinates, icoor, orank, irank, map_data)) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_RuntimeError, - "unknown error in mapping function"); - goto exit; - } - } else if (matrix) { - /* do an affine transformation: */ - Float64 *p = matrix; - for(hh = 0; hh < irank; hh++) { - icoor[hh] = 0.0; - for(ll = 0; ll < orank; ll++) - icoor[hh] += io.coordinates[ll] * *p++; - icoor[hh] += shift[hh]; - } - } else if (coordinates) { - /* mapping is from an coordinates array: */ - char *p = pc; - switch(coordinates->descr->type_num) { - CASE_MAP_COORDINATES(p, icoor, irank, cstride, Bool); - CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt8); - CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt16); - CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt32); -#if HAS_UINT64 - CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt64); -#endif - CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int8); - CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int16); - CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int32); - CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int64); - CASE_MAP_COORDINATES(p, icoor, irank, cstride, Float32); - CASE_MAP_COORDINATES(p, icoor, irank, cstride, Float64); - default: - PyErr_SetString(PyExc_RuntimeError, - "coordinate array data type not supported"); - goto exit; - } - } - /* iterate over axes: */ - for(hh = 0; hh < irank; hh++) { - /* if the input coordinate is outside the borders, map it: */ - double cc = map_coordinate(icoor[hh], idimensions[hh], mode); - if (cc > -1.0) { - /* find the filter location along this axis: */ - int start; - if (order & 1) { - start = (int)floor(cc) - order / 2; - } else { - start = (int)floor(cc + 0.5) - order / 2; - } - /* get the offset to the start of the filter: */ - offset += istrides[hh] * start; - if (start < 0 || start + order >= idimensions[hh]) { - /* implement border mapping, if outside border: */ - edge = 1; - edge_offsets[hh] = data_offsets[hh]; - for(ll = 0; ll <= order; ll++) { - int idx = start + ll; - int len = idimensions[hh]; - if (len <= 1) { - idx = 0; - } else { - int s2 = 2 * len - 2; - if (idx < 0) { - idx = s2 * (int)(-idx / s2) + idx; - idx = idx <= 1 - len ? idx + s2 : -idx; - } else if (idx >= len) { - idx -= s2 * (int)(idx / s2); - if (idx >= len) - idx = s2 - idx; - } - } - /* calculate and store the offests at this edge: */ - edge_offsets[hh][ll] = istrides[hh] * (idx - start); - } - } else { - /* we are not at the border, use precalculated offsets: */ - edge_offsets[hh] = NULL; - } - spline_coefficients(cc, order, splvals[hh]); - } else { - /* we use the constant border condition: */ - constant = 1; - break; - } - } - - if (!constant) { - maybelong *ff = fcoordinates; - for(hh = 0; hh < filter_size; hh++) { - int idx = 0; - if (edge) { - for(ll = 0; ll < irank; ll++) { - if (edge_offsets[ll]) - idx += edge_offsets[ll][ff[ll]]; - else - idx += ff[ll] * istrides[ll]; - } - } else { - idx = foffsets[hh]; - } - idx += offset; - idxs[hh] = idx; - ff += irank; - } - } - if (!constant) { - maybelong *ff = fcoordinates; - t = 0.0; - for(hh = 0; hh < filter_size; hh++) { - double coeff = 0.0; - switch(input->descr->type_num) { - CASE_INTERP_COEFF(coeff, pi, idxs[hh], Bool); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt8); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt16); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt32); -#if HAS_UINT64 - CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt64); -#endif - CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int8); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int16); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int32); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int64); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float32); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float64); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - /* calculate the interpolated value: */ - for(ll = 0; ll < irank; ll++) - if (order > 0) - coeff *= splvals[ll][ff[ll]]; - t += coeff; - ff += irank; - } - } else { - t = cval; - } - /* store output value: */ - switch (output->descr->type_num) { - CASE_INTERP_OUT(po, t, Bool); - CASE_INTERP_OUT_UINT(po, t, UInt8, 0, MAX_UINT8); - CASE_INTERP_OUT_UINT(po, t, UInt16, 0, MAX_UINT16); - CASE_INTERP_OUT_UINT(po, t, UInt32, 0, MAX_UINT32); -#if HAS_UINT64 - /* FIXME */ - CASE_INTERP_OUT_UINT(po, t, UInt64, 0, MAX_UINT32); -#endif - CASE_INTERP_OUT_INT(po, t, Int8, MIN_INT8, MAX_INT8); - CASE_INTERP_OUT_INT(po, t, Int16, MIN_INT16, MAX_INT16); - CASE_INTERP_OUT_INT(po, t, Int32, MIN_INT32, MAX_INT32); - CASE_INTERP_OUT_INT(po, t, Int64, MIN_INT64, MAX_INT64); - CASE_INTERP_OUT(po, t, Float32); - CASE_INTERP_OUT(po, t, Float64); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - if (coordinates) { - NI_ITERATOR_NEXT2(io, ic, po, pc); - } else { - NI_ITERATOR_NEXT(io, po); - } - } - - exit: - if (edge_offsets) - free(edge_offsets); - if (data_offsets) { - for(jj = 0; jj < irank; jj++) - free(data_offsets[jj]); - free(data_offsets); - } - if (splvals) { - for(jj = 0; jj < irank; jj++) - free(splvals[jj]); - free(splvals); - } - if (foffsets) - free(foffsets); - if (fcoordinates) - free(fcoordinates); - if (idxs) - free(idxs); - return PyErr_Occurred() ? 0 : 1; -} - -int NI_ZoomShift(PyArrayObject *input, PyArrayObject* zoom_ar, - PyArrayObject* shift_ar, PyArrayObject *output, - int order, int mode, double cval) -{ - char *po, *pi; - maybelong **zeros = NULL, **offsets = NULL, ***edge_offsets = NULL; - maybelong ftmp[MAXDIM], *fcoordinates = NULL, *foffsets = NULL; - maybelong jj, hh, kk, filter_size, odimensions[MAXDIM]; - maybelong idimensions[MAXDIM], istrides[MAXDIM], *idxs = NULL; - maybelong size; - double ***splvals = NULL; - NI_Iterator io; - Float64 *zooms = zoom_ar ? (Float64*)PyArray_DATA(zoom_ar) : NULL; - Float64 *shifts = shift_ar ? (Float64*)PyArray_DATA(shift_ar) : NULL; - int rank = 0, qq; - - for(kk = 0; kk < input->nd; kk++) { - idimensions[kk] = input->dimensions[kk]; - istrides[kk] = input->strides[kk]; - odimensions[kk] = output->dimensions[kk]; - } - rank = input->nd; - - /* if the mode is 'constant' we need some temps later: */ - if (mode == NI_EXTEND_CONSTANT) { - zeros = (maybelong**)malloc(rank * sizeof(maybelong*)); - if (!zeros) { - PyErr_NoMemory(); - goto exit; - } - for(jj = 0; jj < rank; jj++) - zeros[jj] = NULL; - for(jj = 0; jj < rank; jj++) { - zeros[jj] = (maybelong*)malloc(odimensions[jj] * sizeof(maybelong)); - if(!zeros[jj]) { - PyErr_NoMemory(); - goto exit; - } - } - } - - /* store offsets, along each axis: */ - offsets = (maybelong**)malloc(rank * sizeof(maybelong*)); - /* store spline coefficients, along each axis: */ - splvals = (double***)malloc(rank * sizeof(double**)); - /* store offsets at all edges: */ - edge_offsets = (maybelong***)malloc(rank * sizeof(maybelong**)); - if (!offsets || !splvals || !edge_offsets) { - PyErr_NoMemory(); - goto exit; - } - for(jj = 0; jj < rank; jj++) { - offsets[jj] = NULL; - splvals[jj] = NULL; - edge_offsets[jj] = NULL; - } - for(jj = 0; jj < rank; jj++) { - offsets[jj] = (maybelong*)malloc(odimensions[jj] * sizeof(maybelong)); - splvals[jj] = (double**)malloc(odimensions[jj] * sizeof(double*)); - edge_offsets[jj] = (maybelong**)malloc(odimensions[jj] * sizeof(maybelong*)); - if (!offsets[jj] || !splvals[jj] || !edge_offsets[jj]) { - PyErr_NoMemory(); - goto exit; - } - for(hh = 0; hh < odimensions[jj]; hh++) { - splvals[jj][hh] = NULL; - edge_offsets[jj][hh] = NULL; - } - } - - /* precalculate offsets, and offsets at the edge: */ - for(jj = 0; jj < rank; jj++) { - double shift = 0.0, zoom = 0.0; - if (shifts) - shift = shifts[jj]; - if (zooms) - zoom = zooms[jj]; - for(kk = 0; kk < odimensions[jj]; kk++) { - double cc = (double)kk; - if (shifts) - cc += shift; - if (zooms) - cc *= zoom; - cc = map_coordinate(cc, idimensions[jj], mode); - if (cc > -1.0) { - int start; - if (zeros && zeros[jj]) - zeros[jj][kk] = 0; - if (order & 1) { - start = (int)floor(cc) - order / 2; - } else { - start = (int)floor(cc + 0.5) - order / 2; - } - offsets[jj][kk] = istrides[jj] * start; - if (start < 0 || start + order >= idimensions[jj]) { - edge_offsets[jj][kk] = (maybelong*)malloc((order + 1) * sizeof(maybelong)); - if (!edge_offsets[jj][kk]) { - PyErr_NoMemory(); - goto exit; - } - for(hh = 0; hh <= order; hh++) { - int idx = start + hh; - int len = idimensions[jj]; - if (len <= 1) { - idx = 0; - } else { - int s2 = 2 * len - 2; - if (idx < 0) { - idx = s2 * (int)(-idx / s2) + idx; - idx = idx <= 1 - len ? idx + s2 : -idx; - } else if (idx >= len) { - idx -= s2 * (int)(idx / s2); - if (idx >= len) - idx = s2 - idx; - } - } - edge_offsets[jj][kk][hh] = istrides[jj] * (idx - start); - } - } - if (order > 0) { - splvals[jj][kk] = (double*)malloc((order + 1) * sizeof(double)); - if (!splvals[jj][kk]) { - PyErr_NoMemory(); - goto exit; - } - spline_coefficients(cc, order, splvals[jj][kk]); - } - } else { - zeros[jj][kk] = 1; - } - } - } - - filter_size = 1; - for(jj = 0; jj < rank; jj++) - filter_size *= order + 1; - idxs = (maybelong*)malloc(filter_size * sizeof(idxs)); - if (!idxs) { - PyErr_NoMemory(); - goto exit; - } - - if (!NI_InitPointIterator(output, &io)) - goto exit; - - pi = (void *)PyArray_DATA(input); - po = (void *)PyArray_DATA(output); - - /* store all coordinates and offsets with filter: */ - fcoordinates = (maybelong*)malloc(rank * filter_size * sizeof(maybelong)); - foffsets = (maybelong*)malloc(filter_size * sizeof(maybelong)); - if (!fcoordinates || !foffsets) { - PyErr_NoMemory(); - goto exit; - } - - for(jj = 0; jj < rank; jj++) - ftmp[jj] = 0; - kk = 0; - for(hh = 0; hh < filter_size; hh++) { - for(jj = 0; jj < rank; jj++) - fcoordinates[jj + hh * rank] = ftmp[jj]; - foffsets[hh] = kk; - for(jj = rank - 1; jj >= 0; jj--) { - if (ftmp[jj] < order) { - ftmp[jj]++; - kk += istrides[jj]; - break; - } else { - ftmp[jj] = 0; - kk -= istrides[jj] * order; - } - } - } - size = 1; - for(qq = 0; qq < output->nd; qq++) - size *= output->dimensions[qq]; - for(kk = 0; kk < size; kk++) { - double t = 0.0; - int edge = 0, oo = 0, zero = 0; - - for(hh = 0; hh < rank; hh++) { - if (zeros && zeros[hh][io.coordinates[hh]]) { - /* we use constant border condition */ - zero = 1; - break; - } - oo += offsets[hh][io.coordinates[hh]]; - if (edge_offsets[hh][io.coordinates[hh]]) - edge = 1; - } - - if (!zero) { - maybelong *ff = fcoordinates; - for(hh = 0; hh < filter_size; hh++) { - int idx = 0; - if (edge) { - /* use precalculated edge offsets: */ - for(jj = 0; jj < rank; jj++) { - if (edge_offsets[jj][io.coordinates[jj]]) - idx += edge_offsets[jj][io.coordinates[jj]][ff[jj]]; - else - idx += ff[jj] * istrides[jj]; - } - idx += oo; - } else { - /* use normal offsets: */ - idx += oo + foffsets[hh]; - } - idxs[hh] = idx; - ff += rank; - } - } - if (!zero) { - maybelong *ff = fcoordinates; - t = 0.0; - for(hh = 0; hh < filter_size; hh++) { - double coeff = 0.0; - switch(input->descr->type_num) { - CASE_INTERP_COEFF(coeff, pi, idxs[hh], Bool); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt8); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt16); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt32); -#if HAS_UINT64 - CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt64); -#endif - CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int8); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int16); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int32); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int64); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float32); - CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float64); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - /* calculate interpolated value: */ - for(jj = 0; jj < rank; jj++) - if (order > 0) - coeff *= splvals[jj][io.coordinates[jj]][ff[jj]]; - t += coeff; - ff += rank; - } - } else { - t = cval; - } - /* store output: */ - switch (output->descr->type_num) { - CASE_INTERP_OUT(po, t, Bool); - CASE_INTERP_OUT_UINT(po, t, UInt8, 0, MAX_UINT8); - CASE_INTERP_OUT_UINT(po, t, UInt16, 0, MAX_UINT16); - CASE_INTERP_OUT_UINT(po, t, UInt32, 0, MAX_UINT32); -#if HAS_UINT64 - /* FIXME */ - CASE_INTERP_OUT_UINT(po, t, UInt64, 0, MAX_UINT32); -#endif - CASE_INTERP_OUT_INT(po, t, Int8, MIN_INT8, MAX_INT8); - CASE_INTERP_OUT_INT(po, t, Int16, MIN_INT16, MAX_INT16); - CASE_INTERP_OUT_INT(po, t, Int32, MIN_INT32, MAX_INT32); - CASE_INTERP_OUT_INT(po, t, Int64, MIN_INT64, MAX_INT64); - CASE_INTERP_OUT(po, t, Float32); - CASE_INTERP_OUT(po, t, Float64); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - NI_ITERATOR_NEXT(io, po); - } - - exit: - if (zeros) { - for(jj = 0; jj < rank; jj++) - if (zeros[jj]) - free(zeros[jj]); - free(zeros); - } - if (offsets) { - for(jj = 0; jj < rank; jj++) - if (offsets[jj]) - free(offsets[jj]); - free(offsets); - } - if (splvals) { - for(jj = 0; jj < rank; jj++) { - if (splvals[jj]) { - for(hh = 0; hh < odimensions[jj]; hh++) - if (splvals[jj][hh]) - free(splvals[jj][hh]); - free(splvals[jj]); - } - } - free(splvals); - } - if (edge_offsets) { - for(jj = 0; jj < rank; jj++) { - if (edge_offsets[jj]) { - for(hh = 0; hh < odimensions[jj]; hh++) - if (edge_offsets[jj][hh]) - free(edge_offsets[jj][hh]); - free(edge_offsets[jj]); - } - } - free(edge_offsets); - } - if (foffsets) - free(foffsets); - if (fcoordinates) - free(fcoordinates); - if (idxs) - free(idxs); - return PyErr_Occurred() ? 0 : 1; -} +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ni_support.h" +#include "ni_interpolation.h" +#include +#include + +/* calculate the B-spline interpolation coefficients for given x: */ +static void +spline_coefficients(double x, int order, double *result) +{ + int hh; + double y, start; + + if (order & 1) { + start = (int)floor(x) - order / 2; + } else { + start = (int)floor(x + 0.5) - order / 2; + } + + for(hh = 0; hh <= order; hh++) { + y = fabs(start - x + hh); + + switch(order) { + case 1: + result[hh] = y > 1.0 ? 0.0 : 1.0 - y; + break; + case 2: + if (y < 0.5) { + result[hh] = 0.75 - y * y; + } else if (y < 1.5) { + y = 1.5 - y; + result[hh] = 0.5 * y * y; + } else { + result[hh] = 0.0; + } + break; + case 3: + if (y < 1.0) { + result[hh] = + (y * y * (y - 2.0) * 3.0 + 4.0) / 6.0; + } else if (y < 2.0) { + y = 2.0 - y; + result[hh] = y * y * y / 6.0; + } else { + result[hh] = 0.0; + } + break; + case 4: + if (y < 0.5) { + y *= y; + result[hh] = y * (y * 0.25 - 0.625) + 115.0 / 192.0; + } else if (y < 1.5) { + result[hh] = y * (y * (y * (5.0 / 6.0 - y / 6.0) - 1.25) + + 5.0 / 24.0) + 55.0 / 96.0; + } else if (y < 2.5) { + y -= 2.5; + y *= y; + result[hh] = y * y / 24.0; + } else { + result[hh] = 0.0; + } + break; + case 5: + if (y < 1.0) { + double f = y * y; + result[hh] = + f * (f * (0.25 - y / 12.0) - 0.5) + 0.55; + } else if (y < 2.0) { + result[hh] = y * (y * (y * (y * (y / 24.0 - 0.375) + + 1.25) - 1.75) + 0.625) + 0.425; + } else if (y < 3.0) { + double f = 3.0 - y; + y = f * f; + result[hh] = f * y * y / 120.0; + } else { + result[hh] = 0.0; + } + break; + } + } +} + +/* map a coordinate outside the borders, according to the requested + boundary condition: */ +static double +map_coordinate(double in, maybelong len, int mode) +{ + if (in < 0) { + switch (mode) { + case NI_EXTEND_MIRROR: + if (len <= 1) { + in = 0; + } else { + maybelong sz2 = 2 * len - 2; + in = sz2 * (maybelong)(-in / sz2) + in; + in = in <= 1 - len ? in + sz2 : -in; + } + break; + case NI_EXTEND_REFLECT: + if (len <= 1) { + in = 0; + } else { + maybelong sz2 = 2 * len; + if (in < -sz2) + in = sz2 * (maybelong)(-in / sz2) + in; + in = in < -len ? in + sz2 : -in - 1; + } + break; + case NI_EXTEND_WRAP: + if (len <= 1) { + in = 0; + } else { + maybelong sz = len - 1; + // Integer division of -in/sz gives (-in mod sz) + // Note that 'in' is negative + in += sz * ((maybelong)(-in / sz) + 1); + } + break; + case NI_EXTEND_NEAREST: + in = 0; + break; + case NI_EXTEND_CONSTANT: + in = -1; + break; + } + } else if (in > len-1) { + switch (mode) { + case NI_EXTEND_MIRROR: + if (len <= 1) { + in = 0; + } else { + maybelong sz2 = 2 * len - 2; + in -= sz2 * (maybelong)(in / sz2); + if (in >= len) + in = sz2 - in; + } + break; + case NI_EXTEND_REFLECT: + if (len <= 1) { + in = 0; + } else { + maybelong sz2 = 2 * len; + in -= sz2 * (maybelong)(in / sz2); + if (in >= len) + in = sz2 - in - 1; + } + break; + case NI_EXTEND_WRAP: + if (len <= 1) { + in = 0; + } else { + maybelong sz = len - 1; + in -= sz * (maybelong)(in / sz); + } + break; + case NI_EXTEND_NEAREST: + in = len - 1; + break; + case NI_EXTEND_CONSTANT: + in = -1; + break; + } + } + + return in; +} + +#define BUFFER_SIZE 256000 +#define TOLERANCE 1e-15 + +/* one-dimensional spline filter: */ +int NI_SplineFilter1D(PyArrayObject *input, int order, int axis, + PyArrayObject *output) +{ + int hh, npoles = 0, more; + maybelong kk, ll, lines, len; + double *buffer = NULL, weight, pole[2]; + NI_LineBuffer iline_buffer, oline_buffer; + + len = input->nd > 0 ? input->dimensions[axis] : 1; + if (len < 1) + goto exit; + + /* these are used in the spline filter calculation below: */ + switch (order) { + case 2: + npoles = 1; + pole[0] = sqrt(8.0) - 3.0; + break; + case 3: + npoles = 1; + pole[0] = sqrt(3.0) - 2.0; + break; + case 4: + npoles = 2; + pole[0] = sqrt(664.0 - sqrt(438976.0)) + sqrt(304.0) - 19.0; + pole[1] = sqrt(664.0 + sqrt(438976.0)) - sqrt(304.0) - 19.0; + break; + case 5: + npoles = 2; + pole[0] = sqrt(67.5 - sqrt(4436.25)) + sqrt(26.25) - 6.5; + pole[1] = sqrt(67.5 + sqrt(4436.25)) - sqrt(26.25) - 6.5; + break; + default: + break; + } + + weight = 1.0; + for(hh = 0; hh < npoles; hh++) + weight *= (1.0 - pole[hh]) * (1.0 - 1.0 / pole[hh]); + + /* allocate an initialize the line buffer, only a single one is used, + because the calculation is in-place: */ + lines = -1; + if (!NI_AllocateLineBuffer(input, axis, 0, 0, &lines, BUFFER_SIZE, + &buffer)) + goto exit; + if (!NI_InitLineBuffer(input, axis, 0, 0, lines, buffer, + NI_EXTEND_DEFAULT, 0.0, &iline_buffer)) + goto exit; + if (!NI_InitLineBuffer(output, axis, 0, 0, lines, buffer, + NI_EXTEND_DEFAULT, 0.0, &oline_buffer)) + goto exit; + + /* iterate over all the array lines: */ + do { + /* copy lines from array to buffer: */ + if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) + goto exit; + /* iterate over the lines in the buffer: */ + for(kk = 0; kk < lines; kk++) { + /* get line: */ + double *ln = NI_GET_LINE(iline_buffer, kk); + /* spline filter: */ + if (len > 1) { + for(ll = 0; ll < len; ll++) + ln[ll] *= weight; + for(hh = 0; hh < npoles; hh++) { + double p = pole[hh]; + int max = (int)ceil(log(TOLERANCE) / log(fabs(p))); + if (max < len) { + double zn = p; + double sum = ln[0]; + for(ll = 1; ll < max; ll++) { + sum += zn * ln[ll]; + zn *= p; + } + ln[0] = sum; + } else { + double zn = p; + double iz = 1.0 / p; + double z2n = pow(p, (double)(len - 1)); + double sum = ln[0] + z2n * ln[len - 1]; + z2n *= z2n * iz; + for(ll = 1; ll <= len - 2; ll++) { + sum += (zn + z2n) * ln[ll]; + zn *= p; + z2n *= iz; + } + ln[0] = sum / (1.0 - zn * zn); + } + for(ll = 1; ll < len; ll++) + ln[ll] += p * ln[ll - 1]; + ln[len-1] = (p / (p * p - 1.0)) * (ln[len-1] + p * ln[len-2]); + for(ll = len - 2; ll >= 0; ll--) + ln[ll] = p * (ln[ll + 1] - ln[ll]); + } + } + } + /* copy lines from buffer to array: */ + if (!NI_LineBufferToArray(&oline_buffer)) + goto exit; + } while(more); + + exit: + if (buffer) free(buffer); + return PyErr_Occurred() ? 0 : 1; +} + +#define CASE_MAP_COORDINATES(_p, _coor, _rank, _stride, _type) \ +case t ## _type: \ +{ \ + int _hh; \ + for(_hh = 0; _hh < _rank; _hh++) { \ + _coor[_hh] = *(_type*)_p; \ + _p += _stride; \ + } \ +} \ +break; + +#define CASE_INTERP_COEFF(_coeff, _pi, _idx, _type) \ +case t ## _type: \ + _coeff = *(_type*)(_pi + _idx); \ + break; + +#define CASE_INTERP_OUT(_po, _t, _type) \ +case t ## _type: \ + *(_type*)_po = (_type)_t; \ + break; + +#define CASE_INTERP_OUT_UINT(_po, _t, _type, type_min, type_max) \ +case t ## _type: \ + _t = _t > 0 ? _t + 0.5 : 0; \ + _t = _t > type_max ? type_max : t; \ + _t = _t < type_min ? type_min : t; \ + *(_type*)_po = (_type)_t; \ + break; + +#define CASE_INTERP_OUT_INT(_po, _t, _type, type_min, type_max) \ +case t ## _type: \ + _t = _t > 0 ? _t + 0.5 : _t - 0.5; \ + _t = _t > type_max ? type_max : t; \ + _t = _t < type_min ? type_min : t; \ + *(_type*)_po = (_type)_t; \ + break; + +int +NI_GeometricTransform(PyArrayObject *input, int (*map)(maybelong*, double*, + int, int, void*), void* map_data, PyArrayObject* matrix_ar, + PyArrayObject* shift_ar, PyArrayObject *coordinates, + PyArrayObject *output, int order, int mode, double cval) +{ + char *po, *pi, *pc = NULL; + maybelong **edge_offsets = NULL, **data_offsets = NULL, filter_size; + maybelong ftmp[MAXDIM], *fcoordinates = NULL, *foffsets = NULL; + maybelong cstride = 0, kk, hh, ll, jj, *idxs = NULL; + maybelong size; + double **splvals = NULL, icoor[MAXDIM]; + double idimensions[MAXDIM], istrides[MAXDIM]; + NI_Iterator io, ic; + Float64 *matrix = matrix_ar ? (Float64*)PyArray_DATA(matrix_ar) : NULL; + Float64 *shift = shift_ar ? (Float64*)PyArray_DATA(shift_ar) : NULL; + int irank = 0, orank, qq; + + for(kk = 0; kk < input->nd; kk++) { + idimensions[kk] = input->dimensions[kk]; + istrides[kk] = input->strides[kk]; + } + irank = input->nd; + orank = output->nd; + + /* if the mapping is from array coordinates: */ + if (coordinates) { + /* initialze a line iterator along the first axis: */ + if (!NI_InitPointIterator(coordinates, &ic)) + goto exit; + cstride = ic.strides[0]; + if (!NI_LineIterator(&ic, 0)) + goto exit; + pc = (void *)(PyArray_DATA(coordinates)); + } + + /* offsets used at the borders: */ + edge_offsets = (maybelong**)malloc(irank * sizeof(maybelong*)); + data_offsets = (maybelong**)malloc(irank * sizeof(maybelong*)); + if (!edge_offsets || !data_offsets) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < irank; jj++) + data_offsets[jj] = NULL; + for(jj = 0; jj < irank; jj++) { + data_offsets[jj] = (maybelong*)malloc((order + 1) * sizeof(maybelong)); + if (!data_offsets[jj]) { + PyErr_NoMemory(); + goto exit; + } + } + /* will hold the spline coefficients: */ + splvals = (double**)malloc(irank * sizeof(double*)); + if (!splvals) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < irank; jj++) + splvals[jj] = NULL; + for(jj = 0; jj < irank; jj++) { + splvals[jj] = (double*)malloc((order + 1) * sizeof(double)); + if (!splvals[jj]) { + PyErr_NoMemory(); + goto exit; + } + } + + filter_size = 1; + for(jj = 0; jj < irank; jj++) + filter_size *= order + 1; + idxs = (maybelong*)malloc(filter_size * sizeof(idxs)); + if (!idxs) { + PyErr_NoMemory(); + goto exit; + } + + /* initialize output iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + + /* get data pointers: */ + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + + /* make a table of all possible coordinates within the spline filter: */ + fcoordinates = (maybelong*)malloc(irank * filter_size * sizeof(maybelong)); + /* make a table of all offsets within the spline filter: */ + foffsets = (maybelong*)malloc(filter_size * sizeof(maybelong)); + if (!fcoordinates || !foffsets) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < irank; jj++) + ftmp[jj] = 0; + kk = 0; + for(hh = 0; hh < filter_size; hh++) { + for(jj = 0; jj < irank; jj++) + fcoordinates[jj + hh * irank] = ftmp[jj]; + foffsets[hh] = kk; + for(jj = irank - 1; jj >= 0; jj--) { + if (ftmp[jj] < order) { + ftmp[jj]++; + kk += istrides[jj]; + break; + } else { + ftmp[jj] = 0; + kk -= istrides[jj] * order; + } + } + } + + size = 1; + for(qq = 0; qq < output->nd; qq++) + size *= output->dimensions[qq]; + for(kk = 0; kk < size; kk++) { + double t = 0.0; + int constant = 0, edge = 0, offset = 0; + if (map) { + /* call mappint functions: */ + if (!map(io.coordinates, icoor, orank, irank, map_data)) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, + "unknown error in mapping function"); + goto exit; + } + } else if (matrix) { + /* do an affine transformation: */ + Float64 *p = matrix; + for(hh = 0; hh < irank; hh++) { + icoor[hh] = 0.0; + for(ll = 0; ll < orank; ll++) + icoor[hh] += io.coordinates[ll] * *p++; + icoor[hh] += shift[hh]; + } + } else if (coordinates) { + /* mapping is from an coordinates array: */ + char *p = pc; + switch(coordinates->descr->type_num) { + CASE_MAP_COORDINATES(p, icoor, irank, cstride, Bool); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt8); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt16); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt32); +#if HAS_UINT64 + CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt64); +#endif + CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int8); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int16); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int32); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int64); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, Float32); + CASE_MAP_COORDINATES(p, icoor, irank, cstride, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, + "coordinate array data type not supported"); + goto exit; + } + } + /* iterate over axes: */ + for(hh = 0; hh < irank; hh++) { + /* if the input coordinate is outside the borders, map it: */ + double cc = map_coordinate(icoor[hh], idimensions[hh], mode); + if (cc > -1.0) { + /* find the filter location along this axis: */ + int start; + if (order & 1) { + start = (int)floor(cc) - order / 2; + } else { + start = (int)floor(cc + 0.5) - order / 2; + } + /* get the offset to the start of the filter: */ + offset += istrides[hh] * start; + if (start < 0 || start + order >= idimensions[hh]) { + /* implement border mapping, if outside border: */ + edge = 1; + edge_offsets[hh] = data_offsets[hh]; + for(ll = 0; ll <= order; ll++) { + int idx = start + ll; + int len = idimensions[hh]; + if (len <= 1) { + idx = 0; + } else { + int s2 = 2 * len - 2; + if (idx < 0) { + idx = s2 * (int)(-idx / s2) + idx; + idx = idx <= 1 - len ? idx + s2 : -idx; + } else if (idx >= len) { + idx -= s2 * (int)(idx / s2); + if (idx >= len) + idx = s2 - idx; + } + } + /* calculate and store the offests at this edge: */ + edge_offsets[hh][ll] = istrides[hh] * (idx - start); + } + } else { + /* we are not at the border, use precalculated offsets: */ + edge_offsets[hh] = NULL; + } + spline_coefficients(cc, order, splvals[hh]); + } else { + /* we use the constant border condition: */ + constant = 1; + break; + } + } + + if (!constant) { + maybelong *ff = fcoordinates; + for(hh = 0; hh < filter_size; hh++) { + int idx = 0; + if (edge) { + for(ll = 0; ll < irank; ll++) { + if (edge_offsets[ll]) + idx += edge_offsets[ll][ff[ll]]; + else + idx += ff[ll] * istrides[ll]; + } + } else { + idx = foffsets[hh]; + } + idx += offset; + idxs[hh] = idx; + ff += irank; + } + } + if (!constant) { + maybelong *ff = fcoordinates; + t = 0.0; + for(hh = 0; hh < filter_size; hh++) { + double coeff = 0.0; + switch(input->descr->type_num) { + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Bool); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt8); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt16); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt32); +#if HAS_UINT64 + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt64); +#endif + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int8); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int16); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int32); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int64); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float32); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + /* calculate the interpolated value: */ + for(ll = 0; ll < irank; ll++) + if (order > 0) + coeff *= splvals[ll][ff[ll]]; + t += coeff; + ff += irank; + } + } else { + t = cval; + } + /* store output value: */ + switch (output->descr->type_num) { + CASE_INTERP_OUT(po, t, Bool); + CASE_INTERP_OUT_UINT(po, t, UInt8, 0, MAX_UINT8); + CASE_INTERP_OUT_UINT(po, t, UInt16, 0, MAX_UINT16); + CASE_INTERP_OUT_UINT(po, t, UInt32, 0, MAX_UINT32); +#if HAS_UINT64 + /* FIXME */ + CASE_INTERP_OUT_UINT(po, t, UInt64, 0, MAX_UINT32); +#endif + CASE_INTERP_OUT_INT(po, t, Int8, MIN_INT8, MAX_INT8); + CASE_INTERP_OUT_INT(po, t, Int16, MIN_INT16, MAX_INT16); + CASE_INTERP_OUT_INT(po, t, Int32, MIN_INT32, MAX_INT32); + CASE_INTERP_OUT_INT(po, t, Int64, MIN_INT64, MAX_INT64); + CASE_INTERP_OUT(po, t, Float32); + CASE_INTERP_OUT(po, t, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + if (coordinates) { + NI_ITERATOR_NEXT2(io, ic, po, pc); + } else { + NI_ITERATOR_NEXT(io, po); + } + } + + exit: + if (edge_offsets) + free(edge_offsets); + if (data_offsets) { + for(jj = 0; jj < irank; jj++) + free(data_offsets[jj]); + free(data_offsets); + } + if (splvals) { + for(jj = 0; jj < irank; jj++) + free(splvals[jj]); + free(splvals); + } + if (foffsets) + free(foffsets); + if (fcoordinates) + free(fcoordinates); + if (idxs) + free(idxs); + return PyErr_Occurred() ? 0 : 1; +} + +int NI_ZoomShift(PyArrayObject *input, PyArrayObject* zoom_ar, + PyArrayObject* shift_ar, PyArrayObject *output, + int order, int mode, double cval) +{ + char *po, *pi; + maybelong **zeros = NULL, **offsets = NULL, ***edge_offsets = NULL; + maybelong ftmp[MAXDIM], *fcoordinates = NULL, *foffsets = NULL; + maybelong jj, hh, kk, filter_size, odimensions[MAXDIM]; + maybelong idimensions[MAXDIM], istrides[MAXDIM], *idxs = NULL; + maybelong size; + double ***splvals = NULL; + NI_Iterator io; + Float64 *zooms = zoom_ar ? (Float64*)PyArray_DATA(zoom_ar) : NULL; + Float64 *shifts = shift_ar ? (Float64*)PyArray_DATA(shift_ar) : NULL; + int rank = 0, qq; + + for(kk = 0; kk < input->nd; kk++) { + idimensions[kk] = input->dimensions[kk]; + istrides[kk] = input->strides[kk]; + odimensions[kk] = output->dimensions[kk]; + } + rank = input->nd; + + /* if the mode is 'constant' we need some temps later: */ + if (mode == NI_EXTEND_CONSTANT) { + zeros = (maybelong**)malloc(rank * sizeof(maybelong*)); + if (!zeros) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < rank; jj++) + zeros[jj] = NULL; + for(jj = 0; jj < rank; jj++) { + zeros[jj] = (maybelong*)malloc(odimensions[jj] * sizeof(maybelong)); + if(!zeros[jj]) { + PyErr_NoMemory(); + goto exit; + } + } + } + + /* store offsets, along each axis: */ + offsets = (maybelong**)malloc(rank * sizeof(maybelong*)); + /* store spline coefficients, along each axis: */ + splvals = (double***)malloc(rank * sizeof(double**)); + /* store offsets at all edges: */ + edge_offsets = (maybelong***)malloc(rank * sizeof(maybelong**)); + if (!offsets || !splvals || !edge_offsets) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < rank; jj++) { + offsets[jj] = NULL; + splvals[jj] = NULL; + edge_offsets[jj] = NULL; + } + for(jj = 0; jj < rank; jj++) { + offsets[jj] = (maybelong*)malloc(odimensions[jj] * sizeof(maybelong)); + splvals[jj] = (double**)malloc(odimensions[jj] * sizeof(double*)); + edge_offsets[jj] = (maybelong**)malloc(odimensions[jj] * sizeof(maybelong*)); + if (!offsets[jj] || !splvals[jj] || !edge_offsets[jj]) { + PyErr_NoMemory(); + goto exit; + } + for(hh = 0; hh < odimensions[jj]; hh++) { + splvals[jj][hh] = NULL; + edge_offsets[jj][hh] = NULL; + } + } + + /* precalculate offsets, and offsets at the edge: */ + for(jj = 0; jj < rank; jj++) { + double shift = 0.0, zoom = 0.0; + if (shifts) + shift = shifts[jj]; + if (zooms) + zoom = zooms[jj]; + for(kk = 0; kk < odimensions[jj]; kk++) { + double cc = (double)kk; + if (shifts) + cc += shift; + if (zooms) + cc *= zoom; + cc = map_coordinate(cc, idimensions[jj], mode); + if (cc > -1.0) { + int start; + if (zeros && zeros[jj]) + zeros[jj][kk] = 0; + if (order & 1) { + start = (int)floor(cc) - order / 2; + } else { + start = (int)floor(cc + 0.5) - order / 2; + } + offsets[jj][kk] = istrides[jj] * start; + if (start < 0 || start + order >= idimensions[jj]) { + edge_offsets[jj][kk] = (maybelong*)malloc((order + 1) * sizeof(maybelong)); + if (!edge_offsets[jj][kk]) { + PyErr_NoMemory(); + goto exit; + } + for(hh = 0; hh <= order; hh++) { + int idx = start + hh; + int len = idimensions[jj]; + if (len <= 1) { + idx = 0; + } else { + int s2 = 2 * len - 2; + if (idx < 0) { + idx = s2 * (int)(-idx / s2) + idx; + idx = idx <= 1 - len ? idx + s2 : -idx; + } else if (idx >= len) { + idx -= s2 * (int)(idx / s2); + if (idx >= len) + idx = s2 - idx; + } + } + edge_offsets[jj][kk][hh] = istrides[jj] * (idx - start); + } + } + if (order > 0) { + splvals[jj][kk] = (double*)malloc((order + 1) * sizeof(double)); + if (!splvals[jj][kk]) { + PyErr_NoMemory(); + goto exit; + } + spline_coefficients(cc, order, splvals[jj][kk]); + } + } else { + zeros[jj][kk] = 1; + } + } + } + + filter_size = 1; + for(jj = 0; jj < rank; jj++) + filter_size *= order + 1; + idxs = (maybelong*)malloc(filter_size * sizeof(idxs)); + if (!idxs) { + PyErr_NoMemory(); + goto exit; + } + + if (!NI_InitPointIterator(output, &io)) + goto exit; + + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + + /* store all coordinates and offsets with filter: */ + fcoordinates = (maybelong*)malloc(rank * filter_size * sizeof(maybelong)); + foffsets = (maybelong*)malloc(filter_size * sizeof(maybelong)); + if (!fcoordinates || !foffsets) { + PyErr_NoMemory(); + goto exit; + } + + for(jj = 0; jj < rank; jj++) + ftmp[jj] = 0; + kk = 0; + for(hh = 0; hh < filter_size; hh++) { + for(jj = 0; jj < rank; jj++) + fcoordinates[jj + hh * rank] = ftmp[jj]; + foffsets[hh] = kk; + for(jj = rank - 1; jj >= 0; jj--) { + if (ftmp[jj] < order) { + ftmp[jj]++; + kk += istrides[jj]; + break; + } else { + ftmp[jj] = 0; + kk -= istrides[jj] * order; + } + } + } + size = 1; + for(qq = 0; qq < output->nd; qq++) + size *= output->dimensions[qq]; + for(kk = 0; kk < size; kk++) { + double t = 0.0; + int edge = 0, oo = 0, zero = 0; + + for(hh = 0; hh < rank; hh++) { + if (zeros && zeros[hh][io.coordinates[hh]]) { + /* we use constant border condition */ + zero = 1; + break; + } + oo += offsets[hh][io.coordinates[hh]]; + if (edge_offsets[hh][io.coordinates[hh]]) + edge = 1; + } + + if (!zero) { + maybelong *ff = fcoordinates; + for(hh = 0; hh < filter_size; hh++) { + int idx = 0; + if (edge) { + /* use precalculated edge offsets: */ + for(jj = 0; jj < rank; jj++) { + if (edge_offsets[jj][io.coordinates[jj]]) + idx += edge_offsets[jj][io.coordinates[jj]][ff[jj]]; + else + idx += ff[jj] * istrides[jj]; + } + idx += oo; + } else { + /* use normal offsets: */ + idx += oo + foffsets[hh]; + } + idxs[hh] = idx; + ff += rank; + } + } + if (!zero) { + maybelong *ff = fcoordinates; + t = 0.0; + for(hh = 0; hh < filter_size; hh++) { + double coeff = 0.0; + switch(input->descr->type_num) { + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Bool); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt8); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt16); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt32); +#if HAS_UINT64 + CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt64); +#endif + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int8); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int16); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int32); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int64); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float32); + CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + /* calculate interpolated value: */ + for(jj = 0; jj < rank; jj++) + if (order > 0) + coeff *= splvals[jj][io.coordinates[jj]][ff[jj]]; + t += coeff; + ff += rank; + } + } else { + t = cval; + } + /* store output: */ + switch (output->descr->type_num) { + CASE_INTERP_OUT(po, t, Bool); + CASE_INTERP_OUT_UINT(po, t, UInt8, 0, MAX_UINT8); + CASE_INTERP_OUT_UINT(po, t, UInt16, 0, MAX_UINT16); + CASE_INTERP_OUT_UINT(po, t, UInt32, 0, MAX_UINT32); +#if HAS_UINT64 + /* FIXME */ + CASE_INTERP_OUT_UINT(po, t, UInt64, 0, MAX_UINT32); +#endif + CASE_INTERP_OUT_INT(po, t, Int8, MIN_INT8, MAX_INT8); + CASE_INTERP_OUT_INT(po, t, Int16, MIN_INT16, MAX_INT16); + CASE_INTERP_OUT_INT(po, t, Int32, MIN_INT32, MAX_INT32); + CASE_INTERP_OUT_INT(po, t, Int64, MIN_INT64, MAX_INT64); + CASE_INTERP_OUT(po, t, Float32); + CASE_INTERP_OUT(po, t, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + NI_ITERATOR_NEXT(io, po); + } + + exit: + if (zeros) { + for(jj = 0; jj < rank; jj++) + if (zeros[jj]) + free(zeros[jj]); + free(zeros); + } + if (offsets) { + for(jj = 0; jj < rank; jj++) + if (offsets[jj]) + free(offsets[jj]); + free(offsets); + } + if (splvals) { + for(jj = 0; jj < rank; jj++) { + if (splvals[jj]) { + for(hh = 0; hh < odimensions[jj]; hh++) + if (splvals[jj][hh]) + free(splvals[jj][hh]); + free(splvals[jj]); + } + } + free(splvals); + } + if (edge_offsets) { + for(jj = 0; jj < rank; jj++) { + if (edge_offsets[jj]) { + for(hh = 0; hh < odimensions[jj]; hh++) + if (edge_offsets[jj][hh]) + free(edge_offsets[jj][hh]); + free(edge_offsets[jj]); + } + } + free(edge_offsets); + } + if (foffsets) + free(foffsets); + if (fcoordinates) + free(fcoordinates); + if (idxs) + free(idxs); + return PyErr_Occurred() ? 0 : 1; +} Modified: trunk/scipy/ndimage/src/ni_interpolation.h =================================================================== --- trunk/scipy/ndimage/src/ni_interpolation.h 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/ni_interpolation.h 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,43 +1,43 @@ -/* Copyright (C) 2003-2005 Peter J. Verveer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef NI_INTERPOLATION_H -#define NI_INTERPOLATION_H - -int NI_SplineFilter1D(PyArrayObject*, int, int, PyArrayObject*); -int NI_GeometricTransform(PyArrayObject*, int (*)(maybelong*, double*, int, int, - void*), void*, PyArrayObject*, PyArrayObject*, - PyArrayObject*, PyArrayObject*, int, int, - double); -int NI_ZoomShift(PyArrayObject*, PyArrayObject*, PyArrayObject*, - PyArrayObject*, int, int, double); - -#endif +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NI_INTERPOLATION_H +#define NI_INTERPOLATION_H + +int NI_SplineFilter1D(PyArrayObject*, int, int, PyArrayObject*); +int NI_GeometricTransform(PyArrayObject*, int (*)(maybelong*, double*, int, int, + void*), void*, PyArrayObject*, PyArrayObject*, + PyArrayObject*, PyArrayObject*, int, int, + double); +int NI_ZoomShift(PyArrayObject*, PyArrayObject*, PyArrayObject*, + PyArrayObject*, int, int, double); + +#endif Modified: trunk/scipy/ndimage/src/ni_measure.c =================================================================== --- trunk/scipy/ndimage/src/ni_measure.c 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/ni_measure.c 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,1197 +1,1197 @@ -/* Copyright (C) 2003-2005 Peter J. Verveer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ni_support.h" -#include "ni_measure.h" -#include -#include -#include -#include - -typedef struct { - Int32 index1, index2; - void* next; -} _index_pair; - -#define CASE_LABEL(_p, _pi, _type) \ -case t ## _type: \ - *_p = *(_type*)_pi ? -1 : 0; \ - break - -int NI_Label(PyArrayObject* input, PyArrayObject* strct, - maybelong *max_label, PyArrayObject* output) -{ - int kk; - maybelong jj, ll, ssize, size, filter_size, *offsets = NULL; - maybelong mask_value, *oo; - Bool *ps, *footprint = NULL; - char *pi, *po; - Int32 index = 0, *index_map = NULL; - NI_FilterIterator fi; - NI_Iterator ii, io; - _index_pair *pairs = NULL; - - /* structure size */ - ssize = 1; - for(kk = 0; kk < strct->nd; kk++) - ssize *= strct->dimensions[kk]; - /* we only use the first half of the structure data, so we make a - temporary structure for use with the filter functions: */ - footprint = (Bool*)malloc(ssize * sizeof(Bool)); - if (!footprint) { - PyErr_NoMemory(); - goto exit; - } - ps = (Bool*)PyArray_DATA(strct); - filter_size = 0; - for(jj = 0; jj < ssize / 2; jj++) { - footprint[jj] = ps[jj]; - if (ps[jj]) - ++filter_size; - } - for(jj = ssize / 2; jj < ssize; jj++) - footprint[jj] = 0; - /* get data and size */ - pi = (void *)PyArray_DATA(input); - po = (void *)PyArray_DATA(output); - size = 1; - for(kk = 0; kk < output->nd; kk++) - size *= output->dimensions[kk]; - if (!NI_InitPointIterator(input, &ii)) - goto exit; - if (!NI_InitPointIterator(output, &io)) - goto exit; - /* set all elements in the output corresponding to non-zero elements - in input to -1: */ - for(jj = 0; jj < size; jj++) { - Int32 *p = (Int32*)po; - switch (input->descr->type_num) { - CASE_LABEL(p, pi, Bool); - CASE_LABEL(p, pi, UInt8); - CASE_LABEL(p, pi, UInt16); - CASE_LABEL(p, pi, UInt32); -#if HAS_UINT64 - CASE_LABEL(p, pi, UInt64); -#endif - CASE_LABEL(p, pi, Int8); - CASE_LABEL(p, pi, Int16); - CASE_LABEL(p, pi, Int32); - CASE_LABEL(p, pi, Int64); - CASE_LABEL(p, pi, Float32); - CASE_LABEL(p, pi, Float64); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - NI_ITERATOR_NEXT2(ii, io, pi, po); - } - - /* calculate the filter offsets: */ - if (!NI_InitFilterOffsets(output, footprint, strct->dimensions, NULL, - NI_EXTEND_CONSTANT, &offsets, &mask_value, NULL)) - goto exit; - /* initialize filter iterator: */ - if (!NI_InitFilterIterator(input->nd, strct->dimensions, filter_size, - input->dimensions, NULL, &fi)) - goto exit; - /* reset output iterator: */ - NI_ITERATOR_RESET(io); - po = (void *)PyArray_DATA(output); - /* iterator over the elements: */ - oo = offsets; - for(jj = 0; jj < size; jj++) { - if (*(Int32*)po < 0) { - Int32 neighbor = 0; - /* iterate over structuring element: */ - for(ll = 0; ll < filter_size; ll++) { - int offset = oo[ll]; - if (offset != mask_value) { - Int32 tt = *(Int32*)(po + offset); - if (tt > 0) { - /* this element is next to an already found object: */ - if (neighbor && neighbor != tt) { - /* we have two objects that must be merged later: */ - _index_pair* tp = (_index_pair*)malloc(sizeof(_index_pair)); - if (!tp) { - PyErr_NoMemory(); - goto exit; - } - tp->next = pairs; - /* the pairs must be ordered: */ - if (neighbor < tt) { - tp->index1 = neighbor; - tp->index2 = tt; - } else { - tp->index1 = tt; - tp->index2 = neighbor; - } - pairs = tp; - } else { - neighbor = tt; - } - } - } - } - if (neighbor) { - /* this point belongs to an existing object */ - *(Int32*)po = neighbor; - } else { - /* this may be a new object: */ - *(Int32*)po = ++index; - } - } - NI_FILTER_NEXT(fi, io, oo, po); - } - *max_label = index; - /* merge any touching objects: */ - if (pairs) { - Int32 counter; - index_map = (Int32*)malloc(index * sizeof(Int32)); - if (!index_map) { - PyErr_NoMemory(); - goto exit; - } - for(jj = 0; jj < index; jj++) - index_map[jj] = (Int32)jj; - while (pairs) { - Int32 idx1 = pairs->index1 - 1; - Int32 idx2 = pairs->index2 - 1; - if (index_map[idx2] == idx1 || index_map[idx2] == idx2) { - /* if this pair was already processed, or if idx2 was not - mapped yet, we delete this pair and map idx2 to idx1: */ - _index_pair *tp = pairs; - pairs = tp->next; - free(tp); - index_map[idx2] = idx1; - } else { - /* idx2 was already mapped, therefore we find what it was - mapped to and change the current pair to the result of that - and idx1. Since the pair is not destroyed, it will be - re-processed with the adapted values. */ - idx2 = index_map[idx2]; - /* keep the pairs ordered: */ - if (idx1 < idx2) { - pairs->index1 = idx1 + 1; - pairs->index2 = idx2 + 1; - } else { - pairs->index1 = idx2 + 1; - pairs->index2 = idx1 + 1; - } - } - } - for(jj = 0; jj < index; jj++) { - /* if the current index maps to a index that is also mapped, - change it to map to that index. Since an index always maps to - a lower index or to itself, this will make sure that at the - end all indices map to an unmapped index. */ - if (index_map[index_map[jj]] < index_map[jj]) - index_map[jj] = index_map[index_map[jj]]; - } - /* renumber the indices that are not mapped: */ - counter = 0; - for(jj = 0; jj < index; jj++) - if (index_map[jj] == jj) - index_map[jj] = ++counter; - else - index_map[jj] = index_map[index_map[jj]]; - } - - /* relabel the output if we merged some objects: */ - if (index_map) { - *max_label = 0; - NI_ITERATOR_RESET(io); - po = (void *)PyArray_DATA(output); - for(jj = 0; jj < size; jj++) { - Int32 p = *(Int32*)po; - if (p > 0 ) - *(Int32*)po = index_map[p - 1]; - if (*(Int32*)po > *max_label) - *max_label = *(Int32*)po; - NI_ITERATOR_NEXT(io, po); - } - } - exit: - if (offsets) free(offsets); - if (index_map) free(index_map); - while (pairs) { - _index_pair *tp = pairs; - pairs = (_index_pair*)pairs->next; - free(tp); - } - if (footprint) - free(footprint); - return PyErr_Occurred() ? 0 : 1; -} - -#define CASE_FIND_OBJECT_POINT(_pi, _regions, _rank, _dimensions, \ - _max_label, _ii, _type) \ -case t ## _type: \ -{ \ - int _kk; \ - maybelong _sindex = *(_type*)_pi - 1; \ - if (_sindex >= 0 && _sindex < _max_label) { \ - if (_rank > 0) { \ - _sindex *= 2 * _rank; \ - if (_regions[_sindex] < 0) { \ - for(_kk = 0; _kk < _rank; _kk++) { \ - maybelong _cc = _ii.coordinates[_kk]; \ - _regions[_sindex + _kk] = _cc; \ - _regions[_sindex + _kk + _rank] = _cc + 1; \ - } \ - } else { \ - for(_kk = 0; _kk < _rank; _kk++) { \ - maybelong _cc = _ii.coordinates[_kk]; \ - if (_cc < _regions[_sindex + _kk]) \ - _regions[_sindex + _kk] = _cc; \ - if (_cc + 1 > _regions[_sindex + _kk + _rank]) \ - _regions[_sindex + _kk + _rank] = _cc + 1; \ - } \ - } \ - } else { \ - _regions[_sindex] = 1; \ - } \ - } \ -} \ -break - -int NI_FindObjects(PyArrayObject* input, maybelong max_label, - maybelong* regions) -{ - int kk; - maybelong size, jj; - NI_Iterator ii; - char *pi; - - /* get input data, size and iterator: */ - pi = (void *)PyArray_DATA(input); - size = 1; - for(kk = 0; kk < input->nd; kk++) - size *= input->dimensions[kk]; - if (!NI_InitPointIterator(input, &ii)) - goto exit; - if (input->nd > 0) { - for(jj = 0; jj < 2 * input->nd * max_label; jj++) - regions[jj] = -1; - } else { - for(jj = 0; jj < max_label; jj++) - regions[jj] = -1; - } - /* iterate over all points: */ - for(jj = 0 ; jj < size; jj++) { - switch (input->descr->type_num) { - CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, - max_label, ii, Bool); - CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, - max_label, ii, UInt8); - CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, - max_label, ii, UInt16); - CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, - max_label, ii, UInt32); -#if HAS_UINT64 - CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, - max_label, ii, UInt64); -#endif - CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, - max_label, ii, Int8); - CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, - max_label, ii, Int16); - CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, - max_label, ii, Int32); - CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, - max_label, ii, Int64); - break; - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - NI_ITERATOR_NEXT(ii, pi); - } - exit: - return PyErr_Occurred() ? 0 : 1; -} - - -/* macro to get input value: */ -#if HAS_UINT64 -#define NI_GET_VALUE(_pi, _v, _type) \ -{ \ - switch(_type) { \ - case tBool: \ - _v = (*(Bool*)_pi) != 0; \ - break; \ - case tUInt8: \ - _v = *(UInt8*)_pi; \ - break; \ - case tUInt16: \ - _v = *(UInt16*)_pi; \ - break; \ - case tUInt32: \ - _v = *(UInt32*)_pi; \ - break; \ - case tInt8: \ - _v = *(Int8*)_pi; \ - break; \ - case tInt16: \ - _v = *(Int16*)_pi; \ - break; \ - case tInt32: \ - _v = *(Int32*)_pi; \ - break; \ - case tInt64: \ - _v = *(Int64*)_pi; \ - break; \ - case tUInt64: \ - _v = *(UInt64*)_pi; \ - break; \ - case tFloat32: \ - _v = *(Float32*)_pi; \ - break; \ - case tFloat64: \ - _v = *(Float64*)_pi; \ - break; \ - default: \ - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); \ - return 0; \ - } \ -} -#else -#define NI_GET_VALUE(_pi, _v, _type) \ -{ \ - switch(_type) { \ - case tBool: \ - _v = (*(Bool*)_pi) != 0; \ - break; \ - case tUInt8: \ - _v = *(UInt8*)_pi; \ - break; \ - case tUInt16: \ - _v = *(UInt16*)_pi; \ - break; \ - case tUInt32: \ - _v = *(UInt32*)_pi; \ - break; \ - case tInt8: \ - _v = *(Int8*)_pi; \ - break; \ - case tInt16: \ - _v = *(Int16*)_pi; \ - break; \ - case tInt32: \ - _v = *(Int32*)_pi; \ - break; \ - case tInt64: \ - _v = *(Int64*)_pi; \ - break; \ - case tFloat32: \ - _v = *(Float32*)_pi; \ - break; \ - case tFloat64: \ - _v = *(Float64*)_pi; \ - break; \ - default: \ - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); \ - return 0; \ - } \ -} -#endif - -/* macro to get label value: */ -#if HAS_UINT64 -#define NI_GET_LABEL(_pm, _label, _type) \ -{ \ - if (_pm) { \ - switch(_type) { \ - case tBool: \ - _label = *(Bool*)_pm; \ - break; \ - case tUInt8: \ - _label = *(UInt8*)_pm; \ - break; \ - case tUInt16: \ - _label = *(UInt16*)_pm; \ - break; \ - case tUInt32: \ - _label = *(UInt32*)_pm; \ - break; \ - case tUInt64: \ - _label = *(UInt64*)_pm; \ - break; \ - case tInt8: \ - _label = *(Int8*)_pm; \ - break; \ - case tInt16: \ - _label = *(Int16*)_pm; \ - break; \ - case tInt32: \ - _label = *(Int32*)_pm; \ - break; \ - case tInt64: \ - _label = *(Int64*)_pm; \ - break; \ - case tFloat32: \ - _label = *(Float32*)_pm; \ - break; \ - case tFloat64: \ - _label = *(Float64*)_pm; \ - break; \ - default: \ - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); \ - return 0; \ - } \ - } \ -} -#else -#define NI_GET_LABEL(_pm, _label, _type) \ -{ \ - if (_pm) { \ - switch(_type) { \ - case tBool: \ - _label = *(Bool*)_pm; \ - break; \ - case tUInt8: \ - _label = *(UInt8*)_pm; \ - break; \ - case tUInt16: \ - _label = *(UInt16*)_pm; \ - break; \ - case tUInt32: \ - _label = *(UInt32*)_pm; \ - break; \ - case tInt8: \ - _label = *(Int8*)_pm; \ - break; \ - case tInt16: \ - _label = *(Int16*)_pm; \ - break; \ - case tInt32: \ - _label = *(Int32*)_pm; \ - break; \ - case tInt64: \ - _label = *(Int64*)_pm; \ - break; \ - case tFloat32: \ - _label = *(Float32*)_pm; \ - break; \ - case tFloat64: \ - _label = *(Float64*)_pm; \ - break; \ - default: \ - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); \ - return 0; \ - } \ - } \ -} -#endif - -int NI_Statistics(PyArrayObject *input, PyArrayObject *labels, - maybelong min_label, maybelong max_label, maybelong *indices, - maybelong n_results, double *sum, maybelong *total, double *variance, - double *minimum, double *maximum, maybelong* min_pos, maybelong* max_pos) -{ - char *pi = NULL, *pm = NULL; - NI_Iterator ii, mi; - maybelong jj, size, idx = 0, label = 1, doit = 1; - int qq; - - /* input iterator: */ - if (!NI_InitPointIterator(input, &ii)) - return 0; - /* input data: */ - pi = (void *)PyArray_DATA(input); - if (labels) { - if (!NI_InitPointIterator(labels, &mi)) - return 0; - pm = (void *)PyArray_DATA(labels); - } - /* input size: */ - size = 1; - for(qq = 0; qq < input->nd; qq++) - size *= input->dimensions[qq]; - for(jj = 0; jj < n_results; jj++) { - if (sum) - sum[jj] = 0.0; - if (total) - total[jj] = 0; - if (variance) - variance[jj] = 0; - if (minimum) - minimum[jj] = DBL_MAX; - if (maximum) - maximum[jj] = -DBL_MAX; - if (min_pos) - min_pos[jj] = 0; - if (max_pos) - max_pos[jj] = 0; - } - /* iterate over array: */ - for(jj = 0; jj < size; jj++) { - NI_GET_LABEL(pm, label, labels->descr->type_num); - if (min_label >= 0) { - if (label >= min_label && label <= max_label) { - idx = indices[label - min_label]; - doit = idx >= 0; - } else { - doit = 0; - } - } else { - doit = label != 0; - } - if (doit) { - double val; - NI_GET_VALUE(pi, val, input->descr->type_num); - if (sum) - sum[idx] += val; - if (total) - total[idx]++; - if (minimum && val < minimum[idx]) { - minimum[idx] = val; - if (min_pos) - min_pos[idx] = jj; - } - if (maximum && (val > maximum[idx])) { - maximum[idx] = val; - if (max_pos) - max_pos[idx] = jj; - } - } - if (labels) { - NI_ITERATOR_NEXT2(ii, mi, pi, pm); - } else { - NI_ITERATOR_NEXT(ii, pi); - } - } - if (minimum) { - for(jj = 0; jj < n_results; jj++) { - if (!(minimum[jj] < DBL_MAX)) - minimum[jj] = 0.0; - } - } - if (maximum) { - for(jj = 0; jj < n_results; jj++) { - if (!(maximum[jj] > -DBL_MAX)) - maximum[jj] = 0.0; - } - } - if (variance) { - int do_var = 0; - for(jj = 0; jj < n_results; jj++) - if (total[jj] > 1) { - do_var = 1; - break; - } - if (do_var) { - /* reset input iterator: */ - NI_ITERATOR_RESET(ii); - pi = (void *)PyArray_DATA(input); - if (labels) { - /* reset label iterator: */ - NI_ITERATOR_RESET(mi); - pm = (void *)PyArray_DATA(labels); - } - for(jj = 0; jj < size; jj++) { - NI_GET_LABEL(pm, label, labels->descr->type_num); - if (min_label >= 0) { - if (label >= min_label && label <= max_label) { - idx = indices[label - min_label]; - doit = idx >= 0; - } else { - doit = 0; - } - } else { - doit = label != 0; - } - if (doit) { - double val; - NI_GET_VALUE(pi, val, input->descr->type_num); - val = val - sum[idx] / total[idx]; - variance[idx] += val * val; - } - if (labels) { - NI_ITERATOR_NEXT2(ii, mi, pi, pm); - } else { - NI_ITERATOR_NEXT(ii, pi); - } - } - for(jj = 0; jj < n_results; jj++) - variance[jj] = (total[jj] > 1 ? - variance[jj] / (total[jj] - 1) : 0.0); - } - } - return 1; -} - - -int NI_CenterOfMass(PyArrayObject *input, PyArrayObject *labels, - maybelong min_label, maybelong max_label, maybelong *indices, - maybelong n_results, double *center_of_mass) -{ - char *pi = NULL, *pm = NULL; - NI_Iterator ii, mi; - maybelong jj, kk, size, idx = 0, label = 1, doit = 1; - double *sum = NULL; - int qq; - - /* input iterator: */ - if (!NI_InitPointIterator(input, &ii)) - goto exit; - /* input data: */ - pi = (void *)PyArray_DATA(input); - if (labels) { - if (!NI_InitPointIterator(labels, &mi)) - goto exit; - pm = (void *)PyArray_DATA(labels); - } - /* input size: */ - size = 1; - for(qq = 0; qq < input->nd; qq++) - size *= input->dimensions[qq]; - sum = (double*)malloc(n_results * sizeof(double)); - if (!sum) { - PyErr_NoMemory(); - goto exit; - } - for(jj = 0; jj < n_results; jj++) { - sum[jj] = 0.0; - for(kk = 0; kk < input->nd; kk++) - center_of_mass[jj * input->nd + kk] = 0.0; - } - /* iterate over array: */ - for(jj = 0; jj < size; jj++) { - NI_GET_LABEL(pm, label, labels->descr->type_num); - if (min_label >= 0) { - if (label >= min_label && label <= max_label) { - idx = indices[label - min_label]; - doit = idx >= 0; - } else { - doit = 0; - } - } else { - doit = label != 0; - } - if (doit) { - double val; - NI_GET_VALUE(pi, val, input->descr->type_num); - sum[idx] += val; - for(kk = 0; kk < input->nd; kk++) - center_of_mass[idx * input->nd + kk] += val * ii.coordinates[kk]; - } - if (labels) { - NI_ITERATOR_NEXT2(ii, mi, pi, pm); - } else { - NI_ITERATOR_NEXT(ii, pi); - } - } - for(jj = 0; jj < n_results; jj++) - for(kk = 0; kk < input->nd; kk++) - center_of_mass[jj * input->nd + kk] /= sum[jj]; - exit: - if (sum) - free(sum); - return PyErr_Occurred() == NULL; -} - - -int NI_Histogram(PyArrayObject *input, PyArrayObject *labels, - maybelong min_label, maybelong max_label, maybelong *indices, - maybelong n_results, PyArrayObject **histograms, - double min, double max, maybelong nbins) -{ - char *pi = NULL, *pm = NULL; - NI_Iterator ii, mi; - maybelong jj, kk, size, idx = 0, label = 1, doit = 1; - Int32 **ph = NULL; - double bsize; - int qq; - - /* input iterator: */ - if (!NI_InitPointIterator(input, &ii)) - goto exit; - /* input data: */ - pi = (void *)PyArray_DATA(input); - if (labels) { - if (!NI_InitPointIterator(labels, &mi)) - goto exit; - pm = (void *)PyArray_DATA(labels); - } - ph = (Int32**)malloc(n_results * sizeof(Int32*)); - if (!ph) { - PyErr_NoMemory(); - goto exit; - } - for(jj = 0; jj < n_results; jj++) { - ph[jj] = (Int32*)PyArray_DATA(histograms[jj]); - for(kk = 0; kk < nbins; kk++) - ph[jj][kk] = 0; - } - bsize = (max - min) / (double)nbins; - /* input size: */ - size = 1; - for(qq = 0; qq < input->nd; qq++) - size *= input->dimensions[qq]; - /* iterate over array: */ - for(jj = 0; jj < size; jj++) { - NI_GET_LABEL(pm, label, labels->descr->type_num); - if (min_label >= 0) { - if (label >= min_label && label <= max_label) { - idx = indices[label - min_label]; - doit = idx >= 0; - } else { - doit = 0; - } - } else { - doit = label != 0; - } - if (doit) { - int bin; - double val; - NI_GET_VALUE(pi, val, input->descr->type_num); - if (val >= min && val < max) { - bin = (int)((val - min) / bsize); - ++(ph[idx][bin]); - } - } - if (labels) { - NI_ITERATOR_NEXT2(ii, mi, pi, pm); - } else { - NI_ITERATOR_NEXT(ii, pi); - } - } - exit: - if (ph) - free(ph); - return PyErr_Occurred() == NULL; -} - -#define WS_GET_INDEX(_index, _c_strides, _b_strides, _rank, _out, \ - _contiguous, _type) \ -do { \ - if (_contiguous) { \ - _out = _index * sizeof(_type); \ - } else { \ - int _qq; \ - maybelong _cc, _idx = _index; \ - _out = 0; \ - for (_qq = 0; _qq < _rank; _qq++) { \ - _cc = _idx / _c_strides[_qq]; \ - _idx -= _cc * _c_strides[_qq]; \ - _out += _b_strides[_qq] * _cc; \ - } \ - } \ -} while(0) - -#define CASE_GET_INPUT(_ival, _pi, _type) \ -case t ## _type: \ - _ival = *((_type*)_pi); \ - break - -#define CASE_GET_LABEL(_label, _pm, _type) \ -case t ## _type: \ - _label = *(_type*)_pm; \ - break - -#define CASE_PUT_LABEL(_label, _pl, _type) \ -case t ## _type: \ - *((_type*)_pl) = _label; \ - break - -#define CASE_WINDEX1(_v_index, _p_index, _strides, _istrides, _irank, \ - _icont, _p_idx, _v_idx, _pi, _vval, _pval, _type) \ -case t ## _type: \ - WS_GET_INDEX(_v_index, _strides, _istrides, _irank, _p_idx, _icont, \ - _type); \ - WS_GET_INDEX(_p_index, _strides, _istrides, _irank, _v_idx, _icont, \ - _type); \ - _vval = *(_type*)(_pi + _v_idx); \ - _pval = *(_type*)(_pi + _p_idx); \ - break - -#define CASE_WINDEX2(_v_index, _strides, _ostrides, _irank, _idx, \ - _ocont, _label, _pl, _type) \ -case t ## _type: \ - WS_GET_INDEX(_v_index, _strides, _ostrides, _irank, _idx, \ - _ocont, _type); \ - _label = *(_type*)(_pl + _idx); \ - break - -#define CASE_WINDEX3(_p_index, _strides, _ostrides, _irank, _idx, \ - _ocont, _label, _pl, _type) \ -case t ## _type: \ - WS_GET_INDEX(_p_index, _strides, _ostrides, _irank, _idx, \ - _ocont, _type); \ - *(_type*)(_pl + _idx) = _label; \ -break - -#define DONE_TYPE UInt8 -#define COST_TYPE UInt16 -#define WS_MAXDIM 7 - -typedef struct { - maybelong index; - COST_TYPE cost; - void *next, *prev; - DONE_TYPE done; -} NI_WatershedElement; - -int NI_WatershedIFT(PyArrayObject* input, PyArrayObject* markers, - PyArrayObject* strct, PyArrayObject* output) -{ - char *pl, *pm, *pi; - int ll; - maybelong size, jj, hh, kk, maxval; - maybelong strides[WS_MAXDIM], coordinates[WS_MAXDIM]; - maybelong *nstrides = NULL, nneigh, ssize; - int i_contiguous, o_contiguous; - NI_WatershedElement *temp = NULL, **first = NULL, **last = NULL; - Bool *ps = NULL; - NI_Iterator mi, ii, li; - - i_contiguous = PyArray_ISCONTIGUOUS(input); - o_contiguous = PyArray_ISCONTIGUOUS(output); - ssize = 1; - for(ll = 0; ll < strct->nd; ll++) - ssize *= strct->dimensions[ll]; - if (input->nd > WS_MAXDIM) { - PyErr_SetString(PyExc_RuntimeError, "too many dimensions"); - goto exit; - } - size = 1; - for(ll = 0; ll < input->nd; ll++) - size *= input->dimensions[ll]; - /* Storage for the temporary queue data. */ - temp = (NI_WatershedElement*)malloc(size * sizeof(NI_WatershedElement)); - if (!temp) { - PyErr_NoMemory(); - goto exit; - } - pi = (void *)PyArray_DATA(input); - if (!NI_InitPointIterator(input, &ii)) - goto exit; - /* Initialization and find the maximum of the input. */ - maxval = 0; - for(jj = 0; jj < size; jj++) { - int ival = 0; - switch(input->descr->type_num) { - CASE_GET_INPUT(ival, pi, UInt8); - CASE_GET_INPUT(ival, pi, UInt16); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - temp[jj].index = jj; - temp[jj].done = 0; - if (ival > maxval) - maxval = ival; - NI_ITERATOR_NEXT(ii, pi); - } - pi = (void *)PyArray_DATA(input); - /* Allocate and initialize the storage for the queue. */ - first = (NI_WatershedElement**)malloc((maxval + 1) * - sizeof(NI_WatershedElement*)); - last = (NI_WatershedElement**)malloc((maxval + 1) * - sizeof(NI_WatershedElement*)); - if (!first || !last) { - PyErr_NoMemory(); - goto exit; - } - for(hh = 0; hh <= maxval; hh++) { - first[hh] = NULL; - last[hh] = NULL; - } - if (!NI_InitPointIterator(markers, &mi)) - goto exit; - if (!NI_InitPointIterator(output, &li)) - goto exit; - pm = (void *)PyArray_DATA(markers); - pl = (void *)PyArray_DATA(output); - /* initialize all nodes */ - for(ll = 0; ll < input->nd; ll++) - coordinates[ll] = 0; - for(jj = 0; jj < size; jj++) { - /* get marker */ - int label = 0; - switch(markers->descr->type_num) { - CASE_GET_LABEL(label, pm, UInt8); - CASE_GET_LABEL(label, pm, UInt16); - CASE_GET_LABEL(label, pm, UInt32); -#if HAS_UINT64 - CASE_GET_LABEL(label, pm, UInt64); -#endif - CASE_GET_LABEL(label, pm, Int8); - CASE_GET_LABEL(label, pm, Int16); - CASE_GET_LABEL(label, pm, Int32); - CASE_GET_LABEL(label, pm, Int64); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - switch(output->descr->type_num) { - CASE_PUT_LABEL(label, pl, UInt8); - CASE_PUT_LABEL(label, pl, UInt16); - CASE_PUT_LABEL(label, pl, UInt32); -#if HAS_UINT64 - CASE_PUT_LABEL(label, pl, UInt64); -#endif - CASE_PUT_LABEL(label, pl, Int8); - CASE_PUT_LABEL(label, pl, Int16); - CASE_PUT_LABEL(label, pl, Int32); - CASE_PUT_LABEL(label, pl, Int64); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - NI_ITERATOR_NEXT2(mi, li, pm, pl); - if (label != 0) { - /* This node is a marker */ - temp[jj].cost = 0; - if (!first[0]) { - first[0] = &(temp[jj]); - first[0]->next = NULL; - first[0]->prev = NULL; - last[0] = first[0]; - } else { - if (label > 0) { - /* object markers are enqueued at the beginning, so they are - processed first. */ - temp[jj].next = first[0]; - temp[jj].prev = NULL; - first[0]->prev = &(temp[jj]); - first[0] = &(temp[jj]); - } else { - /* background markers are enqueued at the end, so they are - processed after the object markers. */ - temp[jj].next = NULL; - temp[jj].prev = last[0]; - last[0]->next = &(temp[jj]); - last[0] = &(temp[jj]); - } - } - } else { - /* This node is not a marker */ - temp[jj].cost = maxval + 1; - temp[jj].next = NULL; - temp[jj].prev = NULL; - } - for(ll = input->nd - 1; ll >= 0; ll--) - if (coordinates[ll] < input->dimensions[ll] - 1) { - coordinates[ll]++; - break; - } else { - coordinates[ll] = 0; - } - } - - pl = (void *)PyArray_DATA(output); - ps = (Bool*)PyArray_DATA(strct); - nneigh = 0; - for (kk = 0; kk < ssize; kk++) - if (ps[kk] && kk != (ssize / 2)) - ++nneigh; - nstrides = (maybelong*)malloc(nneigh * sizeof(maybelong)); - if (!nstrides) { - PyErr_NoMemory(); - goto exit; - } - strides[input->nd - 1] = 1; - for(ll = input->nd - 2; ll >= 0; ll--) - strides[ll] = input->dimensions[ll + 1] * strides[ll + 1]; - for(ll = 0; ll < input->nd; ll++) - coordinates[ll] = -1; - for(kk = 0; kk < nneigh; kk++) - nstrides[kk] = 0; - jj = 0; - for(kk = 0; kk < ssize; kk++) { - if (ps[kk]) { - int offset = 0; - for(ll = 0; ll < input->nd; ll++) - offset += coordinates[ll] * strides[ll]; - if (offset != 0) - nstrides[jj++] += offset; - } - for(ll = input->nd - 1; ll >= 0; ll--) - if (coordinates[ll] < 1) { - coordinates[ll]++; - break; - } else { - coordinates[ll] = -1; - } - } - /* Propagation phase: */ - for(jj = 0; jj <= maxval; jj++) { - while (first[jj]) { - /* dequeue first element: */ - NI_WatershedElement *v = first[jj]; - first[jj] = first[jj]->next; - if (first[jj]) - first[jj]->prev = NULL; - v->prev = NULL; - v->next = NULL; - /* Mark element as done: */ - v->done = 1; - /* Iterate over the neighbors of the element: */ - for(hh = 0; hh < nneigh; hh++) { - maybelong v_index = v->index, p_index = v->index, idx, cc; - int qq, outside = 0; - p_index += nstrides[hh]; - /* check if the neighbor is within the extent of the array: */ - idx = p_index; - for (qq = 0; qq < input->nd; qq++) { - cc = idx / strides[qq]; - if (cc < 0 || cc >= input->dimensions[qq]) { - outside = 1; - break; - } - idx -= cc * strides[qq]; - } - if (!outside) { - NI_WatershedElement *p = &(temp[p_index]); - if (!(p->done)) { - /* If the neighbor was not processed yet: */ - int max, pval, vval, wvp, pcost, label, p_idx, v_idx; - switch(input->descr->type_num) { - CASE_WINDEX1(v_index, p_index, strides, input->strides, - input->nd, i_contiguous, p_idx, v_idx, pi, - vval, pval, UInt8); - CASE_WINDEX1(v_index, p_index, strides, input->strides, - input->nd, i_contiguous, p_idx, v_idx, pi, - vval, pval, UInt16); - default: - PyErr_SetString(PyExc_RuntimeError, - "data type not supported"); - goto exit; - } - /* Calculate cost: */ - wvp = pval - vval; - if (wvp < 0) - wvp = -wvp; - /* Find the maximum of this cost and the current - element cost: */ - pcost = p->cost; - max = v->cost > wvp ? v->cost : wvp; - if (max < pcost) { - /* If this maximum is less than the neighbors cost, - adapt the cost and the label of the neighbor: */ - int idx; - p->cost = max; - switch(output->descr->type_num) { - CASE_WINDEX2(v_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, UInt8); - CASE_WINDEX2(v_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, UInt16); - CASE_WINDEX2(v_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, UInt32); -#if HAS_UINT64 - CASE_WINDEX2(v_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, UInt64); -#endif - CASE_WINDEX2(v_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, Int8); - CASE_WINDEX2(v_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, Int16); - CASE_WINDEX2(v_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, Int32); - CASE_WINDEX2(v_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, Int64); - default: - PyErr_SetString(PyExc_RuntimeError, - "data type not supported"); - goto exit; - } - switch(output->descr->type_num) { - CASE_WINDEX3(p_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, UInt8); - CASE_WINDEX3(p_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, UInt16); - CASE_WINDEX3(p_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, UInt32); -#if HAS_UINT64 - CASE_WINDEX3(p_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, UInt64); -#endif - CASE_WINDEX3(p_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, Int8); - CASE_WINDEX3(p_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, Int16); - CASE_WINDEX3(p_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, Int32); - CASE_WINDEX3(p_index, strides, output->strides, input->nd, - idx, o_contiguous, label, pl, Int64); - default: - PyErr_SetString(PyExc_RuntimeError, - "data type not supported"); - goto exit; - } - /* If the neighbor is in a queue, remove it: */ - if (p->next || p->prev) { - NI_WatershedElement *prev = p->prev, *next = p->next; - if (first[pcost] == p) - first[pcost] = next; - if (last[pcost] == p) - last[pcost] = prev; - if (prev) - prev->next = next; - if (next) - next->prev = prev; - } - /* Insert the neighbor in the appropiate queue: */ - if (label < 0) { - p->prev = last[max]; - p->next = NULL; - if (last[max]) - last[max]->next = p; - last[max] = p; - if (!first[max]) - first[max] = p; - } else { - p->next = first[max]; - p->prev = NULL; - if (first[max]) - first[max]->prev = p; - first[max] = p; - if (!last[max]) - last[max] = p; - } - } - } - } - } - } - } - exit: - if (temp) - free(temp); - if (first) - free(first); - if (last) - free(last); - if (nstrides) - free(nstrides); - return PyErr_Occurred() ? 0 : 1; -} +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ni_support.h" +#include "ni_measure.h" +#include +#include +#include +#include + +typedef struct { + Int32 index1, index2; + void* next; +} _index_pair; + +#define CASE_LABEL(_p, _pi, _type) \ +case t ## _type: \ + *_p = *(_type*)_pi ? -1 : 0; \ + break + +int NI_Label(PyArrayObject* input, PyArrayObject* strct, + maybelong *max_label, PyArrayObject* output) +{ + int kk; + maybelong jj, ll, ssize, size, filter_size, *offsets = NULL; + maybelong mask_value, *oo; + Bool *ps, *footprint = NULL; + char *pi, *po; + Int32 index = 0, *index_map = NULL; + NI_FilterIterator fi; + NI_Iterator ii, io; + _index_pair *pairs = NULL; + + /* structure size */ + ssize = 1; + for(kk = 0; kk < strct->nd; kk++) + ssize *= strct->dimensions[kk]; + /* we only use the first half of the structure data, so we make a + temporary structure for use with the filter functions: */ + footprint = (Bool*)malloc(ssize * sizeof(Bool)); + if (!footprint) { + PyErr_NoMemory(); + goto exit; + } + ps = (Bool*)PyArray_DATA(strct); + filter_size = 0; + for(jj = 0; jj < ssize / 2; jj++) { + footprint[jj] = ps[jj]; + if (ps[jj]) + ++filter_size; + } + for(jj = ssize / 2; jj < ssize; jj++) + footprint[jj] = 0; + /* get data and size */ + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(kk = 0; kk < output->nd; kk++) + size *= output->dimensions[kk]; + if (!NI_InitPointIterator(input, &ii)) + goto exit; + if (!NI_InitPointIterator(output, &io)) + goto exit; + /* set all elements in the output corresponding to non-zero elements + in input to -1: */ + for(jj = 0; jj < size; jj++) { + Int32 *p = (Int32*)po; + switch (input->descr->type_num) { + CASE_LABEL(p, pi, Bool); + CASE_LABEL(p, pi, UInt8); + CASE_LABEL(p, pi, UInt16); + CASE_LABEL(p, pi, UInt32); +#if HAS_UINT64 + CASE_LABEL(p, pi, UInt64); +#endif + CASE_LABEL(p, pi, Int8); + CASE_LABEL(p, pi, Int16); + CASE_LABEL(p, pi, Int32); + CASE_LABEL(p, pi, Int64); + CASE_LABEL(p, pi, Float32); + CASE_LABEL(p, pi, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + NI_ITERATOR_NEXT2(ii, io, pi, po); + } + + /* calculate the filter offsets: */ + if (!NI_InitFilterOffsets(output, footprint, strct->dimensions, NULL, + NI_EXTEND_CONSTANT, &offsets, &mask_value, NULL)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(input->nd, strct->dimensions, filter_size, + input->dimensions, NULL, &fi)) + goto exit; + /* reset output iterator: */ + NI_ITERATOR_RESET(io); + po = (void *)PyArray_DATA(output); + /* iterator over the elements: */ + oo = offsets; + for(jj = 0; jj < size; jj++) { + if (*(Int32*)po < 0) { + Int32 neighbor = 0; + /* iterate over structuring element: */ + for(ll = 0; ll < filter_size; ll++) { + int offset = oo[ll]; + if (offset != mask_value) { + Int32 tt = *(Int32*)(po + offset); + if (tt > 0) { + /* this element is next to an already found object: */ + if (neighbor && neighbor != tt) { + /* we have two objects that must be merged later: */ + _index_pair* tp = (_index_pair*)malloc(sizeof(_index_pair)); + if (!tp) { + PyErr_NoMemory(); + goto exit; + } + tp->next = pairs; + /* the pairs must be ordered: */ + if (neighbor < tt) { + tp->index1 = neighbor; + tp->index2 = tt; + } else { + tp->index1 = tt; + tp->index2 = neighbor; + } + pairs = tp; + } else { + neighbor = tt; + } + } + } + } + if (neighbor) { + /* this point belongs to an existing object */ + *(Int32*)po = neighbor; + } else { + /* this may be a new object: */ + *(Int32*)po = ++index; + } + } + NI_FILTER_NEXT(fi, io, oo, po); + } + *max_label = index; + /* merge any touching objects: */ + if (pairs) { + Int32 counter; + index_map = (Int32*)malloc(index * sizeof(Int32)); + if (!index_map) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < index; jj++) + index_map[jj] = (Int32)jj; + while (pairs) { + Int32 idx1 = pairs->index1 - 1; + Int32 idx2 = pairs->index2 - 1; + if (index_map[idx2] == idx1 || index_map[idx2] == idx2) { + /* if this pair was already processed, or if idx2 was not + mapped yet, we delete this pair and map idx2 to idx1: */ + _index_pair *tp = pairs; + pairs = tp->next; + free(tp); + index_map[idx2] = idx1; + } else { + /* idx2 was already mapped, therefore we find what it was + mapped to and change the current pair to the result of that + and idx1. Since the pair is not destroyed, it will be + re-processed with the adapted values. */ + idx2 = index_map[idx2]; + /* keep the pairs ordered: */ + if (idx1 < idx2) { + pairs->index1 = idx1 + 1; + pairs->index2 = idx2 + 1; + } else { + pairs->index1 = idx2 + 1; + pairs->index2 = idx1 + 1; + } + } + } + for(jj = 0; jj < index; jj++) { + /* if the current index maps to a index that is also mapped, + change it to map to that index. Since an index always maps to + a lower index or to itself, this will make sure that at the + end all indices map to an unmapped index. */ + if (index_map[index_map[jj]] < index_map[jj]) + index_map[jj] = index_map[index_map[jj]]; + } + /* renumber the indices that are not mapped: */ + counter = 0; + for(jj = 0; jj < index; jj++) + if (index_map[jj] == jj) + index_map[jj] = ++counter; + else + index_map[jj] = index_map[index_map[jj]]; + } + + /* relabel the output if we merged some objects: */ + if (index_map) { + *max_label = 0; + NI_ITERATOR_RESET(io); + po = (void *)PyArray_DATA(output); + for(jj = 0; jj < size; jj++) { + Int32 p = *(Int32*)po; + if (p > 0 ) + *(Int32*)po = index_map[p - 1]; + if (*(Int32*)po > *max_label) + *max_label = *(Int32*)po; + NI_ITERATOR_NEXT(io, po); + } + } + exit: + if (offsets) free(offsets); + if (index_map) free(index_map); + while (pairs) { + _index_pair *tp = pairs; + pairs = (_index_pair*)pairs->next; + free(tp); + } + if (footprint) + free(footprint); + return PyErr_Occurred() ? 0 : 1; +} + +#define CASE_FIND_OBJECT_POINT(_pi, _regions, _rank, _dimensions, \ + _max_label, _ii, _type) \ +case t ## _type: \ +{ \ + int _kk; \ + maybelong _sindex = *(_type*)_pi - 1; \ + if (_sindex >= 0 && _sindex < _max_label) { \ + if (_rank > 0) { \ + _sindex *= 2 * _rank; \ + if (_regions[_sindex] < 0) { \ + for(_kk = 0; _kk < _rank; _kk++) { \ + maybelong _cc = _ii.coordinates[_kk]; \ + _regions[_sindex + _kk] = _cc; \ + _regions[_sindex + _kk + _rank] = _cc + 1; \ + } \ + } else { \ + for(_kk = 0; _kk < _rank; _kk++) { \ + maybelong _cc = _ii.coordinates[_kk]; \ + if (_cc < _regions[_sindex + _kk]) \ + _regions[_sindex + _kk] = _cc; \ + if (_cc + 1 > _regions[_sindex + _kk + _rank]) \ + _regions[_sindex + _kk + _rank] = _cc + 1; \ + } \ + } \ + } else { \ + _regions[_sindex] = 1; \ + } \ + } \ +} \ +break + +int NI_FindObjects(PyArrayObject* input, maybelong max_label, + maybelong* regions) +{ + int kk; + maybelong size, jj; + NI_Iterator ii; + char *pi; + + /* get input data, size and iterator: */ + pi = (void *)PyArray_DATA(input); + size = 1; + for(kk = 0; kk < input->nd; kk++) + size *= input->dimensions[kk]; + if (!NI_InitPointIterator(input, &ii)) + goto exit; + if (input->nd > 0) { + for(jj = 0; jj < 2 * input->nd * max_label; jj++) + regions[jj] = -1; + } else { + for(jj = 0; jj < max_label; jj++) + regions[jj] = -1; + } + /* iterate over all points: */ + for(jj = 0 ; jj < size; jj++) { + switch (input->descr->type_num) { + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, Bool); + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, UInt8); + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, UInt16); + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, UInt32); +#if HAS_UINT64 + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, UInt64); +#endif + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, Int8); + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, Int16); + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, Int32); + CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, + max_label, ii, Int64); + break; + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + NI_ITERATOR_NEXT(ii, pi); + } + exit: + return PyErr_Occurred() ? 0 : 1; +} + + +/* macro to get input value: */ +#if HAS_UINT64 +#define NI_GET_VALUE(_pi, _v, _type) \ +{ \ + switch(_type) { \ + case tBool: \ + _v = (*(Bool*)_pi) != 0; \ + break; \ + case tUInt8: \ + _v = *(UInt8*)_pi; \ + break; \ + case tUInt16: \ + _v = *(UInt16*)_pi; \ + break; \ + case tUInt32: \ + _v = *(UInt32*)_pi; \ + break; \ + case tInt8: \ + _v = *(Int8*)_pi; \ + break; \ + case tInt16: \ + _v = *(Int16*)_pi; \ + break; \ + case tInt32: \ + _v = *(Int32*)_pi; \ + break; \ + case tInt64: \ + _v = *(Int64*)_pi; \ + break; \ + case tUInt64: \ + _v = *(UInt64*)_pi; \ + break; \ + case tFloat32: \ + _v = *(Float32*)_pi; \ + break; \ + case tFloat64: \ + _v = *(Float64*)_pi; \ + break; \ + default: \ + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); \ + return 0; \ + } \ +} +#else +#define NI_GET_VALUE(_pi, _v, _type) \ +{ \ + switch(_type) { \ + case tBool: \ + _v = (*(Bool*)_pi) != 0; \ + break; \ + case tUInt8: \ + _v = *(UInt8*)_pi; \ + break; \ + case tUInt16: \ + _v = *(UInt16*)_pi; \ + break; \ + case tUInt32: \ + _v = *(UInt32*)_pi; \ + break; \ + case tInt8: \ + _v = *(Int8*)_pi; \ + break; \ + case tInt16: \ + _v = *(Int16*)_pi; \ + break; \ + case tInt32: \ + _v = *(Int32*)_pi; \ + break; \ + case tInt64: \ + _v = *(Int64*)_pi; \ + break; \ + case tFloat32: \ + _v = *(Float32*)_pi; \ + break; \ + case tFloat64: \ + _v = *(Float64*)_pi; \ + break; \ + default: \ + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); \ + return 0; \ + } \ +} +#endif + +/* macro to get label value: */ +#if HAS_UINT64 +#define NI_GET_LABEL(_pm, _label, _type) \ +{ \ + if (_pm) { \ + switch(_type) { \ + case tBool: \ + _label = *(Bool*)_pm; \ + break; \ + case tUInt8: \ + _label = *(UInt8*)_pm; \ + break; \ + case tUInt16: \ + _label = *(UInt16*)_pm; \ + break; \ + case tUInt32: \ + _label = *(UInt32*)_pm; \ + break; \ + case tUInt64: \ + _label = *(UInt64*)_pm; \ + break; \ + case tInt8: \ + _label = *(Int8*)_pm; \ + break; \ + case tInt16: \ + _label = *(Int16*)_pm; \ + break; \ + case tInt32: \ + _label = *(Int32*)_pm; \ + break; \ + case tInt64: \ + _label = *(Int64*)_pm; \ + break; \ + case tFloat32: \ + _label = *(Float32*)_pm; \ + break; \ + case tFloat64: \ + _label = *(Float64*)_pm; \ + break; \ + default: \ + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); \ + return 0; \ + } \ + } \ +} +#else +#define NI_GET_LABEL(_pm, _label, _type) \ +{ \ + if (_pm) { \ + switch(_type) { \ + case tBool: \ + _label = *(Bool*)_pm; \ + break; \ + case tUInt8: \ + _label = *(UInt8*)_pm; \ + break; \ + case tUInt16: \ + _label = *(UInt16*)_pm; \ + break; \ + case tUInt32: \ + _label = *(UInt32*)_pm; \ + break; \ + case tInt8: \ + _label = *(Int8*)_pm; \ + break; \ + case tInt16: \ + _label = *(Int16*)_pm; \ + break; \ + case tInt32: \ + _label = *(Int32*)_pm; \ + break; \ + case tInt64: \ + _label = *(Int64*)_pm; \ + break; \ + case tFloat32: \ + _label = *(Float32*)_pm; \ + break; \ + case tFloat64: \ + _label = *(Float64*)_pm; \ + break; \ + default: \ + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); \ + return 0; \ + } \ + } \ +} +#endif + +int NI_Statistics(PyArrayObject *input, PyArrayObject *labels, + maybelong min_label, maybelong max_label, maybelong *indices, + maybelong n_results, double *sum, maybelong *total, double *variance, + double *minimum, double *maximum, maybelong* min_pos, maybelong* max_pos) +{ + char *pi = NULL, *pm = NULL; + NI_Iterator ii, mi; + maybelong jj, size, idx = 0, label = 1, doit = 1; + int qq; + + /* input iterator: */ + if (!NI_InitPointIterator(input, &ii)) + return 0; + /* input data: */ + pi = (void *)PyArray_DATA(input); + if (labels) { + if (!NI_InitPointIterator(labels, &mi)) + return 0; + pm = (void *)PyArray_DATA(labels); + } + /* input size: */ + size = 1; + for(qq = 0; qq < input->nd; qq++) + size *= input->dimensions[qq]; + for(jj = 0; jj < n_results; jj++) { + if (sum) + sum[jj] = 0.0; + if (total) + total[jj] = 0; + if (variance) + variance[jj] = 0; + if (minimum) + minimum[jj] = DBL_MAX; + if (maximum) + maximum[jj] = -DBL_MAX; + if (min_pos) + min_pos[jj] = 0; + if (max_pos) + max_pos[jj] = 0; + } + /* iterate over array: */ + for(jj = 0; jj < size; jj++) { + NI_GET_LABEL(pm, label, labels->descr->type_num); + if (min_label >= 0) { + if (label >= min_label && label <= max_label) { + idx = indices[label - min_label]; + doit = idx >= 0; + } else { + doit = 0; + } + } else { + doit = label != 0; + } + if (doit) { + double val; + NI_GET_VALUE(pi, val, input->descr->type_num); + if (sum) + sum[idx] += val; + if (total) + total[idx]++; + if (minimum && val < minimum[idx]) { + minimum[idx] = val; + if (min_pos) + min_pos[idx] = jj; + } + if (maximum && (val > maximum[idx])) { + maximum[idx] = val; + if (max_pos) + max_pos[idx] = jj; + } + } + if (labels) { + NI_ITERATOR_NEXT2(ii, mi, pi, pm); + } else { + NI_ITERATOR_NEXT(ii, pi); + } + } + if (minimum) { + for(jj = 0; jj < n_results; jj++) { + if (!(minimum[jj] < DBL_MAX)) + minimum[jj] = 0.0; + } + } + if (maximum) { + for(jj = 0; jj < n_results; jj++) { + if (!(maximum[jj] > -DBL_MAX)) + maximum[jj] = 0.0; + } + } + if (variance) { + int do_var = 0; + for(jj = 0; jj < n_results; jj++) + if (total[jj] > 1) { + do_var = 1; + break; + } + if (do_var) { + /* reset input iterator: */ + NI_ITERATOR_RESET(ii); + pi = (void *)PyArray_DATA(input); + if (labels) { + /* reset label iterator: */ + NI_ITERATOR_RESET(mi); + pm = (void *)PyArray_DATA(labels); + } + for(jj = 0; jj < size; jj++) { + NI_GET_LABEL(pm, label, labels->descr->type_num); + if (min_label >= 0) { + if (label >= min_label && label <= max_label) { + idx = indices[label - min_label]; + doit = idx >= 0; + } else { + doit = 0; + } + } else { + doit = label != 0; + } + if (doit) { + double val; + NI_GET_VALUE(pi, val, input->descr->type_num); + val = val - sum[idx] / total[idx]; + variance[idx] += val * val; + } + if (labels) { + NI_ITERATOR_NEXT2(ii, mi, pi, pm); + } else { + NI_ITERATOR_NEXT(ii, pi); + } + } + for(jj = 0; jj < n_results; jj++) + variance[jj] = (total[jj] > 1 ? + variance[jj] / (total[jj] - 1) : 0.0); + } + } + return 1; +} + + +int NI_CenterOfMass(PyArrayObject *input, PyArrayObject *labels, + maybelong min_label, maybelong max_label, maybelong *indices, + maybelong n_results, double *center_of_mass) +{ + char *pi = NULL, *pm = NULL; + NI_Iterator ii, mi; + maybelong jj, kk, size, idx = 0, label = 1, doit = 1; + double *sum = NULL; + int qq; + + /* input iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* input data: */ + pi = (void *)PyArray_DATA(input); + if (labels) { + if (!NI_InitPointIterator(labels, &mi)) + goto exit; + pm = (void *)PyArray_DATA(labels); + } + /* input size: */ + size = 1; + for(qq = 0; qq < input->nd; qq++) + size *= input->dimensions[qq]; + sum = (double*)malloc(n_results * sizeof(double)); + if (!sum) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < n_results; jj++) { + sum[jj] = 0.0; + for(kk = 0; kk < input->nd; kk++) + center_of_mass[jj * input->nd + kk] = 0.0; + } + /* iterate over array: */ + for(jj = 0; jj < size; jj++) { + NI_GET_LABEL(pm, label, labels->descr->type_num); + if (min_label >= 0) { + if (label >= min_label && label <= max_label) { + idx = indices[label - min_label]; + doit = idx >= 0; + } else { + doit = 0; + } + } else { + doit = label != 0; + } + if (doit) { + double val; + NI_GET_VALUE(pi, val, input->descr->type_num); + sum[idx] += val; + for(kk = 0; kk < input->nd; kk++) + center_of_mass[idx * input->nd + kk] += val * ii.coordinates[kk]; + } + if (labels) { + NI_ITERATOR_NEXT2(ii, mi, pi, pm); + } else { + NI_ITERATOR_NEXT(ii, pi); + } + } + for(jj = 0; jj < n_results; jj++) + for(kk = 0; kk < input->nd; kk++) + center_of_mass[jj * input->nd + kk] /= sum[jj]; + exit: + if (sum) + free(sum); + return PyErr_Occurred() == NULL; +} + + +int NI_Histogram(PyArrayObject *input, PyArrayObject *labels, + maybelong min_label, maybelong max_label, maybelong *indices, + maybelong n_results, PyArrayObject **histograms, + double min, double max, maybelong nbins) +{ + char *pi = NULL, *pm = NULL; + NI_Iterator ii, mi; + maybelong jj, kk, size, idx = 0, label = 1, doit = 1; + Int32 **ph = NULL; + double bsize; + int qq; + + /* input iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* input data: */ + pi = (void *)PyArray_DATA(input); + if (labels) { + if (!NI_InitPointIterator(labels, &mi)) + goto exit; + pm = (void *)PyArray_DATA(labels); + } + ph = (Int32**)malloc(n_results * sizeof(Int32*)); + if (!ph) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < n_results; jj++) { + ph[jj] = (Int32*)PyArray_DATA(histograms[jj]); + for(kk = 0; kk < nbins; kk++) + ph[jj][kk] = 0; + } + bsize = (max - min) / (double)nbins; + /* input size: */ + size = 1; + for(qq = 0; qq < input->nd; qq++) + size *= input->dimensions[qq]; + /* iterate over array: */ + for(jj = 0; jj < size; jj++) { + NI_GET_LABEL(pm, label, labels->descr->type_num); + if (min_label >= 0) { + if (label >= min_label && label <= max_label) { + idx = indices[label - min_label]; + doit = idx >= 0; + } else { + doit = 0; + } + } else { + doit = label != 0; + } + if (doit) { + int bin; + double val; + NI_GET_VALUE(pi, val, input->descr->type_num); + if (val >= min && val < max) { + bin = (int)((val - min) / bsize); + ++(ph[idx][bin]); + } + } + if (labels) { + NI_ITERATOR_NEXT2(ii, mi, pi, pm); + } else { + NI_ITERATOR_NEXT(ii, pi); + } + } + exit: + if (ph) + free(ph); + return PyErr_Occurred() == NULL; +} + +#define WS_GET_INDEX(_index, _c_strides, _b_strides, _rank, _out, \ + _contiguous, _type) \ +do { \ + if (_contiguous) { \ + _out = _index * sizeof(_type); \ + } else { \ + int _qq; \ + maybelong _cc, _idx = _index; \ + _out = 0; \ + for (_qq = 0; _qq < _rank; _qq++) { \ + _cc = _idx / _c_strides[_qq]; \ + _idx -= _cc * _c_strides[_qq]; \ + _out += _b_strides[_qq] * _cc; \ + } \ + } \ +} while(0) + +#define CASE_GET_INPUT(_ival, _pi, _type) \ +case t ## _type: \ + _ival = *((_type*)_pi); \ + break + +#define CASE_GET_LABEL(_label, _pm, _type) \ +case t ## _type: \ + _label = *(_type*)_pm; \ + break + +#define CASE_PUT_LABEL(_label, _pl, _type) \ +case t ## _type: \ + *((_type*)_pl) = _label; \ + break + +#define CASE_WINDEX1(_v_index, _p_index, _strides, _istrides, _irank, \ + _icont, _p_idx, _v_idx, _pi, _vval, _pval, _type) \ +case t ## _type: \ + WS_GET_INDEX(_v_index, _strides, _istrides, _irank, _p_idx, _icont, \ + _type); \ + WS_GET_INDEX(_p_index, _strides, _istrides, _irank, _v_idx, _icont, \ + _type); \ + _vval = *(_type*)(_pi + _v_idx); \ + _pval = *(_type*)(_pi + _p_idx); \ + break + +#define CASE_WINDEX2(_v_index, _strides, _ostrides, _irank, _idx, \ + _ocont, _label, _pl, _type) \ +case t ## _type: \ + WS_GET_INDEX(_v_index, _strides, _ostrides, _irank, _idx, \ + _ocont, _type); \ + _label = *(_type*)(_pl + _idx); \ + break + +#define CASE_WINDEX3(_p_index, _strides, _ostrides, _irank, _idx, \ + _ocont, _label, _pl, _type) \ +case t ## _type: \ + WS_GET_INDEX(_p_index, _strides, _ostrides, _irank, _idx, \ + _ocont, _type); \ + *(_type*)(_pl + _idx) = _label; \ +break + +#define DONE_TYPE UInt8 +#define COST_TYPE UInt16 +#define WS_MAXDIM 7 + +typedef struct { + maybelong index; + COST_TYPE cost; + void *next, *prev; + DONE_TYPE done; +} NI_WatershedElement; + +int NI_WatershedIFT(PyArrayObject* input, PyArrayObject* markers, + PyArrayObject* strct, PyArrayObject* output) +{ + char *pl, *pm, *pi; + int ll; + maybelong size, jj, hh, kk, maxval; + maybelong strides[WS_MAXDIM], coordinates[WS_MAXDIM]; + maybelong *nstrides = NULL, nneigh, ssize; + int i_contiguous, o_contiguous; + NI_WatershedElement *temp = NULL, **first = NULL, **last = NULL; + Bool *ps = NULL; + NI_Iterator mi, ii, li; + + i_contiguous = PyArray_ISCONTIGUOUS(input); + o_contiguous = PyArray_ISCONTIGUOUS(output); + ssize = 1; + for(ll = 0; ll < strct->nd; ll++) + ssize *= strct->dimensions[ll]; + if (input->nd > WS_MAXDIM) { + PyErr_SetString(PyExc_RuntimeError, "too many dimensions"); + goto exit; + } + size = 1; + for(ll = 0; ll < input->nd; ll++) + size *= input->dimensions[ll]; + /* Storage for the temporary queue data. */ + temp = (NI_WatershedElement*)malloc(size * sizeof(NI_WatershedElement)); + if (!temp) { + PyErr_NoMemory(); + goto exit; + } + pi = (void *)PyArray_DATA(input); + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* Initialization and find the maximum of the input. */ + maxval = 0; + for(jj = 0; jj < size; jj++) { + int ival = 0; + switch(input->descr->type_num) { + CASE_GET_INPUT(ival, pi, UInt8); + CASE_GET_INPUT(ival, pi, UInt16); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + temp[jj].index = jj; + temp[jj].done = 0; + if (ival > maxval) + maxval = ival; + NI_ITERATOR_NEXT(ii, pi); + } + pi = (void *)PyArray_DATA(input); + /* Allocate and initialize the storage for the queue. */ + first = (NI_WatershedElement**)malloc((maxval + 1) * + sizeof(NI_WatershedElement*)); + last = (NI_WatershedElement**)malloc((maxval + 1) * + sizeof(NI_WatershedElement*)); + if (!first || !last) { + PyErr_NoMemory(); + goto exit; + } + for(hh = 0; hh <= maxval; hh++) { + first[hh] = NULL; + last[hh] = NULL; + } + if (!NI_InitPointIterator(markers, &mi)) + goto exit; + if (!NI_InitPointIterator(output, &li)) + goto exit; + pm = (void *)PyArray_DATA(markers); + pl = (void *)PyArray_DATA(output); + /* initialize all nodes */ + for(ll = 0; ll < input->nd; ll++) + coordinates[ll] = 0; + for(jj = 0; jj < size; jj++) { + /* get marker */ + int label = 0; + switch(markers->descr->type_num) { + CASE_GET_LABEL(label, pm, UInt8); + CASE_GET_LABEL(label, pm, UInt16); + CASE_GET_LABEL(label, pm, UInt32); +#if HAS_UINT64 + CASE_GET_LABEL(label, pm, UInt64); +#endif + CASE_GET_LABEL(label, pm, Int8); + CASE_GET_LABEL(label, pm, Int16); + CASE_GET_LABEL(label, pm, Int32); + CASE_GET_LABEL(label, pm, Int64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + switch(output->descr->type_num) { + CASE_PUT_LABEL(label, pl, UInt8); + CASE_PUT_LABEL(label, pl, UInt16); + CASE_PUT_LABEL(label, pl, UInt32); +#if HAS_UINT64 + CASE_PUT_LABEL(label, pl, UInt64); +#endif + CASE_PUT_LABEL(label, pl, Int8); + CASE_PUT_LABEL(label, pl, Int16); + CASE_PUT_LABEL(label, pl, Int32); + CASE_PUT_LABEL(label, pl, Int64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + NI_ITERATOR_NEXT2(mi, li, pm, pl); + if (label != 0) { + /* This node is a marker */ + temp[jj].cost = 0; + if (!first[0]) { + first[0] = &(temp[jj]); + first[0]->next = NULL; + first[0]->prev = NULL; + last[0] = first[0]; + } else { + if (label > 0) { + /* object markers are enqueued at the beginning, so they are + processed first. */ + temp[jj].next = first[0]; + temp[jj].prev = NULL; + first[0]->prev = &(temp[jj]); + first[0] = &(temp[jj]); + } else { + /* background markers are enqueued at the end, so they are + processed after the object markers. */ + temp[jj].next = NULL; + temp[jj].prev = last[0]; + last[0]->next = &(temp[jj]); + last[0] = &(temp[jj]); + } + } + } else { + /* This node is not a marker */ + temp[jj].cost = maxval + 1; + temp[jj].next = NULL; + temp[jj].prev = NULL; + } + for(ll = input->nd - 1; ll >= 0; ll--) + if (coordinates[ll] < input->dimensions[ll] - 1) { + coordinates[ll]++; + break; + } else { + coordinates[ll] = 0; + } + } + + pl = (void *)PyArray_DATA(output); + ps = (Bool*)PyArray_DATA(strct); + nneigh = 0; + for (kk = 0; kk < ssize; kk++) + if (ps[kk] && kk != (ssize / 2)) + ++nneigh; + nstrides = (maybelong*)malloc(nneigh * sizeof(maybelong)); + if (!nstrides) { + PyErr_NoMemory(); + goto exit; + } + strides[input->nd - 1] = 1; + for(ll = input->nd - 2; ll >= 0; ll--) + strides[ll] = input->dimensions[ll + 1] * strides[ll + 1]; + for(ll = 0; ll < input->nd; ll++) + coordinates[ll] = -1; + for(kk = 0; kk < nneigh; kk++) + nstrides[kk] = 0; + jj = 0; + for(kk = 0; kk < ssize; kk++) { + if (ps[kk]) { + int offset = 0; + for(ll = 0; ll < input->nd; ll++) + offset += coordinates[ll] * strides[ll]; + if (offset != 0) + nstrides[jj++] += offset; + } + for(ll = input->nd - 1; ll >= 0; ll--) + if (coordinates[ll] < 1) { + coordinates[ll]++; + break; + } else { + coordinates[ll] = -1; + } + } + /* Propagation phase: */ + for(jj = 0; jj <= maxval; jj++) { + while (first[jj]) { + /* dequeue first element: */ + NI_WatershedElement *v = first[jj]; + first[jj] = first[jj]->next; + if (first[jj]) + first[jj]->prev = NULL; + v->prev = NULL; + v->next = NULL; + /* Mark element as done: */ + v->done = 1; + /* Iterate over the neighbors of the element: */ + for(hh = 0; hh < nneigh; hh++) { + maybelong v_index = v->index, p_index = v->index, idx, cc; + int qq, outside = 0; + p_index += nstrides[hh]; + /* check if the neighbor is within the extent of the array: */ + idx = p_index; + for (qq = 0; qq < input->nd; qq++) { + cc = idx / strides[qq]; + if (cc < 0 || cc >= input->dimensions[qq]) { + outside = 1; + break; + } + idx -= cc * strides[qq]; + } + if (!outside) { + NI_WatershedElement *p = &(temp[p_index]); + if (!(p->done)) { + /* If the neighbor was not processed yet: */ + int max, pval, vval, wvp, pcost, label, p_idx, v_idx; + switch(input->descr->type_num) { + CASE_WINDEX1(v_index, p_index, strides, input->strides, + input->nd, i_contiguous, p_idx, v_idx, pi, + vval, pval, UInt8); + CASE_WINDEX1(v_index, p_index, strides, input->strides, + input->nd, i_contiguous, p_idx, v_idx, pi, + vval, pval, UInt16); + default: + PyErr_SetString(PyExc_RuntimeError, + "data type not supported"); + goto exit; + } + /* Calculate cost: */ + wvp = pval - vval; + if (wvp < 0) + wvp = -wvp; + /* Find the maximum of this cost and the current + element cost: */ + pcost = p->cost; + max = v->cost > wvp ? v->cost : wvp; + if (max < pcost) { + /* If this maximum is less than the neighbors cost, + adapt the cost and the label of the neighbor: */ + int idx; + p->cost = max; + switch(output->descr->type_num) { + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt8); + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt16); + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt32); +#if HAS_UINT64 + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt64); +#endif + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int8); + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int16); + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int32); + CASE_WINDEX2(v_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int64); + default: + PyErr_SetString(PyExc_RuntimeError, + "data type not supported"); + goto exit; + } + switch(output->descr->type_num) { + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt8); + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt16); + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt32); +#if HAS_UINT64 + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, UInt64); +#endif + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int8); + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int16); + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int32); + CASE_WINDEX3(p_index, strides, output->strides, input->nd, + idx, o_contiguous, label, pl, Int64); + default: + PyErr_SetString(PyExc_RuntimeError, + "data type not supported"); + goto exit; + } + /* If the neighbor is in a queue, remove it: */ + if (p->next || p->prev) { + NI_WatershedElement *prev = p->prev, *next = p->next; + if (first[pcost] == p) + first[pcost] = next; + if (last[pcost] == p) + last[pcost] = prev; + if (prev) + prev->next = next; + if (next) + next->prev = prev; + } + /* Insert the neighbor in the appropiate queue: */ + if (label < 0) { + p->prev = last[max]; + p->next = NULL; + if (last[max]) + last[max]->next = p; + last[max] = p; + if (!first[max]) + first[max] = p; + } else { + p->next = first[max]; + p->prev = NULL; + if (first[max]) + first[max]->prev = p; + first[max] = p; + if (!last[max]) + last[max] = p; + } + } + } + } + } + } + } + exit: + if (temp) + free(temp); + if (first) + free(first); + if (last) + free(last); + if (nstrides) + free(nstrides); + return PyErr_Occurred() ? 0 : 1; +} Modified: trunk/scipy/ndimage/src/ni_measure.h =================================================================== --- trunk/scipy/ndimage/src/ni_measure.h 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/ni_measure.h 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,59 +1,59 @@ -/* Copyright (C) 2003-2005 Peter J. Verveer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef NI_MEASURE_H -#define NI_MEASURE_H - -#include "nd_image.h" - -/* structure for array regions to find objects: */ -typedef struct { - int start[NI_MAXDIM], end[NI_MAXDIM]; -} NI_ObjectRegion; - -int NI_Label(PyArrayObject*, PyArrayObject*, maybelong*, PyArrayObject*); - -int NI_FindObjects(PyArrayObject*, maybelong, maybelong*); - -int NI_CenterOfMass(PyArrayObject*, PyArrayObject*, maybelong, maybelong, - maybelong*, maybelong, double*); - -int NI_Histogram(PyArrayObject*, PyArrayObject*, maybelong, maybelong, - maybelong*, maybelong, PyArrayObject**, double, double, maybelong); - -int NI_Statistics(PyArrayObject*, PyArrayObject*, maybelong, maybelong, - maybelong*, maybelong, double*, maybelong*, double*, - double*, double*, maybelong*, maybelong*); - -int NI_WatershedIFT(PyArrayObject*, PyArrayObject*, PyArrayObject*, - PyArrayObject*); - -#endif +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NI_MEASURE_H +#define NI_MEASURE_H + +#include "nd_image.h" + +/* structure for array regions to find objects: */ +typedef struct { + int start[NI_MAXDIM], end[NI_MAXDIM]; +} NI_ObjectRegion; + +int NI_Label(PyArrayObject*, PyArrayObject*, maybelong*, PyArrayObject*); + +int NI_FindObjects(PyArrayObject*, maybelong, maybelong*); + +int NI_CenterOfMass(PyArrayObject*, PyArrayObject*, maybelong, maybelong, + maybelong*, maybelong, double*); + +int NI_Histogram(PyArrayObject*, PyArrayObject*, maybelong, maybelong, + maybelong*, maybelong, PyArrayObject**, double, double, maybelong); + +int NI_Statistics(PyArrayObject*, PyArrayObject*, maybelong, maybelong, + maybelong*, maybelong, double*, maybelong*, double*, + double*, double*, maybelong*, maybelong*); + +int NI_WatershedIFT(PyArrayObject*, PyArrayObject*, PyArrayObject*, + PyArrayObject*); + +#endif Modified: trunk/scipy/ndimage/src/ni_morphology.c =================================================================== --- trunk/scipy/ndimage/src/ni_morphology.c 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/ni_morphology.c 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,955 +1,955 @@ -/* Copyright (C) 2003-2005 Peter J. Verveer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ni_support.h" -#include "ni_morphology.h" -#include -#include -#include -#include - -#define LIST_SIZE 100000 - -#define CASE_GET_MASK(_msk_value, _pm, _type) \ -case t ## _type: \ - _msk_value = *(_type*)_pm ? 1 : 0; \ - break - -#define CASE_OUTPUT(_po, _out, _type) \ -case t ## _type: \ - *(_type*)_po = (_type)_out; \ - break - -#define CASE_NI_ERODE_POINT(_pi, _out, _offsets, _filter_size, _type, \ - _mv, _border_value, _bv, _center_is_true,\ - _true, _false, _changed) \ -case t ## _type: \ -{ \ - maybelong _ii, _oo; \ - int _in = *(_type*)_pi ? 1 : 0; \ - if (_mv) { \ - if (_center_is_true && _in == false) { \ - _changed = 0; \ - _out = _in; \ - } else { \ - _out = _true; \ - for(_ii = 0; _ii < _filter_size; _ii++) { \ - _oo = _offsets[_ii]; \ - if (_oo == _bv) { \ - if (!_border_value) { \ - _out = _false; \ - break; \ - } \ - } else { \ - int _nn = *(_type*)(_pi + _oo) ? _true : _false; \ - if (!_nn) { \ - _out = _false; \ - break; \ - } \ - } \ - } \ - _changed = _out != _in; \ - } \ - } else { \ - _out = _in; \ - } \ -} \ -break - -int NI_BinaryErosion(PyArrayObject* input, PyArrayObject* strct, - PyArrayObject* mask, PyArrayObject* output, int bdr_value, - maybelong *origins, int invert, int center_is_true, int* changed, - NI_CoordinateList **coordinate_list) -{ - maybelong struct_size = 0, *offsets = NULL, size, *oo, jj; - maybelong ssize, block_size = 0, *current = NULL, border_flag_value; - int kk, true, false, msk_value; - NI_Iterator ii, io, mi; - NI_FilterIterator fi; - Bool *ps, out = 0; - char *pi, *po, *pm = NULL; - NI_CoordinateBlock *block = NULL; - - ps = (Bool*)PyArray_DATA(strct); - ssize = 1; - for(kk = 0; kk < strct->nd; kk++) - ssize *= strct->dimensions[kk]; - for(jj = 0; jj < ssize; jj++) - if (ps[jj]) ++struct_size; - if (mask) { - if (!NI_InitPointIterator(mask, &mi)) - return 0; - pm = (void *)PyArray_DATA(mask); - } - /* calculate the filter offsets: */ - if (!NI_InitFilterOffsets(input, ps, strct->dimensions, origins, - NI_EXTEND_CONSTANT, &offsets, &border_flag_value, NULL)) - goto exit; - /* initialize input element iterator: */ - if (!NI_InitPointIterator(input, &ii)) - goto exit; - /* initialize output element iterator: */ - if (!NI_InitPointIterator(output, &io)) - goto exit; - /* initialize filter iterator: */ - if (!NI_InitFilterIterator(input->nd, strct->dimensions, struct_size, - input->dimensions, origins, &fi)) - goto exit; - - /* get data pointers an size: */ - pi = (void *)PyArray_DATA(input); - po = (void *)PyArray_DATA(output); - size = 1; - for(kk = 0; kk < input->nd; kk++) - size *= input->dimensions[kk]; - if (invert) { - bdr_value = bdr_value ? 0 : 1; - true = 0; - false = 1; - } else { - bdr_value = bdr_value ? 1 : 0; - true = 1; - false = 0; - } - if (coordinate_list) { - block_size = LIST_SIZE / input->nd / sizeof(int); - if (block_size < 1) - block_size = 1; - if (block_size > size) - block_size = size; - *coordinate_list = NI_InitCoordinateList(block_size, input->nd); - if (!*coordinate_list) - goto exit; - } - /* iterator over the elements: */ - oo = offsets; - *changed = 0; - msk_value = 1; - for(jj = 0; jj < size; jj++) { - int pchange = 0; - if (mask) { - switch(mask->descr->type_num) { - CASE_GET_MASK(msk_value, pm, Bool); - CASE_GET_MASK(msk_value, pm, UInt8); - CASE_GET_MASK(msk_value, pm, UInt16); - CASE_GET_MASK(msk_value, pm, UInt32); -#if HAS_UINT64 - CASE_GET_MASK(msk_value, pm, UInt64); -#endif - CASE_GET_MASK(msk_value, pm, Int8); - CASE_GET_MASK(msk_value, pm, Int16); - CASE_GET_MASK(msk_value, pm, Int32); - CASE_GET_MASK(msk_value, pm, Int64); - CASE_GET_MASK(msk_value, pm, Float32); - CASE_GET_MASK(msk_value, pm, Float64); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - return 0; - } - } - switch (input->descr->type_num) { - CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Bool, msk_value, - bdr_value, border_flag_value, center_is_true, - true, false, pchange); - CASE_NI_ERODE_POINT(pi, out, oo, struct_size, UInt8, msk_value, - bdr_value, border_flag_value, center_is_true, - true, false, pchange); - CASE_NI_ERODE_POINT(pi, out, oo, struct_size, UInt16, msk_value, - bdr_value, border_flag_value, center_is_true, - true, false, pchange); - CASE_NI_ERODE_POINT(pi, out, oo, struct_size, UInt32, msk_value, - bdr_value, border_flag_value, center_is_true, - true, false, pchange); -#if HAS_UINT64 - CASE_NI_ERODE_POINT(pi, out, oo, struct_size, UInt64, msk_value, - bdr_value, border_flag_value, center_is_true, - true, false, pchange); -#endif - CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Int8, msk_value, - bdr_value, border_flag_value, center_is_true, - true, false, pchange); - CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Int16, msk_value, - bdr_value, border_flag_value, center_is_true, - true, false, pchange); - CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Int32, msk_value, - bdr_value, border_flag_value, center_is_true, - true, false, pchange); - CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Int64, msk_value, - bdr_value, border_flag_value, center_is_true, - true, false, pchange); - CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Float32, msk_value, - bdr_value, border_flag_value, center_is_true, - true, false, pchange); - CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Float64, msk_value, - bdr_value, border_flag_value, center_is_true, - true, false, pchange); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - switch (output->descr->type_num) { - CASE_OUTPUT(po, out, Bool); - CASE_OUTPUT(po, out, UInt8); - CASE_OUTPUT(po, out, UInt16); - CASE_OUTPUT(po, out, UInt32); -#if HAS_UINT64 - CASE_OUTPUT(po, out, UInt64); -#endif - CASE_OUTPUT(po, out, Int8); - CASE_OUTPUT(po, out, Int16); - CASE_OUTPUT(po, out, Int32); - CASE_OUTPUT(po, out, Int64); - CASE_OUTPUT(po, out, Float32); - CASE_OUTPUT(po, out, Float64); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - if (pchange) { - *changed = 1; - if (coordinate_list) { - if (block == NULL || block->size == block_size) { - block = NI_CoordinateListAddBlock(*coordinate_list); - current = block->coordinates; - } - for(kk = 0; kk < input->nd; kk++) - *current++ = ii.coordinates[kk]; - block->size++; - } - } - if (mask) { - NI_FILTER_NEXT3(fi, ii, io, mi, oo, pi, po, pm); - } else { - NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); - } - } - - exit: - if (offsets) - free(offsets); - if (PyErr_Occurred()) { - if (coordinate_list) { - NI_FreeCoordinateList(*coordinate_list); - *coordinate_list = NULL; - } - return 0; - } else { - return 1; - } - return PyErr_Occurred() ? 0 : 1; -} - -#define CASE_ERODE_POINT2(_struct_size, _offsets, _coordinate_offsets, \ - _pi, _oo, _irank, _list1, _list2, \ - _current_coors1, _current_coors2, _block1, \ - _block2, _bf_value, _true, _false, _type, \ - _mklist) \ -case t ## _type: \ -{ \ - maybelong _hh, _kk; \ - for(_hh = 0; _hh < _struct_size; _hh++) { \ - maybelong _to = _offsets[_oo + _hh]; \ - if (_to != _bf_value && *(_type*)(_pi + _to) == _true) { \ - if (_mklist) { \ - maybelong *_tc = &(_coordinate_offsets[(_oo + _hh) * _irank]); \ - if (_block2 == NULL || _block2->size == _list2->block_size) { \ - _block2 = NI_CoordinateListAddBlock(_list2); \ - _current_coors2 = _block2->coordinates; \ - } \ - for(_kk = 0; _kk < _irank; _kk++) \ - *_current_coors2++ = _current_coors1[_kk] + _tc[_kk]; \ - _block2->size++; \ - } \ - *(_type*)(_pi + _to) = _false; \ - } \ - } \ -} \ -break - -int NI_BinaryErosion2(PyArrayObject* array, PyArrayObject* strct, - PyArrayObject* mask, int niter, maybelong *origins, - int invert, NI_CoordinateList **iclist) -{ - maybelong struct_size = 0, *offsets = NULL, oo, jj, ssize; - maybelong *coordinate_offsets = NULL, size = 0; - maybelong *current_coordinates1 = NULL, *current_coordinates2 = NULL; - maybelong kk, border_flag_value, current = 0; - int true, false; - NI_Iterator ii, mi; - NI_FilterIterator fi, ci; - Bool *ps; - char *pi, *ibase, *pm = NULL; - NI_CoordinateBlock *block1 = NULL, *block2 = NULL; - NI_CoordinateList *list1 = NULL, *list2 = NULL; - - ps = (Bool*)PyArray_DATA(strct); - ssize = 1; - for(kk = 0; kk < strct->nd; kk++) - ssize *= strct->dimensions[kk]; - for(jj = 0; jj < ssize; jj++) - if (ps[jj]) ++struct_size; - - /* calculate the filter offsets: */ - if (!NI_InitFilterOffsets(array, ps, strct->dimensions, origins, - NI_EXTEND_CONSTANT, &offsets, - &border_flag_value, &coordinate_offsets)) - goto exit; - - /* initialize input element iterator: */ - if (!NI_InitPointIterator(array, &ii)) - goto exit; - - /* initialize filter iterator: */ - if (!NI_InitFilterIterator(array->nd, strct->dimensions, struct_size, - array->dimensions, origins, &fi)) - goto exit; - if (!NI_InitFilterIterator(array->nd, strct->dimensions, - struct_size * array->nd, array->dimensions, - origins, &ci)) - goto exit; - - /* get data pointers and size: */ - ibase = pi = (void *)PyArray_DATA(array); - - if (invert) { - true = 0; - false = 1; - } else { - true = 1; - false = 0; - } - - if (mask) { - /* iterator, data pointer and type of mask array: */ - if (!NI_InitPointIterator(mask, &mi)) - return 0; - pm = (void *)PyArray_DATA(mask); - - size = 1; - for(kk = 0; kk < array->nd; kk++) - size *= array->dimensions[kk]; - - for(jj = 0; jj < size; jj++) { - if (*(Int8*)pm) { - *(Int8*)pm = -1; - } else { - *(Int8*)pm = (Int8)*(Bool*)pi; - *(Bool*)pi = false; - } - NI_ITERATOR_NEXT2(ii, mi, pi, pm) - } - NI_ITERATOR_RESET(ii) - pi = (void *)PyArray_DATA(array); - } - - list1 = NI_InitCoordinateList((*iclist)->block_size, (*iclist)->rank); - list2 = NI_InitCoordinateList((*iclist)->block_size, (*iclist)->rank); - if (!list1 || !list2) - goto exit; - if (NI_CoordinateListStealBlocks(list2, *iclist)) - goto exit; - block2 = list2->blocks; - jj = 0; - while(block1 || block2) { - int mklist = 1; - if (!block1) { - if (niter <= 0 || jj < niter) { - if (NI_CoordinateListStealBlocks(list1, list2)) - goto exit; - block1 = list1->blocks; - block2 = NULL; - current_coordinates1 = block1->coordinates; - current = 0; - ++jj; - mklist = niter <= 0 || jj < niter; - } else { - break; - } - } - NI_ITERATOR_GOTO(ii, current_coordinates1, ibase, pi); - NI_FILTER_GOTO(fi, ii, 0, oo); - - switch (array->descr->type_num) { - CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, - oo, array->nd, list1, list2, current_coordinates1, - current_coordinates2, block1, block2, - border_flag_value, true, false, Bool, mklist); - CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, - oo, array->nd, list1, list2, current_coordinates1, - current_coordinates2, block1, block2, - border_flag_value, true, false, UInt8, mklist); - CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, - oo, array->nd, list1, list2, current_coordinates1, - current_coordinates2, block1, block2, - border_flag_value, true, false, UInt16, mklist); - CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, - oo, array->nd, list1, list2, current_coordinates1, - current_coordinates2, block1, block2, - border_flag_value, true, false, UInt32, mklist); -#if HAS_UINT64 - CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, - oo, array->nd, list1, list2, current_coordinates1, - current_coordinates2, block1, block2, - border_flag_value, true, false, UInt64, mklist); -#endif - CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, - oo, array->nd, list1, list2, current_coordinates1, - current_coordinates2, block1, block2, - border_flag_value, true, false, Int8, mklist); - CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, - oo, array->nd, list1, list2, current_coordinates1, - current_coordinates2, block1, block2, - border_flag_value, true, false, Int16, mklist); - CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, - oo, array->nd, list1, list2, current_coordinates1, - current_coordinates2, block1, block2, - border_flag_value, true, false, Int32, mklist); - CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, - oo, array->nd, list1, list2, current_coordinates1, - current_coordinates2, block1, block2, - border_flag_value, true, false, Int64, mklist); - CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, - oo, array->nd, list1, list2, current_coordinates1, - current_coordinates2, block1, block2, - border_flag_value, true, false, Float32, mklist); - CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, - oo, array->nd, list1, list2, current_coordinates1, - current_coordinates2, block1, block2, - border_flag_value, true, false, Float64, mklist); - default: - PyErr_SetString(PyExc_RuntimeError, "data type not supported"); - goto exit; - } - - ++current; - if (current == block1->size) { - block1 = NI_CoordinateListDeleteBlock(list1); - if (block1) { - current_coordinates1 = block1->coordinates; - current = 0; - } - } else { - current_coordinates1 += array->nd; - } - } - - if (mask) { - NI_ITERATOR_RESET(ii) - NI_ITERATOR_RESET(mi) - pi = (void *)PyArray_DATA(array); - pm = (void *)PyArray_DATA(mask); - for(jj = 0; jj < size; jj++) { - int value = *(Int8*)pm; - if (value >= 0) - *(Bool*)pi = value; - NI_ITERATOR_NEXT2(ii, mi, pi, pm) - } - } - - exit: - if (offsets) - free(offsets); - if (coordinate_offsets) - free(coordinate_offsets); - NI_FreeCoordinateList(list1); - NI_FreeCoordinateList(list2); - if (PyErr_Occurred()) { - return 0; - } else { - return 1; - } - return PyErr_Occurred() ? 0 : 1; -} - - -#define NI_DISTANCE_EUCLIDIAN 1 -#define NI_DISTANCE_CITY_BLOCK 2 -#define NI_DISTANCE_CHESSBOARD 3 - -typedef struct { - maybelong *coordinates; - maybelong index; - void *next; -} NI_BorderElement; - -int NI_DistanceTransformBruteForce(PyArrayObject* input, int metric, - PyArrayObject *sampling_arr, - PyArrayObject* distances, - PyArrayObject* features) -{ - maybelong size, jj, min_index = 0; - int kk; - NI_BorderElement *border_elements = NULL, *temp; - NI_Iterator ii, di, fi; - char *pi, *pd = NULL, *pf = NULL; - Float64 *sampling = sampling_arr ? (void *)PyArray_DATA(sampling_arr) : NULL; - - /* check the output arrays: */ - if (distances) { - pd = (void *)PyArray_DATA(distances); - if (!NI_InitPointIterator(distances, &di)) - goto exit; - } - - if (features) { - pf = (void *)PyArray_DATA(features); - if (!NI_InitPointIterator(features, &fi)) - goto exit; - } - - size = 1; - for(kk = 0; kk < input->nd; kk++) - size *= input->dimensions[kk]; - pi = (void *)PyArray_DATA(input); - - if (!NI_InitPointIterator(input, &ii)) - goto exit; - - for(jj = 0; jj < size; jj++) { - if (*(Int8*)pi < 0) { - temp = (NI_BorderElement*)malloc(sizeof(NI_BorderElement)); - if (!temp) { - PyErr_NoMemory(); - goto exit; - } - temp->next = border_elements; - border_elements = temp; - temp->index = jj; - temp->coordinates = (maybelong*)malloc(input->nd * sizeof(maybelong)); - for(kk = 0; kk < input->nd; kk++) - temp->coordinates[kk] = ii.coordinates[kk]; - } - NI_ITERATOR_NEXT(ii, pi); - } - - NI_ITERATOR_RESET(ii); - pi = (void *)PyArray_DATA(input); - - switch(metric) { - case NI_DISTANCE_EUCLIDIAN: - for(jj = 0; jj < size; jj++) { - if (*(Int8*)pi > 0) { - double distance = DBL_MAX; - temp = border_elements; - while(temp) { - double d = 0.0, t; - for(kk = 0; kk < input->nd; kk++) { - t = ii.coordinates[kk] - temp->coordinates[kk]; - if (sampling) - t *= sampling[kk]; - d += t * t; - } - if (d < distance) { - distance = d; - if (features) - min_index = temp->index; - } - temp = temp->next; - } - if (distances) - *(Float64*)pd = sqrt(distance); - if (features) - *(Int32*)pf = min_index; - } else { - if (distances) - *(Float64*)pd = 0.0; - if (features) - *(Int32*)pf = jj; - } - if (features && distances) { - NI_ITERATOR_NEXT3(ii, di, fi, pi, pd, pf); - } else if (distances) { - NI_ITERATOR_NEXT2(ii, di, pi, pd); - } else { - NI_ITERATOR_NEXT2(ii, fi, pi, pf); - } - } - break; - case NI_DISTANCE_CITY_BLOCK: - case NI_DISTANCE_CHESSBOARD: - for(jj = 0; jj < size; jj++) { - if (*(Int8*)pi > 0) { - unsigned long distance = ULONG_MAX; - temp = border_elements; - while(temp) { - unsigned int d = 0; - maybelong t; - for(kk = 0; kk < input->nd; kk++) { - t = ii.coordinates[kk] - temp->coordinates[kk]; - if (t < 0) - t = -t; - if (metric == NI_DISTANCE_CITY_BLOCK) { - d += t; - } else { - if ((unsigned int)t > d) - d = t; - } - } - if (d < distance) { - distance = d; - if (features) - min_index = temp->index; - } - temp = temp->next; - } - if (distances) - *(UInt32*)pd = distance; - if (features) - *(Int32*)pf = min_index; - } else { - if (distances) - *(UInt32*)pd = 0; - if (features) - *(Int32*)pf = jj; - } - if (features && distances) { - NI_ITERATOR_NEXT3(ii, di, fi, pi, pd, pf); - } else if (distances) { - NI_ITERATOR_NEXT2(ii, di, pi, pd); - } else { - NI_ITERATOR_NEXT2(ii, fi, pi, pf); - } - } - break; - default: - PyErr_SetString(PyExc_RuntimeError, "distance metric not supported"); - goto exit; - } - - exit: - while (border_elements) { - temp = border_elements; - border_elements = border_elements->next; - if (temp->coordinates) - free(temp->coordinates); - free(temp); - } - return PyErr_Occurred() ? 0 : 1; -} - - -int NI_DistanceTransformOnePass(PyArrayObject *strct, - PyArrayObject* distances, PyArrayObject *features) -{ - int kk; - maybelong jj, ii, ssize, size, filter_size, mask_value, *oo; - maybelong *foffsets = NULL, *foo = NULL, *offsets = NULL; - Bool *ps, *pf = NULL, *footprint = NULL; - char *pd; - NI_FilterIterator si, ti; - NI_Iterator di, fi; - - ssize = 1; - for(kk = 0; kk < strct->nd; kk++) - ssize *= strct->dimensions[kk]; - - /* we only use the first half of the structure data, so we make a - temporary structure for use with the filter functions: */ - footprint = (Bool*)malloc(ssize * sizeof(Bool)); - if (!footprint) { - PyErr_NoMemory(); - goto exit; - } - ps = (Bool*)PyArray_DATA(strct); - filter_size = 0; - for(jj = 0; jj < ssize / 2; jj++) { - footprint[jj] = ps[jj]; - if (ps[jj]) - ++filter_size; - } - for(jj = ssize / 2; jj < ssize; jj++) - footprint[jj] = 0; - /* get data and size */ - pd = (void *)PyArray_DATA(distances); - size = 1; - for(kk = 0; kk < distances->nd; kk++) - size *= distances->dimensions[kk]; - if (!NI_InitPointIterator(distances, &di)) - goto exit; - /* calculate the filter offsets: */ - if (!NI_InitFilterOffsets(distances, footprint, strct->dimensions, NULL, - NI_EXTEND_CONSTANT, &offsets, &mask_value, NULL)) - goto exit; - /* initialize filter iterator: */ - if (!NI_InitFilterIterator(distances->nd, strct->dimensions, - filter_size, distances->dimensions, NULL, &si)) - goto exit; - - if (features) { - maybelong dummy; - /* initialize point iterator: */ - pf = (void *)PyArray_DATA(features); - if (!NI_InitPointIterator(features, &fi)) - goto exit; - /* calculate the filter offsets: */ - if (!NI_InitFilterOffsets(features, footprint, strct->dimensions, - NULL, NI_EXTEND_CONSTANT, &foffsets, &dummy, NULL)) - goto exit; - /* initialize filter iterator: */ - if (!NI_InitFilterIterator(distances->nd, strct->dimensions, - filter_size, distances->dimensions, NULL, &ti)) - goto exit; - } - /* iterator over the elements: */ - oo = offsets; - if (features) - foo = foffsets; - for(jj = 0; jj < size; jj++) { - Int32 value = *(Int32*)pd; - if (value != 0) { - Int32 min = value; - maybelong min_offset = 0; - /* iterate over structuring element: */ - for(ii = 0; ii < filter_size; ii++) { - maybelong offset = oo[ii]; - Int32 tt = -1; - if (offset < mask_value) - tt = *(Int32*)(pd + offset); - if (tt >= 0) { - if ((min < 0) || (tt + 1 < min)) { - min = tt + 1; - if (features) - min_offset = foo[ii]; - } - } - } - *(Int32*)pd = min; - if (features) - *(Int32*)pf = *(Int32*)(pf + min_offset); - } - if (features) { - NI_FILTER_NEXT(ti, fi, foo, pf); - } - NI_FILTER_NEXT(si, di, oo, pd); - } - - exit: - if (offsets) free(offsets); - if (foffsets) free(foffsets); - if (footprint) - free(footprint); - return PyErr_Occurred() ? 0 : 1; -} - -static void _VoronoiFT(char *pf, maybelong len, maybelong *coor, int rank, - int d, maybelong stride, maybelong cstride, - maybelong **f, maybelong *g, Float64 *sampling) -{ - maybelong l = -1, ii, maxl, idx1, idx2; - int jj; - - for(ii = 0; ii < len; ii++) - for(jj = 0; jj < rank; jj++) - f[ii][jj] = *(Int32*)(pf + ii * stride + cstride * jj); - for(ii = 0; ii < len; ii++) { - if (*(Int32*)(pf + ii * stride) >= 0) { - double fd = f[ii][d]; - double wR = 0.0; - for(jj = 0; jj < rank; jj++) { - if (jj != d) { - double tw = f[ii][jj] - coor[jj]; - if (sampling) - tw *= sampling[jj]; - wR += tw * tw; - } - } - while(l >= 1) { - double a, b, c, uR = 0.0, vR = 0.0, f1; - idx1 = g[l]; - f1 = f[idx1][d]; - idx2 = g[l - 1]; - a = f1 - f[idx2][d]; - b = fd - f1; - if (sampling) { - a *= sampling[d]; - b *= sampling[d]; - } - c = a + b; - for(jj = 0; jj < rank; jj++) { - if (jj != d) { - double cc = coor[jj]; - double tu = f[idx2][jj] - cc; - double tv = f[idx1][jj] - cc; - if (sampling) { - tu *= sampling[jj]; - tv *= sampling[jj]; - } - uR += tu * tu; - vR += tv * tv; - } - } - if (c * vR - b * uR - a * wR - a * b * c <= 0.0) - break; - --l; - } - ++l; - g[l] = ii; - } - } - maxl = l; - if (maxl >= 0) { - l = 0; - for (ii = 0; ii < len; ii++) { - double delta1 = 0.0, t; - for(jj = 0; jj < rank; jj++) { - t = jj == d ? f[g[l]][jj] - ii : f[g[l]][jj] - coor[jj]; - if (sampling) - t *= sampling[jj]; - delta1 += t * t; - } - while (l < maxl) { - double delta2 = 0.0; - for(jj = 0; jj < rank; jj++) { - t = jj == d ? f[g[l + 1]][jj] - ii : f[g[l + 1]][jj] - coor[jj]; - if (sampling) - t *= sampling[jj]; - delta2 += t * t; - } - if (delta1 <= delta2) - break; - delta1 = delta2; - ++l; - } - idx1 = g[l]; - for(jj = 0; jj < rank; jj++) - *(Int32*)(pf + ii * stride + jj * cstride) = f[idx1][jj]; - } - } -} - - -/* Recursive feature transform */ -static void _ComputeFT(char *pi, char *pf, maybelong *ishape, - maybelong *istrides, maybelong *fstrides, int rank, - int d, maybelong *coor, maybelong **f, maybelong *g, - PyArrayObject *features, Float64 *sampling) -{ - int kk; - maybelong jj; - - if (d == 0) { - char *tf1 = pf; - for(jj = 0; jj < ishape[0]; jj++) { - if (*(Int8*)pi) { - *(Int32*)tf1 = -1; - } else { - char *tf2 = tf1; - *(Int32*)tf2 = jj; - for(kk = 1; kk < rank; kk++) { - tf2 += fstrides[0]; - *(Int32*)tf2 = coor[kk]; - } - } - pi += istrides[0]; - tf1 += fstrides[1]; - } - _VoronoiFT(pf, ishape[0], coor, rank, 0, fstrides[1], fstrides[0], f, - g, sampling); - } else { - UInt32 axes = 0; - char *tf = pf; - maybelong size = 1; - NI_Iterator ii; - - for(jj = 0; jj < ishape[d]; jj++) { - coor[d] = jj; - _ComputeFT(pi, tf, ishape, istrides, fstrides, rank, d - 1, coor, f, - g, features, sampling); - pi += istrides[d]; - tf += fstrides[d + 1]; - } - - for(jj = 0; jj < d; jj++) { - axes |= (UInt32)1 << (jj + 1); - size *= ishape[jj]; - } - NI_InitPointIterator(features, &ii); - NI_SubspaceIterator(&ii, axes); - tf = pf; - for(jj = 0; jj < size; jj++) { - for(kk = 0; kk < d; kk++) - coor[kk] = ii.coordinates[kk]; - _VoronoiFT(tf, ishape[d], coor, rank, d, fstrides[d + 1], - fstrides[0], f, g, sampling); - NI_ITERATOR_NEXT(ii, tf); - } - for(kk = 0; kk < d; kk++) - coor[kk] = 0; - } -} - -/* Exact euclidean feature transform, as described in: C. R. Maurer, - Jr., R. Qi, V. Raghavan, "A linear time algorithm for computing - exact euclidean distance transforms of binary images in arbitrary - dimensions. IEEE Trans. PAMI 25, 265-270, 2003. */ -int NI_EuclideanFeatureTransform(PyArrayObject* input, - PyArrayObject *sampling_arr, - PyArrayObject* features) -{ - int ii; - maybelong coor[NI_MAXDIM], mx = 0, jj; - maybelong *tmp = NULL, **f = NULL, *g = NULL; - char *pi, *pf; - Float64 *sampling = sampling_arr ? ((void *)PyArray_DATA(sampling_arr)) : NULL; - - pi = (void *)PyArray_DATA(input); - pf = (void *)PyArray_DATA(features); - for(ii = 0; ii < input->nd; ii++) { - coor[ii] = 0; - if (input->dimensions[ii] > mx) - mx = input->dimensions[ii]; - } - - /* Some temporaries */ - f = (maybelong**)malloc(mx * sizeof(maybelong*)); - g = (maybelong*)malloc(mx * sizeof(maybelong)); - tmp = (maybelong*)malloc(mx * input->nd * sizeof(maybelong)); - if (!f || !g || !tmp) { - PyErr_NoMemory(); - goto exit; - } - for(jj = 0; jj < mx; jj++) - f[jj] = tmp + jj * input->nd; - - /* First call of recursive feature transform */ - _ComputeFT(pi, pf, input->dimensions, input->strides, features->strides, - input->nd, input->nd - 1, coor, f, g, features, sampling); - - exit: - if (f) - free(f); - if (g) - free(g); - if (tmp) - free(tmp); - - return PyErr_Occurred() ? 0 : 1; -} +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ni_support.h" +#include "ni_morphology.h" +#include +#include +#include +#include + +#define LIST_SIZE 100000 + +#define CASE_GET_MASK(_msk_value, _pm, _type) \ +case t ## _type: \ + _msk_value = *(_type*)_pm ? 1 : 0; \ + break + +#define CASE_OUTPUT(_po, _out, _type) \ +case t ## _type: \ + *(_type*)_po = (_type)_out; \ + break + +#define CASE_NI_ERODE_POINT(_pi, _out, _offsets, _filter_size, _type, \ + _mv, _border_value, _bv, _center_is_true,\ + _true, _false, _changed) \ +case t ## _type: \ +{ \ + maybelong _ii, _oo; \ + int _in = *(_type*)_pi ? 1 : 0; \ + if (_mv) { \ + if (_center_is_true && _in == false) { \ + _changed = 0; \ + _out = _in; \ + } else { \ + _out = _true; \ + for(_ii = 0; _ii < _filter_size; _ii++) { \ + _oo = _offsets[_ii]; \ + if (_oo == _bv) { \ + if (!_border_value) { \ + _out = _false; \ + break; \ + } \ + } else { \ + int _nn = *(_type*)(_pi + _oo) ? _true : _false; \ + if (!_nn) { \ + _out = _false; \ + break; \ + } \ + } \ + } \ + _changed = _out != _in; \ + } \ + } else { \ + _out = _in; \ + } \ +} \ +break + +int NI_BinaryErosion(PyArrayObject* input, PyArrayObject* strct, + PyArrayObject* mask, PyArrayObject* output, int bdr_value, + maybelong *origins, int invert, int center_is_true, int* changed, + NI_CoordinateList **coordinate_list) +{ + maybelong struct_size = 0, *offsets = NULL, size, *oo, jj; + maybelong ssize, block_size = 0, *current = NULL, border_flag_value; + int kk, true, false, msk_value; + NI_Iterator ii, io, mi; + NI_FilterIterator fi; + Bool *ps, out = 0; + char *pi, *po, *pm = NULL; + NI_CoordinateBlock *block = NULL; + + ps = (Bool*)PyArray_DATA(strct); + ssize = 1; + for(kk = 0; kk < strct->nd; kk++) + ssize *= strct->dimensions[kk]; + for(jj = 0; jj < ssize; jj++) + if (ps[jj]) ++struct_size; + if (mask) { + if (!NI_InitPointIterator(mask, &mi)) + return 0; + pm = (void *)PyArray_DATA(mask); + } + /* calculate the filter offsets: */ + if (!NI_InitFilterOffsets(input, ps, strct->dimensions, origins, + NI_EXTEND_CONSTANT, &offsets, &border_flag_value, NULL)) + goto exit; + /* initialize input element iterator: */ + if (!NI_InitPointIterator(input, &ii)) + goto exit; + /* initialize output element iterator: */ + if (!NI_InitPointIterator(output, &io)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(input->nd, strct->dimensions, struct_size, + input->dimensions, origins, &fi)) + goto exit; + + /* get data pointers an size: */ + pi = (void *)PyArray_DATA(input); + po = (void *)PyArray_DATA(output); + size = 1; + for(kk = 0; kk < input->nd; kk++) + size *= input->dimensions[kk]; + if (invert) { + bdr_value = bdr_value ? 0 : 1; + true = 0; + false = 1; + } else { + bdr_value = bdr_value ? 1 : 0; + true = 1; + false = 0; + } + if (coordinate_list) { + block_size = LIST_SIZE / input->nd / sizeof(int); + if (block_size < 1) + block_size = 1; + if (block_size > size) + block_size = size; + *coordinate_list = NI_InitCoordinateList(block_size, input->nd); + if (!*coordinate_list) + goto exit; + } + /* iterator over the elements: */ + oo = offsets; + *changed = 0; + msk_value = 1; + for(jj = 0; jj < size; jj++) { + int pchange = 0; + if (mask) { + switch(mask->descr->type_num) { + CASE_GET_MASK(msk_value, pm, Bool); + CASE_GET_MASK(msk_value, pm, UInt8); + CASE_GET_MASK(msk_value, pm, UInt16); + CASE_GET_MASK(msk_value, pm, UInt32); +#if HAS_UINT64 + CASE_GET_MASK(msk_value, pm, UInt64); +#endif + CASE_GET_MASK(msk_value, pm, Int8); + CASE_GET_MASK(msk_value, pm, Int16); + CASE_GET_MASK(msk_value, pm, Int32); + CASE_GET_MASK(msk_value, pm, Int64); + CASE_GET_MASK(msk_value, pm, Float32); + CASE_GET_MASK(msk_value, pm, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + return 0; + } + } + switch (input->descr->type_num) { + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Bool, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, UInt8, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, UInt16, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, UInt32, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); +#if HAS_UINT64 + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, UInt64, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); +#endif + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Int8, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Int16, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Int32, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Int64, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Float32, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + CASE_NI_ERODE_POINT(pi, out, oo, struct_size, Float64, msk_value, + bdr_value, border_flag_value, center_is_true, + true, false, pchange); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + switch (output->descr->type_num) { + CASE_OUTPUT(po, out, Bool); + CASE_OUTPUT(po, out, UInt8); + CASE_OUTPUT(po, out, UInt16); + CASE_OUTPUT(po, out, UInt32); +#if HAS_UINT64 + CASE_OUTPUT(po, out, UInt64); +#endif + CASE_OUTPUT(po, out, Int8); + CASE_OUTPUT(po, out, Int16); + CASE_OUTPUT(po, out, Int32); + CASE_OUTPUT(po, out, Int64); + CASE_OUTPUT(po, out, Float32); + CASE_OUTPUT(po, out, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + if (pchange) { + *changed = 1; + if (coordinate_list) { + if (block == NULL || block->size == block_size) { + block = NI_CoordinateListAddBlock(*coordinate_list); + current = block->coordinates; + } + for(kk = 0; kk < input->nd; kk++) + *current++ = ii.coordinates[kk]; + block->size++; + } + } + if (mask) { + NI_FILTER_NEXT3(fi, ii, io, mi, oo, pi, po, pm); + } else { + NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); + } + } + + exit: + if (offsets) + free(offsets); + if (PyErr_Occurred()) { + if (coordinate_list) { + NI_FreeCoordinateList(*coordinate_list); + *coordinate_list = NULL; + } + return 0; + } else { + return 1; + } + return PyErr_Occurred() ? 0 : 1; +} + +#define CASE_ERODE_POINT2(_struct_size, _offsets, _coordinate_offsets, \ + _pi, _oo, _irank, _list1, _list2, \ + _current_coors1, _current_coors2, _block1, \ + _block2, _bf_value, _true, _false, _type, \ + _mklist) \ +case t ## _type: \ +{ \ + maybelong _hh, _kk; \ + for(_hh = 0; _hh < _struct_size; _hh++) { \ + maybelong _to = _offsets[_oo + _hh]; \ + if (_to != _bf_value && *(_type*)(_pi + _to) == _true) { \ + if (_mklist) { \ + maybelong *_tc = &(_coordinate_offsets[(_oo + _hh) * _irank]); \ + if (_block2 == NULL || _block2->size == _list2->block_size) { \ + _block2 = NI_CoordinateListAddBlock(_list2); \ + _current_coors2 = _block2->coordinates; \ + } \ + for(_kk = 0; _kk < _irank; _kk++) \ + *_current_coors2++ = _current_coors1[_kk] + _tc[_kk]; \ + _block2->size++; \ + } \ + *(_type*)(_pi + _to) = _false; \ + } \ + } \ +} \ +break + +int NI_BinaryErosion2(PyArrayObject* array, PyArrayObject* strct, + PyArrayObject* mask, int niter, maybelong *origins, + int invert, NI_CoordinateList **iclist) +{ + maybelong struct_size = 0, *offsets = NULL, oo, jj, ssize; + maybelong *coordinate_offsets = NULL, size = 0; + maybelong *current_coordinates1 = NULL, *current_coordinates2 = NULL; + maybelong kk, border_flag_value, current = 0; + int true, false; + NI_Iterator ii, mi; + NI_FilterIterator fi, ci; + Bool *ps; + char *pi, *ibase, *pm = NULL; + NI_CoordinateBlock *block1 = NULL, *block2 = NULL; + NI_CoordinateList *list1 = NULL, *list2 = NULL; + + ps = (Bool*)PyArray_DATA(strct); + ssize = 1; + for(kk = 0; kk < strct->nd; kk++) + ssize *= strct->dimensions[kk]; + for(jj = 0; jj < ssize; jj++) + if (ps[jj]) ++struct_size; + + /* calculate the filter offsets: */ + if (!NI_InitFilterOffsets(array, ps, strct->dimensions, origins, + NI_EXTEND_CONSTANT, &offsets, + &border_flag_value, &coordinate_offsets)) + goto exit; + + /* initialize input element iterator: */ + if (!NI_InitPointIterator(array, &ii)) + goto exit; + + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(array->nd, strct->dimensions, struct_size, + array->dimensions, origins, &fi)) + goto exit; + if (!NI_InitFilterIterator(array->nd, strct->dimensions, + struct_size * array->nd, array->dimensions, + origins, &ci)) + goto exit; + + /* get data pointers and size: */ + ibase = pi = (void *)PyArray_DATA(array); + + if (invert) { + true = 0; + false = 1; + } else { + true = 1; + false = 0; + } + + if (mask) { + /* iterator, data pointer and type of mask array: */ + if (!NI_InitPointIterator(mask, &mi)) + return 0; + pm = (void *)PyArray_DATA(mask); + + size = 1; + for(kk = 0; kk < array->nd; kk++) + size *= array->dimensions[kk]; + + for(jj = 0; jj < size; jj++) { + if (*(Int8*)pm) { + *(Int8*)pm = -1; + } else { + *(Int8*)pm = (Int8)*(Bool*)pi; + *(Bool*)pi = false; + } + NI_ITERATOR_NEXT2(ii, mi, pi, pm) + } + NI_ITERATOR_RESET(ii) + pi = (void *)PyArray_DATA(array); + } + + list1 = NI_InitCoordinateList((*iclist)->block_size, (*iclist)->rank); + list2 = NI_InitCoordinateList((*iclist)->block_size, (*iclist)->rank); + if (!list1 || !list2) + goto exit; + if (NI_CoordinateListStealBlocks(list2, *iclist)) + goto exit; + block2 = list2->blocks; + jj = 0; + while(block1 || block2) { + int mklist = 1; + if (!block1) { + if (niter <= 0 || jj < niter) { + if (NI_CoordinateListStealBlocks(list1, list2)) + goto exit; + block1 = list1->blocks; + block2 = NULL; + current_coordinates1 = block1->coordinates; + current = 0; + ++jj; + mklist = niter <= 0 || jj < niter; + } else { + break; + } + } + NI_ITERATOR_GOTO(ii, current_coordinates1, ibase, pi); + NI_FILTER_GOTO(fi, ii, 0, oo); + + switch (array->descr->type_num) { + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, Bool, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, UInt8, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, UInt16, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, UInt32, mklist); +#if HAS_UINT64 + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, UInt64, mklist); +#endif + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, Int8, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, Int16, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, Int32, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, Int64, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, Float32, mklist); + CASE_ERODE_POINT2(struct_size, offsets, coordinate_offsets, pi, + oo, array->nd, list1, list2, current_coordinates1, + current_coordinates2, block1, block2, + border_flag_value, true, false, Float64, mklist); + default: + PyErr_SetString(PyExc_RuntimeError, "data type not supported"); + goto exit; + } + + ++current; + if (current == block1->size) { + block1 = NI_CoordinateListDeleteBlock(list1); + if (block1) { + current_coordinates1 = block1->coordinates; + current = 0; + } + } else { + current_coordinates1 += array->nd; + } + } + + if (mask) { + NI_ITERATOR_RESET(ii) + NI_ITERATOR_RESET(mi) + pi = (void *)PyArray_DATA(array); + pm = (void *)PyArray_DATA(mask); + for(jj = 0; jj < size; jj++) { + int value = *(Int8*)pm; + if (value >= 0) + *(Bool*)pi = value; + NI_ITERATOR_NEXT2(ii, mi, pi, pm) + } + } + + exit: + if (offsets) + free(offsets); + if (coordinate_offsets) + free(coordinate_offsets); + NI_FreeCoordinateList(list1); + NI_FreeCoordinateList(list2); + if (PyErr_Occurred()) { + return 0; + } else { + return 1; + } + return PyErr_Occurred() ? 0 : 1; +} + + +#define NI_DISTANCE_EUCLIDIAN 1 +#define NI_DISTANCE_CITY_BLOCK 2 +#define NI_DISTANCE_CHESSBOARD 3 + +typedef struct { + maybelong *coordinates; + maybelong index; + void *next; +} NI_BorderElement; + +int NI_DistanceTransformBruteForce(PyArrayObject* input, int metric, + PyArrayObject *sampling_arr, + PyArrayObject* distances, + PyArrayObject* features) +{ + maybelong size, jj, min_index = 0; + int kk; + NI_BorderElement *border_elements = NULL, *temp; + NI_Iterator ii, di, fi; + char *pi, *pd = NULL, *pf = NULL; + Float64 *sampling = sampling_arr ? (void *)PyArray_DATA(sampling_arr) : NULL; + + /* check the output arrays: */ + if (distances) { + pd = (void *)PyArray_DATA(distances); + if (!NI_InitPointIterator(distances, &di)) + goto exit; + } + + if (features) { + pf = (void *)PyArray_DATA(features); + if (!NI_InitPointIterator(features, &fi)) + goto exit; + } + + size = 1; + for(kk = 0; kk < input->nd; kk++) + size *= input->dimensions[kk]; + pi = (void *)PyArray_DATA(input); + + if (!NI_InitPointIterator(input, &ii)) + goto exit; + + for(jj = 0; jj < size; jj++) { + if (*(Int8*)pi < 0) { + temp = (NI_BorderElement*)malloc(sizeof(NI_BorderElement)); + if (!temp) { + PyErr_NoMemory(); + goto exit; + } + temp->next = border_elements; + border_elements = temp; + temp->index = jj; + temp->coordinates = (maybelong*)malloc(input->nd * sizeof(maybelong)); + for(kk = 0; kk < input->nd; kk++) + temp->coordinates[kk] = ii.coordinates[kk]; + } + NI_ITERATOR_NEXT(ii, pi); + } + + NI_ITERATOR_RESET(ii); + pi = (void *)PyArray_DATA(input); + + switch(metric) { + case NI_DISTANCE_EUCLIDIAN: + for(jj = 0; jj < size; jj++) { + if (*(Int8*)pi > 0) { + double distance = DBL_MAX; + temp = border_elements; + while(temp) { + double d = 0.0, t; + for(kk = 0; kk < input->nd; kk++) { + t = ii.coordinates[kk] - temp->coordinates[kk]; + if (sampling) + t *= sampling[kk]; + d += t * t; + } + if (d < distance) { + distance = d; + if (features) + min_index = temp->index; + } + temp = temp->next; + } + if (distances) + *(Float64*)pd = sqrt(distance); + if (features) + *(Int32*)pf = min_index; + } else { + if (distances) + *(Float64*)pd = 0.0; + if (features) + *(Int32*)pf = jj; + } + if (features && distances) { + NI_ITERATOR_NEXT3(ii, di, fi, pi, pd, pf); + } else if (distances) { + NI_ITERATOR_NEXT2(ii, di, pi, pd); + } else { + NI_ITERATOR_NEXT2(ii, fi, pi, pf); + } + } + break; + case NI_DISTANCE_CITY_BLOCK: + case NI_DISTANCE_CHESSBOARD: + for(jj = 0; jj < size; jj++) { + if (*(Int8*)pi > 0) { + unsigned long distance = ULONG_MAX; + temp = border_elements; + while(temp) { + unsigned int d = 0; + maybelong t; + for(kk = 0; kk < input->nd; kk++) { + t = ii.coordinates[kk] - temp->coordinates[kk]; + if (t < 0) + t = -t; + if (metric == NI_DISTANCE_CITY_BLOCK) { + d += t; + } else { + if ((unsigned int)t > d) + d = t; + } + } + if (d < distance) { + distance = d; + if (features) + min_index = temp->index; + } + temp = temp->next; + } + if (distances) + *(UInt32*)pd = distance; + if (features) + *(Int32*)pf = min_index; + } else { + if (distances) + *(UInt32*)pd = 0; + if (features) + *(Int32*)pf = jj; + } + if (features && distances) { + NI_ITERATOR_NEXT3(ii, di, fi, pi, pd, pf); + } else if (distances) { + NI_ITERATOR_NEXT2(ii, di, pi, pd); + } else { + NI_ITERATOR_NEXT2(ii, fi, pi, pf); + } + } + break; + default: + PyErr_SetString(PyExc_RuntimeError, "distance metric not supported"); + goto exit; + } + + exit: + while (border_elements) { + temp = border_elements; + border_elements = border_elements->next; + if (temp->coordinates) + free(temp->coordinates); + free(temp); + } + return PyErr_Occurred() ? 0 : 1; +} + + +int NI_DistanceTransformOnePass(PyArrayObject *strct, + PyArrayObject* distances, PyArrayObject *features) +{ + int kk; + maybelong jj, ii, ssize, size, filter_size, mask_value, *oo; + maybelong *foffsets = NULL, *foo = NULL, *offsets = NULL; + Bool *ps, *pf = NULL, *footprint = NULL; + char *pd; + NI_FilterIterator si, ti; + NI_Iterator di, fi; + + ssize = 1; + for(kk = 0; kk < strct->nd; kk++) + ssize *= strct->dimensions[kk]; + + /* we only use the first half of the structure data, so we make a + temporary structure for use with the filter functions: */ + footprint = (Bool*)malloc(ssize * sizeof(Bool)); + if (!footprint) { + PyErr_NoMemory(); + goto exit; + } + ps = (Bool*)PyArray_DATA(strct); + filter_size = 0; + for(jj = 0; jj < ssize / 2; jj++) { + footprint[jj] = ps[jj]; + if (ps[jj]) + ++filter_size; + } + for(jj = ssize / 2; jj < ssize; jj++) + footprint[jj] = 0; + /* get data and size */ + pd = (void *)PyArray_DATA(distances); + size = 1; + for(kk = 0; kk < distances->nd; kk++) + size *= distances->dimensions[kk]; + if (!NI_InitPointIterator(distances, &di)) + goto exit; + /* calculate the filter offsets: */ + if (!NI_InitFilterOffsets(distances, footprint, strct->dimensions, NULL, + NI_EXTEND_CONSTANT, &offsets, &mask_value, NULL)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(distances->nd, strct->dimensions, + filter_size, distances->dimensions, NULL, &si)) + goto exit; + + if (features) { + maybelong dummy; + /* initialize point iterator: */ + pf = (void *)PyArray_DATA(features); + if (!NI_InitPointIterator(features, &fi)) + goto exit; + /* calculate the filter offsets: */ + if (!NI_InitFilterOffsets(features, footprint, strct->dimensions, + NULL, NI_EXTEND_CONSTANT, &foffsets, &dummy, NULL)) + goto exit; + /* initialize filter iterator: */ + if (!NI_InitFilterIterator(distances->nd, strct->dimensions, + filter_size, distances->dimensions, NULL, &ti)) + goto exit; + } + /* iterator over the elements: */ + oo = offsets; + if (features) + foo = foffsets; + for(jj = 0; jj < size; jj++) { + Int32 value = *(Int32*)pd; + if (value != 0) { + Int32 min = value; + maybelong min_offset = 0; + /* iterate over structuring element: */ + for(ii = 0; ii < filter_size; ii++) { + maybelong offset = oo[ii]; + Int32 tt = -1; + if (offset < mask_value) + tt = *(Int32*)(pd + offset); + if (tt >= 0) { + if ((min < 0) || (tt + 1 < min)) { + min = tt + 1; + if (features) + min_offset = foo[ii]; + } + } + } + *(Int32*)pd = min; + if (features) + *(Int32*)pf = *(Int32*)(pf + min_offset); + } + if (features) { + NI_FILTER_NEXT(ti, fi, foo, pf); + } + NI_FILTER_NEXT(si, di, oo, pd); + } + + exit: + if (offsets) free(offsets); + if (foffsets) free(foffsets); + if (footprint) + free(footprint); + return PyErr_Occurred() ? 0 : 1; +} + +static void _VoronoiFT(char *pf, maybelong len, maybelong *coor, int rank, + int d, maybelong stride, maybelong cstride, + maybelong **f, maybelong *g, Float64 *sampling) +{ + maybelong l = -1, ii, maxl, idx1, idx2; + int jj; + + for(ii = 0; ii < len; ii++) + for(jj = 0; jj < rank; jj++) + f[ii][jj] = *(Int32*)(pf + ii * stride + cstride * jj); + for(ii = 0; ii < len; ii++) { + if (*(Int32*)(pf + ii * stride) >= 0) { + double fd = f[ii][d]; + double wR = 0.0; + for(jj = 0; jj < rank; jj++) { + if (jj != d) { + double tw = f[ii][jj] - coor[jj]; + if (sampling) + tw *= sampling[jj]; + wR += tw * tw; + } + } + while(l >= 1) { + double a, b, c, uR = 0.0, vR = 0.0, f1; + idx1 = g[l]; + f1 = f[idx1][d]; + idx2 = g[l - 1]; + a = f1 - f[idx2][d]; + b = fd - f1; + if (sampling) { + a *= sampling[d]; + b *= sampling[d]; + } + c = a + b; + for(jj = 0; jj < rank; jj++) { + if (jj != d) { + double cc = coor[jj]; + double tu = f[idx2][jj] - cc; + double tv = f[idx1][jj] - cc; + if (sampling) { + tu *= sampling[jj]; + tv *= sampling[jj]; + } + uR += tu * tu; + vR += tv * tv; + } + } + if (c * vR - b * uR - a * wR - a * b * c <= 0.0) + break; + --l; + } + ++l; + g[l] = ii; + } + } + maxl = l; + if (maxl >= 0) { + l = 0; + for (ii = 0; ii < len; ii++) { + double delta1 = 0.0, t; + for(jj = 0; jj < rank; jj++) { + t = jj == d ? f[g[l]][jj] - ii : f[g[l]][jj] - coor[jj]; + if (sampling) + t *= sampling[jj]; + delta1 += t * t; + } + while (l < maxl) { + double delta2 = 0.0; + for(jj = 0; jj < rank; jj++) { + t = jj == d ? f[g[l + 1]][jj] - ii : f[g[l + 1]][jj] - coor[jj]; + if (sampling) + t *= sampling[jj]; + delta2 += t * t; + } + if (delta1 <= delta2) + break; + delta1 = delta2; + ++l; + } + idx1 = g[l]; + for(jj = 0; jj < rank; jj++) + *(Int32*)(pf + ii * stride + jj * cstride) = f[idx1][jj]; + } + } +} + + +/* Recursive feature transform */ +static void _ComputeFT(char *pi, char *pf, maybelong *ishape, + maybelong *istrides, maybelong *fstrides, int rank, + int d, maybelong *coor, maybelong **f, maybelong *g, + PyArrayObject *features, Float64 *sampling) +{ + int kk; + maybelong jj; + + if (d == 0) { + char *tf1 = pf; + for(jj = 0; jj < ishape[0]; jj++) { + if (*(Int8*)pi) { + *(Int32*)tf1 = -1; + } else { + char *tf2 = tf1; + *(Int32*)tf2 = jj; + for(kk = 1; kk < rank; kk++) { + tf2 += fstrides[0]; + *(Int32*)tf2 = coor[kk]; + } + } + pi += istrides[0]; + tf1 += fstrides[1]; + } + _VoronoiFT(pf, ishape[0], coor, rank, 0, fstrides[1], fstrides[0], f, + g, sampling); + } else { + UInt32 axes = 0; + char *tf = pf; + maybelong size = 1; + NI_Iterator ii; + + for(jj = 0; jj < ishape[d]; jj++) { + coor[d] = jj; + _ComputeFT(pi, tf, ishape, istrides, fstrides, rank, d - 1, coor, f, + g, features, sampling); + pi += istrides[d]; + tf += fstrides[d + 1]; + } + + for(jj = 0; jj < d; jj++) { + axes |= (UInt32)1 << (jj + 1); + size *= ishape[jj]; + } + NI_InitPointIterator(features, &ii); + NI_SubspaceIterator(&ii, axes); + tf = pf; + for(jj = 0; jj < size; jj++) { + for(kk = 0; kk < d; kk++) + coor[kk] = ii.coordinates[kk]; + _VoronoiFT(tf, ishape[d], coor, rank, d, fstrides[d + 1], + fstrides[0], f, g, sampling); + NI_ITERATOR_NEXT(ii, tf); + } + for(kk = 0; kk < d; kk++) + coor[kk] = 0; + } +} + +/* Exact euclidean feature transform, as described in: C. R. Maurer, + Jr., R. Qi, V. Raghavan, "A linear time algorithm for computing + exact euclidean distance transforms of binary images in arbitrary + dimensions. IEEE Trans. PAMI 25, 265-270, 2003. */ +int NI_EuclideanFeatureTransform(PyArrayObject* input, + PyArrayObject *sampling_arr, + PyArrayObject* features) +{ + int ii; + maybelong coor[NI_MAXDIM], mx = 0, jj; + maybelong *tmp = NULL, **f = NULL, *g = NULL; + char *pi, *pf; + Float64 *sampling = sampling_arr ? ((void *)PyArray_DATA(sampling_arr)) : NULL; + + pi = (void *)PyArray_DATA(input); + pf = (void *)PyArray_DATA(features); + for(ii = 0; ii < input->nd; ii++) { + coor[ii] = 0; + if (input->dimensions[ii] > mx) + mx = input->dimensions[ii]; + } + + /* Some temporaries */ + f = (maybelong**)malloc(mx * sizeof(maybelong*)); + g = (maybelong*)malloc(mx * sizeof(maybelong)); + tmp = (maybelong*)malloc(mx * input->nd * sizeof(maybelong)); + if (!f || !g || !tmp) { + PyErr_NoMemory(); + goto exit; + } + for(jj = 0; jj < mx; jj++) + f[jj] = tmp + jj * input->nd; + + /* First call of recursive feature transform */ + _ComputeFT(pi, pf, input->dimensions, input->strides, features->strides, + input->nd, input->nd - 1, coor, f, g, features, sampling); + + exit: + if (f) + free(f); + if (g) + free(g); + if (tmp) + free(tmp); + + return PyErr_Occurred() ? 0 : 1; +} Modified: trunk/scipy/ndimage/src/ni_morphology.h =================================================================== --- trunk/scipy/ndimage/src/ni_morphology.h 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/ni_morphology.h 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,46 +1,46 @@ -/* Copyright (C) 2003-2005 Peter J. Verveer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef NI_MORPHOLOGY_H -#define NI_MORPHOLOGY_H - -int NI_BinaryErosion(PyArrayObject*, PyArrayObject*, PyArrayObject*, - PyArrayObject*, int, maybelong*, int, int, int*, NI_CoordinateList**); -int NI_BinaryErosion2(PyArrayObject*, PyArrayObject*, PyArrayObject*, - int, maybelong*, int, NI_CoordinateList**); -int NI_DistanceTransformBruteForce(PyArrayObject*, int, PyArrayObject*, - PyArrayObject*, PyArrayObject*); -int NI_DistanceTransformOnePass(PyArrayObject*, PyArrayObject *, - PyArrayObject*); -int NI_EuclideanFeatureTransform(PyArrayObject*, PyArrayObject*, - PyArrayObject*); - -#endif +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NI_MORPHOLOGY_H +#define NI_MORPHOLOGY_H + +int NI_BinaryErosion(PyArrayObject*, PyArrayObject*, PyArrayObject*, + PyArrayObject*, int, maybelong*, int, int, int*, NI_CoordinateList**); +int NI_BinaryErosion2(PyArrayObject*, PyArrayObject*, PyArrayObject*, + int, maybelong*, int, NI_CoordinateList**); +int NI_DistanceTransformBruteForce(PyArrayObject*, int, PyArrayObject*, + PyArrayObject*, PyArrayObject*); +int NI_DistanceTransformOnePass(PyArrayObject*, PyArrayObject *, + PyArrayObject*); +int NI_EuclideanFeatureTransform(PyArrayObject*, PyArrayObject*, + PyArrayObject*); + +#endif Modified: trunk/scipy/ndimage/src/ni_support.c =================================================================== --- trunk/scipy/ndimage/src/ni_support.c 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/ni_support.c 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,751 +1,751 @@ -/* Copyright (C) 2003-2005 Peter J. Verveer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ni_support.h" - -/* initialize iterations over single array elements: */ -int NI_InitPointIterator(PyArrayObject *array, NI_Iterator *iterator) -{ - int ii; - - iterator->rank_m1 = array->nd - 1; - for(ii = 0; ii < array->nd; ii++) { - /* adapt dimensions for use in the macros: */ - iterator->dimensions[ii] = array->dimensions[ii] - 1; - /* initialize coordinates: */ - iterator->coordinates[ii] = 0; - /* initialize strides: */ - iterator->strides[ii] = array->strides[ii]; - /* calculate the strides to move back at the end of an axis: */ - iterator->backstrides[ii] = - array->strides[ii] * iterator->dimensions[ii]; - } - return 1; -} - - -/* initialize iteration over a lower sub-space: */ -int NI_SubspaceIterator(NI_Iterator *iterator, UInt32 axes) -{ - int ii, last = 0; - - for(ii = 0; ii <= iterator->rank_m1; ii++) { - if (axes & (((UInt32)1) << ii)) { - if (last != ii) { - iterator->dimensions[last] = iterator->dimensions[ii]; - iterator->strides[last] = iterator->strides[ii]; - iterator->backstrides[last] = iterator->backstrides[ii]; - } - ++last; - } - } - iterator->rank_m1 = last - 1; - return 1; -} - -/* initialize iteration over array lines: */ -int NI_LineIterator(NI_Iterator *iterator, int axis) -{ - UInt32 axes = ((UInt32)1) << axis; - return NI_SubspaceIterator(iterator, ~axes); -} - - -/******************************************************************/ -/* Line buffers */ -/******************************************************************/ - -/* Allocate line buffer data */ -int NI_AllocateLineBuffer(PyArrayObject* array, int axis, maybelong size1, - maybelong size2, maybelong *lines, maybelong max_size, double **buffer) -{ - maybelong line_size, max_lines; - int ii; - - /* the number of lines of the array is an upper limit for the - number of lines in the buffer: */ - max_lines = 1; - for(ii = 0; ii < array->nd; ii++) - max_lines *= array->dimensions[ii]; - if (array->nd > 0 && array->dimensions[axis] > 0) - max_lines /= array->dimensions[axis]; - /* calculate the space needed for one line, including space to - support the boundary conditions: */ - line_size = sizeof(double) * (array->dimensions[axis] + size1 + size2); - /* if *lines < 1, no number of lines is proposed, so we calculate it - from the maximum size allowed: */ - if (*lines < 1) { - *lines = line_size > 0 ? max_size / line_size : 0; - if (*lines < 1) - *lines = 1; - } - /* no need to allocate too many lines: */ - if (*lines > max_lines) - *lines = max_lines; - /* allocate data for the buffer: */ - *buffer = (double*)malloc(*lines * line_size); - if (!*buffer) { - PyErr_NoMemory(); - return 0; - } - return 1; -} - -/* Initialize a line buffer */ -int NI_InitLineBuffer(PyArrayObject *array, int axis, maybelong size1, - maybelong size2, maybelong buffer_lines, double *buffer_data, - NI_ExtendMode extend_mode, double extend_value, NI_LineBuffer *buffer) -{ - maybelong line_length = 0, array_lines = 0, size; - int ii; - - size = 1; - for(ii = 0; ii < array->nd; ii++) - size *= array->dimensions[ii]; - /* check if the buffer is big enough: */ - if (size > 0 && buffer_lines < 1) { - PyErr_SetString(PyExc_RuntimeError, "buffer too small"); - return 0; - } - /* Initialize a line iterator to move over the array: */ - if (!NI_InitPointIterator(array, &(buffer->iterator))) - return 0; - if (!NI_LineIterator(&(buffer->iterator), axis)) - return 0; - line_length = array->nd > 0 ? array->dimensions[axis] : 1; - if (line_length > 0) - array_lines = line_length > 0 ? size / line_length : 1; - /* initialize the buffer structure: */ - buffer->array_data = (void *)PyArray_DATA(array); - buffer->buffer_data = buffer_data; - buffer->buffer_lines = buffer_lines; - buffer->array_type = array->descr->type_num; - buffer->array_lines = array_lines; - buffer->next_line = 0; - buffer->size1 = size1; - buffer->size2 = size2; - buffer->line_length = line_length; - buffer->line_stride = array->nd > 0 ? array->strides[axis] : 0; - buffer->extend_mode = extend_mode; - buffer->extend_value = extend_value; - return 1; -} - -/* Extend a line in memory to implement boundary conditions: */ -int NI_ExtendLine(double *line, maybelong length, maybelong size1, - maybelong size2, NI_ExtendMode mode, double constant_value) -{ - maybelong ii, jj, length1, nextend, rextend; - double *l1, *l2, *l3, val; - - switch (mode) { - case NI_EXTEND_WRAP: - nextend = size1 / length; - rextend = size1 - nextend * length; - l1 = line + size1 + length - rextend; - l2 = line; - for(ii = 0; ii < rextend; ii++) - *l2++ = *l1++; - for(ii = 0; ii < nextend; ii++) { - l1 = line + size1; - for(jj = 0; jj < length; jj++) - *l2++ = *l1++; - } - nextend = size2 / length; - rextend = size2 - nextend * length; - l1 = line + size1; - l2 = line + size1 + length; - for(ii = 0; ii < nextend; ii++) { - l3 = l1; - for(jj = 0; jj < length; jj++) - *l2++ = *l3++; - } - for(ii = 0; ii < rextend; ii++) - *l2++ = *l1++; - break; - case NI_EXTEND_MIRROR: - if (length == 1) { - l1 = line; - val = line[size1]; - for(ii = 0; ii < size1; ii++) - *l1++ = val; - l1 = line + size1 + length; - val = line[size1 + length - 1]; - for(ii = 0; ii < size2; ii++) - *l1++ = val; - } else { - length1 = length - 1; - nextend = size1 / length1; - rextend = size1 - nextend * length1; - l1 = line + size1 + 1; - l2 = l1 - 2; - for(ii = 0; ii < nextend; ii++) { - l3 = l1; - for(jj = 0; jj < length1; jj++) - *l2-- = *l3++; - l1 -= length1; - } - for(ii = 0; ii < rextend; ii++) - *l2-- = *l1++; - nextend = size2 / length1; - rextend = size2 - nextend * length1; - l1 = line + size1 + length1 - 1; - l2 = l1 + 2; - for(ii = 0; ii < nextend; ii++) { - l3 = l1; - for(jj = 0; jj < length1; jj++) - *l2++ = *l3--; - l1 += length1; - } - for(ii = 0; ii < rextend; ii++) - *l2++ = *l1--; - } - break; - case NI_EXTEND_REFLECT: - nextend = size1 / length; - rextend = size1 - nextend * length; - l1 = line + size1; - l2 = l1 - 1; - for(ii = 0; ii < nextend; ii++) { - l3 = l1; - for(jj = 0; jj < length; jj++) - *l2-- = *l3++; - l1 -= length; - } - l3 = l1; - for(ii = 0; ii < rextend; ii++) - *l2-- = *l3++; - nextend = size2 / length; - rextend = size2 - nextend * length; - l1 = line + size1 + length - 1; - l2 = l1 + 1; - for(ii = 0; ii < nextend; ii++) { - l3 = l1; - for(jj = 0; jj < length; jj++) - *l2++ = *l3--; - l1 += length; - } - for(ii = 0; ii < rextend; ii++) - *l2++ = *l1--; - break; - case NI_EXTEND_NEAREST: - l1 = line; - val = line[size1]; - for(ii = 0; ii < size1; ii++) - *l1++ = val; - l1 = line + size1 + length; - val = line[size1 + length - 1]; - for(ii = 0; ii < size2; ii++) - *l1++ = val; - break; - case NI_EXTEND_CONSTANT: - l1 = line; - for(ii = 0; ii < size1; ii++) - *l1++ = constant_value; - l1 = line + size1 + length; - for(ii = 0; ii < size2; ii++) - *l1++ = constant_value; - break; - default: - PyErr_SetString(PyExc_RuntimeError, "mode not supported"); - return 0; - } - return 1; -} - - -#define CASE_COPY_DATA_TO_LINE(_pi, _po, _length, _stride, _type) \ -case t ## _type: \ -{ \ - maybelong _ii; \ - for(_ii = 0; _ii < _length; _ii++) { \ - _po[_ii] = (double)*(_type*)_pi; \ - _pi += _stride; \ - } \ -} \ -break - - -/* Copy a line from an array to a buffer: */ -int NI_ArrayToLineBuffer(NI_LineBuffer *buffer, - maybelong *number_of_lines, int *more) -{ - double *pb = buffer->buffer_data; - char *pa; - maybelong length = buffer->line_length; - - pb += buffer->size1; - *number_of_lines = 0; - /* fill until all lines in the array have been processed, or until - the buffer is full: */ - while (buffer->next_line < buffer->array_lines && - *number_of_lines < buffer->buffer_lines) { - pa = buffer->array_data; - /* copy the data from the array to the buffer: */ - switch (buffer->array_type) { - CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Bool); - CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, UInt8); - CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, UInt16); - CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, UInt32); -#if HAS_UINT64 - CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, UInt64); -#endif - CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Int8); - CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Int16); - CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Int32); - CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Int64); - CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Float32); - CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Float64); - default: - PyErr_Format(PyExc_RuntimeError, "array type %d not supported", buffer->array_type); - return 0; - } - /* goto next line in the array: */ - NI_ITERATOR_NEXT(buffer->iterator, buffer->array_data); - /* implement boundary conditions to the line: */ - if (buffer->size1 + buffer->size2 > 0) - if (!NI_ExtendLine(pb - buffer->size1, length, buffer->size1, - buffer->size2, buffer->extend_mode, - buffer->extend_value)) - return 0; - /* The number of the array lines copied: */ - ++(buffer->next_line); - /* keep track of (and return) the number of lines in the buffer: */ - ++(*number_of_lines); - pb += buffer->line_length + buffer->size1 + buffer->size2; - } - /* if not all array lines were processed, *more is set true: */ - *more = buffer->next_line < buffer->array_lines; - return 1; -} - -#define CASE_COPY_LINE_TO_DATA(_pi, _po, _length, _stride, _type) \ -case t ## _type: \ -{ \ - maybelong _ii; \ - for(_ii = 0; _ii < _length; _ii++) { \ - *(_type*)_po = (_type)_pi[_ii]; \ - _po += _stride; \ - } \ -} \ -break - -/* Copy a line from a buffer to an array: */ -int NI_LineBufferToArray(NI_LineBuffer *buffer) -{ - double *pb = buffer->buffer_data; - char *pa; - maybelong jj, length = buffer->line_length; - - pb += buffer->size1; - for(jj = 0; jj < buffer->buffer_lines; jj++) { - /* if all array lines are copied return: */ - if (buffer->next_line == buffer->array_lines) - break; - pa = buffer->array_data; - /* copy data from the buffer to the array: */ - switch (buffer->array_type) { - CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Bool); - CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, UInt8); - CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, UInt16); - CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, UInt32); -#if HAS_UINT64 - CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, UInt64); -#endif - CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Int8); - CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Int16); - CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Int32); - CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Int64); - CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Float32); - CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Float64); - default: - PyErr_SetString(PyExc_RuntimeError, "array type not supported"); - return 0; - } - /* move to the next line in the array: */ - NI_ITERATOR_NEXT(buffer->iterator, buffer->array_data); - /* number of lines copied: */ - ++(buffer->next_line); - /* move the buffer data pointer to the next line: */ - pb += buffer->line_length + buffer->size1 + buffer->size2; - } - return 1; -} - -/******************************************************************/ -/* Multi-dimensional filter support functions */ -/******************************************************************/ - -/* Initialize a filter iterator: */ -int -NI_InitFilterIterator(int rank, maybelong *filter_shape, - maybelong filter_size, maybelong *array_shape, - maybelong *origins, NI_FilterIterator *iterator) -{ - int ii; - maybelong fshape[MAXDIM], forigins[MAXDIM]; - - for(ii = 0; ii < rank; ii++) { - fshape[ii] = *filter_shape++; - forigins[ii] = origins ? *origins++ : 0; - } - /* calculate the strides, used to move the offsets pointer through - the offsets table: */ - if (rank > 0) { - iterator->strides[rank - 1] = filter_size; - for(ii = rank - 2; ii >= 0; ii--) { - maybelong step = array_shape[ii + 1] < fshape[ii + 1] ? - array_shape[ii + 1] : fshape[ii + 1]; - iterator->strides[ii] = iterator->strides[ii + 1] * step; - } - } - for(ii = 0; ii < rank; ii++) { - maybelong step = array_shape[ii] < fshape[ii] ? - array_shape[ii] : fshape[ii]; - maybelong orgn = fshape[ii] / 2 + forigins[ii]; - /* stride for stepping back to previous offsets: */ - iterator->backstrides[ii] = (step - 1) * iterator->strides[ii]; - /* initialize boundary extension sizes: */ - iterator->bound1[ii] = orgn; - iterator->bound2[ii] = array_shape[ii] - fshape[ii] + orgn; - } - return 1; -} - -/* Calculate the offsets to the filter points, for all border regions and - the interior of the array: */ -int NI_InitFilterOffsets(PyArrayObject *array, Bool *footprint, - maybelong *filter_shape, maybelong* origins, - NI_ExtendMode mode, maybelong **offsets, maybelong *border_flag_value, - maybelong **coordinate_offsets) -{ - int rank, ii; - maybelong kk, ll, filter_size = 1, offsets_size = 1, max_size = 0; - maybelong max_stride = 0, *ashape = NULL, *astrides = NULL; - maybelong footprint_size = 0, coordinates[MAXDIM], position[MAXDIM]; - maybelong fshape[MAXDIM], forigins[MAXDIM], *po, *pc = NULL; - - rank = array->nd; - ashape = array->dimensions; - astrides = array->strides; - for(ii = 0; ii < rank; ii++) { - fshape[ii] = *filter_shape++; - forigins[ii] = origins ? *origins++ : 0.0; - } - /* the size of the footprint array: */ - for(ii = 0; ii < rank; ii++) - filter_size *= fshape[ii]; - /* calculate the number of non-zero elements in the footprint: */ - if (footprint) { - for(kk = 0; kk < filter_size; kk++) - if (footprint[kk]) - ++footprint_size; - } else { - footprint_size = filter_size; - } - /* calculate how many sets of offsets must be stored: */ - for(ii = 0; ii < rank; ii++) - offsets_size *= (ashape[ii] < fshape[ii] ? ashape[ii] : fshape[ii]); - /* allocate offsets data: */ - *offsets = (maybelong*)malloc(offsets_size * footprint_size * - sizeof(maybelong)); - if (!*offsets) { - PyErr_NoMemory(); - goto exit; - } - if (coordinate_offsets) { - *coordinate_offsets = (maybelong*)malloc(offsets_size * rank * - footprint_size * sizeof(maybelong)); - if (!*coordinate_offsets) { - PyErr_NoMemory(); - goto exit; - } - } - for(ii = 0; ii < rank; ii++) { - maybelong stride; - /* find maximum axis size: */ - if (ashape[ii] > max_size) - max_size = ashape[ii]; - /* find maximum stride: */ - stride = astrides[ii] < 0 ? -astrides[ii] : astrides[ii]; - if (stride > max_stride) - max_stride = stride; - /* coordinates for iterating over the kernel elements: */ - coordinates[ii] = 0; - /* keep track of the kernel position: */ - position[ii] = 0; - } - /* the flag to indicate that we are outside the border must have a - value that is larger than any possible offset: */ - *border_flag_value = max_size * max_stride + 1; - /* calculate all possible offsets to elements in the filter kernel, - for all regions in the array (interior and border regions): */ - po = *offsets; - if (coordinate_offsets) { - pc = *coordinate_offsets; - } - /* iterate over all regions: */ - for(ll = 0; ll < offsets_size; ll++) { - /* iterate over the elements in the footprint array: */ - for(kk = 0; kk < filter_size; kk++) { - maybelong offset = 0; - /* only calculate an offset if the footprint is 1: */ - if (!footprint || footprint[kk]) { - /* find offsets along all axes: */ - for(ii = 0; ii < rank; ii++) { - maybelong orgn = fshape[ii] / 2 + forigins[ii]; - maybelong cc = coordinates[ii] - orgn + position[ii]; - maybelong len = ashape[ii]; - /* apply boundary conditions, if necessary: */ - switch (mode) { - case NI_EXTEND_MIRROR: - if (cc < 0) { - if (len <= 1) { - cc = 0; - } else { - int sz2 = 2 * len - 2; - cc = sz2 * (int)(-cc / sz2) + cc; - cc = cc <= 1 - len ? cc + sz2 : -cc; - } - } else if (cc >= len) { - if (len <= 1) { - cc = 0; - } else { - int sz2 = 2 * len - 2; - cc -= sz2 * (int)(cc / sz2); - if (cc >= len) - cc = sz2 - cc; - } - } - break; - case NI_EXTEND_REFLECT: - if (cc < 0) { - if (len <= 1) { - cc = 0; - } else { - int sz2 = 2 * len; - if (cc < -sz2) - cc = sz2 * (int)(-cc / sz2) + cc; - cc = cc < -len ? cc + sz2 : -cc - 1; - } - } else if (cc >= len) { - if (len <= 1) {cc = 0; - } else { - int sz2 = 2 * len; - cc -= sz2 * (int)(cc / sz2); - if (cc >= len) - cc = sz2 - cc - 1; - } - } - break; - case NI_EXTEND_WRAP: - if (cc < 0) { - if (len <= 1) { - cc = 0; - } else { - int sz = len; - cc += sz * (int)(-cc / sz); - if (cc < 0) - cc += sz; - } - } else if (cc >= len) { - if (len <= 1) { - cc = 0; - } else { - int sz = len; - cc -= sz * (int)(cc / sz); - } - } - break; - case NI_EXTEND_NEAREST: - if (cc < 0) { - cc = 0; - } else if (cc >= len) { - cc = len - 1; - } - break; - case NI_EXTEND_CONSTANT: - if (cc < 0 || cc >= len) - cc = *border_flag_value; - break; - default: - PyErr_SetString(PyExc_RuntimeError, - "boundary mode not supported"); - goto exit; - } - - /* calculate offset along current axis: */ - if (cc == *border_flag_value) { - /* just flag that we are outside the border */ - offset = *border_flag_value; - if (coordinate_offsets) - pc[ii] = 0; - break; - } else { - /* use an offset that is possibly mapped from outside the - border: */ - cc = cc - position[ii]; - offset += astrides[ii] * cc; - if (coordinate_offsets) - pc[ii] = cc; - } - } - /* store the offset */ - *po++ = offset; - if (coordinate_offsets) - pc += rank; - } - /* next point in the filter: */ - for(ii = rank - 1; ii >= 0; ii--) { - if (coordinates[ii] < fshape[ii] - 1) { - coordinates[ii]++; - break; - } else { - coordinates[ii] = 0; - } - } - } - - /* move to the next array region: */ - for(ii = rank - 1; ii >= 0; ii--) { - int orgn = fshape[ii] / 2 + forigins[ii]; - if (position[ii] == orgn) { - position[ii] += ashape[ii] - fshape[ii] + 1; - if (position[ii] <= orgn) - position[ii] = orgn + 1; - } else { - position[ii]++; - } - if (position[ii] < ashape[ii]) { - break; - } else { - position[ii] = 0; - } - } - } - - exit: - if (PyErr_Occurred()) { - if (*offsets) - free(*offsets); - if (coordinate_offsets && *coordinate_offsets) - free(*coordinate_offsets); - return 0; - } else { - return 1; - } -} - -NI_CoordinateList* NI_InitCoordinateList(int size, int rank) -{ - NI_CoordinateList *list = \ - (NI_CoordinateList*)malloc(sizeof(NI_CoordinateList)); - if (!list) { - PyErr_NoMemory(); - return NULL; - } - list->block_size = size; - list->rank = rank; - list->blocks = NULL; - return list; -} - -int NI_CoordinateListStealBlocks(NI_CoordinateList *list1, - NI_CoordinateList *list2) -{ - if (list1->block_size != list2->block_size || - list1->rank != list2->rank) { - PyErr_SetString(PyExc_RuntimeError, "coordinate lists not compatible"); - return 1; - } - if (list1->blocks) { - PyErr_SetString(PyExc_RuntimeError, "first is list not empty"); - return 1; - } - list1->blocks = list2->blocks; - list2->blocks = NULL; - return 0; -} - -NI_CoordinateBlock* NI_CoordinateListAddBlock(NI_CoordinateList *list) -{ - NI_CoordinateBlock* block = NULL; - block = (NI_CoordinateBlock*)malloc(sizeof(NI_CoordinateBlock)); - if (!block) { - PyErr_NoMemory(); - goto exit; - } - block->coordinates = (maybelong*)malloc(list->block_size * list->rank * - sizeof(maybelong)); - if (!block->coordinates) { - PyErr_NoMemory(); - goto exit; - } - block->next = list->blocks; - list->blocks = block; - block->size = 0; - -exit: - if (PyErr_Occurred()) { - if (block) - free(block); - return NULL; - } - return block; -} - -NI_CoordinateBlock* NI_CoordinateListDeleteBlock(NI_CoordinateList *list) -{ - NI_CoordinateBlock* block = list->blocks; - if (block) { - list->blocks = block->next; - if (block->coordinates) - free(block->coordinates); - free(block); - } - return list->blocks; -} - -void NI_FreeCoordinateList(NI_CoordinateList *list) -{ - if (list) { - NI_CoordinateBlock *block = list->blocks; - while (block) { - NI_CoordinateBlock *tmp = block; - block = block->next; - if (tmp->coordinates) - free(tmp->coordinates); - free(tmp); - } - list->blocks = NULL; - free(list); - } -} +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ni_support.h" + +/* initialize iterations over single array elements: */ +int NI_InitPointIterator(PyArrayObject *array, NI_Iterator *iterator) +{ + int ii; + + iterator->rank_m1 = array->nd - 1; + for(ii = 0; ii < array->nd; ii++) { + /* adapt dimensions for use in the macros: */ + iterator->dimensions[ii] = array->dimensions[ii] - 1; + /* initialize coordinates: */ + iterator->coordinates[ii] = 0; + /* initialize strides: */ + iterator->strides[ii] = array->strides[ii]; + /* calculate the strides to move back at the end of an axis: */ + iterator->backstrides[ii] = + array->strides[ii] * iterator->dimensions[ii]; + } + return 1; +} + + +/* initialize iteration over a lower sub-space: */ +int NI_SubspaceIterator(NI_Iterator *iterator, UInt32 axes) +{ + int ii, last = 0; + + for(ii = 0; ii <= iterator->rank_m1; ii++) { + if (axes & (((UInt32)1) << ii)) { + if (last != ii) { + iterator->dimensions[last] = iterator->dimensions[ii]; + iterator->strides[last] = iterator->strides[ii]; + iterator->backstrides[last] = iterator->backstrides[ii]; + } + ++last; + } + } + iterator->rank_m1 = last - 1; + return 1; +} + +/* initialize iteration over array lines: */ +int NI_LineIterator(NI_Iterator *iterator, int axis) +{ + UInt32 axes = ((UInt32)1) << axis; + return NI_SubspaceIterator(iterator, ~axes); +} + + +/******************************************************************/ +/* Line buffers */ +/******************************************************************/ + +/* Allocate line buffer data */ +int NI_AllocateLineBuffer(PyArrayObject* array, int axis, maybelong size1, + maybelong size2, maybelong *lines, maybelong max_size, double **buffer) +{ + maybelong line_size, max_lines; + int ii; + + /* the number of lines of the array is an upper limit for the + number of lines in the buffer: */ + max_lines = 1; + for(ii = 0; ii < array->nd; ii++) + max_lines *= array->dimensions[ii]; + if (array->nd > 0 && array->dimensions[axis] > 0) + max_lines /= array->dimensions[axis]; + /* calculate the space needed for one line, including space to + support the boundary conditions: */ + line_size = sizeof(double) * (array->dimensions[axis] + size1 + size2); + /* if *lines < 1, no number of lines is proposed, so we calculate it + from the maximum size allowed: */ + if (*lines < 1) { + *lines = line_size > 0 ? max_size / line_size : 0; + if (*lines < 1) + *lines = 1; + } + /* no need to allocate too many lines: */ + if (*lines > max_lines) + *lines = max_lines; + /* allocate data for the buffer: */ + *buffer = (double*)malloc(*lines * line_size); + if (!*buffer) { + PyErr_NoMemory(); + return 0; + } + return 1; +} + +/* Initialize a line buffer */ +int NI_InitLineBuffer(PyArrayObject *array, int axis, maybelong size1, + maybelong size2, maybelong buffer_lines, double *buffer_data, + NI_ExtendMode extend_mode, double extend_value, NI_LineBuffer *buffer) +{ + maybelong line_length = 0, array_lines = 0, size; + int ii; + + size = 1; + for(ii = 0; ii < array->nd; ii++) + size *= array->dimensions[ii]; + /* check if the buffer is big enough: */ + if (size > 0 && buffer_lines < 1) { + PyErr_SetString(PyExc_RuntimeError, "buffer too small"); + return 0; + } + /* Initialize a line iterator to move over the array: */ + if (!NI_InitPointIterator(array, &(buffer->iterator))) + return 0; + if (!NI_LineIterator(&(buffer->iterator), axis)) + return 0; + line_length = array->nd > 0 ? array->dimensions[axis] : 1; + if (line_length > 0) + array_lines = line_length > 0 ? size / line_length : 1; + /* initialize the buffer structure: */ + buffer->array_data = (void *)PyArray_DATA(array); + buffer->buffer_data = buffer_data; + buffer->buffer_lines = buffer_lines; + buffer->array_type = array->descr->type_num; + buffer->array_lines = array_lines; + buffer->next_line = 0; + buffer->size1 = size1; + buffer->size2 = size2; + buffer->line_length = line_length; + buffer->line_stride = array->nd > 0 ? array->strides[axis] : 0; + buffer->extend_mode = extend_mode; + buffer->extend_value = extend_value; + return 1; +} + +/* Extend a line in memory to implement boundary conditions: */ +int NI_ExtendLine(double *line, maybelong length, maybelong size1, + maybelong size2, NI_ExtendMode mode, double constant_value) +{ + maybelong ii, jj, length1, nextend, rextend; + double *l1, *l2, *l3, val; + + switch (mode) { + case NI_EXTEND_WRAP: + nextend = size1 / length; + rextend = size1 - nextend * length; + l1 = line + size1 + length - rextend; + l2 = line; + for(ii = 0; ii < rextend; ii++) + *l2++ = *l1++; + for(ii = 0; ii < nextend; ii++) { + l1 = line + size1; + for(jj = 0; jj < length; jj++) + *l2++ = *l1++; + } + nextend = size2 / length; + rextend = size2 - nextend * length; + l1 = line + size1; + l2 = line + size1 + length; + for(ii = 0; ii < nextend; ii++) { + l3 = l1; + for(jj = 0; jj < length; jj++) + *l2++ = *l3++; + } + for(ii = 0; ii < rextend; ii++) + *l2++ = *l1++; + break; + case NI_EXTEND_MIRROR: + if (length == 1) { + l1 = line; + val = line[size1]; + for(ii = 0; ii < size1; ii++) + *l1++ = val; + l1 = line + size1 + length; + val = line[size1 + length - 1]; + for(ii = 0; ii < size2; ii++) + *l1++ = val; + } else { + length1 = length - 1; + nextend = size1 / length1; + rextend = size1 - nextend * length1; + l1 = line + size1 + 1; + l2 = l1 - 2; + for(ii = 0; ii < nextend; ii++) { + l3 = l1; + for(jj = 0; jj < length1; jj++) + *l2-- = *l3++; + l1 -= length1; + } + for(ii = 0; ii < rextend; ii++) + *l2-- = *l1++; + nextend = size2 / length1; + rextend = size2 - nextend * length1; + l1 = line + size1 + length1 - 1; + l2 = l1 + 2; + for(ii = 0; ii < nextend; ii++) { + l3 = l1; + for(jj = 0; jj < length1; jj++) + *l2++ = *l3--; + l1 += length1; + } + for(ii = 0; ii < rextend; ii++) + *l2++ = *l1--; + } + break; + case NI_EXTEND_REFLECT: + nextend = size1 / length; + rextend = size1 - nextend * length; + l1 = line + size1; + l2 = l1 - 1; + for(ii = 0; ii < nextend; ii++) { + l3 = l1; + for(jj = 0; jj < length; jj++) + *l2-- = *l3++; + l1 -= length; + } + l3 = l1; + for(ii = 0; ii < rextend; ii++) + *l2-- = *l3++; + nextend = size2 / length; + rextend = size2 - nextend * length; + l1 = line + size1 + length - 1; + l2 = l1 + 1; + for(ii = 0; ii < nextend; ii++) { + l3 = l1; + for(jj = 0; jj < length; jj++) + *l2++ = *l3--; + l1 += length; + } + for(ii = 0; ii < rextend; ii++) + *l2++ = *l1--; + break; + case NI_EXTEND_NEAREST: + l1 = line; + val = line[size1]; + for(ii = 0; ii < size1; ii++) + *l1++ = val; + l1 = line + size1 + length; + val = line[size1 + length - 1]; + for(ii = 0; ii < size2; ii++) + *l1++ = val; + break; + case NI_EXTEND_CONSTANT: + l1 = line; + for(ii = 0; ii < size1; ii++) + *l1++ = constant_value; + l1 = line + size1 + length; + for(ii = 0; ii < size2; ii++) + *l1++ = constant_value; + break; + default: + PyErr_SetString(PyExc_RuntimeError, "mode not supported"); + return 0; + } + return 1; +} + + +#define CASE_COPY_DATA_TO_LINE(_pi, _po, _length, _stride, _type) \ +case t ## _type: \ +{ \ + maybelong _ii; \ + for(_ii = 0; _ii < _length; _ii++) { \ + _po[_ii] = (double)*(_type*)_pi; \ + _pi += _stride; \ + } \ +} \ +break + + +/* Copy a line from an array to a buffer: */ +int NI_ArrayToLineBuffer(NI_LineBuffer *buffer, + maybelong *number_of_lines, int *more) +{ + double *pb = buffer->buffer_data; + char *pa; + maybelong length = buffer->line_length; + + pb += buffer->size1; + *number_of_lines = 0; + /* fill until all lines in the array have been processed, or until + the buffer is full: */ + while (buffer->next_line < buffer->array_lines && + *number_of_lines < buffer->buffer_lines) { + pa = buffer->array_data; + /* copy the data from the array to the buffer: */ + switch (buffer->array_type) { + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Bool); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, UInt8); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, UInt16); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, UInt32); +#if HAS_UINT64 + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, UInt64); +#endif + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Int8); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Int16); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Int32); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Int64); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Float32); + CASE_COPY_DATA_TO_LINE(pa, pb, length, buffer->line_stride, Float64); + default: + PyErr_Format(PyExc_RuntimeError, "array type %d not supported", buffer->array_type); + return 0; + } + /* goto next line in the array: */ + NI_ITERATOR_NEXT(buffer->iterator, buffer->array_data); + /* implement boundary conditions to the line: */ + if (buffer->size1 + buffer->size2 > 0) + if (!NI_ExtendLine(pb - buffer->size1, length, buffer->size1, + buffer->size2, buffer->extend_mode, + buffer->extend_value)) + return 0; + /* The number of the array lines copied: */ + ++(buffer->next_line); + /* keep track of (and return) the number of lines in the buffer: */ + ++(*number_of_lines); + pb += buffer->line_length + buffer->size1 + buffer->size2; + } + /* if not all array lines were processed, *more is set true: */ + *more = buffer->next_line < buffer->array_lines; + return 1; +} + +#define CASE_COPY_LINE_TO_DATA(_pi, _po, _length, _stride, _type) \ +case t ## _type: \ +{ \ + maybelong _ii; \ + for(_ii = 0; _ii < _length; _ii++) { \ + *(_type*)_po = (_type)_pi[_ii]; \ + _po += _stride; \ + } \ +} \ +break + +/* Copy a line from a buffer to an array: */ +int NI_LineBufferToArray(NI_LineBuffer *buffer) +{ + double *pb = buffer->buffer_data; + char *pa; + maybelong jj, length = buffer->line_length; + + pb += buffer->size1; + for(jj = 0; jj < buffer->buffer_lines; jj++) { + /* if all array lines are copied return: */ + if (buffer->next_line == buffer->array_lines) + break; + pa = buffer->array_data; + /* copy data from the buffer to the array: */ + switch (buffer->array_type) { + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Bool); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, UInt8); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, UInt16); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, UInt32); +#if HAS_UINT64 + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, UInt64); +#endif + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Int8); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Int16); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Int32); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Int64); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Float32); + CASE_COPY_LINE_TO_DATA(pb, pa, length, buffer->line_stride, Float64); + default: + PyErr_SetString(PyExc_RuntimeError, "array type not supported"); + return 0; + } + /* move to the next line in the array: */ + NI_ITERATOR_NEXT(buffer->iterator, buffer->array_data); + /* number of lines copied: */ + ++(buffer->next_line); + /* move the buffer data pointer to the next line: */ + pb += buffer->line_length + buffer->size1 + buffer->size2; + } + return 1; +} + +/******************************************************************/ +/* Multi-dimensional filter support functions */ +/******************************************************************/ + +/* Initialize a filter iterator: */ +int +NI_InitFilterIterator(int rank, maybelong *filter_shape, + maybelong filter_size, maybelong *array_shape, + maybelong *origins, NI_FilterIterator *iterator) +{ + int ii; + maybelong fshape[MAXDIM], forigins[MAXDIM]; + + for(ii = 0; ii < rank; ii++) { + fshape[ii] = *filter_shape++; + forigins[ii] = origins ? *origins++ : 0; + } + /* calculate the strides, used to move the offsets pointer through + the offsets table: */ + if (rank > 0) { + iterator->strides[rank - 1] = filter_size; + for(ii = rank - 2; ii >= 0; ii--) { + maybelong step = array_shape[ii + 1] < fshape[ii + 1] ? + array_shape[ii + 1] : fshape[ii + 1]; + iterator->strides[ii] = iterator->strides[ii + 1] * step; + } + } + for(ii = 0; ii < rank; ii++) { + maybelong step = array_shape[ii] < fshape[ii] ? + array_shape[ii] : fshape[ii]; + maybelong orgn = fshape[ii] / 2 + forigins[ii]; + /* stride for stepping back to previous offsets: */ + iterator->backstrides[ii] = (step - 1) * iterator->strides[ii]; + /* initialize boundary extension sizes: */ + iterator->bound1[ii] = orgn; + iterator->bound2[ii] = array_shape[ii] - fshape[ii] + orgn; + } + return 1; +} + +/* Calculate the offsets to the filter points, for all border regions and + the interior of the array: */ +int NI_InitFilterOffsets(PyArrayObject *array, Bool *footprint, + maybelong *filter_shape, maybelong* origins, + NI_ExtendMode mode, maybelong **offsets, maybelong *border_flag_value, + maybelong **coordinate_offsets) +{ + int rank, ii; + maybelong kk, ll, filter_size = 1, offsets_size = 1, max_size = 0; + maybelong max_stride = 0, *ashape = NULL, *astrides = NULL; + maybelong footprint_size = 0, coordinates[MAXDIM], position[MAXDIM]; + maybelong fshape[MAXDIM], forigins[MAXDIM], *po, *pc = NULL; + + rank = array->nd; + ashape = array->dimensions; + astrides = array->strides; + for(ii = 0; ii < rank; ii++) { + fshape[ii] = *filter_shape++; + forigins[ii] = origins ? *origins++ : 0.0; + } + /* the size of the footprint array: */ + for(ii = 0; ii < rank; ii++) + filter_size *= fshape[ii]; + /* calculate the number of non-zero elements in the footprint: */ + if (footprint) { + for(kk = 0; kk < filter_size; kk++) + if (footprint[kk]) + ++footprint_size; + } else { + footprint_size = filter_size; + } + /* calculate how many sets of offsets must be stored: */ + for(ii = 0; ii < rank; ii++) + offsets_size *= (ashape[ii] < fshape[ii] ? ashape[ii] : fshape[ii]); + /* allocate offsets data: */ + *offsets = (maybelong*)malloc(offsets_size * footprint_size * + sizeof(maybelong)); + if (!*offsets) { + PyErr_NoMemory(); + goto exit; + } + if (coordinate_offsets) { + *coordinate_offsets = (maybelong*)malloc(offsets_size * rank * + footprint_size * sizeof(maybelong)); + if (!*coordinate_offsets) { + PyErr_NoMemory(); + goto exit; + } + } + for(ii = 0; ii < rank; ii++) { + maybelong stride; + /* find maximum axis size: */ + if (ashape[ii] > max_size) + max_size = ashape[ii]; + /* find maximum stride: */ + stride = astrides[ii] < 0 ? -astrides[ii] : astrides[ii]; + if (stride > max_stride) + max_stride = stride; + /* coordinates for iterating over the kernel elements: */ + coordinates[ii] = 0; + /* keep track of the kernel position: */ + position[ii] = 0; + } + /* the flag to indicate that we are outside the border must have a + value that is larger than any possible offset: */ + *border_flag_value = max_size * max_stride + 1; + /* calculate all possible offsets to elements in the filter kernel, + for all regions in the array (interior and border regions): */ + po = *offsets; + if (coordinate_offsets) { + pc = *coordinate_offsets; + } + /* iterate over all regions: */ + for(ll = 0; ll < offsets_size; ll++) { + /* iterate over the elements in the footprint array: */ + for(kk = 0; kk < filter_size; kk++) { + maybelong offset = 0; + /* only calculate an offset if the footprint is 1: */ + if (!footprint || footprint[kk]) { + /* find offsets along all axes: */ + for(ii = 0; ii < rank; ii++) { + maybelong orgn = fshape[ii] / 2 + forigins[ii]; + maybelong cc = coordinates[ii] - orgn + position[ii]; + maybelong len = ashape[ii]; + /* apply boundary conditions, if necessary: */ + switch (mode) { + case NI_EXTEND_MIRROR: + if (cc < 0) { + if (len <= 1) { + cc = 0; + } else { + int sz2 = 2 * len - 2; + cc = sz2 * (int)(-cc / sz2) + cc; + cc = cc <= 1 - len ? cc + sz2 : -cc; + } + } else if (cc >= len) { + if (len <= 1) { + cc = 0; + } else { + int sz2 = 2 * len - 2; + cc -= sz2 * (int)(cc / sz2); + if (cc >= len) + cc = sz2 - cc; + } + } + break; + case NI_EXTEND_REFLECT: + if (cc < 0) { + if (len <= 1) { + cc = 0; + } else { + int sz2 = 2 * len; + if (cc < -sz2) + cc = sz2 * (int)(-cc / sz2) + cc; + cc = cc < -len ? cc + sz2 : -cc - 1; + } + } else if (cc >= len) { + if (len <= 1) {cc = 0; + } else { + int sz2 = 2 * len; + cc -= sz2 * (int)(cc / sz2); + if (cc >= len) + cc = sz2 - cc - 1; + } + } + break; + case NI_EXTEND_WRAP: + if (cc < 0) { + if (len <= 1) { + cc = 0; + } else { + int sz = len; + cc += sz * (int)(-cc / sz); + if (cc < 0) + cc += sz; + } + } else if (cc >= len) { + if (len <= 1) { + cc = 0; + } else { + int sz = len; + cc -= sz * (int)(cc / sz); + } + } + break; + case NI_EXTEND_NEAREST: + if (cc < 0) { + cc = 0; + } else if (cc >= len) { + cc = len - 1; + } + break; + case NI_EXTEND_CONSTANT: + if (cc < 0 || cc >= len) + cc = *border_flag_value; + break; + default: + PyErr_SetString(PyExc_RuntimeError, + "boundary mode not supported"); + goto exit; + } + + /* calculate offset along current axis: */ + if (cc == *border_flag_value) { + /* just flag that we are outside the border */ + offset = *border_flag_value; + if (coordinate_offsets) + pc[ii] = 0; + break; + } else { + /* use an offset that is possibly mapped from outside the + border: */ + cc = cc - position[ii]; + offset += astrides[ii] * cc; + if (coordinate_offsets) + pc[ii] = cc; + } + } + /* store the offset */ + *po++ = offset; + if (coordinate_offsets) + pc += rank; + } + /* next point in the filter: */ + for(ii = rank - 1; ii >= 0; ii--) { + if (coordinates[ii] < fshape[ii] - 1) { + coordinates[ii]++; + break; + } else { + coordinates[ii] = 0; + } + } + } + + /* move to the next array region: */ + for(ii = rank - 1; ii >= 0; ii--) { + int orgn = fshape[ii] / 2 + forigins[ii]; + if (position[ii] == orgn) { + position[ii] += ashape[ii] - fshape[ii] + 1; + if (position[ii] <= orgn) + position[ii] = orgn + 1; + } else { + position[ii]++; + } + if (position[ii] < ashape[ii]) { + break; + } else { + position[ii] = 0; + } + } + } + + exit: + if (PyErr_Occurred()) { + if (*offsets) + free(*offsets); + if (coordinate_offsets && *coordinate_offsets) + free(*coordinate_offsets); + return 0; + } else { + return 1; + } +} + +NI_CoordinateList* NI_InitCoordinateList(int size, int rank) +{ + NI_CoordinateList *list = \ + (NI_CoordinateList*)malloc(sizeof(NI_CoordinateList)); + if (!list) { + PyErr_NoMemory(); + return NULL; + } + list->block_size = size; + list->rank = rank; + list->blocks = NULL; + return list; +} + +int NI_CoordinateListStealBlocks(NI_CoordinateList *list1, + NI_CoordinateList *list2) +{ + if (list1->block_size != list2->block_size || + list1->rank != list2->rank) { + PyErr_SetString(PyExc_RuntimeError, "coordinate lists not compatible"); + return 1; + } + if (list1->blocks) { + PyErr_SetString(PyExc_RuntimeError, "first is list not empty"); + return 1; + } + list1->blocks = list2->blocks; + list2->blocks = NULL; + return 0; +} + +NI_CoordinateBlock* NI_CoordinateListAddBlock(NI_CoordinateList *list) +{ + NI_CoordinateBlock* block = NULL; + block = (NI_CoordinateBlock*)malloc(sizeof(NI_CoordinateBlock)); + if (!block) { + PyErr_NoMemory(); + goto exit; + } + block->coordinates = (maybelong*)malloc(list->block_size * list->rank * + sizeof(maybelong)); + if (!block->coordinates) { + PyErr_NoMemory(); + goto exit; + } + block->next = list->blocks; + list->blocks = block; + block->size = 0; + +exit: + if (PyErr_Occurred()) { + if (block) + free(block); + return NULL; + } + return block; +} + +NI_CoordinateBlock* NI_CoordinateListDeleteBlock(NI_CoordinateList *list) +{ + NI_CoordinateBlock* block = list->blocks; + if (block) { + list->blocks = block->next; + if (block->coordinates) + free(block->coordinates); + free(block); + } + return list->blocks; +} + +void NI_FreeCoordinateList(NI_CoordinateList *list) +{ + if (list) { + NI_CoordinateBlock *block = list->blocks; + while (block) { + NI_CoordinateBlock *tmp = block; + block = block->next; + if (tmp->coordinates) + free(tmp->coordinates); + free(tmp); + } + list->blocks = NULL; + free(list); + } +} Modified: trunk/scipy/ndimage/src/ni_support.h =================================================================== --- trunk/scipy/ndimage/src/ni_support.h 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/ni_support.h 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,323 +1,323 @@ -/* Copyright (C) 2003-2005 Peter J. Verveer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef NI_SUPPORT_H -#define NI_SUPPORT_H - -#include "nd_image.h" -#include -#include -#include -#include - -/* The different boundary conditions. The mirror condition is not used - by the python code, but C code is kept around in case we might wish - to add it. */ -typedef enum { - NI_EXTEND_FIRST = 0, - NI_EXTEND_NEAREST = 0, - NI_EXTEND_WRAP = 1, - NI_EXTEND_REFLECT = 2, - NI_EXTEND_MIRROR = 3, - NI_EXTEND_CONSTANT = 4, - NI_EXTEND_LAST = NI_EXTEND_CONSTANT, - NI_EXTEND_DEFAULT = NI_EXTEND_MIRROR -} NI_ExtendMode; - -/******************************************************************/ -/* Iterators */ -/******************************************************************/ - -/******************************************************************/ -/* Iterators */ -/******************************************************************/ - -/* the iterator structure: */ -typedef struct { - int rank_m1; - maybelong dimensions[MAXDIM]; - maybelong coordinates[MAXDIM]; - maybelong strides[MAXDIM]; - maybelong backstrides[MAXDIM]; -} NI_Iterator; - -/* initialize iterations over single array elements: */ -int NI_InitPointIterator(PyArrayObject*, NI_Iterator*); - -/* initialize iterations over an arbritrary sub-space: */ -int NI_SubspaceIterator(NI_Iterator*, UInt32); - -/* initialize iteration over array lines: */ -int NI_LineIterator(NI_Iterator*, int); - -/* reset an iterator */ -#define NI_ITERATOR_RESET(iterator) \ -{ \ - int _ii; \ - for(_ii = 0; _ii <= (iterator).rank_m1; _ii++) \ - (iterator).coordinates[_ii] = 0; \ -} - -/* go to the next point in a single array */ -#define NI_ITERATOR_NEXT(iterator, pointer) \ -{ \ - int _ii; \ - for(_ii = (iterator).rank_m1; _ii >= 0; _ii--) \ - if ((iterator).coordinates[_ii] < (iterator).dimensions[_ii]) { \ - (iterator).coordinates[_ii]++; \ - pointer += (iterator).strides[_ii]; \ - break; \ - } else { \ - (iterator).coordinates[_ii] = 0; \ - pointer -= (iterator).backstrides[_ii]; \ - } \ -} - -/* go to the next point in two arrays of the same size */ -#define NI_ITERATOR_NEXT2(iterator1, iterator2, pointer1, pointer2) \ -{ \ - int _ii; \ - for(_ii = (iterator1).rank_m1; _ii >= 0; _ii--) \ - if ((iterator1).coordinates[_ii] < (iterator1).dimensions[_ii]) { \ - (iterator1).coordinates[_ii]++; \ - pointer1 += (iterator1).strides[_ii]; \ - pointer2 += (iterator2).strides[_ii]; \ - break; \ - } else { \ - (iterator1).coordinates[_ii] = 0; \ - pointer1 -= (iterator1).backstrides[_ii]; \ - pointer2 -= (iterator2).backstrides[_ii]; \ - } \ -} - -/* go to the next point in three arrays of the same size */ -#define NI_ITERATOR_NEXT3(iterator1, iterator2, iterator3, \ - pointer1, pointer2, pointer3) \ -{ \ - int _ii; \ - for(_ii = (iterator1).rank_m1; _ii >= 0; _ii--) \ - if ((iterator1).coordinates[_ii] < (iterator1).dimensions[_ii]) { \ - (iterator1).coordinates[_ii]++; \ - pointer1 += (iterator1).strides[_ii]; \ - pointer2 += (iterator2).strides[_ii]; \ - pointer3 += (iterator3).strides[_ii]; \ - break; \ - } else { \ - (iterator1).coordinates[_ii] = 0; \ - pointer1 -= (iterator1).backstrides[_ii]; \ - pointer2 -= (iterator2).backstrides[_ii]; \ - pointer3 -= (iterator3).backstrides[_ii]; \ - } \ -} - -/* go to an arbitrary point in a single array */ -#define NI_ITERATOR_GOTO(iterator, destination, base, pointer) \ -{ \ - int _ii; \ - pointer = base; \ - for(_ii = (iterator).rank_m1; _ii >= 0; _ii--) { \ - pointer += destination[_ii] * (iterator).strides[_ii]; \ - (iterator).coordinates[_ii] = destination[_ii]; \ - } \ -} - -/******************************************************************/ -/* Line buffers */ -/******************************************************************/ - -/* the linebuffer structure: */ -typedef struct { - double *buffer_data; - maybelong buffer_lines, line_length, line_stride; - maybelong size1, size2, array_lines, next_line; - NI_Iterator iterator; - char* array_data; - NumarrayType array_type; - NI_ExtendMode extend_mode; - double extend_value; -} NI_LineBuffer; - -/* Get the next line being processed: */ -#define NI_GET_LINE(_buffer, _line) \ - ((_buffer).buffer_data + (_line) * ((_buffer).line_length + \ - (_buffer).size1 + (_buffer).size2)) -/* Allocate line buffer data */ -int NI_AllocateLineBuffer(PyArrayObject*, int, maybelong, maybelong, - maybelong*, maybelong, double**); - -/* Initialize a line buffer */ -int NI_InitLineBuffer(PyArrayObject*, int, maybelong, maybelong, maybelong, - double*, NI_ExtendMode, double, NI_LineBuffer*); - -/* Extend a line in memory to implement boundary conditions: */ -int NI_ExtendLine(double*, maybelong, maybelong, maybelong, NI_ExtendMode, double); - -/* Copy a line from an array to a buffer: */ -int NI_ArrayToLineBuffer(NI_LineBuffer*, maybelong*, int*); - -/* Copy a line from a buffer to an array: */ -int NI_LineBufferToArray(NI_LineBuffer*); - -/******************************************************************/ -/* Multi-dimensional filter support functions */ -/******************************************************************/ - -/* the filter iterator structure: */ -typedef struct { - maybelong strides[MAXDIM], backstrides[MAXDIM]; - maybelong bound1[MAXDIM], bound2[MAXDIM]; -} NI_FilterIterator; - -/* Initialize a filter iterator: */ -int NI_InitFilterIterator(int, maybelong*, maybelong, maybelong*, - maybelong*, NI_FilterIterator*); - -/* Calculate the offsets to the filter points, for all border regions and - the interior of the array: */ -int NI_InitFilterOffsets(PyArrayObject*, Bool*, maybelong*, - maybelong*, NI_ExtendMode, maybelong**, maybelong*, maybelong**); - -/* Move to the next point in an array, possible changing the filter - offsets, to adapt to boundary conditions: */ -#define NI_FILTER_NEXT(iteratorf, iterator1, pointerf, pointer1) \ -{ \ - int _ii; \ - for(_ii = (iterator1).rank_m1; _ii >= 0; _ii--) { \ - maybelong _pp = (iterator1).coordinates[_ii]; \ - if (_pp < (iterator1).dimensions[_ii]) { \ - if (_pp < (iteratorf).bound1[_ii] || \ - _pp >= (iteratorf).bound2[_ii]) \ - pointerf += (iteratorf).strides[_ii]; \ - (iterator1).coordinates[_ii]++; \ - pointer1 += (iterator1).strides[_ii]; \ - break; \ - } else { \ - (iterator1).coordinates[_ii] = 0; \ - pointer1 -= (iterator1).backstrides[_ii]; \ - pointerf -= (iteratorf).backstrides[_ii]; \ - } \ - } \ -} - -/* Move to the next point in two arrays, possible changing the pointer - to the filter offsets when moving into a different region in the - array: */ -#define NI_FILTER_NEXT2(iteratorf, iterator1, iterator2, \ - pointerf, pointer1, pointer2) \ -{ \ - int _ii; \ - for(_ii = (iterator1).rank_m1; _ii >= 0; _ii--) { \ - maybelong _pp = (iterator1).coordinates[_ii]; \ - if (_pp < (iterator1).dimensions[_ii]) { \ - if (_pp < (iteratorf).bound1[_ii] || \ - _pp >= (iteratorf).bound2[_ii]) \ - pointerf += (iteratorf).strides[_ii]; \ - (iterator1).coordinates[_ii]++; \ - pointer1 += (iterator1).strides[_ii]; \ - pointer2 += (iterator2).strides[_ii]; \ - break; \ - } else { \ - (iterator1).coordinates[_ii] = 0; \ - pointer1 -= (iterator1).backstrides[_ii]; \ - pointer2 -= (iterator2).backstrides[_ii]; \ - pointerf -= (iteratorf).backstrides[_ii]; \ - } \ - } \ -} - -/* Move to the next point in three arrays, possible changing the pointer - to the filter offsets when moving into a different region in the - array: */ -#define NI_FILTER_NEXT3(iteratorf, iterator1, iterator2, iterator3, \ - pointerf, pointer1, pointer2, pointer3) \ -{ \ - int _ii; \ - for(_ii = (iterator1).rank_m1; _ii >= 0; _ii--) { \ - maybelong _pp = (iterator1).coordinates[_ii]; \ - if (_pp < (iterator1).dimensions[_ii]) { \ - if (_pp < (iteratorf).bound1[_ii] || \ - _pp >= (iteratorf).bound2[_ii]) \ - pointerf += (iteratorf).strides[_ii]; \ - (iterator1).coordinates[_ii]++; \ - pointer1 += (iterator1).strides[_ii]; \ - pointer2 += (iterator2).strides[_ii]; \ - pointer3 += (iterator3).strides[_ii]; \ - break; \ - } else { \ - (iterator1).coordinates[_ii] = 0; \ - pointer1 -= (iterator1).backstrides[_ii]; \ - pointer2 -= (iterator2).backstrides[_ii]; \ - pointer3 -= (iterator3).backstrides[_ii]; \ - pointerf -= (iteratorf).backstrides[_ii]; \ - } \ - } \ -} - -/* Move the pointer to the filter offsets according to the given - coordinates: */ -#define NI_FILTER_GOTO(iteratorf, iterator, fbase, pointerf) \ -{ \ - int _ii; \ - maybelong _jj; \ - pointerf = fbase; \ - for(_ii = iterator.rank_m1; _ii >= 0; _ii--) { \ - maybelong _pp = iterator.coordinates[_ii]; \ - maybelong b1 = (iteratorf).bound1[_ii]; \ - maybelong b2 = (iteratorf).bound2[_ii]; \ - if (_pp < b1) { \ - _jj = _pp; \ - } else if (_pp > b2 && b2 >= b1) { \ - _jj = _pp + b1 - b2; \ - } else { \ - _jj = b1; \ - } \ - pointerf += (iteratorf).strides[_ii] * _jj; \ - } \ -} - -typedef struct { - maybelong *coordinates; - int size; - void *next; -} NI_CoordinateBlock; - -typedef struct { - int block_size, rank; - void *blocks; -} NI_CoordinateList; - -NI_CoordinateList* NI_InitCoordinateList(int, int); -int NI_CoordinateListStealBlocks(NI_CoordinateList*, NI_CoordinateList*); -NI_CoordinateBlock* NI_CoordinateListAddBlock(NI_CoordinateList*); -NI_CoordinateBlock* NI_CoordinateListDeleteBlock(NI_CoordinateList*); -void NI_FreeCoordinateList(NI_CoordinateList*); - -#endif +/* Copyright (C) 2003-2005 Peter J. Verveer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NI_SUPPORT_H +#define NI_SUPPORT_H + +#include "nd_image.h" +#include +#include +#include +#include + +/* The different boundary conditions. The mirror condition is not used + by the python code, but C code is kept around in case we might wish + to add it. */ +typedef enum { + NI_EXTEND_FIRST = 0, + NI_EXTEND_NEAREST = 0, + NI_EXTEND_WRAP = 1, + NI_EXTEND_REFLECT = 2, + NI_EXTEND_MIRROR = 3, + NI_EXTEND_CONSTANT = 4, + NI_EXTEND_LAST = NI_EXTEND_CONSTANT, + NI_EXTEND_DEFAULT = NI_EXTEND_MIRROR +} NI_ExtendMode; + +/******************************************************************/ +/* Iterators */ +/******************************************************************/ + +/******************************************************************/ +/* Iterators */ +/******************************************************************/ + +/* the iterator structure: */ +typedef struct { + int rank_m1; + maybelong dimensions[MAXDIM]; + maybelong coordinates[MAXDIM]; + maybelong strides[MAXDIM]; + maybelong backstrides[MAXDIM]; +} NI_Iterator; + +/* initialize iterations over single array elements: */ +int NI_InitPointIterator(PyArrayObject*, NI_Iterator*); + +/* initialize iterations over an arbritrary sub-space: */ +int NI_SubspaceIterator(NI_Iterator*, UInt32); + +/* initialize iteration over array lines: */ +int NI_LineIterator(NI_Iterator*, int); + +/* reset an iterator */ +#define NI_ITERATOR_RESET(iterator) \ +{ \ + int _ii; \ + for(_ii = 0; _ii <= (iterator).rank_m1; _ii++) \ + (iterator).coordinates[_ii] = 0; \ +} + +/* go to the next point in a single array */ +#define NI_ITERATOR_NEXT(iterator, pointer) \ +{ \ + int _ii; \ + for(_ii = (iterator).rank_m1; _ii >= 0; _ii--) \ + if ((iterator).coordinates[_ii] < (iterator).dimensions[_ii]) { \ + (iterator).coordinates[_ii]++; \ + pointer += (iterator).strides[_ii]; \ + break; \ + } else { \ + (iterator).coordinates[_ii] = 0; \ + pointer -= (iterator).backstrides[_ii]; \ + } \ +} + +/* go to the next point in two arrays of the same size */ +#define NI_ITERATOR_NEXT2(iterator1, iterator2, pointer1, pointer2) \ +{ \ + int _ii; \ + for(_ii = (iterator1).rank_m1; _ii >= 0; _ii--) \ + if ((iterator1).coordinates[_ii] < (iterator1).dimensions[_ii]) { \ + (iterator1).coordinates[_ii]++; \ + pointer1 += (iterator1).strides[_ii]; \ + pointer2 += (iterator2).strides[_ii]; \ + break; \ + } else { \ + (iterator1).coordinates[_ii] = 0; \ + pointer1 -= (iterator1).backstrides[_ii]; \ + pointer2 -= (iterator2).backstrides[_ii]; \ + } \ +} + +/* go to the next point in three arrays of the same size */ +#define NI_ITERATOR_NEXT3(iterator1, iterator2, iterator3, \ + pointer1, pointer2, pointer3) \ +{ \ + int _ii; \ + for(_ii = (iterator1).rank_m1; _ii >= 0; _ii--) \ + if ((iterator1).coordinates[_ii] < (iterator1).dimensions[_ii]) { \ + (iterator1).coordinates[_ii]++; \ + pointer1 += (iterator1).strides[_ii]; \ + pointer2 += (iterator2).strides[_ii]; \ + pointer3 += (iterator3).strides[_ii]; \ + break; \ + } else { \ + (iterator1).coordinates[_ii] = 0; \ + pointer1 -= (iterator1).backstrides[_ii]; \ + pointer2 -= (iterator2).backstrides[_ii]; \ + pointer3 -= (iterator3).backstrides[_ii]; \ + } \ +} + +/* go to an arbitrary point in a single array */ +#define NI_ITERATOR_GOTO(iterator, destination, base, pointer) \ +{ \ + int _ii; \ + pointer = base; \ + for(_ii = (iterator).rank_m1; _ii >= 0; _ii--) { \ + pointer += destination[_ii] * (iterator).strides[_ii]; \ + (iterator).coordinates[_ii] = destination[_ii]; \ + } \ +} + +/******************************************************************/ +/* Line buffers */ +/******************************************************************/ + +/* the linebuffer structure: */ +typedef struct { + double *buffer_data; + maybelong buffer_lines, line_length, line_stride; + maybelong size1, size2, array_lines, next_line; + NI_Iterator iterator; + char* array_data; + NumarrayType array_type; + NI_ExtendMode extend_mode; + double extend_value; +} NI_LineBuffer; + +/* Get the next line being processed: */ +#define NI_GET_LINE(_buffer, _line) \ + ((_buffer).buffer_data + (_line) * ((_buffer).line_length + \ + (_buffer).size1 + (_buffer).size2)) +/* Allocate line buffer data */ +int NI_AllocateLineBuffer(PyArrayObject*, int, maybelong, maybelong, + maybelong*, maybelong, double**); + +/* Initialize a line buffer */ +int NI_InitLineBuffer(PyArrayObject*, int, maybelong, maybelong, maybelong, + double*, NI_ExtendMode, double, NI_LineBuffer*); + +/* Extend a line in memory to implement boundary conditions: */ +int NI_ExtendLine(double*, maybelong, maybelong, maybelong, NI_ExtendMode, double); + +/* Copy a line from an array to a buffer: */ +int NI_ArrayToLineBuffer(NI_LineBuffer*, maybelong*, int*); + +/* Copy a line from a buffer to an array: */ +int NI_LineBufferToArray(NI_LineBuffer*); + +/******************************************************************/ +/* Multi-dimensional filter support functions */ +/******************************************************************/ + +/* the filter iterator structure: */ +typedef struct { + maybelong strides[MAXDIM], backstrides[MAXDIM]; + maybelong bound1[MAXDIM], bound2[MAXDIM]; +} NI_FilterIterator; + +/* Initialize a filter iterator: */ +int NI_InitFilterIterator(int, maybelong*, maybelong, maybelong*, + maybelong*, NI_FilterIterator*); + +/* Calculate the offsets to the filter points, for all border regions and + the interior of the array: */ +int NI_InitFilterOffsets(PyArrayObject*, Bool*, maybelong*, + maybelong*, NI_ExtendMode, maybelong**, maybelong*, maybelong**); + +/* Move to the next point in an array, possible changing the filter + offsets, to adapt to boundary conditions: */ +#define NI_FILTER_NEXT(iteratorf, iterator1, pointerf, pointer1) \ +{ \ + int _ii; \ + for(_ii = (iterator1).rank_m1; _ii >= 0; _ii--) { \ + maybelong _pp = (iterator1).coordinates[_ii]; \ + if (_pp < (iterator1).dimensions[_ii]) { \ + if (_pp < (iteratorf).bound1[_ii] || \ + _pp >= (iteratorf).bound2[_ii]) \ + pointerf += (iteratorf).strides[_ii]; \ + (iterator1).coordinates[_ii]++; \ + pointer1 += (iterator1).strides[_ii]; \ + break; \ + } else { \ + (iterator1).coordinates[_ii] = 0; \ + pointer1 -= (iterator1).backstrides[_ii]; \ + pointerf -= (iteratorf).backstrides[_ii]; \ + } \ + } \ +} + +/* Move to the next point in two arrays, possible changing the pointer + to the filter offsets when moving into a different region in the + array: */ +#define NI_FILTER_NEXT2(iteratorf, iterator1, iterator2, \ + pointerf, pointer1, pointer2) \ +{ \ + int _ii; \ + for(_ii = (iterator1).rank_m1; _ii >= 0; _ii--) { \ + maybelong _pp = (iterator1).coordinates[_ii]; \ + if (_pp < (iterator1).dimensions[_ii]) { \ + if (_pp < (iteratorf).bound1[_ii] || \ + _pp >= (iteratorf).bound2[_ii]) \ + pointerf += (iteratorf).strides[_ii]; \ + (iterator1).coordinates[_ii]++; \ + pointer1 += (iterator1).strides[_ii]; \ + pointer2 += (iterator2).strides[_ii]; \ + break; \ + } else { \ + (iterator1).coordinates[_ii] = 0; \ + pointer1 -= (iterator1).backstrides[_ii]; \ + pointer2 -= (iterator2).backstrides[_ii]; \ + pointerf -= (iteratorf).backstrides[_ii]; \ + } \ + } \ +} + +/* Move to the next point in three arrays, possible changing the pointer + to the filter offsets when moving into a different region in the + array: */ +#define NI_FILTER_NEXT3(iteratorf, iterator1, iterator2, iterator3, \ + pointerf, pointer1, pointer2, pointer3) \ +{ \ + int _ii; \ + for(_ii = (iterator1).rank_m1; _ii >= 0; _ii--) { \ + maybelong _pp = (iterator1).coordinates[_ii]; \ + if (_pp < (iterator1).dimensions[_ii]) { \ + if (_pp < (iteratorf).bound1[_ii] || \ + _pp >= (iteratorf).bound2[_ii]) \ + pointerf += (iteratorf).strides[_ii]; \ + (iterator1).coordinates[_ii]++; \ + pointer1 += (iterator1).strides[_ii]; \ + pointer2 += (iterator2).strides[_ii]; \ + pointer3 += (iterator3).strides[_ii]; \ + break; \ + } else { \ + (iterator1).coordinates[_ii] = 0; \ + pointer1 -= (iterator1).backstrides[_ii]; \ + pointer2 -= (iterator2).backstrides[_ii]; \ + pointer3 -= (iterator3).backstrides[_ii]; \ + pointerf -= (iteratorf).backstrides[_ii]; \ + } \ + } \ +} + +/* Move the pointer to the filter offsets according to the given + coordinates: */ +#define NI_FILTER_GOTO(iteratorf, iterator, fbase, pointerf) \ +{ \ + int _ii; \ + maybelong _jj; \ + pointerf = fbase; \ + for(_ii = iterator.rank_m1; _ii >= 0; _ii--) { \ + maybelong _pp = iterator.coordinates[_ii]; \ + maybelong b1 = (iteratorf).bound1[_ii]; \ + maybelong b2 = (iteratorf).bound2[_ii]; \ + if (_pp < b1) { \ + _jj = _pp; \ + } else if (_pp > b2 && b2 >= b1) { \ + _jj = _pp + b1 - b2; \ + } else { \ + _jj = b1; \ + } \ + pointerf += (iteratorf).strides[_ii] * _jj; \ + } \ +} + +typedef struct { + maybelong *coordinates; + int size; + void *next; +} NI_CoordinateBlock; + +typedef struct { + int block_size, rank; + void *blocks; +} NI_CoordinateList; + +NI_CoordinateList* NI_InitCoordinateList(int, int); +int NI_CoordinateListStealBlocks(NI_CoordinateList*, NI_CoordinateList*); +NI_CoordinateBlock* NI_CoordinateListAddBlock(NI_CoordinateList*); +NI_CoordinateBlock* NI_CoordinateListDeleteBlock(NI_CoordinateList*); +void NI_FreeCoordinateList(NI_CoordinateList*); + +#endif Modified: trunk/scipy/ndimage/src/register/Register_EXT.c =================================================================== --- trunk/scipy/ndimage/src/register/Register_EXT.c 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/register/Register_EXT.c 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,753 +1,753 @@ -/* Python extension interface code */ - -#include "Python.h" -#include "numpy/arrayobject.h" - -static PyObject *Register_Histogram(PyObject *self, PyObject *args) -{ - /* - joint histogram memory is created in python to avoid memory leak problem - */ - - int num; - int numM; - int nd; - int type; - int itype; - int nd_histo; - int nd_rotmatrix; - int nd_S; - npy_intp *dimsF; - npy_intp *dimsG; - npy_intp *dims_histo; - npy_intp *dims_rotmatrix; - npy_intp *dims_S; - unsigned char *imageG; - unsigned char *imageF; - double *pHisto; - double *M; - int *S; - PyObject *imgArray1 = NULL; - PyObject *imgArray2 = NULL; - PyObject *rotArray = NULL; - PyObject *SArray = NULL; - PyObject *hArray = NULL; - - if(!PyArg_ParseTuple(args, "OOOOO", &imgArray1, &imgArray2, &rotArray, &SArray, &hArray)) - goto exit; - - /* check in the Python code that F and G are the same dims, type */ - imageF = (unsigned char *)PyArray_DATA(imgArray1); - imageG = (unsigned char *)PyArray_DATA(imgArray2); - nd = PyArray_NDIM(imgArray1); - /* reads dims as 0 = layers, 1 = rows, 2 = cols */ - dimsF = PyArray_DIMS(imgArray1); - dimsG = PyArray_DIMS(imgArray2); - type = PyArray_TYPE(imgArray1); - num = PyArray_SIZE(imgArray1); - - M = (double *)PyArray_DATA(rotArray); - nd_rotmatrix = PyArray_NDIM(rotArray); - dims_rotmatrix = PyArray_DIMS(rotArray); - numM = PyArray_SIZE(rotArray); - - S = (int *)PyArray_DATA(SArray); - nd_S = PyArray_NDIM(SArray); - dims_S = PyArray_DIMS(SArray); - - pHisto = (double *)PyArray_DATA(hArray); - nd_histo = PyArray_NDIM(hArray); - dims_histo = PyArray_DIMS(hArray); - /* check to make sure this is 256x256 */ - - if(!NI_Histogram2D((int)dimsF[0], (int)dimsF[1], (int)dimsF[2], - (int)dimsG[0], (int)dimsG[1], (int)dimsG[2], - S, M, imageG, imageF, pHisto)) - goto exit; - -exit: - - /* return the 2D histogram */ - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - - -static PyObject *Register_HistogramLite(PyObject *self, PyObject *args) -{ - /* - joint histogram memory is created in python to avoid memory leak problem - */ - - int num; - int numG; - int nd; - int type; - int itype; - int nd_histo; - int nd_rotmatrix; - int nd_S; - npy_intp *dimsF; - npy_intp *dimsG; - npy_intp *dims_histo; - npy_intp *dims_rotmatrix; - npy_intp *dims_S; - unsigned char *imageG; - unsigned char *imageF; - double *pHisto; - double *M; - int *S; - PyObject *imgArray1 = NULL; - PyObject *imgArray2 = NULL; - PyObject *rotArray = NULL; - PyObject *SArray = NULL; - PyObject *hArray = NULL; - - if(!PyArg_ParseTuple(args, "OOOOO", &imgArray1, &imgArray2, &rotArray, &SArray, &hArray)) - goto exit; - - /* check in the Python code that F and G are the same dims, type */ - imageF = (unsigned char *)PyArray_DATA(imgArray1); - imageG = (unsigned char *)PyArray_DATA(imgArray2); - /* reads dims as 0 = layers, 1 = rows, 2 = cols */ - nd = PyArray_NDIM(imgArray1); - dimsF = PyArray_DIMS(imgArray1); - dimsG = PyArray_DIMS(imgArray2); - type = PyArray_TYPE(imgArray1); - num = PyArray_SIZE(imgArray1); - numG = PyArray_SIZE(imgArray2); - - M = (double *)PyArray_DATA(rotArray); - nd_rotmatrix = PyArray_NDIM(rotArray); - dims_rotmatrix = PyArray_DIMS(rotArray); - - S = (int *)PyArray_DATA(SArray); - nd_S = PyArray_NDIM(SArray); - dims_S = PyArray_DIMS(SArray); - - pHisto = (double *)PyArray_DATA(hArray); - nd_histo = PyArray_NDIM(hArray); - dims_histo = PyArray_DIMS(hArray); - /* check to make sure this is 256x256 */ - - if(!NI_Histogram2DLite((int)dimsF[0], (int)dimsF[1], (int)dimsF[2], - (int)dimsG[0], (int)dimsG[1], (int)dimsG[2], - S, M, imageG, imageF, pHisto)) - goto exit; - -exit: - - /* return the 2D histogram */ - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - -static PyObject *Register_VolumeResample(PyObject *self, PyObject *args) -{ - - int num; - int nd; - int type; - int itype; - int mode; - int scale; - npy_intp *dimsF; - npy_intp *dimsG; - unsigned char *imageG; - unsigned char *imageF; - double *Z; - PyObject *imgArray1 = NULL; - PyObject *imgArray2 = NULL; - PyObject *coordZoom = NULL; - - if(!PyArg_ParseTuple(args, "OOOii", &imgArray1, &imgArray2, &coordZoom, &scale, &mode)) - goto exit; - - /* check in the Python code that F and G are the same dims, type */ - imageF = (unsigned char *)PyArray_DATA(imgArray1); - imageG = (unsigned char *)PyArray_DATA(imgArray2); - Z = (double *)PyArray_DATA(coordZoom); - /* reads dims as 0 = layers, 1 = rows, 2 = cols */ - nd = PyArray_NDIM(imgArray1); - dimsF = PyArray_DIMS(imgArray1); - dimsG = PyArray_DIMS(imgArray2); - type = PyArray_TYPE(imgArray1); - num = PyArray_SIZE(imgArray1); - - if(!NI_VolumeResample((int)dimsF[0], (int)dimsF[1], (int)dimsF[2], - (int)dimsG[0], (int)dimsG[1], (int)dimsG[2], - scale, mode, imageG, imageF, Z)) - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - - - -static PyObject *Register_CubicResample(PyObject *self, PyObject *args) -{ - - int num; - int nd; - int type; - int itype; - int nd_rotmatrix; - int nd_S; - npy_intp *dimsF; - npy_intp *dimsG; - npy_intp *dims_rotmatrix; - npy_intp *dims_S; - unsigned char *imageG; - unsigned char *imageF; - double *M; - int *S; - PyObject *imgArray1 = NULL; - PyObject *imgArray2 = NULL; - PyObject *rotArray = NULL; - PyObject *SArray = NULL; - - if(!PyArg_ParseTuple(args, "OOOO", &imgArray1, &imgArray2, &rotArray, &SArray)) - goto exit; - - /* check in the Python code that F and G are the same dims, type */ - imageF = (unsigned char *)PyArray_DATA(imgArray1); - imageG = (unsigned char *)PyArray_DATA(imgArray2); - /* reads dims as 0 = layers, 1 = rows, 2 = cols */ - nd = PyArray_NDIM(imgArray1); - dimsF = PyArray_DIMS(imgArray1); - dimsG = PyArray_DIMS(imgArray2); - type = PyArray_TYPE(imgArray1); - num = PyArray_SIZE(imgArray1); - - M = (double *)PyArray_DATA(rotArray); - nd_rotmatrix = PyArray_NDIM(rotArray); - dims_rotmatrix = PyArray_DIMS(rotArray); - - S = (int *)PyArray_DATA(SArray); - nd_S = PyArray_NDIM(SArray); - dims_S = PyArray_DIMS(SArray); - - if(!NI_CubicResample((int)dimsF[0], (int)dimsF[1], (int)dimsF[2], - (int)dimsG[0], (int)dimsG[1], (int)dimsG[2], - S, M, imageG, imageF)) - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - - -static PyObject *Register_LinearResample(PyObject *self, PyObject *args) -{ - - int num; - int nd; - int type; - int itype; - int nd_rotmatrix; - int nd_S; - npy_intp *dimsF; - npy_intp *dimsG; - npy_intp *dims_rotmatrix; - npy_intp *dims_S; - unsigned char *imageG; - unsigned char *imageF; - double *M; - int *S; - PyObject *imgArray1 = NULL; - PyObject *imgArray2 = NULL; - PyObject *rotArray = NULL; - PyObject *SArray = NULL; - - if(!PyArg_ParseTuple(args, "OOOO", &imgArray1, &imgArray2, &rotArray, &SArray)) - goto exit; - - /* check in the Python code that F and G are the same dims, type */ - imageF = (unsigned char *)PyArray_DATA(imgArray1); - imageG = (unsigned char *)PyArray_DATA(imgArray2); - /* reads dims as 0 = layers, 1 = rows, 2 = cols */ - nd = PyArray_NDIM(imgArray1); - dimsF = PyArray_DIMS(imgArray1); - dimsG = PyArray_DIMS(imgArray2); - type = PyArray_TYPE(imgArray1); - num = PyArray_SIZE(imgArray1); - - M = (double *)PyArray_DATA(rotArray); - nd_rotmatrix = PyArray_NDIM(rotArray); - dims_rotmatrix = PyArray_DIMS(rotArray); - - S = (int *)PyArray_DATA(SArray); - nd_S = PyArray_NDIM(SArray); - dims_S = PyArray_DIMS(SArray); - - if(!NI_LinearResample((int)dimsF[0], (int)dimsF[1], (int)dimsF[2], - (int)dimsG[0], (int)dimsG[1], (int)dimsG[2], - S, M, imageG, imageF)) - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - - -static PyObject *Register_ImageThreshold(PyObject *self, PyObject *args) -{ - - /* set threshold from the volume integrated histogram */ - int num; - int nd; - int type; - int itype; - int histogram_elements; - int tindex; - npy_intp *dimsImage; - npy_intp *dimsHistogram; - unsigned short *image; - double *H; - double *IH; - double threshold; - PyObject *imgArray = NULL; - PyObject *histogram = NULL; - PyObject *ihistogram = NULL; - - if(!PyArg_ParseTuple(args, "OOOd", &imgArray, &histogram, &ihistogram, &threshold)) - goto exit; - - image = (unsigned short *)PyArray_DATA(imgArray); - /* reads dims as 0 = layers, 1 = rows, 2 = cols */ - nd = PyArray_NDIM(imgArray); - dimsImage = PyArray_DIMS(imgArray); - type = PyArray_TYPE(imgArray); - num = PyArray_SIZE(imgArray); - - H = (double *)PyArray_DATA(histogram); - IH = (double *)PyArray_DATA(ihistogram); - histogram_elements = PyArray_SIZE(histogram); - - if(!NI_ImageThreshold((int)dimsImage[0], (int)dimsImage[1], (int)dimsImage[2], - image, H, IH, histogram_elements, threshold, &tindex)) - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("i", tindex); - -} - - -static PyObject *Register_ResampleWithGradient(PyObject *self, PyObject *args) -{ - - int num; - int nd; - int type; - int itype; - int nd_rotmatrix; - int nd_S; - npy_intp *dimsScale; - npy_intp *dimsOffset; - npy_intp *dimsS; - npy_intp *dimsD; - npy_intp *dims_rotmatrix; - npy_intp *dims_S; - unsigned char *imageS; - unsigned char *imageD; - double *M; - int *S; - double *scale; - int *offset; - double *gradientX; - double *gradientY; - double *gradientZ; - PyObject *imgArrayS = NULL; - PyObject *imgArrayD = NULL; - PyObject *rotArray = NULL; - PyObject *SArray = NULL; - PyObject *scaleArray = NULL; - PyObject *offsetArray = NULL; - PyObject *gradXArray = NULL; - PyObject *gradYArray = NULL; - PyObject *gradZArray = NULL; - - if(!PyArg_ParseTuple(args, "OOOOOOOOO", &imgArrayS, &imgArrayD, &rotArray, &SArray, &scaleArray, - &offsetArray, &gradXArray, &gradYArray, &gradZArray)) - goto exit; - - /* check in the Python code that S and D are the same dims, type */ - imageS = (unsigned char *)PyArray_DATA(imgArrayS); - imageD = (unsigned char *)PyArray_DATA(imgArrayD); - /* reads dims as 0 = layers, 1 = rows, 2 = cols */ - nd = PyArray_NDIM(imgArrayS); - dimsS = PyArray_DIMS(imgArrayS); - dimsD = PyArray_DIMS(imgArrayD); - type = PyArray_TYPE(imgArrayS); - num = PyArray_SIZE(imgArrayS); - - M = (double *)PyArray_DATA(rotArray); - nd_rotmatrix = PyArray_NDIM(rotArray); - dims_rotmatrix = PyArray_DIMS(rotArray); - - S = (int *)PyArray_DATA(SArray); - nd_S = PyArray_NDIM(SArray); - dims_S = PyArray_DIMS(SArray); - - scale = (double *)PyArray_DATA(scaleArray); - offset = (int *)PyArray_DATA(offsetArray); - dimsScale = PyArray_DIMS(scaleArray); - dimsOffset = PyArray_DIMS(offsetArray); - - gradientX = (double *)PyArray_DATA(gradXArray); - gradientY = (double *)PyArray_DATA(gradYArray); - gradientZ = (double *)PyArray_DATA(gradZArray); - - if(!NI_ResampleWithGradient((int)dimsS[0], (int)dimsS[1], (int)dimsS[2], - (int)dimsD[0], (int)dimsD[1], (int)dimsD[2], - S, M, imageD, imageS, scale, offset, gradientX, - gradientY, gradientZ)) - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - - -static PyObject *Register_Find_Mask(PyObject *self, PyObject *args) -{ - - int i; - int num; - int length; - double *X; - double *Y; - double *Z; - int *xLims; - int *yLims; - int *zLims; - int *mask; - PyObject *MArray = NULL; - PyObject *XArray = NULL; - PyObject *YArray = NULL; - PyObject *ZArray = NULL; - PyObject *XLimits = NULL; - PyObject *YLimits = NULL; - PyObject *ZLimits = NULL; - - if(!PyArg_ParseTuple(args, "OOOOOOO", &MArray, &XArray, &YArray, &ZArray, &XLimits, &YLimits, &ZLimits)) - goto exit; - - num = PyArray_SIZE(XArray); - X = (double *)PyArray_DATA(XArray); - Y = (double *)PyArray_DATA(YArray); - Z = (double *)PyArray_DATA(ZArray); - mask = (int *)PyArray_DATA(MArray); - xLims = (int *)PyArray_DATA(XLimits); - yLims = (int *)PyArray_DATA(YLimits); - zLims = (int *)PyArray_DATA(ZLimits); - - for(length = 0, i = 0; i < num; ++i){ - if( ((X[i] >= xLims[0]) && (X[i] <= xLims[1])) && - ((Y[i] >= yLims[0]) && (Y[i] <= yLims[1])) && - ((Z[i] >= zLims[0]) && (Z[i] <= zLims[1])) ){ - mask[length++] = i; - } - } - - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("i", length); - -} - - - -static PyObject *Register_Resample_Gradient_Coords(PyObject *self, PyObject *args) -{ - - int num; - int size; - int nd; - int type; - int itype; - int nd_S; - npy_intp *dimsScale; - npy_intp *dimsOffset; - npy_intp *dimsS; - npy_intp *dimsD; - npy_intp *dims_S; - npy_intp *dims_Coords; - unsigned char *imageS; - unsigned char *imageD; - double *X; - double *Y; - double *Z; - int *S; - double *scale; - int *offset; - double *gradientX; - double *gradientY; - double *gradientZ; - PyObject *imgArrayS = NULL; - PyObject *imgArrayD = NULL; - PyObject *SArray = NULL; - PyObject *scaleArray = NULL; - PyObject *offsetArray = NULL; - PyObject *gradXArray = NULL; - PyObject *gradYArray = NULL; - PyObject *gradZArray = NULL; - PyObject *coordXArray = NULL; - PyObject *coordYArray = NULL; - PyObject *coordZArray = NULL; - - if(!PyArg_ParseTuple(args, "OOOOOOOOOOO", &coordZArray, &coordYArray, &coordXArray, - &imgArrayS, &imgArrayD, &SArray, &scaleArray, &offsetArray, - &gradXArray, &gradYArray, &gradZArray)) - goto exit; - - /* check in the Python code that S and D are the same dims, type */ - imageS = (unsigned char *)PyArray_DATA(imgArrayS); - imageD = (unsigned char *)PyArray_DATA(imgArrayD); - /* reads dims as 0 = layers, 1 = rows, 2 = cols */ - nd = PyArray_NDIM(imgArrayS); - dimsS = PyArray_DIMS(imgArrayS); - dimsD = PyArray_DIMS(imgArrayD); - type = PyArray_TYPE(imgArrayS); - num = PyArray_SIZE(imgArrayS); - - S = (int *)PyArray_DATA(SArray); - nd_S = PyArray_NDIM(SArray); - dims_S = PyArray_DIMS(SArray); - - scale = (double *)PyArray_DATA(scaleArray); - offset = (int *)PyArray_DATA(offsetArray); - dimsScale = PyArray_DIMS(scaleArray); - dimsOffset = PyArray_DIMS(offsetArray); - - gradientX = (double *)PyArray_DATA(gradXArray); - gradientY = (double *)PyArray_DATA(gradYArray); - gradientZ = (double *)PyArray_DATA(gradZArray); - - X = (double *)PyArray_DATA(coordXArray); - Y = (double *)PyArray_DATA(coordYArray); - Z = (double *)PyArray_DATA(coordZArray); - - dims_Coords = PyArray_DIMS(coordXArray); - size = PyArray_SIZE(coordXArray); - - if(!NI_Resample_Gradient_Coords(size, (int)dimsS[0], (int)dimsS[1], (int)dimsS[2], (int)dimsD[0], - (int)dimsD[1], (int)dimsD[2], S, X, Y, Z, imageD, imageS, scale, - offset, gradientX, gradientY, gradientZ)) - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - - - -static PyObject *Register_Resample_Coords(PyObject *self, PyObject *args) -{ - - int num; - int size; - int nd; - int type; - int itype; - int nd_S; - npy_intp *dimsScale; - npy_intp *dimsOffset; - npy_intp *dimsS; - npy_intp *dimsD; - npy_intp *dims_S; - npy_intp *dims_Coords; - unsigned char *imageS; - unsigned char *imageD; - double *X; - double *Y; - double *Z; - int *S; - double *scale; - int *offset; - PyObject *imgArrayS = NULL; - PyObject *imgArrayD = NULL; - PyObject *SArray = NULL; - PyObject *scaleArray = NULL; - PyObject *offsetArray = NULL; - PyObject *coordXArray = NULL; - PyObject *coordYArray = NULL; - PyObject *coordZArray = NULL; - - if(!PyArg_ParseTuple(args, "OOOOOOOO", &coordZArray, &coordYArray, &coordXArray, - &imgArrayS, &imgArrayD, &SArray, &scaleArray, &offsetArray)) - goto exit; - - /* check in the Python code that S and D are the same dims, type */ - imageS = (unsigned char *)PyArray_DATA(imgArrayS); - imageD = (unsigned char *)PyArray_DATA(imgArrayD); - /* reads dims as 0 = layers, 1 = rows, 2 = cols */ - nd = PyArray_NDIM(imgArrayS); - dimsS = PyArray_DIMS(imgArrayS); - dimsD = PyArray_DIMS(imgArrayD); - type = PyArray_TYPE(imgArrayS); - num = PyArray_SIZE(imgArrayS); - - S = (int *)PyArray_DATA(SArray); - nd_S = PyArray_NDIM(SArray); - dims_S = PyArray_DIMS(SArray); - - scale = (double *)PyArray_DATA(scaleArray); - offset = (int *)PyArray_DATA(offsetArray); - dimsScale = PyArray_DIMS(scaleArray); - dimsOffset = PyArray_DIMS(offsetArray); - - X = (double *)PyArray_DATA(coordXArray); - Y = (double *)PyArray_DATA(coordYArray); - Z = (double *)PyArray_DATA(coordZArray); - - dims_Coords = PyArray_DIMS(coordXArray); - size = PyArray_SIZE(coordXArray); - - if(!NI_Resample_Coords(size, (int)dimsS[0], (int)dimsS[1], (int)dimsS[2], (int)dimsD[0], - (int)dimsD[1], (int)dimsD[2], S, X, Y, Z, imageD, imageS, scale, offset)) - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - - -static PyObject *Register_Complete_Symmetry(PyObject *self, PyObject *args) -{ - - int nx; - int ny; - int nz; - int ni; - double *A; - PyObject *AlphaArray = NULL; - - if(!PyArg_ParseTuple(args, "Oiiii", &AlphaArray, &nx, &ny, &nz, &ni)) - goto exit; - - A = (double *)PyArray_DATA(AlphaArray); - - if(!NI_Complete_Symmetry(A, nx, ny, nz, ni)) - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - - - -static PyObject *Register_LT_Tensor_Product(PyObject *self, PyObject *args) -{ - int M1; - int M2; - int rows; - int cur_row; - int coeff_1; - int coeff_2; - double *A1; - double *A2; - double *B1; - double *B2; - double *Basis; - PyObject *AlphaArray1 = NULL; - PyObject *AlphaArray2 = NULL; - PyObject *BetaArray1 = NULL; - PyObject *BetaArray2 = NULL; - PyObject *BasisArray = NULL; - - if(!PyArg_ParseTuple(args, "OOOOOiiiiii", &AlphaArray1, &AlphaArray2, &BetaArray1, &BetaArray2, - &BasisArray, &M1, &M2, &rows, &cur_row, &coeff_1, &coeff_2)) - goto exit; - - A1 = (double *)PyArray_DATA(AlphaArray1); - A2 = (double *)PyArray_DATA(AlphaArray2); - B1 = (double *)PyArray_DATA(BetaArray1); - B2 = (double *)PyArray_DATA(BetaArray2); - Basis = (double *)PyArray_DATA(BasisArray); - - if(!NI_LT_Tensor_Product(A1, A2, B1, B2, Basis, M1, M2, rows, cur_row, coeff_1, coeff_2)) - goto exit; - - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - - - -static PyObject *Register_LT_Mrqcof(PyObject *self, PyObject *args) -{ - - int M1; - double wt; - double value; - double *A; - double *B; - double *V; - PyObject *AlphaArray = NULL; - PyObject *BetaArray = NULL; - PyObject *VArray = NULL; - - if(!PyArg_ParseTuple(args, "OOOddi", &AlphaArray, &BetaArray, &VArray, &wt, &value, &M1)) - goto exit; - - A = (double *)PyArray_DATA(AlphaArray); - B = (double *)PyArray_DATA(BetaArray); - V = (double *)PyArray_DATA(VArray); - - if(!NI_LT_Mrqcof(A, B, V, wt, value, M1)) - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - - -static PyMethodDef RegisterMethods[] = -{ - { "register_complete_symmetry", Register_Complete_Symmetry, METH_VARARGS, NULL }, - { "register_lt_mrqcof", Register_LT_Mrqcof, METH_VARARGS, NULL }, - { "register_lt_tensor_product", Register_LT_Tensor_Product, METH_VARARGS, NULL }, - { "register_find_mask", Register_Find_Mask, METH_VARARGS, NULL }, - { "register_resample_coords", Register_Resample_Coords, METH_VARARGS, NULL }, - { "register_resample_gradient_coords", Register_Resample_Gradient_Coords, METH_VARARGS, NULL }, - { "register_resample_w_gradient", Register_ResampleWithGradient, METH_VARARGS, NULL }, - { "register_histogram", Register_Histogram, METH_VARARGS, NULL }, - { "register_histogram_lite", Register_HistogramLite, METH_VARARGS, NULL }, - { "register_linear_resample", Register_LinearResample, METH_VARARGS, NULL }, - { "register_cubic_resample", Register_CubicResample, METH_VARARGS, NULL }, - { "register_volume_resample", Register_VolumeResample, METH_VARARGS, NULL }, - { "register_image_threshold", Register_ImageThreshold, METH_VARARGS, NULL }, - { NULL, NULL, 0, NULL}, -}; - -PyMODINIT_FUNC init_register(void) -{ - Py_InitModule("_register", RegisterMethods); - import_array(); -} - - +/* Python extension interface code */ + +#include "Python.h" +#include "numpy/arrayobject.h" + +static PyObject *Register_Histogram(PyObject *self, PyObject *args) +{ + /* + joint histogram memory is created in python to avoid memory leak problem + */ + + int num; + int numM; + int nd; + int type; + int itype; + int nd_histo; + int nd_rotmatrix; + int nd_S; + npy_intp *dimsF; + npy_intp *dimsG; + npy_intp *dims_histo; + npy_intp *dims_rotmatrix; + npy_intp *dims_S; + unsigned char *imageG; + unsigned char *imageF; + double *pHisto; + double *M; + int *S; + PyObject *imgArray1 = NULL; + PyObject *imgArray2 = NULL; + PyObject *rotArray = NULL; + PyObject *SArray = NULL; + PyObject *hArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOOO", &imgArray1, &imgArray2, &rotArray, &SArray, &hArray)) + goto exit; + + /* check in the Python code that F and G are the same dims, type */ + imageF = (unsigned char *)PyArray_DATA(imgArray1); + imageG = (unsigned char *)PyArray_DATA(imgArray2); + nd = PyArray_NDIM(imgArray1); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + dimsF = PyArray_DIMS(imgArray1); + dimsG = PyArray_DIMS(imgArray2); + type = PyArray_TYPE(imgArray1); + num = PyArray_SIZE(imgArray1); + + M = (double *)PyArray_DATA(rotArray); + nd_rotmatrix = PyArray_NDIM(rotArray); + dims_rotmatrix = PyArray_DIMS(rotArray); + numM = PyArray_SIZE(rotArray); + + S = (int *)PyArray_DATA(SArray); + nd_S = PyArray_NDIM(SArray); + dims_S = PyArray_DIMS(SArray); + + pHisto = (double *)PyArray_DATA(hArray); + nd_histo = PyArray_NDIM(hArray); + dims_histo = PyArray_DIMS(hArray); + /* check to make sure this is 256x256 */ + + if(!NI_Histogram2D((int)dimsF[0], (int)dimsF[1], (int)dimsF[2], + (int)dimsG[0], (int)dimsG[1], (int)dimsG[2], + S, M, imageG, imageF, pHisto)) + goto exit; + +exit: + + /* return the 2D histogram */ + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Register_HistogramLite(PyObject *self, PyObject *args) +{ + /* + joint histogram memory is created in python to avoid memory leak problem + */ + + int num; + int numG; + int nd; + int type; + int itype; + int nd_histo; + int nd_rotmatrix; + int nd_S; + npy_intp *dimsF; + npy_intp *dimsG; + npy_intp *dims_histo; + npy_intp *dims_rotmatrix; + npy_intp *dims_S; + unsigned char *imageG; + unsigned char *imageF; + double *pHisto; + double *M; + int *S; + PyObject *imgArray1 = NULL; + PyObject *imgArray2 = NULL; + PyObject *rotArray = NULL; + PyObject *SArray = NULL; + PyObject *hArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOOO", &imgArray1, &imgArray2, &rotArray, &SArray, &hArray)) + goto exit; + + /* check in the Python code that F and G are the same dims, type */ + imageF = (unsigned char *)PyArray_DATA(imgArray1); + imageG = (unsigned char *)PyArray_DATA(imgArray2); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArray1); + dimsF = PyArray_DIMS(imgArray1); + dimsG = PyArray_DIMS(imgArray2); + type = PyArray_TYPE(imgArray1); + num = PyArray_SIZE(imgArray1); + numG = PyArray_SIZE(imgArray2); + + M = (double *)PyArray_DATA(rotArray); + nd_rotmatrix = PyArray_NDIM(rotArray); + dims_rotmatrix = PyArray_DIMS(rotArray); + + S = (int *)PyArray_DATA(SArray); + nd_S = PyArray_NDIM(SArray); + dims_S = PyArray_DIMS(SArray); + + pHisto = (double *)PyArray_DATA(hArray); + nd_histo = PyArray_NDIM(hArray); + dims_histo = PyArray_DIMS(hArray); + /* check to make sure this is 256x256 */ + + if(!NI_Histogram2DLite((int)dimsF[0], (int)dimsF[1], (int)dimsF[2], + (int)dimsG[0], (int)dimsG[1], (int)dimsG[2], + S, M, imageG, imageF, pHisto)) + goto exit; + +exit: + + /* return the 2D histogram */ + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + +static PyObject *Register_VolumeResample(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int itype; + int mode; + int scale; + npy_intp *dimsF; + npy_intp *dimsG; + unsigned char *imageG; + unsigned char *imageF; + double *Z; + PyObject *imgArray1 = NULL; + PyObject *imgArray2 = NULL; + PyObject *coordZoom = NULL; + + if(!PyArg_ParseTuple(args, "OOOii", &imgArray1, &imgArray2, &coordZoom, &scale, &mode)) + goto exit; + + /* check in the Python code that F and G are the same dims, type */ + imageF = (unsigned char *)PyArray_DATA(imgArray1); + imageG = (unsigned char *)PyArray_DATA(imgArray2); + Z = (double *)PyArray_DATA(coordZoom); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArray1); + dimsF = PyArray_DIMS(imgArray1); + dimsG = PyArray_DIMS(imgArray2); + type = PyArray_TYPE(imgArray1); + num = PyArray_SIZE(imgArray1); + + if(!NI_VolumeResample((int)dimsF[0], (int)dimsF[1], (int)dimsF[2], + (int)dimsG[0], (int)dimsG[1], (int)dimsG[2], + scale, mode, imageG, imageF, Z)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + + +static PyObject *Register_CubicResample(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int itype; + int nd_rotmatrix; + int nd_S; + npy_intp *dimsF; + npy_intp *dimsG; + npy_intp *dims_rotmatrix; + npy_intp *dims_S; + unsigned char *imageG; + unsigned char *imageF; + double *M; + int *S; + PyObject *imgArray1 = NULL; + PyObject *imgArray2 = NULL; + PyObject *rotArray = NULL; + PyObject *SArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOO", &imgArray1, &imgArray2, &rotArray, &SArray)) + goto exit; + + /* check in the Python code that F and G are the same dims, type */ + imageF = (unsigned char *)PyArray_DATA(imgArray1); + imageG = (unsigned char *)PyArray_DATA(imgArray2); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArray1); + dimsF = PyArray_DIMS(imgArray1); + dimsG = PyArray_DIMS(imgArray2); + type = PyArray_TYPE(imgArray1); + num = PyArray_SIZE(imgArray1); + + M = (double *)PyArray_DATA(rotArray); + nd_rotmatrix = PyArray_NDIM(rotArray); + dims_rotmatrix = PyArray_DIMS(rotArray); + + S = (int *)PyArray_DATA(SArray); + nd_S = PyArray_NDIM(SArray); + dims_S = PyArray_DIMS(SArray); + + if(!NI_CubicResample((int)dimsF[0], (int)dimsF[1], (int)dimsF[2], + (int)dimsG[0], (int)dimsG[1], (int)dimsG[2], + S, M, imageG, imageF)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Register_LinearResample(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int itype; + int nd_rotmatrix; + int nd_S; + npy_intp *dimsF; + npy_intp *dimsG; + npy_intp *dims_rotmatrix; + npy_intp *dims_S; + unsigned char *imageG; + unsigned char *imageF; + double *M; + int *S; + PyObject *imgArray1 = NULL; + PyObject *imgArray2 = NULL; + PyObject *rotArray = NULL; + PyObject *SArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOO", &imgArray1, &imgArray2, &rotArray, &SArray)) + goto exit; + + /* check in the Python code that F and G are the same dims, type */ + imageF = (unsigned char *)PyArray_DATA(imgArray1); + imageG = (unsigned char *)PyArray_DATA(imgArray2); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArray1); + dimsF = PyArray_DIMS(imgArray1); + dimsG = PyArray_DIMS(imgArray2); + type = PyArray_TYPE(imgArray1); + num = PyArray_SIZE(imgArray1); + + M = (double *)PyArray_DATA(rotArray); + nd_rotmatrix = PyArray_NDIM(rotArray); + dims_rotmatrix = PyArray_DIMS(rotArray); + + S = (int *)PyArray_DATA(SArray); + nd_S = PyArray_NDIM(SArray); + dims_S = PyArray_DIMS(SArray); + + if(!NI_LinearResample((int)dimsF[0], (int)dimsF[1], (int)dimsF[2], + (int)dimsG[0], (int)dimsG[1], (int)dimsG[2], + S, M, imageG, imageF)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Register_ImageThreshold(PyObject *self, PyObject *args) +{ + + /* set threshold from the volume integrated histogram */ + int num; + int nd; + int type; + int itype; + int histogram_elements; + int tindex; + npy_intp *dimsImage; + npy_intp *dimsHistogram; + unsigned short *image; + double *H; + double *IH; + double threshold; + PyObject *imgArray = NULL; + PyObject *histogram = NULL; + PyObject *ihistogram = NULL; + + if(!PyArg_ParseTuple(args, "OOOd", &imgArray, &histogram, &ihistogram, &threshold)) + goto exit; + + image = (unsigned short *)PyArray_DATA(imgArray); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArray); + dimsImage = PyArray_DIMS(imgArray); + type = PyArray_TYPE(imgArray); + num = PyArray_SIZE(imgArray); + + H = (double *)PyArray_DATA(histogram); + IH = (double *)PyArray_DATA(ihistogram); + histogram_elements = PyArray_SIZE(histogram); + + if(!NI_ImageThreshold((int)dimsImage[0], (int)dimsImage[1], (int)dimsImage[2], + image, H, IH, histogram_elements, threshold, &tindex)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("i", tindex); + +} + + +static PyObject *Register_ResampleWithGradient(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int itype; + int nd_rotmatrix; + int nd_S; + npy_intp *dimsScale; + npy_intp *dimsOffset; + npy_intp *dimsS; + npy_intp *dimsD; + npy_intp *dims_rotmatrix; + npy_intp *dims_S; + unsigned char *imageS; + unsigned char *imageD; + double *M; + int *S; + double *scale; + int *offset; + double *gradientX; + double *gradientY; + double *gradientZ; + PyObject *imgArrayS = NULL; + PyObject *imgArrayD = NULL; + PyObject *rotArray = NULL; + PyObject *SArray = NULL; + PyObject *scaleArray = NULL; + PyObject *offsetArray = NULL; + PyObject *gradXArray = NULL; + PyObject *gradYArray = NULL; + PyObject *gradZArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOOOOOOO", &imgArrayS, &imgArrayD, &rotArray, &SArray, &scaleArray, + &offsetArray, &gradXArray, &gradYArray, &gradZArray)) + goto exit; + + /* check in the Python code that S and D are the same dims, type */ + imageS = (unsigned char *)PyArray_DATA(imgArrayS); + imageD = (unsigned char *)PyArray_DATA(imgArrayD); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArrayS); + dimsS = PyArray_DIMS(imgArrayS); + dimsD = PyArray_DIMS(imgArrayD); + type = PyArray_TYPE(imgArrayS); + num = PyArray_SIZE(imgArrayS); + + M = (double *)PyArray_DATA(rotArray); + nd_rotmatrix = PyArray_NDIM(rotArray); + dims_rotmatrix = PyArray_DIMS(rotArray); + + S = (int *)PyArray_DATA(SArray); + nd_S = PyArray_NDIM(SArray); + dims_S = PyArray_DIMS(SArray); + + scale = (double *)PyArray_DATA(scaleArray); + offset = (int *)PyArray_DATA(offsetArray); + dimsScale = PyArray_DIMS(scaleArray); + dimsOffset = PyArray_DIMS(offsetArray); + + gradientX = (double *)PyArray_DATA(gradXArray); + gradientY = (double *)PyArray_DATA(gradYArray); + gradientZ = (double *)PyArray_DATA(gradZArray); + + if(!NI_ResampleWithGradient((int)dimsS[0], (int)dimsS[1], (int)dimsS[2], + (int)dimsD[0], (int)dimsD[1], (int)dimsD[2], + S, M, imageD, imageS, scale, offset, gradientX, + gradientY, gradientZ)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Register_Find_Mask(PyObject *self, PyObject *args) +{ + + int i; + int num; + int length; + double *X; + double *Y; + double *Z; + int *xLims; + int *yLims; + int *zLims; + int *mask; + PyObject *MArray = NULL; + PyObject *XArray = NULL; + PyObject *YArray = NULL; + PyObject *ZArray = NULL; + PyObject *XLimits = NULL; + PyObject *YLimits = NULL; + PyObject *ZLimits = NULL; + + if(!PyArg_ParseTuple(args, "OOOOOOO", &MArray, &XArray, &YArray, &ZArray, &XLimits, &YLimits, &ZLimits)) + goto exit; + + num = PyArray_SIZE(XArray); + X = (double *)PyArray_DATA(XArray); + Y = (double *)PyArray_DATA(YArray); + Z = (double *)PyArray_DATA(ZArray); + mask = (int *)PyArray_DATA(MArray); + xLims = (int *)PyArray_DATA(XLimits); + yLims = (int *)PyArray_DATA(YLimits); + zLims = (int *)PyArray_DATA(ZLimits); + + for(length = 0, i = 0; i < num; ++i){ + if( ((X[i] >= xLims[0]) && (X[i] <= xLims[1])) && + ((Y[i] >= yLims[0]) && (Y[i] <= yLims[1])) && + ((Z[i] >= zLims[0]) && (Z[i] <= zLims[1])) ){ + mask[length++] = i; + } + } + + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("i", length); + +} + + + +static PyObject *Register_Resample_Gradient_Coords(PyObject *self, PyObject *args) +{ + + int num; + int size; + int nd; + int type; + int itype; + int nd_S; + npy_intp *dimsScale; + npy_intp *dimsOffset; + npy_intp *dimsS; + npy_intp *dimsD; + npy_intp *dims_S; + npy_intp *dims_Coords; + unsigned char *imageS; + unsigned char *imageD; + double *X; + double *Y; + double *Z; + int *S; + double *scale; + int *offset; + double *gradientX; + double *gradientY; + double *gradientZ; + PyObject *imgArrayS = NULL; + PyObject *imgArrayD = NULL; + PyObject *SArray = NULL; + PyObject *scaleArray = NULL; + PyObject *offsetArray = NULL; + PyObject *gradXArray = NULL; + PyObject *gradYArray = NULL; + PyObject *gradZArray = NULL; + PyObject *coordXArray = NULL; + PyObject *coordYArray = NULL; + PyObject *coordZArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOOOOOOOOO", &coordZArray, &coordYArray, &coordXArray, + &imgArrayS, &imgArrayD, &SArray, &scaleArray, &offsetArray, + &gradXArray, &gradYArray, &gradZArray)) + goto exit; + + /* check in the Python code that S and D are the same dims, type */ + imageS = (unsigned char *)PyArray_DATA(imgArrayS); + imageD = (unsigned char *)PyArray_DATA(imgArrayD); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArrayS); + dimsS = PyArray_DIMS(imgArrayS); + dimsD = PyArray_DIMS(imgArrayD); + type = PyArray_TYPE(imgArrayS); + num = PyArray_SIZE(imgArrayS); + + S = (int *)PyArray_DATA(SArray); + nd_S = PyArray_NDIM(SArray); + dims_S = PyArray_DIMS(SArray); + + scale = (double *)PyArray_DATA(scaleArray); + offset = (int *)PyArray_DATA(offsetArray); + dimsScale = PyArray_DIMS(scaleArray); + dimsOffset = PyArray_DIMS(offsetArray); + + gradientX = (double *)PyArray_DATA(gradXArray); + gradientY = (double *)PyArray_DATA(gradYArray); + gradientZ = (double *)PyArray_DATA(gradZArray); + + X = (double *)PyArray_DATA(coordXArray); + Y = (double *)PyArray_DATA(coordYArray); + Z = (double *)PyArray_DATA(coordZArray); + + dims_Coords = PyArray_DIMS(coordXArray); + size = PyArray_SIZE(coordXArray); + + if(!NI_Resample_Gradient_Coords(size, (int)dimsS[0], (int)dimsS[1], (int)dimsS[2], (int)dimsD[0], + (int)dimsD[1], (int)dimsD[2], S, X, Y, Z, imageD, imageS, scale, + offset, gradientX, gradientY, gradientZ)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + + +static PyObject *Register_Resample_Coords(PyObject *self, PyObject *args) +{ + + int num; + int size; + int nd; + int type; + int itype; + int nd_S; + npy_intp *dimsScale; + npy_intp *dimsOffset; + npy_intp *dimsS; + npy_intp *dimsD; + npy_intp *dims_S; + npy_intp *dims_Coords; + unsigned char *imageS; + unsigned char *imageD; + double *X; + double *Y; + double *Z; + int *S; + double *scale; + int *offset; + PyObject *imgArrayS = NULL; + PyObject *imgArrayD = NULL; + PyObject *SArray = NULL; + PyObject *scaleArray = NULL; + PyObject *offsetArray = NULL; + PyObject *coordXArray = NULL; + PyObject *coordYArray = NULL; + PyObject *coordZArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOOOOOO", &coordZArray, &coordYArray, &coordXArray, + &imgArrayS, &imgArrayD, &SArray, &scaleArray, &offsetArray)) + goto exit; + + /* check in the Python code that S and D are the same dims, type */ + imageS = (unsigned char *)PyArray_DATA(imgArrayS); + imageD = (unsigned char *)PyArray_DATA(imgArrayD); + /* reads dims as 0 = layers, 1 = rows, 2 = cols */ + nd = PyArray_NDIM(imgArrayS); + dimsS = PyArray_DIMS(imgArrayS); + dimsD = PyArray_DIMS(imgArrayD); + type = PyArray_TYPE(imgArrayS); + num = PyArray_SIZE(imgArrayS); + + S = (int *)PyArray_DATA(SArray); + nd_S = PyArray_NDIM(SArray); + dims_S = PyArray_DIMS(SArray); + + scale = (double *)PyArray_DATA(scaleArray); + offset = (int *)PyArray_DATA(offsetArray); + dimsScale = PyArray_DIMS(scaleArray); + dimsOffset = PyArray_DIMS(offsetArray); + + X = (double *)PyArray_DATA(coordXArray); + Y = (double *)PyArray_DATA(coordYArray); + Z = (double *)PyArray_DATA(coordZArray); + + dims_Coords = PyArray_DIMS(coordXArray); + size = PyArray_SIZE(coordXArray); + + if(!NI_Resample_Coords(size, (int)dimsS[0], (int)dimsS[1], (int)dimsS[2], (int)dimsD[0], + (int)dimsD[1], (int)dimsD[2], S, X, Y, Z, imageD, imageS, scale, offset)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Register_Complete_Symmetry(PyObject *self, PyObject *args) +{ + + int nx; + int ny; + int nz; + int ni; + double *A; + PyObject *AlphaArray = NULL; + + if(!PyArg_ParseTuple(args, "Oiiii", &AlphaArray, &nx, &ny, &nz, &ni)) + goto exit; + + A = (double *)PyArray_DATA(AlphaArray); + + if(!NI_Complete_Symmetry(A, nx, ny, nz, ni)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + + +static PyObject *Register_LT_Tensor_Product(PyObject *self, PyObject *args) +{ + int M1; + int M2; + int rows; + int cur_row; + int coeff_1; + int coeff_2; + double *A1; + double *A2; + double *B1; + double *B2; + double *Basis; + PyObject *AlphaArray1 = NULL; + PyObject *AlphaArray2 = NULL; + PyObject *BetaArray1 = NULL; + PyObject *BetaArray2 = NULL; + PyObject *BasisArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOOOiiiiii", &AlphaArray1, &AlphaArray2, &BetaArray1, &BetaArray2, + &BasisArray, &M1, &M2, &rows, &cur_row, &coeff_1, &coeff_2)) + goto exit; + + A1 = (double *)PyArray_DATA(AlphaArray1); + A2 = (double *)PyArray_DATA(AlphaArray2); + B1 = (double *)PyArray_DATA(BetaArray1); + B2 = (double *)PyArray_DATA(BetaArray2); + Basis = (double *)PyArray_DATA(BasisArray); + + if(!NI_LT_Tensor_Product(A1, A2, B1, B2, Basis, M1, M2, rows, cur_row, coeff_1, coeff_2)) + goto exit; + + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + + +static PyObject *Register_LT_Mrqcof(PyObject *self, PyObject *args) +{ + + int M1; + double wt; + double value; + double *A; + double *B; + double *V; + PyObject *AlphaArray = NULL; + PyObject *BetaArray = NULL; + PyObject *VArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOddi", &AlphaArray, &BetaArray, &VArray, &wt, &value, &M1)) + goto exit; + + A = (double *)PyArray_DATA(AlphaArray); + B = (double *)PyArray_DATA(BetaArray); + V = (double *)PyArray_DATA(VArray); + + if(!NI_LT_Mrqcof(A, B, V, wt, value, M1)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyMethodDef RegisterMethods[] = +{ + { "register_complete_symmetry", Register_Complete_Symmetry, METH_VARARGS, NULL }, + { "register_lt_mrqcof", Register_LT_Mrqcof, METH_VARARGS, NULL }, + { "register_lt_tensor_product", Register_LT_Tensor_Product, METH_VARARGS, NULL }, + { "register_find_mask", Register_Find_Mask, METH_VARARGS, NULL }, + { "register_resample_coords", Register_Resample_Coords, METH_VARARGS, NULL }, + { "register_resample_gradient_coords", Register_Resample_Gradient_Coords, METH_VARARGS, NULL }, + { "register_resample_w_gradient", Register_ResampleWithGradient, METH_VARARGS, NULL }, + { "register_histogram", Register_Histogram, METH_VARARGS, NULL }, + { "register_histogram_lite", Register_HistogramLite, METH_VARARGS, NULL }, + { "register_linear_resample", Register_LinearResample, METH_VARARGS, NULL }, + { "register_cubic_resample", Register_CubicResample, METH_VARARGS, NULL }, + { "register_volume_resample", Register_VolumeResample, METH_VARARGS, NULL }, + { "register_image_threshold", Register_ImageThreshold, METH_VARARGS, NULL }, + { NULL, NULL, 0, NULL}, +}; + +PyMODINIT_FUNC init_register(void) +{ + Py_InitModule("_register", RegisterMethods); + import_array(); +} + + Modified: trunk/scipy/ndimage/src/register/Register_IMPL.c =================================================================== --- trunk/scipy/ndimage/src/register/Register_IMPL.c 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/register/Register_IMPL.c 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,1369 +1,1369 @@ -#include -#include - -float tri_cubic_convolve(unsigned char *pVolume, int x, int y, int z, float xp, float yp, - float zp, int colsG, int rowsG, int layersG, int sliceSizeG){ - - int i, j, k; - int layerOffsets[4]; - int rowOffsets[4]; - float ps1, ps2, ps3; - float Y[4], NewRow[4], NewLayer[4]; - float R, C, L, D, T; - float valueXYZ = 0.0; - float dataCube[4][4][4]; - /* [cols][rows][layers] */ - - rowOffsets[0] = (y-1)*colsG; - rowOffsets[1] = (y )*colsG; - rowOffsets[2] = (y+1)*colsG; - rowOffsets[3] = (y+2)*colsG; - - layerOffsets[0] = (z-1)*sliceSizeG; - layerOffsets[1] = (z )*sliceSizeG; - layerOffsets[2] = (z+1)*sliceSizeG; - layerOffsets[3] = (z+2)*sliceSizeG; - - /* get numerator for interpolation */ - C = xp - (float)x; - R = yp - (float)y; - L = zp - (float)z; - D = (float)0.002; - - /* get 4x4 window over all 4 layers */ - for(i = 0; i < 4; ++i){ - for(j = 0; j < 4; ++j){ - dataCube[0][j][i] = (float)pVolume[layerOffsets[i]+rowOffsets[j]+x-1]; - dataCube[1][j][i] = (float)pVolume[layerOffsets[i]+rowOffsets[j]+x]; - dataCube[2][j][i] = (float)pVolume[layerOffsets[i]+rowOffsets[j]+x+1]; - dataCube[3][j][i] = (float)pVolume[layerOffsets[i]+rowOffsets[j]+x+2]; - } - } - - for(i = 0; i < 4; ++i){ - /* interpolate 4 rows in all 4 layers */ - for(j = 0; j < 4; ++j){ - if(C > D){ - Y[0] = dataCube[0][j][i]; - Y[1] = dataCube[1][j][i]; - Y[2] = dataCube[2][j][i]; - Y[3] = dataCube[3][j][i]; - ps1 = Y[2] - Y[0]; - ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; - ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; - NewRow[j] = Y[1]+C*(ps1+C*(ps2+C*ps3)); - } - else{ - NewRow[j] = dataCube[1][j][i]; - } - } - /* interpolate across 4 columns */ - if(R > D){ - Y[0] = NewRow[0]; - Y[1] = NewRow[1]; - Y[2] = NewRow[2]; - Y[3] = NewRow[3]; - ps1 = Y[2] - Y[0]; - ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; - ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; - T = (Y[1]+R*(ps1+R*(ps2+R*ps3))); - NewLayer[i] = T; - } - else{ - T = NewRow[1]; - NewLayer[i] = T; - } - } - /* interpolate across 4 layers */ - if(L > D){ - Y[0] = NewLayer[0]; - Y[1] = NewLayer[1]; - Y[2] = NewLayer[2]; - Y[3] = NewLayer[3]; - ps1 = Y[2] - Y[0]; - ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; - ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; - T = (Y[1]+L*(ps1+L*(ps2+L*ps3))); - valueXYZ = T; - } - else{ - T = NewLayer[1]; - valueXYZ = T; - } - - return(valueXYZ); - -} - -float trilinear_A(unsigned char *pVolume, int x, int y, int z, float dx, float dy, float dz, int dims[]){ - - // Vxyz for [0,1] values of x, y, z - int V000; - int V100; - int V010; - int V001; - int V011; - int V101; - int V110; - int V111; - - int ptr_x0; - int ptr_y0; - int ptr_z0; - - int ptr_x1; - int ptr_y1; - int ptr_z1; - - float valueXYZ; - - ptr_x0 = x; - ptr_y0 = y * dims[0]; - ptr_z0 = z * dims[1]; - - ptr_x1 = ptr_x0 + 1; - ptr_y1 = ptr_y0 + dims[0]; - ptr_z1 = ptr_z0 + dims[1]; - - V000 = pVolume[ptr_x0+ptr_y0+ptr_z0]; - V100 = pVolume[ptr_x1+ptr_y0+ptr_z0]; - V010 = pVolume[ptr_x0+ptr_y1+ptr_z0]; - V001 = pVolume[ptr_x0+ptr_y0+ptr_z1]; - V011 = pVolume[ptr_x0+ptr_y1+ptr_z1]; - V101 = pVolume[ptr_x1+ptr_y0+ptr_z1]; - V110 = pVolume[ptr_x1+ptr_y1+ptr_z0]; - V111 = pVolume[ptr_x1+ptr_y1+ptr_z1]; - - // dx, dy, dz are increments in x, y, z - // dx = 0 is x = 1 as x, y and z are [0, 1] in range - - valueXYZ = - V000 * (1.0-dx) * (1.0 - dy) * (1.0 - dz) + - V100 * (dx) * (1.0 - dy) * (1.0 - dz) + - V010 * (1.0-dx) * (dy) * (1.0 - dz) + - V001 * (1.0-dx) * (1.0 - dy) * (dz) + - V101 * (dx) * (1.0 - dy) * (dz) + - V011 * (1.0-dx) * (dy) * (dz) + - V110 * (dx) * (dy) * (1.0 - dz) + - V111 * (dx) * (dy) * (dz); - - - return(valueXYZ); - -} - -float trilinear_B(unsigned char *pVolume, float dx, float dy, float dz, int corners[]){ - - // Vxyz for [0,1] values of x, y, z - int V000; - int V100; - int V010; - int V001; - int V011; - int V101; - int V110; - int V111; - - int ptr_x0 = corners[0]; - int ptr_y0 = corners[1]; - int ptr_z0 = corners[2]; - - int ptr_x1 = corners[3]; - int ptr_y1 = corners[4]; - int ptr_z1 = corners[5]; - - float valueXYZ; - - V000 = pVolume[ptr_x0+ptr_y0+ptr_z0]; - V100 = pVolume[ptr_x1+ptr_y0+ptr_z0]; - V010 = pVolume[ptr_x0+ptr_y1+ptr_z0]; - V001 = pVolume[ptr_x0+ptr_y0+ptr_z1]; - V011 = pVolume[ptr_x0+ptr_y1+ptr_z1]; - V101 = pVolume[ptr_x1+ptr_y0+ptr_z1]; - V110 = pVolume[ptr_x1+ptr_y1+ptr_z0]; - V111 = pVolume[ptr_x1+ptr_y1+ptr_z1]; - - // dx, dy, dz are increments in x, y, z - // dx = 0 is x = 1 as x, y and z are [0, 1] in range - - valueXYZ = - V000 * (1.0-dx) * (1.0 - dy) * (1.0 - dz) + - V100 * (dx) * (1.0 - dy) * (1.0 - dz) + - V010 * (1.0-dx) * (dy) * (1.0 - dz) + - V001 * (1.0-dx) * (1.0 - dy) * (dz) + - V101 * (dx) * (1.0 - dy) * (dz) + - V011 * (1.0-dx) * (dy) * (dz) + - V110 * (dx) * (dy) * (1.0 - dz) + - V111 * (dx) * (dy) * (dz); - - - return(valueXYZ); - -} - -int NI_Histogram2D(int layersF, int rowsF, int colsF, int layersG, int rowsG, int colsG, - int *dimSteps, double *M, unsigned char *imageG, unsigned char *imageF, double *H) -{ - - int status; - int seed; - int dimsF[3]; - int dimsG[3]; - int dims_F[2]; - int dims_G[2]; - int ivf, ivg; - float ran_x, ran_y, ran_z; - float vf, delta; - float x, y, z; - float dx, dy, dz; - float xp, yp, zp; - float rx, ry, rz; - - dimsF[0] = colsF; - dimsF[1] = rowsF; - dimsF[2] = layersF; - dimsG[0] = colsG; - dimsG[1] = rowsG; - dimsG[2] = layersG; - - dims_G[0] = dimsG[0]; - dims_G[1] = dimsG[0]*dimsG[1]; - dims_F[0] = dimsF[0]; - dims_F[1] = dimsF[0]*dimsF[1]; - - seed = 1000; - srand(seed); - - /* because of stochastic sampling, subtract 1 from upper bounds */ - for(z = 0.0; z < layersG-dimSteps[2]-1; z += dimSteps[2]){ - for(y = 0.0; y < rowsG-dimSteps[1]-1; y += dimSteps[1]){ - for(x = 0.0; x < colsG-dimSteps[0]-1; x += dimSteps[0]){ - /* positive jitter the x, y, z values */ - ran_x = 1.0 * rand()/((float)RAND_MAX); - ran_y = 1.0 * rand()/((float)RAND_MAX); - ran_z = 1.0 * rand()/((float)RAND_MAX); - dx = x + ran_x*dimSteps[0]; - dy = y + ran_y*dimSteps[1]; - dz = z + ran_z*dimSteps[2]; - - /* get the 'from' coordinates */ - xp = M[0]*dx + M[1]*dy + M[2]*dz + M[3]; - yp = M[4]*dx + M[5]*dy + M[6]*dz + M[7]; - zp = M[8]*dx + M[9]*dy + M[10]*dz + M[11]; - /* clip the resample window */ - if((zp >= 0.0 && zp < layersF-dimSteps[2]) && - (yp >= 0.0 && yp < rowsF-dimSteps[1]) && - (xp >= 0.0 && xp < colsF-dimSteps[0])){ - /* resample the coordinates using a trilinear interpolation */ - /* resample imageF using the rotated-jittered xyz coordinates */ - rx = xp - (int)xp; - ry = yp - (int)yp; - rz = zp - (int)zp; - //vf = trilinear_A(imageF, (int)dx, (int)dy, (int)dz, rx, ry, rz, dims_F); - vf = trilinear_A(imageF, (int)xp, (int)yp, (int)zp, rx, ry, rz, dims_F); - /* floor */ - ivf = (int)vf; - delta = vf - ivf; - /* resample imageG using the jittered xyz coordinates */ - rx = dx - (int)dx; - ry = dy - (int)dy; - rz = dz - (int)dz; - ivg = (int)trilinear_A(imageG, (int)dx, (int)dy, (int)dz, rx, ry, rz, dims_G); - //ivg = (int)trilinear_A(imageG, (int)xp, (int)yp, (int)zp, rx, ry, rz, dims_G); - /* ivf will be < 255 as 8 bit data and trilinear doesn't ring */ - H[ivf+256*ivg] += 1.0 - delta; - if(ivf < 255){ - H[ivf+1+256*ivg] += delta; - } - } - } - } - } - - status = 1; - - return status; - -} - - -int NI_Histogram2DLite(int layersF, int rowsF, int colsF, int layersG, int rowsG, int colsG, - int *dimSteps, double *M, unsigned char *imageG, unsigned char *imageF, double *H) -{ - - int i; - int status; - int sliceG; - int rowG; - int sliceSizeG; - int dimsF[3]; - int dimsG[3]; - int dims[2]; - int ivf, ivg; - float vf, delta; - float x, y, z; - float xp, yp, zp; - float dx, dy, dz; - - int ptr_x0; - int ptr_y0; - int ptr_z0; - int ptr_x1; - int ptr_y1; - int ptr_z1; - // - // Vxyz for [0,1] values of x, y, z - // - int V000; - int V100; - int V010; - int V001; - int V011; - int V101; - int V110; - int V111; - int g[64], f[64]; - float valueXYZ; - - // - // G is fixed; F is rotated - // - sliceSizeG = rowsG * colsG; - dimsF[0] = colsF; - dimsF[1] = rowsF; - dimsF[2] = layersF; - dimsG[0] = colsG; - dimsG[1] = rowsG; - dimsG[2] = layersG; - - dims[0] = dimsF[0]; - dims[1] = dimsF[0]*dimsF[1]; - - for(z = 0.0; z < layersG-dimSteps[2]-1; z += dimSteps[2]){ - sliceG = (int)z * sliceSizeG; - for(y = 0.0; y < rowsG-dimSteps[1]-1; y += dimSteps[1]){ - rowG = (int)y * colsG; - for(x = 0.0; x < colsG-dimSteps[0]-1; x += dimSteps[0]){ - // get the 'from' coordinates - xp = M[0]*x + M[1]*y + M[2]*z + M[3]; - yp = M[4]*x + M[5]*y + M[6]*z + M[7]; - zp = M[8]*x + M[9]*y + M[10]*z + M[11]; - // clip the resample window - if((zp >= 0.0 && zp < layersF-dimSteps[2]) && - (yp >= 0.0 && yp < rowsF-dimSteps[1]) && - (xp >= 0.0 && xp < colsF-dimSteps[0])){ - - // corners of the 3D unit volume cube - ptr_z0 = (int)zp * dims[1]; - ptr_z1 = ptr_z0 + dims[1]; - ptr_y0 = (int)yp * dims[0]; - ptr_y1 = ptr_y0 + dims[0]; - ptr_x0 = (int)xp; - ptr_x1 = ptr_x0 + 1; - dx = xp - (int)xp; - dy = yp - (int)yp; - dz = zp - (int)zp; - - // imageG is not rotated. sample the given x,y,z - ivg = imageG[sliceG+rowG+(int)x]; - // imageF IS rotated. sample the rotated xp,yp,zp - V000 = imageF[ptr_x0+ptr_y0+ptr_z0]; - V100 = imageF[ptr_x1+ptr_y0+ptr_z0]; - V010 = imageF[ptr_x0+ptr_y1+ptr_z0]; - V001 = imageF[ptr_x0+ptr_y0+ptr_z1]; - V011 = imageF[ptr_x0+ptr_y1+ptr_z1]; - V101 = imageF[ptr_x1+ptr_y0+ptr_z1]; - V110 = imageF[ptr_x1+ptr_y1+ptr_z0]; - V111 = imageF[ptr_x1+ptr_y1+ptr_z1]; - - vf = V000 * (1.0-dx) * (1.0 - dy) * (1.0 - dz) + - V100 * (dx) * (1.0 - dy) * (1.0 - dz) + - V010 * (1.0-dx) * (dy) * (1.0 - dz) + - V001 * (1.0-dx) * (1.0 - dy) * (dz) + - V101 * (dx) * (1.0 - dy) * (dz) + - V011 * (1.0-dx) * (dy) * (dz) + - V110 * (dx) * (dy) * (1.0 - dz) + - V111 * (dx) * (dy) * (dz); - - ivf = (int)(vf); - H[ivf+256*ivg] += 1.0; - } - } - } - } - - status = 1; - - return status; - -} - - -int NI_LinearResample(int layersF, int rowsF, int colsF, int layersG, int rowsG, int colsG, - int *dimSteps, double *M, unsigned char *imageG, unsigned char *imageF) -{ - - int i; - int status; - int sliceG; - int rowG; - int sliceSizeG; - int dimsF[3]; - int dimsG[3]; - int dims[2]; - int ivf, ivg; - float vf, delta; - float x, y, z; - float xp, yp, zp; - float dx, dy, dz; - - int ptr_x0; - int ptr_y0; - int ptr_z0; - int ptr_x1; - int ptr_y1; - int ptr_z1; - // - // Vxyz for [0,1] values of x, y, z - // - int V000; - int V100; - int V010; - int V001; - int V011; - int V101; - int V110; - int V111; - float valueXYZ; - - // - // G is fixed; F is rotated - // - sliceSizeG = rowsG * colsG; - dimsF[0] = colsF; - dimsF[1] = rowsF; - dimsF[2] = layersF; - dimsG[0] = colsG; - dimsG[1] = rowsG; - dimsG[2] = layersG; - - dims[0] = dimsF[0]; - dims[1] = dimsF[0]*dimsF[1]; - - for(z = 0.0; z < layersG-dimSteps[2]-1; z += dimSteps[2]){ - sliceG = (int)z * sliceSizeG; - for(y = 0.0; y < rowsG-dimSteps[1]-1; y += dimSteps[1]){ - rowG = (int)y * colsG; - for(x = 0.0; x < colsG-dimSteps[0]-1; x += dimSteps[0]){ - // get the 'from' coordinates - xp = M[0]*x + M[1]*y + M[2]*z + M[3]; - yp = M[4]*x + M[5]*y + M[6]*z + M[7]; - zp = M[8]*x + M[9]*y + M[10]*z + M[11]; - // clip the resample window - if((zp >= 0.0 && zp < layersF-dimSteps[2]) && - (yp >= 0.0 && yp < rowsF-dimSteps[1]) && - (xp >= 0.0 && xp < colsF-dimSteps[0])){ - - // corners of the 3D unit volume cube - ptr_z0 = (int)zp * dims[1]; - ptr_z1 = ptr_z0 + dims[1]; - ptr_y0 = (int)yp * dims[0]; - ptr_y1 = ptr_y0 + dims[0]; - ptr_x0 = (int)xp; - ptr_x1 = ptr_x0 + 1; - dx = xp - (int)xp; - dy = yp - (int)yp; - dz = zp - (int)zp; - - // imageF IS rotated. sample the rotated xp,yp,zp - // and stored in imageG - V000 = imageF[ptr_x0+ptr_y0+ptr_z0]; - V100 = imageF[ptr_x1+ptr_y0+ptr_z0]; - V010 = imageF[ptr_x0+ptr_y1+ptr_z0]; - V001 = imageF[ptr_x0+ptr_y0+ptr_z1]; - V011 = imageF[ptr_x0+ptr_y1+ptr_z1]; - V101 = imageF[ptr_x1+ptr_y0+ptr_z1]; - V110 = imageF[ptr_x1+ptr_y1+ptr_z0]; - V111 = imageF[ptr_x1+ptr_y1+ptr_z1]; - - vf = V000 * (1.0-dx) * (1.0 - dy) * (1.0 - dz) + - V100 * (dx) * (1.0 - dy) * (1.0 - dz) + - V010 * (1.0-dx) * (dy) * (1.0 - dz) + - V001 * (1.0-dx) * (1.0 - dy) * (dz) + - V101 * (dx) * (1.0 - dy) * (dz) + - V011 * (1.0-dx) * (dy) * (dz) + - V110 * (dx) * (dy) * (1.0 - dz) + - V111 * (dx) * (dy) * (dz); - - imageG[sliceG+rowG+(int)x] = (int)vf; - - } - } - } - } - - status = 1; - - return status; - -} - - - -int NI_VolumeResample(int layersS, int rowsS, int colsS, int layersD, int rowsD, int colsD, - int scale, int mode, unsigned char *imageD, unsigned char *imageS, double *Z) -{ - - int i; - int x, y, z; - int sliceSizeSrc; - int sliceSizeDst; - int status; - int ivf; - int xf, xg, yg, zg; - int g_slice, f_slice; - int g_row, f_row; - int g_slicesize, f_slicesize; - int itemp, sOffset, dOffset; - int XInt, YInt, ZInt; - float ps1, ps2, ps3; - float Y[4], tpoint, reSampler; - float XPrime, YPrime, ZPrime; - float C, R, L; - float *RLUT; - float *samples; - - if(mode ==1){ - /* - * integer subsample - */ - g_slicesize = rowsD * colsD; - f_slicesize = rowsS * colsS; - for(zg = 0; zg < layersD; ++zg){ - g_slice = zg * g_slicesize; - f_slice = zg * scale * f_slicesize; - for(yg = 0; yg < rowsD; ++yg){ - g_row = yg * colsD; - f_row = yg * scale * colsS; - for(xg = 0; xg < colsD; ++xg){ - xf = xg * scale; - ivf = imageS[f_slice+f_row+xf]; - imageD[g_slice+g_row+xg] = ivf; - } - } - } - } - else if(mode ==2){ - /* - * fractional cubic convolution resample - */ - - /* first resample each column in all rows and all layers */ - - sliceSizeSrc = colsS * rowsS; - sliceSizeDst = colsD * rowsD; - - RLUT = calloc(colsD, sizeof(float)); - samples = calloc(colsS+4, sizeof(float)); - reSampler = (float)1.0/Z[0]; - tpoint = (float)0.0; - for(i = 0; i < colsD; ++i){ - RLUT[i] = tpoint; - tpoint += reSampler; - } - - for(z = 0; z < layersS; ++z){ - sOffset = z * sliceSizeSrc; - dOffset = z * sliceSizeDst; - for(y = 0; y < rowsS; ++y){ - for(x = 0; x < colsS; ++x){ - samples[x] = (float)imageS[sOffset+x]; - } - for(x = 1; x < colsD; ++x){ - XPrime = RLUT[x]; - XInt = (int)XPrime; - C = XPrime - (float)XInt; - Y[0] = samples[XInt-1]; - Y[1] = samples[XInt]; - Y[2] = samples[XInt+1]; - Y[3] = samples[XInt+2]; - ps1 = Y[2] - Y[0]; - ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; - ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; - itemp = (int)(Y[1]+C*(ps1+C*(ps2+C*ps3))); - if(itemp < 0) itemp = 0; - if(itemp > 255) itemp = 255; - imageD[dOffset+x] = itemp; - } - sOffset += colsS; - dOffset += colsD; - } - } - free(RLUT); - free(samples); - - /* second resample each row in all columns and all layers */ - RLUT = calloc(rowsD, sizeof(float)); - samples = calloc(rowsS+4, sizeof(float)); - reSampler = (float)1.0/Z[1]; - tpoint = (float)0.0; - for(i = 0; i < rowsD; ++i){ - RLUT[i] = tpoint; - tpoint += reSampler; - } - - for(z = 0; z < layersS; ++z){ - dOffset = z * sliceSizeDst; - for(x = 0; x < colsD; ++x){ - for(y = 0; y < rowsS; ++y){ - samples[y] = (float)imageD[dOffset+x+y*colsD]; - } - for(y = 1; y < rowsD; ++y){ - YPrime = RLUT[y]; - YInt = (int)YPrime; - R = YPrime - (float)YInt; - Y[0] = samples[YInt-1]; - Y[1] = samples[YInt]; - Y[2] = samples[YInt+1]; - Y[3] = samples[YInt+2]; - ps1 = Y[2] - Y[0]; - ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; - ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; - itemp = (int)(Y[1]+R*(ps1+R*(ps2+R*ps3))); - if(itemp < 0) itemp = 0; - if(itemp > 255) itemp = 255; - imageD[dOffset+x+y*colsD] = itemp; - } - } - } - free(RLUT); - free(samples); - - /* third resample each layers in all columns and all rows */ - RLUT = calloc(layersD, sizeof(float)); - samples = calloc(layersS+4, sizeof(float)); - reSampler = (float)1.0/Z[2]; - tpoint = (float)0.0; - for(i = 0; i < layersD; ++i){ - RLUT[i] = tpoint; - tpoint += reSampler; - } - - for(y = 0; y < rowsD; ++y){ - dOffset = y * colsD; - for(x = 0; x < colsD; ++x){ - for(z = 0; z < layersS; ++z){ - samples[z] = (float)imageD[dOffset+x+z*sliceSizeDst]; - } - for(z = 1; z < layersD; ++z){ - ZPrime = RLUT[z]; - ZInt = (int)ZPrime; - L = ZPrime - (float)ZInt; - Y[0] = samples[ZInt-1]; - Y[1] = samples[ZInt]; - Y[2] = samples[ZInt+1]; - Y[3] = samples[ZInt+2]; - ps1 = Y[2] - Y[0]; - ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; - ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; - itemp = (int)(Y[1]+R*(ps1+R*(ps2+R*ps3))); - if(itemp < 0) itemp = 0; - if(itemp > 255) itemp = 255; - imageD[dOffset+x+z*sliceSizeDst] = itemp; - } - } - } - free(RLUT); - free(samples); - } - - status = 1; - - return status; - -} - - -int NI_CubicResample(int layersF, int rowsF, int colsF, int layersG, int rowsG, int colsG, - int *dimSteps, double *M, unsigned char *imageG, unsigned char *imageF) -{ - - int i; - int status; - int sliceG; - int rowG; - int sliceSizeG; - int ivf; - float vf; - float x, y, z; - float xp, yp, zp; - - sliceSizeG = rowsG * colsG; - for(z = 1.0; z < layersG-dimSteps[2]-2; z += dimSteps[2]){ - sliceG = (int)z * sliceSizeG; - for(y = 1.0; y < rowsG-dimSteps[1]-2; y += dimSteps[1]){ - rowG = (int)y * colsG; - for(x = 1.0; x < colsG-dimSteps[0]-2; x += dimSteps[0]){ - // get the 'from' coordinates - xp = M[0]*x + M[1]*y + M[2]*z + M[3]; - yp = M[4]*x + M[5]*y + M[6]*z + M[7]; - zp = M[8]*x + M[9]*y + M[10]*z + M[11]; - // clip the resample window - if((zp >= 1.0 && zp < layersF-dimSteps[2]-2) && - (yp >= 1.0 && yp < rowsF-dimSteps[1]-2) && - (xp >= 1.0 && xp < colsF-dimSteps[0]-2)){ - vf = tri_cubic_convolve(imageF, (int)xp, (int)yp, (int)zp, xp, yp, - zp, colsG, rowsG, layersG, sliceSizeG); - /* clip at hard edges */ - if(vf < 0.0) vf = 0.0; - if(vf > 255.0) vf = 255.0; - imageG[sliceG+rowG+(int)x] = (int)vf; - } - } - } - } - - status = 1; - - return status; - -} - -int NI_ImageThreshold(int layers, int rows, int cols, unsigned short *image, double *H, - double *IH, int histogram_elements, double threshold, int *index) -{ - - int i, j, k; - int status; - int ptr; - int value; - float sum; - - for(i = 0; i < histogram_elements; ++i){ - H[i] = 0; - IH[i] = 0; - } - ptr = 0; - for(i = 0; i < layers; ++i){ - for(j = 0; j < rows; ++j){ - for(k = 0; k < cols; ++k){ - value = image[ptr++]; - ++H[value]; - } - } - } - - sum = 0.0; - for(i = 0; i < histogram_elements; ++i){ - sum += H[i]; - } - /* normalize the volume histogram */ - for(i = 0; i < histogram_elements; ++i){ - H[i] = H[i] / sum; - } - - /* build the integrated histogram */ - IH[0] = H[0]; - for(i = 1; i < histogram_elements; ++i){ - IH[i] = IH[i-1] + H[i]; - } - - /* get the threshold crossing. this deals with the high amplitude outliers in the volume */ - *index = histogram_elements-1; - for(i = 0; i < histogram_elements; ++i){ - if(IH[i] > threshold){ - *index = i; - break; - } - } - - status = 1; - - return status; - -} - - -int NI_ResampleWithGradient(int layersS, int rowsS, int colsS, int layersD, int rowsD, - int colsD, int *dimSteps, double *M, unsigned char *imageD, - unsigned char *imageS, double *scale, int *offset, double *gradientX, - double *gradientY, double *gradientZ) -{ - - int i; - int seed; - int status; - int sliceD; - int rowD; - int sliceSizeD; - int dimsS[3]; - int dimsD[3]; - int dims[2]; - float vs; - float x, y, z; - float xp, yp, zp; - float dx1, dy1, dz1; - float dx2, dy2, dz2; - float ran_x, ran_y, ran_z; - float dx, dy, dz; - double gradX, gradY, gradZ; - - int ptr_x0; - int ptr_y0; - int ptr_z0; - int ptr_x1; - int ptr_y1; - int ptr_z1; - // - // Vxyz for [0,1] values of x, y, z - // - int V000; - int V100; - int V010; - int V001; - int V011; - int V101; - int V110; - int V111; - float valueXYZ; - - sliceSizeD = rowsD * colsD; - dimsD[0] = colsD; - dimsD[1] = rowsD; - dimsD[2] = layersD; - dimsS[0] = colsS; - dimsS[1] = rowsS; - dimsS[2] = layersS; - - dims[0] = dimsS[0]; - dims[1] = dimsS[0]*dimsS[1]; - - seed = 1000; - srand(seed); - - for(z = 0.0; z < layersD-dimSteps[2]-1; z += dimSteps[2]){ - sliceD = (int)z * sliceSizeD; - for(y = 0.0; y < rowsD-dimSteps[1]-1; y += dimSteps[1]){ - rowD = (int)y * colsD; - for(x = 0.0; x < colsD-dimSteps[0]-1; x += dimSteps[0]){ - - /* jitter the coordinates to prevent aliasing */ - ran_x = 1.0 * rand()/((float)RAND_MAX); - ran_y = 1.0 * rand()/((float)RAND_MAX); - ran_z = 1.0 * rand()/((float)RAND_MAX); - - dx = x + ran_x; - dy = y + ran_y; - dz = z + ran_z; - - // get the 'from' coordinates - xp = M[0]*dx + M[1]*dy + M[2]*dz + M[3]; - yp = M[4]*dx + M[5]*dy + M[6]*dz + M[7]; - zp = M[8]*dx + M[9]*dy + M[10]*dz + M[11]; - // clip the resample window - if((zp >= 0.0 && zp < layersS-dimSteps[2]) && - (yp >= 0.0 && yp < rowsS-dimSteps[1]) && - (xp >= 0.0 && xp < colsS-dimSteps[0])){ - - // corners of the 3D unit volume cube - ptr_z0 = (int)zp * dims[1]; - ptr_z1 = ptr_z0 + dims[1]; - ptr_y0 = (int)yp * dims[0]; - ptr_y1 = ptr_y0 + dims[0]; - ptr_x0 = (int)xp; - ptr_x1 = ptr_x0 + 1; - - dx1 = xp - (int)xp; - dy1 = yp - (int)yp; - dz1 = zp - (int)zp; - dx2 = 1.0 - dx1; - dy2 = 1.0 - dy1; - dz2 = 1.0 - dz1; - - V000 = imageS[ptr_x0+ptr_y0+ptr_z0]; - V100 = imageS[ptr_x1+ptr_y0+ptr_z0]; - V010 = imageS[ptr_x0+ptr_y1+ptr_z0]; - V001 = imageS[ptr_x0+ptr_y0+ptr_z1]; - V011 = imageS[ptr_x0+ptr_y1+ptr_z1]; - V101 = imageS[ptr_x1+ptr_y0+ptr_z1]; - V110 = imageS[ptr_x1+ptr_y1+ptr_z0]; - V111 = imageS[ptr_x1+ptr_y1+ptr_z1]; - - vs = V000 * (dx2) * (dy2) * (dz2) + - V100 * (dx1) * (dy2) * (dz2) + - V010 * (dx2) * (dy1) * (dz2) + - V001 * (dx2) * (dy2) * (dz1) + - V101 * (dx1) * (dy2) * (dz1) + - V011 * (dx2) * (dy1) * (dz1) + - V110 * (dx1) * (dy1) * (dz2) + - V111 * (dx1) * (dy1) * (dz1); - - /* resampled voxel */ - imageD[sliceD+rowD+(int)x] = (int)(vs*scale[(int)zp]) + offset[(int)zp]; - - /* - * x gradient voxel. for no resample dz1, dy1 = 0.0 and - * dy2, dz2 = 1.0 so gradX = V100 - V000 - */ - - /* d/d(dx1) = 1.0, d/d(dx2) = -1.0 */ - gradX = V000 * (-1.0) * (dy2) * (dz2) + - V100 * (1.0) * (dy2) * (dz2) + - V010 * (-1.0) * (dy1) * (dz2) + - V001 * (-1.0) * (dy2) * (dz1) + - V101 * (1.0) * (dy2) * (dz1) + - V011 * (-1.0) * (dy1) * (dz1) + - V110 * (1.0) * (dy1) * (dz2) + - V111 * (1.0) * (dy1) * (dz1); - - /* d/d(dy1) = 1.0, d/d(dy2) = -1.0 */ - gradY = V000 * (dx2) * (-1.0) * (dz2) + - V100 * (dx1) * (-1.0) * (dz2) + - V010 * (dx2) * (1.0) * (dz2) + - V001 * (dx2) * (-1.0) * (dz1) + - V101 * (dx1) * (-1.0) * (dz1) + - V011 * (dx2) * (1.0) * (dz1) + - V110 * (dx1) * (1.0) * (dz2) + - V111 * (dx1) * (1.0) * (dz1); - - /* d/d(dz1) = 1.0, d/d(dz2) = -1.0 */ - gradZ = V000 * (dx2) * (dy2) * (-1.0) + - V100 * (dx1) * (dy2) * (-1.0) + - V010 * (dx2) * (dy1) * (-1.0) + - V001 * (dx2) * (dy2) * (1.0) + - V101 * (dx1) * (dy2) * (1.0) + - V011 * (dx2) * (dy1) * (1.0) + - V110 * (dx1) * (dy1) * (-1.0) + - V111 * (dx1) * (dy1) * (1.0); - - gradientX[sliceD+rowD+(int)x] = (gradX*scale[(int)zp]); - gradientY[sliceD+rowD+(int)x] = (gradY*scale[(int)zp]); - gradientZ[sliceD+rowD+(int)x] = (gradZ*scale[(int)zp]); - - } - } - } - } - - status = 1; - - return status; - -} - - -int NI_Resample_Gradient_Coords(int size, int layersS, int rowsS, int colsS, int layersD, int rowsD, - int colsD, int *dimSteps, double *X, double *Y, double *Z, - unsigned char *imageD, unsigned char *imageS, double *scale, - int *offset, double *gradientX, double *gradientY, double *gradientZ) -{ - - int i; - int status; - int sliceSizeD; - int dimsS[3]; - int dimsD[3]; - int dims[2]; - float vs; - float xp, yp, zp; - float dx1, dy1, dz1; - float dx2, dy2, dz2; - double gradX, gradY, gradZ; - - int ptr_x0; - int ptr_y0; - int ptr_z0; - int ptr_x1; - int ptr_y1; - int ptr_z1; - // - // Vxyz for [0,1] values of x, y, z - // - int V000; - int V100; - int V010; - int V001; - int V011; - int V101; - int V110; - int V111; - float valueXYZ; - - sliceSizeD = rowsD * colsD; - dimsD[0] = colsD; - dimsD[1] = rowsD; - dimsD[2] = layersD; - dimsS[0] = colsS; - dimsS[1] = rowsS; - dimsS[2] = layersS; - - dims[0] = dimsS[0]; - dims[1] = dimsS[0]*dimsS[1]; - - for(i = 0; i < size; ++i){ - // get the 'from' unrolled coordinates - zp = Z[i]; - yp = Y[i]; - xp = X[i]; - - // clip the resample window - if((zp >= 0.0 && zp < layersS-dimSteps[2]) && - (yp >= 0.0 && yp < rowsS-dimSteps[1]) && - (xp >= 0.0 && xp < colsS-dimSteps[0])){ - - // corners of the 3D unit volume cube - ptr_z0 = (int)zp * dims[1]; - ptr_z1 = ptr_z0 + dims[1]; - ptr_y0 = (int)yp * dims[0]; - ptr_y1 = ptr_y0 + dims[0]; - ptr_x0 = (int)xp; - ptr_x1 = ptr_x0 + 1; - - dx1 = xp - (int)xp; - dy1 = yp - (int)yp; - dz1 = zp - (int)zp; - dx2 = 1.0 - dx1; - dy2 = 1.0 - dy1; - dz2 = 1.0 - dz1; - - V000 = imageS[ptr_x0+ptr_y0+ptr_z0]; - V100 = imageS[ptr_x1+ptr_y0+ptr_z0]; - V010 = imageS[ptr_x0+ptr_y1+ptr_z0]; - V001 = imageS[ptr_x0+ptr_y0+ptr_z1]; - V011 = imageS[ptr_x0+ptr_y1+ptr_z1]; - V101 = imageS[ptr_x1+ptr_y0+ptr_z1]; - V110 = imageS[ptr_x1+ptr_y1+ptr_z0]; - V111 = imageS[ptr_x1+ptr_y1+ptr_z1]; - - vs = V000 * (dx2) * (dy2) * (dz2) + - V100 * (dx1) * (dy2) * (dz2) + - V010 * (dx2) * (dy1) * (dz2) + - V001 * (dx2) * (dy2) * (dz1) + - V101 * (dx1) * (dy2) * (dz1) + - V011 * (dx2) * (dy1) * (dz1) + - V110 * (dx1) * (dy1) * (dz2) + - V111 * (dx1) * (dy1) * (dz1); - - /* resampled voxel saved in the unrolled clipped volume */ - imageD[i] = (int)(vs*scale[(int)zp]) + offset[(int)zp]; - - /* - * x gradient voxel. for no resample dz1, dy1 = 0.0 and - * dy2, dz2 = 1.0 so gradX = V100 - V000 - */ - - /* d/d(dx1) = 1.0, d/d(dx2) = -1.0 */ - gradX = V000 * (-1.0) * (dy2) * (dz2) + - V100 * (1.0) * (dy2) * (dz2) + - V010 * (-1.0) * (dy1) * (dz2) + - V001 * (-1.0) * (dy2) * (dz1) + - V101 * (1.0) * (dy2) * (dz1) + - V011 * (-1.0) * (dy1) * (dz1) + - V110 * (1.0) * (dy1) * (dz2) + - V111 * (1.0) * (dy1) * (dz1); - - /* d/d(dy1) = 1.0, d/d(dy2) = -1.0 */ - gradY = V000 * (dx2) * (-1.0) * (dz2) + - V100 * (dx1) * (-1.0) * (dz2) + - V010 * (dx2) * (1.0) * (dz2) + - V001 * (dx2) * (-1.0) * (dz1) + - V101 * (dx1) * (-1.0) * (dz1) + - V011 * (dx2) * (1.0) * (dz1) + - V110 * (dx1) * (1.0) * (dz2) + - V111 * (dx1) * (1.0) * (dz1); - - /* d/d(dz1) = 1.0, d/d(dz2) = -1.0 */ - gradZ = V000 * (dx2) * (dy2) * (-1.0) + - V100 * (dx1) * (dy2) * (-1.0) + - V010 * (dx2) * (dy1) * (-1.0) + - V001 * (dx2) * (dy2) * (1.0) + - V101 * (dx1) * (dy2) * (1.0) + - V011 * (dx2) * (dy1) * (1.0) + - V110 * (dx1) * (dy1) * (-1.0) + - V111 * (dx1) * (dy1) * (1.0); - - /* gradients saved in the unrolled clipped gradient volume */ - gradientX[i] = (gradX*scale[(int)zp]); - gradientY[i] = (gradY*scale[(int)zp]); - gradientZ[i] = (gradZ*scale[(int)zp]); - - } - - } - - status = 1; - - return status; - -} - - - -int NI_Resample_Coords(int size, int layersS, int rowsS, int colsS, int layersD, int rowsD, - int colsD, int *dimSteps, double *X, double *Y, double *Z, - unsigned char *imageD, unsigned char *imageS, double *scale, int *offset) -{ - - int i; - int status; - int sliceSizeD; - int dimsS[3]; - int dimsD[3]; - int dims[2]; - float vs; - float xp, yp, zp; - float dx1, dy1, dz1; - float dx2, dy2, dz2; - - int ptr_x0; - int ptr_y0; - int ptr_z0; - int ptr_x1; - int ptr_y1; - int ptr_z1; - // - // Vxyz for [0,1] values of x, y, z - // - int V000; - int V100; - int V010; - int V001; - int V011; - int V101; - int V110; - int V111; - float valueXYZ; - - sliceSizeD = rowsD * colsD; - dimsD[0] = colsD; - dimsD[1] = rowsD; - dimsD[2] = layersD; - dimsS[0] = colsS; - dimsS[1] = rowsS; - dimsS[2] = layersS; - - dims[0] = dimsS[0]; - dims[1] = dimsS[0]*dimsS[1]; - - for(i = 0; i < size; ++i){ - // get the 'from' unrolled coordinates - zp = Z[i]; - yp = Y[i]; - xp = X[i]; - - // clip the resample window - if((zp >= 0.0 && zp < layersS-dimSteps[2]) && - (yp >= 0.0 && yp < rowsS-dimSteps[1]) && - (xp >= 0.0 && xp < colsS-dimSteps[0])){ - - // corners of the 3D unit volume cube - ptr_z0 = (int)zp * dims[1]; - ptr_z1 = ptr_z0 + dims[1]; - ptr_y0 = (int)yp * dims[0]; - ptr_y1 = ptr_y0 + dims[0]; - ptr_x0 = (int)xp; - ptr_x1 = ptr_x0 + 1; - - dx1 = xp - (int)xp; - dy1 = yp - (int)yp; - dz1 = zp - (int)zp; - dx2 = 1.0 - dx1; - dy2 = 1.0 - dy1; - dz2 = 1.0 - dz1; - - V000 = imageS[ptr_x0+ptr_y0+ptr_z0]; - V100 = imageS[ptr_x1+ptr_y0+ptr_z0]; - V010 = imageS[ptr_x0+ptr_y1+ptr_z0]; - V001 = imageS[ptr_x0+ptr_y0+ptr_z1]; - V011 = imageS[ptr_x0+ptr_y1+ptr_z1]; - V101 = imageS[ptr_x1+ptr_y0+ptr_z1]; - V110 = imageS[ptr_x1+ptr_y1+ptr_z0]; - V111 = imageS[ptr_x1+ptr_y1+ptr_z1]; - - vs = V000 * (dx2) * (dy2) * (dz2) + - V100 * (dx1) * (dy2) * (dz2) + - V010 * (dx2) * (dy1) * (dz2) + - V001 * (dx2) * (dy2) * (dz1) + - V101 * (dx1) * (dy2) * (dz1) + - V011 * (dx2) * (dy1) * (dz1) + - V110 * (dx1) * (dy1) * (dz2) + - V111 * (dx1) * (dy1) * (dz1); - - /* resampled voxel saved in the unrolled clipped volume */ - imageD[i] = (int)(vs*scale[(int)zp]) + offset[(int)zp]; - } - - } - - status = 1; - - return status; - -} - - - -int NI_LT_Mrqcof(double *alpha, double *beta, double *V, double wt, double value, int M1){ - - int i, j; - double v1; - int status; - - for(i = 0; i < M1; ++i){ - v1 = V[i]; - beta[i] = v1 * value * wt; - for(j = 0; j <= i; ++j){ - alpha[M1*i+j] = v1 * V[j]; - } - } - - status = 1; - - return status; - -} - - -int NI_LT_Tensor_Product(double *alpha_1, double *alpha_2, double *beta_1, double *beta_2, double *basis, - int M1, int M2, int rows, int row_number, int coeff_1, int coeff_2){ - - - // - // lower triangular tensor product - // - - int i, j, k, m; - int loop3_outer, loop3_inner; - int status; - double wt1; - double wt2; - double *ptr1; - double *ptr2; - - for(i = 0; i < coeff_1; ++i){ - wt1 = basis[rows*i + row_number]; - for(loop3_outer = 0; loop3_outer < 3; ++loop3_outer){ - // - // spatial-spatial covariances - // - for(loop3_inner = 0; loop3_inner <= loop3_outer; ++loop3_inner){ - for(j = 0; j <= i; ++j){ - // - // outer product of basis array - // - wt2 = wt1 * basis[rows*j + row_number]; - ptr1 = &alpha_1[coeff_2*(M1*(coeff_1*loop3_outer+i)+(coeff_1*loop3_inner)+j)]; - ptr2 = &alpha_2[coeff_2*(M2*loop3_outer+loop3_inner)]; - for(k = 0; k < coeff_2; ++k){ - for(m = 0; m <= k; ++m){ - ptr1[M1*k+m] += (wt2 * ptr2[M2*k+m]); - } - } - } - // - // spatial-intensity covariances (single G volume assumed) - // - ptr1 = &alpha_1[coeff_2*(M1*coeff_1*3+(coeff_1*loop3_inner)+i)]; - ptr2 = &alpha_2[coeff_2*(M2*3+loop3_outer)]; - for(k = 0; k < coeff_2; ++k){ - ptr1[M1+k] += (wt1 * ptr2[M2+k]); - } - // - // spatial component of beta - // - for(k = 0; k < coeff_2; ++k){ - beta_1[k+coeff_2*(coeff_1*loop3_outer+i)] += (wt1 * beta_2[coeff_2*loop3_outer+k]); - } - } - } - } - - // - // intensity-intensity covariances - // - ptr1 = &alpha_1[coeff_2*(M1*coeff_1*3+(coeff_1*3))]; - ptr2 = &alpha_2[coeff_2*(M2*3+3)]; - for(k = 0; k < coeff_2; ++k){ - ptr1[k] += ptr2[k]; - } - - // - // intensity component of beta - // - - beta_1[coeff_2*coeff_1*3] += beta_2[coeff_2*3]; - - status = 1; - - return status; - -} - - - -int NI_Complete_Symmetry(double *Alpha, int nx, int ny, int nz, int ni4){ - - // - // complete symmetry of Alpha matrix over the 3D brain volume - // - - int z1, z2; - int y1, y2; - int x1, x2; - int loop3_outer, loop3_inner; - int M1; - int status; - double *ptrx; - double *ptry; - double *ptrz; - - M1 = 3*nx*ny*nz + ni4; - - for(loop3_outer = 0; loop3_outer < 3; ++loop3_outer){ - for(loop3_inner = 0; loop3_inner <= loop3_outer; ++loop3_inner){ - ptrz = &Alpha[nx*ny*nz*(M1*loop3_outer+loop3_inner)]; - for(z1 = 0; z1 < nz; ++z1){ - for(z2 = 0; z2 <= z1; ++z2){ - ptry = ptrz + nx*ny*(M1*z1 + z2); - for(y1 = 0; y1 < ny; ++y1){ - for(y2 = 0; y2 <= y1; ++y2){ - ptrx = ptry + nx*(M1*y1 + y2); - for(x1 = 0; x1 <= nx; ++x1){ - for(y2 = 0; y2 <= y1; ++y2){ - ptrx[M1*x2+x1] = ptrx[M1*x1+x2]; - } - } - } - } - for(x1 = 0; x1 < nx*ny; ++x1){ - for(x2 = 0; x2 < x1; ++x2){ - ptry[M1*x2+x1] = ptry[M1*x1+x2]; - } - } - } - for(x1 = 0; x1 < nx*ny*nz; ++x1){ - for(x2 = 0; x2 < x1; ++x2){ - ptrz[M1*x2+x1] = ptrz[M1*x1+x2]; - } - } - - } - } - } - - for(x1 = 0; x1 < nx*ny*nz*3+ni4; ++x1){ - for(x2 = 0; x2 < x1; ++x2){ - Alpha[M1*x2+x1] = Alpha[M1*x1+x2]; - } - } - - - status = 1; - - return status; - -} - - - - +#include +#include + +float tri_cubic_convolve(unsigned char *pVolume, int x, int y, int z, float xp, float yp, + float zp, int colsG, int rowsG, int layersG, int sliceSizeG){ + + int i, j, k; + int layerOffsets[4]; + int rowOffsets[4]; + float ps1, ps2, ps3; + float Y[4], NewRow[4], NewLayer[4]; + float R, C, L, D, T; + float valueXYZ = 0.0; + float dataCube[4][4][4]; + /* [cols][rows][layers] */ + + rowOffsets[0] = (y-1)*colsG; + rowOffsets[1] = (y )*colsG; + rowOffsets[2] = (y+1)*colsG; + rowOffsets[3] = (y+2)*colsG; + + layerOffsets[0] = (z-1)*sliceSizeG; + layerOffsets[1] = (z )*sliceSizeG; + layerOffsets[2] = (z+1)*sliceSizeG; + layerOffsets[3] = (z+2)*sliceSizeG; + + /* get numerator for interpolation */ + C = xp - (float)x; + R = yp - (float)y; + L = zp - (float)z; + D = (float)0.002; + + /* get 4x4 window over all 4 layers */ + for(i = 0; i < 4; ++i){ + for(j = 0; j < 4; ++j){ + dataCube[0][j][i] = (float)pVolume[layerOffsets[i]+rowOffsets[j]+x-1]; + dataCube[1][j][i] = (float)pVolume[layerOffsets[i]+rowOffsets[j]+x]; + dataCube[2][j][i] = (float)pVolume[layerOffsets[i]+rowOffsets[j]+x+1]; + dataCube[3][j][i] = (float)pVolume[layerOffsets[i]+rowOffsets[j]+x+2]; + } + } + + for(i = 0; i < 4; ++i){ + /* interpolate 4 rows in all 4 layers */ + for(j = 0; j < 4; ++j){ + if(C > D){ + Y[0] = dataCube[0][j][i]; + Y[1] = dataCube[1][j][i]; + Y[2] = dataCube[2][j][i]; + Y[3] = dataCube[3][j][i]; + ps1 = Y[2] - Y[0]; + ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; + ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; + NewRow[j] = Y[1]+C*(ps1+C*(ps2+C*ps3)); + } + else{ + NewRow[j] = dataCube[1][j][i]; + } + } + /* interpolate across 4 columns */ + if(R > D){ + Y[0] = NewRow[0]; + Y[1] = NewRow[1]; + Y[2] = NewRow[2]; + Y[3] = NewRow[3]; + ps1 = Y[2] - Y[0]; + ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; + ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; + T = (Y[1]+R*(ps1+R*(ps2+R*ps3))); + NewLayer[i] = T; + } + else{ + T = NewRow[1]; + NewLayer[i] = T; + } + } + /* interpolate across 4 layers */ + if(L > D){ + Y[0] = NewLayer[0]; + Y[1] = NewLayer[1]; + Y[2] = NewLayer[2]; + Y[3] = NewLayer[3]; + ps1 = Y[2] - Y[0]; + ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; + ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; + T = (Y[1]+L*(ps1+L*(ps2+L*ps3))); + valueXYZ = T; + } + else{ + T = NewLayer[1]; + valueXYZ = T; + } + + return(valueXYZ); + +} + +float trilinear_A(unsigned char *pVolume, int x, int y, int z, float dx, float dy, float dz, int dims[]){ + + // Vxyz for [0,1] values of x, y, z + int V000; + int V100; + int V010; + int V001; + int V011; + int V101; + int V110; + int V111; + + int ptr_x0; + int ptr_y0; + int ptr_z0; + + int ptr_x1; + int ptr_y1; + int ptr_z1; + + float valueXYZ; + + ptr_x0 = x; + ptr_y0 = y * dims[0]; + ptr_z0 = z * dims[1]; + + ptr_x1 = ptr_x0 + 1; + ptr_y1 = ptr_y0 + dims[0]; + ptr_z1 = ptr_z0 + dims[1]; + + V000 = pVolume[ptr_x0+ptr_y0+ptr_z0]; + V100 = pVolume[ptr_x1+ptr_y0+ptr_z0]; + V010 = pVolume[ptr_x0+ptr_y1+ptr_z0]; + V001 = pVolume[ptr_x0+ptr_y0+ptr_z1]; + V011 = pVolume[ptr_x0+ptr_y1+ptr_z1]; + V101 = pVolume[ptr_x1+ptr_y0+ptr_z1]; + V110 = pVolume[ptr_x1+ptr_y1+ptr_z0]; + V111 = pVolume[ptr_x1+ptr_y1+ptr_z1]; + + // dx, dy, dz are increments in x, y, z + // dx = 0 is x = 1 as x, y and z are [0, 1] in range + + valueXYZ = + V000 * (1.0-dx) * (1.0 - dy) * (1.0 - dz) + + V100 * (dx) * (1.0 - dy) * (1.0 - dz) + + V010 * (1.0-dx) * (dy) * (1.0 - dz) + + V001 * (1.0-dx) * (1.0 - dy) * (dz) + + V101 * (dx) * (1.0 - dy) * (dz) + + V011 * (1.0-dx) * (dy) * (dz) + + V110 * (dx) * (dy) * (1.0 - dz) + + V111 * (dx) * (dy) * (dz); + + + return(valueXYZ); + +} + +float trilinear_B(unsigned char *pVolume, float dx, float dy, float dz, int corners[]){ + + // Vxyz for [0,1] values of x, y, z + int V000; + int V100; + int V010; + int V001; + int V011; + int V101; + int V110; + int V111; + + int ptr_x0 = corners[0]; + int ptr_y0 = corners[1]; + int ptr_z0 = corners[2]; + + int ptr_x1 = corners[3]; + int ptr_y1 = corners[4]; + int ptr_z1 = corners[5]; + + float valueXYZ; + + V000 = pVolume[ptr_x0+ptr_y0+ptr_z0]; + V100 = pVolume[ptr_x1+ptr_y0+ptr_z0]; + V010 = pVolume[ptr_x0+ptr_y1+ptr_z0]; + V001 = pVolume[ptr_x0+ptr_y0+ptr_z1]; + V011 = pVolume[ptr_x0+ptr_y1+ptr_z1]; + V101 = pVolume[ptr_x1+ptr_y0+ptr_z1]; + V110 = pVolume[ptr_x1+ptr_y1+ptr_z0]; + V111 = pVolume[ptr_x1+ptr_y1+ptr_z1]; + + // dx, dy, dz are increments in x, y, z + // dx = 0 is x = 1 as x, y and z are [0, 1] in range + + valueXYZ = + V000 * (1.0-dx) * (1.0 - dy) * (1.0 - dz) + + V100 * (dx) * (1.0 - dy) * (1.0 - dz) + + V010 * (1.0-dx) * (dy) * (1.0 - dz) + + V001 * (1.0-dx) * (1.0 - dy) * (dz) + + V101 * (dx) * (1.0 - dy) * (dz) + + V011 * (1.0-dx) * (dy) * (dz) + + V110 * (dx) * (dy) * (1.0 - dz) + + V111 * (dx) * (dy) * (dz); + + + return(valueXYZ); + +} + +int NI_Histogram2D(int layersF, int rowsF, int colsF, int layersG, int rowsG, int colsG, + int *dimSteps, double *M, unsigned char *imageG, unsigned char *imageF, double *H) +{ + + int status; + int seed; + int dimsF[3]; + int dimsG[3]; + int dims_F[2]; + int dims_G[2]; + int ivf, ivg; + float ran_x, ran_y, ran_z; + float vf, delta; + float x, y, z; + float dx, dy, dz; + float xp, yp, zp; + float rx, ry, rz; + + dimsF[0] = colsF; + dimsF[1] = rowsF; + dimsF[2] = layersF; + dimsG[0] = colsG; + dimsG[1] = rowsG; + dimsG[2] = layersG; + + dims_G[0] = dimsG[0]; + dims_G[1] = dimsG[0]*dimsG[1]; + dims_F[0] = dimsF[0]; + dims_F[1] = dimsF[0]*dimsF[1]; + + seed = 1000; + srand(seed); + + /* because of stochastic sampling, subtract 1 from upper bounds */ + for(z = 0.0; z < layersG-dimSteps[2]-1; z += dimSteps[2]){ + for(y = 0.0; y < rowsG-dimSteps[1]-1; y += dimSteps[1]){ + for(x = 0.0; x < colsG-dimSteps[0]-1; x += dimSteps[0]){ + /* positive jitter the x, y, z values */ + ran_x = 1.0 * rand()/((float)RAND_MAX); + ran_y = 1.0 * rand()/((float)RAND_MAX); + ran_z = 1.0 * rand()/((float)RAND_MAX); + dx = x + ran_x*dimSteps[0]; + dy = y + ran_y*dimSteps[1]; + dz = z + ran_z*dimSteps[2]; + + /* get the 'from' coordinates */ + xp = M[0]*dx + M[1]*dy + M[2]*dz + M[3]; + yp = M[4]*dx + M[5]*dy + M[6]*dz + M[7]; + zp = M[8]*dx + M[9]*dy + M[10]*dz + M[11]; + /* clip the resample window */ + if((zp >= 0.0 && zp < layersF-dimSteps[2]) && + (yp >= 0.0 && yp < rowsF-dimSteps[1]) && + (xp >= 0.0 && xp < colsF-dimSteps[0])){ + /* resample the coordinates using a trilinear interpolation */ + /* resample imageF using the rotated-jittered xyz coordinates */ + rx = xp - (int)xp; + ry = yp - (int)yp; + rz = zp - (int)zp; + //vf = trilinear_A(imageF, (int)dx, (int)dy, (int)dz, rx, ry, rz, dims_F); + vf = trilinear_A(imageF, (int)xp, (int)yp, (int)zp, rx, ry, rz, dims_F); + /* floor */ + ivf = (int)vf; + delta = vf - ivf; + /* resample imageG using the jittered xyz coordinates */ + rx = dx - (int)dx; + ry = dy - (int)dy; + rz = dz - (int)dz; + ivg = (int)trilinear_A(imageG, (int)dx, (int)dy, (int)dz, rx, ry, rz, dims_G); + //ivg = (int)trilinear_A(imageG, (int)xp, (int)yp, (int)zp, rx, ry, rz, dims_G); + /* ivf will be < 255 as 8 bit data and trilinear doesn't ring */ + H[ivf+256*ivg] += 1.0 - delta; + if(ivf < 255){ + H[ivf+1+256*ivg] += delta; + } + } + } + } + } + + status = 1; + + return status; + +} + + +int NI_Histogram2DLite(int layersF, int rowsF, int colsF, int layersG, int rowsG, int colsG, + int *dimSteps, double *M, unsigned char *imageG, unsigned char *imageF, double *H) +{ + + int i; + int status; + int sliceG; + int rowG; + int sliceSizeG; + int dimsF[3]; + int dimsG[3]; + int dims[2]; + int ivf, ivg; + float vf, delta; + float x, y, z; + float xp, yp, zp; + float dx, dy, dz; + + int ptr_x0; + int ptr_y0; + int ptr_z0; + int ptr_x1; + int ptr_y1; + int ptr_z1; + // + // Vxyz for [0,1] values of x, y, z + // + int V000; + int V100; + int V010; + int V001; + int V011; + int V101; + int V110; + int V111; + int g[64], f[64]; + float valueXYZ; + + // + // G is fixed; F is rotated + // + sliceSizeG = rowsG * colsG; + dimsF[0] = colsF; + dimsF[1] = rowsF; + dimsF[2] = layersF; + dimsG[0] = colsG; + dimsG[1] = rowsG; + dimsG[2] = layersG; + + dims[0] = dimsF[0]; + dims[1] = dimsF[0]*dimsF[1]; + + for(z = 0.0; z < layersG-dimSteps[2]-1; z += dimSteps[2]){ + sliceG = (int)z * sliceSizeG; + for(y = 0.0; y < rowsG-dimSteps[1]-1; y += dimSteps[1]){ + rowG = (int)y * colsG; + for(x = 0.0; x < colsG-dimSteps[0]-1; x += dimSteps[0]){ + // get the 'from' coordinates + xp = M[0]*x + M[1]*y + M[2]*z + M[3]; + yp = M[4]*x + M[5]*y + M[6]*z + M[7]; + zp = M[8]*x + M[9]*y + M[10]*z + M[11]; + // clip the resample window + if((zp >= 0.0 && zp < layersF-dimSteps[2]) && + (yp >= 0.0 && yp < rowsF-dimSteps[1]) && + (xp >= 0.0 && xp < colsF-dimSteps[0])){ + + // corners of the 3D unit volume cube + ptr_z0 = (int)zp * dims[1]; + ptr_z1 = ptr_z0 + dims[1]; + ptr_y0 = (int)yp * dims[0]; + ptr_y1 = ptr_y0 + dims[0]; + ptr_x0 = (int)xp; + ptr_x1 = ptr_x0 + 1; + dx = xp - (int)xp; + dy = yp - (int)yp; + dz = zp - (int)zp; + + // imageG is not rotated. sample the given x,y,z + ivg = imageG[sliceG+rowG+(int)x]; + // imageF IS rotated. sample the rotated xp,yp,zp + V000 = imageF[ptr_x0+ptr_y0+ptr_z0]; + V100 = imageF[ptr_x1+ptr_y0+ptr_z0]; + V010 = imageF[ptr_x0+ptr_y1+ptr_z0]; + V001 = imageF[ptr_x0+ptr_y0+ptr_z1]; + V011 = imageF[ptr_x0+ptr_y1+ptr_z1]; + V101 = imageF[ptr_x1+ptr_y0+ptr_z1]; + V110 = imageF[ptr_x1+ptr_y1+ptr_z0]; + V111 = imageF[ptr_x1+ptr_y1+ptr_z1]; + + vf = V000 * (1.0-dx) * (1.0 - dy) * (1.0 - dz) + + V100 * (dx) * (1.0 - dy) * (1.0 - dz) + + V010 * (1.0-dx) * (dy) * (1.0 - dz) + + V001 * (1.0-dx) * (1.0 - dy) * (dz) + + V101 * (dx) * (1.0 - dy) * (dz) + + V011 * (1.0-dx) * (dy) * (dz) + + V110 * (dx) * (dy) * (1.0 - dz) + + V111 * (dx) * (dy) * (dz); + + ivf = (int)(vf); + H[ivf+256*ivg] += 1.0; + } + } + } + } + + status = 1; + + return status; + +} + + +int NI_LinearResample(int layersF, int rowsF, int colsF, int layersG, int rowsG, int colsG, + int *dimSteps, double *M, unsigned char *imageG, unsigned char *imageF) +{ + + int i; + int status; + int sliceG; + int rowG; + int sliceSizeG; + int dimsF[3]; + int dimsG[3]; + int dims[2]; + int ivf, ivg; + float vf, delta; + float x, y, z; + float xp, yp, zp; + float dx, dy, dz; + + int ptr_x0; + int ptr_y0; + int ptr_z0; + int ptr_x1; + int ptr_y1; + int ptr_z1; + // + // Vxyz for [0,1] values of x, y, z + // + int V000; + int V100; + int V010; + int V001; + int V011; + int V101; + int V110; + int V111; + float valueXYZ; + + // + // G is fixed; F is rotated + // + sliceSizeG = rowsG * colsG; + dimsF[0] = colsF; + dimsF[1] = rowsF; + dimsF[2] = layersF; + dimsG[0] = colsG; + dimsG[1] = rowsG; + dimsG[2] = layersG; + + dims[0] = dimsF[0]; + dims[1] = dimsF[0]*dimsF[1]; + + for(z = 0.0; z < layersG-dimSteps[2]-1; z += dimSteps[2]){ + sliceG = (int)z * sliceSizeG; + for(y = 0.0; y < rowsG-dimSteps[1]-1; y += dimSteps[1]){ + rowG = (int)y * colsG; + for(x = 0.0; x < colsG-dimSteps[0]-1; x += dimSteps[0]){ + // get the 'from' coordinates + xp = M[0]*x + M[1]*y + M[2]*z + M[3]; + yp = M[4]*x + M[5]*y + M[6]*z + M[7]; + zp = M[8]*x + M[9]*y + M[10]*z + M[11]; + // clip the resample window + if((zp >= 0.0 && zp < layersF-dimSteps[2]) && + (yp >= 0.0 && yp < rowsF-dimSteps[1]) && + (xp >= 0.0 && xp < colsF-dimSteps[0])){ + + // corners of the 3D unit volume cube + ptr_z0 = (int)zp * dims[1]; + ptr_z1 = ptr_z0 + dims[1]; + ptr_y0 = (int)yp * dims[0]; + ptr_y1 = ptr_y0 + dims[0]; + ptr_x0 = (int)xp; + ptr_x1 = ptr_x0 + 1; + dx = xp - (int)xp; + dy = yp - (int)yp; + dz = zp - (int)zp; + + // imageF IS rotated. sample the rotated xp,yp,zp + // and stored in imageG + V000 = imageF[ptr_x0+ptr_y0+ptr_z0]; + V100 = imageF[ptr_x1+ptr_y0+ptr_z0]; + V010 = imageF[ptr_x0+ptr_y1+ptr_z0]; + V001 = imageF[ptr_x0+ptr_y0+ptr_z1]; + V011 = imageF[ptr_x0+ptr_y1+ptr_z1]; + V101 = imageF[ptr_x1+ptr_y0+ptr_z1]; + V110 = imageF[ptr_x1+ptr_y1+ptr_z0]; + V111 = imageF[ptr_x1+ptr_y1+ptr_z1]; + + vf = V000 * (1.0-dx) * (1.0 - dy) * (1.0 - dz) + + V100 * (dx) * (1.0 - dy) * (1.0 - dz) + + V010 * (1.0-dx) * (dy) * (1.0 - dz) + + V001 * (1.0-dx) * (1.0 - dy) * (dz) + + V101 * (dx) * (1.0 - dy) * (dz) + + V011 * (1.0-dx) * (dy) * (dz) + + V110 * (dx) * (dy) * (1.0 - dz) + + V111 * (dx) * (dy) * (dz); + + imageG[sliceG+rowG+(int)x] = (int)vf; + + } + } + } + } + + status = 1; + + return status; + +} + + + +int NI_VolumeResample(int layersS, int rowsS, int colsS, int layersD, int rowsD, int colsD, + int scale, int mode, unsigned char *imageD, unsigned char *imageS, double *Z) +{ + + int i; + int x, y, z; + int sliceSizeSrc; + int sliceSizeDst; + int status; + int ivf; + int xf, xg, yg, zg; + int g_slice, f_slice; + int g_row, f_row; + int g_slicesize, f_slicesize; + int itemp, sOffset, dOffset; + int XInt, YInt, ZInt; + float ps1, ps2, ps3; + float Y[4], tpoint, reSampler; + float XPrime, YPrime, ZPrime; + float C, R, L; + float *RLUT; + float *samples; + + if(mode ==1){ + /* + * integer subsample + */ + g_slicesize = rowsD * colsD; + f_slicesize = rowsS * colsS; + for(zg = 0; zg < layersD; ++zg){ + g_slice = zg * g_slicesize; + f_slice = zg * scale * f_slicesize; + for(yg = 0; yg < rowsD; ++yg){ + g_row = yg * colsD; + f_row = yg * scale * colsS; + for(xg = 0; xg < colsD; ++xg){ + xf = xg * scale; + ivf = imageS[f_slice+f_row+xf]; + imageD[g_slice+g_row+xg] = ivf; + } + } + } + } + else if(mode ==2){ + /* + * fractional cubic convolution resample + */ + + /* first resample each column in all rows and all layers */ + + sliceSizeSrc = colsS * rowsS; + sliceSizeDst = colsD * rowsD; + + RLUT = calloc(colsD, sizeof(float)); + samples = calloc(colsS+4, sizeof(float)); + reSampler = (float)1.0/Z[0]; + tpoint = (float)0.0; + for(i = 0; i < colsD; ++i){ + RLUT[i] = tpoint; + tpoint += reSampler; + } + + for(z = 0; z < layersS; ++z){ + sOffset = z * sliceSizeSrc; + dOffset = z * sliceSizeDst; + for(y = 0; y < rowsS; ++y){ + for(x = 0; x < colsS; ++x){ + samples[x] = (float)imageS[sOffset+x]; + } + for(x = 1; x < colsD; ++x){ + XPrime = RLUT[x]; + XInt = (int)XPrime; + C = XPrime - (float)XInt; + Y[0] = samples[XInt-1]; + Y[1] = samples[XInt]; + Y[2] = samples[XInt+1]; + Y[3] = samples[XInt+2]; + ps1 = Y[2] - Y[0]; + ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; + ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; + itemp = (int)(Y[1]+C*(ps1+C*(ps2+C*ps3))); + if(itemp < 0) itemp = 0; + if(itemp > 255) itemp = 255; + imageD[dOffset+x] = itemp; + } + sOffset += colsS; + dOffset += colsD; + } + } + free(RLUT); + free(samples); + + /* second resample each row in all columns and all layers */ + RLUT = calloc(rowsD, sizeof(float)); + samples = calloc(rowsS+4, sizeof(float)); + reSampler = (float)1.0/Z[1]; + tpoint = (float)0.0; + for(i = 0; i < rowsD; ++i){ + RLUT[i] = tpoint; + tpoint += reSampler; + } + + for(z = 0; z < layersS; ++z){ + dOffset = z * sliceSizeDst; + for(x = 0; x < colsD; ++x){ + for(y = 0; y < rowsS; ++y){ + samples[y] = (float)imageD[dOffset+x+y*colsD]; + } + for(y = 1; y < rowsD; ++y){ + YPrime = RLUT[y]; + YInt = (int)YPrime; + R = YPrime - (float)YInt; + Y[0] = samples[YInt-1]; + Y[1] = samples[YInt]; + Y[2] = samples[YInt+1]; + Y[3] = samples[YInt+2]; + ps1 = Y[2] - Y[0]; + ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; + ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; + itemp = (int)(Y[1]+R*(ps1+R*(ps2+R*ps3))); + if(itemp < 0) itemp = 0; + if(itemp > 255) itemp = 255; + imageD[dOffset+x+y*colsD] = itemp; + } + } + } + free(RLUT); + free(samples); + + /* third resample each layers in all columns and all rows */ + RLUT = calloc(layersD, sizeof(float)); + samples = calloc(layersS+4, sizeof(float)); + reSampler = (float)1.0/Z[2]; + tpoint = (float)0.0; + for(i = 0; i < layersD; ++i){ + RLUT[i] = tpoint; + tpoint += reSampler; + } + + for(y = 0; y < rowsD; ++y){ + dOffset = y * colsD; + for(x = 0; x < colsD; ++x){ + for(z = 0; z < layersS; ++z){ + samples[z] = (float)imageD[dOffset+x+z*sliceSizeDst]; + } + for(z = 1; z < layersD; ++z){ + ZPrime = RLUT[z]; + ZInt = (int)ZPrime; + L = ZPrime - (float)ZInt; + Y[0] = samples[ZInt-1]; + Y[1] = samples[ZInt]; + Y[2] = samples[ZInt+1]; + Y[3] = samples[ZInt+2]; + ps1 = Y[2] - Y[0]; + ps2 = (float)2.0*(Y[0] - Y[1]) + Y[2] - Y[3]; + ps3 = -Y[0] + Y[1] - Y[2] + Y[3]; + itemp = (int)(Y[1]+R*(ps1+R*(ps2+R*ps3))); + if(itemp < 0) itemp = 0; + if(itemp > 255) itemp = 255; + imageD[dOffset+x+z*sliceSizeDst] = itemp; + } + } + } + free(RLUT); + free(samples); + } + + status = 1; + + return status; + +} + + +int NI_CubicResample(int layersF, int rowsF, int colsF, int layersG, int rowsG, int colsG, + int *dimSteps, double *M, unsigned char *imageG, unsigned char *imageF) +{ + + int i; + int status; + int sliceG; + int rowG; + int sliceSizeG; + int ivf; + float vf; + float x, y, z; + float xp, yp, zp; + + sliceSizeG = rowsG * colsG; + for(z = 1.0; z < layersG-dimSteps[2]-2; z += dimSteps[2]){ + sliceG = (int)z * sliceSizeG; + for(y = 1.0; y < rowsG-dimSteps[1]-2; y += dimSteps[1]){ + rowG = (int)y * colsG; + for(x = 1.0; x < colsG-dimSteps[0]-2; x += dimSteps[0]){ + // get the 'from' coordinates + xp = M[0]*x + M[1]*y + M[2]*z + M[3]; + yp = M[4]*x + M[5]*y + M[6]*z + M[7]; + zp = M[8]*x + M[9]*y + M[10]*z + M[11]; + // clip the resample window + if((zp >= 1.0 && zp < layersF-dimSteps[2]-2) && + (yp >= 1.0 && yp < rowsF-dimSteps[1]-2) && + (xp >= 1.0 && xp < colsF-dimSteps[0]-2)){ + vf = tri_cubic_convolve(imageF, (int)xp, (int)yp, (int)zp, xp, yp, + zp, colsG, rowsG, layersG, sliceSizeG); + /* clip at hard edges */ + if(vf < 0.0) vf = 0.0; + if(vf > 255.0) vf = 255.0; + imageG[sliceG+rowG+(int)x] = (int)vf; + } + } + } + } + + status = 1; + + return status; + +} + +int NI_ImageThreshold(int layers, int rows, int cols, unsigned short *image, double *H, + double *IH, int histogram_elements, double threshold, int *index) +{ + + int i, j, k; + int status; + int ptr; + int value; + float sum; + + for(i = 0; i < histogram_elements; ++i){ + H[i] = 0; + IH[i] = 0; + } + ptr = 0; + for(i = 0; i < layers; ++i){ + for(j = 0; j < rows; ++j){ + for(k = 0; k < cols; ++k){ + value = image[ptr++]; + ++H[value]; + } + } + } + + sum = 0.0; + for(i = 0; i < histogram_elements; ++i){ + sum += H[i]; + } + /* normalize the volume histogram */ + for(i = 0; i < histogram_elements; ++i){ + H[i] = H[i] / sum; + } + + /* build the integrated histogram */ + IH[0] = H[0]; + for(i = 1; i < histogram_elements; ++i){ + IH[i] = IH[i-1] + H[i]; + } + + /* get the threshold crossing. this deals with the high amplitude outliers in the volume */ + *index = histogram_elements-1; + for(i = 0; i < histogram_elements; ++i){ + if(IH[i] > threshold){ + *index = i; + break; + } + } + + status = 1; + + return status; + +} + + +int NI_ResampleWithGradient(int layersS, int rowsS, int colsS, int layersD, int rowsD, + int colsD, int *dimSteps, double *M, unsigned char *imageD, + unsigned char *imageS, double *scale, int *offset, double *gradientX, + double *gradientY, double *gradientZ) +{ + + int i; + int seed; + int status; + int sliceD; + int rowD; + int sliceSizeD; + int dimsS[3]; + int dimsD[3]; + int dims[2]; + float vs; + float x, y, z; + float xp, yp, zp; + float dx1, dy1, dz1; + float dx2, dy2, dz2; + float ran_x, ran_y, ran_z; + float dx, dy, dz; + double gradX, gradY, gradZ; + + int ptr_x0; + int ptr_y0; + int ptr_z0; + int ptr_x1; + int ptr_y1; + int ptr_z1; + // + // Vxyz for [0,1] values of x, y, z + // + int V000; + int V100; + int V010; + int V001; + int V011; + int V101; + int V110; + int V111; + float valueXYZ; + + sliceSizeD = rowsD * colsD; + dimsD[0] = colsD; + dimsD[1] = rowsD; + dimsD[2] = layersD; + dimsS[0] = colsS; + dimsS[1] = rowsS; + dimsS[2] = layersS; + + dims[0] = dimsS[0]; + dims[1] = dimsS[0]*dimsS[1]; + + seed = 1000; + srand(seed); + + for(z = 0.0; z < layersD-dimSteps[2]-1; z += dimSteps[2]){ + sliceD = (int)z * sliceSizeD; + for(y = 0.0; y < rowsD-dimSteps[1]-1; y += dimSteps[1]){ + rowD = (int)y * colsD; + for(x = 0.0; x < colsD-dimSteps[0]-1; x += dimSteps[0]){ + + /* jitter the coordinates to prevent aliasing */ + ran_x = 1.0 * rand()/((float)RAND_MAX); + ran_y = 1.0 * rand()/((float)RAND_MAX); + ran_z = 1.0 * rand()/((float)RAND_MAX); + + dx = x + ran_x; + dy = y + ran_y; + dz = z + ran_z; + + // get the 'from' coordinates + xp = M[0]*dx + M[1]*dy + M[2]*dz + M[3]; + yp = M[4]*dx + M[5]*dy + M[6]*dz + M[7]; + zp = M[8]*dx + M[9]*dy + M[10]*dz + M[11]; + // clip the resample window + if((zp >= 0.0 && zp < layersS-dimSteps[2]) && + (yp >= 0.0 && yp < rowsS-dimSteps[1]) && + (xp >= 0.0 && xp < colsS-dimSteps[0])){ + + // corners of the 3D unit volume cube + ptr_z0 = (int)zp * dims[1]; + ptr_z1 = ptr_z0 + dims[1]; + ptr_y0 = (int)yp * dims[0]; + ptr_y1 = ptr_y0 + dims[0]; + ptr_x0 = (int)xp; + ptr_x1 = ptr_x0 + 1; + + dx1 = xp - (int)xp; + dy1 = yp - (int)yp; + dz1 = zp - (int)zp; + dx2 = 1.0 - dx1; + dy2 = 1.0 - dy1; + dz2 = 1.0 - dz1; + + V000 = imageS[ptr_x0+ptr_y0+ptr_z0]; + V100 = imageS[ptr_x1+ptr_y0+ptr_z0]; + V010 = imageS[ptr_x0+ptr_y1+ptr_z0]; + V001 = imageS[ptr_x0+ptr_y0+ptr_z1]; + V011 = imageS[ptr_x0+ptr_y1+ptr_z1]; + V101 = imageS[ptr_x1+ptr_y0+ptr_z1]; + V110 = imageS[ptr_x1+ptr_y1+ptr_z0]; + V111 = imageS[ptr_x1+ptr_y1+ptr_z1]; + + vs = V000 * (dx2) * (dy2) * (dz2) + + V100 * (dx1) * (dy2) * (dz2) + + V010 * (dx2) * (dy1) * (dz2) + + V001 * (dx2) * (dy2) * (dz1) + + V101 * (dx1) * (dy2) * (dz1) + + V011 * (dx2) * (dy1) * (dz1) + + V110 * (dx1) * (dy1) * (dz2) + + V111 * (dx1) * (dy1) * (dz1); + + /* resampled voxel */ + imageD[sliceD+rowD+(int)x] = (int)(vs*scale[(int)zp]) + offset[(int)zp]; + + /* + * x gradient voxel. for no resample dz1, dy1 = 0.0 and + * dy2, dz2 = 1.0 so gradX = V100 - V000 + */ + + /* d/d(dx1) = 1.0, d/d(dx2) = -1.0 */ + gradX = V000 * (-1.0) * (dy2) * (dz2) + + V100 * (1.0) * (dy2) * (dz2) + + V010 * (-1.0) * (dy1) * (dz2) + + V001 * (-1.0) * (dy2) * (dz1) + + V101 * (1.0) * (dy2) * (dz1) + + V011 * (-1.0) * (dy1) * (dz1) + + V110 * (1.0) * (dy1) * (dz2) + + V111 * (1.0) * (dy1) * (dz1); + + /* d/d(dy1) = 1.0, d/d(dy2) = -1.0 */ + gradY = V000 * (dx2) * (-1.0) * (dz2) + + V100 * (dx1) * (-1.0) * (dz2) + + V010 * (dx2) * (1.0) * (dz2) + + V001 * (dx2) * (-1.0) * (dz1) + + V101 * (dx1) * (-1.0) * (dz1) + + V011 * (dx2) * (1.0) * (dz1) + + V110 * (dx1) * (1.0) * (dz2) + + V111 * (dx1) * (1.0) * (dz1); + + /* d/d(dz1) = 1.0, d/d(dz2) = -1.0 */ + gradZ = V000 * (dx2) * (dy2) * (-1.0) + + V100 * (dx1) * (dy2) * (-1.0) + + V010 * (dx2) * (dy1) * (-1.0) + + V001 * (dx2) * (dy2) * (1.0) + + V101 * (dx1) * (dy2) * (1.0) + + V011 * (dx2) * (dy1) * (1.0) + + V110 * (dx1) * (dy1) * (-1.0) + + V111 * (dx1) * (dy1) * (1.0); + + gradientX[sliceD+rowD+(int)x] = (gradX*scale[(int)zp]); + gradientY[sliceD+rowD+(int)x] = (gradY*scale[(int)zp]); + gradientZ[sliceD+rowD+(int)x] = (gradZ*scale[(int)zp]); + + } + } + } + } + + status = 1; + + return status; + +} + + +int NI_Resample_Gradient_Coords(int size, int layersS, int rowsS, int colsS, int layersD, int rowsD, + int colsD, int *dimSteps, double *X, double *Y, double *Z, + unsigned char *imageD, unsigned char *imageS, double *scale, + int *offset, double *gradientX, double *gradientY, double *gradientZ) +{ + + int i; + int status; + int sliceSizeD; + int dimsS[3]; + int dimsD[3]; + int dims[2]; + float vs; + float xp, yp, zp; + float dx1, dy1, dz1; + float dx2, dy2, dz2; + double gradX, gradY, gradZ; + + int ptr_x0; + int ptr_y0; + int ptr_z0; + int ptr_x1; + int ptr_y1; + int ptr_z1; + // + // Vxyz for [0,1] values of x, y, z + // + int V000; + int V100; + int V010; + int V001; + int V011; + int V101; + int V110; + int V111; + float valueXYZ; + + sliceSizeD = rowsD * colsD; + dimsD[0] = colsD; + dimsD[1] = rowsD; + dimsD[2] = layersD; + dimsS[0] = colsS; + dimsS[1] = rowsS; + dimsS[2] = layersS; + + dims[0] = dimsS[0]; + dims[1] = dimsS[0]*dimsS[1]; + + for(i = 0; i < size; ++i){ + // get the 'from' unrolled coordinates + zp = Z[i]; + yp = Y[i]; + xp = X[i]; + + // clip the resample window + if((zp >= 0.0 && zp < layersS-dimSteps[2]) && + (yp >= 0.0 && yp < rowsS-dimSteps[1]) && + (xp >= 0.0 && xp < colsS-dimSteps[0])){ + + // corners of the 3D unit volume cube + ptr_z0 = (int)zp * dims[1]; + ptr_z1 = ptr_z0 + dims[1]; + ptr_y0 = (int)yp * dims[0]; + ptr_y1 = ptr_y0 + dims[0]; + ptr_x0 = (int)xp; + ptr_x1 = ptr_x0 + 1; + + dx1 = xp - (int)xp; + dy1 = yp - (int)yp; + dz1 = zp - (int)zp; + dx2 = 1.0 - dx1; + dy2 = 1.0 - dy1; + dz2 = 1.0 - dz1; + + V000 = imageS[ptr_x0+ptr_y0+ptr_z0]; + V100 = imageS[ptr_x1+ptr_y0+ptr_z0]; + V010 = imageS[ptr_x0+ptr_y1+ptr_z0]; + V001 = imageS[ptr_x0+ptr_y0+ptr_z1]; + V011 = imageS[ptr_x0+ptr_y1+ptr_z1]; + V101 = imageS[ptr_x1+ptr_y0+ptr_z1]; + V110 = imageS[ptr_x1+ptr_y1+ptr_z0]; + V111 = imageS[ptr_x1+ptr_y1+ptr_z1]; + + vs = V000 * (dx2) * (dy2) * (dz2) + + V100 * (dx1) * (dy2) * (dz2) + + V010 * (dx2) * (dy1) * (dz2) + + V001 * (dx2) * (dy2) * (dz1) + + V101 * (dx1) * (dy2) * (dz1) + + V011 * (dx2) * (dy1) * (dz1) + + V110 * (dx1) * (dy1) * (dz2) + + V111 * (dx1) * (dy1) * (dz1); + + /* resampled voxel saved in the unrolled clipped volume */ + imageD[i] = (int)(vs*scale[(int)zp]) + offset[(int)zp]; + + /* + * x gradient voxel. for no resample dz1, dy1 = 0.0 and + * dy2, dz2 = 1.0 so gradX = V100 - V000 + */ + + /* d/d(dx1) = 1.0, d/d(dx2) = -1.0 */ + gradX = V000 * (-1.0) * (dy2) * (dz2) + + V100 * (1.0) * (dy2) * (dz2) + + V010 * (-1.0) * (dy1) * (dz2) + + V001 * (-1.0) * (dy2) * (dz1) + + V101 * (1.0) * (dy2) * (dz1) + + V011 * (-1.0) * (dy1) * (dz1) + + V110 * (1.0) * (dy1) * (dz2) + + V111 * (1.0) * (dy1) * (dz1); + + /* d/d(dy1) = 1.0, d/d(dy2) = -1.0 */ + gradY = V000 * (dx2) * (-1.0) * (dz2) + + V100 * (dx1) * (-1.0) * (dz2) + + V010 * (dx2) * (1.0) * (dz2) + + V001 * (dx2) * (-1.0) * (dz1) + + V101 * (dx1) * (-1.0) * (dz1) + + V011 * (dx2) * (1.0) * (dz1) + + V110 * (dx1) * (1.0) * (dz2) + + V111 * (dx1) * (1.0) * (dz1); + + /* d/d(dz1) = 1.0, d/d(dz2) = -1.0 */ + gradZ = V000 * (dx2) * (dy2) * (-1.0) + + V100 * (dx1) * (dy2) * (-1.0) + + V010 * (dx2) * (dy1) * (-1.0) + + V001 * (dx2) * (dy2) * (1.0) + + V101 * (dx1) * (dy2) * (1.0) + + V011 * (dx2) * (dy1) * (1.0) + + V110 * (dx1) * (dy1) * (-1.0) + + V111 * (dx1) * (dy1) * (1.0); + + /* gradients saved in the unrolled clipped gradient volume */ + gradientX[i] = (gradX*scale[(int)zp]); + gradientY[i] = (gradY*scale[(int)zp]); + gradientZ[i] = (gradZ*scale[(int)zp]); + + } + + } + + status = 1; + + return status; + +} + + + +int NI_Resample_Coords(int size, int layersS, int rowsS, int colsS, int layersD, int rowsD, + int colsD, int *dimSteps, double *X, double *Y, double *Z, + unsigned char *imageD, unsigned char *imageS, double *scale, int *offset) +{ + + int i; + int status; + int sliceSizeD; + int dimsS[3]; + int dimsD[3]; + int dims[2]; + float vs; + float xp, yp, zp; + float dx1, dy1, dz1; + float dx2, dy2, dz2; + + int ptr_x0; + int ptr_y0; + int ptr_z0; + int ptr_x1; + int ptr_y1; + int ptr_z1; + // + // Vxyz for [0,1] values of x, y, z + // + int V000; + int V100; + int V010; + int V001; + int V011; + int V101; + int V110; + int V111; + float valueXYZ; + + sliceSizeD = rowsD * colsD; + dimsD[0] = colsD; + dimsD[1] = rowsD; + dimsD[2] = layersD; + dimsS[0] = colsS; + dimsS[1] = rowsS; + dimsS[2] = layersS; + + dims[0] = dimsS[0]; + dims[1] = dimsS[0]*dimsS[1]; + + for(i = 0; i < size; ++i){ + // get the 'from' unrolled coordinates + zp = Z[i]; + yp = Y[i]; + xp = X[i]; + + // clip the resample window + if((zp >= 0.0 && zp < layersS-dimSteps[2]) && + (yp >= 0.0 && yp < rowsS-dimSteps[1]) && + (xp >= 0.0 && xp < colsS-dimSteps[0])){ + + // corners of the 3D unit volume cube + ptr_z0 = (int)zp * dims[1]; + ptr_z1 = ptr_z0 + dims[1]; + ptr_y0 = (int)yp * dims[0]; + ptr_y1 = ptr_y0 + dims[0]; + ptr_x0 = (int)xp; + ptr_x1 = ptr_x0 + 1; + + dx1 = xp - (int)xp; + dy1 = yp - (int)yp; + dz1 = zp - (int)zp; + dx2 = 1.0 - dx1; + dy2 = 1.0 - dy1; + dz2 = 1.0 - dz1; + + V000 = imageS[ptr_x0+ptr_y0+ptr_z0]; + V100 = imageS[ptr_x1+ptr_y0+ptr_z0]; + V010 = imageS[ptr_x0+ptr_y1+ptr_z0]; + V001 = imageS[ptr_x0+ptr_y0+ptr_z1]; + V011 = imageS[ptr_x0+ptr_y1+ptr_z1]; + V101 = imageS[ptr_x1+ptr_y0+ptr_z1]; + V110 = imageS[ptr_x1+ptr_y1+ptr_z0]; + V111 = imageS[ptr_x1+ptr_y1+ptr_z1]; + + vs = V000 * (dx2) * (dy2) * (dz2) + + V100 * (dx1) * (dy2) * (dz2) + + V010 * (dx2) * (dy1) * (dz2) + + V001 * (dx2) * (dy2) * (dz1) + + V101 * (dx1) * (dy2) * (dz1) + + V011 * (dx2) * (dy1) * (dz1) + + V110 * (dx1) * (dy1) * (dz2) + + V111 * (dx1) * (dy1) * (dz1); + + /* resampled voxel saved in the unrolled clipped volume */ + imageD[i] = (int)(vs*scale[(int)zp]) + offset[(int)zp]; + } + + } + + status = 1; + + return status; + +} + + + +int NI_LT_Mrqcof(double *alpha, double *beta, double *V, double wt, double value, int M1){ + + int i, j; + double v1; + int status; + + for(i = 0; i < M1; ++i){ + v1 = V[i]; + beta[i] = v1 * value * wt; + for(j = 0; j <= i; ++j){ + alpha[M1*i+j] = v1 * V[j]; + } + } + + status = 1; + + return status; + +} + + +int NI_LT_Tensor_Product(double *alpha_1, double *alpha_2, double *beta_1, double *beta_2, double *basis, + int M1, int M2, int rows, int row_number, int coeff_1, int coeff_2){ + + + // + // lower triangular tensor product + // + + int i, j, k, m; + int loop3_outer, loop3_inner; + int status; + double wt1; + double wt2; + double *ptr1; + double *ptr2; + + for(i = 0; i < coeff_1; ++i){ + wt1 = basis[rows*i + row_number]; + for(loop3_outer = 0; loop3_outer < 3; ++loop3_outer){ + // + // spatial-spatial covariances + // + for(loop3_inner = 0; loop3_inner <= loop3_outer; ++loop3_inner){ + for(j = 0; j <= i; ++j){ + // + // outer product of basis array + // + wt2 = wt1 * basis[rows*j + row_number]; + ptr1 = &alpha_1[coeff_2*(M1*(coeff_1*loop3_outer+i)+(coeff_1*loop3_inner)+j)]; + ptr2 = &alpha_2[coeff_2*(M2*loop3_outer+loop3_inner)]; + for(k = 0; k < coeff_2; ++k){ + for(m = 0; m <= k; ++m){ + ptr1[M1*k+m] += (wt2 * ptr2[M2*k+m]); + } + } + } + // + // spatial-intensity covariances (single G volume assumed) + // + ptr1 = &alpha_1[coeff_2*(M1*coeff_1*3+(coeff_1*loop3_inner)+i)]; + ptr2 = &alpha_2[coeff_2*(M2*3+loop3_outer)]; + for(k = 0; k < coeff_2; ++k){ + ptr1[M1+k] += (wt1 * ptr2[M2+k]); + } + // + // spatial component of beta + // + for(k = 0; k < coeff_2; ++k){ + beta_1[k+coeff_2*(coeff_1*loop3_outer+i)] += (wt1 * beta_2[coeff_2*loop3_outer+k]); + } + } + } + } + + // + // intensity-intensity covariances + // + ptr1 = &alpha_1[coeff_2*(M1*coeff_1*3+(coeff_1*3))]; + ptr2 = &alpha_2[coeff_2*(M2*3+3)]; + for(k = 0; k < coeff_2; ++k){ + ptr1[k] += ptr2[k]; + } + + // + // intensity component of beta + // + + beta_1[coeff_2*coeff_1*3] += beta_2[coeff_2*3]; + + status = 1; + + return status; + +} + + + +int NI_Complete_Symmetry(double *Alpha, int nx, int ny, int nz, int ni4){ + + // + // complete symmetry of Alpha matrix over the 3D brain volume + // + + int z1, z2; + int y1, y2; + int x1, x2; + int loop3_outer, loop3_inner; + int M1; + int status; + double *ptrx; + double *ptry; + double *ptrz; + + M1 = 3*nx*ny*nz + ni4; + + for(loop3_outer = 0; loop3_outer < 3; ++loop3_outer){ + for(loop3_inner = 0; loop3_inner <= loop3_outer; ++loop3_inner){ + ptrz = &Alpha[nx*ny*nz*(M1*loop3_outer+loop3_inner)]; + for(z1 = 0; z1 < nz; ++z1){ + for(z2 = 0; z2 <= z1; ++z2){ + ptry = ptrz + nx*ny*(M1*z1 + z2); + for(y1 = 0; y1 < ny; ++y1){ + for(y2 = 0; y2 <= y1; ++y2){ + ptrx = ptry + nx*(M1*y1 + y2); + for(x1 = 0; x1 <= nx; ++x1){ + for(y2 = 0; y2 <= y1; ++y2){ + ptrx[M1*x2+x1] = ptrx[M1*x1+x2]; + } + } + } + } + for(x1 = 0; x1 < nx*ny; ++x1){ + for(x2 = 0; x2 < x1; ++x2){ + ptry[M1*x2+x1] = ptry[M1*x1+x2]; + } + } + } + for(x1 = 0; x1 < nx*ny*nz; ++x1){ + for(x2 = 0; x2 < x1; ++x2){ + ptrz[M1*x2+x1] = ptrz[M1*x1+x2]; + } + } + + } + } + } + + for(x1 = 0; x1 < nx*ny*nz*3+ni4; ++x1){ + for(x2 = 0; x2 < x1; ++x2){ + Alpha[M1*x2+x1] = Alpha[M1*x1+x2]; + } + } + + + status = 1; + + return status; + +} + + + + Modified: trunk/scipy/ndimage/src/segment/Segmenter_EXT.c =================================================================== --- trunk/scipy/ndimage/src/segment/Segmenter_EXT.c 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/segment/Segmenter_EXT.c 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,682 +1,682 @@ -#include "ndImage_Segmenter_structs.h" -#include "Python.h" -#include "numpy/arrayobject.h" - -static PyObject *Segmenter_EdgePreFilter(PyObject *self, PyObject *args) -{ - - int lowThreshold; - int highThreshold; - int num; - int nd; - int type; - int aperature; - int half_taps; - npy_intp *dims; - unsigned short *fP1; - double *fP2; - double *pKernel; - PyObject *iArray = NULL; - PyObject *eArray = NULL; - PyObject *kernel = NULL; - - // - // pass in 2D LPF coefficients - if(!PyArg_ParseTuple(args, "iiiOOO", &lowThreshold, &highThreshold, - &half_taps, &kernel, &iArray, &eArray)) - goto exit; - - fP1 = (unsigned short *)PyArray_DATA(iArray); - nd = PyArray_NDIM(iArray); - dims = PyArray_DIMS(iArray); - type = PyArray_TYPE(iArray); - num = PyArray_SIZE(iArray); - fP2 = (double *)PyArray_DATA(eArray); - pKernel = (double *)PyArray_DATA(kernel); - aperature = PyArray_SIZE(kernel); - - if(!PyArray_ISCONTIGUOUS(iArray) || !PyArray_ISCONTIGUOUS(eArray)) - goto exit; - - - if(!NI_EdgePreFilter(num, (int)dims[0], (int)dims[1], lowThreshold, - highThreshold, aperature, half_taps, fP1, fP2, pKernel)) - - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - - -static PyObject *Segmenter_SobelImage(PyObject *self, PyObject *args) -{ - - int num; - int nd; - int type; - npy_intp *dims; - double *fP1; - double *fP2; - double pAve; - int minValue; - int maxValue; - PyObject *iArray = NULL; - PyObject *eArray = NULL; - - if(!PyArg_ParseTuple(args, "OO", &iArray, &eArray)) - goto exit; - - fP1 = (double *)PyArray_DATA(iArray); - nd = PyArray_NDIM(iArray); - dims = PyArray_DIMS(iArray); - type = PyArray_TYPE(iArray); - num = PyArray_SIZE(iArray); - fP2 = (double *)PyArray_DATA(eArray); - - if(!PyArray_ISCONTIGUOUS(iArray) || !PyArray_ISCONTIGUOUS(eArray)) - goto exit; - - - if(!NI_SobelImage(num, (int)dims[0], (int)dims[1], fP1, fP2, &pAve, &minValue, &maxValue)) - - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("dii", pAve, minValue, maxValue); - -} - - -static PyObject *Segmenter_SobelEdges(PyObject *self, PyObject *args) -{ - - int num; - int nd; - int type; - npy_intp *dims; - double *fP1; - unsigned short *fP2; - double pAve; - int minValue; - int maxValue; - int mode; - double sobelLow; - PyObject *iArray = NULL; - PyObject *eArray = NULL; - - if(!PyArg_ParseTuple(args, "OOdiiid", &iArray, &eArray, &pAve, &minValue, &maxValue, &mode, - &sobelLow)) - goto exit; - - fP1 = (double *)PyArray_DATA(iArray); - nd = PyArray_NDIM(iArray); - dims = PyArray_DIMS(iArray); - type = PyArray_TYPE(iArray); - num = PyArray_SIZE(iArray); - fP2 = (unsigned short *)PyArray_DATA(eArray); - - if(!PyArray_ISCONTIGUOUS(iArray) || !PyArray_ISCONTIGUOUS(eArray)) - goto exit; - - - if(!NI_SobelEdge(num, (int)dims[0], (int)dims[1], fP1, fP2, mode, pAve, minValue, maxValue, sobelLow)) - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - - - -static PyObject *Segmenter_GetBlobs(PyObject *self, PyObject *args) -{ - - int num; - int nd; - int type; - int mask; - npy_intp *dims; - unsigned short *fP1; - unsigned short *fP2; - int groups; - PyObject *iArray = NULL; - PyObject *eArray = NULL; - - if(!PyArg_ParseTuple(args, "OOi", &iArray, &eArray, &mask)) - goto exit; - - fP1 = (unsigned short *)PyArray_DATA(iArray); - nd = PyArray_NDIM(iArray); - dims = PyArray_DIMS(iArray); - type = PyArray_TYPE(iArray); - num = PyArray_SIZE(iArray); - fP2 = (unsigned short *)PyArray_DATA(eArray); - - if(!PyArray_ISCONTIGUOUS(iArray) || !PyArray_ISCONTIGUOUS(eArray)) - goto exit; - - - if(nd == 2){ - if(!NI_GetBlobs2D(num, (int)dims[0], (int)dims[1], fP1, fP2, &groups, mask)) - goto exit; - } - else if(nd == 3){ - if(!NI_GetBlobs3D(num, (int)dims[0], (int)dims[1], (int)dims[2], fP1, fP2, - &groups, mask)) - goto exit; - } - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("i", groups); - -} - -static PyObject *Segmenter_GetBlobRegions(PyObject *self, PyObject *args) -{ - - - int num; - int nd; - int type; - npy_intp *dims; - npy_intp *objNumber; - unsigned short *fP1; - PyObject *iArray = NULL; - PyObject *nArray = NULL; - objStruct *myData; - - if(!PyArg_ParseTuple(args, "OO", &iArray, &nArray)) - goto exit; - - if(!PyArray_ISCONTIGUOUS(iArray) || !PyArray_ISCONTIGUOUS(nArray)) - goto exit; - - // - // PyArray_ContiguousFromObject or PyArray_ContiguousFromAny to be explored - // for non-contiguous - // - - - // pointer to the edge-labeled image - nd = PyArray_NDIM(iArray); - dims = PyArray_DIMS(iArray); - type = PyArray_TYPE(iArray); - num = PyArray_SIZE(iArray); - fP1 = (unsigned short *)PyArray_DATA(iArray); - - // the object descriptor array that was allocated from numpy - objNumber = PyArray_DIMS(nArray); // this is the number of labels in the edge image - myData = (objStruct*)PyArray_DATA(nArray); - - /* need to pass in 2D/3D flag and mask. NI_GetBlobRegions will call - * 2D or 3D blob_extraction */ - - if(nd == 2){ - if(!NI_GetBlobRegions2D((int)dims[0], (int)dims[1], (int)objNumber[0], fP1, myData)) - goto exit; - } - else if(nd == 3){ - if(!NI_GetBlobRegions3D((int)dims[0], (int)dims[1], (int)dims[2], - (int)objNumber[0], fP1, myData)) - goto exit; - } - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - - -static PyObject *Segmenter_ThinFilter(PyObject *self, PyObject *args) -{ - - int number_masks; - int roi_rows; - int roi_cols; - int cols; - unsigned char *input; - unsigned char *cinput; - unsigned char *erosion; - unsigned char *dialation; - unsigned char *hmt; - unsigned char *copy; - unsigned short *j_mask; - unsigned short *k_mask; - PyObject *jArray = NULL; - PyObject *kArray = NULL; - PyObject *iArray = NULL; - PyObject *cArray = NULL; - PyObject *eArray = NULL; - PyObject *dArray = NULL; - PyObject *hArray = NULL; - PyObject *pArray = NULL; - - if(!PyArg_ParseTuple(args, "OOiiiiOOOOOO", &jArray, &kArray, &number_masks, &roi_rows, - &roi_cols, &cols, &iArray, &cArray, &eArray, &dArray, &hArray, &pArray)) - goto exit; - - - j_mask = (unsigned short *)PyArray_DATA(jArray); - k_mask = (unsigned short *)PyArray_DATA(kArray); - - input = (unsigned char *)PyArray_DATA(iArray); - cinput = (unsigned char *)PyArray_DATA(cArray); - erosion = (unsigned char *)PyArray_DATA(eArray); - dialation = (unsigned char *)PyArray_DATA(dArray); - hmt = (unsigned char *)PyArray_DATA(hArray); - copy = (unsigned char *)PyArray_DATA(pArray); - - if(!PyArray_ISCONTIGUOUS(iArray)) - goto exit; - - if(!NI_ThinMorphoFilter(roi_rows, roi_cols, cols, number_masks, j_mask, k_mask, - input, cinput, erosion, dialation, hmt, copy)) - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - - -static PyObject *Segmenter_CannyFilter(PyObject *self, PyObject *args) -{ - - int num; - int nd; - int type; - int aperature; - npy_intp *dims; - double *fP1; - double *h_DG_image; - double *v_DG_image; - double *pKernel; - float aveXValue; - float aveYValue; - PyObject *iArray = NULL; - PyObject *hArray = NULL; - PyObject *vArray = NULL; - PyObject *kernel = NULL; - - if(!PyArg_ParseTuple(args, "OOOOi", &iArray, &hArray, &vArray, &kernel, &aperature)) - goto exit; - - fP1 = (double *)PyArray_DATA(iArray); - nd = PyArray_NDIM(iArray); - dims = PyArray_DIMS(iArray); - type = PyArray_TYPE(iArray); - num = PyArray_SIZE(iArray); - - h_DG_image = (double *)PyArray_DATA(hArray); - v_DG_image = (double *)PyArray_DATA(vArray); - pKernel = (double *)PyArray_DATA(kernel); - - if(!PyArray_ISCONTIGUOUS(iArray)) - goto exit; - - if(!NI_CannyFilter(num, (int)dims[0], (int)dims[1], fP1, h_DG_image, - v_DG_image, pKernel, aperature, &aveXValue, &aveYValue)) - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("dd", aveXValue, aveYValue); - -} - - - - -static PyObject *Segmenter_CannyNonMaxSupress(PyObject *self, PyObject *args) -{ - - int num; - int nd; - int type; - int aperature; - int mode; - npy_intp *dims; - double *h_DG_image; - double *v_DG_image; - double *magnitude; - double aveXValue; - double aveYValue; - double aveMagnitude; - double canny_low; - double canny_high; - double canny_l; - double canny_h; - PyObject *mArray = NULL; - PyObject *hArray = NULL; - PyObject *vArray = NULL; - - if(!PyArg_ParseTuple(args, "OOOidddd", &hArray, &vArray, &mArray, &mode, &aveXValue, - &aveYValue, &canny_l, &canny_h)) - goto exit; - - magnitude = (double *)PyArray_DATA(mArray); - nd = PyArray_NDIM(mArray); - dims = PyArray_DIMS(mArray); - type = PyArray_TYPE(mArray); - num = PyArray_SIZE(mArray); - - h_DG_image = (double *)PyArray_DATA(hArray); - v_DG_image = (double *)PyArray_DATA(vArray); - - if(!PyArray_ISCONTIGUOUS(mArray)) - goto exit; - - if(!NI_CannyNonMaxSupress(num, (int)dims[0], (int)dims[1], magnitude, h_DG_image, - v_DG_image, mode, aveXValue, aveYValue, &aveMagnitude, - &canny_low, &canny_high, canny_l, canny_h)) - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("ddd", aveMagnitude, canny_low, canny_high); - -} - - - -static PyObject *Segmenter_CannyHysteresis(PyObject *self, PyObject *args) -{ - - int num; - int nd; - int type; - int aperature; - int mode; - npy_intp *dims; - double *magnitude; - unsigned short *hys_image; - double canny_low; - double canny_high; - PyObject *mArray = NULL; - PyObject *hArray = NULL; - - if(!PyArg_ParseTuple(args, "OOdd", &mArray, &hArray, &canny_low, &canny_high)) - goto exit; - - magnitude = (double *)PyArray_DATA(mArray); - nd = PyArray_NDIM(mArray); - dims = PyArray_DIMS(mArray); - type = PyArray_TYPE(mArray); - num = PyArray_SIZE(mArray); - - hys_image = (unsigned short *)PyArray_DATA(hArray); - - if(!PyArray_ISCONTIGUOUS(mArray)) - goto exit; - - if(!NI_CannyHysteresis(num, (int)dims[0], (int)dims[1], magnitude, hys_image, - canny_low, canny_high)) - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - - -static PyObject *Segmenter_BinaryEdge(PyObject *self, PyObject *args) -{ - - int num; - int nd; - int type; - npy_intp *dims; - unsigned short *mask_image; - unsigned short *edge_image; - PyObject *mArray = NULL; - PyObject *eArray = NULL; - - if(!PyArg_ParseTuple(args, "OO", &mArray, &eArray)) - goto exit; - - mask_image = (unsigned short *)PyArray_DATA(mArray); - nd = PyArray_NDIM(mArray); - dims = PyArray_DIMS(mArray); - type = PyArray_TYPE(mArray); - num = PyArray_SIZE(mArray); - edge_image = (unsigned short *)PyArray_DATA(eArray); - - if(!PyArray_ISCONTIGUOUS(mArray)) - goto exit; - - if(!NI_BinaryEdge(num, (int)dims[0], (int)dims[1], mask_image, edge_image)) - goto exit; - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - -static PyObject *Segmenter_LawsTextureMetric(PyObject *self, PyObject *args) -{ - - int i; - int num; - int nd; - int type; - int mode; - npy_intp *dims; - npy_intp *laws_dims; - float *lawsImage; - double *src_image; - unsigned short *mask; - double *L7; - double *E7; - double *S7; - double *W7; - double *R7; - double *O7; - int number_kernels; - int kernel_size; - int filters; - LawsFilter7 lawsFilter; - PyObject *lArray = NULL; - PyObject *mArray = NULL; - PyObject *sArray = NULL; - PyObject *LArray = NULL; - PyObject *EArray = NULL; - PyObject *SArray = NULL; - PyObject *WArray = NULL; - PyObject *RArray = NULL; - PyObject *OArray = NULL; - - if(!PyArg_ParseTuple(args, "OOOiiiOOOOOO", &mArray, &sArray, &lArray, &number_kernels, - &kernel_size, &filters, &LArray, &EArray, - &SArray, &WArray, &RArray, &OArray)) - goto exit; - - src_image = (double*)PyArray_DATA(sArray); - nd = PyArray_NDIM(sArray); - dims = PyArray_DIMS(sArray); - type = PyArray_TYPE(sArray); - num = PyArray_SIZE(sArray); - - laws_dims = PyArray_DIMS(lArray); - mask = (unsigned short *)PyArray_DATA(mArray); - lawsImage = (float*)PyArray_DATA(lArray); - L7 = (double *)PyArray_DATA(LArray); - E7 = (double *)PyArray_DATA(EArray); - S7 = (double *)PyArray_DATA(SArray); - W7 = (double *)PyArray_DATA(WArray); - R7 = (double *)PyArray_DATA(RArray); - O7 = (double *)PyArray_DATA(OArray); - - lawsFilter.numberKernels = number_kernels; - lawsFilter.kernelLength = kernel_size; - lawsFilter.numberFilterLayers = filters; - for(i = 0; i < kernel_size; ++i){ - lawsFilter.lawsKernel[0][i] = L7[i]; - lawsFilter.lawsKernel[1][i] = E7[i]; - lawsFilter.lawsKernel[2][i] = S7[i]; - lawsFilter.lawsKernel[3][i] = W7[i]; - lawsFilter.lawsKernel[4][i] = R7[i]; - lawsFilter.lawsKernel[5][i] = O7[i]; - } - - if(!PyArray_ISCONTIGUOUS(sArray)){ - printf("PyArray_ISCONTIGUOUS error\n"); - goto exit; - } - - if(!NI_LawsTexture(num, (int)dims[0], (int)dims[1], src_image, mask, lawsImage, - lawsFilter)){ - goto exit; - } - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - -static PyObject *Segmenter_RoiCoOccurence(PyObject *self, PyObject *args) -{ - int num; - int nd; - int type; - int distance; - int orientation; - npy_intp *dims; - npy_intp *dims_cocm; - unsigned short *mask_image; - unsigned short *raw_image; - int *coc_matrix; - PyObject *mArray = NULL; - PyObject *rArray = NULL; - PyObject *cArray = NULL; - - if(!PyArg_ParseTuple(args, "OOOii", &mArray, &rArray, &cArray, &distance, &orientation)) - goto exit; - - mask_image = (unsigned short *)PyArray_DATA(mArray); - nd = PyArray_NDIM(mArray); - dims = PyArray_DIMS(mArray); - type = PyArray_TYPE(mArray); - num = PyArray_SIZE(mArray); - raw_image = (unsigned short *)PyArray_DATA(rArray); - coc_matrix = (int *)PyArray_DATA(cArray); - dims_cocm = PyArray_DIMS(cArray); - - if(!PyArray_ISCONTIGUOUS(mArray) || !PyArray_ISCONTIGUOUS(rArray)){ - printf("PyArray_ISCONTIGUOUS error\n"); - goto exit; - } - - if(!NI_RoiCoOccurence(num, (int)dims[0], (int)dims[1], mask_image, raw_image, - coc_matrix, distance, orientation)) - goto exit; - - - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - -static PyObject *Segmenter_GrowRegion(PyObject *self, PyObject *args) -{ - - - int num; - int nd; - int type; - int Label; - int N_connectivity; - double low_threshold; - double high_threshold; - npy_intp *dims; - npy_intp *objNumber; - unsigned short *label; - double *section; - PyObject *sArray = NULL; - PyObject *lArray = NULL; - PyObject *eArray = NULL; - PyObject *nArray = NULL; - objStruct *expanded_ROI; - objStruct *newgrow_ROI; - - if(!PyArg_ParseTuple(args, "OOOOddii", &sArray, &lArray, &eArray, &nArray, &low_threshold, - &high_threshold, &Label, &N_connectivity)){ - printf("PyArg_ParseTuple error\n"); - goto exit; - } - - if(!PyArray_ISCONTIGUOUS(sArray) || !PyArray_ISCONTIGUOUS(lArray)){ - printf("PyArray_ISCONTIGUOUS error\n"); - goto exit; - } - - section = (double *)PyArray_DATA(sArray); - nd = PyArray_NDIM(sArray); - dims = PyArray_DIMS(sArray); - type = PyArray_TYPE(sArray); - num = PyArray_SIZE(sArray); - - label = (unsigned short *)PyArray_DATA(lArray); - expanded_ROI = (objStruct*)PyArray_DATA(eArray); - newgrow_ROI = (objStruct*)PyArray_DATA(nArray); - - if(nd == 2){ - if(!NI_GrowRegion2D((int)dims[0], (int)dims[1], section, label, expanded_ROI, - newgrow_ROI, low_threshold, high_threshold, Label, N_connectivity)) - goto exit; - } - else if(nd == 3){ - if(!NI_GrowRegion3D((int)dims[0], (int)dims[1], (int)dims[2], section, label, - expanded_ROI, newgrow_ROI, low_threshold, high_threshold, - Label, N_connectivity)) - goto exit; - } - - -exit: - - return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); - -} - -static PyMethodDef SegmenterMethods[] = -{ - { "region_grow", Segmenter_GrowRegion, METH_VARARGS, NULL }, - { "roi_co_occurence", Segmenter_RoiCoOccurence, METH_VARARGS, NULL }, - { "binary_edge", Segmenter_BinaryEdge, METH_VARARGS, NULL }, - { "laws_texture_metric", Segmenter_LawsTextureMetric, METH_VARARGS, NULL }, - { "canny_hysteresis", Segmenter_CannyHysteresis, METH_VARARGS, NULL }, - { "canny_nonmax_supress", Segmenter_CannyNonMaxSupress, METH_VARARGS, NULL }, - { "canny_filter", Segmenter_CannyFilter, METH_VARARGS, NULL }, - { "sobel_edges", Segmenter_SobelEdges, METH_VARARGS, NULL }, - { "sobel_image", Segmenter_SobelImage, METH_VARARGS, NULL }, - { "edge_prefilter", Segmenter_EdgePreFilter, METH_VARARGS, NULL }, - { "get_blobs", Segmenter_GetBlobs, METH_VARARGS, NULL }, - { "get_blob_regions", Segmenter_GetBlobRegions, METH_VARARGS, NULL }, - { "thin_filter", Segmenter_ThinFilter, METH_VARARGS, NULL }, - { NULL, NULL, 0, NULL}, -}; - -PyMODINIT_FUNC init_segment(void) -{ - Py_InitModule("_segment", SegmenterMethods); - import_array(); -} - - - - - +#include "ndImage_Segmenter_structs.h" +#include "Python.h" +#include "numpy/arrayobject.h" + +static PyObject *Segmenter_EdgePreFilter(PyObject *self, PyObject *args) +{ + + int lowThreshold; + int highThreshold; + int num; + int nd; + int type; + int aperature; + int half_taps; + npy_intp *dims; + unsigned short *fP1; + double *fP2; + double *pKernel; + PyObject *iArray = NULL; + PyObject *eArray = NULL; + PyObject *kernel = NULL; + + // + // pass in 2D LPF coefficients + if(!PyArg_ParseTuple(args, "iiiOOO", &lowThreshold, &highThreshold, + &half_taps, &kernel, &iArray, &eArray)) + goto exit; + + fP1 = (unsigned short *)PyArray_DATA(iArray); + nd = PyArray_NDIM(iArray); + dims = PyArray_DIMS(iArray); + type = PyArray_TYPE(iArray); + num = PyArray_SIZE(iArray); + fP2 = (double *)PyArray_DATA(eArray); + pKernel = (double *)PyArray_DATA(kernel); + aperature = PyArray_SIZE(kernel); + + if(!PyArray_ISCONTIGUOUS(iArray) || !PyArray_ISCONTIGUOUS(eArray)) + goto exit; + + + if(!NI_EdgePreFilter(num, (int)dims[0], (int)dims[1], lowThreshold, + highThreshold, aperature, half_taps, fP1, fP2, pKernel)) + + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Segmenter_SobelImage(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + npy_intp *dims; + double *fP1; + double *fP2; + double pAve; + int minValue; + int maxValue; + PyObject *iArray = NULL; + PyObject *eArray = NULL; + + if(!PyArg_ParseTuple(args, "OO", &iArray, &eArray)) + goto exit; + + fP1 = (double *)PyArray_DATA(iArray); + nd = PyArray_NDIM(iArray); + dims = PyArray_DIMS(iArray); + type = PyArray_TYPE(iArray); + num = PyArray_SIZE(iArray); + fP2 = (double *)PyArray_DATA(eArray); + + if(!PyArray_ISCONTIGUOUS(iArray) || !PyArray_ISCONTIGUOUS(eArray)) + goto exit; + + + if(!NI_SobelImage(num, (int)dims[0], (int)dims[1], fP1, fP2, &pAve, &minValue, &maxValue)) + + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("dii", pAve, minValue, maxValue); + +} + + +static PyObject *Segmenter_SobelEdges(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + npy_intp *dims; + double *fP1; + unsigned short *fP2; + double pAve; + int minValue; + int maxValue; + int mode; + double sobelLow; + PyObject *iArray = NULL; + PyObject *eArray = NULL; + + if(!PyArg_ParseTuple(args, "OOdiiid", &iArray, &eArray, &pAve, &minValue, &maxValue, &mode, + &sobelLow)) + goto exit; + + fP1 = (double *)PyArray_DATA(iArray); + nd = PyArray_NDIM(iArray); + dims = PyArray_DIMS(iArray); + type = PyArray_TYPE(iArray); + num = PyArray_SIZE(iArray); + fP2 = (unsigned short *)PyArray_DATA(eArray); + + if(!PyArray_ISCONTIGUOUS(iArray) || !PyArray_ISCONTIGUOUS(eArray)) + goto exit; + + + if(!NI_SobelEdge(num, (int)dims[0], (int)dims[1], fP1, fP2, mode, pAve, minValue, maxValue, sobelLow)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + + +static PyObject *Segmenter_GetBlobs(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int mask; + npy_intp *dims; + unsigned short *fP1; + unsigned short *fP2; + int groups; + PyObject *iArray = NULL; + PyObject *eArray = NULL; + + if(!PyArg_ParseTuple(args, "OOi", &iArray, &eArray, &mask)) + goto exit; + + fP1 = (unsigned short *)PyArray_DATA(iArray); + nd = PyArray_NDIM(iArray); + dims = PyArray_DIMS(iArray); + type = PyArray_TYPE(iArray); + num = PyArray_SIZE(iArray); + fP2 = (unsigned short *)PyArray_DATA(eArray); + + if(!PyArray_ISCONTIGUOUS(iArray) || !PyArray_ISCONTIGUOUS(eArray)) + goto exit; + + + if(nd == 2){ + if(!NI_GetBlobs2D(num, (int)dims[0], (int)dims[1], fP1, fP2, &groups, mask)) + goto exit; + } + else if(nd == 3){ + if(!NI_GetBlobs3D(num, (int)dims[0], (int)dims[1], (int)dims[2], fP1, fP2, + &groups, mask)) + goto exit; + } + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("i", groups); + +} + +static PyObject *Segmenter_GetBlobRegions(PyObject *self, PyObject *args) +{ + + + int num; + int nd; + int type; + npy_intp *dims; + npy_intp *objNumber; + unsigned short *fP1; + PyObject *iArray = NULL; + PyObject *nArray = NULL; + objStruct *myData; + + if(!PyArg_ParseTuple(args, "OO", &iArray, &nArray)) + goto exit; + + if(!PyArray_ISCONTIGUOUS(iArray) || !PyArray_ISCONTIGUOUS(nArray)) + goto exit; + + // + // PyArray_ContiguousFromObject or PyArray_ContiguousFromAny to be explored + // for non-contiguous + // + + + // pointer to the edge-labeled image + nd = PyArray_NDIM(iArray); + dims = PyArray_DIMS(iArray); + type = PyArray_TYPE(iArray); + num = PyArray_SIZE(iArray); + fP1 = (unsigned short *)PyArray_DATA(iArray); + + // the object descriptor array that was allocated from numpy + objNumber = PyArray_DIMS(nArray); // this is the number of labels in the edge image + myData = (objStruct*)PyArray_DATA(nArray); + + /* need to pass in 2D/3D flag and mask. NI_GetBlobRegions will call + * 2D or 3D blob_extraction */ + + if(nd == 2){ + if(!NI_GetBlobRegions2D((int)dims[0], (int)dims[1], (int)objNumber[0], fP1, myData)) + goto exit; + } + else if(nd == 3){ + if(!NI_GetBlobRegions3D((int)dims[0], (int)dims[1], (int)dims[2], + (int)objNumber[0], fP1, myData)) + goto exit; + } + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Segmenter_ThinFilter(PyObject *self, PyObject *args) +{ + + int number_masks; + int roi_rows; + int roi_cols; + int cols; + unsigned char *input; + unsigned char *cinput; + unsigned char *erosion; + unsigned char *dialation; + unsigned char *hmt; + unsigned char *copy; + unsigned short *j_mask; + unsigned short *k_mask; + PyObject *jArray = NULL; + PyObject *kArray = NULL; + PyObject *iArray = NULL; + PyObject *cArray = NULL; + PyObject *eArray = NULL; + PyObject *dArray = NULL; + PyObject *hArray = NULL; + PyObject *pArray = NULL; + + if(!PyArg_ParseTuple(args, "OOiiiiOOOOOO", &jArray, &kArray, &number_masks, &roi_rows, + &roi_cols, &cols, &iArray, &cArray, &eArray, &dArray, &hArray, &pArray)) + goto exit; + + + j_mask = (unsigned short *)PyArray_DATA(jArray); + k_mask = (unsigned short *)PyArray_DATA(kArray); + + input = (unsigned char *)PyArray_DATA(iArray); + cinput = (unsigned char *)PyArray_DATA(cArray); + erosion = (unsigned char *)PyArray_DATA(eArray); + dialation = (unsigned char *)PyArray_DATA(dArray); + hmt = (unsigned char *)PyArray_DATA(hArray); + copy = (unsigned char *)PyArray_DATA(pArray); + + if(!PyArray_ISCONTIGUOUS(iArray)) + goto exit; + + if(!NI_ThinMorphoFilter(roi_rows, roi_cols, cols, number_masks, j_mask, k_mask, + input, cinput, erosion, dialation, hmt, copy)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Segmenter_CannyFilter(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int aperature; + npy_intp *dims; + double *fP1; + double *h_DG_image; + double *v_DG_image; + double *pKernel; + float aveXValue; + float aveYValue; + PyObject *iArray = NULL; + PyObject *hArray = NULL; + PyObject *vArray = NULL; + PyObject *kernel = NULL; + + if(!PyArg_ParseTuple(args, "OOOOi", &iArray, &hArray, &vArray, &kernel, &aperature)) + goto exit; + + fP1 = (double *)PyArray_DATA(iArray); + nd = PyArray_NDIM(iArray); + dims = PyArray_DIMS(iArray); + type = PyArray_TYPE(iArray); + num = PyArray_SIZE(iArray); + + h_DG_image = (double *)PyArray_DATA(hArray); + v_DG_image = (double *)PyArray_DATA(vArray); + pKernel = (double *)PyArray_DATA(kernel); + + if(!PyArray_ISCONTIGUOUS(iArray)) + goto exit; + + if(!NI_CannyFilter(num, (int)dims[0], (int)dims[1], fP1, h_DG_image, + v_DG_image, pKernel, aperature, &aveXValue, &aveYValue)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("dd", aveXValue, aveYValue); + +} + + + + +static PyObject *Segmenter_CannyNonMaxSupress(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int aperature; + int mode; + npy_intp *dims; + double *h_DG_image; + double *v_DG_image; + double *magnitude; + double aveXValue; + double aveYValue; + double aveMagnitude; + double canny_low; + double canny_high; + double canny_l; + double canny_h; + PyObject *mArray = NULL; + PyObject *hArray = NULL; + PyObject *vArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOidddd", &hArray, &vArray, &mArray, &mode, &aveXValue, + &aveYValue, &canny_l, &canny_h)) + goto exit; + + magnitude = (double *)PyArray_DATA(mArray); + nd = PyArray_NDIM(mArray); + dims = PyArray_DIMS(mArray); + type = PyArray_TYPE(mArray); + num = PyArray_SIZE(mArray); + + h_DG_image = (double *)PyArray_DATA(hArray); + v_DG_image = (double *)PyArray_DATA(vArray); + + if(!PyArray_ISCONTIGUOUS(mArray)) + goto exit; + + if(!NI_CannyNonMaxSupress(num, (int)dims[0], (int)dims[1], magnitude, h_DG_image, + v_DG_image, mode, aveXValue, aveYValue, &aveMagnitude, + &canny_low, &canny_high, canny_l, canny_h)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue("ddd", aveMagnitude, canny_low, canny_high); + +} + + + +static PyObject *Segmenter_CannyHysteresis(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + int aperature; + int mode; + npy_intp *dims; + double *magnitude; + unsigned short *hys_image; + double canny_low; + double canny_high; + PyObject *mArray = NULL; + PyObject *hArray = NULL; + + if(!PyArg_ParseTuple(args, "OOdd", &mArray, &hArray, &canny_low, &canny_high)) + goto exit; + + magnitude = (double *)PyArray_DATA(mArray); + nd = PyArray_NDIM(mArray); + dims = PyArray_DIMS(mArray); + type = PyArray_TYPE(mArray); + num = PyArray_SIZE(mArray); + + hys_image = (unsigned short *)PyArray_DATA(hArray); + + if(!PyArray_ISCONTIGUOUS(mArray)) + goto exit; + + if(!NI_CannyHysteresis(num, (int)dims[0], (int)dims[1], magnitude, hys_image, + canny_low, canny_high)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + + +static PyObject *Segmenter_BinaryEdge(PyObject *self, PyObject *args) +{ + + int num; + int nd; + int type; + npy_intp *dims; + unsigned short *mask_image; + unsigned short *edge_image; + PyObject *mArray = NULL; + PyObject *eArray = NULL; + + if(!PyArg_ParseTuple(args, "OO", &mArray, &eArray)) + goto exit; + + mask_image = (unsigned short *)PyArray_DATA(mArray); + nd = PyArray_NDIM(mArray); + dims = PyArray_DIMS(mArray); + type = PyArray_TYPE(mArray); + num = PyArray_SIZE(mArray); + edge_image = (unsigned short *)PyArray_DATA(eArray); + + if(!PyArray_ISCONTIGUOUS(mArray)) + goto exit; + + if(!NI_BinaryEdge(num, (int)dims[0], (int)dims[1], mask_image, edge_image)) + goto exit; + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + +static PyObject *Segmenter_LawsTextureMetric(PyObject *self, PyObject *args) +{ + + int i; + int num; + int nd; + int type; + int mode; + npy_intp *dims; + npy_intp *laws_dims; + float *lawsImage; + double *src_image; + unsigned short *mask; + double *L7; + double *E7; + double *S7; + double *W7; + double *R7; + double *O7; + int number_kernels; + int kernel_size; + int filters; + LawsFilter7 lawsFilter; + PyObject *lArray = NULL; + PyObject *mArray = NULL; + PyObject *sArray = NULL; + PyObject *LArray = NULL; + PyObject *EArray = NULL; + PyObject *SArray = NULL; + PyObject *WArray = NULL; + PyObject *RArray = NULL; + PyObject *OArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOiiiOOOOOO", &mArray, &sArray, &lArray, &number_kernels, + &kernel_size, &filters, &LArray, &EArray, + &SArray, &WArray, &RArray, &OArray)) + goto exit; + + src_image = (double*)PyArray_DATA(sArray); + nd = PyArray_NDIM(sArray); + dims = PyArray_DIMS(sArray); + type = PyArray_TYPE(sArray); + num = PyArray_SIZE(sArray); + + laws_dims = PyArray_DIMS(lArray); + mask = (unsigned short *)PyArray_DATA(mArray); + lawsImage = (float*)PyArray_DATA(lArray); + L7 = (double *)PyArray_DATA(LArray); + E7 = (double *)PyArray_DATA(EArray); + S7 = (double *)PyArray_DATA(SArray); + W7 = (double *)PyArray_DATA(WArray); + R7 = (double *)PyArray_DATA(RArray); + O7 = (double *)PyArray_DATA(OArray); + + lawsFilter.numberKernels = number_kernels; + lawsFilter.kernelLength = kernel_size; + lawsFilter.numberFilterLayers = filters; + for(i = 0; i < kernel_size; ++i){ + lawsFilter.lawsKernel[0][i] = L7[i]; + lawsFilter.lawsKernel[1][i] = E7[i]; + lawsFilter.lawsKernel[2][i] = S7[i]; + lawsFilter.lawsKernel[3][i] = W7[i]; + lawsFilter.lawsKernel[4][i] = R7[i]; + lawsFilter.lawsKernel[5][i] = O7[i]; + } + + if(!PyArray_ISCONTIGUOUS(sArray)){ + printf("PyArray_ISCONTIGUOUS error\n"); + goto exit; + } + + if(!NI_LawsTexture(num, (int)dims[0], (int)dims[1], src_image, mask, lawsImage, + lawsFilter)){ + goto exit; + } + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + +static PyObject *Segmenter_RoiCoOccurence(PyObject *self, PyObject *args) +{ + int num; + int nd; + int type; + int distance; + int orientation; + npy_intp *dims; + npy_intp *dims_cocm; + unsigned short *mask_image; + unsigned short *raw_image; + int *coc_matrix; + PyObject *mArray = NULL; + PyObject *rArray = NULL; + PyObject *cArray = NULL; + + if(!PyArg_ParseTuple(args, "OOOii", &mArray, &rArray, &cArray, &distance, &orientation)) + goto exit; + + mask_image = (unsigned short *)PyArray_DATA(mArray); + nd = PyArray_NDIM(mArray); + dims = PyArray_DIMS(mArray); + type = PyArray_TYPE(mArray); + num = PyArray_SIZE(mArray); + raw_image = (unsigned short *)PyArray_DATA(rArray); + coc_matrix = (int *)PyArray_DATA(cArray); + dims_cocm = PyArray_DIMS(cArray); + + if(!PyArray_ISCONTIGUOUS(mArray) || !PyArray_ISCONTIGUOUS(rArray)){ + printf("PyArray_ISCONTIGUOUS error\n"); + goto exit; + } + + if(!NI_RoiCoOccurence(num, (int)dims[0], (int)dims[1], mask_image, raw_image, + coc_matrix, distance, orientation)) + goto exit; + + + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + +static PyObject *Segmenter_GrowRegion(PyObject *self, PyObject *args) +{ + + + int num; + int nd; + int type; + int Label; + int N_connectivity; + double low_threshold; + double high_threshold; + npy_intp *dims; + npy_intp *objNumber; + unsigned short *label; + double *section; + PyObject *sArray = NULL; + PyObject *lArray = NULL; + PyObject *eArray = NULL; + PyObject *nArray = NULL; + objStruct *expanded_ROI; + objStruct *newgrow_ROI; + + if(!PyArg_ParseTuple(args, "OOOOddii", &sArray, &lArray, &eArray, &nArray, &low_threshold, + &high_threshold, &Label, &N_connectivity)){ + printf("PyArg_ParseTuple error\n"); + goto exit; + } + + if(!PyArray_ISCONTIGUOUS(sArray) || !PyArray_ISCONTIGUOUS(lArray)){ + printf("PyArray_ISCONTIGUOUS error\n"); + goto exit; + } + + section = (double *)PyArray_DATA(sArray); + nd = PyArray_NDIM(sArray); + dims = PyArray_DIMS(sArray); + type = PyArray_TYPE(sArray); + num = PyArray_SIZE(sArray); + + label = (unsigned short *)PyArray_DATA(lArray); + expanded_ROI = (objStruct*)PyArray_DATA(eArray); + newgrow_ROI = (objStruct*)PyArray_DATA(nArray); + + if(nd == 2){ + if(!NI_GrowRegion2D((int)dims[0], (int)dims[1], section, label, expanded_ROI, + newgrow_ROI, low_threshold, high_threshold, Label, N_connectivity)) + goto exit; + } + else if(nd == 3){ + if(!NI_GrowRegion3D((int)dims[0], (int)dims[1], (int)dims[2], section, label, + expanded_ROI, newgrow_ROI, low_threshold, high_threshold, + Label, N_connectivity)) + goto exit; + } + + +exit: + + return PyErr_Occurred() ? NULL : (PyObject*)Py_BuildValue(""); + +} + +static PyMethodDef SegmenterMethods[] = +{ + { "region_grow", Segmenter_GrowRegion, METH_VARARGS, NULL }, + { "roi_co_occurence", Segmenter_RoiCoOccurence, METH_VARARGS, NULL }, + { "binary_edge", Segmenter_BinaryEdge, METH_VARARGS, NULL }, + { "laws_texture_metric", Segmenter_LawsTextureMetric, METH_VARARGS, NULL }, + { "canny_hysteresis", Segmenter_CannyHysteresis, METH_VARARGS, NULL }, + { "canny_nonmax_supress", Segmenter_CannyNonMaxSupress, METH_VARARGS, NULL }, + { "canny_filter", Segmenter_CannyFilter, METH_VARARGS, NULL }, + { "sobel_edges", Segmenter_SobelEdges, METH_VARARGS, NULL }, + { "sobel_image", Segmenter_SobelImage, METH_VARARGS, NULL }, + { "edge_prefilter", Segmenter_EdgePreFilter, METH_VARARGS, NULL }, + { "get_blobs", Segmenter_GetBlobs, METH_VARARGS, NULL }, + { "get_blob_regions", Segmenter_GetBlobRegions, METH_VARARGS, NULL }, + { "thin_filter", Segmenter_ThinFilter, METH_VARARGS, NULL }, + { NULL, NULL, 0, NULL}, +}; + +PyMODINIT_FUNC init_segment(void) +{ + Py_InitModule("_segment", SegmenterMethods); + import_array(); +} + + + + + Modified: trunk/scipy/ndimage/src/segment/Segmenter_IMPL.c =================================================================== --- trunk/scipy/ndimage/src/segment/Segmenter_IMPL.c 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/segment/Segmenter_IMPL.c 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,1671 +1,1671 @@ -#include -#include -#include -#include -#include "ndImage_Segmenter_structs.h" - -// these are for this standalone and come out with the full build -// -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define FALSE 0 -#define TRUE 1 - - -int NI_EdgePreFilter(int num, int rows, int cols, int lowThreshold, int highThreshold, - int aperature, int HalfFilterTaps, unsigned short *sImage, double *dImage, - double *kernel){ - - int i, j, k, n, num1; - int offset; - double sum, value; - double *buffer; - int max_buffer = MAX(rows, cols); - int status; - - buffer = calloc(max_buffer+aperature+16, sizeof(double)); - - num1 = HalfFilterTaps; - offset = 0; - for(i = 0; i < rows; ++i){ - /* copy image row to local buffer */ - for(j = 0; j < cols; ++j){ - buffer[num1+j] = sImage[offset+j]; - } - /* constant pad the ends of the buffer */ - for(j = 0; j < num1; ++j){ - buffer[j] = buffer[num1]; - } - for(j = cols+num1; j < cols+2*num1; ++j){ - buffer[j] = buffer[cols-1+num1]; - } - - /* Perform Symmetric Convolution in the X dimension. */ - for(n = 0, j = num1; j < (cols+num1); ++j, ++n){ - sum = buffer[j] * kernel[num1]; - for(k = 1; k < num1; ++k){ - sum += kernel[num1-k] * (buffer[j+k] + buffer[j-k]); - } - dImage[offset+n] = sum; - } - offset += cols; - } - - offset = 0; - for(i = 0; i < cols; ++i){ - /* copy image column to local buffer */ - offset = 0; - for(j = 0; j < rows; ++j){ - buffer[num1+j] = dImage[offset+i]; - offset += cols; - } - /* constant pad the ends of the buffer */ - for(j = 0; j < num1; ++j){ - buffer[j] = buffer[num1]; - } - for(j = rows+num1; j < rows+2*num1; ++j){ - buffer[j] = buffer[rows-1+num1]; - } - - /* Perform Symmetric Convolution in the Y dimension. */ - offset = 0; - for(j = num1; j < (rows+num1); ++j){ - sum = buffer[j] * kernel[num1]; - for(k = 1; k < num1; ++k){ - sum += kernel[num1-k] * (buffer[j+k] + buffer[j-k]); - } - dImage[offset+i] = sum; - offset += cols; - } - } - - /* threshold the image */ - offset = 0; - for(i = 0; i < rows; ++i){ - for(j = 0; j < cols; ++j){ - value = dImage[offset+j]; - if(value < (float)lowThreshold) value = (float)0.0; - if(value > (float)highThreshold) value = (float)0.0; - dImage[offset+j] = value; - } - offset += cols; - } - - free(buffer); - - status = 1; - - return(status); - -} - -int NI_SobelImage(int samples, int rows, int cols, double *rawImage, double *edgeImage, double *pAve, - int *minValue, int *maxValue){ - - int i, j; - int p, m, n; - int offset; - int offsetM1; - int offsetP1; - int status; - int count = 0; - - /* - // Sobel - */ - offset = cols; - *pAve = 0.0; - *minValue = 10000; - *maxValue = -10000; - for(i = 1; i < rows-1; ++i){ - offsetM1 = offset - cols; - offsetP1 = offset + cols; - for(j = 1; j < cols-1; ++j){ - n = 2*rawImage[offsetM1+j] + rawImage[offsetM1+j-1] + rawImage[offsetM1+j+1] - - 2*rawImage[offsetP1+j] - rawImage[offsetP1+j-1] - rawImage[offsetP1+j+1]; - m = 2*rawImage[offset+j-1] + rawImage[offsetM1+j-1] + rawImage[offsetP1+j-1] - - 2*rawImage[offset+j+1] - rawImage[offsetM1+j+1] - rawImage[offsetP1+j+1]; - p = (int)sqrt((float)(m*m) + (float)(n*n)); - if(p > 0){ - *pAve += p; - if(p > *maxValue) *maxValue = p; - if(p < *minValue) *minValue = p; - ++count; - } - edgeImage[offset+j] = p; - } - offset += cols; - } - /* threshold based on ave */ - *pAve /= count; - - status = 1; - - return(status); - -} - - -int NI_BinaryEdge(int samples, int rows, int cols, unsigned short *labelImage, unsigned short *edgeImage){ - - int i, j, k; - int maxValue; - int offset; - int offsetM1; - int offsetP1; - int values3x3[8]; - int status; - - offset = cols; - for(i = 1; i < rows-1; ++i){ - offsetM1 = offset - cols; - offsetP1 = offset + cols; - for(j = 1; j < cols-1; ++j){ - values3x3[0] = labelImage[offset+j] - labelImage[offset+j+1]; - values3x3[1] = labelImage[offset+j] - labelImage[offsetM1+j+1]; - values3x3[2] = labelImage[offset+j] - labelImage[offsetM1+j]; - values3x3[3] = labelImage[offset+j] - labelImage[offsetM1+j-1]; - values3x3[4] = labelImage[offset+j] - labelImage[offset+j-1]; - values3x3[5] = labelImage[offset+j] - labelImage[offsetP1+j-1]; - values3x3[6] = labelImage[offset+j] - labelImage[offsetP1+j]; - values3x3[7] = labelImage[offset+j] - labelImage[offsetP1+j+1]; - maxValue = -1; - for(k = 0; k < 8; ++k){ - maxValue = MAX(maxValue, values3x3[k]); - } - edgeImage[offset+j] = maxValue; - } - offset += cols; - } - - status = 1; - - return(status); - -} - -int NI_SobelEdge(int samples, int rows, int cols, double *edgeImage, unsigned short *edges, - int mode, double pAve, int minValue, int maxValue, double sobelLow){ - - int i, j; - int offset; - int value; - int maxIndex; - int status; - int histogram[256]; - float pThreshold; - double scale; - double step; - - scale = 1.0 / maxValue; - - step = 255.0/(maxValue-minValue); - for(i = 0; i < 256; ++i){ - histogram[i] = 0; - } - offset = 0; - for(i = 0; i < rows; ++i){ - for(j = 0; j < cols; ++j){ - value = (int)(step*(edgeImage[offset+j]-minValue)); - ++histogram[value]; - } - offset += cols; - } - - if(mode == 1){ - /* based on the mean value of edge energy */ - pThreshold = (int)(sobelLow * (float)pAve); - } - else{ - /* based on the mode value of edge energy */ - pThreshold = (sobelLow * (minValue + ((float)maxIndex/step))); - } - - offset = 0; - for(i = 0; i < rows; ++i){ - for(j = 0; j < cols; ++j){ - if(edgeImage[offset+j] > pThreshold){ - edges[offset+j] = 1; - } - else{ - edges[offset+j] = 0; - } - } - offset += cols; - } - - status = 1; - return(status); - -} - -int NI_GetBlobs3D(int samples, int layers, int rows, int cols, unsigned short *edges, - unsigned short *connectedEdges, int *groups, int mask){ - - int i, j, k, l, m; - int lOffset, rOffset, Label; - int lOffsetP, lOffsetN; - int rOffsetP, rOffsetN; - int Classes[4096]; - int dwImageSize, ptr; - bool NewLabel; - bool Change; - bool connected; - int T[27]; - int *ccompImage; - int layerSize; - int count; - int status; - - layerSize = rows * cols; - dwImageSize = layers * rows * cols; - ccompImage = calloc(dwImageSize, sizeof(int )); - - Label = 1; - for(i = 1; i < layers-1; ++i){ - lOffset = i * layerSize; - lOffsetP = lOffset+layerSize; - lOffsetN = lOffset-layerSize; - for(j = 1; j < rows-1; ++j){ - rOffset = j * cols; - rOffsetP = rOffset+cols; - rOffsetN = rOffset-cols; - for(k = 1; k < cols-1; ++k){ - if(edges[lOffset+rOffset+k]){ - /* - check 3x3x3 connectivity - */ - - T[0] = edges[lOffset+rOffset+k]; - T[1] = edges[lOffset+rOffset+k+1]; - T[2] = edges[lOffset+rOffsetN+k+1]; - T[3] = edges[lOffset+rOffsetN+k]; - T[4] = edges[lOffset+rOffsetN+k-1]; - T[5] = edges[lOffset+rOffset+k-1]; - T[6] = edges[lOffset+rOffsetP+k-1]; - T[7] = edges[lOffset+rOffsetP+k]; - T[8] = edges[lOffset+rOffsetP+k+1]; - - T[9] = edges[lOffsetN+rOffset+k]; - T[10] = edges[lOffsetN+rOffset+k+1]; - T[11] = edges[lOffsetN+rOffsetN+k+1]; - T[12] = edges[lOffsetN+rOffsetN+k]; - T[13] = edges[lOffsetN+rOffsetN+k-1]; - T[14] = edges[lOffsetN+rOffset+k-1]; - T[15] = edges[lOffsetN+rOffsetP+k-1]; - T[16] = edges[lOffsetN+rOffsetP+k]; - T[17] = edges[lOffsetN+rOffsetP+k+1]; - - T[18] = edges[lOffsetP+rOffset+k]; - T[19] = edges[lOffsetP+rOffset+k+1]; - T[20] = edges[lOffsetP+rOffsetN+k+1]; - T[21] = edges[lOffsetP+rOffsetN+k]; - T[22] = edges[lOffsetP+rOffsetN+k-1]; - T[23] = edges[lOffsetP+rOffset+k-1]; - T[24] = edges[lOffsetP+rOffsetP+k-1]; - T[25] = edges[lOffsetP+rOffsetP+k]; - T[26] = edges[lOffsetP+rOffsetP+k+1]; - - connected = FALSE; - if(mask == 1){ - count = 0; - for(l = 1; l < 27; ++l){ - count += T[l]; - } - if(count){ - connected = TRUE; - } - } - else if(mask == 6){ - count = (T[2] + T[4] + T[6] + T[8] + T[9] + T[18]); - if(count == 6){ - connected = TRUE; - } - } - else if(mask == 14){ - count = (T[2] + T[4] + T[6] + T[8] + T[9] + T[18] + T[11] + - T[13] + T[15] + T[17] + T[20] + T[22] + T[24] + T[26]); - if(count == 14){ - connected = TRUE; - } - } - else if(mask == 26){ - count = 0; - for(l = 1; l < 27; ++l){ - count += T[l]; - } - if(count == 26){ - connected = TRUE; - } - } - if(connected){ - ccompImage[lOffset+rOffset+k] = Label++; - } - } - } - } - } - - - while(1){ - Change = FALSE; - /* - // TOP-DOWN Pass for labeling - */ - for(i = 1; i < layers-1; ++i){ - lOffset = i * layerSize; - lOffsetP = lOffset+layerSize; - lOffsetN = lOffset-layerSize; - for(j = 1; j < rows-1; ++j){ - rOffset = j * cols; - rOffsetP = rOffset+cols; - rOffsetN = rOffset-cols; - for(k = 1; k < cols-1; ++k){ - if(ccompImage[lOffset+rOffset+k] != 0){ - - T[0] = ccompImage[lOffset+rOffset+k]; - T[1] = ccompImage[lOffset+rOffset+k+1]; - T[2] = ccompImage[lOffset+rOffsetN+k+1]; - T[3] = ccompImage[lOffset+rOffsetN+k]; - T[4] = ccompImage[lOffset+rOffsetN+k-1]; - T[5] = ccompImage[lOffset+rOffset+k-1]; - T[6] = ccompImage[lOffset+rOffsetP+k-1]; - T[7] = ccompImage[lOffset+rOffsetP+k]; - T[8] = ccompImage[lOffset+rOffsetP+k+1]; - - T[9] = ccompImage[lOffsetN+rOffset+k]; - T[10] = ccompImage[lOffsetN+rOffset+k+1]; - T[11] = ccompImage[lOffsetN+rOffsetN+k+1]; - T[12] = ccompImage[lOffsetN+rOffsetN+k]; - T[13] = ccompImage[lOffsetN+rOffsetN+k-1]; - T[14] = ccompImage[lOffsetN+rOffset+k-1]; - T[15] = ccompImage[lOffsetN+rOffsetP+k-1]; - T[16] = ccompImage[lOffsetN+rOffsetP+k]; - T[17] = ccompImage[lOffsetN+rOffsetP+k+1]; - - T[18] = ccompImage[lOffsetP+rOffset+k]; - T[19] = ccompImage[lOffsetP+rOffset+k+1]; - T[20] = ccompImage[lOffsetP+rOffsetN+k+1]; - T[21] = ccompImage[lOffsetP+rOffsetN+k]; - T[22] = ccompImage[lOffsetP+rOffsetN+k-1]; - T[23] = ccompImage[lOffsetP+rOffset+k-1]; - T[24] = ccompImage[lOffsetP+rOffsetP+k-1]; - T[25] = ccompImage[lOffsetP+rOffsetP+k]; - T[26] = ccompImage[lOffsetP+rOffsetP+k+1]; - - m = T[0]; - for(l = 1; l < 27; ++l){ - if(T[l] != 0){ - if(T[l] < m) m = T[l]; - } - } - if(m != ccompImage[lOffset+rOffset+k]){ - Change = TRUE; - ccompImage[lOffset+rOffset+k] = m; - } - } - } - } - } - /* - // BOTTOM-UP Pass for labeling - */ - for(i = layers-1; i > 0; --i){ - lOffset = i * layerSize; - lOffsetP = lOffset+layerSize; - lOffsetN = lOffset-layerSize; - for(j = rows-1; j > 0; --j){ - rOffset = j * cols; - rOffsetP = rOffset+cols; - rOffsetN = rOffset-cols; - for(k = cols-1; k > 0; --k){ - if(ccompImage[lOffset+rOffset+k] != 0){ - - T[0] = ccompImage[lOffset+rOffset+k]; - T[1] = ccompImage[lOffset+rOffset+k+1]; - T[2] = ccompImage[lOffset+rOffsetN+k+1]; - T[3] = ccompImage[lOffset+rOffsetN+k]; - T[4] = ccompImage[lOffset+rOffsetN+k-1]; - T[5] = ccompImage[lOffset+rOffset+k-1]; - T[6] = ccompImage[lOffset+rOffsetP+k-1]; - T[7] = ccompImage[lOffset+rOffsetP+k]; - T[8] = ccompImage[lOffset+rOffsetP+k+1]; - - T[9] = ccompImage[lOffsetN+rOffset+k]; - T[10] = ccompImage[lOffsetN+rOffset+k+1]; - T[11] = ccompImage[lOffsetN+rOffsetN+k+1]; - T[12] = ccompImage[lOffsetN+rOffsetN+k]; - T[13] = ccompImage[lOffsetN+rOffsetN+k-1]; - T[14] = ccompImage[lOffsetN+rOffset+k-1]; - T[15] = ccompImage[lOffsetN+rOffsetP+k-1]; - T[16] = ccompImage[lOffsetN+rOffsetP+k]; - T[17] = ccompImage[lOffsetN+rOffsetP+k+1]; - - T[18] = ccompImage[lOffsetP+rOffset+k]; - T[19] = ccompImage[lOffsetP+rOffset+k+1]; - T[20] = ccompImage[lOffsetP+rOffsetN+k+1]; - T[21] = ccompImage[lOffsetP+rOffsetN+k]; - T[22] = ccompImage[lOffsetP+rOffsetN+k-1]; - T[23] = ccompImage[lOffsetP+rOffset+k-1]; - T[24] = ccompImage[lOffsetP+rOffsetP+k-1]; - T[25] = ccompImage[lOffsetP+rOffsetP+k]; - T[26] = ccompImage[lOffsetP+rOffsetP+k+1]; - - m = T[0]; - for(l = 1; l < 27; ++l){ - if(T[l] != 0){ - if(T[l] < m) m = T[l]; - } - } - if(m != ccompImage[lOffset+rOffset+k]){ - Change = TRUE; - ccompImage[lOffset+rOffset+k] = m; - } - } - } - } - } - - if(!Change) break; - - } /* end while loop */ - - Label = 1; - Classes[0] = 0; - ptr = 0; - for(i = 0; i < layers; ++i){ - for(j = 0; j < rows; ++j){ - for(k = 0; k < cols; ++k){ - m = ccompImage[ptr]; - ++ptr; - if(m > 0){ - NewLabel = TRUE; - for(l = 1; l < Label; ++l){ - if(Classes[l] == m) NewLabel = FALSE; - } - if(NewLabel){ - Classes[Label++] = m; - if(Label > 4000){ - return 0; - } - } - } - } - } - } - - *groups = Label; - - ptr = 0; - for(i = 0; i < layers; ++i){ - for(j = 0; j < rows; ++j){ - for(k = 0; k < cols; ++k){ - m = ccompImage[ptr]; - for(l = 1; l < Label; ++l){ - if(Classes[l] == m){ - connectedEdges[ptr] = l; - break; - } - } - ++ptr; - } - } - } - - free(ccompImage); - - status = 1; - return(status); - -} - -int NI_GetBlobs2D(int samples, int rows, int cols, unsigned short *edges, unsigned short *connectedEdges, - int *groups, int mask){ - - int i, j, k, l, m; - int offset; - int Label; - int status; - int Classes[4096]; - bool NewLabel; - bool Change; - bool connected; - int count; - unsigned short T[12]; - - /* - // connected components labeling. pixels with 1, 4 or 8 connectedness. - */ - Label = 1; - offset = 0; - for(i = 0; i < rows; ++i){ - for(j = 0; j < cols; ++j){ - connectedEdges[offset+j] = 0; - if(edges[offset+j] == 1){ - connected = FALSE; - if(mask == 1){ - count = 0; - for(l = 1; l < 9; ++l){ - count += T[l]; - } - if(count){ - connected = TRUE; - } - } - else if(mask == 4){ - count = (T[2] + T[4] + T[6] + T[8]); - if(count == 4){ - connected = TRUE; - } - } - else if(mask == 8){ - count = 0; - for(l = 1; l < 9; ++l){ - count += T[l]; - } - if(count == 8){ - connected = TRUE; - } - } - if(connected){ - connectedEdges[offset+j] = Label++; - } - } - } - offset += cols; - } - - while(1){ - Change = FALSE; - /* - // TOP-DOWN Pass for labeling - */ - offset = cols; - for(i = 1; i < rows-1; ++i){ - for(j = 1; j < cols-1; ++j){ - if(connectedEdges[offset+j] != 0){ - T[0] = connectedEdges[offset+j]; - T[1] = connectedEdges[offset+j+1]; - T[2] = connectedEdges[offset-cols+j+1]; - T[3] = connectedEdges[offset-cols+j]; - T[4] = connectedEdges[offset-cols+j-1]; - T[5] = connectedEdges[offset+j-1]; - T[6] = connectedEdges[offset+cols+j-1]; - T[7] = connectedEdges[offset+cols+j]; - T[8] = connectedEdges[offset+cols+j+1]; - m = T[0]; - for(l = 1; l < 9; ++l){ - if(T[l] != 0){ - if(T[l] < m) m = T[l]; - } - } - if(m != connectedEdges[offset+j]){ - Change = TRUE; - connectedEdges[offset+j] = m; - } - } - } - offset += cols; - } - /* - // BOTTOM-UP Pass for labeling - */ - offset = (rows-1)*cols; - for(i = (rows-1); i > 1; --i){ - for(j = (cols-1); j > 1; --j){ - if(connectedEdges[offset+j] != 0){ - T[0] = connectedEdges[offset+j]; - T[1] = connectedEdges[offset+j+1]; - T[2] = connectedEdges[offset-cols+j+1]; - T[3] = connectedEdges[offset-cols+j]; - T[4] = connectedEdges[offset-cols+j-1]; - T[5] = connectedEdges[offset+j-1]; - T[6] = connectedEdges[offset+cols+j-1]; - T[7] = connectedEdges[offset+cols+j]; - T[8] = connectedEdges[offset+cols+j+1]; - m = T[0]; - for(l = 1; l < 9; ++l){ - if(T[l] != 0){ - if(T[l] < m) m = T[l]; - } - } - if(m != connectedEdges[offset+j]){ - Change = TRUE; - connectedEdges[offset+j] = m; - } - } - } - offset -= cols; - } - if(!Change) break; - } /* end while loop */ - - Classes[0] = 0; - Label = 1; - offset = cols; - for(i = 1; i < (rows-1); ++i){ - for(j = 1; j < (cols-1); ++j){ - m = connectedEdges[offset+j]; - if(m > 0){ - NewLabel = TRUE; - for(k = 1; k < Label; ++k){ - if(Classes[k] == m) NewLabel = FALSE; - } - if(NewLabel){ - Classes[Label++] = m; - if(Label > 4000){ - return 0; /* too many labeled regions. this is a pathology */ - } - } - } - } - offset += cols; - } - - /* - // re-label the connected blobs in continuous label order - */ - offset = cols; - for(i = 1; i < (rows-1); ++i){ - for(j = 1; j < (cols-1); ++j){ - m = connectedEdges[offset+j]; - if(m > 0){ - for(k = 1; k < Label; ++k){ - if(Classes[k] == m){ - connectedEdges[offset+j] = (unsigned short)k; - break; - } - } - } - } - offset += cols; - } - - *groups = Label; - - /* - // prune the isolated pixels - */ - offset = 0; - for(i = 0; i < rows; ++i){ - for(j = 0; j < cols; ++j){ - if(connectedEdges[offset+j] > (*groups)){ - connectedEdges[offset+j] = 0; - } - } - offset += cols; - } - - status = 1; - return(status); - -} - -int NI_GetBlobRegions3D(int layers, int rows, int cols, int numberObjects, - unsigned short *labeledEdges, objStruct objectMetrics[]){ - - - int status; - int i, j, k, l, m; - int offset; - int count; - int LowX; - int LowY; - int LowZ; - int HighX; - int HighY; - int HighZ; - int ptr; - float centerX; - float centerY; - float centerZ; - - for(l = 1; l < numberObjects; ++l){ - offset = cols; - LowX = 32767; - LowY = 32767; - LowZ = 32767; - HighX = 0; - HighY = 0; - HighZ = 0; - count = 0; - centerX = (float)0.0; - centerY = (float)0.0; - centerZ = (float)0.0; - ptr = 0; - for(i = 0; i < layers; ++i){ - for(j = 0; j < rows; ++j){ - for(k = 0; k < cols; ++k){ - m = labeledEdges[ptr++]; - if(l == m){ - if(i < LowZ) LowZ = i; - if(j < LowY) LowY = j; - if(k < LowX) LowX = k; - if(i > HighZ) HighZ = i; - if(j > HighY) HighY = j; - if(k > HighX) HighX = k; - centerX += (float)k; - centerY += (float)j; - centerZ += (float)i; - ++count; - } - } - } - } - /* the bounding box for the 2D blob */ - objectMetrics[l-1].Left = LowX; - objectMetrics[l-1].Right = HighX; - objectMetrics[l-1].Bottom = LowY; - objectMetrics[l-1].Top = HighY; - objectMetrics[l-1].Front = LowZ; - objectMetrics[l-1].Back = HighZ; - objectMetrics[l-1].Mass = count; - objectMetrics[l-1].cX = centerX/(float)count; - objectMetrics[l-1].cY = centerY/(float)count; - objectMetrics[l-1].cZ = centerZ/(float)count; - objectMetrics[l-1].Label = l; - } - - status = numberObjects; - - return(status); - -} - -int NI_GetBlobRegions2D(int rows, int cols, int numberObjects, unsigned short *labeledEdges, - objStruct objectMetrics[]){ - - int i, j, k, m; - int count; - int LowX; - int LowY; - int HighX; - int HighY; - int status; - int ptr; - float centerX; - float centerY; - - for(k = 1; k < numberObjects; ++k){ - LowX = 32767; - LowY = 32767; - HighX = 0; - HighY = 0; - count = 0; - centerX = (float)0.0; - centerY = (float)0.0; - ptr = 0; - for(i = 0; i < rows; ++i){ - for(j = 0; j < cols; ++j){ - m = labeledEdges[ptr++]; - if(k == m){ - if(i < LowY) LowY = i; - if(j < LowX) LowX = j; - if(i > HighY) HighY = i; - if(j > HighX) HighX = j; - centerX += (float)j; - centerY += (float)i; - ++count; - } - } - } - /* the bounding box for the 2D blob */ - objectMetrics[k-1].Left = LowX; - objectMetrics[k-1].Right = HighX; - objectMetrics[k-1].Bottom = LowY; - objectMetrics[k-1].Top = HighY; - objectMetrics[k-1].Mass = count; - objectMetrics[k-1].cX = centerX/(float)count; - objectMetrics[k-1].cY = centerY/(float)count; - objectMetrics[k-1].Label = k; - } - - status = numberObjects; - return status; - -} - - -int NI_ThinMorphoFilter(int regRows, int regColumns, int spadSize, int masks, unsigned short *J_mask, - unsigned short *K_mask, unsigned char *Input, unsigned char *CInput, - unsigned char *ErosionStage, unsigned char *DialationStage, - unsigned char *HMT, unsigned char *Copy){ - - int i, j, k, l, m, n, overlap, hit; - int LowValue1, HighValue1; - int LowValue2, HighValue2; - int Column, T, nloop; - int Offset; - int N, M; - int maskCols = 3; - int j_mask[3][3]; - int k_mask[3][3]; - int status; - - N = regRows; - M = regColumns; - - LowValue1 = 1; - HighValue1 = 0; - - LowValue2 = 0; - HighValue2 = 1; - - Offset = 0; - for(i = 0; i < N; ++i){ - for(j = 0; j < M; ++j){ - Copy[Offset+j] = Input[Offset+j]; - } - Offset += spadSize; - } - - nloop = 0; - while(1){ - /* erode */ - Column = 0; - for(n = 0; n < masks; ++n){ - for(i = 0; i < 3; ++i){ - for(j = 0; j < 3; ++j){ - j_mask[i][j] = J_mask[i+maskCols*(Column+j)]; - } - } - for(i = 0; i < 3; ++i){ - for(j = 0; j < 3; ++j){ - k_mask[i][j] = K_mask[i+maskCols*(Column+j)]; - } - } - Column += 3; - - Offset = spadSize; - for(i = 1; i < N-1; ++i){ - for(j = 1; j < M-1; ++j){ - hit = LowValue1; - for(k = -1; k < 2; ++k){ - for(l = -1; l < 2; ++l){ - T = j_mask[k+1][l+1]; - if(T == 1){ - overlap = T*Input[Offset+(k*spadSize)+j+l]; - if(overlap == HighValue1) hit = HighValue1; - } - } - } - ErosionStage[Offset+j] = hit; - } - Offset += spadSize; - } - - /* dialate */ - Offset = 0; - for(i = 0; i < N; ++i){ - for(j = 0; j < M; ++j){ - CInput[Offset+j] = (~Input[Offset+j]) & 0x1; - } - Offset += spadSize; - } - - Offset = spadSize; - for(i = 1; i < N-1; ++i){ - for(j = 1; j < M-1; ++j){ - hit = LowValue1; - for(k = -1; k < 2; ++k){ - for(l = -1; l < 2; ++l){ - T = k_mask[k+1][l+1]; - if(T == 1){ - overlap = T*CInput[Offset+(k*spadSize)+j+l]; - if(overlap == HighValue1) hit = HighValue1; - } - } - } - DialationStage[Offset+j] = hit; - } - Offset += spadSize; - } - - /* form the HMT */ - Offset = 0; - for(i = 0; i < N; ++i){ - for(j = 0; j < M; ++j){ - m = (ErosionStage[Offset+j]*DialationStage[Offset+j]); - HMT[Offset+j] = m; - } - Offset += spadSize; - } - - /* Thin for stage n */ - - Offset = 0; - for(i = 0; i < N; ++i){ - for(j = 0; j < M; ++j){ - HMT[Offset+j] = (~HMT[Offset+j]) & 0x1; - } - Offset += spadSize; - } - - Offset = 0; - for (i = 0; i < N; ++i){ - for (j = 0; j < M; ++j){ - m = (Input[Offset+j]*HMT[Offset+j]); - Input[Offset+j] = m; - } - Offset += spadSize; - } - } - - /* check for no change */ - hit = 0; - Offset = 0; - for(i = 0; i < N; ++i){ - for(j = 0; j < M; ++j){ - hit += abs(Copy[Offset+j]-Input[Offset+j]); - } - Offset += spadSize; - } - if(!hit) break; - - hit = 0; - Offset = 0; - for(i = 0; i < N; ++i){ - for(j = 0; j < M; ++j){ - Copy[Offset+j] = Input[Offset+j]; - if(Input[Offset+j]) ++hit; - } - Offset += spadSize; - } - /* nloop is data dependent. */ - ++nloop; - } - - - status = 1; - return status; - -} - - -int NI_CannyFilter(int samples, int rows, int cols, double *rawImage, - double *hDGImage, double *vDGImage, double *dgKernel, - int gWidth, float *aveXValue, float *aveYValue){ - - - /* - // implements the derivative of Gaussian filter. kernel set by CannyEdges - */ - int i, j, k; - int ptr; - int mLength; - int count; - int status; - float *tBuffer = NULL; - double sum; - - *aveXValue = (float)0.0; - *aveYValue = (float)0.0; - - mLength = MAX(rows, cols) + 64; - tBuffer = calloc(mLength, sizeof(float)); - - /* - // filter X - */ - count = 0; - for(i = 0; i < rows; ++i){ - ptr = i * cols; - for(j = gWidth; j < cols-gWidth; ++j){ - sum = dgKernel[0] * rawImage[ptr+j]; - for(k = 1; k < gWidth; ++k){ - sum += dgKernel[k] * (-rawImage[ptr+j+k] + rawImage[ptr+j-k]); - } - hDGImage[ptr+j] = (float)sum; - if(sum != (float)0.0){ - ++count; - *aveXValue += (float)fabs(sum); - } - } - } - if(count){ - *aveXValue /= (float)count; - } - /* - // filter Y - */ - count = 0; - for(i = 0; i < cols; ++i){ - for(j = 0; j < rows; ++j){ - ptr = j * cols; - tBuffer[j] = rawImage[ptr+i]; - } - for(j = gWidth; j < rows-gWidth; ++j){ - ptr = j * cols; - sum = dgKernel[0] * tBuffer[j]; - for(k = 1; k < gWidth; ++k){ - sum += dgKernel[k] * (-tBuffer[j+k] + tBuffer[j-k]); - } - vDGImage[ptr+i] = sum; - if(sum != (float)0.0){ - ++count; - *aveYValue += (float)fabs(sum); - } - } - } - if(count){ - *aveYValue /= (float)count; - } - - free(tBuffer); - - status = 1; - - return status; - -} - -double tmagnitude(double X, double Y){ - return sqrt(X*X + Y*Y); -} - -int NI_CannyNonMaxSupress(int num, int rows, int cols, double *magImage, double *hDGImage, - double *vDGImage, int mode, double aveXValue, double aveYValue, - double *tAve, double *cannyLow, double *cannyHigh, - double cannyL, double cannyH){ - - int i, j; - int ptr, ptr_m1, ptr_p1; - float xSlope, ySlope, G1, G2, G3, G4, G, xC, yC; - float scale; - float maxValue = (float)0.0; - float minValue = (float)0.0; - int value; - int mValue; - int mIndex; - int count; - int status; - int histogram[256]; - double step; - - for(i = 1; i < rows-1; ++i){ - ptr = i * cols; - ptr_m1 = ptr - cols; - ptr_p1 = ptr + cols; - for(j = 1; j < cols; ++j){ - magImage[ptr+j] = (float)0.0; - xC = hDGImage[ptr+j]; - yC = vDGImage[ptr+j]; - if(!((fabs(xC) < aveXValue) && (fabs(yC) < aveYValue))){ - G = tmagnitude(xC, yC); - if(fabs(yC) > fabs(xC)){ - /* vertical gradient */ - xSlope = (float)(fabs(xC) / fabs(yC)); - ySlope = (float)1.0; - G2 = tmagnitude(hDGImage[ptr_m1+j], vDGImage[ptr_m1+j]); - G4 = tmagnitude(hDGImage[ptr_p1+j], vDGImage[ptr_p1+j]); - if((xC*yC) > (float)0.0){ - G1 = tmagnitude(hDGImage[ptr_m1+j-1], vDGImage[ptr_m1+j-1]); - G3 = tmagnitude(hDGImage[ptr_p1+j+1], vDGImage[ptr_p1+j+1]); - } - else{ - G1 = tmagnitude(hDGImage[ptr_m1+j+1], vDGImage[ptr_m1+j+1]); - G3 = tmagnitude(hDGImage[ptr_p1+j-1], vDGImage[ptr_p1+j-1]); - } - } - else{ - /* horizontal gradient */ - xSlope = (float)(fabs(yC) / fabs(xC)); - ySlope = (float)1.0; - G2 = tmagnitude(hDGImage[ptr+j+1], vDGImage[ptr+j+1]); - G4 = tmagnitude(hDGImage[ptr+j-1], vDGImage[ptr+j-1]); - if((xC*yC) > (float)0.0){ - G1 = tmagnitude(hDGImage[ptr_p1+j+1], vDGImage[ptr_p1+j+1]); - G3 = tmagnitude(hDGImage[ptr_m1+j-1], vDGImage[ptr_m1+j-1]); - } - else{ - G1 = tmagnitude(hDGImage[ptr_m1+j+1], vDGImage[ptr_m1+j+1]); - G3 = tmagnitude(hDGImage[ptr_p1+j-1], vDGImage[ptr_p1+j-1]); - } - } - if((G > (xSlope*G1+(ySlope-xSlope)*G2))&&(G > (xSlope*G3+(ySlope-xSlope)*G4))){ - magImage[ptr+j] = G; - } - if(magImage[ptr+j] > maxValue) maxValue = magImage[ptr+j]; - if(magImage[ptr+j] < minValue) minValue = magImage[ptr+j]; - } - } - } - - scale = (float)1.0 / (maxValue-minValue); - ptr = 0; - count = 0; - *tAve = 0.0; - for(i = 0; i < rows; ++i){ - for(j = 0; j < cols; ++j){ - magImage[ptr] = scale * (magImage[ptr]-minValue); - if(magImage[ptr] > 0.0){ - *tAve += magImage[ptr]; - ++count; - } - ++ptr; - } - } - *tAve /= (float)count; - - step = 255.0; - for(i = 0; i < 256; ++i){ - histogram[i] = 0; - } - ptr = 0; - for(i = 0; i < rows; ++i){ - for(j = 0; j < cols; ++j){ - value = (int)(step*(magImage[ptr])); - ++histogram[value]; - ++ptr; - } - } - /* - // now get the max after skipping the low values - */ - mValue = -1; - mIndex = 0; - for(i = 10; i < 256; ++i){ - if(histogram[i] > mValue){ - mValue = histogram[i]; - mIndex = i; - } - } - - if(mode == 1){ - /* based on the mean value of edge energy */ - *cannyLow = ((cannyL) * *tAve); - *cannyHigh = ((cannyH) * *tAve); - } - else{ - /* based on the mode value of edge energy */ - *cannyLow = ((cannyL) * ((float)mIndex/step)); - *cannyHigh = ((cannyH) * ((float)mIndex/step)); - } - status = 1; - - return status; - -} - -int trace_Edge(int i, int j, int rows, int cols, double cannyLow, double *magImage, - unsigned short *hys_image){ - - int n, m; - int ptr; - int flag; - - ptr = i * cols; - if(hys_image[ptr+j] == 0){ - /* - // this point is above high threshold - */ - hys_image[ptr+j] = 1; - flag = 0; - for(n = -1; n <= 1; ++n){ - for(m = -1; m <= 1; ++m){ - if(n == 0 && m == 0) continue; - if(((i+n) > 0) && ((j+m) > 0) && ((i+n) < rows) && ((j+m) < cols)){ - ptr = (i+n) * cols; - if(magImage[ptr+j+m] > cannyLow){ - /* - // this point is above low threshold - */ - if(trace_Edge(i+n, j+m, rows, cols, cannyLow, magImage, hys_image)){ - flag = 1; - break; - } - } - } - } - if(flag) break; - } - return(1); - } - - return(0); - -} - -int NI_CannyHysteresis(int num, int rows, int cols, double *magImage, unsigned short *hys_image, - double cannyLow, double cannyHigh){ - - - int status; - int i, j; - int ptr; - - for(i = 0; i < rows; ++i){ - ptr = i * cols; - for(j = 0; j < cols; ++j){ - if(magImage[ptr+j] > cannyHigh){ - trace_Edge(i, j, rows, cols, cannyLow, magImage, hys_image); - } - } - } - - status = 1; - - return status; - -} - -float lawsConvolution(float *image, float *rowFilter, float *colFilter, int kernelSize){ - - int i, j; - int offset; - float result[7]; - float sum; - - /* filter rows */ - for(i = 0; i < kernelSize; ++i){ - sum = (float)0.0; - offset = i * kernelSize; - for(j = 0; j < kernelSize; ++j){ - sum += (rowFilter[j]*image[offset+j]); - } - result[i] = sum; - } - - /* filter columns */ - sum = (float)0.0; - for(j = 0; j < kernelSize; ++j){ - sum += (rowFilter[j]*result[j]); - } - - return(sum); - -} - -void computeLaws(LawsFilter7 lawsFilter, int aperature, int srcRows, int srcCols, - unsigned short *MaskImage, float *lawsImage, double *sourceImage){ - - /* - // hard-wirred to Law's 7 kernels - */ - int i, j; - int lawsLayer; - int column, row; - int maskOffset[7]; - int dataOffset[7]; - float myImage[49]; - int count; - int outerKernelNumber; - int innerKernelNumber; - int rowNumber; - int kernelSize = lawsFilter.kernelLength; - int fullMask = kernelSize*kernelSize; - int layerStep = srcRows*srcCols; - float *rowFilter; - float *colFilter; - float filterResult1; - float filterResult2; - float lawsLL=1.0; - - for(i = aperature; i < srcRows-aperature; ++i){ - // get the row array offset for mask and data source. - for(row = -aperature; row <= aperature; ++row){ - maskOffset[row+aperature] = (i+row)*srcCols; - dataOffset[row+aperature] = maskOffset[row+aperature]; - } - for(j = aperature; j < srcCols-aperature; ++j){ - /* - // get 7x7 segment and make sure have 100% mask coverage - */ - count = 0; - for(row = -aperature; row <= aperature; ++row){ - rowNumber = (row+aperature)*kernelSize; - for(column = -aperature; column <= aperature; ++column){ - if(MaskImage[maskOffset[row+aperature]+j+column]){ - myImage[rowNumber+column+aperature] = sourceImage[dataOffset[row+aperature]+j+column]; - ++count; - } - } - } - if(count == fullMask){ - /* - // 100% mask coverage. now do the Law's texture filters - */ - lawsLayer = 0; - for(outerKernelNumber = 0; outerKernelNumber < lawsFilter.numberKernels; ++outerKernelNumber){ - /* - // outer loop pulls the i'th kernel. kernel 0 is the LP kernel - // the outer loop is the iso-kernel - */ - rowFilter = &lawsFilter.lawsKernel[outerKernelNumber][0]; - colFilter = &lawsFilter.lawsKernel[outerKernelNumber][0]; - filterResult1 = lawsConvolution(myImage, rowFilter, colFilter, kernelSize); - /* lawsLayer 0 is the LP and needs to be used to scale. */ - if(outerKernelNumber){ - lawsImage[lawsLayer*layerStep + i*srcCols + j] = (float)2.0 * filterResult1; - } - else{ - lawsLL = filterResult1; - lawsLL = (float)2.0 * filterResult1; - lawsImage[lawsLayer*layerStep + i*srcCols + j] = (float)2.0 * filterResult1; - } - ++lawsLayer; - /* - // now do the inner loop and get the column filters for the other laws kernels - */ - for(innerKernelNumber = outerKernelNumber+1; - innerKernelNumber < lawsFilter.numberKernels; - ++innerKernelNumber){ - colFilter = &lawsFilter.lawsKernel[innerKernelNumber][0]; - filterResult1 = lawsConvolution(myImage, rowFilter, colFilter, kernelSize); - filterResult2 = lawsConvolution(myImage, colFilter, rowFilter, kernelSize); - lawsImage[lawsLayer*layerStep + i*srcCols + j] = filterResult1 + filterResult2; - ++lawsLayer; - } - } - } - } - } - - return; - -} - - -int NI_LawsTexture(int num, int rows, int cols, double *src_image, unsigned short *mask, - float *lawsImage, LawsFilter7 lawsFilter){ - - int status; - int number_kernels; - int kernel_size; - int filters; - int aperature; - number_kernels = lawsFilter.numberKernels; - kernel_size = lawsFilter.kernelLength; - filters = lawsFilter.numberFilterLayers; - aperature = (kernel_size-1)/2; - - computeLaws(lawsFilter, aperature, rows, cols, mask, lawsImage, src_image); - - status = 1; - - return status; - -} - - -int NI_RoiCoOccurence(int samples, int rows, int cols, unsigned short *labelImage, - unsigned short *rawImage, int *cocMatrix, int distance, int orientation){ - - int i, j; - int offset; - int d_row; - int d_col; - int status; - int start_row; - int stop_row; - int start_col; - int stop_col; - int mask; - int pixel; - int d_mask_value; - int d_pixel_value; - - /* built around 8 bit histograms */ - - offset = 0; - if(orientation == 90){ - start_row = 0; - stop_row = rows; - start_col = 0; - stop_col = cols-distance; - d_row = 0; - d_col = distance; - } - else if(orientation == 180){ - start_row = 0; - stop_row = rows-distance; - start_col = 0; - stop_col = cols; - d_row = cols*distance; - d_col = 0; - } - else if(orientation == 45){ - start_row = 0; - stop_row = rows-distance; - start_col = distance; - stop_col = cols; - d_row = cols*distance; - d_col = -distance; - } - else if(orientation == 135){ - start_row = 0; - stop_row = rows-distance; - start_col = 0; - stop_col = cols-distance; - d_row = cols*distance; - d_col = distance; - } - - for(i = start_row; i < stop_row; ++i){ - for(j = start_col; j < stop_col; ++j){ - mask = labelImage[offset+j]; - if(mask){ - /* d rows away from current row */ - pixel = rawImage[offset+j]; - d_mask_value = labelImage[offset+d_row+j+d_col]; - if(d_mask_value){ - /* over the mask */ - d_pixel_value = rawImage[offset+d_row+j+d_col]; - /* update the 2D joint histograms */ - ++cocMatrix[d_pixel_value*256+pixel]; - ++cocMatrix[d_pixel_value+pixel*256]; - } - } - } - offset += cols; - } - - status = 1; - - return(status); - -} - -int NI_GrowRegion2D(int rows, int cols, double *rawimage, unsigned short *label, - objStruct *expanded_ROI, objStruct *newgrow_ROI, double low_threshold, - double high_threshold, int Label, int N_connectivity){ - - int i, j, p, m; - int offset; - int offsetM, offsetP; - int status; - int T[8], count; - int LowX; - int LowY; - int HighX; - int HighY; - double value; - bool change; - - while(1){ - change = FALSE; - for(i = 1; i < rows-1; ++i){ - offset = i * cols; - offsetM = offset - cols; - offsetP = offset + cols; - for(j = 1; j < cols-1; ++j){ - m = label[offset+j]; - if(!m){ - /* un-labeled pixel */ - value = rawimage[offset+j]; - if((value > low_threshold) && (value < high_threshold)){ - /* check for N-connectivity */ - T[0] = label[offset+j+1]; - T[1] = label[offsetM+j+1]; - T[2] = label[offsetM+j]; - T[3] = label[offsetM+j-1]; - T[4] = label[offset+j-1]; - T[5] = label[offsetP+j-1]; - T[6] = label[offsetP+j]; - T[7] = label[offsetP+j+1]; - count = 0; - for(p = 0; p < 8; ++p){ - if(T[p] == Label){ - ++count; - } - } - if(count > N_connectivity){ - label[offset+j] = Label; - change = TRUE; - } - } - } - } - } - if(!change) break; - } - - /* get new bounding box */ - newgrow_ROI->Left = expanded_ROI->Left + LowX; - newgrow_ROI->Right = newgrow_ROI->Left + (HighX-LowX); - newgrow_ROI->Bottom = expanded_ROI->Bottom + LowY; - newgrow_ROI->Top = expanded_ROI->Bottom + (HighY-LowY); - newgrow_ROI->Mass = count; - - status = 1; - - return(status); - -} - -int NI_GrowRegion3D(int layers, int rows, int cols, double *rawimage, unsigned short *label, - objStruct *expanded_ROI, objStruct *newgrow_ROI, double low_threshold, - double high_threshold, int Label, int N_connectivity){ - - int i, j, k, m, p; - int offset; - int ptr; - int lOffset, rOffset; - int lOffsetP, lOffsetN; - int rOffsetP, rOffsetN; - int layerSize; - int status; - int T[26], count; - int LowX; - int LowY; - int LowZ; - int HighX; - int HighY; - int HighZ; - float centerX; - float centerY; - float centerZ; - double value; - bool change; - - layerSize = rows * cols; - while(1){ - change = FALSE; - for(i = 1; i < layers-1; ++i){ - lOffset = i * layerSize; - lOffsetP = lOffset+layerSize; - lOffsetN = lOffset-layerSize; - for(j = 1; j < rows-1; ++j){ - rOffset = j * cols; - rOffsetP = rOffset+cols; - rOffsetN = rOffset-cols; - for(k = 1; k < cols-1; ++k){ - m = label[lOffset+rOffset+k]; - if(!m){ - /* un-labeled voxel */ - value = rawimage[lOffset+rOffset+k]; - if((value > low_threshold) && (value < high_threshold)){ - /* check for N-connectivity */ - T[0] = label[lOffset+rOffset+k+1]; - T[1] = label[lOffset+rOffsetN+k+1]; - T[2] = label[lOffset+rOffsetN+k]; - T[3] = label[lOffset+rOffsetN+k-1]; - T[4] = label[lOffset+rOffset+k-1]; - T[5] = label[lOffset+rOffsetP+k-1]; - T[6] = label[lOffset+rOffsetP+k]; - T[7] = label[lOffset+rOffsetP+k+1]; - - T[8] = label[lOffsetN+rOffset+k]; - T[9] = label[lOffsetN+rOffset+k+1]; - T[10] = label[lOffsetN+rOffsetN+k+1]; - T[11] = label[lOffsetN+rOffsetN+k]; - T[12] = label[lOffsetN+rOffsetN+k-1]; - T[13] = label[lOffsetN+rOffset+k-1]; - T[14] = label[lOffsetN+rOffsetP+k-1]; - T[15] = label[lOffsetN+rOffsetP+k]; - T[16] = label[lOffsetN+rOffsetP+k+1]; - - T[17] = label[lOffsetP+rOffset+k]; - T[18] = label[lOffsetP+rOffset+k+1]; - T[19] = label[lOffsetP+rOffsetN+k+1]; - T[20] = label[lOffsetP+rOffsetN+k]; - T[21] = label[lOffsetP+rOffsetN+k-1]; - T[22] = label[lOffsetP+rOffset+k-1]; - T[23] = label[lOffsetP+rOffsetP+k-1]; - T[24] = label[lOffsetP+rOffsetP+k]; - T[25] = label[lOffsetP+rOffsetP+k+1]; - - count = 0; - for(p = 0; p < 26; ++p){ - if(T[p] == Label){ - ++count; - } - } - if(count > N_connectivity){ - label[lOffset+rOffset+k]= Label; - change = TRUE; - } - } - } - } - } - } - if(!change) break; - } - - LowX = 32767; - LowY = 32767; - LowZ = 32767; - HighX = 0; - HighY = 0; - HighZ = 0; - count = 0; - centerX = (float)0.0; - centerY = (float)0.0; - centerZ = (float)0.0; - ptr = 0; - count = 0; - for(i = 0; i < layers; ++i){ - for(j = 0; j < rows; ++j){ - for(k = 0; k < cols; ++k){ - m = label[ptr++]; - if(m == Label){ - if(i < LowZ) LowZ = i; - if(j < LowY) LowY = j; - if(k < LowX) LowX = k; - if(i > HighZ) HighZ = i; - if(j > HighY) HighY = j; - if(k > HighX) HighX = k; - centerX += (float)k; - centerY += (float)j; - centerZ += (float)i; - ++count; - } - } - } - } - - newgrow_ROI->Left = expanded_ROI->Left + LowX; - newgrow_ROI->Right = newgrow_ROI->Left + (HighX-LowX); - newgrow_ROI->Bottom = expanded_ROI->Bottom + LowY; - newgrow_ROI->Top = newgrow_ROI->Bottom + (HighY-LowY); - newgrow_ROI->Front = expanded_ROI->Front + LowZ; - newgrow_ROI->Back = expanded_ROI->Front + (HighZ-LowZ); - newgrow_ROI->Mass = count; - - status = 1; - - return(status); - -} - - +#include +#include +#include +#include +#include "ndImage_Segmenter_structs.h" + +// these are for this standalone and come out with the full build +// +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define FALSE 0 +#define TRUE 1 + + +int NI_EdgePreFilter(int num, int rows, int cols, int lowThreshold, int highThreshold, + int aperature, int HalfFilterTaps, unsigned short *sImage, double *dImage, + double *kernel){ + + int i, j, k, n, num1; + int offset; + double sum, value; + double *buffer; + int max_buffer = MAX(rows, cols); + int status; + + buffer = calloc(max_buffer+aperature+16, sizeof(double)); + + num1 = HalfFilterTaps; + offset = 0; + for(i = 0; i < rows; ++i){ + /* copy image row to local buffer */ + for(j = 0; j < cols; ++j){ + buffer[num1+j] = sImage[offset+j]; + } + /* constant pad the ends of the buffer */ + for(j = 0; j < num1; ++j){ + buffer[j] = buffer[num1]; + } + for(j = cols+num1; j < cols+2*num1; ++j){ + buffer[j] = buffer[cols-1+num1]; + } + + /* Perform Symmetric Convolution in the X dimension. */ + for(n = 0, j = num1; j < (cols+num1); ++j, ++n){ + sum = buffer[j] * kernel[num1]; + for(k = 1; k < num1; ++k){ + sum += kernel[num1-k] * (buffer[j+k] + buffer[j-k]); + } + dImage[offset+n] = sum; + } + offset += cols; + } + + offset = 0; + for(i = 0; i < cols; ++i){ + /* copy image column to local buffer */ + offset = 0; + for(j = 0; j < rows; ++j){ + buffer[num1+j] = dImage[offset+i]; + offset += cols; + } + /* constant pad the ends of the buffer */ + for(j = 0; j < num1; ++j){ + buffer[j] = buffer[num1]; + } + for(j = rows+num1; j < rows+2*num1; ++j){ + buffer[j] = buffer[rows-1+num1]; + } + + /* Perform Symmetric Convolution in the Y dimension. */ + offset = 0; + for(j = num1; j < (rows+num1); ++j){ + sum = buffer[j] * kernel[num1]; + for(k = 1; k < num1; ++k){ + sum += kernel[num1-k] * (buffer[j+k] + buffer[j-k]); + } + dImage[offset+i] = sum; + offset += cols; + } + } + + /* threshold the image */ + offset = 0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + value = dImage[offset+j]; + if(value < (float)lowThreshold) value = (float)0.0; + if(value > (float)highThreshold) value = (float)0.0; + dImage[offset+j] = value; + } + offset += cols; + } + + free(buffer); + + status = 1; + + return(status); + +} + +int NI_SobelImage(int samples, int rows, int cols, double *rawImage, double *edgeImage, double *pAve, + int *minValue, int *maxValue){ + + int i, j; + int p, m, n; + int offset; + int offsetM1; + int offsetP1; + int status; + int count = 0; + + /* + // Sobel + */ + offset = cols; + *pAve = 0.0; + *minValue = 10000; + *maxValue = -10000; + for(i = 1; i < rows-1; ++i){ + offsetM1 = offset - cols; + offsetP1 = offset + cols; + for(j = 1; j < cols-1; ++j){ + n = 2*rawImage[offsetM1+j] + rawImage[offsetM1+j-1] + rawImage[offsetM1+j+1] - + 2*rawImage[offsetP1+j] - rawImage[offsetP1+j-1] - rawImage[offsetP1+j+1]; + m = 2*rawImage[offset+j-1] + rawImage[offsetM1+j-1] + rawImage[offsetP1+j-1] - + 2*rawImage[offset+j+1] - rawImage[offsetM1+j+1] - rawImage[offsetP1+j+1]; + p = (int)sqrt((float)(m*m) + (float)(n*n)); + if(p > 0){ + *pAve += p; + if(p > *maxValue) *maxValue = p; + if(p < *minValue) *minValue = p; + ++count; + } + edgeImage[offset+j] = p; + } + offset += cols; + } + /* threshold based on ave */ + *pAve /= count; + + status = 1; + + return(status); + +} + + +int NI_BinaryEdge(int samples, int rows, int cols, unsigned short *labelImage, unsigned short *edgeImage){ + + int i, j, k; + int maxValue; + int offset; + int offsetM1; + int offsetP1; + int values3x3[8]; + int status; + + offset = cols; + for(i = 1; i < rows-1; ++i){ + offsetM1 = offset - cols; + offsetP1 = offset + cols; + for(j = 1; j < cols-1; ++j){ + values3x3[0] = labelImage[offset+j] - labelImage[offset+j+1]; + values3x3[1] = labelImage[offset+j] - labelImage[offsetM1+j+1]; + values3x3[2] = labelImage[offset+j] - labelImage[offsetM1+j]; + values3x3[3] = labelImage[offset+j] - labelImage[offsetM1+j-1]; + values3x3[4] = labelImage[offset+j] - labelImage[offset+j-1]; + values3x3[5] = labelImage[offset+j] - labelImage[offsetP1+j-1]; + values3x3[6] = labelImage[offset+j] - labelImage[offsetP1+j]; + values3x3[7] = labelImage[offset+j] - labelImage[offsetP1+j+1]; + maxValue = -1; + for(k = 0; k < 8; ++k){ + maxValue = MAX(maxValue, values3x3[k]); + } + edgeImage[offset+j] = maxValue; + } + offset += cols; + } + + status = 1; + + return(status); + +} + +int NI_SobelEdge(int samples, int rows, int cols, double *edgeImage, unsigned short *edges, + int mode, double pAve, int minValue, int maxValue, double sobelLow){ + + int i, j; + int offset; + int value; + int maxIndex; + int status; + int histogram[256]; + float pThreshold; + double scale; + double step; + + scale = 1.0 / maxValue; + + step = 255.0/(maxValue-minValue); + for(i = 0; i < 256; ++i){ + histogram[i] = 0; + } + offset = 0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + value = (int)(step*(edgeImage[offset+j]-minValue)); + ++histogram[value]; + } + offset += cols; + } + + if(mode == 1){ + /* based on the mean value of edge energy */ + pThreshold = (int)(sobelLow * (float)pAve); + } + else{ + /* based on the mode value of edge energy */ + pThreshold = (sobelLow * (minValue + ((float)maxIndex/step))); + } + + offset = 0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + if(edgeImage[offset+j] > pThreshold){ + edges[offset+j] = 1; + } + else{ + edges[offset+j] = 0; + } + } + offset += cols; + } + + status = 1; + return(status); + +} + +int NI_GetBlobs3D(int samples, int layers, int rows, int cols, unsigned short *edges, + unsigned short *connectedEdges, int *groups, int mask){ + + int i, j, k, l, m; + int lOffset, rOffset, Label; + int lOffsetP, lOffsetN; + int rOffsetP, rOffsetN; + int Classes[4096]; + int dwImageSize, ptr; + bool NewLabel; + bool Change; + bool connected; + int T[27]; + int *ccompImage; + int layerSize; + int count; + int status; + + layerSize = rows * cols; + dwImageSize = layers * rows * cols; + ccompImage = calloc(dwImageSize, sizeof(int )); + + Label = 1; + for(i = 1; i < layers-1; ++i){ + lOffset = i * layerSize; + lOffsetP = lOffset+layerSize; + lOffsetN = lOffset-layerSize; + for(j = 1; j < rows-1; ++j){ + rOffset = j * cols; + rOffsetP = rOffset+cols; + rOffsetN = rOffset-cols; + for(k = 1; k < cols-1; ++k){ + if(edges[lOffset+rOffset+k]){ + /* + check 3x3x3 connectivity + */ + + T[0] = edges[lOffset+rOffset+k]; + T[1] = edges[lOffset+rOffset+k+1]; + T[2] = edges[lOffset+rOffsetN+k+1]; + T[3] = edges[lOffset+rOffsetN+k]; + T[4] = edges[lOffset+rOffsetN+k-1]; + T[5] = edges[lOffset+rOffset+k-1]; + T[6] = edges[lOffset+rOffsetP+k-1]; + T[7] = edges[lOffset+rOffsetP+k]; + T[8] = edges[lOffset+rOffsetP+k+1]; + + T[9] = edges[lOffsetN+rOffset+k]; + T[10] = edges[lOffsetN+rOffset+k+1]; + T[11] = edges[lOffsetN+rOffsetN+k+1]; + T[12] = edges[lOffsetN+rOffsetN+k]; + T[13] = edges[lOffsetN+rOffsetN+k-1]; + T[14] = edges[lOffsetN+rOffset+k-1]; + T[15] = edges[lOffsetN+rOffsetP+k-1]; + T[16] = edges[lOffsetN+rOffsetP+k]; + T[17] = edges[lOffsetN+rOffsetP+k+1]; + + T[18] = edges[lOffsetP+rOffset+k]; + T[19] = edges[lOffsetP+rOffset+k+1]; + T[20] = edges[lOffsetP+rOffsetN+k+1]; + T[21] = edges[lOffsetP+rOffsetN+k]; + T[22] = edges[lOffsetP+rOffsetN+k-1]; + T[23] = edges[lOffsetP+rOffset+k-1]; + T[24] = edges[lOffsetP+rOffsetP+k-1]; + T[25] = edges[lOffsetP+rOffsetP+k]; + T[26] = edges[lOffsetP+rOffsetP+k+1]; + + connected = FALSE; + if(mask == 1){ + count = 0; + for(l = 1; l < 27; ++l){ + count += T[l]; + } + if(count){ + connected = TRUE; + } + } + else if(mask == 6){ + count = (T[2] + T[4] + T[6] + T[8] + T[9] + T[18]); + if(count == 6){ + connected = TRUE; + } + } + else if(mask == 14){ + count = (T[2] + T[4] + T[6] + T[8] + T[9] + T[18] + T[11] + + T[13] + T[15] + T[17] + T[20] + T[22] + T[24] + T[26]); + if(count == 14){ + connected = TRUE; + } + } + else if(mask == 26){ + count = 0; + for(l = 1; l < 27; ++l){ + count += T[l]; + } + if(count == 26){ + connected = TRUE; + } + } + if(connected){ + ccompImage[lOffset+rOffset+k] = Label++; + } + } + } + } + } + + + while(1){ + Change = FALSE; + /* + // TOP-DOWN Pass for labeling + */ + for(i = 1; i < layers-1; ++i){ + lOffset = i * layerSize; + lOffsetP = lOffset+layerSize; + lOffsetN = lOffset-layerSize; + for(j = 1; j < rows-1; ++j){ + rOffset = j * cols; + rOffsetP = rOffset+cols; + rOffsetN = rOffset-cols; + for(k = 1; k < cols-1; ++k){ + if(ccompImage[lOffset+rOffset+k] != 0){ + + T[0] = ccompImage[lOffset+rOffset+k]; + T[1] = ccompImage[lOffset+rOffset+k+1]; + T[2] = ccompImage[lOffset+rOffsetN+k+1]; + T[3] = ccompImage[lOffset+rOffsetN+k]; + T[4] = ccompImage[lOffset+rOffsetN+k-1]; + T[5] = ccompImage[lOffset+rOffset+k-1]; + T[6] = ccompImage[lOffset+rOffsetP+k-1]; + T[7] = ccompImage[lOffset+rOffsetP+k]; + T[8] = ccompImage[lOffset+rOffsetP+k+1]; + + T[9] = ccompImage[lOffsetN+rOffset+k]; + T[10] = ccompImage[lOffsetN+rOffset+k+1]; + T[11] = ccompImage[lOffsetN+rOffsetN+k+1]; + T[12] = ccompImage[lOffsetN+rOffsetN+k]; + T[13] = ccompImage[lOffsetN+rOffsetN+k-1]; + T[14] = ccompImage[lOffsetN+rOffset+k-1]; + T[15] = ccompImage[lOffsetN+rOffsetP+k-1]; + T[16] = ccompImage[lOffsetN+rOffsetP+k]; + T[17] = ccompImage[lOffsetN+rOffsetP+k+1]; + + T[18] = ccompImage[lOffsetP+rOffset+k]; + T[19] = ccompImage[lOffsetP+rOffset+k+1]; + T[20] = ccompImage[lOffsetP+rOffsetN+k+1]; + T[21] = ccompImage[lOffsetP+rOffsetN+k]; + T[22] = ccompImage[lOffsetP+rOffsetN+k-1]; + T[23] = ccompImage[lOffsetP+rOffset+k-1]; + T[24] = ccompImage[lOffsetP+rOffsetP+k-1]; + T[25] = ccompImage[lOffsetP+rOffsetP+k]; + T[26] = ccompImage[lOffsetP+rOffsetP+k+1]; + + m = T[0]; + for(l = 1; l < 27; ++l){ + if(T[l] != 0){ + if(T[l] < m) m = T[l]; + } + } + if(m != ccompImage[lOffset+rOffset+k]){ + Change = TRUE; + ccompImage[lOffset+rOffset+k] = m; + } + } + } + } + } + /* + // BOTTOM-UP Pass for labeling + */ + for(i = layers-1; i > 0; --i){ + lOffset = i * layerSize; + lOffsetP = lOffset+layerSize; + lOffsetN = lOffset-layerSize; + for(j = rows-1; j > 0; --j){ + rOffset = j * cols; + rOffsetP = rOffset+cols; + rOffsetN = rOffset-cols; + for(k = cols-1; k > 0; --k){ + if(ccompImage[lOffset+rOffset+k] != 0){ + + T[0] = ccompImage[lOffset+rOffset+k]; + T[1] = ccompImage[lOffset+rOffset+k+1]; + T[2] = ccompImage[lOffset+rOffsetN+k+1]; + T[3] = ccompImage[lOffset+rOffsetN+k]; + T[4] = ccompImage[lOffset+rOffsetN+k-1]; + T[5] = ccompImage[lOffset+rOffset+k-1]; + T[6] = ccompImage[lOffset+rOffsetP+k-1]; + T[7] = ccompImage[lOffset+rOffsetP+k]; + T[8] = ccompImage[lOffset+rOffsetP+k+1]; + + T[9] = ccompImage[lOffsetN+rOffset+k]; + T[10] = ccompImage[lOffsetN+rOffset+k+1]; + T[11] = ccompImage[lOffsetN+rOffsetN+k+1]; + T[12] = ccompImage[lOffsetN+rOffsetN+k]; + T[13] = ccompImage[lOffsetN+rOffsetN+k-1]; + T[14] = ccompImage[lOffsetN+rOffset+k-1]; + T[15] = ccompImage[lOffsetN+rOffsetP+k-1]; + T[16] = ccompImage[lOffsetN+rOffsetP+k]; + T[17] = ccompImage[lOffsetN+rOffsetP+k+1]; + + T[18] = ccompImage[lOffsetP+rOffset+k]; + T[19] = ccompImage[lOffsetP+rOffset+k+1]; + T[20] = ccompImage[lOffsetP+rOffsetN+k+1]; + T[21] = ccompImage[lOffsetP+rOffsetN+k]; + T[22] = ccompImage[lOffsetP+rOffsetN+k-1]; + T[23] = ccompImage[lOffsetP+rOffset+k-1]; + T[24] = ccompImage[lOffsetP+rOffsetP+k-1]; + T[25] = ccompImage[lOffsetP+rOffsetP+k]; + T[26] = ccompImage[lOffsetP+rOffsetP+k+1]; + + m = T[0]; + for(l = 1; l < 27; ++l){ + if(T[l] != 0){ + if(T[l] < m) m = T[l]; + } + } + if(m != ccompImage[lOffset+rOffset+k]){ + Change = TRUE; + ccompImage[lOffset+rOffset+k] = m; + } + } + } + } + } + + if(!Change) break; + + } /* end while loop */ + + Label = 1; + Classes[0] = 0; + ptr = 0; + for(i = 0; i < layers; ++i){ + for(j = 0; j < rows; ++j){ + for(k = 0; k < cols; ++k){ + m = ccompImage[ptr]; + ++ptr; + if(m > 0){ + NewLabel = TRUE; + for(l = 1; l < Label; ++l){ + if(Classes[l] == m) NewLabel = FALSE; + } + if(NewLabel){ + Classes[Label++] = m; + if(Label > 4000){ + return 0; + } + } + } + } + } + } + + *groups = Label; + + ptr = 0; + for(i = 0; i < layers; ++i){ + for(j = 0; j < rows; ++j){ + for(k = 0; k < cols; ++k){ + m = ccompImage[ptr]; + for(l = 1; l < Label; ++l){ + if(Classes[l] == m){ + connectedEdges[ptr] = l; + break; + } + } + ++ptr; + } + } + } + + free(ccompImage); + + status = 1; + return(status); + +} + +int NI_GetBlobs2D(int samples, int rows, int cols, unsigned short *edges, unsigned short *connectedEdges, + int *groups, int mask){ + + int i, j, k, l, m; + int offset; + int Label; + int status; + int Classes[4096]; + bool NewLabel; + bool Change; + bool connected; + int count; + unsigned short T[12]; + + /* + // connected components labeling. pixels with 1, 4 or 8 connectedness. + */ + Label = 1; + offset = 0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + connectedEdges[offset+j] = 0; + if(edges[offset+j] == 1){ + connected = FALSE; + if(mask == 1){ + count = 0; + for(l = 1; l < 9; ++l){ + count += T[l]; + } + if(count){ + connected = TRUE; + } + } + else if(mask == 4){ + count = (T[2] + T[4] + T[6] + T[8]); + if(count == 4){ + connected = TRUE; + } + } + else if(mask == 8){ + count = 0; + for(l = 1; l < 9; ++l){ + count += T[l]; + } + if(count == 8){ + connected = TRUE; + } + } + if(connected){ + connectedEdges[offset+j] = Label++; + } + } + } + offset += cols; + } + + while(1){ + Change = FALSE; + /* + // TOP-DOWN Pass for labeling + */ + offset = cols; + for(i = 1; i < rows-1; ++i){ + for(j = 1; j < cols-1; ++j){ + if(connectedEdges[offset+j] != 0){ + T[0] = connectedEdges[offset+j]; + T[1] = connectedEdges[offset+j+1]; + T[2] = connectedEdges[offset-cols+j+1]; + T[3] = connectedEdges[offset-cols+j]; + T[4] = connectedEdges[offset-cols+j-1]; + T[5] = connectedEdges[offset+j-1]; + T[6] = connectedEdges[offset+cols+j-1]; + T[7] = connectedEdges[offset+cols+j]; + T[8] = connectedEdges[offset+cols+j+1]; + m = T[0]; + for(l = 1; l < 9; ++l){ + if(T[l] != 0){ + if(T[l] < m) m = T[l]; + } + } + if(m != connectedEdges[offset+j]){ + Change = TRUE; + connectedEdges[offset+j] = m; + } + } + } + offset += cols; + } + /* + // BOTTOM-UP Pass for labeling + */ + offset = (rows-1)*cols; + for(i = (rows-1); i > 1; --i){ + for(j = (cols-1); j > 1; --j){ + if(connectedEdges[offset+j] != 0){ + T[0] = connectedEdges[offset+j]; + T[1] = connectedEdges[offset+j+1]; + T[2] = connectedEdges[offset-cols+j+1]; + T[3] = connectedEdges[offset-cols+j]; + T[4] = connectedEdges[offset-cols+j-1]; + T[5] = connectedEdges[offset+j-1]; + T[6] = connectedEdges[offset+cols+j-1]; + T[7] = connectedEdges[offset+cols+j]; + T[8] = connectedEdges[offset+cols+j+1]; + m = T[0]; + for(l = 1; l < 9; ++l){ + if(T[l] != 0){ + if(T[l] < m) m = T[l]; + } + } + if(m != connectedEdges[offset+j]){ + Change = TRUE; + connectedEdges[offset+j] = m; + } + } + } + offset -= cols; + } + if(!Change) break; + } /* end while loop */ + + Classes[0] = 0; + Label = 1; + offset = cols; + for(i = 1; i < (rows-1); ++i){ + for(j = 1; j < (cols-1); ++j){ + m = connectedEdges[offset+j]; + if(m > 0){ + NewLabel = TRUE; + for(k = 1; k < Label; ++k){ + if(Classes[k] == m) NewLabel = FALSE; + } + if(NewLabel){ + Classes[Label++] = m; + if(Label > 4000){ + return 0; /* too many labeled regions. this is a pathology */ + } + } + } + } + offset += cols; + } + + /* + // re-label the connected blobs in continuous label order + */ + offset = cols; + for(i = 1; i < (rows-1); ++i){ + for(j = 1; j < (cols-1); ++j){ + m = connectedEdges[offset+j]; + if(m > 0){ + for(k = 1; k < Label; ++k){ + if(Classes[k] == m){ + connectedEdges[offset+j] = (unsigned short)k; + break; + } + } + } + } + offset += cols; + } + + *groups = Label; + + /* + // prune the isolated pixels + */ + offset = 0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + if(connectedEdges[offset+j] > (*groups)){ + connectedEdges[offset+j] = 0; + } + } + offset += cols; + } + + status = 1; + return(status); + +} + +int NI_GetBlobRegions3D(int layers, int rows, int cols, int numberObjects, + unsigned short *labeledEdges, objStruct objectMetrics[]){ + + + int status; + int i, j, k, l, m; + int offset; + int count; + int LowX; + int LowY; + int LowZ; + int HighX; + int HighY; + int HighZ; + int ptr; + float centerX; + float centerY; + float centerZ; + + for(l = 1; l < numberObjects; ++l){ + offset = cols; + LowX = 32767; + LowY = 32767; + LowZ = 32767; + HighX = 0; + HighY = 0; + HighZ = 0; + count = 0; + centerX = (float)0.0; + centerY = (float)0.0; + centerZ = (float)0.0; + ptr = 0; + for(i = 0; i < layers; ++i){ + for(j = 0; j < rows; ++j){ + for(k = 0; k < cols; ++k){ + m = labeledEdges[ptr++]; + if(l == m){ + if(i < LowZ) LowZ = i; + if(j < LowY) LowY = j; + if(k < LowX) LowX = k; + if(i > HighZ) HighZ = i; + if(j > HighY) HighY = j; + if(k > HighX) HighX = k; + centerX += (float)k; + centerY += (float)j; + centerZ += (float)i; + ++count; + } + } + } + } + /* the bounding box for the 2D blob */ + objectMetrics[l-1].Left = LowX; + objectMetrics[l-1].Right = HighX; + objectMetrics[l-1].Bottom = LowY; + objectMetrics[l-1].Top = HighY; + objectMetrics[l-1].Front = LowZ; + objectMetrics[l-1].Back = HighZ; + objectMetrics[l-1].Mass = count; + objectMetrics[l-1].cX = centerX/(float)count; + objectMetrics[l-1].cY = centerY/(float)count; + objectMetrics[l-1].cZ = centerZ/(float)count; + objectMetrics[l-1].Label = l; + } + + status = numberObjects; + + return(status); + +} + +int NI_GetBlobRegions2D(int rows, int cols, int numberObjects, unsigned short *labeledEdges, + objStruct objectMetrics[]){ + + int i, j, k, m; + int count; + int LowX; + int LowY; + int HighX; + int HighY; + int status; + int ptr; + float centerX; + float centerY; + + for(k = 1; k < numberObjects; ++k){ + LowX = 32767; + LowY = 32767; + HighX = 0; + HighY = 0; + count = 0; + centerX = (float)0.0; + centerY = (float)0.0; + ptr = 0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + m = labeledEdges[ptr++]; + if(k == m){ + if(i < LowY) LowY = i; + if(j < LowX) LowX = j; + if(i > HighY) HighY = i; + if(j > HighX) HighX = j; + centerX += (float)j; + centerY += (float)i; + ++count; + } + } + } + /* the bounding box for the 2D blob */ + objectMetrics[k-1].Left = LowX; + objectMetrics[k-1].Right = HighX; + objectMetrics[k-1].Bottom = LowY; + objectMetrics[k-1].Top = HighY; + objectMetrics[k-1].Mass = count; + objectMetrics[k-1].cX = centerX/(float)count; + objectMetrics[k-1].cY = centerY/(float)count; + objectMetrics[k-1].Label = k; + } + + status = numberObjects; + return status; + +} + + +int NI_ThinMorphoFilter(int regRows, int regColumns, int spadSize, int masks, unsigned short *J_mask, + unsigned short *K_mask, unsigned char *Input, unsigned char *CInput, + unsigned char *ErosionStage, unsigned char *DialationStage, + unsigned char *HMT, unsigned char *Copy){ + + int i, j, k, l, m, n, overlap, hit; + int LowValue1, HighValue1; + int LowValue2, HighValue2; + int Column, T, nloop; + int Offset; + int N, M; + int maskCols = 3; + int j_mask[3][3]; + int k_mask[3][3]; + int status; + + N = regRows; + M = regColumns; + + LowValue1 = 1; + HighValue1 = 0; + + LowValue2 = 0; + HighValue2 = 1; + + Offset = 0; + for(i = 0; i < N; ++i){ + for(j = 0; j < M; ++j){ + Copy[Offset+j] = Input[Offset+j]; + } + Offset += spadSize; + } + + nloop = 0; + while(1){ + /* erode */ + Column = 0; + for(n = 0; n < masks; ++n){ + for(i = 0; i < 3; ++i){ + for(j = 0; j < 3; ++j){ + j_mask[i][j] = J_mask[i+maskCols*(Column+j)]; + } + } + for(i = 0; i < 3; ++i){ + for(j = 0; j < 3; ++j){ + k_mask[i][j] = K_mask[i+maskCols*(Column+j)]; + } + } + Column += 3; + + Offset = spadSize; + for(i = 1; i < N-1; ++i){ + for(j = 1; j < M-1; ++j){ + hit = LowValue1; + for(k = -1; k < 2; ++k){ + for(l = -1; l < 2; ++l){ + T = j_mask[k+1][l+1]; + if(T == 1){ + overlap = T*Input[Offset+(k*spadSize)+j+l]; + if(overlap == HighValue1) hit = HighValue1; + } + } + } + ErosionStage[Offset+j] = hit; + } + Offset += spadSize; + } + + /* dialate */ + Offset = 0; + for(i = 0; i < N; ++i){ + for(j = 0; j < M; ++j){ + CInput[Offset+j] = (~Input[Offset+j]) & 0x1; + } + Offset += spadSize; + } + + Offset = spadSize; + for(i = 1; i < N-1; ++i){ + for(j = 1; j < M-1; ++j){ + hit = LowValue1; + for(k = -1; k < 2; ++k){ + for(l = -1; l < 2; ++l){ + T = k_mask[k+1][l+1]; + if(T == 1){ + overlap = T*CInput[Offset+(k*spadSize)+j+l]; + if(overlap == HighValue1) hit = HighValue1; + } + } + } + DialationStage[Offset+j] = hit; + } + Offset += spadSize; + } + + /* form the HMT */ + Offset = 0; + for(i = 0; i < N; ++i){ + for(j = 0; j < M; ++j){ + m = (ErosionStage[Offset+j]*DialationStage[Offset+j]); + HMT[Offset+j] = m; + } + Offset += spadSize; + } + + /* Thin for stage n */ + + Offset = 0; + for(i = 0; i < N; ++i){ + for(j = 0; j < M; ++j){ + HMT[Offset+j] = (~HMT[Offset+j]) & 0x1; + } + Offset += spadSize; + } + + Offset = 0; + for (i = 0; i < N; ++i){ + for (j = 0; j < M; ++j){ + m = (Input[Offset+j]*HMT[Offset+j]); + Input[Offset+j] = m; + } + Offset += spadSize; + } + } + + /* check for no change */ + hit = 0; + Offset = 0; + for(i = 0; i < N; ++i){ + for(j = 0; j < M; ++j){ + hit += abs(Copy[Offset+j]-Input[Offset+j]); + } + Offset += spadSize; + } + if(!hit) break; + + hit = 0; + Offset = 0; + for(i = 0; i < N; ++i){ + for(j = 0; j < M; ++j){ + Copy[Offset+j] = Input[Offset+j]; + if(Input[Offset+j]) ++hit; + } + Offset += spadSize; + } + /* nloop is data dependent. */ + ++nloop; + } + + + status = 1; + return status; + +} + + +int NI_CannyFilter(int samples, int rows, int cols, double *rawImage, + double *hDGImage, double *vDGImage, double *dgKernel, + int gWidth, float *aveXValue, float *aveYValue){ + + + /* + // implements the derivative of Gaussian filter. kernel set by CannyEdges + */ + int i, j, k; + int ptr; + int mLength; + int count; + int status; + float *tBuffer = NULL; + double sum; + + *aveXValue = (float)0.0; + *aveYValue = (float)0.0; + + mLength = MAX(rows, cols) + 64; + tBuffer = calloc(mLength, sizeof(float)); + + /* + // filter X + */ + count = 0; + for(i = 0; i < rows; ++i){ + ptr = i * cols; + for(j = gWidth; j < cols-gWidth; ++j){ + sum = dgKernel[0] * rawImage[ptr+j]; + for(k = 1; k < gWidth; ++k){ + sum += dgKernel[k] * (-rawImage[ptr+j+k] + rawImage[ptr+j-k]); + } + hDGImage[ptr+j] = (float)sum; + if(sum != (float)0.0){ + ++count; + *aveXValue += (float)fabs(sum); + } + } + } + if(count){ + *aveXValue /= (float)count; + } + /* + // filter Y + */ + count = 0; + for(i = 0; i < cols; ++i){ + for(j = 0; j < rows; ++j){ + ptr = j * cols; + tBuffer[j] = rawImage[ptr+i]; + } + for(j = gWidth; j < rows-gWidth; ++j){ + ptr = j * cols; + sum = dgKernel[0] * tBuffer[j]; + for(k = 1; k < gWidth; ++k){ + sum += dgKernel[k] * (-tBuffer[j+k] + tBuffer[j-k]); + } + vDGImage[ptr+i] = sum; + if(sum != (float)0.0){ + ++count; + *aveYValue += (float)fabs(sum); + } + } + } + if(count){ + *aveYValue /= (float)count; + } + + free(tBuffer); + + status = 1; + + return status; + +} + +double tmagnitude(double X, double Y){ + return sqrt(X*X + Y*Y); +} + +int NI_CannyNonMaxSupress(int num, int rows, int cols, double *magImage, double *hDGImage, + double *vDGImage, int mode, double aveXValue, double aveYValue, + double *tAve, double *cannyLow, double *cannyHigh, + double cannyL, double cannyH){ + + int i, j; + int ptr, ptr_m1, ptr_p1; + float xSlope, ySlope, G1, G2, G3, G4, G, xC, yC; + float scale; + float maxValue = (float)0.0; + float minValue = (float)0.0; + int value; + int mValue; + int mIndex; + int count; + int status; + int histogram[256]; + double step; + + for(i = 1; i < rows-1; ++i){ + ptr = i * cols; + ptr_m1 = ptr - cols; + ptr_p1 = ptr + cols; + for(j = 1; j < cols; ++j){ + magImage[ptr+j] = (float)0.0; + xC = hDGImage[ptr+j]; + yC = vDGImage[ptr+j]; + if(!((fabs(xC) < aveXValue) && (fabs(yC) < aveYValue))){ + G = tmagnitude(xC, yC); + if(fabs(yC) > fabs(xC)){ + /* vertical gradient */ + xSlope = (float)(fabs(xC) / fabs(yC)); + ySlope = (float)1.0; + G2 = tmagnitude(hDGImage[ptr_m1+j], vDGImage[ptr_m1+j]); + G4 = tmagnitude(hDGImage[ptr_p1+j], vDGImage[ptr_p1+j]); + if((xC*yC) > (float)0.0){ + G1 = tmagnitude(hDGImage[ptr_m1+j-1], vDGImage[ptr_m1+j-1]); + G3 = tmagnitude(hDGImage[ptr_p1+j+1], vDGImage[ptr_p1+j+1]); + } + else{ + G1 = tmagnitude(hDGImage[ptr_m1+j+1], vDGImage[ptr_m1+j+1]); + G3 = tmagnitude(hDGImage[ptr_p1+j-1], vDGImage[ptr_p1+j-1]); + } + } + else{ + /* horizontal gradient */ + xSlope = (float)(fabs(yC) / fabs(xC)); + ySlope = (float)1.0; + G2 = tmagnitude(hDGImage[ptr+j+1], vDGImage[ptr+j+1]); + G4 = tmagnitude(hDGImage[ptr+j-1], vDGImage[ptr+j-1]); + if((xC*yC) > (float)0.0){ + G1 = tmagnitude(hDGImage[ptr_p1+j+1], vDGImage[ptr_p1+j+1]); + G3 = tmagnitude(hDGImage[ptr_m1+j-1], vDGImage[ptr_m1+j-1]); + } + else{ + G1 = tmagnitude(hDGImage[ptr_m1+j+1], vDGImage[ptr_m1+j+1]); + G3 = tmagnitude(hDGImage[ptr_p1+j-1], vDGImage[ptr_p1+j-1]); + } + } + if((G > (xSlope*G1+(ySlope-xSlope)*G2))&&(G > (xSlope*G3+(ySlope-xSlope)*G4))){ + magImage[ptr+j] = G; + } + if(magImage[ptr+j] > maxValue) maxValue = magImage[ptr+j]; + if(magImage[ptr+j] < minValue) minValue = magImage[ptr+j]; + } + } + } + + scale = (float)1.0 / (maxValue-minValue); + ptr = 0; + count = 0; + *tAve = 0.0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + magImage[ptr] = scale * (magImage[ptr]-minValue); + if(magImage[ptr] > 0.0){ + *tAve += magImage[ptr]; + ++count; + } + ++ptr; + } + } + *tAve /= (float)count; + + step = 255.0; + for(i = 0; i < 256; ++i){ + histogram[i] = 0; + } + ptr = 0; + for(i = 0; i < rows; ++i){ + for(j = 0; j < cols; ++j){ + value = (int)(step*(magImage[ptr])); + ++histogram[value]; + ++ptr; + } + } + /* + // now get the max after skipping the low values + */ + mValue = -1; + mIndex = 0; + for(i = 10; i < 256; ++i){ + if(histogram[i] > mValue){ + mValue = histogram[i]; + mIndex = i; + } + } + + if(mode == 1){ + /* based on the mean value of edge energy */ + *cannyLow = ((cannyL) * *tAve); + *cannyHigh = ((cannyH) * *tAve); + } + else{ + /* based on the mode value of edge energy */ + *cannyLow = ((cannyL) * ((float)mIndex/step)); + *cannyHigh = ((cannyH) * ((float)mIndex/step)); + } + status = 1; + + return status; + +} + +int trace_Edge(int i, int j, int rows, int cols, double cannyLow, double *magImage, + unsigned short *hys_image){ + + int n, m; + int ptr; + int flag; + + ptr = i * cols; + if(hys_image[ptr+j] == 0){ + /* + // this point is above high threshold + */ + hys_image[ptr+j] = 1; + flag = 0; + for(n = -1; n <= 1; ++n){ + for(m = -1; m <= 1; ++m){ + if(n == 0 && m == 0) continue; + if(((i+n) > 0) && ((j+m) > 0) && ((i+n) < rows) && ((j+m) < cols)){ + ptr = (i+n) * cols; + if(magImage[ptr+j+m] > cannyLow){ + /* + // this point is above low threshold + */ + if(trace_Edge(i+n, j+m, rows, cols, cannyLow, magImage, hys_image)){ + flag = 1; + break; + } + } + } + } + if(flag) break; + } + return(1); + } + + return(0); + +} + +int NI_CannyHysteresis(int num, int rows, int cols, double *magImage, unsigned short *hys_image, + double cannyLow, double cannyHigh){ + + + int status; + int i, j; + int ptr; + + for(i = 0; i < rows; ++i){ + ptr = i * cols; + for(j = 0; j < cols; ++j){ + if(magImage[ptr+j] > cannyHigh){ + trace_Edge(i, j, rows, cols, cannyLow, magImage, hys_image); + } + } + } + + status = 1; + + return status; + +} + +float lawsConvolution(float *image, float *rowFilter, float *colFilter, int kernelSize){ + + int i, j; + int offset; + float result[7]; + float sum; + + /* filter rows */ + for(i = 0; i < kernelSize; ++i){ + sum = (float)0.0; + offset = i * kernelSize; + for(j = 0; j < kernelSize; ++j){ + sum += (rowFilter[j]*image[offset+j]); + } + result[i] = sum; + } + + /* filter columns */ + sum = (float)0.0; + for(j = 0; j < kernelSize; ++j){ + sum += (rowFilter[j]*result[j]); + } + + return(sum); + +} + +void computeLaws(LawsFilter7 lawsFilter, int aperature, int srcRows, int srcCols, + unsigned short *MaskImage, float *lawsImage, double *sourceImage){ + + /* + // hard-wirred to Law's 7 kernels + */ + int i, j; + int lawsLayer; + int column, row; + int maskOffset[7]; + int dataOffset[7]; + float myImage[49]; + int count; + int outerKernelNumber; + int innerKernelNumber; + int rowNumber; + int kernelSize = lawsFilter.kernelLength; + int fullMask = kernelSize*kernelSize; + int layerStep = srcRows*srcCols; + float *rowFilter; + float *colFilter; + float filterResult1; + float filterResult2; + float lawsLL=1.0; + + for(i = aperature; i < srcRows-aperature; ++i){ + // get the row array offset for mask and data source. + for(row = -aperature; row <= aperature; ++row){ + maskOffset[row+aperature] = (i+row)*srcCols; + dataOffset[row+aperature] = maskOffset[row+aperature]; + } + for(j = aperature; j < srcCols-aperature; ++j){ + /* + // get 7x7 segment and make sure have 100% mask coverage + */ + count = 0; + for(row = -aperature; row <= aperature; ++row){ + rowNumber = (row+aperature)*kernelSize; + for(column = -aperature; column <= aperature; ++column){ + if(MaskImage[maskOffset[row+aperature]+j+column]){ + myImage[rowNumber+column+aperature] = sourceImage[dataOffset[row+aperature]+j+column]; + ++count; + } + } + } + if(count == fullMask){ + /* + // 100% mask coverage. now do the Law's texture filters + */ + lawsLayer = 0; + for(outerKernelNumber = 0; outerKernelNumber < lawsFilter.numberKernels; ++outerKernelNumber){ + /* + // outer loop pulls the i'th kernel. kernel 0 is the LP kernel + // the outer loop is the iso-kernel + */ + rowFilter = &lawsFilter.lawsKernel[outerKernelNumber][0]; + colFilter = &lawsFilter.lawsKernel[outerKernelNumber][0]; + filterResult1 = lawsConvolution(myImage, rowFilter, colFilter, kernelSize); + /* lawsLayer 0 is the LP and needs to be used to scale. */ + if(outerKernelNumber){ + lawsImage[lawsLayer*layerStep + i*srcCols + j] = (float)2.0 * filterResult1; + } + else{ + lawsLL = filterResult1; + lawsLL = (float)2.0 * filterResult1; + lawsImage[lawsLayer*layerStep + i*srcCols + j] = (float)2.0 * filterResult1; + } + ++lawsLayer; + /* + // now do the inner loop and get the column filters for the other laws kernels + */ + for(innerKernelNumber = outerKernelNumber+1; + innerKernelNumber < lawsFilter.numberKernels; + ++innerKernelNumber){ + colFilter = &lawsFilter.lawsKernel[innerKernelNumber][0]; + filterResult1 = lawsConvolution(myImage, rowFilter, colFilter, kernelSize); + filterResult2 = lawsConvolution(myImage, colFilter, rowFilter, kernelSize); + lawsImage[lawsLayer*layerStep + i*srcCols + j] = filterResult1 + filterResult2; + ++lawsLayer; + } + } + } + } + } + + return; + +} + + +int NI_LawsTexture(int num, int rows, int cols, double *src_image, unsigned short *mask, + float *lawsImage, LawsFilter7 lawsFilter){ + + int status; + int number_kernels; + int kernel_size; + int filters; + int aperature; + number_kernels = lawsFilter.numberKernels; + kernel_size = lawsFilter.kernelLength; + filters = lawsFilter.numberFilterLayers; + aperature = (kernel_size-1)/2; + + computeLaws(lawsFilter, aperature, rows, cols, mask, lawsImage, src_image); + + status = 1; + + return status; + +} + + +int NI_RoiCoOccurence(int samples, int rows, int cols, unsigned short *labelImage, + unsigned short *rawImage, int *cocMatrix, int distance, int orientation){ + + int i, j; + int offset; + int d_row; + int d_col; + int status; + int start_row; + int stop_row; + int start_col; + int stop_col; + int mask; + int pixel; + int d_mask_value; + int d_pixel_value; + + /* built around 8 bit histograms */ + + offset = 0; + if(orientation == 90){ + start_row = 0; + stop_row = rows; + start_col = 0; + stop_col = cols-distance; + d_row = 0; + d_col = distance; + } + else if(orientation == 180){ + start_row = 0; + stop_row = rows-distance; + start_col = 0; + stop_col = cols; + d_row = cols*distance; + d_col = 0; + } + else if(orientation == 45){ + start_row = 0; + stop_row = rows-distance; + start_col = distance; + stop_col = cols; + d_row = cols*distance; + d_col = -distance; + } + else if(orientation == 135){ + start_row = 0; + stop_row = rows-distance; + start_col = 0; + stop_col = cols-distance; + d_row = cols*distance; + d_col = distance; + } + + for(i = start_row; i < stop_row; ++i){ + for(j = start_col; j < stop_col; ++j){ + mask = labelImage[offset+j]; + if(mask){ + /* d rows away from current row */ + pixel = rawImage[offset+j]; + d_mask_value = labelImage[offset+d_row+j+d_col]; + if(d_mask_value){ + /* over the mask */ + d_pixel_value = rawImage[offset+d_row+j+d_col]; + /* update the 2D joint histograms */ + ++cocMatrix[d_pixel_value*256+pixel]; + ++cocMatrix[d_pixel_value+pixel*256]; + } + } + } + offset += cols; + } + + status = 1; + + return(status); + +} + +int NI_GrowRegion2D(int rows, int cols, double *rawimage, unsigned short *label, + objStruct *expanded_ROI, objStruct *newgrow_ROI, double low_threshold, + double high_threshold, int Label, int N_connectivity){ + + int i, j, p, m; + int offset; + int offsetM, offsetP; + int status; + int T[8], count; + int LowX; + int LowY; + int HighX; + int HighY; + double value; + bool change; + + while(1){ + change = FALSE; + for(i = 1; i < rows-1; ++i){ + offset = i * cols; + offsetM = offset - cols; + offsetP = offset + cols; + for(j = 1; j < cols-1; ++j){ + m = label[offset+j]; + if(!m){ + /* un-labeled pixel */ + value = rawimage[offset+j]; + if((value > low_threshold) && (value < high_threshold)){ + /* check for N-connectivity */ + T[0] = label[offset+j+1]; + T[1] = label[offsetM+j+1]; + T[2] = label[offsetM+j]; + T[3] = label[offsetM+j-1]; + T[4] = label[offset+j-1]; + T[5] = label[offsetP+j-1]; + T[6] = label[offsetP+j]; + T[7] = label[offsetP+j+1]; + count = 0; + for(p = 0; p < 8; ++p){ + if(T[p] == Label){ + ++count; + } + } + if(count > N_connectivity){ + label[offset+j] = Label; + change = TRUE; + } + } + } + } + } + if(!change) break; + } + + /* get new bounding box */ + newgrow_ROI->Left = expanded_ROI->Left + LowX; + newgrow_ROI->Right = newgrow_ROI->Left + (HighX-LowX); + newgrow_ROI->Bottom = expanded_ROI->Bottom + LowY; + newgrow_ROI->Top = expanded_ROI->Bottom + (HighY-LowY); + newgrow_ROI->Mass = count; + + status = 1; + + return(status); + +} + +int NI_GrowRegion3D(int layers, int rows, int cols, double *rawimage, unsigned short *label, + objStruct *expanded_ROI, objStruct *newgrow_ROI, double low_threshold, + double high_threshold, int Label, int N_connectivity){ + + int i, j, k, m, p; + int offset; + int ptr; + int lOffset, rOffset; + int lOffsetP, lOffsetN; + int rOffsetP, rOffsetN; + int layerSize; + int status; + int T[26], count; + int LowX; + int LowY; + int LowZ; + int HighX; + int HighY; + int HighZ; + float centerX; + float centerY; + float centerZ; + double value; + bool change; + + layerSize = rows * cols; + while(1){ + change = FALSE; + for(i = 1; i < layers-1; ++i){ + lOffset = i * layerSize; + lOffsetP = lOffset+layerSize; + lOffsetN = lOffset-layerSize; + for(j = 1; j < rows-1; ++j){ + rOffset = j * cols; + rOffsetP = rOffset+cols; + rOffsetN = rOffset-cols; + for(k = 1; k < cols-1; ++k){ + m = label[lOffset+rOffset+k]; + if(!m){ + /* un-labeled voxel */ + value = rawimage[lOffset+rOffset+k]; + if((value > low_threshold) && (value < high_threshold)){ + /* check for N-connectivity */ + T[0] = label[lOffset+rOffset+k+1]; + T[1] = label[lOffset+rOffsetN+k+1]; + T[2] = label[lOffset+rOffsetN+k]; + T[3] = label[lOffset+rOffsetN+k-1]; + T[4] = label[lOffset+rOffset+k-1]; + T[5] = label[lOffset+rOffsetP+k-1]; + T[6] = label[lOffset+rOffsetP+k]; + T[7] = label[lOffset+rOffsetP+k+1]; + + T[8] = label[lOffsetN+rOffset+k]; + T[9] = label[lOffsetN+rOffset+k+1]; + T[10] = label[lOffsetN+rOffsetN+k+1]; + T[11] = label[lOffsetN+rOffsetN+k]; + T[12] = label[lOffsetN+rOffsetN+k-1]; + T[13] = label[lOffsetN+rOffset+k-1]; + T[14] = label[lOffsetN+rOffsetP+k-1]; + T[15] = label[lOffsetN+rOffsetP+k]; + T[16] = label[lOffsetN+rOffsetP+k+1]; + + T[17] = label[lOffsetP+rOffset+k]; + T[18] = label[lOffsetP+rOffset+k+1]; + T[19] = label[lOffsetP+rOffsetN+k+1]; + T[20] = label[lOffsetP+rOffsetN+k]; + T[21] = label[lOffsetP+rOffsetN+k-1]; + T[22] = label[lOffsetP+rOffset+k-1]; + T[23] = label[lOffsetP+rOffsetP+k-1]; + T[24] = label[lOffsetP+rOffsetP+k]; + T[25] = label[lOffsetP+rOffsetP+k+1]; + + count = 0; + for(p = 0; p < 26; ++p){ + if(T[p] == Label){ + ++count; + } + } + if(count > N_connectivity){ + label[lOffset+rOffset+k]= Label; + change = TRUE; + } + } + } + } + } + } + if(!change) break; + } + + LowX = 32767; + LowY = 32767; + LowZ = 32767; + HighX = 0; + HighY = 0; + HighZ = 0; + count = 0; + centerX = (float)0.0; + centerY = (float)0.0; + centerZ = (float)0.0; + ptr = 0; + count = 0; + for(i = 0; i < layers; ++i){ + for(j = 0; j < rows; ++j){ + for(k = 0; k < cols; ++k){ + m = label[ptr++]; + if(m == Label){ + if(i < LowZ) LowZ = i; + if(j < LowY) LowY = j; + if(k < LowX) LowX = k; + if(i > HighZ) HighZ = i; + if(j > HighY) HighY = j; + if(k > HighX) HighX = k; + centerX += (float)k; + centerY += (float)j; + centerZ += (float)i; + ++count; + } + } + } + } + + newgrow_ROI->Left = expanded_ROI->Left + LowX; + newgrow_ROI->Right = newgrow_ROI->Left + (HighX-LowX); + newgrow_ROI->Bottom = expanded_ROI->Bottom + LowY; + newgrow_ROI->Top = newgrow_ROI->Bottom + (HighY-LowY); + newgrow_ROI->Front = expanded_ROI->Front + LowZ; + newgrow_ROI->Back = expanded_ROI->Front + (HighZ-LowZ); + newgrow_ROI->Mass = count; + + status = 1; + + return(status); + +} + + Modified: trunk/scipy/ndimage/src/segment/ndImage_Segmenter_structs.h =================================================================== --- trunk/scipy/ndimage/src/segment/ndImage_Segmenter_structs.h 2008-08-09 02:31:58 UTC (rev 4633) +++ trunk/scipy/ndimage/src/segment/ndImage_Segmenter_structs.h 2008-08-09 19:29:36 UTC (rev 4634) @@ -1,29 +1,29 @@ -#ifndef V1_STRUCTSH -#define V1_STRUCTSH - -#define bool unsigned char - -typedef struct{ - int numberKernels; - int kernelLength; - int numberFilterLayers; - float lawsKernel[6][7]; - char name[7]; -}LawsFilter7; - -typedef struct{ - // filled in GetObjectStats - int Left; - int Right; - int Top; - int Bottom; - int Front; - int Back; - int Label; - int Mass; - float cX; - float cY; - float cZ; -}objStruct; - -#endif +#ifndef V1_STRUCTSH +#define V1_STRUCTSH + +#define bool unsigned char + +typedef struct{ + int numberKernels; + int kernelLength; + int numberFilterLayers; + float lawsKernel[6][7]; + char name[7]; +}LawsFilter7; + +typedef struct{ + // filled in GetObjectStats + int Left; + int Right; + int Top; + int Bottom; + int Front; + int Back; + int Label; + int Mass; + float cX; + float cY; + float cZ; +}objStruct; + +#endif From scipy-svn at scipy.org Sun Aug 10 21:21:02 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Sun, 10 Aug 2008 20:21:02 -0500 (CDT) Subject: [Scipy-svn] r4635 - in trunk/scipy/stats/models: . tests Message-ID: <20080811012102.A4BF739C107@scipy.org> Author: jarrod.millman Date: 2008-08-10 20:20:59 -0500 (Sun, 10 Aug 2008) New Revision: 4635 Modified: trunk/scipy/stats/models/bspline.py trunk/scipy/stats/models/setup.py trunk/scipy/stats/models/setupscons.py trunk/scipy/stats/models/tests/test_bspline.py Log: ran reindent Modified: trunk/scipy/stats/models/bspline.py =================================================================== --- trunk/scipy/stats/models/bspline.py 2008-08-09 19:29:36 UTC (rev 4634) +++ trunk/scipy/stats/models/bspline.py 2008-08-11 01:20:59 UTC (rev 4635) @@ -198,9 +198,9 @@ Bspline to avoid extra evaluation in the __call__ method ''' - # FIXME: update parameter names, replace single character names + # FIXME: update parameter names, replace single character names # FIXME: `order` should be actual spline order (implemented as order+1) - ## FIXME: update the use of spline order in extension code (evaluate is recursively called) + ## FIXME: update the use of spline order in extension code (evaluate is recursively called) # FIXME: eliminate duplicate M and m attributes (m is order, M is related to tau size) def __init__(self, knots, order=4, M=None, coef=None, x=None): @@ -437,7 +437,7 @@ fhat = ARGMIN_f SUM_i=1^n (y_i-f(x_i))^2 + pen * int f^(2)^2 - int is integral. pen is lambda (from Hastie) + int is integral. pen is lambda (from Hastie) See Chapter 5 of Modified: trunk/scipy/stats/models/setup.py =================================================================== --- trunk/scipy/stats/models/setup.py 2008-08-09 19:29:36 UTC (rev 4634) +++ trunk/scipy/stats/models/setup.py 2008-08-11 01:20:59 UTC (rev 4635) @@ -18,4 +18,3 @@ from numpy.distutils.core import setup setup(**configuration(top_path='').todict()) - Modified: trunk/scipy/stats/models/setupscons.py =================================================================== --- trunk/scipy/stats/models/setupscons.py 2008-08-09 19:29:36 UTC (rev 4634) +++ trunk/scipy/stats/models/setupscons.py 2008-08-11 01:20:59 UTC (rev 4635) @@ -18,4 +18,3 @@ from numpy.distutils.core import setup setup(**configuration(top_path='').todict()) - Modified: trunk/scipy/stats/models/tests/test_bspline.py =================================================================== --- trunk/scipy/stats/models/tests/test_bspline.py 2008-08-09 19:29:36 UTC (rev 4634) +++ trunk/scipy/stats/models/tests/test_bspline.py 2008-08-11 01:20:59 UTC (rev 4635) @@ -19,8 +19,8 @@ # C extension is working (in a technical sense, not functional). def test_basis(self): b = bsp.BSpline(np.linspace(0,1,11)) - x = np.array([0.4, 0.5]) - v = b.basis(x, lower=0, upper=13) + x = np.array([0.4, 0.5]) + v = b.basis(x, lower=0, upper=13) t = np.array([[ 0. , 0. ], [ 0. , 0. ], [ 0. , 0. ], @@ -34,7 +34,7 @@ [ 0. , 0. ], [ 0. , 0. ], [ 0. , 0. ]]) - assert_array_almost_equal(v, t, decimal=6) + assert_array_almost_equal(v, t, decimal=6) # FIXME: Have no idea what this test does. It's here to simply verify the # C extension is working (in a technical sense, not functional). From scipy-svn at scipy.org Mon Aug 11 12:17:39 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 11 Aug 2008 11:17:39 -0500 (CDT) Subject: [Scipy-svn] r4636 - trunk/scipy/stats/tests Message-ID: <20080811161739.18B9E39C05F@scipy.org> Author: pierregm Date: 2008-08-11 11:17:36 -0500 (Mon, 11 Aug 2008) New Revision: 4636 Modified: trunk/scipy/stats/tests/test_mstats.py Log: fixed test_cov test to reflect the new numpy.ma.cov modifications Modified: trunk/scipy/stats/tests/test_mstats.py =================================================================== --- trunk/scipy/stats/tests/test_mstats.py 2008-08-11 01:20:59 UTC (rev 4635) +++ trunk/scipy/stats/tests/test_mstats.py 2008-08-11 16:17:36 UTC (rev 4636) @@ -192,9 +192,12 @@ winter.var(ddof=0)) assert_almost_equal(mstats.cov(winter,winter,bias=False), winter.var(ddof=1)) - assert_almost_equal(mstats.cov(winter,spring), 7.7) - assert_almost_equal(mstats.cov(winter,summer), 19.1111111, 7) - assert_almost_equal(mstats.cov(winter,fall), 20) + assert_almost_equal(mstats.cov(winter,spring)[0,1], 7.7) + assert_almost_equal(mstats.cov(winter,spring)[1,0], 7.7) + assert_almost_equal(mstats.cov(winter,summer)[0,1], 19.1111111, 7) + assert_almost_equal(mstats.cov(winter,summer)[1,0], 19.1111111, 7) + assert_almost_equal(mstats.cov(winter,fall)[0,1], 20) + assert_almost_equal(mstats.cov(winter,fall)[1,0], 20) class TestTrimming(TestCase): From scipy-svn at scipy.org Mon Aug 11 17:39:20 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 11 Aug 2008 16:39:20 -0500 (CDT) Subject: [Scipy-svn] r4637 - in branches/Interpolate1D: . docs extensions tests Message-ID: <20080811213920.77E0739C04C@scipy.org> Author: fcady Date: 2008-08-11 16:39:17 -0500 (Mon, 11 Aug 2008) New Revision: 4637 Added: branches/Interpolate1D/extensions/interp_526.f branches/Interpolate1D/extensions/interp_526a.pyf Modified: branches/Interpolate1D/__init__.py branches/Interpolate1D/docs/tutorial.rst branches/Interpolate1D/info.py branches/Interpolate1D/interpolate2d.py branches/Interpolate1D/setup.py branches/Interpolate1D/tests/regression_test.py branches/Interpolate1D/tests/test_interpolate2d.py Log: incorporation of TOMS algorithm 526 Modified: branches/Interpolate1D/__init__.py =================================================================== --- branches/Interpolate1D/__init__.py 2008-08-11 16:17:36 UTC (rev 4636) +++ branches/Interpolate1D/__init__.py 2008-08-11 21:39:17 UTC (rev 4637) @@ -15,3 +15,6 @@ # wrapped by interpolate*.py files from fitpack_wrapper import Spline +# wrapper around Fortran implementing Tom's algorithm 526 +from algorithm526_wrapper import algorithm526 + Modified: branches/Interpolate1D/docs/tutorial.rst =================================================================== --- branches/Interpolate1D/docs/tutorial.rst 2008-08-11 16:17:36 UTC (rev 4636) +++ branches/Interpolate1D/docs/tutorial.rst 2008-08-11 21:39:17 UTC (rev 4637) @@ -564,6 +564,8 @@ 'linear', 'cubic' and 'spline', however, work in both cases, and we try to give analogous methods the same name. But some methods are particular to, or have only been written for, one praticular dimensionality. +#. In particular, 2D supports the keywork '526', which implements TOMS algorithm 526. + See below for more information. As in 1D, linear interpolation is used by default, while out of bounds returns NaN. @@ -639,6 +641,13 @@ #) get_coeffs Same as Spline +------------------------------- +TOMS Algorithm 526 +------------------------------- +TOMS (Transactions on Mathematical Software) algorithm 526 is an +algorithm for interpolation of from scattered 2-dimensional data. It is +described in "ALGORITHM 526: Bivariate Interpolation and Smooth +Fitting for Irregularly Distributed Data Points [El ]" by Hiroshi Akima. ================================================ Added: branches/Interpolate1D/extensions/interp_526.f =================================================================== --- branches/Interpolate1D/extensions/interp_526.f 2008-08-11 16:17:36 UTC (rev 4636) +++ branches/Interpolate1D/extensions/interp_526.f 2008-08-11 21:39:17 UTC (rev 4637) @@ -0,0 +1,1681 @@ +CF77FLAGS(gnu)=-fno-automatic -finit-local-zero + SUBROUTINE IDBVIP(MD,NCP,NDP,XD,YD,ZD,NIP,XI,YI,ZI, ID001340 + 1 IWK,WK) +C THIS SUBROUTINE PERFORMS BIVARIATE INTERPOLATION WHEN THE PRO- +C JECTIONS OF THE DATA POINTS IN THE X-Y PLANE ARE IRREGULARLY +C DISTRIBUTED IN THE PLANE. +C THE INPUT PARAMETERS ARE +C MD = MODE OF COMPUTATION (MUST BE 1, 2, OR 3), +C = 1 FOR NEW NCP AND/OR NEW XD-YD, +C = 2 FOR OLD NCP, OLD XD-YD, NEW XI-YI, +C = 3 FOR OLD NCP, OLD XD-YD, OLD XI-YI, +C NCP = NUMBER OF ADDITIONAL DATA POINTS USED FOR ESTI- +C MATING PARTIAL DERIVATIVES AT EACH DATA POINT +C (MUST BE 2 OR GREATER, BUT SMALLER THAN NDP), +C NDP = NUMBER OF DATA POINTS (MUST BE 4 OR GREATER), +C XD = ARRAY OF DIMENSION NDP CONTAINING THE X +C COORDINATES OF THE DATA POINTS, +C YD = ARRAY OF DIMENSION NDP CONTAINING THE Y +C COORDINATES OF THE DATA POINTS, +C ZD = ARRAY OF DIMENSION NDP CONTAINING THE Z +C COORDINATES OF THE DATA POINTS, +C NIP = NUMBER OF OUTPUT POINTS AT WHICH INTERPOLATION +C IS TO BE PERFORMED (MUST BE 1 OR GREATER), +C XI = ARRAY OF DIMENSION NIP CONTAINING THE X +C COORDINATES OF THE OUTPUT POINTS, +C YI = ARRAY OF DIMENSION NIP CONTAINING THE Y +C COORDINATES OF THE OUTPUT POINTS. +C THE OUTPUT PARAMETER IS +C ZI = ARRAY OF DIMENSION NIP WHERE INTERPOLATED Z +C VALUES ARE TO BE STORED. +C THE OTHER PARAMETERS ARE +C IWK = INTEGER ARRAY OF DIMENSION +C MAX0(31,27+NCP)*NDP+NIP +C USED INTERNALLY AS A WORK AREA, +C WK = ARRAY OF DIMENSION 8*NDP USED INTERNALLY AS A +C WORK AREA. +C THE VERY FIRST CALL TO THIS SUBROUTINE AND THE CALL WITH A NEW +C NCP VALUE, A NEW NDP VALUE, AND/OR NEW CONTENTS OF THE XD AND +C YD ARRAYS MUST BE MADE WITH MD=1. THE CALL WITH MD=2 MUST BE +C PRECEDED BY ANOTHER CALL WITH THE SAME NCP AND NDP VALUES AND +C WITH THE SAME CONTENTS OF THE XD AND YD ARRAYS. THE CALL WITH +C MD=3 MUST BE PRECEDED BY ANOTHER CALL WITH THE SAME NCP, NDP, +C AND NIP VALUES AND WITH THE SAME CONTENTS OF THE XD, YD, XI, +C AND YI ARRAYS. BETWEEN THE CALL WITH MD=2 OR MD=3 AND ITS +C PRECEDING CALL, THE IWK AND WK ARRAYS MUST NOT BE DISTURBED. +C USE OF A VALUE BETWEEN 3 AND 5 (INCLUSIVE) FOR NCP IS RECOM- +C MENDED UNLESS THERE ARE EVIDENCES THAT DICTATE OTHERWISE. +C THE LUN CONSTANT IN THE DATA INITIALIZATION STATEMENT IS THE +C LOGICAL UNIT NUMBER OF THE STANDARD OUTPUT UNIT AND IS, +C THEREFORE, SYSTEM DEPENDENT. +C THIS SUBROUTINE CALLS THE IDCLDP, IDLCTN, IDPDRV, IDPTIP, AND +C IDTANG SUBROUTINES. +C DECLARATION STATEMENTS + DIMENSION XD(100),YD(100),ZD(100),XI(1000),YI(1000), + 1 ZI(1000),IWK(4100),WK(800) + COMMON/IDLC/NIT + COMMON/IDPI/ITPV + DATA LUN/6/ +C SETTING OF SOME INPUT PARAMETERS TO LOCAL VARIABLES. + +C (FOR MD=1,2,3) + 10 MD0=MD + NCP0=NCP + NDP0=NDP + NIP0=NIP +C ERROR CHECK. (FOR MD=1,2,3) + 20 IF(MD0.LT.1.OR.MD0.GT.3) GO TO 90 + IF(NCP0.LT.2.OR.NCP0.GE.NDP0) GO TO 90 + IF(NDP0.LT.4) GO TO 90 + IF(NIP0.LT.1) GO TO 90 + + IF(MD0.GE.2) GO TO 21 + IWK(1)=NCP0 + IWK(2)=NDP0 + GO TO 22 + 21 NCPPV=IWK(1) + NDPPV=IWK(2) + IF(NCP0.NE.NCPPV) GO TO 90 + IF(NDP0.NE.NDPPV) GO TO 90 + 22 IF(MD0.GE.3) GO TO 23 + IWK(3)=NIP + GO TO 30 + 23 NIPPV=IWK(3) + IF(NIP0.NE.NIPPV) GO TO 90 +C ALLOCATION OF STORAGE AREAS IN THE IWK ARRAY. (FOR MD=1,2,3) + 30 JWIPT=16 + JWIWL=6*NDP0+1 + JWIWK=JWIWL + JWIPL=24*NDP0+1 + JWIWP=30*NDP0+1 + JWIPC=27*NDP0+1 + JWIT0=MAX0(31,27+NCP0)*NDP0 +C TRIANGULATES THE X-Y PLANE. (FOR MD=1) + 40 IF(MD0.GT.1) GO TO 50 + CALL IDTANG(NDP0,XD,YD,NT,IWK(JWIPT),NL,IWK(JWIPL), + 1 IWK(JWIWL),IWK(JWIWP),WK) + IWK(5)=NT + IWK(6)=NL + IF(NT.EQ.0) RETURN +C DETERMINES NCP POINTS CLOSEST TO EACH DATA POINT. (FOR MD=1) + 50 IF(MD0.GT.1) GO TO 60 + CALL IDCLDP(NDP0,XD,YD,NCP0,IWK(JWIPC)) + IF(IWK(JWIPC).EQ.0) RETURN +C LOCATES ALL POINTS AT WHICH INTERPOLATION IS TO BE PERFORMED. +C (FOR MD=1,2) + 60 IF(MD0.EQ.3) GO TO 70 + NIT=0 + JWIT=JWIT0 + DO 61 IIP=1,NIP0 + JWIT=JWIT+1 +C FIXME: This is where the thing dies if we have more than 1 output value + CALL IDLCTN(NDP0,XD,YD,NT,IWK(JWIPT),NL,IWK(JWIPL), + 1 XI(IIP),YI(IIP),IWK(JWIT),IWK(JWIWK),WK) + 61 CONTINUE +C ESTIMATES PARTIAL DERIVATIVES AT ALL DATA POINTS. +C (FOR MD=1,2,3) + 70 CALL IDPDRV(NDP0,XD,YD,ZD,NCP0,IWK(JWIPC),WK) +C INTERPOLATES THE ZI VALUES. (FOR MD=1,2,3) + 80 ITPV=0 + JWIT=JWIT0 + DO 81 IIP=1,NIP0 + JWIT=JWIT+1 + CALL IDPTIP(XD,YD,ZD,NT,IWK(JWIPT),NL,IWK(JWIPL),WK, + 1 IWK(JWIT),XI(IIP),YI(IIP),ZI(IIP)) + 81 CONTINUE + RETURN +C ERROR EXIT + 90 WRITE (LUN,2090) MD0,NCP0,NDP0,NIP0 + RETURN +C FORMAT STATEMENT FOR ERROR MESSAGE + 2090 FORMAT(1X/41H *** IMPROPER INPUT PARAMETER VALUE(S)./ + 1 7H MD =,I4,10X,5HNCP =,I6,10X,5HNDP =,I6, + 2 10X,5HNIP =,I6/ + 3 35H ERROR DETECTED IN ROUTINE IDBVIP/) + END + SUBROUTINE IDCLDP(NDP,XD,YD,NCP,IPC) ID002720 +C THIS SUBROUTINE SELECTS SEVERAL DATA POINTS THAT ARE CLOSEST +C TO EACH OF THE DATA POINT. +C THE INPUT PARAMETERS ARE +C NDP = NUMBER OF DATA POINTS, +C XD,YD = ARRAYS OF DIMENSION NDP CONTAINING THE X AND Y +C COORDINATES OF THE DATA POINTS, +C NCP = NUMBER OF DATA POINTS CLOSEST TO EACH DATA +C POINTS. +C THE OUTPUT PARAMETER IS +C IPC = INTEGER ARRAY OF DIMENSION NCP*NDP, WHERE THE +C POINT NUMBERS OF NCP DATA POINTS CLOSEST TO +C EACH OF THE NDP DATA POINTS ARE TO BE STORED. +C THIS SUBROUTINE ARBITRARILY SETS A RESTRICTION THAT NCP MUST +C NOT EXCEED 25. +C THE LUN CONSTANT IN THE DATA INITIALIZATION STATEMENT IS THE +C LOGICAL UNIT NUMBER OF THE STANDARD OUTPUT UNIT AND IS, +C THEREFORE, SYSTEM DEPENDENT. +C DECLARATION STATEMENTS + DIMENSION XD(100),YD(100),IPC(400) + DIMENSION DSQ0(25),IPC0(25) + DATA NCPMX/25/, LUN/6/ +C STATEMENT FUNCTION + DSQF(U1,V1,U2,V2)=(U2-U1)**2+(V2-V1)**2 +C PRELIMINARY PROCESSING + 10 NDP0=NDP + NCP0=NCP + IF(NDP0.LT.2) GO TO 90 + IF(NCP0.LT.1.OR.NCP0.GT.NCPMX.OR.NCP0.GE.NDP0) GO TO 90 +C CALCULATION + 20 DO 59 IP1=1,NDP0 +C - SELECTS NCP POINTS. + X1=XD(IP1) + Y1=YD(IP1) + J1=0 + DSQMX=0.0 + DO 22 IP2=1,NDP0 + IF(IP2.EQ.IP1) GO TO 22 + DSQI=DSQF(X1,Y1,XD(IP2),YD(IP2)) + J1=J1+1 + DSQ0(J1)=DSQI + IPC0(J1)=IP2 + IF(DSQI.LE.DSQMX) GO TO 21 + DSQMX=DSQI + JMX=J1 + 21 IF(J1.GE.NCP0) GO TO 23 + 22 CONTINUE + 23 IP2MN=IP2+1 + IF(IP2MN.GT.NDP0) GO TO 30 + DO 25 IP2=IP2MN,NDP0 + IF(IP2.EQ.IP1) GO TO 25 + DSQI=DSQF(X1,Y1,XD(IP2),YD(IP2)) + IF(DSQI.GE.DSQMX) GO TO 25 + DSQ0(JMX)=DSQI + IPC0(JMX)=IP2 + DSQMX=0.0 + DO 24 J1=1,NCP0 + IF(DSQ0(J1).LE.DSQMX) GO TO 24 + DSQMX=DSQ0(J1) + JMX=J1 + 24 CONTINUE + 25 CONTINUE +C - CHECKS IF ALL THE NCP+1 POINTS ARE COLLINEAR. + 30 IP2=IPC0(1) + DX12=XD(IP2)-X1 + DY12=YD(IP2)-Y1 + DO 31 J3=2,NCP0 + IP3=IPC0(J3) + DX13=XD(IP3)-X1 + DY13=YD(IP3)-Y1 + IF((DY13*DX12-DX13*DY12).NE.0.0) GO TO 50 + 31 CONTINUE +C - SEARCHES FOR THE CLOSEST NONCOLLINEAR POINT. + 40 NCLPT=0 + DO 43 IP3=1,NDP0 + IF(IP3.EQ.IP1) GO TO 43 + DO 41 J4=1,NCP0 + IF(IP3.EQ.IPC0(J4)) GO TO 43 + 41 CONTINUE + DX13=XD(IP3)-X1 + DY13=YD(IP3)-Y1 + IF((DY13*DX12-DX13*DY12).EQ.0.0) GO TO 43 + DSQI=DSQF(X1,Y1,XD(IP3),YD(IP3)) + IF(NCLPT.EQ.0) GO TO 42 + IF(DSQI.GE.DSQMN) GO TO 43 + 42 NCLPT=1 + DSQMN=DSQI + IP3MN=IP3 + 43 CONTINUE + IF(NCLPT.EQ.0) GO TO 91 + DSQMX=DSQMN + IPC0(JMX)=IP3MN +C - REPLACES THE LOCAL ARRAY FOR THE OUTPUT ARRAY. + 50 J1=(IP1-1)*NCP0 + DO 51 J2=1,NCP0 + J1=J1+1 + IPC(J1)=IPC0(J2) + 51 CONTINUE + 59 CONTINUE + RETURN +C ERROR EXIT + 90 WRITE (LUN,2090) + GO TO 92 + 91 WRITE (LUN,2091) + 92 WRITE (LUN,2092) NDP0,NCP0 + IPC(1)=0 + RETURN +C FORMAT STATEMENTS FOR ERROR MESSAGES + 2090 FORMAT(1X/41H *** IMPROPER INPUT PARAMETER VALUE(S).) + 2091 FORMAT(1X/33H *** ALL COLLINEAR DATA POINTS.) + 2092 FORMAT(8H NDP =,I5,5X,5HNCP =,I5/ + 1 35H ERROR DETECTED IN ROUTINE IDCLDP/) + END + SUBROUTINE IDGRID(XD, YD, NT, IPT, NL, IPL, NXI, NYI, XI, YI, IDG 10 + * NGP, IGP) +C THIS SUBROUTINE ORGANIZES GRID POINTS FOR SURFACE FITTING BY +C SORTING THEM IN ASCENDING ORDER OF TRIANGLE NUMBERS AND OF THE +C BORDER LINE SEGMENT NUMBER. +C THE INPUT PARAMETERS ARE +C XD,YD = ARRAYS OF DIMENSION NDP CONTAINING THE X AND Y +C COORDINATES OF THE DATA POINTS, WHERE NDP IS THE +C NUMBER OF THE DATA POINTS, +C NT = NUMBER OF TRIANGLES, +C IPT = INTEGER ARRAY OF DIMENSION 3*NT CONTAINING THE +C POINT NUMBERS OF THE VERTEXES OF THE TRIANGLES, +C NL = NUMBER OF BORDER LINE SEGMENTS, +C IPL = INTEGER ARRAY OF DIMENSION 3*NL CONTAINING THE +C POINT NUMBERS OF THE END POINTS OF THE BORDER +C LINE SEGMENTS AND THEIR RESPECTIVE TRIANGLE +C NUMBERS, +C NXI = NUMBER OF GRID POINTS IN THE X COORDINATE, +C NYI = NUMBER OF GRID POINTS IN THE Y COORDINATE, +C XI,YI = ARRAYS OF DIMENSION NXI AND NYI CONTAINING +C THE X AND Y COORDINATES OF THE GRID POINTS, +C RESPECTIVELY. +C THE OUTPUT PARAMETERS ARE +C NGP = INTEGER ARRAY OF DIMENSION 2*(NT+2*NL) WHERE THE +C NUMBER OF GRID POINTS THAT BELONG TO EACH OF THE +C TRIANGLES OR OF THE BORDER LINE SEGMENTS ARE TO +C BE STORED, +C IGP = INTEGER ARRAY OF DIMENSION NXI*NYI WHERE THE +C GRID POINT NUMBERS ARE TO BE STORED IN ASCENDING +C ORDER OF THE TRIANGLE NUMBER AND THE BORDER LINE +C SEGMENT NUMBER. +C DECLARATION STATEMENTS + DIMENSION XD(100), YD(100), IPT(585), IPL(300), XI(101), + * YI(101), NGP(800), IGP(10201) +C STATEMENT FUNCTIONS + SIDE(U1,V1,U2,V2,U3,V3) = (U1-U3)*(V2-V3) - (V1-V3)*(U2-U3) + SPDT(U1,V1,U2,V2,U3,V3) = (U1-U2)*(U3-U2) + (V1-V2)*(V3-V2) +C PRELIMINARY PROCESSING + NT0 = NT + NL0 = NL + NXI0 = NXI + NYI0 = NYI + NXINYI = NXI0*NYI0 + XIMN = AMIN1(XI(1),XI(NXI0)) + XIMX = AMAX1(XI(1),XI(NXI0)) + YIMN = AMIN1(YI(1),YI(NYI0)) + YIMX = AMAX1(YI(1),YI(NYI0)) +C DETERMINES GRID POINTS INSIDE THE DATA AREA. + JNGP0 = 0 + JNGP1 = 2*(NT0+2*NL0) + 1 + JIGP0 = 0 + JIGP1 = NXINYI + 1 + DO 160 IT0=1,NT0 + NGP0 = 0 + NGP1 = 0 + IT0T3 = IT0*3 + IP1 = IPT(IT0T3-2) + IP2 = IPT(IT0T3-1) + IP3 = IPT(IT0T3) + X1 = XD(IP1) + Y1 = YD(IP1) + X2 = XD(IP2) + Y2 = YD(IP2) + X3 = XD(IP3) + Y3 = YD(IP3) + XMN = AMIN1(X1,X2,X3) + XMX = AMAX1(X1,X2,X3) + YMN = AMIN1(Y1,Y2,Y3) + YMX = AMAX1(Y1,Y2,Y3) + INSD = 0 + DO 20 IXI=1,NXI0 + IF (XI(IXI).GE.XMN .AND. XI(IXI).LE.XMX) GO TO 10 + IF (INSD.EQ.0) GO TO 20 + IXIMX = IXI - 1 + GO TO 30 + 10 IF (INSD.EQ.1) GO TO 20 + INSD = 1 + IXIMN = IXI + 20 CONTINUE + IF (INSD.EQ.0) GO TO 150 + IXIMX = NXI0 + 30 DO 140 IYI=1,NYI0 + YII = YI(IYI) + IF (YII.LT.YMN .OR. YII.GT.YMX) GO TO 140 + DO 130 IXI=IXIMN,IXIMX + XII = XI(IXI) + L = 0 + IF (SIDE(X1,Y1,X2,Y2,XII,YII)) 130, 40, 50 + 40 L = 1 + 50 IF (SIDE(X2,Y2,X3,Y3,XII,YII)) 130, 60, 70 + 60 L = 1 + 70 IF (SIDE(X3,Y3,X1,Y1,XII,YII)) 130, 80, 90 + 80 L = 1 + 90 IZI = NXI0*(IYI-1) + IXI + IF (L.EQ.1) GO TO 100 + NGP0 = NGP0 + 1 + JIGP0 = JIGP0 + 1 + IGP(JIGP0) = IZI + GO TO 130 + 100 IF (JIGP1.GT.NXINYI) GO TO 120 + DO 110 JIGP1I=JIGP1,NXINYI + IF (IZI.EQ.IGP(JIGP1I)) GO TO 130 + 110 CONTINUE + 120 NGP1 = NGP1 + 1 + JIGP1 = JIGP1 - 1 + IGP(JIGP1) = IZI + 130 CONTINUE + 140 CONTINUE + 150 JNGP0 = JNGP0 + 1 + NGP(JNGP0) = NGP0 + JNGP1 = JNGP1 - 1 + NGP(JNGP1) = NGP1 + 160 CONTINUE +C DETERMINES GRID POINTS OUTSIDE THE DATA AREA. +C - IN SEMI-INFINITE RECTANGULAR AREA. + DO 450 IL0=1,NL0 + NGP0 = 0 + NGP1 = 0 + IL0T3 = IL0*3 + IP1 = IPL(IL0T3-2) + IP2 = IPL(IL0T3-1) + X1 = XD(IP1) + Y1 = YD(IP1) + X2 = XD(IP2) + Y2 = YD(IP2) + XMN = XIMN + XMX = XIMX + YMN = YIMN + YMX = YIMX + IF (Y2.GE.Y1) XMN = AMIN1(X1,X2) + IF (Y2.LE.Y1) XMX = AMAX1(X1,X2) + IF (X2.LE.X1) YMN = AMIN1(Y1,Y2) + IF (X2.GE.X1) YMX = AMAX1(Y1,Y2) + INSD = 0 + DO 180 IXI=1,NXI0 + IF (XI(IXI).GE.XMN .AND. XI(IXI).LE.XMX) GO TO 170 + IF (INSD.EQ.0) GO TO 180 + IXIMX = IXI - 1 + GO TO 190 + 170 IF (INSD.EQ.1) GO TO 180 + INSD = 1 + IXIMN = IXI + 180 CONTINUE + IF (INSD.EQ.0) GO TO 310 + IXIMX = NXI0 + 190 DO 300 IYI=1,NYI0 + YII = YI(IYI) + IF (YII.LT.YMN .OR. YII.GT.YMX) GO TO 300 + DO 290 IXI=IXIMN,IXIMX + XII = XI(IXI) + L = 0 + IF (SIDE(X1,Y1,X2,Y2,XII,YII)) 210, 200, 290 + 200 L = 1 + 210 IF (SPDT(X2,Y2,X1,Y1,XII,YII)) 290, 220, 230 + 220 L = 1 + 230 IF (SPDT(X1,Y1,X2,Y2,XII,YII)) 290, 240, 250 + 240 L = 1 + 250 IZI = NXI0*(IYI-1) + IXI + IF (L.EQ.1) GO TO 260 + NGP0 = NGP0 + 1 + JIGP0 = JIGP0 + 1 + IGP(JIGP0) = IZI + GO TO 290 + 260 IF (JIGP1.GT.NXINYI) GO TO 280 + DO 270 JIGP1I=JIGP1,NXINYI + IF (IZI.EQ.IGP(JIGP1I)) GO TO 290 + 270 CONTINUE + 280 NGP1 = NGP1 + 1 + JIGP1 = JIGP1 - 1 + IGP(JIGP1) = IZI + 290 CONTINUE + 300 CONTINUE + 310 JNGP0 = JNGP0 + 1 + NGP(JNGP0) = NGP0 + JNGP1 = JNGP1 - 1 + NGP(JNGP1) = NGP1 +C - IN SEMI-INFINITE TRIANGULAR AREA. + NGP0 = 0 + NGP1 = 0 + ILP1 = MOD(IL0,NL0) + 1 + ILP1T3 = ILP1*3 + IP3 = IPL(ILP1T3-1) + X3 = XD(IP3) + Y3 = YD(IP3) + XMN = XIMN + XMX = XIMX + YMN = YIMN + YMX = YIMX + IF (Y3.GE.Y2 .AND. Y2.GE.Y1) XMN = X2 + IF (Y3.LE.Y2 .AND. Y2.LE.Y1) XMX = X2 + IF (X3.LE.X2 .AND. X2.LE.X1) YMN = Y2 + IF (X3.GE.X2 .AND. X2.GE.X1) YMX = Y2 + INSD = 0 + DO 330 IXI=1,NXI0 + IF (XI(IXI).GE.XMN .AND. XI(IXI).LE.XMX) GO TO 320 + IF (INSD.EQ.0) GO TO 330 + IXIMX = IXI - 1 + GO TO 340 + 320 IF (INSD.EQ.1) GO TO 330 + INSD = 1 + IXIMN = IXI + 330 CONTINUE + IF (INSD.EQ.0) GO TO 440 + IXIMX = NXI0 + 340 DO 430 IYI=1,NYI0 + YII = YI(IYI) + IF (YII.LT.YMN .OR. YII.GT.YMX) GO TO 430 + DO 420 IXI=IXIMN,IXIMX + XII = XI(IXI) + L = 0 + IF (SPDT(X1,Y1,X2,Y2,XII,YII)) 360, 350, 420 + 350 L = 1 + 360 IF (SPDT(X3,Y3,X2,Y2,XII,YII)) 380, 370, 420 + 370 L = 1 + 380 IZI = NXI0*(IYI-1) + IXI + IF (L.EQ.1) GO TO 390 + NGP0 = NGP0 + 1 + JIGP0 = JIGP0 + 1 + IGP(JIGP0) = IZI + GO TO 420 + 390 IF (JIGP1.GT.NXINYI) GO TO 410 + DO 400 JIGP1I=JIGP1,NXINYI + IF (IZI.EQ.IGP(JIGP1I)) GO TO 420 + 400 CONTINUE + 410 NGP1 = NGP1 + 1 + JIGP1 = JIGP1 - 1 + IGP(JIGP1) = IZI + 420 CONTINUE + 430 CONTINUE + 440 JNGP0 = JNGP0 + 1 + NGP(JNGP0) = NGP0 + JNGP1 = JNGP1 - 1 + NGP(JNGP1) = NGP1 + 450 CONTINUE + RETURN + END + SUBROUTINE IDLCTN(NDP, XD, YD, NT, IPT, NL, IPL, XII, YII, ITI, IDL 10 + * IWK, WK) +C THIS SUBROUTINE LOCATES A POINT, I.E., DETERMINES TO WHAT TRI- +C ANGLE A GIVEN POINT (XII,YII) BELONGS. WHEN THE GIVEN POINT +C DOES NOT LIE INSIDE THE DATA AREA, THIS SUBROUTINE DETERMINES +C THE BORDER LINE SEGMENT WHEN THE POINT LIES IN AN OUTSIDE +C RECTANGULAR AREA, AND TWO BORDER LINE SEGMENTS WHEN THE POINT +C LIES IN AN OUTSIDE TRIANGULAR AREA. +C THE INPUT PARAMETERS ARE +C NDP = NUMBER OF DATA POINTS, +C XD,YD = ARRAYS OF DIMENSION NDP CONTAINING THE X AND Y +C COORDINATES OF THE DATA POINTS, +C NT = NUMBER OF TRIANGLES, +C IPT = INTEGER ARRAY OF DIMENSION 3*NT CONTAINING THE +C POINT NUMBERS OF THE VERTEXES OF THE TRIANGLES, +C NL = NUMBER OF BORDER LINE SEGMENTS, +C IPL = INTEGER ARRAY OF DIMENSION 3*NL CONTAINING THE +C POINT NUMBERS OF THE END POINTS OF THE BORDER +C LINE SEGMENTS AND THEIR RESPECTIVE TRIANGLE +C NUMBERS, +C XII,YII = X AND Y COORDINATES OF THE POINT TO BE +C LOCATED. +C THE OUTPUT PARAMETER IS +C ITI = TRIANGLE NUMBER, WHEN THE POINT IS INSIDE THE +C DATA AREA, OR +C TWO BORDER LINE SEGMENT NUMBERS, IL1 AND IL2, +C CODED TO IL1*(NT+NL)+IL2, WHEN THE POINT IS +C OUTSIDE THE DATA AREA. +C THE OTHER PARAMETERS ARE +C IWK = INTEGER ARRAY OF DIMENSION 18*NDP USED INTER- +C NALLY AS A WORK AREA, +C WK = ARRAY OF DIMENSION 8*NDP USED INTERNALLY AS A +C WORK AREA. +C DECLARATION STATEMENTS + DIMENSION XD(100), YD(100), IPT(585), IPL(300), IWK(1800), + * WK(800) + DIMENSION NTSC(9), IDSC(9) + COMMON /IDLC/ NIT +C STATEMENT FUNCTIONS + SIDE(U1,V1,U2,V2,U3,V3) = (U1-U3)*(V2-V3) - (V1-V3)*(U2-U3) + SPDT(U1,V1,U2,V2,U3,V3) = (U1-U2)*(U3-U2) + (V1-V2)*(V3-V2) +C PRELIMINARY PROCESSING + NDP0 = NDP + NT0 = NT + NL0 = NL + NTL = NT0 + NL0 + X0 = XII + Y0 = YII +C WRITE(*,*) 'IDLCTN 0.5', NIT +C PROCESSING FOR A NEW SET OF DATA POINTS + IF (NIT.NE.0) GO TO 80 + NIT = 1 +C - DIVIDES THE X-Y PLANE INTO NINE RECTANGULAR SECTIONS. + XMN = XD(1) + XMX = XMN + YMN = YD(1) + YMX = YMN + DO 10 IDP=2,NDP0 + XI = XD(IDP) + YI = YD(IDP) + XMN = AMIN1(XI,XMN) + XMX = AMAX1(XI,XMX) + YMN = AMIN1(YI,YMN) + YMX = AMAX1(YI,YMX) + 10 CONTINUE + XS1 = (XMN+XMN+XMX)/3.0 + XS2 = (XMN+XMX+XMX)/3.0 + YS1 = (YMN+YMN+YMX)/3.0 + YS2 = (YMN+YMX+YMX)/3.0 +C WRITE(*,*) 'IDLCTN 1' +C - DETERMINES AND STORES IN THE IWK ARRAY TRIANGLE NUMBERS OF +C - THE TRIANGLES ASSOCIATED WITH EACH OF THE NINE SECTIONS. + DO 20 ISC=1,9 + NTSC(ISC) = 0 + IDSC(ISC) = 0 + 20 CONTINUE + IT0T3 = 0 + JWK = 0 + DO 70 IT0=1,NT0 + IT0T3 = IT0T3 + 3 + I1 = IPT(IT0T3-2) + I2 = IPT(IT0T3-1) + I3 = IPT(IT0T3) + XMN = AMIN1(XD(I1),XD(I2),XD(I3)) + XMX = AMAX1(XD(I1),XD(I2),XD(I3)) + YMN = AMIN1(YD(I1),YD(I2),YD(I3)) + YMX = AMAX1(YD(I1),YD(I2),YD(I3)) + IF (YMN.GT.YS1) GO TO 30 + IF (XMN.LE.XS1) IDSC(1) = 1 + IF (XMX.GE.XS1 .AND. XMN.LE.XS2) IDSC(2) = 1 + IF (XMX.GE.XS2) IDSC(3) = 1 + 30 IF (YMX.LT.YS1 .OR. YMN.GT.YS2) GO TO 40 + IF (XMN.LE.XS1) IDSC(4) = 1 + IF (XMX.GE.XS1 .AND. XMN.LE.XS2) IDSC(5) = 1 + IF (XMX.GE.XS2) IDSC(6) = 1 + 40 IF (YMX.LT.YS2) GO TO 50 + IF (XMN.LE.XS1) IDSC(7) = 1 + IF (XMX.GE.XS1 .AND. XMN.LE.XS2) IDSC(8) = 1 + IF (XMX.GE.XS2) IDSC(9) = 1 + 50 DO 60 ISC=1,9 + IF (IDSC(ISC).EQ.0) GO TO 60 + JIWK = 9*NTSC(ISC) + ISC + IWK(JIWK) = IT0 + NTSC(ISC) = NTSC(ISC) + 1 + IDSC(ISC) = 0 + 60 CONTINUE +C - STORES IN THE WK ARRAY THE MINIMUM AND MAXIMUM OF THE X AND +C - Y COORDINATE VALUES FOR EACH OF THE TRIANGLE. + JWK = JWK + 4 + WK(JWK-3) = XMN + WK(JWK-2) = XMX + WK(JWK-1) = YMN + WK(JWK) = YMX + 70 CONTINUE + GO TO 110 +C CHECKS IF IN THE SAME TRIANGLE AS PREVIOUS. + 80 IT0 = ITIPV + IF (IT0.GT.NT0) GO TO 90 +C WRITE(*,*) 'IDLCTN after if90' + IT0T3 = IT0*3 + IP1 = IPT(IT0T3-2) + X1 = XD(IP1) + Y1 = YD(IP1) + IP2 = IPT(IT0T3-1) + X2 = XD(IP2) + Y2 = YD(IP2) + IF (SIDE(X1,Y1,X2,Y2,X0,Y0).LT.0.0) GO TO 110 + IP3 = IPT(IT0T3) + X3 = XD(IP3) + Y3 = YD(IP3) + IF (SIDE(X2,Y2,X3,Y3,X0,Y0).LT.0.0) GO TO 110 + IF (SIDE(X3,Y3,X1,Y1,X0,Y0).LT.0.0) GO TO 110 + GO TO 170 +C CHECKS IF ON THE SAME BORDER LINE SEGMENT. + 90 IL1 = IT0/NTL + IL2 = IT0 - IL1*NTL + IL1T3 = IL1*3 + IP1 = IPL(IL1T3-2) +C WRITE(*,*) 'XXXXXXXXXXXXXXXXXXXXIDLCTN after 90', IP1 + X1 = XD(IP1) + Y1 = YD(IP1) + IP2 = IPL(IL1T3-1) + X2 = XD(IP2) + Y2 = YD(IP2) + IF (IL2.NE.IL1) GO TO 100 + IF (SPDT(X1,Y1,X2,Y2,X0,Y0).LT.0.0) GO TO 110 + IF (SPDT(X2,Y2,X1,Y1,X0,Y0).LT.0.0) GO TO 110 + IF (SIDE(X1,Y1,X2,Y2,X0,Y0).GT.0.0) GO TO 110 + GO TO 170 +C CHECKS IF BETWEEN THE SAME TWO BORDER LINE SEGMENTS. + 100 IF (SPDT(X1,Y1,X2,Y2,X0,Y0).GT.0.0) GO TO 110 + IP3 = IPL(3*IL2-1) + X3 = XD(IP3) + Y3 = YD(IP3) + IF (SPDT(X3,Y3,X2,Y2,X0,Y0).LE.0.0) GO TO 170 +C LOCATES INSIDE THE DATA AREA. +C - DETERMINES THE SECTION IN WHICH THE POINT IN QUESTION LIES. + 110 ISC = 1 + IF (X0.GE.XS1) ISC = ISC + 1 + IF (X0.GE.XS2) ISC = ISC + 1 + IF (Y0.GE.YS1) ISC = ISC + 3 + IF (Y0.GE.YS2) ISC = ISC + 3 +C - SEARCHES THROUGH THE TRIANGLES ASSOCIATED WITH THE SECTION. + NTSCI = NTSC(ISC) + IF (NTSCI.LE.0) GO TO 130 + JIWK = -9 + ISC + DO 120 ITSC=1,NTSCI + JIWK = JIWK + 9 + IT0 = IWK(JIWK) + JWK = IT0*4 + IF (X0.LT.WK(JWK-3)) GO TO 120 + IF (X0.GT.WK(JWK-2)) GO TO 120 + IF (Y0.LT.WK(JWK-1)) GO TO 120 + IF (Y0.GT.WK(JWK)) GO TO 120 + IT0T3 = IT0*3 + IP1 = IPT(IT0T3-2) + X1 = XD(IP1) + Y1 = YD(IP1) + IP2 = IPT(IT0T3-1) + X2 = XD(IP2) + Y2 = YD(IP2) + IF (SIDE(X1,Y1,X2,Y2,X0,Y0).LT.0.0) GO TO 120 + IP3 = IPT(IT0T3) + X3 = XD(IP3) + Y3 = YD(IP3) + IF (SIDE(X2,Y2,X3,Y3,X0,Y0).LT.0.0) GO TO 120 + IF (SIDE(X3,Y3,X1,Y1,X0,Y0).LT.0.0) GO TO 120 + GO TO 170 + 120 CONTINUE +C LOCATES OUTSIDE THE DATA AREA. + 130 DO 150 IL1=1,NL0 + IL1T3 = IL1*3 + IP1 = IPL(IL1T3-2) + X1 = XD(IP1) + Y1 = YD(IP1) + IP2 = IPL(IL1T3-1) + X2 = XD(IP2) + Y2 = YD(IP2) + IF (SPDT(X2,Y2,X1,Y1,X0,Y0).LT.0.0) GO TO 150 + IF (SPDT(X1,Y1,X2,Y2,X0,Y0).LT.0.0) GO TO 140 + IF (SIDE(X1,Y1,X2,Y2,X0,Y0).GT.0.0) GO TO 150 + IL2 = IL1 + GO TO 160 + 140 IL2 = MOD(IL1,NL0) + 1 + IP3 = IPL(3*IL2-1) + X3 = XD(IP3) + Y3 = YD(IP3) + IF (SPDT(X3,Y3,X2,Y2,X0,Y0).LE.0.0) GO TO 160 + 150 CONTINUE + IT0 = 1 + GO TO 170 + 160 IT0 = IL1*NTL + IL2 +C NORMAL EXIT + 170 ITI = IT0 + ITIPV = IT0 + RETURN + END + SUBROUTINE IDPDRV(NDP,XD,YD,ZD,NCP,IPC,PD) ID008940 +C THIS SUBROUTINE ESTIMATES PARTIAL DERIVATIVES OF THE FIRST AND +C SECOND ORDER AT THE DATA POINTS. +C THE INPUT PARAMETERS ARE +C NDP = NUMBER OF DATA POINTS, +C XD,YD,ZD = ARRAYS OF DIMENSION NDP CONTAINING THE X, +C Y, AND Z COORDINATES OF THE DATA POINTS, +C NCP = NUMBER OF ADDITIONAL DATA POINTS USED FOR ESTI- +C MATING PARTIAL DERIVATIVES AT EACH DATA POINT, +C IPC = INTEGER ARRAY OF DIMENSION NCP*NDP CONTAINING +C THE POINT NUMBERS OF NCP DATA POINTS CLOSEST TO +C EACH OF THE NDP DATA POINTS. +C THE OUTPUT PARAMETER IS +C PD = ARRAY OF DIMENSION 5*NDP, WHERE THE ESTIMATED +C ZX, ZY, ZXX, ZXY, AND ZYY VALUES AT THE DATA +C POINTS ARE TO BE STORED. +C DECLARATION STATEMENTS + DIMENSION XD(100),YD(100),ZD(100),IPC(400),PD(500) + REAL NMX,NMY,NMZ,NMXX,NMXY,NMYX,NMYY +C PRELIMINARY PROCESSING + 10 NDP0=NDP + NCP0=NCP + NCPM1=NCP0-1 +C ESTIMATION OF ZX AND ZY + 20 DO 24 IP0=1,NDP0 + X0=XD(IP0) + Y0=YD(IP0) + Z0=ZD(IP0) + NMX=0.0 + NMY=0.0 + NMZ=0.0 + JIPC0=NCP0*(IP0-1) + DO 23 IC1=1,NCPM1 + JIPC=JIPC0+IC1 + IPI=IPC(JIPC) + DX1=XD(IPI)-X0 + DY1=YD(IPI)-Y0 + DZ1=ZD(IPI)-Z0 + IC2MN=IC1+1 + DO 22 IC2=IC2MN,NCP0 + JIPC=JIPC0+IC2 + IPI=IPC(JIPC) + DX2=XD(IPI)-X0 + DY2=YD(IPI)-Y0 + DNMZ=DX1*DY2-DY1*DX2 + IF(DNMZ.EQ.0.0) GO TO 22 + DZ2=ZD(IPI)-Z0 + DNMX=DY1*DZ2-DZ1*DY2 + DNMY=DZ1*DX2-DX1*DZ2 + IF(DNMZ.GE.0.0) GO TO 21 + DNMX=-DNMX + DNMY=-DNMY + DNMZ=-DNMZ + 21 NMX=NMX+DNMX + NMY=NMY+DNMY + NMZ=NMZ+DNMZ + 22 CONTINUE + 23 CONTINUE + JPD0=5*IP0 + PD(JPD0-4)=-NMX/NMZ + PD(JPD0-3)=-NMY/NMZ + 24 CONTINUE +C ESTIMATION OF ZXX, ZXY, AND ZYY + 30 DO 34 IP0=1,NDP0 + JPD0=JPD0+5 + X0=XD(IP0) + JPD0=5*IP0 + Y0=YD(IP0) + ZX0=PD(JPD0-4) + ZY0=PD(JPD0-3) + NMXX=0.0 + NMXY=0.0 + NMYX=0.0 + NMYY=0.0 + NMZ =0.0 + JIPC0=NCP0*(IP0-1) + DO 33 IC1=1,NCPM1 + JIPC=JIPC0+IC1 + IPI=IPC(JIPC) + DX1=XD(IPI)-X0 + DY1=YD(IPI)-Y0 + JPD=5*IPI + DZX1=PD(JPD-4)-ZX0 + DZY1=PD(JPD-3)-ZY0 + IC2MN=IC1+1 + DO 32 IC2=IC2MN,NCP0 + JIPC=JIPC0+IC2 + IPI=IPC(JIPC) + DX2=XD(IPI)-X0 + DY2=YD(IPI)-Y0 + DNMZ =DX1*DY2 -DY1*DX2 + IF(DNMZ.EQ.0.0) GO TO 32 + JPD=5*IPI + DZX2=PD(JPD-4)-ZX0 + DZY2=PD(JPD-3)-ZY0 + DNMXX=DY1*DZX2-DZX1*DY2 + DNMXY=DZX1*DX2-DX1*DZX2 + DNMYX=DY1*DZY2-DZY1*DY2 + DNMYY=DZY1*DX2-DX1*DZY2 + IF(DNMZ.GE.0.0) GO TO 31 + DNMXX=-DNMXX + DNMXY=-DNMXY + DNMYX=-DNMYX + DNMYY=-DNMYY + DNMZ =-DNMZ + 31 NMXX=NMXX+DNMXX + NMXY=NMXY+DNMXY + NMYX=NMYX+DNMYX + NMYY=NMYY+DNMYY + NMZ =NMZ +DNMZ + 32 CONTINUE + 33 CONTINUE + PD(JPD0-2)=-NMXX/NMZ + PD(JPD0-1)=-(NMXY+NMYX)/(2.0*NMZ) + PD(JPD0) =-NMYY/NMZ + 34 CONTINUE + RETURN + END + SUBROUTINE IDPTIP(XD,YD,ZD,NT,IPT,NL,IPL,PDD,ITI,XII,YII, ID010190 + 1 ZII) +C THIS SUBROUTINE PERFORMS PUNCTUAL INTERPOLATION OR EXTRAPOLA- +C TION, I.E., DETERMINES THE Z VALUE AT A POINT. +C THE INPUT PARAMETERS ARE +C XD,YD,ZD = ARRAYS OF DIMENSION NDP CONTAINING THE X, +C Y, AND Z COORDINATES OF THE DATA POINTS, WHERE +C NDP IS THE NUMBER OF THE DATA POINTS, +C NT = NUMBER OF TRIANGLES, +C IPT = INTEGER ARRAY OF DIMENSION 3*NT CONTAINING THE +C POINT NUMBERS OF THE VERTEXES OF THE TRIANGLES, +C NL = NUMBER OF BORDER LINE SEGMENTS, +C IPL = INTEGER ARRAY OF DIMENSION 3*NL CONTAINING THE +C POINT NUMBERS OF THE END POINTS OF THE BORDER +C LINE SEGMENTS AND THEIR RESPECTIVE TRIANGLE +C NUMBERS, +C PDD = ARRAY OF DIMENSION 5*NDP CONTAINING THE PARTIAL +C DERIVATIVES AT THE DATA POINTS, +C ITI = TRIANGLE NUMBER OF THE TRIANGLE IN WHICH LIES +C THE POINT FOR WHICH INTERPOLATION IS TO BE +C PERFORMED, +C XII,YII = X AND Y COORDINATES OF THE POINT FOR WHICH +C INTERPOLATION IS TO BE PERFORMED. +C THE OUTPUT PARAMETER IS +C ZII = INTERPOLATED Z VALUE. +C DECLARATION STATEMENTS + DIMENSION XD(100),YD(100),ZD(100),IPT(585),IPL(300), + 1 PDD(500) + COMMON/IDPI/ITPV + DIMENSION X(3),Y(3),Z(3),PD(15), + 1 ZU(3),ZV(3),ZUU(3),ZUV(3),ZVV(3) + REAL LU,LV + EQUIVALENCE (P5,P50) +C PRELIMINARY PROCESSING + 10 IT0=ITI + NTL=NT+NL + IF(IT0.LE.NTL) GO TO 20 + IL1=IT0/NTL + IL2=IT0-IL1*NTL + IF(IL1.EQ.IL2) GO TO 40 + GO TO 60 +C CALCULATION OF ZII BY INTERPOLATION. +C CHECKS IF THE NECESSARY COEFFICIENTS HAVE BEEN CALCULATED. + 20 IF(IT0.EQ.ITPV) GO TO 30 +C LOADS COORDINATE AND PARTIAL DERIVATIVE VALUES AT THE +C VERTEXES. + 21 JIPT=3*(IT0-1) + JPD=0 + DO 23 I=1,3 + JIPT=JIPT+1 + IDP=IPT(JIPT) + X(I)=XD(IDP) + Y(I)=YD(IDP) + Z(I)=ZD(IDP) + JPDD=5*(IDP-1) + DO 22 KPD=1,5 + JPD=JPD+1 + JPDD=JPDD+1 + PD(JPD)=PDD(JPDD) + 22 CONTINUE + 23 CONTINUE +C DETERMINES THE COEFFICIENTS FOR THE COORDINATE SYSTEM +C TRANSFORMATION FROM THE X-Y SYSTEM TO THE U-V SYSTEM +C AND VICE VERSA. + 24 X0=X(1) + Y0=Y(1) + A=X(2)-X0 + B=X(3)-X0 + C=Y(2)-Y0 + D=Y(3)-Y0 + AD=A*D + BC=B*C + DLT=AD-BC + AP= D/DLT + BP=-B/DLT + CP=-C/DLT + DP= A/DLT +C CONVERTS THE PARTIAL DERIVATIVES AT THE VERTEXES OF THE +C TRIANGLE FOR THE U-V COORDINATE SYSTEM. + 25 AA=A*A + ACT2=2.0*A*C + CC=C*C + AB=A*B + ADBC=AD+BC + CD=C*D + BB=B*B + BDT2=2.0*B*D + DD=D*D + DO 26 I=1,3 + JPD=5*I + ZU(I)=A*PD(JPD-4)+C*PD(JPD-3) + ZV(I)=B*PD(JPD-4)+D*PD(JPD-3) + ZUU(I)=AA*PD(JPD-2)+ACT2*PD(JPD-1)+CC*PD(JPD) + ZUV(I)=AB*PD(JPD-2)+ADBC*PD(JPD-1)+CD*PD(JPD) + ZVV(I)=BB*PD(JPD-2)+BDT2*PD(JPD-1)+DD*PD(JPD) + 26 CONTINUE +C CALCULATES THE COEFFICIENTS OF THE POLYNOMIAL. + 27 P00=Z(1) + P10=ZU(1) + P01=ZV(1) + P20=0.5*ZUU(1) + P11=ZUV(1) + P02=0.5*ZVV(1) + H1=Z(2)-P00-P10-P20 + H2=ZU(2)-P10-ZUU(1) + H3=ZUU(2)-ZUU(1) + P30= 10.0*H1-4.0*H2+0.5*H3 + P40=-15.0*H1+7.0*H2 -H3 + P50= 6.0*H1-3.0*H2+0.5*H3 + H1=Z(3)-P00-P01-P02 + H2=ZV(3)-P01-ZVV(1) + H3=ZVV(3)-ZVV(1) + P03= 10.0*H1-4.0*H2+0.5*H3 + P04=-15.0*H1+7.0*H2 -H3 + P05= 6.0*H1-3.0*H2+0.5*H3 + LU=SQRT(AA+CC) + LV=SQRT(BB+DD) + THXU=ATAN2(C,A) + THUV=ATAN2(D,B)-THXU + CSUV=COS(THUV) + P41=5.0*LV*CSUV/LU*P50 + P14=5.0*LU*CSUV/LV*P05 + H1=ZV(2)-P01-P11-P41 + H2=ZUV(2)-P11-4.0*P41 + P21= 3.0*H1-H2 + P31=-2.0*H1+H2 + H1=ZU(3)-P10-P11-P14 + H2=ZUV(3)-P11-4.0*P14 + P12= 3.0*H1-H2 + P13=-2.0*H1+H2 + THUS=ATAN2(D-C,B-A)-THXU + THSV=THUV-THUS + AA= SIN(THSV)/LU + BB=-COS(THSV)/LU + CC= SIN(THUS)/LV + DD= COS(THUS)/LV + AC=AA*CC + AD=AA*DD + BC=BB*CC + G1=AA*AC*(3.0*BC+2.0*AD) + G2=CC*AC*(3.0*AD+2.0*BC) + H1=-AA*AA*AA*(5.0*AA*BB*P50+(4.0*BC+AD)*P41) + 1 -CC*CC*CC*(5.0*CC*DD*P05+(4.0*AD+BC)*P14) + H2=0.5*ZVV(2)-P02-P12 + H3=0.5*ZUU(3)-P20-P21 + P22=(G1*H2+G2*H3-H1)/(G1+G2) + P32=H2-P22 + P23=H3-P22 + ITPV=IT0 +C CONVERTS XII AND YII TO U-V SYSTEM. + 30 DX=XII-X0 + DY=YII-Y0 + U=AP*DX+BP*DY + V=CP*DX+DP*DY +C EVALUATES THE POLYNOMIAL. + 31 P0=P00+V*(P01+V*(P02+V*(P03+V*(P04+V*P05)))) + P1=P10+V*(P11+V*(P12+V*(P13+V*P14))) + P2=P20+V*(P21+V*(P22+V*P23)) + P3=P30+V*(P31+V*P32) + P4=P40+V*P41 + ZII=P0+U*(P1+U*(P2+U*(P3+U*(P4+U*P5)))) + RETURN +C CALCULATION OF ZII BY EXTRAPOLATION IN THE RECTANGLE. +C CHECKS IF THE NECESSARY COEFFICIENTS HAVE BEEN CALCULATED. + 40 IF(IT0.EQ.ITPV) GO TO 50 +C LOADS COORDINATE AND PARTIAL DERIVATIVE VALUES AT THE END +C POINTS OF THE BORDER LINE SEGMENT. + 41 JIPL=3*(IL1-1) + JPD=0 + DO 43 I=1,2 + JIPL=JIPL+1 + IDP=IPL(JIPL) + X(I)=XD(IDP) + Y(I)=YD(IDP) + Z(I)=ZD(IDP) + JPDD=5*(IDP-1) + DO 42 KPD=1,5 + JPD=JPD+1 + JPDD=JPDD+1 + PD(JPD)=PDD(JPDD) + 42 CONTINUE + 43 CONTINUE +C DETERMINES THE COEFFICIENTS FOR THE COORDINATE SYSTEM +C TRANSFORMATION FROM THE X-Y SYSTEM TO THE U-V SYSTEM +C AND VICE VERSA. + 44 X0=X(1) + Y0=Y(1) + A=Y(2)-Y(1) + B=X(2)-X(1) + C=-B + D=A + AD=A*D + BC=B*C + DLT=AD-BC + AP= D/DLT + BP=-B/DLT + CP=-BP + DP= AP +C CONVERTS THE PARTIAL DERIVATIVES AT THE END POINTS OF THE +C BORDER LINE SEGMENT FOR THE U-V COORDINATE SYSTEM. + 45 AA=A*A + ACT2=2.0*A*C + CC=C*C + AB=A*B + ADBC=AD+BC + CD=C*D + BB=B*B + BDT2=2.0*B*D + DD=D*D + DO 46 I=1,2 + JPD=5*I + ZU(I)=A*PD(JPD-4)+C*PD(JPD-3) + ZV(I)=B*PD(JPD-4)+D*PD(JPD-3) + ZUU(I)=AA*PD(JPD-2)+ACT2*PD(JPD-1)+CC*PD(JPD) + ZUV(I)=AB*PD(JPD-2)+ADBC*PD(JPD-1)+CD*PD(JPD) + ZVV(I)=BB*PD(JPD-2)+BDT2*PD(JPD-1)+DD*PD(JPD) + 46 CONTINUE +C CALCULATES THE COEFFICIENTS OF THE POLYNOMIAL. + 47 P00=Z(1) + P10=ZU(1) + P01=ZV(1) + P20=0.5*ZUU(1) + P11=ZUV(1) + P02=0.5*ZVV(1) + H1=Z(2)-P00-P01-P02 + H2=ZV(2)-P01-ZVV(1) + H3=ZVV(2)-ZVV(1) + P03= 10.0*H1-4.0*H2+0.5*H3 + P04=-15.0*H1+7.0*H2 -H3 + P05= 6.0*H1-3.0*H2+0.5*H3 + H1=ZU(2)-P10-P11 + H2=ZUV(2)-P11 + P12= 3.0*H1-H2 + P13=-2.0*H1+H2 + P21=0.0 + P23=-ZUU(2)+ZUU(1) + P22=-1.5*P23 + ITPV=IT0 +C CONVERTS XII AND YII TO U-V SYSTEM. + 50 DX=XII-X0 + DY=YII-Y0 + U=AP*DX+BP*DY + V=CP*DX+DP*DY +C EVALUATES THE POLYNOMIAL. + 51 P0=P00+V*(P01+V*(P02+V*(P03+V*(P04+V*P05)))) + P1=P10+V*(P11+V*(P12+V*P13)) + P2=P20+V*(P21+V*(P22+V*P23)) + ZII=P0+U*(P1+U*P2) + RETURN +C CALCULATION OF ZII BY EXTRAPOLATION IN THE TRIANGLE. +C CHECKS IF THE NECESSARY COEFFICIENTS HAVE BEEN CALCULATED. + 60 IF(IT0.EQ.ITPV) GO TO 70 +C LOADS COORDINATE AND PARTIAL DERIVATIVE VALUES AT THE VERTEX +C OF THE TRIANGLE. + 61 JIPL=3*IL2-2 + IDP=IPL(JIPL) + X(1)=XD(IDP) + Y(1)=YD(IDP) + Z(1)=ZD(IDP) + JPDD=5*(IDP-1) + DO 62 KPD=1,5 + JPDD=JPDD+1 + PD(KPD)=PDD(JPDD) + 62 CONTINUE +C CALCULATES THE COEFFICIENTS OF THE POLYNOMIAL. + 67 P00=Z(1) + P10=PD(1) + P01=PD(2) + P20=0.5*PD(3) + P11=PD(4) + P02=0.5*PD(5) + ITPV=IT0 +C CONVERTS XII AND YII TO U-V SYSTEM. + 70 U=XII-X(1) + V=YII-Y(1) +C EVALUATES THE POLYNOMIAL. + 71 P0=P00+V*(P01+V*P02) + P1=P10+V*P11 + ZII=P0+U*(P1+U*P20) + RETURN + END + SUBROUTINE IDSFFT(MD,NCP,NDP,XD,YD,ZD,NXI,NYI,XI,YI,ZI, ID013070 + 1 IWK,WK) +C THIS SUBROUTINE PERFORMS SMOOTH SURFACE FITTING WHEN THE PRO- +C JECTIONS OF THE DATA POINTS IN THE X-Y PLANE ARE IRREGULARLY +C DISTRIBUTED IN THE PLANE. +C THE INPUT PARAMETERS ARE +C MD = MODE OF COMPUTATION (MUST BE 1, 2, OR 3), +C = 1 FOR NEW NCP AND/OR NEW XD-YD, +C = 2 FOR OLD NCP, OLD XD-YD, NEW XI-YI, +C = 3 FOR OLD NCP, OLD XD-YD, OLD XI-YI, +C NCP = NUMBER OF ADDITIONAL DATA POINTS USED FOR ESTI- +C MATING PARTIAL DERIVATIVES AT EACH DATA POINT +C (MUST BE 2 OR GREATER, BUT SMALLER THAN NDP), +C NDP = NUMBER OF DATA POINTS (MUST BE 4 OR GREATER), +C XD = ARRAY OF DIMENSION NDP CONTAINING THE X +C COORDINATES OF THE DATA POINTS, +C YD = ARRAY OF DIMENSION NDP CONTAINING THE Y +C COORDINATES OF THE DATA POINTS, +C ZD = ARRAY OF DIMENSION NDP CONTAINING THE Z +C COORDINATES OF THE DATA POINTS, +C NXI = NUMBER OF OUTPUT GRID POINTS IN THE X COORDINATE +C (MUST BE 1 OR GREATER), +C NYI = NUMBER OF OUTPUT GRID POINTS IN THE Y COORDINATE +C (MUST BE 1 OR GREATER), +C XI = ARRAY OF DIMENSION NXI CONTAINING THE X +C COORDINATES OF THE OUTPUT GRID POINTS, +C YI = ARRAY OF DIMENSION NYI CONTAINING THE Y +C COORDINATES OF THE OUTPUT GRID POINTS. +C THE OUTPUT PARAMETER IS +C ZI = DOUBLY-DIMENSIONED ARRAY OF DIMENSION (NXI,NYI), +C WHERE THE INTERPOLATED Z VALUES AT THE OUTPUT +C GRID POINTS ARE TO BE STORED. +C THE OTHER PARAMETERS ARE +C IWK = INTEGER ARRAY OF DIMENSION +C MAX0(31,27+NCP)*NDP+NXI*NYI +C USED INTERNALLY AS A WORK AREA, +C WK = ARRAY OF DIMENSION 5*NDP USED INTERNALLY AS A +C WORK AREA. +C THE VERY FIRST CALL TO THIS SUBROUTINE AND THE CALL WITH A NEW +C NCP VALUE, A NEW NDP VALUE, AND/OR NEW CONTENTS OF THE XD AND +C YD ARRAYS MUST BE MADE WITH MD=1. THE CALL WITH MD=2 MUST BE +C PRECEDED BY ANOTHER CALL WITH THE SAME NCP AND NDP VALUES AND +C WITH THE SAME CONTENTS OF THE XD AND YD ARRAYS. THE CALL WITH +C MD=3 MUST BE PRECEDED BY ANOTHER CALL WITH THE SAME NCP, NDP, +C NXI, AND NYI VALUES AND WITH THE SAME CONTENTS OF THE XD, YD, +C XI, AND YI ARRAYS. BETWEEN THE CALL WITH MD=2 OR MD=3 AND ITS +C PRECEDING CALL, THE IWK AND WK ARRAYS MUST NOT BE DISTURBED. +C USE OF A VALUE BETWEEN 3 AND 5 (INCLUSIVE) FOR NCP IS RECOM- +C MENDED UNLESS THERE ARE EVIDENCES THAT DICTATE OTHERWISE. +C THE LUN CONSTANT IN THE DATA INITIALIZATION STATEMENT IS THE +C LOGICAL UNIT NUMBER OF THE STANDARD OUTPUT UNIT AND IS, +C THEREFORE, SYSTEM DEPENDENT. +C THIS SUBROUTINE CALLS THE IDCLDP, IDGRID, IDPDRV, IDPTIP, AND +C IDTANG SUBROUTINES. +C DECLARATION STATEMENTS + DIMENSION XD(100),YD(100),ZD(100),XI(101),YI(101), + 1 ZI(10201),IWK(13301),WK(500) + COMMON/IDPI/ITPV + DATA LUN/6/ +C SETTING OF SOME INPUT PARAMETERS TO LOCAL VARIABLES. +C (FOR MD=1,2,3) + 10 MD0=MD + NCP0=NCP + NDP0=NDP + NXI0=NXI + NYI0=NYI +C ERROR CHECK. (FOR MD=1,2,3) + 20 IF(MD0.LT.1.OR.MD0.GT.3) GO TO 90 + IF(NCP0.LT.2.OR.NCP0.GE.NDP0) GO TO 90 + IF(NDP0.LT.4) GO TO 90 + IF(NXI0.LT.1.OR.NYI0.LT.1) GO TO 90 + IF(MD0.GE.2) GO TO 21 + IWK(1)=NCP0 + IWK(2)=NDP0 + GO TO 22 + 21 NCPPV=IWK(1) + NDPPV=IWK(2) + IF(NCP0.NE.NCPPV) GO TO 90 + IF(NDP0.NE.NDPPV) GO TO 90 + 22 IF(MD0.GE.3) GO TO 23 + IWK(3)=NXI0 + IWK(4)=NYI0 + GO TO 30 + 23 NXIPV=IWK(3) + NYIPV=IWK(4) + IF(NXI0.NE.NXIPV) GO TO 90 + IF(NYI0.NE.NYIPV) GO TO 90 +C ALLOCATION OF STORAGE AREAS IN THE IWK ARRAY. (FOR MD=1,2,3) + 30 JWIPT=16 + JWIWL=6*NDP0+1 + JWNGP0=JWIWL-1 + JWIPL=24*NDP0+1 + JWIWP=30*NDP0+1 + JWIPC=27*NDP0+1 + JWIGP0=MAX0(31,27+NCP0)*NDP0 +C TRIANGULATES THE X-Y PLANE. (FOR MD=1) + 40 IF(MD0.GT.1) GO TO 50 + CALL IDTANG(NDP0,XD,YD,NT,IWK(JWIPT),NL,IWK(JWIPL), + 1 IWK(JWIWL),IWK(JWIWP),WK) + IWK(5)=NT + IWK(6)=NL + IF(NT.EQ.0) RETURN +C DETERMINES NCP POINTS CLOSEST TO EACH DATA POINT. (FOR MD=1) + 50 IF(MD0.GT.1) GO TO 60 + CALL IDCLDP(NDP0,XD,YD,NCP0,IWK(JWIPC)) + IF(IWK(JWIPC).EQ.0) RETURN +C SORTS OUTPUT GRID POINTS IN ASCENDING ORDER OF THE TRIANGLE +C NUMBER AND THE BORDER LINE SEGMENT NUMBER. (FOR MD=1,2) + 60 IF(MD0.EQ.3) GO TO 70 + CALL IDGRID(XD,YD,NT,IWK(JWIPT),NL,IWK(JWIPL),NXI0,NYI0, + 1 XI,YI,IWK(JWNGP0+1),IWK(JWIGP0+1)) +C ESTIMATES PARTIAL DERIVATIVES AT ALL DATA POINTS. +C (FOR MD=1,2,3) + 70 CALL IDPDRV(NDP0,XD,YD,ZD,NCP0,IWK(JWIPC),WK) +C INTERPOLATES THE ZI VALUES. (FOR MD=1,2,3) + 80 ITPV=0 + JIG0MX=0 + JIG1MN=NXI0*NYI0+1 + NNGP=NT+2*NL + DO 89 JNGP=1,NNGP + ITI=JNGP + IF(JNGP.LE.NT) GO TO 81 + IL1=(JNGP-NT+1)/2 + IL2=(JNGP-NT+2)/2 + IF(IL2.GT.NL) IL2=1 + ITI=IL1*(NT+NL)+IL2 + 81 JWNGP=JWNGP0+JNGP + NGP0=IWK(JWNGP) + IF(NGP0.EQ.0) GO TO 86 + JIG0MN=JIG0MX+1 + JIG0MX=JIG0MX+NGP0 + DO 82 JIGP=JIG0MN,JIG0MX + JWIGP=JWIGP0+JIGP + IZI=IWK(JWIGP) + IYI=(IZI-1)/NXI0+1 + IXI=IZI-NXI0*(IYI-1) + CALL IDPTIP(XD,YD,ZD,NT,IWK(JWIPT),NL,IWK(JWIPL),WK, + 1 ITI,XI(IXI),YI(IYI),ZI(IZI)) + 82 CONTINUE + 86 JWNGP=JWNGP0+2*NNGP+1-JNGP + NGP1=IWK(JWNGP) + IF(NGP1.EQ.0) GO TO 89 + JIG1MX=JIG1MN-1 + JIG1MN=JIG1MN-NGP1 + DO 87 JIGP=JIG1MN,JIG1MX + JWIGP=JWIGP0+JIGP + IZI=IWK(JWIGP) + IYI=(IZI-1)/NXI0+1 + IXI=IZI-NXI0*(IYI-1) + CALL IDPTIP(XD,YD,ZD,NT,IWK(JWIPT),NL,IWK(JWIPL),WK, + 1 ITI,XI(IXI),YI(IYI),ZI(IZI)) + 87 CONTINUE + 89 CONTINUE + RETURN +C ERROR EXIT + 90 WRITE (LUN,2090) MD0,NCP0,NDP0,NXI0,NYI0 + RETURN +C FORMAT STATEMENT FOR ERROR MESSAGE + 2090 FORMAT(1X/41H *** IMPROPER INPUT PARAMETER VALUE(S)./ + 1 7H MD =,I4,10X,5HNCP =,I6,10X,5HNDP =,I6, + 2 10X,5HNXI =,I6,10X,5HNYI =,I6/ + 3 35H ERROR DETECTED IN ROUTINE IDSFFT/) + END + SUBROUTINE IDTANG(NDP,XD,YD,NT,IPT,NL,IPL,IWL,IWP,WK) ID014770 +C THIS SUBROUTINE PERFORMS TRIANGULATION. IT DIVIDES THE X-Y +C PLANE INTO A NUMBER OF TRIANGLES ACCORDING TO GIVEN DATA +C POINTS IN THE PLANE, DETERMINES LINE SEGMENTS THAT FORM THE +C BORDER OF DATA AREA, AND DETERMINES THE TRIANGLE NUMBERS +C CORRESPONDING TO THE BORDER LINE SEGMENTS. +C AT COMPLETION, POINT NUMBERS OF THE VERTEXES OF EACH TRIANGLE +C ARE LISTED COUNTER-CLOCKWISE. POINT NUMBERS OF THE END POINTS +C OF EACH BORDER LINE SEGMENT ARE LISTED COUNTER-CLOCKWISE, +C LISTING ORDER OF THE LINE SEGMENTS BEING COUNTER-CLOCKWISE. +C THE LUN CONSTANT IN THE DATA INITIALIZATION STATEMENT IS THE +C LOGICAL UNIT NUMBER OF THE STANDARD OUTPUT UNIT AND IS, +C THEREFORE, SYSTEM DEPENDENT. +C THIS SUBROUTINE CALLS THE IDXCHG FUNCTION. +C THE INPUT PARAMETERS ARE +C NDP = NUMBER OF DATA POINTS, +C XD = ARRAY OF DIMENSION NDP CONTAINING THE +C X COORDINATES OF THE DATA POINTS, +C YD = ARRAY OF DIMENSION NDP CONTAINING THE +C Y COORDINATES OF THE DATA POINTS. +C THE OUTPUT PARAMETERS ARE +C NT = NUMBER OF TRIANGLES, +C IPT = INTEGER ARRAY OF DIMENSION 6*NDP-15, WHERE THE +C POINT NUMBERS OF THE VERTEXES OF THE (IT)TH +C TRIANGLE ARE TO BE STORED AS THE (3*IT-2)ND, +C (3*IT-1)ST, AND (3*IT)TH ELEMENTS, +C IT=1,2,...,NT, +C NL = NUMBER OF BORDER LINE SEGMENTS, +C IPL = INTEGER ARRAY OF DIMENSION 6*NDP, WHERE THE +C POINT NUMBERS OF THE END POINTS OF THE (IL)TH +C BORDER LINE SEGMENT AND ITS RESPECTIVE TRIANGLE +C NUMBER ARE TO BE STORED AS THE (3*IL-2)ND, +C (3*IL-1)ST, AND (3*IL)TH ELEMENTS, +C IL=1,2,..., NL. +C THE OTHER PARAMETERS ARE +C IWL = INTEGER ARRAY OF DIMENSION 18*NDP USED +C INTERNALLY AS A WORK AREA, +C IWP = INTEGER ARRAY OF DIMENSION NDP USED +C INTERNALLY AS A WORK AREA, +C WK = ARRAY OF DIMENSION NDP USED INTERNALLY AS A +C WORK AREA. +C DECLARATION STATEMENTS + DIMENSION XD(100),YD(100),IPT(585),IPL(600), + 1 IWL(1800),IWP(100),WK(100) + DIMENSION ITF(2) + DATA RATIO/1.0E-6/, NREP/100/, LUN/6/ +C STATEMENT FUNCTIONS + DSQF(U1,V1,U2,V2)=(U2-U1)**2+(V2-V1)**2 + SIDE(U1,V1,U2,V2,U3,V3)=(V3-V1)*(U2-U1)-(U3-U1)*(V2-V1) +C PRELIMINARY PROCESSING + 10 NDP0=NDP + NDPM1=NDP0-1 + IF(NDP0.LT.4) GO TO 90 +C DETERMINES THE CLOSEST PAIR OF DATA POINTS AND THEIR MIDPOINT. + 20 DSQMN=DSQF(XD(1),YD(1),XD(2),YD(2)) + IPMN1=1 + IPMN2=2 + DO 22 IP1=1,NDPM1 + X1=XD(IP1) + Y1=YD(IP1) + IP1P1=IP1+1 + DO 21 IP2=IP1P1,NDP0 + DSQI=DSQF(X1,Y1,XD(IP2),YD(IP2)) + IF(DSQI.EQ.0.0) GO TO 91 + IF(DSQI.GE.DSQMN) GO TO 21 + DSQMN=DSQI + IPMN1=IP1 + IPMN2=IP2 + 21 CONTINUE + 22 CONTINUE + DSQ12=DSQMN + XDMP=(XD(IPMN1)+XD(IPMN2))/2.0 + YDMP=(YD(IPMN1)+YD(IPMN2))/2.0 +C SORTS THE OTHER (NDP-2) DATA POINTS IN ASCENDING ORDER OF +C DISTANCE FROM THE MIDPOINT AND STORES THE SORTED DATA POINT +C NUMBERS IN THE IWP ARRAY. + 30 JP1=2 + DO 31 IP1=1,NDP0 + IF(IP1.EQ.IPMN1.OR.IP1.EQ.IPMN2) GO TO 31 + JP1=JP1+1 + IWP(JP1)=IP1 + WK(JP1)=DSQF(XDMP,YDMP,XD(IP1),YD(IP1)) + 31 CONTINUE + DO 33 JP1=3,NDPM1 + DSQMN=WK(JP1) + JPMN=JP1 + DO 32 JP2=JP1,NDP0 + IF(WK(JP2).GE.DSQMN) GO TO 32 + DSQMN=WK(JP2) + JPMN=JP2 + 32 CONTINUE + ITS=IWP(JP1) + IWP(JP1)=IWP(JPMN) + IWP(JPMN)=ITS + WK(JPMN)=WK(JP1) + 33 CONTINUE +C IF NECESSARY, MODIFIES THE ORDERING IN SUCH A WAY THAT THE +C FIRST THREE DATA POINTS ARE NOT COLLINEAR. + 35 AR=DSQ12*RATIO + X1=XD(IPMN1) + Y1=YD(IPMN1) + DX21=XD(IPMN2)-X1 + DY21=YD(IPMN2)-Y1 + DO 36 JP=3,NDP0 + IP=IWP(JP) + IF(ABS((YD(IP)-Y1)*DX21-(XD(IP)-X1)*DY21).GT.AR) + 1 GO TO 37 + 36 CONTINUE + GO TO 92 + 37 IF(JP.EQ.3) GO TO 40 + JPMX=JP + JP=JPMX+1 + DO 38 JPC=4,JPMX + JP=JP-1 + IWP(JP)=IWP(JP-1) + 38 CONTINUE + IWP(3)=IP +C FORMS THE FIRST TRIANGLE. STORES POINT NUMBERS OF THE VER- +C TEXES OF THE TRIANGLE IN THE IPT ARRAY, AND STORES POINT NUM- +C BERS OF THE BORDER LINE SEGMENTS AND THE TRIANGLE NUMBER IN +C THE IPL ARRAY. + 40 IP1=IPMN1 + IP2=IPMN2 + IP3=IWP(3) + IF(SIDE(XD(IP1),YD(IP1),XD(IP2),YD(IP2),XD(IP3),YD(IP3)) + 1 .GE.0.0) GO TO 41 + IP1=IPMN2 + IP2=IPMN1 + 41 NT0=1 + NTT3=3 + IPT(1)=IP1 + IPT(2)=IP2 + IPT(3)=IP3 + NL0=3 + NLT3=9 + IPL(1)=IP1 + IPL(2)=IP2 + IPL(3)=1 + IPL(4)=IP2 + IPL(5)=IP3 + IPL(6)=1 + IPL(7)=IP3 + IPL(8)=IP1 + IPL(9)=1 +C ADDS THE REMAINING (NDP-3) DATA POINTS, ONE BY ONE. + 50 DO 79 JP1=4,NDP0 + IP1=IWP(JP1) + X1=XD(IP1) + Y1=YD(IP1) +C - DETERMINES THE VISIBLE BORDER LINE SEGMENTS. + IP2=IPL(1) + JPMN=1 + DXMN=XD(IP2)-X1 + DYMN=YD(IP2)-Y1 + DSQMN=DXMN**2+DYMN**2 + ARMN=DSQMN*RATIO + JPMX=1 + DXMX=DXMN + DYMX=DYMN + DSQMX=DSQMN + ARMX=ARMN + DO 52 JP2=2,NL0 + IP2=IPL(3*JP2-2) + DX=XD(IP2)-X1 + DY=YD(IP2)-Y1 + AR=DY*DXMN-DX*DYMN + IF(AR.GT.ARMN) GO TO 51 + DSQI=DX**2+DY**2 + IF(AR.GE.(-ARMN).AND.DSQI.GE.DSQMN) GO TO 51 + JPMN=JP2 + DXMN=DX + DYMN=DY + DSQMN=DSQI + ARMN=DSQMN*RATIO + 51 AR=DY*DXMX-DX*DYMX + IF(AR.LT.(-ARMX)) GO TO 52 + DSQI=DX**2+DY**2 + IF(AR.LE.ARMX.AND.DSQI.GE.DSQMX) GO TO 52 + JPMX=JP2 + DXMX=DX + DYMX=DY + DSQMX=DSQI + ARMX=DSQMX*RATIO + 52 CONTINUE + IF(JPMX.LT.JPMN) JPMX=JPMX+NL0 + NSH=JPMN-1 + IF(NSH.LE.0) GO TO 60 +C - SHIFTS (ROTATES) THE IPL ARRAY TO HAVE THE INVISIBLE BORDER +C - LINE SEGMENTS CONTAINED IN THE FIRST PART OF THE IPL ARRAY. + NSHT3=NSH*3 + DO 53 JP2T3=3,NSHT3,3 + JP3T3=JP2T3+NLT3 + IPL(JP3T3-2)=IPL(JP2T3-2) + IPL(JP3T3-1)=IPL(JP2T3-1) + IPL(JP3T3) =IPL(JP2T3) + 53 CONTINUE + DO 54 JP2T3=3,NLT3,3 + JP3T3=JP2T3+NSHT3 + IPL(JP2T3-2)=IPL(JP3T3-2) + IPL(JP2T3-1)=IPL(JP3T3-1) + IPL(JP2T3) =IPL(JP3T3) + 54 CONTINUE + JPMX=JPMX-NSH +C - ADDS TRIANGLES TO THE IPT ARRAY, UPDATES BORDER LINE +C - SEGMENTS IN THE IPL ARRAY, AND SETS FLAGS FOR THE BORDER +C - LINE SEGMENTS TO BE REEXAMINED IN THE IWL ARRAY. + 60 JWL=0 + DO 64 JP2=JPMX,NL0 + JP2T3=JP2*3 + IPL1=IPL(JP2T3-2) + IPL2=IPL(JP2T3-1) + IT =IPL(JP2T3) +C - - ADDS A TRIANGLE TO THE IPT ARRAY. + NT0=NT0+1 + NTT3=NTT3+3 + IPT(NTT3-2)=IPL2 + IPT(NTT3-1)=IPL1 + IPT(NTT3) =IP1 +C - - UPDATES BORDER LINE SEGMENTS IN THE IPL ARRAY. + IF(JP2.NE.JPMX) GO TO 61 + IPL(JP2T3-1)=IP1 + IPL(JP2T3) =NT0 + 61 IF(JP2.NE.NL0) GO TO 62 + NLN=JPMX+1 + NLNT3=NLN*3 + IPL(NLNT3-2)=IP1 + IPL(NLNT3-1)=IPL(1) + IPL(NLNT3) =NT0 +C - - DETERMINES THE VERTEX THAT DOES NOT LIE ON THE BORDER +C - - LINE SEGMENTS. + 62 ITT3=IT*3 + IPTI=IPT(ITT3-2) + IF(IPTI.NE.IPL1.AND.IPTI.NE.IPL2) GO TO 63 + IPTI=IPT(ITT3-1) + IF(IPTI.NE.IPL1.AND.IPTI.NE.IPL2) GO TO 63 + IPTI=IPT(ITT3) +C - - CHECKS IF THE EXCHANGE IS NECESSARY. + 63 IF(IDXCHG(XD,YD,IP1,IPTI,IPL1,IPL2).EQ.0) GO TO 64 +C - - MODIFIES THE IPT ARRAY WHEN NECESSARY. + IPT(ITT3-2)=IPTI + IPT(ITT3-1)=IPL1 + IPT(ITT3) =IP1 + IPT(NTT3-1)=IPTI + IF(JP2.EQ.JPMX) IPL(JP2T3)=IT + IF(JP2.EQ.NL0.AND.IPL(3).EQ.IT) IPL(3)=NT0 +C - - SETS FLAGS IN THE IWL ARRAY. + JWL=JWL+4 + IWL(JWL-3)=IPL1 + IWL(JWL-2)=IPTI + IWL(JWL-1)=IPTI + IWL(JWL) =IPL2 + 64 CONTINUE + NL0=NLN + NLT3=NLNT3 + NLF=JWL/2 + IF(NLF.EQ.0) GO TO 79 +C - IMPROVES TRIANGULATION. + 70 NTT3P3=NTT3+3 + DO 78 IREP=1,NREP + DO 76 ILF=1,NLF + ILFT2=ILF*2 + IPL1=IWL(ILFT2-1) + IPL2=IWL(ILFT2) +C - - LOCATES IN THE IPT ARRAY TWO TRIANGLES ON BOTH SIDES OF +C - - THE FLAGGED LINE SEGMENT. + NTF=0 + DO 71 ITT3R=3,NTT3,3 + ITT3=NTT3P3-ITT3R + IPT1=IPT(ITT3-2) + IPT2=IPT(ITT3-1) + IPT3=IPT(ITT3) + IF(IPL1.NE.IPT1.AND.IPL1.NE.IPT2.AND. + 1 IPL1.NE.IPT3) GO TO 71 + IF(IPL2.NE.IPT1.AND.IPL2.NE.IPT2.AND. + 1 IPL2.NE.IPT3) GO TO 71 + NTF=NTF+1 + ITF(NTF)=ITT3/3 + IF(NTF.EQ.2) GO TO 72 + 71 CONTINUE + IF(NTF.LT.2) GO TO 76 +C - - DETERMINES THE VERTEXES OF THE TRIANGLES THAT DO NOT LIE +C - - ON THE LINE SEGMENT. + 72 IT1T3=ITF(1)*3 + IPTI1=IPT(IT1T3-2) + IF(IPTI1.NE.IPL1.AND.IPTI1.NE.IPL2) GO TO 73 + IPTI1=IPT(IT1T3-1) + IF(IPTI1.NE.IPL1.AND.IPTI1.NE.IPL2) GO TO 73 + IPTI1=IPT(IT1T3) + 73 IT2T3=ITF(2)*3 + IPTI2=IPT(IT2T3-2) + IF(IPTI2.NE.IPL1.AND.IPTI2.NE.IPL2) GO TO 74 + IPTI2=IPT(IT2T3-1) + IF(IPTI2.NE.IPL1.AND.IPTI2.NE.IPL2) GO TO 74 + IPTI2=IPT(IT2T3) +C - - CHECKS IF THE EXCHANGE IS NECESSARY. + 74 IF(IDXCHG(XD,YD,IPTI1,IPTI2,IPL1,IPL2).EQ.0) + 1 GO TO 76 +C - - MODIFIES THE IPT ARRAY WHEN NECESSARY. + IPT(IT1T3-2)=IPTI1 + IPT(IT1T3-1)=IPTI2 + IPT(IT1T3) =IPL1 + IPT(IT2T3-2)=IPTI2 + IPT(IT2T3-1)=IPTI1 + IPT(IT2T3) =IPL2 +C - - SETS NEW FLAGS. + JWL=JWL+8 + IWL(JWL-7)=IPL1 + IWL(JWL-6)=IPTI1 + IWL(JWL-5)=IPTI1 + IWL(JWL-4)=IPL2 + IWL(JWL-3)=IPL2 + IWL(JWL-2)=IPTI2 + IWL(JWL-1)=IPTI2 + IWL(JWL) =IPL1 + DO 75 JLT3=3,NLT3,3 + IPLJ1=IPL(JLT3-2) + IPLJ2=IPL(JLT3-1) + IF((IPLJ1.EQ.IPL1.AND.IPLJ2.EQ.IPTI2).OR. + 1 (IPLJ2.EQ.IPL1.AND.IPLJ1.EQ.IPTI2)) + 2 IPL(JLT3)=ITF(1) + IF((IPLJ1.EQ.IPL2.AND.IPLJ2.EQ.IPTI1).OR. + 1 (IPLJ2.EQ.IPL2.AND.IPLJ1.EQ.IPTI1)) + 2 IPL(JLT3)=ITF(2) + 75 CONTINUE + 76 CONTINUE + NLFC=NLF + NLF=JWL/2 + IF(NLF.EQ.NLFC) GO TO 79 +C - - RESETS THE IWL ARRAY FOR THE NEXT ROUND. + JWL=0 + JWL1MN=(NLFC+1)*2 + NLFT2=NLF*2 + DO 77 JWL1=JWL1MN,NLFT2,2 + JWL=JWL+2 + IWL(JWL-1)=IWL(JWL1-1) + IWL(JWL) =IWL(JWL1) + 77 CONTINUE + NLF=JWL/2 + 78 CONTINUE + 79 CONTINUE +C REARRANGES THE IPT ARRAY SO THAT THE VERTEXES OF EACH TRIANGLE +C ARE LISTED COUNTER-CLOCKWISE. + 80 DO 81 ITT3=3,NTT3,3 + IP1=IPT(ITT3-2) + IP2=IPT(ITT3-1) + IP3=IPT(ITT3) + IF(SIDE(XD(IP1),YD(IP1),XD(IP2),YD(IP2),XD(IP3),YD(IP3)) + 1 .GE.0.0) GO TO 81 + IPT(ITT3-2)=IP2 + IPT(ITT3-1)=IP1 + 81 CONTINUE + NT=NT0 + NL=NL0 + RETURN +C ERROR EXIT + 90 WRITE (LUN,2090) NDP0 + GO TO 93 + 91 WRITE (LUN,2091) NDP0,IP1,IP2,X1,Y1 + GO TO 93 + 92 WRITE (LUN,2092) NDP0 + 93 WRITE (LUN,2093) + NT=0 + RETURN +C FORMAT STATEMENTS + 2090 FORMAT(1X/23H *** NDP LESS THAN 4./8H NDP =,I5) + 2091 FORMAT(1X/29H *** IDENTICAL DATA POINTS./ + 1 8H NDP =,I5,5X,5HIP1 =,I5,5X,5HIP2 =,I5, + 2 5X,4HXD =,E12.4,5X,4HYD =,E12.4) + 2092 FORMAT(1X/33H *** ALL COLLINEAR DATA POINTS./ + 1 8H NDP =,I5) + 2093 FORMAT(35H ERROR DETECTED IN ROUTINE IDTANG/) + END + FUNCTION IDXCHG(X,Y,I1,I2,I3,I4) ID018560 +C THIS FUNCTION DETERMINES WHETHER OR NOT THE EXCHANGE OF TWO +C TRIANGLES IS NECESSARY ON THE BASIS OF MAX-MIN-ANGLE CRITERION +C BY C. L. LAWSON. +C THE INPUT PARAMETERS ARE +C X,Y = ARRAYS CONTAINING THE COORDINATES OF THE DATA +C POINTS, +C I1,I2,I3,I4 = POINT NUMBERS OF FOUR POINTS P1, P2, +C P3, AND P4 THAT FORM A QUADRILATERAL WITH P3 +C AND P4 CONNECTED DIAGONALLY. +C THIS FUNCTION RETURNS AN INTEGER VALUE 1 (ONE) WHEN AN EX- +C CHANGE IS NECESSARY, AND 0 (ZERO) OTHERWISE. +C DECLARATION STATEMENTS + DIMENSION X(100),Y(100) + EQUIVALENCE (C2SQ,C1SQ),(A3SQ,B2SQ),(B3SQ,A1SQ), + 1 (A4SQ,B1SQ),(B4SQ,A2SQ),(C4SQ,C3SQ) +C PRELIMINARY PROCESSING + 10 X1=X(I1) + Y1=Y(I1) + X2=X(I2) + Y2=Y(I2) + X3=X(I3) + Y3=Y(I3) + X4=X(I4) + Y4=Y(I4) +C CALCULATION + 20 IDX=0 + U3=(Y2-Y3)*(X1-X3)-(X2-X3)*(Y1-Y3) + U4=(Y1-Y4)*(X2-X4)-(X1-X4)*(Y2-Y4) + IF(U3*U4.LE.0.0) GO TO 30 + U1=(Y3-Y1)*(X4-X1)-(X3-X1)*(Y4-Y1) + U2=(Y4-Y2)*(X3-X2)-(X4-X2)*(Y3-Y2) + A1SQ=(X1-X3)**2+(Y1-Y3)**2 + B1SQ=(X4-X1)**2+(Y4-Y1)**2 + C1SQ=(X3-X4)**2+(Y3-Y4)**2 + A2SQ=(X2-X4)**2+(Y2-Y4)**2 + B2SQ=(X3-X2)**2+(Y3-Y2)**2 + C3SQ=(X2-X1)**2+(Y2-Y1)**2 + S1SQ=U1*U1/(C1SQ*AMAX1(A1SQ,B1SQ)) + S2SQ=U2*U2/(C2SQ*AMAX1(A2SQ,B2SQ)) + S3SQ=U3*U3/(C3SQ*AMAX1(A3SQ,B3SQ)) + S4SQ=U4*U4/(C4SQ*AMAX1(A4SQ,B4SQ)) + IF(AMIN1(S1SQ,S2SQ).LT.AMIN1(S3SQ,S4SQ)) IDX=1 + 30 IDXCHG=IDX + RETURN + END Added: branches/Interpolate1D/extensions/interp_526a.pyf =================================================================== --- branches/Interpolate1D/extensions/interp_526a.pyf 2008-08-11 16:17:36 UTC (rev 4636) +++ branches/Interpolate1D/extensions/interp_526a.pyf 2008-08-11 21:39:17 UTC (rev 4637) @@ -0,0 +1,25 @@ +! -*- f90 -*- +! Note: the context of this file is case sensitive. + +python module interp_526 ! in + ! blubber foo bar + interface ! in :interp_526 + subroutine idbvip(md,ncp,ndp,xd,yd,zd,nip,xi,yi,zi,iwk,wk) ! in :interp_526:interp_526a.f + integer optional,check((md>=1)&&(md<=3)):: md = 1 + integer optional,check((ncp>=2)&&(ncp=4) :: ndp=len(xd) + real dimension(ndp) :: xd + real dimension(ndp),depend(ndp),check(len(yd)==ndp) :: yd + real dimension(ndp),depend(ndp) :: zd + integer depend(xi),intent(hide) :: nip=len(xi) + real dimension(nip) :: xi + real dimension(nip),depend(nip),check(len(yi)==nip) :: yi + real dimension(nip),depend(nip),intent(out) :: zi + integer dimension((MAX(31,27+ncp))*ndp+nip),depend(ncp,ndp,nip),intent(hide,cache) :: iwk + real dimension(8 * ndp),depend(ndp),intent(hide,cache) :: wk + end subroutine idbvip + end interface +end python module interp_526 + +! This file was auto-generated with f2py (version:2_2527). +! See http://cens.ioc.ee/projects/f2py2e/ Modified: branches/Interpolate1D/info.py =================================================================== --- branches/Interpolate1D/info.py 2008-08-11 16:17:36 UTC (rev 4636) +++ branches/Interpolate1D/info.py 2008-08-11 21:39:17 UTC (rev 4637) @@ -56,6 +56,7 @@ logarithmic : logarithmic interpolation block : block interpolation block_average_above : block average above interpolation + algorithm526 : interpolation of 2D scattered data by TOMS Algorithm 526 """ Modified: branches/Interpolate1D/interpolate2d.py =================================================================== --- branches/Interpolate1D/interpolate2d.py 2008-08-11 16:17:36 UTC (rev 4636) +++ branches/Interpolate1D/interpolate2d.py 2008-08-11 21:39:17 UTC (rev 4637) @@ -2,6 +2,7 @@ from numpy import NaN, array import numpy as np from fitpack_wrapper import Spline2d +from algorithm526_wrapper import algorithm526 def atleast_1d_and_contiguous(ary, dtype = np.float64): # FIXME : don't have in 2 places @@ -19,7 +20,8 @@ 'Quartic' : Spline2d(kx=4, ky=4), 'quartic' : Spline2d(kx=4, ky=4), 'Quar' : Spline2d(kx=4, ky=4), 'quar' : Spline2d(kx=4, ky=4), 'Quintic' : Spline2d(kx=5, ky=5), 'quintic' : Spline2d(kx=5, ky=5), - 'Quin' : Spline2d(kx=5, ky=5), 'quin' : Spline2d(kx=5, ky=5) + 'Quin' : Spline2d(kx=5, ky=5), 'quin' : Spline2d(kx=5, ky=5), + '526' : algorithm526, 'algorithm526':algorithm526, } # dictionary of types for casting. key = possible datatype, value = datatype it is cast to @@ -133,11 +135,12 @@ self._init_xyz(x, y, z, bad_data) self.kind = self._init_interp_method(kind) + self.out = self._init_interp_method(out) def _init_xyz(self, x, y, z, bad_data): - # all must be vectors. Should allow meshgrid, though? Perhaps. - # Mention that in documentation. + + # FIXME : perhaps allow 2D input if it is inthe form of meshgrid if bad_data is not None: try: # check that bad_data contains only numerical values @@ -248,9 +251,9 @@ (min(self._y) <= newy) & (newy <= max(self._y)) # filling array of interpolated z-values - result = np.zeros(np.shape(newx)) - if sum(in_range_mask) > 0: # if there are in-range values. hack to deal - # with behavior of np.vectorize on arrays of length 0 + result = np.zeros(np.shape(newx), dtype = self._zdtype) + if sum(in_range_mask) > 0: # if there are in-range values. hack to deal + # with behavior of np.vectorize on arrays of length 0 result[in_range_mask] = self.kind(newx[in_range_mask], newy[in_range_mask]) if sum(~in_range_mask) > 0: result[~in_range_mask] = self.out(newx[~in_range_mask], newy[~in_range_mask]) Modified: branches/Interpolate1D/setup.py =================================================================== --- branches/Interpolate1D/setup.py 2008-08-11 16:17:36 UTC (rev 4636) +++ branches/Interpolate1D/setup.py 2008-08-11 21:39:17 UTC (rev 4637) @@ -30,15 +30,21 @@ # ND Image routines for ND interpolation config.add_extension('_nd_image', - sources=["extensions/ndimage/nd_image.c", - "extensions/ndimage/ni_filters.c", - "extensions/ndimage/ni_fourier.c", - "extensions/ndimage/ni_interpolation.c", - "extensions/ndimage/ni_measure.c", - "extensions/ndimage/ni_morphology.c", - "extensions/ndimage/ni_support.c"], + sources = ["extensions/ndimage/nd_image.c", + "extensions/ndimage/ni_filters.c", + "extensions/ndimage/ni_fourier.c", + "extensions/ndimage/ni_interpolation.c", + "extensions/ndimage/ni_measure.c", + "extensions/ndimage/ni_morphology.c", + "extensions/ndimage/ni_support.c"], include_dirs=['extensions/ndimage']+[get_include()], ) + + # implements algorithm 526 for 2D interpolation + config.add_extension('interp_526', + sources = ['extensions/interp_526a.pyf', + 'extensions/interp_526.f'] + ) config.add_data_dir('docs') Modified: branches/Interpolate1D/tests/regression_test.py =================================================================== --- branches/Interpolate1D/tests/regression_test.py 2008-08-11 16:17:36 UTC (rev 4636) +++ branches/Interpolate1D/tests/regression_test.py 2008-08-11 21:39:17 UTC (rev 4637) @@ -38,7 +38,8 @@ Test1_dict[test_name] = t2-t1 current_dict['Test1'] = Test1_dict - + +# 2-dimensional if True: test_list = [name for name in dir(Test2) if name.find('test_') == 0] Test2_dict = {} @@ -52,6 +53,7 @@ current_dict['Test2'] = Test2_dict +# N-dmensional if True: test_list = [name for name in dir(TestN) if name.find('test_') == 0] TestN_dict = {} Modified: branches/Interpolate1D/tests/test_interpolate2d.py =================================================================== --- branches/Interpolate1D/tests/test_interpolate2d.py 2008-08-11 16:17:36 UTC (rev 4636) +++ branches/Interpolate1D/tests/test_interpolate2d.py 2008-08-11 21:39:17 UTC (rev 4637) @@ -129,7 +129,7 @@ def test_string_linear(self): """ make sure : string 'linear' works """ - N = 7 + N = 700 X, Y = meshgrid(arange(N), arange(N)) Z = X + Y x, y, z = map(ravel, [X, Y, Z] ) @@ -145,7 +145,7 @@ def test_string_quadratic(self): """ make sure : string 'quadratic' works """ - N = 7 + N = 700 X, Y = meshgrid(arange(N), arange(N)) Z = X + Y x, y, z = map(ravel, [X, Y, Z] ) @@ -161,7 +161,7 @@ def test_string_cubic(self): """make sure : string "cubic" works """ - N = 7 + N = 700 X, Y = meshgrid(arange(N), arange(N)) Z = X + Y x, y, z = map(ravel, [X, Y, Z] ) @@ -174,5 +174,22 @@ self.assertAllclose(newz, newx+newy) + def test_string_526(self): + """ make sure : keyword '526' works + ie that TOMS algorithm 526 works + """ + N = 700 + X, Y = meshgrid(arange(N), arange(N)) + Z = X + Y + x, y, z = map(ravel, [X, Y, Z] ) + + newx = np.arange(1, N)-0.5 + newy = newx + + interp_func = Interpolate2d(x, y, z, kind='526', out='526') + newz = interp_func(newx, newy) + + self.assertAllclose(newz, newx+newy) + if __name__ == '__main__': unittest.main() \ No newline at end of file From scipy-svn at scipy.org Mon Aug 11 19:09:06 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 11 Aug 2008 18:09:06 -0500 (CDT) Subject: [Scipy-svn] r4638 - in trunk/scipy/ndimage: . src tests Message-ID: <20080811230906.02F8139C107@scipy.org> Author: jarrod.millman Date: 2008-08-11 18:08:56 -0500 (Mon, 11 Aug 2008) New Revision: 4638 Removed: trunk/scipy/ndimage/_registration.py trunk/scipy/ndimage/_segmenter.py trunk/scipy/ndimage/src/register/ trunk/scipy/ndimage/src/segment/ trunk/scipy/ndimage/tests/test_registration.py trunk/scipy/ndimage/tests/test_segment.py Modified: trunk/scipy/ndimage/setup.py Log: removing segmentation and registration code since it isn't ready for release. Deleted: trunk/scipy/ndimage/_registration.py =================================================================== --- trunk/scipy/ndimage/_registration.py 2008-08-11 21:39:17 UTC (rev 4637) +++ trunk/scipy/ndimage/_registration.py 2008-08-11 23:08:56 UTC (rev 4638) @@ -1,1044 +0,0 @@ -# -# written by Tom Waite -# rigid body 3D registration -# - - -import math -import numpy as np -from scipy.special import erf -from scipy.ndimage import correlate1d -from scipy.optimize import fmin_powell, fmin_cg - -import scipy.ndimage._register as reg - -import time -import glob - -# Issue warning regarding heavy development status of this module -import warnings -_msg = "The registration code is under heavy development and therefore the \ -public API will change in the future. The NIPY group is actively working on \ -this code, and has every intention of generalizing this for the Scipy \ -community. Use this module minimally, if at all, until it this warning is \ -removed." -warnings.warn(_msg, UserWarning) - -# TODO: Add docstrings for public functions in extension code. -# Add docstrings to extension code. -#from numpy.lib import add_newdoc -#add_newdoc('scipy.ndimage._register', 'register_histogram', -# """A joint histogram used for registration module. -# """) - - -# -# ---- co-registration and IO ---- -# - -def resize_image(imageS, imageS_mat, imageR_mat): - """ - zoom_image = resize_image(imageS, imageS_mat, imageR_mat) - - Fractional resample source_image to reference_image size. The - resample is implemented with 3D cubic spline. The source - imageS_mat is the 4x4 voxel-to-physical conversion matrix. - - Parameters - ---------- - - imageS: {ndarray} - imageS is the source image to be resized. - - imageS_mat : {ndarray} - the 4x4 transform of the source image that maps voxel to physical. - - imageR_mat : {ndarray} - the 4x4 transform of the destination image that maps voxel to physical. - - Returns - ------- - zoom_image : {ndarray} - - Examples - -------- - - >>> import _registration as reg - >>> measures, image_anat, image_anat_mat, image_fmri_mat, fmri_series = reg.demo_MRI_coregistration() - - >>> resampled_fmri = reg.resize_image(fmri_series[10], image_fmri_mat, image_anat_mat) - - image 10 in the fmri_series is resampled from image_fmri_mat to image_anat coordinates - - """ - - # get the zoom - Z = imageS_mat.diagonal() / imageR_mat.diagonal() - - # new volume dimensions (rounded). D, imageS and Z are 3D and this is a vector element product - D = (imageS.shape * Z + 0.5).astype(np.int16) - - # for the test data, set the xyz voxel sizes for fMRI volume. M is a 4x4 matrix. - M = np.diag(imageS_mat.diagonal() / Z) - - image = np.zeros((D[2],D[1],D[0]),np.uint8) - - mode = 2 - scale = 0 - reg.register_volume_resample(imageS, image, Z, scale, mode) - - return image, M - -def remap_image(image, M_inverse, resample='linear'): - """ - remaped_image = remap_image(image, parm_vector, resample='linear') - - rotates and translates image using the 3 angles and 3 translations in the 6-dim - parm_vector. The mapping is stored in the 4x4 M_inverse matrix from the get_inverse_mapping - method. - - Parameters - ---------- - image : {ndarray} - image is the source image to be remapped. - - M_inverse : {ndarray} - M_inverse is the 4x4 inverse affine matrix - - resample : {'linear', 'cubic'}, optional - - - Returns - ------- - remaped_image : {ndarray} - - Examples - -------- - image = fmri_series[i] - x[0:6] = measures[i]['align_rotate'][0:6] - M = get_inverse_mappings(x) - # overwrite the fMRI volume with the aligned volume - fmri_series[i] = remap_image(image, M, resample='cubic') - - """ - - # allocate the zero image - remaped_image = np.zeros(image.shape, dtype=np.uint8) - - step = np.array([1, 1, 1], dtype=np.int32) - - if resample == 'linear': - # trilinear interpolation mapping. - reg.register_linear_resample(image, remaped_image, M_inverse, step) - elif resample == 'cubic': - # tricubic convolve interpolation mapping. - reg.register_cubic_resample(image, remaped_image, M_inverse, step) - - return remaped_image - - -def get_inverse_mappings(parm_vector): - """ - M_inverse = get_inverse_mappings(parm_vector) - - takes the 6-dimensional rotation/translation vector and builds the inverse - 4x4 mapping matrix M_inverse that will map imageG to imageF orientation - - Parameters - ---------- - parm_vector : {nd_array} - - Returns - ------- - M_inverse : {nd_array} - - Examples - -------- - - >>> import numpy as NP - >>> import _registration as reg - >>> array = np.zeros(6, dtype=float) - >>> M = reg.get_inverse_mappings(array) - >>> M - - array([ - [ 1., 0., 0., 0.], - [ 0., 1., 0., 0.], - [ 0., 0., 1., 0.], - [ 0., 0., 0., 1.]]) - - """ - # get the inverse mapping to rotate the G matrix to F space following registration - # -parm_vector is the inverse angles and translations - M_inverse = build_rotate_matrix(-parm_vector) - return M_inverse - -def register(image1, image1_mat, image2, image2_mat, multires=[4, 2], histo_fwhm=3, - ftype=1, lite=0, smhist=0, method='nmi', opt_method='hybrid', - optimize_function=None): - - """ - parm_vector = register(image1, image1_mat, image2, image2_mat, multires=[4, 2], histo_fwhm=3, - ftype=1, lite=0, smhist=0, method='nmi', opt_method='powell'): - - alignment of the two images (measured by mutual information or cross correlation) - using optimization search of 3 angle and 3 translation parameters. The optimization - uses either the Powell or Conjugate Gradient methods in the scipy optimization - package. The optimal rigid body parameter is returned. - - Parameters - ---------- - image1 : {nd_array} - image1 is the source image to be remapped during the registration. - image1_mat : {nd_array} - image1_mat is the source image MAT - image2 : {nd_array} - image2 is the reference image that image1 gets mapped to. - image2_mat : {nd_array} - image2_mat is the source image MAT - multires: {list}, optional - the volume subsample values for each pass of the registration. - the default is 2 passes with subsample 4 in pass 1 and subsample 2 in pass 2 - histo_fwhm : {int}, optional - used for the filter kernel in the low pass filter of the joint histogram - ftype : {0, 1}, optional - flag for type of low pass filter. 0 is Gauss-Spline - 1 is pure Gauss. Sigma determined from volume sampling info. - lite : {0, 1}, optional - lite of 1 is to jitter both images during resampling. 0 - is to not jitter. jittering is for non-aliased volumes. - smhist: {0, 1}, optional - flag for joint histogram low pass filtering. 0 for no filter, - 1 for do filter. - method: {'nmi', 'mi', 'ncc', 'ecc', 'mse'}, optional - flag for type of registration metric. nmi is normalized mutual - information; mi is mutual information; ecc is entropy cross - correlation; ncc is normalized cross correlation. mse is mean - squared error. - opt_method: {'powell', 'cg', 'hybrid'}, optional - registration is two pass. Pass 1 is low res to get close to alignment - and pass 2 starts at the pass 1 optimal alignment. In powell pass 1 and - 2 are powell, in hybrid pass 2 is conjugate gradient. - - - Returns - ------- - parm_vector : {nd_array} - this is the optimal alignment (6-dim) array with 3 angles and - 3 translations. - - Examples - -------- - - >>> import numpy as NP - >>> import _registration as reg - - >>> image1, image2, fwhm, improc = reg.demo_build_dual_volumes() - >>> parm_vector = register(image1, image2, fwhm, improc) - - """ - - # do the parameter validity checking. this is specific to this 3D registration. - # make sure the image is 3D and the mats are 4x4 with nonzero diagonal - - if image1.ndim != 3: - raise ValueError, "Image 1 is not 3 dimensional" - - if image2.ndim != 3: - raise ValueError, "Image 2 is not 3 dimensional" - - if image1.dtype != np.uint8: - raise ValueError, "Image 1 is not 8 bit (required for joint histogram)" - - if image2.dtype != np.uint8: - raise ValueError, "Image 2 is not 8 bit (required for joint histogram)" - - if image1_mat.shape != (4,4): - raise ValueError, "Image1 MAT is not 4x4" - - if image2_mat.shape != (4,4): - raise ValueError, "Image2 MAT is not 4x4" - - if (np.diag(image1_mat)).prod() == 0: - raise ValueError, "Image1 MAT has a 0 on the diagonal" - - if (np.diag(image2_mat)).prod() == 0: - raise ValueError, "Image2 MAT has a 0 on the diagonal" - - if opt_method=='hybrid' and np.size(multires) != 2: - raise ValueError, "hybrid method must be 2 pass registration" - - if ftype != 0 and ftype != 1: - raise ValueError, "choose filter type 0 or 1 only" - - if lite != 0 and lite != 1: - raise ValueError, "choose histogram generation type 0 or 1 only" - - if smhist != 0 and smhist != 1: - raise ValueError, "choose histogram smoothing type 0 or 1 only" - - if method != 'nmi' and method != 'mi' and method != 'ncc'\ - and method != 'ecc' and method != 'mse': - raise ValueError, "choose cost method nmi, mi, ecc, mse, ncc" - - if opt_method != 'powell' and opt_method != 'cg' and opt_method != 'hybrid': - raise ValueError, "only optimize methods powell, cg or hybrid are supported" - - # default is to use the cost_function I provided. - # this shows you can override this but the parameters will have to - # be changed for the new cost function if it is different - - if optimize_function == None: - optimize_function = cost_function - - parm_vector = multires_registration(optimize_function, image1, image1_mat, image2, image2_mat, - multires, histo_fwhm, lite, smhist, method, opt_method) - - return parm_vector - -def multires_registration(optimize_function, image1, image1_mat, image2, image2_mat, - multires, histo_fwhm, lite, smhist, method, opt_method): - - """ - - to be called by register() which does parameter validation - - Parameters - ---------- - image1 : {nd_array} - image1 is the source image to be remapped during the registration. - image1_mat : {nd_array} - image1_mat is the source image MAT - image2 : {nd_array} - image2 is the reference image that image1 gets mapped to. - image2_mat : {nd_array} - image2_mat is the source image MAT - multires: {list}, optional - the volume subsample values for each pass of the registration. - the default is 2 passes with subsample 4 in pass 1 and subsample 2 in pass 2 - histo_fwhm : {int}, optional - used for the filter kernel in the low pass filter of the joint histogram - ftype : {0, 1}, optional - flag for type of low pass filter. 0 is Gauss-Spline - 1 is pure Gauss. Sigma determined from volume sampling info. - lite : {0, 1}, optional - lite of 1 is to jitter both images during resampling. 0 - is to not jitter. jittering is for non-aliased volumes. - smhist: {0, 1}, optional - flag for joint histogram low pass filtering. 0 for no filter, - 1 for do filter. - method: {'nmi', 'mi', 'ncc', 'ecc', 'mse'}, optional - flag for type of registration metric. nmi is normalized mutual - information; mi is mutual information; ecc is entropy cross - correlation; ncc is normalized cross correlation. mse is mean - squared error. - opt_method: {'powell', 'cg', 'hybrid'}, optional - registration is two pass. Pass 1 is low res to get close to alignment - and pass 2 starts at the pass 1 optimal alignment. In powell pass 1 and - 2 are powell, in hybrid pass 2 is conjugate gradient. - - - Returns - ------- - parm_vector : {nd_array} - this is the optimal alignment (6-dim) array with 3 angles and - 3 translations. - - Examples - -------- - - (calling this from register which optionally filters image2) - >>> import numpy as NP - >>> import _registration as reg - >>> image1, mat1, image2, mat2 = reg.demo_build_dual_volumes() - >>> parm_vector = register(image1, image2, imdata) - - """ - ret_histo=0 - step = np.array([1, 1, 1], dtype=np.int32) - fwhm = np.zeros(2, dtype=np.int32) - # make the step a scalar to can put in a multi-res loop - loop = range(np.size(multires)) - # 6-D zero vector - x = np.zeros(6, dtype=np.float64); - # the kernel fwhm value for the x and y joint histogram filter - fwhm[:] = histo_fwhm - for i in loop: - # this is the volume subsample - step[:] = multires[i] - # optfunc_args is specific to the cost_function in this file - # this will need to change if you use another optimize_function. - optfunc_args = (image1, image1_mat, image2, image2_mat, step, histo_fwhm, - lite, smhist, method, ret_histo) - p_args = (optfunc_args,) - if opt_method=='powell': - print 'POWELL multi-res registration step size ', step - print 'vector ', x - x = fmin_powell(optimize_function, x, args=p_args, callback=callback_powell) - elif opt_method=='cg': - print 'CG multi-res registration step size ', step - print 'vector ', x - x = fmin_cg(optimize_function, x, args=p_args, callback=callback_cg) - elif opt_method=='hybrid': - if i==0: - print 'Hybrid POWELL multi-res registration step size ', step - print 'vector ', x - lite = 0 - optfunc_args = (image1, image1_mat, image2, image2_mat, step, histo_fwhm, - lite, smhist, method, ret_histo) - p_args = (optfunc_args,) - x = fmin_powell(optimize_function, x, args=p_args, callback=callback_powell) - elif i==1: - print 'Hybrid CG multi-res registration step size ', step - print 'vector ', x - lite = 1 - optfunc_args = (image1, image1_mat, image2, image2_mat, step, histo_fwhm, - lite, smhist, method, ret_histo) - p_args = (optfunc_args,) - x = fmin_cg(optimize_function, x, args=p_args, callback=callback_cg) - - return x - - -def callback_powell(x): - """ - called by optimize.powell only. prints current parameter vector. - """ - print 'Parameter Vector from Powell: - ' - print x - return - -def callback_cg(x): - """ - called by optimize.cg only. prints current parameter vector. - """ - print 'Parameter Vector from Conjugate Gradient: - ' - print x - return - -def smooth_kernel(fwhm, x, pixel_scale=8.0, ktype=1): - """ - kernel = smooth_kernel(fwhm, x, ktype=1) - - smooth_kernel creates filter kernel based on image sampling parameters. - provide domain of kernel and sampling parameters. - - Parameters - ---------- - fwhm : {int} - used for kernel width - x : {nd_array} - domain of kernel - ktype: {1, 2}, optional - kernel type. 1 is Gauss convoled with spline, 2 is Gauss - - - Returns - ------- - kernel : {nd_array} - - Examples - -------- - - >>> import numpy as NP - >>> import _registration as reg - >>> fwhm = 3 - >>> ftype = 2 - >>> p = np.ceil(2*fwhm).astype(int) - >>> x = np.array(range(-p, p+1)) - >>> kernel = reg.smooth_kernel(fwhm, x, ktype=ftype) - >>> kernel - - array([ - 4.77853772e-06, 1.41575516e-04, 2.26516955e-03, - 1.95718875e-02, 9.13238336e-02, 2.30120330e-01, - 3.13144850e-01, 2.30120330e-01, 9.13238336e-02, - 1.95718875e-02, 2.26516955e-03, 1.41575516e-04, - 4.77853772e-06]) - - """ - eps = 0.00001 - s = np.square((fwhm/math.sqrt(pixel_scale*math.log(2.0)))) + eps - if ktype==1: - # from SPM: Gauss kernel convolved with 1st degree B spline - w1 = 0.5 * math.sqrt(2.0/s) - w2 = -0.5 / s - w3 = math.sqrt((s*math.pi) /2.0) - kernel = 0.5*(erf(w1*(x+1))*(x+1) + erf(w1*(x-1))*(x-1) - - 2.0*erf(w1*(x))*(x) + w3*(np.exp(w2*np.square(x+1))) - + np.exp(w2*(np.square(x-1))) - - 2.0*np.exp(w2*np.square(x))) - kernel[kernel<0] = 0 - kernel = kernel / kernel.sum() - else: - # Gauss kernel - kernel = (1.0/math.sqrt(2.0*math.pi*s)) * np.exp(-np.square(x)/(2.0*s)) - kernel = kernel / kernel.sum() - - return kernel - -def filter_image_3D(imageRaw, fwhm, ftype=2, give_2D=0): - """ - image_F_xyz = filter_image_3D(imageRaw, fwhm, ftype=2): - does 3D separable digital filtering using scipy.ndimage.correlate1d - - Parameters - ---------- - imageRaw : {nd_array} - the unfiltered 3D volume image - fwhm : {int} - used for kernel width. this is 3 elements (one for each dimension) - ktype: {1, 2}, optional - kernel type. 1 is Gauss convoled with spline (SPM), 2 is Gauss - - Returns - ------- - image_F_xyz : {nd_array} - 3D filtered volume image - - Examples - -------- - - >>> import _registration as reg - >>> image1, image2, imdata = reg.demo_build_dual_volumes() - >>> ftype = 1 - >>> image_Filter_xyz = filter_image_3D(image, fwhm, ftype) - >>> image1['data'] = image_Filter_xyz - """ - - p = np.ceil(2*fwhm).astype(int) - x = np.array(range(-p[0], p[0]+1)) - kernel_x = smooth_kernel(fwhm[0], x, ktype=ftype) - - x = np.array(range(-p[1], p[1]+1)) - kernel_y = smooth_kernel(fwhm[1], x, ktype=ftype) - - x = np.array(range(-p[2], p[2]+1)) - kernel_z = smooth_kernel(fwhm[2], x, ktype=ftype) - - output=None - # 3D filter in 3 1D separable stages. keep the image - # names at each stage separate in case you need them - # for example may need an image that is 2D slice filtered only - axis = 0 - image_F_x = correlate1d(imageRaw, kernel_x, axis, output) - axis = 1 - image_F_xy = correlate1d(image_F_x, kernel_y, axis, output) - axis = 2 - image_F_xyz = correlate1d(image_F_xy, kernel_z, axis, output) - - if give_2D==0: - return image_F_xyz - else: - return image_F_xyz, image_F_xy - - -def build_fwhm(M, S): - """ - fwhm = build_fwhm(M, S) - - builds the low pass filter kernel sigma value from the image pixel sampling - - Parameters - ---------- - M : {nd_array} - input 4x4 voxel to physical map matrix (called 'MAT') - - S : {nd_array} - 1x3 sample increment array. should be = (1, 1, 1) - - Returns - ------- - fwhm : {nd_array} - the 3D Gaussian kernel width - - Examples - -------- - - >>> import numpy as NP - >>> import _registration as reg - >>> anat_desc = reg.load_anatMRI_desc() - >>> image1 = reg.load_volume(anat_desc, imagename='ANAT1_V0001.img') - >>> image1['fwhm'] = reg.build_fwhm(image1['mat'], imdata['step']) - - """ - # M contains the voxel to physical mapping - view_3x3 = np.square(M[0:3, 0:3]) - # sum the elements in the first row - vxg = np.sqrt(view_3x3.sum(axis=1)) - # assumes that voxel sampling is the same for xyz as S is the step - size = np.array([1,1,1])*S[0] - x = np.square(size) - np.square(vxg) - # clip - x[x<0] = 0 - fwhm = np.sqrt(x) / vxg - # pathology when stepsize = 1 for MAT equal to the identity matrix - fwhm[fwhm==0] = 1 - # return the 3D Gaussian kernel width (xyz) - return fwhm - -def cost_function(x, optfunc_args): - """ - cost = cost_function(x, optfunc_args) --- OR --- - cost, joint_histogram = cost_function(x, optfunc_args) - - computes the alignment between 2 volumes using cross correlation or mutual - information metrics. In both the 8 bit joint histogram of the 2 images is - computed. The 8 bit scaling is done using an integrated histogram method and - is called prior to this. - - Parameters - ---------- - x : {nd_array} - this is the current (6-dim) array with 3 angles and 3 translations. - - optfunc_args : {tuple} - this is a tuple of 8 elements that is formed in the scipy.optimize powell - and cg (conjugate gradient) functions. this is why the elements need to be - a tuple. The elements of optfunc_args are: - - image_F : {dictionary} - image_F is the source image to be remapped during the registration. - it is a dictionary with the data as an ndarray in the ['data'] component. - image_G : {dictionary} - image_G is the reference image that image_F gets mapped to. - sample_vector : {nd_array} - sample in x,y,x. should be (1,1,1) - fwhm : {nd_array} - Gaussian sigma - do_lite : {0, 1} - lite of 1 is to jitter both images during resampling. - 0 is to not jitter. jittering is for non-aliased volumes. - smooth : {0, 1} - flag for joint histogram low pass filtering. 0 for no filter, - 1 for do filter. - method : {'nmi', 'mi', 'ncc', 'ecc', 'mse'} - flag for type of registration metric. nmi is normalized mutual - information; mi is mutual information; ecc is entropy cross - correlation; ncc is normalized cross correlation. mse is mean - square error. with mse there is no joint histogram. - ret_histo : {0, 1} - if 0 return is: cost - if 0 return is: cost, joint_histogram - - Returns - ------- - cost : {float} - the negative of one of the mutual information metrics - or negative cross correlation. use negative as the optimization - is minimization. - - --- OR --- (if ret_histo = 1) - - cost : {float} - the negative of one of the mutual information metrics - or negative cross correlation. use negative as the optimization - is minimization. - - joint_histogram : {nd_array} - the 2D (256x256) joint histogram of the two volumes - - - Examples - -------- - - >>> import numpy as NP - >>> import _registration as reg - >>> anat_desc = reg.load_anatMRI_desc() - >>> image1 = reg.load_volume(anat_desc, imagename='ANAT1_V0001.img') - >>> image2 = reg.load_volume(anat_desc, imagename='ANAT1_V0001.img') - >>> image1['fwhm'] = reg.build_fwhm(image1['mat'], imdata['step']) - >>> image2['fwhm'] = reg.build_fwhm(image2['mat'], imdata['step']) - >>> method = 'ncc' - >>> lite = 1 - >>> smhist = 0 - >>> ret_histo = 1 - >>> optfunc_args = (image1, image2, imdata['step'], imdata['fwhm'], lite, smhist, method, ret_histo) - >>> x = np.zeros(6, dtype=np.float64) - >>> return cost, joint_histogram = reg.cost_function(x, optfunc_args) - - - """ - - image_F = optfunc_args[0] - image_F_mat = optfunc_args[1] - image_G = optfunc_args[2] - image_G_mat = optfunc_args[3] - sample_vector = optfunc_args[4] - fwhm = optfunc_args[5] - do_lite = optfunc_args[6] - smooth = optfunc_args[7] - method = optfunc_args[8] - ret_histo = optfunc_args[9] - - rot_matrix = build_rotate_matrix(x) - cost = 0.0 - epsilon = 2.2e-16 - # image_G is base image - # image_F is the to-be-rotated image - # rot_matrix is the 4x4 constructed (rigid body) transform matrix - # sample_vector is the subsample vector for x-y-z - - F_inv = np.linalg.inv(image_F_mat) - composite = np.dot(F_inv, image_G_mat) - composite = np.dot(composite, rot_matrix) - - if method == 'mse': - # - # mean squard error method - # - - # allocate the zero image - #(layers, rows, cols) = image_F.shape - remap_image_F = np.zeros(image_F.shape, dtype=np.uint8) - # trilinear interpolation mapping. - reg.register_linear_resample(image_F, remap_image_F, composite, sample_vector) - cost = (np.square(image_G-remap_image_F)).mean() - # cost is min when G and F are aligned so keep cost positive - - return cost - - else: - # - # histogram-based methods (nmi, ncc, mi, ecc) - # - - # allocate memory for 2D histogram - joint_histogram = np.zeros([256, 256], dtype=np.float64) - - if do_lite: - reg.register_histogram_lite(image_F, image_G, composite, sample_vector, joint_histogram) - else: - reg.register_histogram(image_F, image_G, composite, sample_vector, joint_histogram) - - # smooth the histogram - if smooth: - p = np.ceil(2*fwhm).astype(int) - x = np.array(range(-p, p+1)) - hkernel = smooth_kernel(fwhm, x) - output=None - # 2D filter in 1D separable stages using the same kernel. SPM - # has options for a 2D fwhm kernel yet only uses 1 element - axis = 0 - joint_histogram = correlate1d(joint_histogram, hkernel, axis, output) - axis = 1 - joint_histogram = correlate1d(joint_histogram, hkernel, axis, output) - - joint_histogram += epsilon # prevent log(0) - # normalize the joint histogram - joint_histogram /= joint_histogram.sum() - # get the marginals - marginal_col = joint_histogram.sum(axis=0) - marginal_row = joint_histogram.sum(axis=1) - - if method == 'mi': - # mutual information - marginal_outer = np.outer(marginal_col, marginal_row) - H = joint_histogram * np.log(joint_histogram / marginal_outer) - mutual_information = H.sum() - cost = -mutual_information - - elif method == 'ecc': - # entropy correlation coefficient - marginal_outer = np.outer(marginal_col, marginal_row) - H = joint_histogram * np.log(joint_histogram / marginal_outer) - mutual_information = H.sum() - row_entropy = marginal_row * np.log(marginal_row) - col_entropy = marginal_col * np.log(marginal_col) - ecc = -2.0*mutual_information/(row_entropy.sum() + col_entropy.sum()) - cost = -ecc - - elif method == 'nmi': - # normalized mutual information - row_entropy = marginal_row * np.log(marginal_row) - col_entropy = marginal_col * np.log(marginal_col) - H = joint_histogram * np.log(joint_histogram) - nmi = (row_entropy.sum() + col_entropy.sum()) / (H.sum()) - cost = -nmi - - elif method == 'ncc': - # cross correlation from the joint histogram - r, c = joint_histogram.shape - i = np.array(range(1,c+1)) - j = np.array(range(1,r+1)) - m1 = (marginal_row * i).sum() - m2 = (marginal_col * j).sum() - sig1 = np.sqrt((marginal_row*(np.square(i-m1))).sum()) - sig2 = np.sqrt((marginal_col*(np.square(j-m2))).sum()) - [a, b] = np.mgrid[1:c+1, 1:r+1] - a = a - m1 - b = b - m2 - # element multiplies in the joint histogram and grids - H = ((joint_histogram * a) * b).sum() - ncc = H / (np.dot(sig1, sig2)) - cost = -ncc - - if ret_histo: - return cost, joint_histogram - else: - return cost - - -def build_rotate_matrix(img_data_parms): - """ - rot_matrix = reg.build_rotate_matrix(img_data_parms) - - takes the 6 element vector (3 angles, 3 translations) and build the 4x4 mapping matrix - - Parameters - ---------- - img_data_parms : {nd_array} - this is the current (6-dim) array with 3 angles and 3 translations. - - Returns - ------- - rot_matrix: {nd_array} - the 4x4 mapping matrix - - Examples - -------- - - >>> import numpy as NP - >>> import _registration as reg - >>> x = np.zeros(6, dtype=np.float64) - >>> M = reg.build_rotate_matrix(x) - >>> M - array([[ 1., 0., 0., 0.], - [ 0., 1., 0., 0.], - [ 0., 0., 1., 0.], - [ 0., 0., 0., 1.]]) - - - """ - - R1 = np.zeros([4,4], dtype=np.float64); - R2 = np.zeros([4,4], dtype=np.float64); - R3 = np.zeros([4,4], dtype=np.float64); - T = np.eye(4, dtype=np.float64); - - alpha = math.radians(img_data_parms[0]) - beta = math.radians(img_data_parms[1]) - gamma = math.radians(img_data_parms[2]) - - R1[0][0] = 1.0 - R1[1][1] = math.cos(alpha) - R1[1][2] = math.sin(alpha) - R1[2][1] = -math.sin(alpha) - R1[2][2] = math.cos(alpha) - R1[3][3] = 1.0 - - R2[0][0] = math.cos(beta) - R2[0][2] = math.sin(beta) - R2[1][1] = 1.0 - R2[2][0] = -math.sin(beta) - R2[2][2] = math.cos(beta) - R2[3][3] = 1.0 - - R3[0][0] = math.cos(gamma) - R3[0][1] = math.sin(gamma) - R3[1][0] = -math.sin(gamma) - R3[1][1] = math.cos(gamma) - R3[2][2] = 1.0 - R3[3][3] = 1.0 - - T[0][0] = 1.0 - T[1][1] = 1.0 - T[2][2] = 1.0 - T[3][3] = 1.0 - T[0][3] = img_data_parms[3] - T[1][3] = img_data_parms[4] - T[2][3] = img_data_parms[5] - - rot_matrix = np.dot(T, R1); - rot_matrix = np.dot(rot_matrix, R2); - rot_matrix = np.dot(rot_matrix, R3); - - return rot_matrix - - -def build_gauss_volume(imagedesc, S=[1500.0, 2500.0, 1000.0]): - - """ - build a 3D Gaussian volume. user passes in image dims in imagedesc - the sigma for each axis is S[3] where 0=z, 1=y, 2=x - - volume3D = build_test_volume(imagedesc, S) - - Parameters - ---------- - imagedesc : {dictionary} - volume dimensions and sampling - - S : {tuple} - the Gaussian sigma for Z, Y and X - - Returns - ------- - - volume3D : {nd_array} - the 3D volume for testing - - """ - layers = imagedesc['layers'] - rows = imagedesc['rows'] - cols = imagedesc['cols'] - - L = layers/2 - R = rows/2 - C = cols/2 - - # build coordinates for 3D Gaussian volume - # coordinates are centered at (0, 0, 0) - [a, b, c] = np.mgrid[-L:L, -R:R, -C:C] - - sigma = np.array([S[0], S[1], S[2]]) - aa = (np.square(a))/sigma[0] - bb = (np.square(b))/sigma[1] - cc = (np.square(c))/sigma[2] - volume3D = (255.0*np.exp(-(aa + bb + cc))).astype(np.uint8) - - return volume3D - - -def scale_image(image, max_amp=255, image_type=np.uint8, threshold=0.999, fetch_ih=0): - - """ - scale and threshold clip the volume using the integrated histogram - to set the high threshold - - Parameters - ---------- - image : {nd_array} - raw unscaled volume - - max_amp : int (default 255) - the maximum value of the scaled image - - image_type : nd_array dtype (default uint8) - the type of the volume to return. - - threshold : float (default 0.999) - the value of the normalized integrated histogram - that when reached sets the high threshold index - - Returns - ------- - image : {nd_array} - the scaled volume - ih : {nd_array} - the integrated histogram. can be used for image display - purpose (histogram equalization) - - """ - - max = image.max() - min = image.min() - if max == 0 and min == 0: - raise ValueError, "Zero image. cannot be scaled" - - # need range of pixels for the number of bins - h, edges = np.histogram(image, bins=(max-min)) - ih = (np.cumsum(h)).astype(np.float64) - # normalize the integrated histogram - ih = ih / ih.max() - indices = np.where(ih >= threshold) - # wind up getting all the indices where the ih >= threshold - # and only need the first index. tuple has one nd_array and - # get the 0 element from it ([0][0]) - index = indices[0][0] - scale = float(max_amp) / (index-min) - image = (scale*(image.astype(np.float)-min)) - image[image>max_amp] = max_amp - # down type. usually will go from float to 8 bit (needed for the 8 bit joint histogram) - image = image.astype(image_type) - - if fetch_ih == 1: - return image, ih - else: - return image - - -def check_alignment(image1, image1_mat, image2, image2_mat, histo_fwhm=3, method='ncc', lite=0, - smhist=0, alpha=0.0, beta=0.0, gamma=0.0, Tx=0, Ty=0, Tz=0, ret_histo=0): - - """ - test the cost function and (optional) view the joint histogram. can be used - during intra-modal registration to measure the current alignment (return - the cross correlation). would measure before and after registration - - - - """ - - # do the parameter validity checking. this is specific to this 3D registration. - # make sure the image is 3D and the mats are 4x4 with nonzero diagonal - - if image1.ndim != 3: - raise ValueError, "Image 1 is not 3 dimensional" - - if image2.ndim != 3: - raise ValueError, "Image 2 is not 3 dimensional" - - if image1.dtype != np.uint8: - raise ValueError, "Image 1 is not 8 bit (required for joint histogram)" - - if image2.dtype != np.uint8: - raise ValueError, "Image 2 is not 8 bit (required for joint histogram)" - - if image1_mat.shape != (4,4): - raise ValueError, "Image1 MAT is not 4x4" - - if image2_mat.shape != (4,4): - raise ValueError, "Image2 MAT is not 4x4" - - if (np.diag(image1_mat)).prod() == 0: - raise ValueError, "Image1 MAT has a 0 on the diagonal" - - if (np.diag(image2_mat)).prod() == 0: - raise ValueError, "Image2 MAT has a 0 on the diagonal" - - if method != 'nmi' and method != 'mi' and method != 'ncc'\ - and method != 'ecc' and method != 'mse': - raise ValueError, "choose cost method nmi, mi, ecc, mse, ncc" - - P = np.zeros(6, dtype=np.float64); - P[0] = alpha - P[1] = beta - P[2] = gamma - P[3] = Tx - P[4] = Ty - P[5] = Tz - - step = np.array([1, 1, 1], dtype=np.int32) - optfunc_args = (image1, image1_mat, image2, image2_mat, step, histo_fwhm, lite, - smhist, method, ret_histo) - - if ret_histo: - cost, joint_histogram = cost_function(P, optfunc_args) - return cost, joint_histogram - else: - cost = cost_function(P, optfunc_args) - return cost - - - -def build_scale_volume(image, mat, scale): - # - # rescale the 'mat' (voxel to physical mapping matrix) - # - M = mat * scale - (layers, rows, cols) = image.shape - # dimensions - D = np.zeros(3, dtype=np.int32); - Z = np.zeros(3, dtype=np.float64); - D[0] = rows/scale - D[1] = cols/scale - D[2] = layers/scale - image2 = np.zeros([D[2], D[0], D[1]], dtype=np.uint8) - mode = 1; - reg.register_volume_resample(image, image2, Z, scale, mode) - return image2, M - - - - Deleted: trunk/scipy/ndimage/_segmenter.py =================================================================== --- trunk/scipy/ndimage/_segmenter.py 2008-08-11 21:39:17 UTC (rev 4637) +++ trunk/scipy/ndimage/_segmenter.py 2008-08-11 23:08:56 UTC (rev 4638) @@ -1,1718 +0,0 @@ -import math -import numpy as NP -import scipy.ndimage._segment as S - -_objstruct = NP.dtype([('Left', 'i'), - ('Right', 'i'), - ('Top', 'i'), - ('Bottom', 'i'), - ('Front', 'i'), - ('Back', 'i'), - ('Label', 'i'), - ('Mass', 'i'), - ('cX', 'f'), - ('cY', 'f'), - ('cZ', 'f'), - ('voxelMean', 'f'), - ('voxelVar', 'f'), - ('COM', 'f', 6), - ('TEM', 'f', 21)] - ) - - -# Issue warning regarding heavy development status of this module -import warnings -_msg = "The segmentation code is under heavy development and therefore the \ -public API will change in the future. The NIPY group is actively working on \ -this code, and has every intention of generalizing this for the Scipy \ -community. Use this module minimally, if at all, until it this warning is \ -removed." -warnings.warn(_msg, UserWarning) - -def canny_hysteresis(magnitude, canny_stats): - """ - edge_image = canny_hysteresis(magnitude, canny_stats) - - hystereis stage of Canny filter - - Parameters - ---------- - - magnitude : {nd_array} - the output from the canny_nonmax_supress() method - - canny_stats : {dictionary} - contains the low and high thesholds determined from canny_nonmax_supress() - - Returns - ---------- - edge_image : {nd_array} - the labeled edge image that can be displayed and used for later processing - - """ - [rows, cols] = magnitude.shape - edge_image = NP.zeros(rows*cols, dtype=NP.int16).reshape(rows, cols) - S.canny_hysteresis(magnitude, edge_image, canny_stats['low'], canny_stats['high']) - - return edge_image - -def canny_nonmax_supress(horz_DGFilter, vert_DGFilter, img_means, thres=0.5, - mode=1, canny_l=0.5, canny_h=0.8): - """ - magnitude, canny_stats = canny_nonmax_supress(horz_DGFilter, vert_DGFilter, img_means, - thres=0.5, mode=1, canny_l=0.5, canny_h=0.8) - - non-max supression stage of Canny filter - - Parameters - ---------- - - horz_DGFilter : {nd_array} - the horizonal filtered image using the derivative of Gaussian kernel filter. - this is the output of the canny_filter method - - vert_DGFilter : {nd_array} - the vertical filtered image using the derivative of Gaussian kernel filter. - this is the output of the canny_filter method - - img_means : {dictionary} - mean X and Y values of edge signals determined from canny_filter - - thres : {float}, optional - edge threshold applied to x and y filtered means - - mode : {0, 1}, optional - threshold based on histogram mean(0) or mode(1) - - canny_low : {float}, optional - low threshold applied to magnitude filtered - - canny_high : {float}, optional - high threshold applied to magnitude filtered - - Returns - ---------- - - magnitude : {nd_array} - magnitude of X and Y filtered for critical samples - - canny_stats : {dictionary} - mean, low and high to be used for hysteresis - - """ - [rows, cols] = horz_DGFilter.shape - magnitude = NP.zeros(rows*cols, dtype=NP.float64).reshape(rows, cols) - aveMag, canny_low, canny_high = S.canny_nonmax_supress(horz_DGFilter, vert_DGFilter, - magnitude, mode, img_means['x-dg']*thres, - img_means['y-dg']*thres, canny_l, canny_h) - - canny_stats = {'mean' : aveMag, 'low' : canny_low, 'high' : canny_high} - - return magnitude, canny_stats - -def canny_filter(slice, dg_kernel): - """ - horz_DGFilter, vert_DGFilter, img_means = canny_filter(slice, dg_kernel) - - Canny derivative of Gaussian filter - returns the X and Y filterd image - - Parameters - ---------- - - slice : {nd_array} - 2D image array - - dg_kernel : {dictionary} - derivative of Gaussian kernel from build_d_gauss_kernel() - - Returns - ---------- - - horz_DGFilter : {nd_array} - X filtered image - - vert_DGFilter : {nd_array} - Y filtered image - - img_means : {dictionary} - - - """ - slice = slice.astype(NP.float64) - [rows, cols] = slice.shape - horz_DGFilter = NP.zeros(rows*cols, dtype=NP.float64).reshape(rows, cols) - vert_DGFilter = NP.zeros(rows*cols, dtype=NP.float64).reshape(rows, cols) - aveX, aveY = S.canny_filter(slice, horz_DGFilter, vert_DGFilter, - dg_kernel['coefficients'], dg_kernel['kernelSize']) - - img_means = {'x-dg' : aveX, 'y-dg' : aveY} - - return horz_DGFilter, vert_DGFilter, img_means - - -def binary_edge(label_image, ROI): - """ - binary_edge_image = binary_edge(label_image, ROI) - - takes the ROI dictionary with the blob bounding boxes and generates - the binary edge for each blob. The ROI mask is used to isolate - the binary edges for later use (e.g. contour tracing). - - Parameters - ---------- - - label_image : {nd_array} - an image with labeled regions from get_blobs() method - - ROI : {dictionary} - Region of Interest structure that has blob bounding boxes - - Returns - ---------- - - binary_edge_image : {nd_array} - edge image for each ROI combined into a single image - - """ - - [rows, cols] = label_image.shape - binary_edge_image = NP.zeros(rows*cols, dtype=NP.uint16).reshape(rows, cols) - number_regions = ROI.size - indices = range(0, number_regions) - for i in indices: - left = ROI[i]['Left']-2 - right = ROI[i]['Right']+2 - bottom = ROI[i]['Bottom']-2 - top = ROI[i]['Top']+2 - Label = ROI[i]['Label'] - if left < 0: - left = 0 - if bottom < 0: - bottom = 0 - if right > cols-1: - right = cols-1 - if top > rows-1: - top = rows-1 - - roi_rows = top-bottom - roi_cols = right-left - label_region = NP.zeros(roi_rows*roi_cols, dtype=NP.uint16).reshape(roi_rows, roi_cols) - input = NP.zeros(roi_rows*roi_cols, dtype=NP.uint16).reshape(roi_rows, roi_cols) - # load the labeled region - label_region[0:roi_rows, 0:roi_cols][label_image[bottom:top, left:right]==Label] = 1 - S.binary_edge(label_region, input) - input[0:roi_rows,0:roi_cols][input[0:roi_rows,0:roi_cols]==1] = Label - binary_edge_image[bottom:top,left:right] = binary_edge_image[bottom:top,left:right] + \ - input[0:roi_rows,0:roi_cols] - - return binary_edge_image - - -def roi_co_occurence(label_image, raw_image, ROI, distance=2, orientation=90, verbose=0): - """ - roi_co_occurence(label_image, raw_image, ROI, distance=2, orientation=90, verbose=0) - - - OR - - - texture_arrays = roi_co_occurence(label_image, raw_image, ROI, distance=2, verbose=1) - - (N-S, E-W, NW-SE, NE-SW) computes one of 4 directional co-occurence matrices and features. - In debug=1 will return the 4 joint histograms for each ROI. This is used to compute texture - features for a pre-segmented region. The seg_co_occurence() method will be used for texture- - based segmentation. - - Parameters - ---------- - - label_image : {nd_array} - an image with labeled regions from get_blobs() method - - raw_image : {nd_array} - raw image from which texture features get extracted - - distance : {int} - integer value of pixel offset in forming joint histogram. default value 2 - - orientation : {45, 90, 135, 180} - direction for pixel offet. - - ROI : {dictionary} - Region of Interest structure that has blob bounding boxes. The largest - 2D target bounding box is extracted. - - - Returns - ---------- - - co_occurence_images : {dictionary} - contains 4 joint histogram images for each ROI - returned if verbose=1 - - """ - - if orientation != 45 and orientation != 90 and orientation != 135 and orientation != 180: - orientation = 90 - - epsilon = 2.2e-16 - num_bits = 256 - copy_image = raw_image.copy() - number_regions = ROI.size - indices = range(0, number_regions) - co_occurence_image_list = {} - for i in indices: - left = ROI[i]['Left'] - right = ROI[i]['Right'] - bottom = ROI[i]['Bottom'] - top = ROI[i]['Top'] - Label = ROI[i]['Label'] - rows = top-bottom - cols = right-left - # copy the mask to section image - section = NP.zeros(rows*cols, dtype=label_image.dtype).reshape(rows, cols) - section[0:rows, 0:cols][label_image[bottom:top, left:right]==Label] = 1 - source_region = NP.zeros(rows*cols, dtype=NP.float64).reshape(rows, cols) - cocm_block = NP.zeros(num_bits*num_bits, dtype=NP.int32).reshape(num_bits, num_bits) - source_region[0:rows, 0:cols] = copy_image[bottom:top, left:right] - # scale segment to 8 bits. this needs to be smarter (e.g. use integrated histogram method) - max_value = source_region.max() - min_value = source_region.min() - scale = 255.0 / (max_value-min_value) - image_roi = (scale*(source_region-min_value)).astype(NP.int16) - # image_roi is short type - S.roi_co_occurence(section, image_roi, cocm_block, distance, orientation) - co_occurence_image_list[i] = cocm_block - # normalize the joint histogram prior to feature extraction - joint_histogram = cocm_block.astype(NP.float64) - joint_histogram = joint_histogram / joint_histogram.sum() - # to prevent log(0) - joint_histogram += epsilon - # compute the com features - energy = joint_histogram.std() - H = joint_histogram * NP.log(joint_histogram) - entropy = H.sum() - r, c = joint_histogram.shape - [a, b] = NP.mgrid[1:c+1, 1:r+1] - contrast = ((NP.square(a-b))*joint_histogram).sum() - d = 1.0 + NP.abs(a-b) - homogeneity = (joint_histogram / d).sum() - ROI[i]['COM'][0] = distance - ROI[i]['COM'][1] = orientation - ROI[i]['COM'][2] = energy - ROI[i]['COM'][3] = entropy - ROI[i]['COM'][4] = contrast - ROI[i]['COM'][5] = homogeneity - - if verbose == 1: - return co_occurence_image_list - else: - return - - - -def region_grow(label_image, raw_image, ROI, roi_index, roi_inflate, - low_thresh=0.5, high_thresh=1.5, N_connectivity=3, debug=0): - """ - region_grow(label_image, raw_image, ROI, roi_index, roi_inflate, stop_thresh) - - starting from a seed (masks or regions in the label_image) grow the regions based - on (1) connectivity (2D or 3D) and (2) raw voxel values > stop threshold criterion. - - Parameters - ---------- - - label_image : {nd_array} - an image with labeled regions from get_blobs() method - - raw_image : {nd_array} - raw image from which texture features get extracted - - ROI : {dictionary} - Region of Interest structure that has blob bounding boxes. The largest - 2D target bounding box is extracted. - - roi_index : {int} - the single ROI element to apply region growing to. - - roi_inflate : {list} - the maximum increase in the ROI bounding box. For 3D the tuple is [layers, rows, cols] - and for 2D it is [rows, cols]. - - low_thresh : {float} - this is the percent of the voxel mean that the growing region must be GREATER than. - region growing terminates when the raw_image is BELOW this value. - - high_thresh : {float} - this is the percent of the voxel mean that the growing region must be LESS than. - region growing terminates when the raw_image is ABOVE this value. - - N_connectivity : {int} - for growing this indicates how connected in a 3x3 or 3x3x3 window the un-labeled - sample is. Make less than full connected for growing boundaries - - Returns - ---------- - - label : {nd_array} - the label image with the selected ROI after region growing. only returned - in debug mode. - - """ - - _c_ext_struct = NP.dtype([('Left', 'i'), - ('Right', 'i'), - ('Top', 'i'), - ('Bottom', 'i'), - ('Front', 'i'), - ('Back', 'i'), - ('Label', 'i'), - ('Mass', 'i'), - ('cX', 'f'), - ('cY', 'f'), - ('cZ', 'f')] - ) - - expanded_ROI = NP.zeros(1, dtype=_c_ext_struct) - - dimensions = label_image.ndim - - if dimensions == 3: - z_ext = roi_inflate[0] - y_ext = roi_inflate[1] - x_ext = roi_inflate[2] - [layers, rows, cols] = label_image.shape - else: - y_ext = roi_inflate[0] - x_ext = roi_inflate[1] - [rows, cols] = label_image.shape - - if dimensions == 2: - left = ROI[roi_index]['Left']-x_ext - right = ROI[roi_index]['Right']+x_ext - bottom = ROI[roi_index]['Bottom']-y_ext - top = ROI[roi_index]['Top']+y_ext - Label = ROI[roi_index]['Label'] - lcutoff = low_thresh * ROI[roi_index]['voxelMean'] - hcutoff = high_thresh * ROI[roi_index]['voxelMean'] - if left < 0: - left = 0 - if bottom < 0: - bottom = 0 - if right > cols-1: - right = cols-1 - if top > rows-1: - top = rows-1 - expanded_ROI['Left'] = left - expanded_ROI['Right'] = right - expanded_ROI['Top'] = top - expanded_ROI['Bottom'] = bottom - expanded_ROI['Label'] = Label - rows = top-bottom - cols = right-left - label = NP.zeros(rows*cols, dtype=NP.int16).reshape(rows, cols) - section = NP.zeros(rows*cols, dtype=NP.float64).reshape(rows, cols) - label = label_image[bottom:top, left:right].copy() - section = (raw_image[bottom:top, left:right].astype(NP.float64)).copy() - elif dimensions == 3: - left = ROI[roi_index]['Left']-x_ext - right = ROI[roi_index]['Right']+x_ext - bottom = ROI[roi_index]['Bottom']-y_ext - top = ROI[roi_index]['Top']+y_ext - front = ROI[roi_index]['Front']-z_ext - back = ROI[roi_index]['Back']+z_ext - Label = ROI[roi_index]['Label'] - lcutoff = low_thresh * ROI[roi_index]['voxelMean'] - hcutoff = high_thresh * ROI[roi_index]['voxelMean'] - if left < 0: - left = 0 - if bottom < 0: - bottom = 0 - if right > cols-1: - right = cols-1 - if top > rows-1: - top = rows-1 - if front < 0: - front = 0 - if back > layers-1: - back = layers-1 - expanded_ROI['Left'] = left - expanded_ROI['Right'] = right - expanded_ROI['Top'] = top - expanded_ROI['Bottom'] = bottom - expanded_ROI['Back'] = back - expanded_ROI['Front'] = front - expanded_ROI['Label'] = Label - rows = top-bottom - cols = right-left - layers = back-front - label = NP.zeros(layers*rows*cols, dtype=NP.int16).reshape(layers, rows, cols) - label = label_image[front:back, bottom:top, left:right].copy() - section = NP.zeros(layers*rows*cols, dtype=NP.float64).reshape(layers, rows, cols) - section = (raw_image[front:back, bottom:top, left:right].astype(NP.float64)).copy() - - # - # this newgrow_ROI gets filled in and the label image is grown - # - - newgrow_ROI = NP.zeros(1, dtype=_c_ext_struct) - S.region_grow(section, label, expanded_ROI, newgrow_ROI, lcutoff, hcutoff, Label, N_connectivity) - - if debug==1: - # - # do not update ROI for index and the label_image - # - return label - - else: - # - # update (overwrite) ROI for index and the label_image - # - if dimensions == 2: - ROI[roi_index]['Left'] = newgrow_ROI['Left'] - ROI[roi_index]['Right'] = newgrow_ROI['Right'] - ROI[roi_index]['Top'] = newgrow_ROI['Top'] - ROI[roi_index]['Bottom'] = newgrow_ROI['Bottom'] - left = ROI[roi_index]['Left'] - right = ROI[roi_index]['Right'] - top = ROI[roi_index]['Top'] - bottom = ROI[roi_index]['Bottom'] - rows = top-bottom - cols = right-left - label_image[bottom:top,left:right] = label[0:rows,0:cols] - elif dimensions == 3: - ROI[roi_index]['Left'] = newgrow_ROI['Left'] - ROI[roi_index]['Right'] = newgrow_ROI['Right'] - ROI[roi_index]['Top'] = newgrow_ROI['Top'] - ROI[roi_index]['Bottom'] = newgrow_ROI['Bottom'] - ROI[roi_index]['Front'] = newgrow_ROI['Front'] - ROI[roi_index]['Back'] = newgrow_ROI['Back'] - left = expanded_ROI['Left'] - right = expanded_ROI['Right'] - top = expanded_ROI['Top'] - bottom = expanded_ROI['Bottom'] - front = expanded_ROI['Front'] - back = expanded_ROI['Back'] - rows = top-bottom - cols = right-left - layers = back-front - label_image[front:back,bottom:top,left:right] = label[0:layers,0:rows,0:cols] - - return - - - -def seg_co_occurence(raw_image, window=16, distance=2, orientation=90): - """ - cocm_images = seg_co_occurence(raw_image, window=16, distance=2, orientation=90) - - (N-S, E-W, NW-SE, NE-SW) computes one of 4 directional co-occurence matrices and features. - In debug=1 will return the 4 joint histograms for each ROI. - - The seg_co_occurence() method is used for texture-based segmentation. Feature images are - returned from which segmentation can be later performed. - - **** - NOTE: This is very slow and a fast method using Unsers histogram approximation will be - added in the future. - **** - - - Parameters - ---------- - - raw_image : {nd_array} - raw image from which texture features get extracted - - window : {int} - integer value of moving 2D window. Window slides in 2D over image and is the - region-of-interest from which co-occurence texture features are extracted. The - window is 2D square so only a single value is entered. Default window is 32x32. - - distance : {int} - integer value of pixel offset in forming joint histogram. default value 2 - - orientation : {45, 90, 135, 180} - direction for pixel offet. - - Returns - ---------- - - cocm_images : {dictionary} - - co_occurence_feature_images. contains 4 normalized feature - windows with keys: energy, entropy, contrast and homogeneity. - - """ - - if orientation != 45 and orientation != 90 and orientation != 135 and orientation != 180: - orientation = 90 - - epsilon = 2.2e-16 - num_bits = 256 - copy_image = raw_image.copy() - [rows, cols] = copy_image.shape - row_indices = range(window, rows-window) - col_indices = range(window, cols-window) - - # create a fixed mask and scratch window for raw source - section = NP.ones(2*window*2*window, dtype=NP.int16).reshape(2*window, 2*window) - source_region = NP.zeros(2*window*2*window, dtype=NP.float64).reshape(2*window, 2*window) - - # output images - energy_image = NP.zeros(rows*cols, dtype=NP.float64).reshape(rows, cols) - entropy_image = NP.zeros(rows*cols, dtype=NP.float64).reshape(rows, cols) - homogeneity_image = NP.zeros(rows*cols, dtype=NP.float64).reshape(rows, cols) - contrast_image = NP.zeros(rows*cols, dtype=NP.float64).reshape(rows, cols) - cocm_block = NP.zeros(num_bits*num_bits, dtype=NP.int32).reshape(num_bits, num_bits) - - for i in row_indices: - bottom = i - window - top = i + window - for j in col_indices: - left = j - window - right = j + window - source_region[0:2*window, 0:2*window] = copy_image[bottom:top, left:right] - # scale segment to 8 bits. this needs to be smarter (e.g. use integrated histogram method) - max_value = source_region.max() - min_value = source_region.min() - scale = 255.0 / (max_value-min_value) - image_roi = (scale*(source_region-min_value)).astype(NP.int16) - # image_roi is short type - cocm_block[:] = 0.0 - S.roi_co_occurence(section, image_roi, cocm_block, distance, orientation) - # normalize the joint histogram prior to feature extraction - joint_histogram = cocm_block.astype(NP.float64) - joint_histogram = joint_histogram / joint_histogram.sum() - # to prevent log(0) - joint_histogram += epsilon - # compute the com features - energy = joint_histogram.std() - H = joint_histogram * NP.log(joint_histogram) - entropy = H.sum() - r, c = joint_histogram.shape - [a, b] = NP.mgrid[1:c+1, 1:r+1] - contrast = ((NP.square(a-b))*joint_histogram).sum() - d = 1.0 + NP.abs(a-b) - homogeneity = (joint_histogram / d).sum() - # store the feature pixel for the 4 images - energy_image[i, j] = energy - entropy_image[i, j] = entropy - contrast_image[i, j] = contrast - homogeneity_image[i, j] = homogeneity - - scale_energy = 1.0 / max(energy_image.max(), abs(energy_image.min())) - scale_entropy = 1.0 / max(entropy_image.max(), abs(entropy_image.min())) - scale_contrast = 1.0 / max(contrast_image.max(), abs(contrast_image.min())) - scale_homogeneity = 1.0 / max(homogeneity_image.max(), abs(homogeneity_image.min())) - - energy_image = scale_energy * energy_image - entropy_image = scale_entropy * entropy_image - homogeneity_image = scale_homogeneity * homogeneity_image - contrast_image = scale_contrast * contrast_image - - cocm_images = {'energy_image' : energy_image, 'entropy_image' : entropy_image, - 'homogeneity_image' : homogeneity_image, 'contrast_image' : contrast_image} - - return cocm_images - - -def roi_mat_filter(label_image, thin_kernel, ROI): - """ - thin_edge_image = roi_mat_filter(label_image, thin_kernel, ROI) - - gets the largest object in the ROI list and returns the medial axis for - that object. Idea is that the largest object is a reference, e.g. the skull - for anatomical MRI. - - Parameters - ---------- - - label_image : {nd_array} - an image with labeled regions from get_blobs() method - - thin_kernel : {dictionary} - set of 8 'J' and 'K' 3x3 masks from build_morpho_thin_masks() method - - ROI : {dictionary} - Region of Interest structure that has blob bounding boxes. The largest - 2D target bounding box is extracted. - - Returns - ---------- - - thin_edge_image : {nd_array} - thinned edge image for the largest object. - - """ - - - [rows, cols] = label_image.shape - # destination image - thin_edge_image = NP.zeros(rows*cols, dtype=NP.uint16).reshape(rows, cols) - # scratch memory for thin - input = NP.zeros(rows*cols, dtype=NP.uint8).reshape(rows, cols) - cinput = NP.zeros(rows*cols, dtype=NP.uint8).reshape(rows, cols) - erosion = NP.zeros(rows*cols, dtype=NP.uint8).reshape(rows, cols) - dialation = NP.zeros(rows*cols, dtype=NP.uint8).reshape(rows, cols) - hmt = NP.zeros(rows*cols, dtype=NP.uint8).reshape(rows, cols) - copy = NP.zeros(rows*cols, dtype=NP.uint8).reshape(rows, cols) - - bbox = get_max_bounding_box(ROI) - - left = bbox['Left']-1 - right = bbox['Right']+1 - bottom = bbox['Bottom']-1 - top = bbox['Top']+1 - Label = bbox['Label'] - - if left < 0: - left = 0 - if bottom < 0: - bottom = 0 - if right > cols-1: - right = cols-1 - if top > rows-1: - top = rows-1 - - inflate = 1 - roi_rows = top-bottom+2*inflate - roi_cols = right-left+2*inflate - rgrows = top-bottom - rgcols = right-left - # clear the memory - input[0:roi_rows, 0:roi_cols] = 0 - # load the labeled region - input[inflate:inflate+rgrows, inflate:inflate+rgcols] \ - [label_image[bottom:top, left:right]==Label] = 1 - # thin this region - S.thin_filter(thin_kernel['jmask'], thin_kernel['kmask'], thin_kernel['number3x3Masks'], - roi_rows, roi_cols, cols, input, cinput, erosion, dialation, hmt, copy) - - # accumulate the images (do not over-write). for overlapping regions - input[inflate:rgrows+inflate,inflate:rgcols+inflate] \ - [input[inflate:rgrows+inflate,inflate:rgcols+inflate]==1] = Label - thin_edge_image[bottom:top,left:right] = input[inflate:rgrows+inflate,inflate:rgcols+inflate] - - return thin_edge_image - -def mat_filter(label_image, thin_kernel, ROI=None): - """ - mat_image = mat_filter(label_image, thin_kernel, ROI=None) - - takes the ROI dictionary with the blob bounding boxes and thins each blob - giving the medial axis. if ROI is null will create a single ROI with the - bounding box set equal to the full image - - Parameters - ---------- - - label_image : {nd_array} - an image with labeled regions from get_blobs() method - - thin_kernel : {dictionary} - set of 8 'J' and 'K' 3x3 masks from build_morpho_thin_masks() method - - ROI : {dictionary} - Region of Interest structure that has blob bounding boxes - - Returns - ---------- - - mat_image : {nd_array} - thinned edge image - - """ - if ROI==None: - ROIList = NP.zeros(1, dtype=_objstruct) - [rows, cols] = label_image.shape - ROIList['Left'] = 2 - ROIList['Right'] = cols-3 - ROIList['Bottom'] = 2 - ROIList['Top'] = rows-3 - - [rows, cols] = label_image.shape - # destination image - thin_edge_image = NP.zeros(rows*cols, dtype=NP.uint16).reshape(rows, cols) - mat_image = NP.zeros(rows*cols, dtype=NP.uint16).reshape(rows, cols) - # scratch memory for thin - input = NP.zeros(rows*cols, dtype=NP.uint8).reshape(rows, cols) - cinput = NP.zeros(rows*cols, dtype=NP.uint8).reshape(rows, cols) - erosion = NP.zeros(rows*cols, dtype=NP.uint8).reshape(rows, cols) - dialation = NP.zeros(rows*cols, dtype=NP.uint8).reshape(rows, cols) - hmt = NP.zeros(rows*cols, dtype=NP.uint8).reshape(rows, cols) - copy = NP.zeros(rows*cols, dtype=NP.uint8).reshape(rows, cols) - - number_regions = ROI.size - indices = range(0, number_regions) - inflate = 1 - for i in indices: - left = ROI[i]['Left']-1 - right = ROI[i]['Right']+1 - bottom = ROI[i]['Bottom']-1 - top = ROI[i]['Top']+1 - Label = ROI[i]['Label'] - if left < 0: - left = 0 - if bottom < 0: - bottom = 0 - if right > cols-1: - right = cols-1 - if top > rows-1: - top = rows-1 - - roi_rows = top-bottom+2*inflate - roi_cols = right-left+2*inflate - rgrows = top-bottom - rgcols = right-left - # clear the memory - input[0:roi_rows, 0:roi_cols] = 0 - # load the labeled region - input[inflate:inflate+rgrows, inflate:inflate+rgcols] \ - [label_image[bottom:top, left:right]==Label] = 1 - # thin this region - S.thin_filter(thin_kernel['jmask'], thin_kernel['kmask'], thin_kernel['number3x3Masks'], - roi_rows, roi_cols, cols, input, cinput, erosion, dialation, hmt, copy) - - # accumulate the images (do not over-write). for overlapping regions - input[inflate:rgrows+inflate,inflate:rgcols+inflate] \ - [input[inflate:rgrows+inflate,inflate:rgcols+inflate]==1] = Label - thin_edge_image[bottom:top,left:right] = thin_edge_image[bottom:top,left:right] + \ - input[inflate:rgrows+inflate,inflate:rgcols+inflate] - - - # accumulate overlaps set back to binary at later date - mat_image[:, :] = thin_edge_image[:, :] - - return mat_image - - -def laws_texture_filter(raw_image, label_image, laws_kernel, ROI=None, dc_thres=1.0, - mean_feature=1, verbose=0): - """ - texture_images = laws_texture_filter(raw_image, label_image, laws_kernel, ROI=None, verbose=1) - . - OR - . - laws_texture_filter(raw_image, label_image, laws_kernel, ROI=None, verbose=0) - - Parameters - ---------- - - raw_image : {nd_array} - raw double image - - label_image : {nd_array} - an image with labeled regions from get_blobs() method - - laws_kernel : {dictionary} - set of 6 length-7 Law's texture feature kernels - - ROI : {dictionary} - Region of Interest structure that has blob bounding boxes - - dc_thres : {float} - used as a filter. Sets texture feature to 0.0 when the - mean level is above this. Removes the low frequency, high amplitude - image regions from the feature list - - mean_feature : {0, 1}, optional - when set to 1, the feature is the mean value of the - selected Law's texture filter. When 0 the feature is - the standard deviation. - - verbose : {0, 1}, optional - determines if return is to include Law's filter images - - Returns - ---------- - - laws_image : {dictionary} - contains 21 Laws filtered regions for each ROI - returned if verbose=1 - - - """ - if ROI==None: - ROI= NP.zeros(1, dtype=_objstruct) - [rows, cols] = label_image.shape - ROI['Left'] = 2 - ROI['Right'] = cols-3 - ROI['Bottom'] = 2 - ROI['Top'] = rows-3 - - laws_image_list = {} - number_regions = ROI.size - layers = laws_kernel['filters'] - indices = range(0, number_regions) - filters = range(0, layers) - for i in indices: - left = ROI[i]['Left'] - right = ROI[i]['Right'] - bottom = ROI[i]['Bottom'] - top = ROI[i]['Top'] - Label = ROI[i]['Label'] - rows = top-bottom - cols = right-left - label_region = NP.zeros(rows*cols, dtype=NP.uint16).reshape(rows, cols) - source_region = NP.zeros(rows*cols, dtype=NP.float64).reshape(rows, cols) - laws_block = NP.zeros(layers*rows*cols, dtype=NP.float32).reshape(layers, rows, cols) - # load the labeled region - label_region[0:rows, 0:cols][label_image[bottom:top, left:right]==Label] = 1 - source_region[0:rows, 0:cols] = raw_image[bottom:top, left:right] - - S.laws_texture_metric(label_region, source_region, laws_block, laws_kernel['numKernels'], - laws_kernel['kernelSize'], laws_kernel['filters'], - laws_kernel['coefficients'][0], laws_kernel['coefficients'][1], - laws_kernel['coefficients'][2], laws_kernel['coefficients'][3], - laws_kernel['coefficients'][4], laws_kernel['coefficients'][5]) - - for j in filters: - # compute the energy measure for each filter in the ROI - mask_image = laws_block[j, :, :][label_region[:, :]>0] - mean = abs(mask_image.mean()) - std = mask_image.std() - if mean > dc_thres: - mean = 0.0 - std = 0.0 - if mean_feature == 1: - ROI[i]['TEM'][j] = mean - else: - ROI[i]['TEM'][j] = std - - ROI[i]['TEM'][:] = ROI[i]['TEM'][:] / ROI[i]['TEM'][:].max() - # accumulate the 21 Law's filtered ROI's and optional - # return as image (3D) - laws_image_list[i] = laws_block - - if verbose == 1: - return laws_image_list - else: - return - - - -def get_voxel_measures(label_image, raw_image, ROI=None): - """ - mat_image = mat_filter(label_image, raw_image, ROI=None) - - takes the ROI dictionary with the blob bounding boxes and gets the voxel measures - from each ROI in the raw data. - - Parameters - ---------- - - label_image : {nd_array} - an image with labeled regions from get_blobs() method - - raw_image : {nd_array} - the original double image (raw voxels) from which voxel measures are made - - ROI : {dictionary} - Region of Interest structure that has blob bounding boxes - - - Returns - ---------- - - none - - """ - - dimensions = label_image.ndim - - if ROI==None: - ROIList = NP.zeros(1, dtype=_objstruct) - if dimensions == 2: - [rows, cols] = label_image.shape - ROIList['Left'] = 1 - ROIList['Right'] = cols-1 - ROIList['Bottom'] = 1 - ROIList['Top'] = rows-1 - elif dimensions == 3: - [layers, rows, cols] = label_image.shape - ROIList['Left'] = 1 - ROIList['Right'] = cols-1 - ROIList['Bottom'] = 1 - ROIList['Top'] = rows-1 - ROIList['Front'] = 1 - ROIList['Back'] = layers-1 - - number_regions = ROI.size - indices = range(0, number_regions) - inflate = 1 - for i in indices: - if dimensions == 2: - left = ROI[i]['Left'] - right = ROI[i]['Right'] - bottom = ROI[i]['Bottom'] - top = ROI[i]['Top'] - Label = ROI[i]['Label'] - rows = top-bottom-1 - cols = right-left-1 - section= NP.zeros(rows*cols, dtype=raw_image.dtype).reshape(rows, cols) - section = raw_image[bottom:top, left:right] \ - [label_image[bottom:top, left:right]==Label] - elif dimensions == 3: - left = ROI[i]['Left'] - right = ROI[i]['Right'] - bottom = ROI[i]['Bottom'] - top = ROI[i]['Top'] - front = ROI[i]['Front'] - back = ROI[i]['Back'] - Label = ROI[i]['Label'] - rows = top-bottom-1 - cols = right-left-1 - layers = back-front-1 - section= NP.zeros(layers*rows*cols, dtype=raw_image.dtype).reshape(layers, rows, cols) - section = raw_image[front:back, bottom:top, left:right] \ - [label_image[front:back, bottom:top, left:right]==Label] - - mask = section[section>0] - ROI[i]['voxelMean'] = mask.mean() - ROI[i]['voxelVar'] = mask.std() - - return - - -def get_blob_regions(labeled_image, groups, dust=16): - """ - ROIList = get_blob_regions(labeled_image, groups, dust=16) - - get the bounding box for each labelled blob in the image - allocate the dictionary structure that gets filled in with later - stage processing to add blob features. - - Parameters - ---------- - - label_image : {nd_array} - a 2D or 3D image with labeled regions from get_blobs() method - - groups : {int} - number of blobs in image determined by get_blobs() method - - Returns - ---------- - - ROIList : {dictionary} - structure that has the bounding box and area of each blob - - - - """ - - _c_ext_struct = NP.dtype([('Left', 'i'), - ('Right', 'i'), - ('Top', 'i'), - ('Bottom', 'i'), - ('Front', 'i'), - ('Back', 'i'), - ('Label', 'i'), - ('Mass', 'i'), - ('cX', 'f'), - ('cY', 'f'), - ('cZ', 'f')] - ) - - c_ext_ROI = NP.zeros(groups, dtype=_c_ext_struct) - ROIList = NP.zeros(groups, dtype=_objstruct) - # return the bounding box for each connected edge - S.get_blob_regions(labeled_image, c_ext_ROI) - - indices = range(0, groups) - for i in indices: - ROIList[i]['Left'] = c_ext_ROI[i]['Left'] - ROIList[i]['Right'] = c_ext_ROI[i]['Right'] - ROIList[i]['Bottom'] = c_ext_ROI[i]['Bottom'] - ROIList[i]['Top'] = c_ext_ROI[i]['Top'] - ROIList[i]['Front'] = c_ext_ROI[i]['Front'] - ROIList[i]['Back'] = c_ext_ROI[i]['Back'] - ROIList[i]['Label'] = c_ext_ROI[i]['Label'] - ROIList[i]['Mass'] = c_ext_ROI[i]['Mass'] - ROIList[i]['cX'] = c_ext_ROI[i]['cX'] - ROIList[i]['cY'] = c_ext_ROI[i]['cY'] - ROIList[i]['cZ'] = c_ext_ROI[i]['cZ'] - - return ROIList[ROIList['Mass']>dust] - - -def get_blobs(binary_edge_image, mask=1): - """ - - labeled_edge_image, groups = get_blobs(binary_edge_image) - - get the total number of blobs in a 2D or 3D image and convert the - binary image (or volume) to labelled regions - - Parameters - ---------- - - binary_edge_image : {nd_array} - an binary image/volume - - mask : {int} - the size of the 2D or 3D connectivity mask. For 2D this is 1, 4 or 8. - For 3D this is 1, 6, 14 or 28. Mask = 1 is ANY connection in 3x3 - or 3x3x3 mask for 2D or 3D, respectively. - - Returns - ---------- - - label_image : {nd_array} - an image/volume with labeled regions from get_blobs() method - - groups : {int} - number of blobs in image determined by get_blobs() method - - """ - - dimensions = binary_edge_image.ndim - if dimensions == 2: - if mask != 1 and mask != 4 and mask != 8: - mask = 1 - [rows, cols] = binary_edge_image.shape - labeled_edge_image_or_vol = NP.zeros(rows*cols, dtype=NP.uint16).reshape(rows, cols) - elif dimensions == 3: - if mask != 1 and mask != 6 and mask != 14 and mask != 28: - mask = 1 - [layers, rows, cols] = binary_edge_image.shape - labeled_edge_image_or_vol = NP.zeros(layers*rows*cols, dtype=NP.uint16).reshape(layers, rows, cols) - else: - labeled_edge_image_or_vol = None - groups = 0 - return labeled_edge_image_or_vol, groups - - groups = S.get_blobs(binary_edge_image, labeled_edge_image_or_vol, mask) - - return labeled_edge_image_or_vol, groups - - -def sobel_edges(sobel_edge_image, sobel_stats, mode=1, sobel_threshold=0.3): - """ - sobel_edge = sobel_edges(sobel_edge_image, sobel_stats, mode=1, sobel_threshold=0.3) - take sobel-filtered image and return binary edges - - Parameters - ---------- - - sobel_edge_image : {nd_array} - edge-filtered image from sobel_image() method - - sobel_stats : {dictionary} - mean and nonzero min, max of sobel filtering - - mode : {0, 1}, optional - threshold based on histogram mean(0) or mode(1) - - sobel_threshold : {float}, optional - low threshold applied to edge filtered image for edge generation - - Returns - ---------- - - sobel_edge : {nd_array} - binary edge-image - - """ - [rows, cols] = sobel_edge_image.shape - sobel_edge = NP.zeros(rows*cols, dtype=NP.uint16).reshape(rows, cols) - S.sobel_edges(sobel_edge_image, sobel_edge, sobel_stats['ave_gt0'], sobel_stats['min_gt0'], - sobel_stats['max_gt0'], mode, sobel_threshold) - - return sobel_edge - - -def sobel_image(filtered_slice): - """ - sobel_edge_image, sobel_stats = sobel_image(filtered_slice) - - take 2D raw or filtered image slice and get sobel-filtered image - - Parameters - ---------- - - filtered_slice : {nd_array} - raw or pre-processed (filtered and thresholded) 2D image - - Returns - ---------- - - sobel_edge_image : {nd_array} - edge-filtered image from sobel_image() method - - sobel_stats : {dictionary} - mean and nonzero min, max of sobel filtering - - """ - filtered_slice = filtered_slice.astype(NP.float64) - [rows, cols] = filtered_slice.shape - sobel_edge_image = NP.zeros(rows*cols, dtype=NP.float64).reshape(rows, cols) - pAve, min_value, max_value = S.sobel_image(filtered_slice, sobel_edge_image) - - # can replace this with numpy calls for the image stats. but C ext is faster - # S.sobel_image(filtered_slice, sobel_edge_image) - # sobel_mask = sobel_edge_image[sobel_edge_image>0] - # pAve = sobel_mask.mean() - # min_value = sobel_mask.min() - # max_value = sobel_mask.max() - - sobel_stats= {'ave_gt0' : pAve, 'min_gt0': min_value, 'max_gt0': max_value} - - return sobel_edge_image, sobel_stats - -def pre_filter(slice, filter, low_threshold=0, high_threshold=0, conv_binary=0): - """ - edge_filter = pre_filter(slice, filter, low_threshold=0, high_threshold=slice.max(), conv_binary=0) - - take 2D image slice and filter and pre-filter and threshold prior to segmentation - - Parameters - ---------- - slice : {nd_array} - input 2D image. gets cast to int16 - - filter : {dictionary} - 2D filter kernel set from build_2d_kernel() - - low_threshold : {int}, optional - default 0 - - high_threshold : {int}, optional - default max value of source image - - conv_binary : {0, 1}, optional - flag to convert edge_filter image to binary valued. default - is binary conversion off - - Returns - ---------- - edge_filter : {nd_array} - filtered and thresholded image that can be (optional) binary. - - """ - - # make sure the input is 16 bits. this is input to edge machine - # so can handle raw and 8 bit scaled inputs - if high_threshold==0: - # default to the maximum value of the image - high_threshold = slice.max() - - slice = slice.astype(NP.int16) - [rows, cols] = slice.shape - edge_image = NP.zeros(rows*cols, dtype=NP.float64).reshape(rows, cols) - S.edge_prefilter(low_threshold, high_threshold, filter['kernelSize'], filter['kernel'], - slice, edge_image) - - if conv_binary == 1: - edge_image[edge_image>0] = 1 - edge_image = edge_image.astype(NP.uint16) - - return edge_image - -def get_max_bounding_box(ROI): - """ - bounding_box = get_max_bounding_box(ROI) - - take an ROI structure and find the maximum area bounding box - - Parameters - ---------- - - ROI : {dictionary} - the ROI is the automatically extracted blob regions of interest - and contains the rectangular bounding box of each blob. - - Returns - ---------- - - bounding_box : {dictionary} - the Left, Right, Top Bottom and Label of the LARGEST bounding box in the ROI - - """ - max_index = ROI[:]['Mass'].argmax() - bounding_box = {'Left' : ROI[max_index]['Left'], 'Right' : ROI[max_index]['Right'], - 'Top' : ROI[max_index]['Top'], 'Bottom' : ROI[max_index]['Bottom'], - 'Label' : ROI[max_index]['Label']} - - return bounding_box - -def get_all_bounding_boxes(ROI): - """ - measures = get_all_bounding_boxes(ROI) - - get all bounding boxes in the ROI (feature) dictionary - - Parameters - ---------- - - ROI : {dictionary} - the ROI is the automatically extracted blob regions of interest - and contains the rectangular bounding box of each blob. - - Returns - ---------- - - measures : {dictionary} - the Left, Right, Top and Bottom of all bounding boxes in the ROI - - """ - - number = ROI.size - indices = range(0, ROI.size) - _shortstruct = NP.dtype([('left', 'i'), - ('right', 'i'), - ('top', 'i'), - ('bottom', 'i')]) - measures = NP.zeros(number, dtype=_shortstruct) - for i in indices: - measures[i]['left'] = ROI[i]['Left'] - measures[i]['right'] = ROI[i]['Right'] - measures[i]['top'] = ROI[i]['Top'] - measures[i]['bottom'] = ROI[i]['Bottom'] - - return measures - - -def build_2d_kernel(aperature=21, hiFilterCutoff=10.0): - """ - - FIRFilter = build_2d_kernel(aperature, hiFilterCutoff) - - build hamming-windowed FIR filter with sinc kernel - - Parameters - ---------- - - aperature : {int}, optional - the number of coefficients in the filter. default is 21. needs to be ODD - - hiFilterCutoff : {float} - the upper cutoff in digital frequency units - - Returns - ---------- - - FIRFilter : {dictionary} - filter kernel - - """ - - rad = math.pi / 180.0 - HalfFilterTaps = (aperature-1) / 2 - kernel = NP.zeros((aperature), dtype=NP.float64) - LC = 0.0 - HC = hiFilterCutoff * rad - t2 = 2.0 * math.pi - t1 = 2.0 * HalfFilterTaps + 1.0 - indices = range(-HalfFilterTaps, HalfFilterTaps+1, 1) - j = 0 - for i in indices: - if i == 0: - tLOW = LC - tHIGH = HC - else: - tLOW = math.sin(i*LC)/i - tHIGH = math.sin(i*HC)/i - # Hamming window - t3 = 0.54 + 0.46*(math.cos(i*t2/t1)) - t4 = t3*(tHIGH-tLOW) - kernel[j] = t4 - j += 1 - - # normalize the kernel - sum = kernel.sum() - kernel /= sum - - FIRFilter= {'kernelSize' : HalfFilterTaps, 'kernel': kernel} - - return FIRFilter - -def build_d_gauss_kernel(gWidth=20, sigma=1.0): - - """ - DGFilter = build_d_gauss_kernel(gWidth, sigma) - - build the derivative of Gaussian kernel for Canny edge filter - - Parameters - ---------- - gWdith : {int}, optional - width of derivative of Gaussian kernel. - default value is 20 - - sigma : {float}, optional - sigma term of derivative of Gaussian kernel - default value is 1.0 - - Returns - ---------- - - DGFilter : {dictionary} - filter kernel - - """ - - kernel = NP.zeros((1+gWidth), dtype=NP.float64) - indices = range(0, gWidth) - - for i in indices: - kernel[i] = math.exp(((-i*i)/(2.0 * sigma * sigma))) - kernel[i] *= -(i / (sigma * sigma)) - - DGFilter= {'kernelSize' : gWidth, 'coefficients': kernel} - - return DGFilter - -def build_morpho_thin_masks(): - - """ - MATFilter = build_morpho_thin_masks() - - build 2 sets (J and K) of 8 3x3 morphology masks (structuring elements) - to implement thinning (medial axis transformation - MAT) - - - Parameters - ---------- - - None - - Returns - ---------- - - MATFilter : {dictionary} - morphology filter kernels. there are 2 sets of 8 3x3 masks - - """ - - # (layers, rows, cols) - size = (8*3*3) - J_mask = NP.zeros(size, dtype=NP.int16) - K_mask = NP.zeros(size, dtype=NP.int16) - - maskCols = 3 - # load the 8 J masks for medial axis transformation - Column = 0 - J_mask[0+maskCols*(Column+0)] = 1 - J_mask[0+maskCols*(Column+1)] = 1 - J_mask[0+maskCols*(Column+2)] = 1 - J_mask[1+maskCols*(Column+1)] = 1 - - Column += 3 - J_mask[0+maskCols*(Column+1)] = 1 - J_mask[1+maskCols*(Column+1)] = 1 - J_mask[1+maskCols*(Column+2)] = 1 - - Column += 3 - J_mask[0+maskCols*(Column+0)] = 1 - J_mask[1+maskCols*(Column+0)] = 1 - J_mask[2+maskCols*(Column+0)] = 1 - J_mask[1+maskCols*(Column+1)] = 1 - - Column += 3 - J_mask[0+maskCols*(Column+1)] = 1 - J_mask[1+maskCols*(Column+0)] = 1 - J_mask[1+maskCols*(Column+1)] = 1 - - Column += 3 - J_mask[0+maskCols*(Column+2)] = 1 - J_mask[1+maskCols*(Column+1)] = 1 - J_mask[1+maskCols*(Column+2)] = 1 - J_mask[2+maskCols*(Column+2)] = 1 - - Column += 3 - J_mask[1+maskCols*(Column+0)] = 1 - J_mask[1+maskCols*(Column+1)] = 1 - J_mask[2+maskCols*(Column+1)] = 1 - - Column += 3 - J_mask[1+maskCols*(Column+1)] = 1 - J_mask[2+maskCols*(Column+0)] = 1 - J_mask[2+maskCols*(Column+1)] = 1 - J_mask[2+maskCols*(Column+2)] = 1 - - Column += 3 - J_mask[1+maskCols*(Column+1)] = 1 - J_mask[1+maskCols*(Column+2)] = 1 - J_mask[2+maskCols*(Column+1)] = 1 - - # load the 8 K masks for medial axis transformation - Column = 0 - K_mask[2+maskCols*(Column+0)] = 1 - K_mask[2+maskCols*(Column+1)] = 1 - K_mask[2+maskCols*(Column+2)] = 1 - - Column += 3 - K_mask[1+maskCols*(Column+0)] = 1 - K_mask[2+maskCols*(Column+0)] = 1 - K_mask[2+maskCols*(Column+1)] = 1 - - Column += 3 - K_mask[0+maskCols*(Column+2)] = 1 - K_mask[1+maskCols*(Column+2)] = 1 - K_mask[2+maskCols*(Column+2)] = 1 - - Column += 3 - K_mask[1+maskCols*(Column+2)] = 1 - K_mask[2+maskCols*(Column+1)] = 1 - K_mask[2+maskCols*(Column+2)] = 1 - - Column += 3 - K_mask[0+maskCols*(Column+0)] = 1 - K_mask[1+maskCols*(Column+0)] = 1 - K_mask[2+maskCols*(Column+0)] = 1 - - Column += 3 - K_mask[0+maskCols*(Column+1)] = 1 - K_mask[0+maskCols*(Column+2)] = 1 - K_mask[1+maskCols*(Column+2)] = 1 - - Column += 3 - K_mask[0+maskCols*(Column+0)] = 1 - K_mask[0+maskCols*(Column+1)] = 1 - K_mask[0+maskCols*(Column+2)] = 1 - - Column += 3 - K_mask[0+maskCols*(Column+0)] = 1 - K_mask[0+maskCols*(Column+1)] = 1 - K_mask[1+maskCols*(Column+0)] = 1 - - MATFilter = {'number3x3Masks' : 8, 'jmask' : J_mask, 'kmask' : K_mask} - - return MATFilter - - -def build_laws_kernel(): - - """ - LAWSFilter = build_laws_kernel() - - build 6 length-7 Law's texture filter masks - mask names are: 'L', 'S', 'E', 'W', 'R', 'O' - - - Parameters - ---------- - - None - - Returns - ---------- - - LAWSFilter : {dictionary} - a set of 6 length-7 Laws texture kernels - - """ - aperature = (6, 7) - coefficients = NP.zeros((aperature), dtype=NP.float64) - names = ('L', 'E', 'S', 'W', 'R', 'O' ) - - coefficients[0, :] = ( 1.0, 6.0, 15.0, 20.0, 15.0, 6.0, 1.0) - coefficients[1, :] = (-1.0, -4.0, -5.0, 0.0, 5.0, 4.0, 1.0) - coefficients[2, :] = (-1.0, -2.0, 1.0, 4.0, 1.0, -2.0, -1.0) - coefficients[3, :] = (-1.0, 0.0, 3.0, 0.0, -3.0, 0.0, 1.0) - coefficients[4, :] = ( 1.0, -2.0, -1.0, 4.0, -1.0, -2.0, 1.0) - coefficients[5, :] = (-1.0, 6.0, -15.0, 20.0, -15.0, 6.0, -1.0) - - LAWSFilter= {'numKernels' : 6, 'kernelSize' : 7, 'filters' : 21, - 'coefficients': coefficients, 'names': names} - - return LAWSFilter - -def build_laws_masks(LAWSFilter): - - """ - masks = build_laws_masks(LAWSFilter) - - takes the Laws Filter dictionary and builds the 21 7x7 kernel masks that are - used in Laws texture feature extraction. - - Parameters - ---------- - - LAWSFilter : {dictionary} - a set of 6 length-7 Laws texture kernels - - Returns - ---------- - - masks : {list} - a list of 21 7x7 kernels (2D nd_array) - - Examples: - use this along with FFT Pack to view the spatial frequency response. Create a 256x256 zero - array and pad the first 7x7 with the Laws kernel and then get the 2D power spectrum and display - with pylab - - - LAWSFilter = build_laws_kernel() - mask = build_laws_masks(LAWSFilter) - - mask_2 = masks[2] - - z = NP.zeros(256*256, dtype=NP.float32).reshape(256, 256) - z[0:7, 0:7] = mask_0 - x = abs(fftshift(fft2(z))) - pylab.imshow(x) - - """ - - outer_indices = range(0, LAWSFilter['numKernels']) - mask_array = {} - count = 0 - for i in outer_indices: - rowFilter = LAWSFilter['coefficients'][i] - colFilter = LAWSFilter['coefficients'][i] - matrix = NP.outer(rowFilter, colFilter) - mask_array[count] = 2.0*matrix - count = count + 1 - inner_indices = range(i+1, LAWSFilter['numKernels']) - for j in inner_indices: - colFilter = LAWSFilter['coefficients'][j] - matrix = NP.outer(rowFilter, colFilter) + NP.outer(colFilter, rowFilter) - mask_array[count] = matrix - count = count + 1 - - return mask_array - - -# -# test pattern generators for demo and test -# - -def build_test_texture_discs(): - """ - discs = build_test_texture_discs() - - builds 4 discs with plane wave texture. used for test and demo - - Parameters - ---------- - - None - - Returns - ---------- - - discs : {nd_array} - a 512x512 image with 4 test discs (one per quadrant) - - """ - rows = 512 - cols = 512 - rad = NP.pi / 180.0 - test_image = NP.zeros(rows*cols, dtype=NP.float32).reshape(rows, cols) - [a, b] = NP.mgrid[0:rows, 0:cols] - - test_image[0:255,0:255] = NP.sin(4.0*rad*a[0:255,0:255]) + NP.sin(-4.0*rad*b[0:255,0:255]) - test_image[256:511,256:511] = NP.sin(24.0*rad*a[0:255,0:255]) + NP.sin(20.0*rad*b[0:255,0:255]) - - test_image = test_image + test_image.min() - discs = build_test_unit_discs() - discs = discs * test_image - - return discs - - -def build_test_discs(): - """ - test_image = build_test_discs() - build 4 discs of equal radius and different mean values for edge/blob testing - - Parameters - ---------- - - None - - Returns - ---------- - - test_image : {nd_array} - a 512x512 image with 4 test discs (one per quadrant) - - """ - radius = 50 - rows = 512 - cols = 512 - test_image = NP.zeros(rows*cols, dtype=NP.int16).reshape(rows, cols) - y_indices = NP.array(range(-radius, radius+1)) - center_x = rows / 4 - center_y = cols / 4 - - for i in y_indices: - x = math.sqrt(float(radius)**2 - float(i)**2) - # different raw mean levels - test_image[1*center_y+i, 1*center_x-x:1*center_x+x] = 80 - test_image[1*center_y+i, 3*center_x-x:3*center_x+x] = 90 - test_image[3*center_y+i, 1*center_x-x:1*center_x+x] = 100 - test_image[3*center_y+i, 3*center_x-x:3*center_x+x] = 110 - - return test_image - - -def build_test_unit_discs(): - """ - test_image = build_test_unit_discs() - build 2 discs of equal radius and same mean values for texture testing - - Parameters - ---------- - - None - - Returns - ---------- - - test_image : {nd_array} - a 512x512 image with 4 test discs (one per quadrant) - - """ - radius = 50 - rows = 512 - cols = 512 - test_image = NP.zeros(rows*cols, dtype=NP.int16).reshape(rows, cols) - y_indices = NP.array(range(-radius, radius+1)) - center_x = rows / 4 - center_y = cols / 4 - - for i in y_indices: - x = math.sqrt(float(radius)**2 - float(i)**2) - # different raw mean levels - test_image[1*center_y+i, 1*center_x-x:1*center_x+x] = 100 - test_image[3*center_y+i, 3*center_x-x:3*center_x+x] = 100 - - return test_image - - -def build_test_impulses(): - """ - test_image = build_test_impulses() - - build 4 test impulses discs centered in the 4 discs. used - for testing filter kernels, esp. Laws' filter kernel. Filtering - with these test patterns will return Law's kernel outer product matrices. - - Parameters - ---------- - - None - - Returns - ---------- - - test_image : {nd_array} - a 512x512 image with 4 test discs (one per quadrant) - - """ - rows = 512 - cols = 512 - test_image = NP.zeros(rows*cols, dtype=NP.int16).reshape(rows, cols) - test_image[128,128] = 1 - test_image[378,128] = 1 - test_image[128,378] = 1 - test_image[378,378] = 1 - - return test_image - - - Modified: trunk/scipy/ndimage/setup.py =================================================================== --- trunk/scipy/ndimage/setup.py 2008-08-11 21:39:17 UTC (rev 4637) +++ trunk/scipy/ndimage/setup.py 2008-08-11 23:08:56 UTC (rev 4638) @@ -14,17 +14,6 @@ include_dirs=['src']+[get_include()], ) - config.add_extension('_segment', - sources=['src/segment/Segmenter_EXT.c', - 'src/segment/Segmenter_IMPL.c'], - depends = ['src/segment/ndImage_Segmenter_structs.h'] - ) - - config.add_extension('_register', - sources=['src/register/Register_EXT.c', - 'src/register/Register_IMPL.c'] - ) - config.add_data_dir('tests') return config Deleted: trunk/scipy/ndimage/tests/test_registration.py =================================================================== --- trunk/scipy/ndimage/tests/test_registration.py 2008-08-11 21:39:17 UTC (rev 4637) +++ trunk/scipy/ndimage/tests/test_registration.py 2008-08-11 23:08:56 UTC (rev 4638) @@ -1,192 +0,0 @@ -import math -import numpy as np -import scipy.ndimage._registration as reg -from numpy.testing import * - -def load_desc(): - # this is for a 256x256x90 volume with 0.9375 x 0.9375 * 1.5 mm voxel sizes - rows = 256 - cols = 256 - layers = 90 - xsamp = 0.9375 - ysamp = 0.9375 - zsamp = 1.5 - desc = {'rows' : rows, 'cols' : cols, 'layers' : layers, - 'sample_x' : xsamp, 'sample_y' : ysamp, 'sample_z' : zsamp} - return desc - -def build_volume(imagedesc, S=[1500.0, 2500.0, 1000.0]): - - """ - build a 3D Gaussian volume. user passes in image dims in imagedesc - the sigma for each axis is S[3] where 0=z, 1=y, 2=x - - volume3D = build_test_volume(imagedesc, S) - - Parameters - ---------- - imagedesc : {dictionary} - volume dimensions and sampling - - S : {tuple} - the Gaussian sigma for Z, Y and X - - Returns - ------- - - volume3D : {nd_array} - the 3D volume for testing - - """ - layers = imagedesc['layers'] - rows = imagedesc['rows'] - cols = imagedesc['cols'] - - L = layers/2 - R = rows/2 - C = cols/2 - - # build coordinates for 3D Gaussian volume - # coordinates are centered at (0, 0, 0) - [a, b, c] = np.mgrid[-L:L, -R:R, -C:C] - - sigma = np.array([S[0], S[1], S[2]]) - aa = (np.square(a))/sigma[0] - bb = (np.square(b))/sigma[1] - cc = (np.square(c))/sigma[2] - volume3D = (255.0*np.exp(-(aa + bb + cc))).astype(np.uint8) - - return volume3D - - # self.failUnless(diff(output, tcov) < eps) -class TestRegistration(TestCase): - - def test_affine_matrix_build_1(self): - "test_affine_matrix_build_1" - P = np.zeros(6) - M = reg.build_rotate_matrix(P) - E = np.eye(4) - match = (E==M).all() - assert_equal(match, True) - return - - def test_affine_matrix_build_2(self): - "test_affine_matrix_build_2" - P = np.zeros(6) - P[0] = 1.0 - M = reg.build_rotate_matrix(P) - E = np.array([ - [ 1. , 0. , 0. , 0. ], - [ 0. , 0.9998477 , 0.01745241, 0. ], - [ 0. , -0.01745241, 0.9998477 , 0. ], - [ 0. , 0. , 0. , 1. ] - ]) - assert_array_almost_equal(E, M, decimal=6) - return - - def test_affine_matrix_build_3(self): - "test_affine_matrix_build_3" - P = np.zeros(6) - P[0] = 1.0 - P[1] = 1.0 - P[2] = 1.0 - M = reg.build_rotate_matrix(P) - E = np.array([ - [ 0.99969541, 0.01744975, 0.01745241, 0. ], - [-0.01775429, 0.9996901 , 0.01744975, 0. ], - [-0.0171425 , -0.01775429, 0.99969541, 0. ], - [ 0. , 0. , 0. , 1. ] - ]) - assert_array_almost_equal(E, M, decimal=6) - return - - @dec.slow - def test_autoalign_histogram_1(self): - "test_autoalign_histogram_1" - desc = load_desc() - gvol = build_volume(desc) - mat = np.eye(4) - cost, joint = reg.check_alignment(gvol, mat, gvol, mat, ret_histo=1, lite=1) - # confirm that with lite=1 only have non-zero on the main diagonal - j_diag = joint.diagonal() - Z = np.diag(j_diag) - W = joint - Z - # clip the near-zero fuzz - W[abs(W) < 1e-10] = 0.0 - assert_equal(W.max(), 0.0) - return - - @dec.slow - def test_autoalign_histogram_2(self): - "test_autoalign_histogram_2" - desc = load_desc() - gvol = build_volume(desc) - mat = np.eye(4) - cost, joint = reg.check_alignment(gvol, mat, gvol, mat, ret_histo=1, lite=0) - # confirm that with lite=0 DO have non-zero on the main diagonal - j_diag = joint.diagonal() - Z = np.diag(j_diag) - W = joint - Z - # clip the near-zero fuzz - W[abs(W) < 1e-10] = 0.0 - s = (W.max() > 0.0) - # make sure there are off-diagonal values - assert_equal(s, True) - return - - @dec.slow - def test_autoalign_ncc_value_1(self): - "test_autoalign_ncc_value_1" - desc = load_desc() - gvol = build_volume(desc) - mat = np.eye(4) - cost = reg.check_alignment(gvol, mat, gvol, mat, method='ncc', lite=1) - # confirm the cross correlation is near 1.0 - t = abs(cost) + 0.0001 - s = (t >= 1.0) - assert_equal(s, True) - return - - @dec.slow - def test_autoalign_ncc_value_2(self): - "test_autoalign_ncc_value_2" - desc = load_desc() - gvol = build_volume(desc) - mat = np.eye(4) - cost = reg.check_alignment(gvol, mat, gvol, mat, method='ncc', lite=0) - # confirm the cross correlation is near 1.0 - t = abs(cost) + 0.0001 - s = (t >= 1.0) - assert_equal(s, True) - return - - @dec.slow - def test_autoalign_nmi_value_1(self): - "test_autoalign_nmi_value_1" - desc = load_desc() - gvol = build_volume(desc) - mat = np.eye(4) - cost = reg.check_alignment(gvol, mat, gvol, mat, method='nmi', lite=1) - # confirm the normalized mutual information is near -2.0 - assert_almost_equal(cost, -2.0, decimal=6) - return - - @dec.slow - def test_autoalign_nmi_value_2(self): - "test_autoalign_nmi_value_2" - desc = load_desc() - gvol = build_volume(desc) - mat = np.eye(4) - cost = reg.check_alignment(gvol, mat, gvol, mat, method='nmi', lite=0) - # confirm the normalized mutual information is near -2.0 - assert_almost_equal(cost, -1.7973048186515352, decimal=6) - return - - - -if __name__ == "__main__": - #nose.runmodule() - run_module_suite() - - - Deleted: trunk/scipy/ndimage/tests/test_segment.py =================================================================== --- trunk/scipy/ndimage/tests/test_segment.py 2008-08-11 21:39:17 UTC (rev 4637) +++ trunk/scipy/ndimage/tests/test_segment.py 2008-08-11 23:08:56 UTC (rev 4638) @@ -1,159 +0,0 @@ -import math -import numpy as NP -import scipy.ndimage._segmenter as seg -from numpy.testing import * - -def run_sobel(): - img = seg.build_test_discs() - filter = seg.build_2d_kernel(hiFilterCutoff=60.0) - fslice = seg.pre_filter(img, filter, low_threshold=0, high_threshold=255) - sobel_edge_image, sobel_stats = seg.sobel_image(fslice) - sobel_edge = seg.sobel_edges(sobel_edge_image, sobel_stats, sobel_threshold=0.8) - label_sobel, sobel_groups = seg.get_blobs(sobel_edge) - ROI = seg.get_blob_regions(label_sobel, sobel_groups) - measures = seg.get_all_bounding_boxes(ROI) - thin_kernel = seg.build_morpho_thin_masks() - sobel_edges = seg.mat_filter(label_sobel, thin_kernel, ROI) - seg.get_voxel_measures(label_sobel, img, ROI) - means = ROI[:]['voxelMean'] - return measures, means - -def run_canny(): - img = seg.build_test_discs() - filter = seg.build_2d_kernel(hiFilterCutoff=60.0) - fslice = seg.pre_filter(img, filter, low_threshold=0, high_threshold=255) - canny_kernel = seg.build_d_gauss_kernel() - horz, vert, imean = seg.canny_filter(fslice, canny_kernel) - mag, canny_stats = seg.canny_nonmax_supress(horz, vert, imean) - canny_edge = seg.canny_hysteresis(mag, canny_stats) - label_canny, canny_groups = seg.get_blobs(canny_edge) - ROI = seg.get_blob_regions(label_canny, canny_groups) - measures = seg.get_all_bounding_boxes(ROI) - seg.get_voxel_measures(label_canny, img, ROI) - means = ROI[:]['voxelMean'] - return measures, means - -def run_texture1(): - filter = seg.build_2d_kernel(hiFilterCutoff=60.0) - img = seg.build_test_discs() - disc_mask = seg.pre_filter(img, filter, low_threshold=50, high_threshold=255, - conv_binary=1) - label_disc_mask, disc_mask_groups = seg.get_blobs(disc_mask) - disc_ROI = seg.get_blob_regions(label_disc_mask, disc_mask_groups) - laws_kernel = seg.build_laws_kernel() - impulse = seg.build_test_impulses() - calib = seg.laws_texture_filter(impulse, label_disc_mask, laws_kernel, - ROI=disc_ROI, verbose=1) - kernels = calib[0] - x = laws_kernel['coefficients'][0] - m = NP.outer(x, x) - m = m * 2 - laws_LL = kernels[0, 50-4:50+3, 50-3:50+4] - return m, laws_LL - - -def run_texture2(): - filter = seg.build_2d_kernel(hiFilterCutoff=60.0) - img = seg.build_test_unit_discs() - disc = seg.pre_filter(img, filter, low_threshold=50, high_threshold=255) - disc_mask = seg.pre_filter(img, filter, low_threshold=50, high_threshold=255, - conv_binary=1) - label_disc_mask, disc_mask_groups = seg.get_blobs(disc_mask) - disc_ROI = seg.get_blob_regions(label_disc_mask, disc_mask_groups) - laws_kernel = seg.build_laws_kernel() - texture_img = seg.build_test_texture_discs() - seg.laws_texture_filter(texture_img, label_disc_mask, laws_kernel, ROI=disc_ROI, - mean_feature=1, verbose=0) - tem = disc_ROI['TEM'] - return tem - -class TestSegment(TestCase): - def test_sobel(self): - # generate 4 discs, find the bounding boxes and - # confirm the bounding boxes are at the true position - measures, voxel_means = run_sobel() - number = measures.size - _shortstruct = NP.dtype([('left', 'i'), - ('right', 'i'), - ('top', 'i'), - ('bottom', 'i')]) - - assert_equal(number, 4) - # load the ground truth - truth = NP.zeros(number, dtype=_shortstruct) - truth[0] = (76, 179, 179, 77) - truth[1] = (332, 435, 179, 77) - truth[2] = (76, 179, 435, 333) - truth[3] = (332, 435, 435, 333) - match = (truth==measures).all() - assert_equal(match, True) - # load the ground truth for the bounding box test image mean value - voxel_truth = NP.zeros(number, dtype=NP.float64) - voxel_truth = (80.0, 90.0, 100.0, 110.0) - match = (voxel_truth==voxel_means).all() - assert_equal(match, True) - - return - - def test_canny(self): - # generate 4 discs, find the bounding boxes and - # confirm the bounding boxes are at the true position - measures, voxel_means = run_canny() - number = measures.size - _shortstruct = NP.dtype([('left', 'i'), - ('right', 'i'), - ('top', 'i'), - ('bottom', 'i')]) - - assert_equal(number, 4) - # load the ground truth for the bounding box - truth = NP.zeros(number, dtype=_shortstruct) - truth[0] = (78, 177, 177, 79) - truth[1] = (334, 433, 177, 79) - truth[2] = (78, 177, 433, 335) - truth[3] = (334, 433, 433, 335) - match = (truth==measures).all() - assert_equal(match, True) - # load the ground truth for the bounding box test image mean value - voxel_truth = NP.zeros(number, dtype=NP.float64) - voxel_truth = (80.0, 90.0, 100.0, 110.0) - match = (voxel_truth==voxel_means).all() - assert_equal(match, True) - - return - - def test_texture1(self): - # [1] texture1 is delta functions and confirm the - # filter result is outer product of the L kernel - M, Laws_LL = run_texture1() - match = (Laws_LL==M).all() - assert_equal(match, True) - return - - def test_texture2(self): - # [2] texture2 is 2 plane waves and assert the 20-element feature - # vector for each disc is correct - tem = run_texture2() - tem0 = tem[0] - tem1 = tem[1] - truth_tem0 = NP.array( - [ 0. , 0. , 0. , 0. , 0. , - 0. , 0.13306101, 0.08511007, 0.05084148, 0.07550675, - 0.4334695 , 0.03715914, 0.00289055, 0.02755581, 0.48142046, - 0.03137803, 0.00671277, 0.51568902, 0.01795249, 0.49102375, 1. - ], dtype=NP.float32) - truth_tem1 = NP.array( - [ 0. , 0. , 0. , 0. , 0. , - 0. , 0.02970393, 0.00164266, 0.00922416, 0.01221788, - 0.51485199, 0.03298925, 0.02212243, 0.01912871, 0.48350537, - 0.01125561, 0.00826189, 0.49437219, 0.00526817, 0.49736592, 1. - ], dtype=NP.float32) - - assert_array_almost_equal(tem0, truth_tem0, decimal=6) - assert_array_almost_equal(tem1, truth_tem1, decimal=6) - - return - -if __name__ == "__main__": - nose.runmodule() - From scipy-svn at scipy.org Mon Aug 11 19:10:38 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 11 Aug 2008 18:10:38 -0500 (CDT) Subject: [Scipy-svn] r4639 - trunk/scipy/stats Message-ID: <20080811231038.247C039C107@scipy.org> Author: jarrod.millman Date: 2008-08-11 18:10:28 -0500 (Mon, 11 Aug 2008) New Revision: 4639 Removed: trunk/scipy/stats/models/ Modified: trunk/scipy/stats/setup.py trunk/scipy/stats/setupscons.py Log: remove models code because it isn't ready for release Modified: trunk/scipy/stats/setup.py =================================================================== --- trunk/scipy/stats/setup.py 2008-08-11 23:08:56 UTC (rev 4638) +++ trunk/scipy/stats/setup.py 2008-08-11 23:10:28 UTC (rev 4639) @@ -6,7 +6,6 @@ from numpy.distutils.misc_util import Configuration config = Configuration('stats', parent_package, top_path) - config.add_subpackage('models') config.add_data_dir('tests') config.add_library('statlib', Modified: trunk/scipy/stats/setupscons.py =================================================================== --- trunk/scipy/stats/setupscons.py 2008-08-11 23:08:56 UTC (rev 4638) +++ trunk/scipy/stats/setupscons.py 2008-08-11 23:10:28 UTC (rev 4639) @@ -7,7 +7,6 @@ config = Configuration('stats', parent_package, top_path) config.add_sconscript('SConstruct') - config.add_subpackage('models') config.add_data_dir('tests') return config From scipy-svn at scipy.org Mon Aug 11 19:12:22 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 11 Aug 2008 18:12:22 -0500 (CDT) Subject: [Scipy-svn] r4640 - trunk/scipy/io Message-ID: <20080811231222.3FCF139C107@scipy.org> Author: oliphant Date: 2008-08-11 18:12:21 -0500 (Mon, 11 Aug 2008) New Revision: 4640 Modified: trunk/scipy/io/wavfile.py Log: Fix 64-bit issue for wav-file reading. Modified: trunk/scipy/io/wavfile.py =================================================================== --- trunk/scipy/io/wavfile.py 2008-08-11 23:10:28 UTC (rev 4639) +++ trunk/scipy/io/wavfile.py 2008-08-11 23:12:21 UTC (rev 4640) @@ -4,7 +4,7 @@ # assumes file pointer is immediately # after the 'fmt ' id def _read_fmt_chunk(fid): - res = struct.unpack('lhHLLHH',fid.read(20)) + res = struct.unpack('ihHIIHH',fid.read(20)) size, comp, noc, rate, sbytes, ba, bits = res if (comp != 1 or size > 16): print "Warning: unfamiliar format bytes..." @@ -96,7 +96,7 @@ bits = data.dtype.itemsize * 8 sbytes = rate*(bits / 8)*noc ba = noc * (bits / 8) - fid.write(struct.pack('lhHLLHH', 16, 1, noc, rate, sbytes, ba, bits)) + fid.write(struct.pack('ihHIIHH', 16, 1, noc, rate, sbytes, ba, bits)) # data chunk fid.write('data') fid.write(struct.pack('i', data.nbytes)) From scipy-svn at scipy.org Mon Aug 11 20:11:34 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 11 Aug 2008 19:11:34 -0500 (CDT) Subject: [Scipy-svn] r4641 - in branches/Interpolate1D: . docs tests Message-ID: <20080812001134.D0DBA39C144@scipy.org> Author: fcady Date: 2008-08-11 19:11:21 -0500 (Mon, 11 Aug 2008) New Revision: 4641 Modified: branches/Interpolate1D/docs/tutorial.rst branches/Interpolate1D/interpolate1d.py branches/Interpolate1D/interpolate2d.py branches/Interpolate1D/interpolateNd.py branches/Interpolate1D/tests/test_interpolate2d.py Log: some small changes after talking to Eric. More to be made tomorrow Modified: branches/Interpolate1D/docs/tutorial.rst =================================================================== --- branches/Interpolate1D/docs/tutorial.rst 2008-08-11 23:12:21 UTC (rev 4640) +++ branches/Interpolate1D/docs/tutorial.rst 2008-08-12 00:11:21 UTC (rev 4641) @@ -429,32 +429,38 @@ code for working with splines. However, Interpolate1d only wraps a part of this functionality. For some tasks, it is good to be able to directly access this power. -This section describes the operation of the Spline class. +This section provides a brief introduction to the mathematics of splines +and describes the operation of the Spline class. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Intro to Splines ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Splines are a class of functions which +Splines are a class of functions which + #) are easy and quick to evaluate, #) can be fitted to any 1D data, and #) are quite smooth -#) do not show the pathological Runge's phenomenon which mares polynomial fits +#) do not show the pathological Runge's phenomenon which mars polynomial fits + Thus, they are ideal for interpolation if we need something smoother than a simple linear fit. This is the barest of mathematical primers on splines; -more information is readily available on the internet. +more information is readily available on the internet. Wikipedia, for example, has +a very accessible but reasonably thorough treatment_ of splines and their use +in interpolation. +.. _treatment : http://en.wikipedia.org/wiki/Spline_interpolation Mathematically, a spline function S of order k is defined relative to a sequence of "knots", x1, x2, ..., xn. On every interval [xi, x_{i-1}], S is a polynomial of order at most k (it is from this that the ease and speed -of splines arises). At a knot, where two of the polynomials meet, they are required to agree in the first -k-1 derivatives (ie all but the last). A spline is specified by the locations of its knots and the coefficients -of its polynomial in each interval. +of splines arises, since polynomials are easy to work with). At a knot, where two of the polynomials meet, +they are required to agree in the first k-1 derivatives (ie all but the highest). A spline is specified by the +locations of its knots and, for each interval, the coefficients of polynomial that describes it. For interpolation purposes, the knots are typically chosen to be the known data points. It is also common for splines to include smoothing of data, so that the curve does not pass through all the data points but is smoother than it would be if it had to. k=3 is the most -common order of spline used in interpolation, and is often called a cubic spline. +common order of spline used in interpolation, and is often called a 'cubic' or 'natural' spline spline. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Basic Usage Modified: branches/Interpolate1D/interpolate1d.py =================================================================== --- branches/Interpolate1D/interpolate1d.py 2008-08-11 23:12:21 UTC (rev 4640) +++ branches/Interpolate1D/interpolate1d.py 2008-08-12 00:11:21 UTC (rev 4641) @@ -10,22 +10,22 @@ # dictionary of interpolation functions/classes/objects method_register = \ { # functions - 'linear' : linear, 'Linear' : linear, - 'logarithmic' : logarithmic, 'Logarithmic' : logarithmic, - 'block' : block, 'Block' : block, - 'block_average_above' : block_average_above, - 'Block_average_above' : block_average_above, - 'nearest' : nearest, 'Nearest' : nearest, + 'linear' : linear, + 'logarithmic' : logarithmic, + 'block' : block, + 'block_average_above' : block_average_above, + 'nearest' : nearest, # Splines - 'Spline' : Spline, 'spline' : Spline, - 'Quadratic' : Spline(k=2), 'quadratic' : Spline(k=2), - 'Quad' : Spline(k=2), 'quad' : Spline(k=2), - 'Cubic' : Spline(k=3), 'cubic' : Spline(k=3), - 'Quartic' : Spline(k=4), 'quartic' : Spline(k=4), - 'Quar' : Spline(k=4), 'quar' : Spline(k=4), - 'Quintic' : Spline(k=5), 'quintic' : Spline(k=5), - 'Quin' : Spline(k=5), 'quin' : Spline(k=5) + 'spline' : Spline, + 'quadratic' : Spline(k=2), + 'quad' : Spline(k=2), + 'cubic' : Spline(k=3), + 'quartic' : Spline(k=4), + 'quar' : Spline(k=4), + 'quintic' : Spline(k=5), + 'quin' : Spline(k=5), + 'natural': Spline(k=3), } # dictionary of types for casting. key = possible datatype, value = datatype it is cast to @@ -56,6 +56,10 @@ interpolate from. Note that 2-dimensional y is not currently supported. + newx -- list of 1D numpy array + x values at which to interpolate the value + of the function + Optional Arguments ------------------- @@ -159,6 +163,10 @@ y includes the y-values for the data set to interpolate from. Note that 2-dimensional y is not supported. + + newx -- list of 1D numpy array + x values at which to interpolate the value + of the function Optional Arguments ------------------- @@ -306,7 +314,7 @@ # primary usage : user passes a string indicating a known function # pick interpolator accordingly if isinstance(interp_arg, basestring): - interpolator = method_register.setdefault(interp_arg, None ) + interpolator = method_register.setdefault(interp_arg.lower(), None ) if interpolator is None: raise TypeError, "input string %s not valid" % interp_arg else: Modified: branches/Interpolate1D/interpolate2d.py =================================================================== --- branches/Interpolate1D/interpolate2d.py 2008-08-11 23:12:21 UTC (rev 4640) +++ branches/Interpolate1D/interpolate2d.py 2008-08-12 00:11:21 UTC (rev 4641) @@ -12,16 +12,16 @@ method_register = \ { 'linear' : Spline2d(kx=1, ky=1), - 'Linear' : Spline2d(kx=1, ky=1), - 'Spline' : Spline2d(), 'spline' : Spline2d(), - 'Quadratic' : Spline2d(kx=2, ky=2), 'quadratic' : Spline2d(kx=2, ky=2), - 'Quad' : Spline2d(kx=2, ky=2), 'quad' : Spline2d(kx=2, ky=2), - 'Cubic' : Spline2d(kx=3, ky=3), 'cubic' : Spline2d(kx=3, ky=3), - 'Quartic' : Spline2d(kx=4, ky=4), 'quartic' : Spline2d(kx=4, ky=4), - 'Quar' : Spline2d(kx=4, ky=4), 'quar' : Spline2d(kx=4, ky=4), - 'Quintic' : Spline2d(kx=5, ky=5), 'quintic' : Spline2d(kx=5, ky=5), - 'Quin' : Spline2d(kx=5, ky=5), 'quin' : Spline2d(kx=5, ky=5), + 'spline' : Spline2d(), + 'quadratic' : Spline2d(kx=2, ky=2), + 'quad' : Spline2d(kx=2, ky=2), + 'cubic' : Spline2d(kx=3, ky=3), + 'quartic' : Spline2d(kx=4, ky=4), + 'quar' : Spline2d(kx=4, ky=4), + 'quintic' : Spline2d(kx=5, ky=5), + 'quin' : Spline2d(kx=5, ky=5), '526' : algorithm526, 'algorithm526':algorithm526, + 'natural' : Spline2d(kx=3, ky=3), } # dictionary of types for casting. key = possible datatype, value = datatype it is cast to @@ -177,7 +177,7 @@ # primary usage : user passes a string indicating a known function # pick interpolator accordingly if isinstance(method, basestring): - interpolator = method_register.setdefault(method, None ) + interpolator = method_register.setdefault(method.lower(), None ) if interpolator is None: raise TypeError, "input string %s not valid" % method else: Modified: branches/Interpolate1D/interpolateNd.py =================================================================== --- branches/Interpolate1D/interpolateNd.py 2008-08-11 23:12:21 UTC (rev 4640) +++ branches/Interpolate1D/interpolateNd.py 2008-08-12 00:11:21 UTC (rev 4641) @@ -131,12 +131,21 @@ # The array interpolation is handled by the C extension _nd_image. def __init__(self, data, starting_coords =None, spacings = None, kind='linear', out=NaN): - """ data = array or list of lists - starting_coords = None, list, 1D array or 2D (nx1) array - spacings = None, list, 1D array or 2D (nx1) array - kind = string or integer - 0 = block extrapolation between midpoints - out = string in 'nearest', 'wrap', 'reflect', 'mirror', 'constant' + """ Parameters + ----------- + data = array or list of lists + + Optional Parameters + ------------------- + starting_coords = None, list, 1D array or 2D (nx1) array + spatial coordinate where data[0,..., 0] is measured. + Defaults to zeros. + spacings = None, list, 1D array or 2D (nx1) array + spacings[i] is spacing along axis i + defaults to all ones + kind = string or integer + indicates type of interpolation to perform + out = string in 'nearest', 'wrap', 'reflect', 'mirror', 'constant' or just NaN """ @@ -167,32 +176,25 @@ 1:1, '1':1, 'linear':1, - 'Linear':1, 2:2, '2':2, 'quadratic':2, 'quad':2, - 'Quadratic':2, - 'Quad':2, 3:3, '3':3, 'spline':3, - 'Spline':3, 'cubic':3, - 'Cubic':3, + 'natural':3, 4:4, '4':4, 'quartic':4, - 'Quartic':4, 5:5, '5':5, 'quintic':5, 'quint':5, - 'Quintic':5, - 'Quint':5 } - if order_dict.has_key(kind): - self.order = order_dict[kind] + if order_dict.has_key(str(kind).lower()): + self.order = order_dict[str(kind).lower()] elif isinstance(kind, int): raise ValueError, "Only spline orders 0, 1, ..., 5 are supported" else: @@ -289,7 +291,10 @@ return num_indices_in_bounds == self.ndim def _spline_filter(self, data, order = 3): - """ Multi-dimensional spline filter. + """ This step is required by the extension module. I (Field Cady) + do not fully understand why. + + Multi-dimensional spline filter. Note: The multi-dimensional filter is implemented as a sequence of one-dimensional spline filters. The intermediate arrays are stored Modified: branches/Interpolate1D/tests/test_interpolate2d.py =================================================================== --- branches/Interpolate1D/tests/test_interpolate2d.py 2008-08-11 23:12:21 UTC (rev 4640) +++ branches/Interpolate1D/tests/test_interpolate2d.py 2008-08-12 00:11:21 UTC (rev 4641) @@ -129,7 +129,7 @@ def test_string_linear(self): """ make sure : string 'linear' works """ - N = 700 + N = 7 X, Y = meshgrid(arange(N), arange(N)) Z = X + Y x, y, z = map(ravel, [X, Y, Z] ) @@ -145,7 +145,7 @@ def test_string_quadratic(self): """ make sure : string 'quadratic' works """ - N = 700 + N = 7 X, Y = meshgrid(arange(N), arange(N)) Z = X + Y x, y, z = map(ravel, [X, Y, Z] ) @@ -161,7 +161,7 @@ def test_string_cubic(self): """make sure : string "cubic" works """ - N = 700 + N = 7 X, Y = meshgrid(arange(N), arange(N)) Z = X + Y x, y, z = map(ravel, [X, Y, Z] ) @@ -178,7 +178,7 @@ """ make sure : keyword '526' works ie that TOMS algorithm 526 works """ - N = 700 + N = 7 X, Y = meshgrid(arange(N), arange(N)) Z = X + Y x, y, z = map(ravel, [X, Y, Z] ) From scipy-svn at scipy.org Tue Aug 12 13:15:20 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 12 Aug 2008 12:15:20 -0500 (CDT) Subject: [Scipy-svn] r4642 - branches/Interpolate1D/docs Message-ID: <20080812171520.7225339C107@scipy.org> Author: fcady Date: 2008-08-12 12:15:10 -0500 (Tue, 12 Aug 2008) New Revision: 4642 Added: branches/Interpolate1D/docs/geology_dataset1.txt branches/Interpolate1D/docs/optimization.png branches/Interpolate1D/docs/plot_temp_vs_depth.png branches/Interpolate1D/docs/plot_temp_vs_depth_clean.png branches/Interpolate1D/docs/spline.png branches/Interpolate1D/docs/thickness_data.dat Modified: branches/Interpolate1D/docs/tutorial.rst Log: prettier tutorial, including better examples and more pictures Added: branches/Interpolate1D/docs/geology_dataset1.txt =================================================================== --- branches/Interpolate1D/docs/geology_dataset1.txt 2008-08-12 00:11:21 UTC (rev 4641) +++ branches/Interpolate1D/docs/geology_dataset1.txt 2008-08-12 17:15:10 UTC (rev 4642) @@ -0,0 +1,10 @@ +1.499536604568347800e+000 1.658453575548198300e-001 +3.697762547686129800e+000 3.994002011895560500e-001 +4.093644614730469500e+000 4.393270321822482200e-001 +7.671079003802294200e+000 1.000000000000000000e+003 +8.269696620589108700e+000 7.949075438330595000e-001 +1.007630409931378800e+001 8.999214508357034100e-001 +1.263468232585750100e+001 9.860973953103480100e-001 +1.312256663311384800e+001 9.936523208151388800e-001 +1.659125799620406700e+001 1.000000000000000000e+003 +1.939929889697446800e+001 8.338880137988362600e-001 Property changes on: branches/Interpolate1D/docs/geology_dataset1.txt ___________________________________________________________________ Name: svn:executable + * Added: branches/Interpolate1D/docs/optimization.png =================================================================== (Binary files differ) Property changes on: branches/Interpolate1D/docs/optimization.png ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: branches/Interpolate1D/docs/plot_temp_vs_depth.png =================================================================== (Binary files differ) Property changes on: branches/Interpolate1D/docs/plot_temp_vs_depth.png ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: branches/Interpolate1D/docs/plot_temp_vs_depth_clean.png =================================================================== (Binary files differ) Property changes on: branches/Interpolate1D/docs/plot_temp_vs_depth_clean.png ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: branches/Interpolate1D/docs/spline.png =================================================================== (Binary files differ) Property changes on: branches/Interpolate1D/docs/spline.png ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: branches/Interpolate1D/docs/thickness_data.dat =================================================================== --- branches/Interpolate1D/docs/thickness_data.dat 2008-08-12 00:11:21 UTC (rev 4641) +++ branches/Interpolate1D/docs/thickness_data.dat 2008-08-12 17:15:10 UTC (rev 4642) @@ -0,0 +1,10 @@ +9.424048978739288900e-001 -9.508761403068971800e+000 +9.998766914279348900e-001 -9.895012964291035800e+000 +1.127952820779362300e+000 -3.904822709859180600e+000 +1.157936681816710500e+000 -1.605861744330539200e+000 +1.202510554645833900e+000 1.940671938130194500e+000 +1.314422096865679900e+000 8.869036982549690900e+000 +1.398645599167923900e+000 9.813198077596094700e+000 +1.458882224612567200e+000 7.804047162000441200e+000 +1.545769275246878100e+000 1.988814246858684700e+000 +1.603025472727923000e+000 -2.549859447665460800e+000 Property changes on: branches/Interpolate1D/docs/thickness_data.dat ___________________________________________________________________ Name: svn:executable + * Modified: branches/Interpolate1D/docs/tutorial.rst =================================================================== --- branches/Interpolate1D/docs/tutorial.rst 2008-08-12 00:11:21 UTC (rev 4641) +++ branches/Interpolate1D/docs/tutorial.rst 2008-08-12 17:15:10 UTC (rev 4642) @@ -95,14 +95,14 @@ There is a large selection of strings which specify a range of interpolation methods. The list includes: -#. 'linear' : linear interpolation, same as the default -#. 'block' : "round new_x down" to the nearest values where we know y. -#. 'nearest' : take the y value of the nearest point -#. 'logarithmic' : logarithmic interpolation (linear in log(y) ) -#. 'spline' : spline interpolation of default order (currently 3) -#. 'cubic' : 3rd order spline interpolation -#. 'quartic' : 4th order spline interpolation -#. 'quintic' : 5th order spline interpolation +#) 'linear' : linear interpolation, same as the default +#) 'block' : "round new_x down" to the nearest values where we know y. +#) 'nearest' : take the y value of the nearest point +#) 'logarithmic' : logarithmic interpolation (linear in log(y) ) +#) 'spline' : spline interpolation of default order (currently 3) +#) 'cubic' : 3rd order spline interpolation +#) 'quartic' : 4th order spline interpolation +#) 'quintic' : 5th order spline interpolation The same flexibility is afforded for extrapolation by the keywords low and high, which specify how to treat values below and above the range of known data: :: @@ -315,16 +315,20 @@ and 2) estimate the average temperature. :: - In []: data_array = loadtxt('dataset1.txt') + In []: data_array = loadtxt('geology_dataset1.txt') In []: shape(data_array) Out []: (12, 2) In []: depth = data_array[:,0] In []: temp = data_array[:,1] In []: max(depth) - Out []: 20 + Out []: 19.39929 In []: plot(depth, temp) +.. image :: plot_temp_vs_depth.png + +:: + # He realizes that many of the temperatures are 1000, indicating # a measurement error, which makes it look terrible. # And what is there doesn't look smooth @@ -332,8 +336,12 @@ In []: import interpolate as I In []: plot( I.interp1d(depth, temp, linspace(0,20,100), bad_data = [1000]) # much better, but he wants to see it smoother too - In []: plot( I.interp1d(depth, temp, linspace(0,20,100), kind='cubic', bad_data = [1000]) + In []: plot( I.interp1d(depth, temp, linspace(0,20,100), kind='cubic', bad_data = [1000])) +.. image :: plot_temp_vs_depth_clean.png + +:: + # To find the average temp he can't average the data points because the samples # are not necessarily uniform, but it is easy to uniformly sample the interpolated function In []: average_temp = average( I.interp1d(depth, temp, linspace(0,20,100), 'cubic', bad_data=[1000]) ) @@ -397,7 +405,7 @@ prototype, and repeat. If she does this, she can "zoom in" on the optimal thickness. :: - In []: data_array = loadtxt('data.dat') + In []: data_array = loadtxt('thickness_data.dat') In []: thickness = data_array[:,0] In []: performance = data_array[:,1] In []: new_thick = linspace( min(thickness), max(thickness), 200 ) @@ -406,11 +414,20 @@ # somewhat expensive, making prototypes is much more so In []: new_perf = interp1d(thickness, performance, new_thick, kind = 'quintic') In []: guess_perf = max(new_perf) - In []: guess_thick = new_thick( find( new_perf == best_perf ) ) + In []: guess_thick = new_thick[ find( new_perf == guess_perf ) ] In []: len(guess_thick) Out []: 1 # make sure she only got one answer. + # To get a feel, she plots the data, the interpolated curve, and the + # estimated optimal point + In []: plot(thickness, performance, 'r', new_thick, new_perf) + In []: scatter(guess_thick, [guess_perf], marker='>') #guess_perf in braces to make iterable + +.. image :: optimization.png + +:: - # At this point she builds the prototype and calculates its performance. + # Now she builds the prototype using the estimated optimal thickness + # and measures its performance. # She wants to re-insert it into the array and interpolate again In []: measured_perf = 10.7 #the measured performance In []: where_to_insert = max( find(thickness < guess_thick) ) +1 @@ -457,6 +474,11 @@ they are required to agree in the first k-1 derivatives (ie all but the highest). A spline is specified by the locations of its knots and, for each interval, the coefficients of polynomial that describes it. +Below is a simple cubic spline, with the knots indicated by red dots. The third derivative is not +continuous at these points, but it is not visualy apparent; the curve appears smooth. + +.. image :: spline.png + For interpolation purposes, the knots are typically chosen to be the known data points. It is also common for splines to include smoothing of data, so that the curve does not pass through all the data points but is smoother than it would be if it had to. k=3 is the most @@ -476,7 +498,7 @@ In []: new_x = linspace(0, 2*pi, 40) In []: plot(x, y, 'r', new_x, interp(new_x), 'g') -..image :: spline_of_sin.png +.. image :: spline_of_sin.png Notice that the resulting curve is extremely smooth. It is this smoothness that makes splines in general (and cubic splines in particular) so sought after. @@ -493,23 +515,24 @@ At instantiation: -#. bbox -This is a 2-element list specifying the endpoints of the approximation interval. -It default to [x[0],x[-1]] -#. w -a 1D sequence of weights which defaults to all ones. -#. s -If s is zero, the interpolation is exact. If s is not 0, the curve is smoothe subject to -the constraint that sum((w[i]*( y[i]-s(x[i]) ))**2,axis=0) <= s +#) bbox + This is a 2-element list specifying the endpoints of the approximation interval. + It default to [x[0],x[-1]] +#) w + List of non-negative weights indicating the "importance" of each data point. + Not relevant unless s is not zero. +#) s + If s is zero, the interpolation is exact. If s is not 0, the curve is smoothe subject to + the constraint that sum((w[i]*( y[i]-s(x[i]) ))**2,axis=0) <= s BEWARE : in the current implementation of the code, if s is small but not zero, - instantiating Spline can become painfully slow. +instantiating Spline can become painfully slow. At calling: -#. nu -Spline returns, not the spline function S, but the (nu)th derivative of S. nu defaults -to 0, so Spline usually returns the zeroth derivative of S, ie S. +#) nu + Spline returns, not the spline function S, but the (nu)th derivative of S. nu defaults + to 0, so Spline usually returns the zeroth derivative of S, ie S. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -518,19 +541,19 @@ The following special methods are also available, which are not wrapped by Interpolate1d : -#. set_smoothing_factor(s = 0.0) -#. get_knots +#) set_smoothing_factor(s = 0.0) +#) get_knots returns the positions of the knots of the spline -#. get_coeffs +#) get_coeffs returns the coefficients of the -#. get_residual - returns the weighted sum of the errors (due to smoothing) at the data points - sum((w[i]*( y[i]-s(x[i]) ))**2,axis=0) -#. integral(a, b) +#) get_residual + returns the weighted sum of the squared errors (due to smoothing) at the data points: + sum( w[i]*( y[i]-s(x[i]) )^2 ) +#) integral(a, b) returns the integral from a to b -#. derivatives(x) +#) derivatives(x) returns all the derivatives of the spline at point x -#. roots +#) roots This only works for cubic splines. But it returns the places where the spline is identically zero. @@ -539,10 +562,8 @@ 2D Interpolation ================================================ -*[This is being written preemptively]* - In 2D interpolation, known data are of the form (x, y, z), and we interpolate -z_new from (x_new, y_new). +newz at the point(s) (newx, newy). As in the case of 1D interpolation, there is a convenient functional interface for 2D interpolation as well as a callable object which can be more efficient. @@ -560,17 +581,17 @@ If they are scalars or zero-dimensional arrays, newz will be a scalar as well. Otherwise a vector is returned. The only differences from intper1d are -#. The known data points are specified by 3 arrays (x, y and z) rather than 2 (x and y). +#) The known data points are specified by 3 arrays (x, y and z) rather than 2 (x and y). z is the dependent variable, while x and y are independent variables. -#. Where to interpolate values is specified by two arrays, newx and newy, rather +#) Where to interpolate values is specified by two arrays, newx and newy, rather than only one array. -#. The extrapolation keywords "low" and "high" are replaced by the single keyword "out" +#) The extrapolation keywords "low" and "high" are replaced by the single keyword "out" for out-of-bounds. -#. Not all of the same keyword arguments are available for 1D and 2D. The main ones like +#) Not all of the same keyword arguments are available for 1D and 2D. The main ones like 'linear', 'cubic' and 'spline', however, work in both cases, and we try to give analogous methods the same name. But some methods are particular to, or have only been written for, one praticular dimensionality. -#. In particular, 2D supports the keywork '526', which implements TOMS algorithm 526. +#) In particular, 2D supports the keywork '526', which implements TOMS algorithm 526. See below for more information. As in 1D, linear interpolation is used by default, while out of bounds returns NaN. From scipy-svn at scipy.org Tue Aug 12 15:15:14 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 12 Aug 2008 14:15:14 -0500 (CDT) Subject: [Scipy-svn] r4643 - in branches/Interpolate1D: . docs Message-ID: <20080812191514.67E4339C05F@scipy.org> Author: fcady Date: 2008-08-12 14:15:11 -0500 (Tue, 12 Aug 2008) New Revision: 4643 Added: branches/Interpolate1D/docs/README.txt Modified: branches/Interpolate1D/docs/tutorial.rst branches/Interpolate1D/interpolate2d.py branches/Interpolate1D/setup.py Log: added README.txt file that describes organization of the module so that future developers can understand the design and rational behind it easily. Added: branches/Interpolate1D/docs/README.txt =================================================================== --- branches/Interpolate1D/docs/README.txt 2008-08-12 17:15:10 UTC (rev 4642) +++ branches/Interpolate1D/docs/README.txt 2008-08-12 19:15:11 UTC (rev 4643) @@ -0,0 +1,71 @@ +README + + +This file contains information about the architecture (not the api) of the module +and license information. It is designed mostly for developers who need to +understand the organization of the files, extensions, etc and the logic (or lack thereof) +behind them so that they can continue development of the module. + +The key the understanding the module is to understand where it came from. +Interpolation code in a variety of different forms for a variety of different purposes +had been spread throughout the various parts of Enthought code. The goal was to +collect these various pieces of code and combine them into one module with a +reasonable, intuitive api. But under the hood, there are several extension +modules whose functionalities overlap or do not naturally dovetail. + +Main Files: +interpolate1d.py : + Contains the Interpolate1d class and the interp1d functional wrapper + around it. This mostly provides a user-interface; the user passes in + keywords, and according to those keywords, Interpolate1d will call functions + and classes in the wrapper files. +interpolate2d.py : + Completely analogous to interpolate1d.py. A user interface that calls machinery + in the wrapper files. Its organization is also almost completely analogous to + that of interpolate1d.py. +interpolateNd.py : + This file doubles as a user interface and wrapper file around the _nd_image + extension. Interpolate1d and 2d are both operated by inputting lists of + points, which is pretty generic and lends itself to removing bad data etc. + But the _nd_image extension requires a uniform grid, so this file only performs + interpolation with the _nd_image extension. _nd_image interpolates array entries, + so this file handles 1) formatting, and 2) translations between spatial coordinates and + array indices. + + The spline filtering step is carried over from ndimage, and is necessary to make + the extension module work properly. In the future, it could be good to modify + the _nd_image module to include this annoying step itself and hide it from the + developer. + +Wrapper files: +fitpack_wrapper.py : + This file provides the Spline and Spline2d classes which provide a variety of 1d and + 2d spline functions. It is these classes which are accessed by Interpolate1d and + Interpolate2d, but note that only part of their functionality is accessed. Things like + smoothing and seeing spline coefficients are supported by Spline and Spline2d but to + exported. Internally, these classes call the _dfitpack extension. + + This is based on code that was in scipy.interpolate. Much of the functionality that was + in scipy.interpolate is not reproduced here. + +interpolate_wrapper.py : + A variety of 1d interpolation functions. Most of them are just wrappers around _interpolate, + but others are stand-alone. + +algorithm526_wrapper.py : + very simple interface to the _interp_526 module. The main reason for the new file is so + that the imported function is recognized by Interpolate2d as a function, rather than a + Fortran object so that _init_xyz works. + +Extensions: +_dfitpack : + Fortran extension module. This wraps part of the functionality of the fitpack library. +_interpolate : + C extension module with basic functions. +_nd_image : + C extensions module. It uses spline interpolation of various orders to interpolate entries + in an array. +_interp_526 : + Fortran extension module implementing TOMS Algorithm 526. Taken from the Pore Pressure + project. + Property changes on: branches/Interpolate1D/docs/README.txt ___________________________________________________________________ Name: svn:executable + * Modified: branches/Interpolate1D/docs/tutorial.rst =================================================================== --- branches/Interpolate1D/docs/tutorial.rst 2008-08-12 17:15:10 UTC (rev 4642) +++ branches/Interpolate1D/docs/tutorial.rst 2008-08-12 19:15:11 UTC (rev 4643) @@ -23,6 +23,8 @@ them at work in realistic sample sessions. These sessions demonstrate how to use the interpolate module, but also highlight some of the uses of interpolation techniques. + + ====================== 1D Interpolation ====================== @@ -85,7 +87,7 @@ Out []: array([ NaN, NaN, 0.63661977, 0.72676046]) If we want a type of interpolation other than linear, there is a range of options which we can specify -with the keyword argument "kind", which is usually a string. Continuing from the previous example,:: +with the keyword argument "kind", which is usually a (non-case-sensitive) string. Continuing from the previous example,:: # If we want quadratic (2nd order) spline interpolation, we can use the string 'quadratic' In []: new_y_quadratic = interp1d(x, y, new_x, kind = 'quadratic') @@ -738,5 +740,5 @@ Still in development. Ideally the range of interpolation would be the convex hull of the known - data points, and a Delaunay triangulation would be determined and stored - at instantiation. Then again, that would be VERY expensive. \ No newline at end of file + data points, and a Delaunay tesselation would be determined and stored + at instantiation. Then again, that would be very expensive. \ No newline at end of file Modified: branches/Interpolate1D/interpolate2d.py =================================================================== --- branches/Interpolate1D/interpolate2d.py 2008-08-12 17:15:10 UTC (rev 4642) +++ branches/Interpolate1D/interpolate2d.py 2008-08-12 19:15:11 UTC (rev 4643) @@ -9,6 +9,7 @@ return np.atleast_1d( np.ascontiguousarray(ary, dtype) ) # dictionary of interpolation functions/classes/objects +# keys are possible values of keyword "kind" method_register = \ { 'linear' : Spline2d(kx=1, ky=1), @@ -16,24 +17,28 @@ 'quadratic' : Spline2d(kx=2, ky=2), 'quad' : Spline2d(kx=2, ky=2), 'cubic' : Spline2d(kx=3, ky=3), + 'natural' : Spline2d(kx=3, ky=3), 'quartic' : Spline2d(kx=4, ky=4), 'quar' : Spline2d(kx=4, ky=4), 'quintic' : Spline2d(kx=5, ky=5), 'quin' : Spline2d(kx=5, ky=5), '526' : algorithm526, 'algorithm526':algorithm526, - 'natural' : Spline2d(kx=3, ky=3), } # dictionary of types for casting. key = possible datatype, value = datatype it is cast to # BEWARE : if you cast things to integers, you will lose interpolation ability -dtype_register = {np.float32 : np.float32, - np.float64 : np.float64 - } +dtype_register = { + np.float32 : np.float32, + np.float64 : np.float64 + } +# input will be cast to this type if it's not a key in dtype_register dtype_default = np.float64 +# functional interface: creates and calls an instance of objective interface def interp2d(x, y, z, newx, newy, kind='linear', out=NaN, bad_data=None): return Interpolate2d(x, y, z, kind=kind, out=out, bad_data=bad_data)(newx, newy) - + +# objective interface class Interpolate2d: """ A callable class for interpolation of 1D, real-valued data. @@ -141,14 +146,6 @@ def _init_xyz(self, x, y, z, bad_data): # FIXME : perhaps allow 2D input if it is inthe form of meshgrid - - if bad_data is not None: - try: # check that bad_data contains only numerical values - sum_of_bad_data = sum(bad_data) - except: - raise TypeError, "bad_data must be either None \ - or a list of numbers" - x, y, z = self._remove_bad_data(x, y, z, bad_data) # check acceptable sizes and dimensions x = np.atleast_1d(x) @@ -160,6 +157,15 @@ assert z.ndim == 1 , "z must be one-dimensional" assert len(x) == len(y) , "x and y must be of the same length" assert len(x) == len(z) , "x and z must be of the same length" + + # remove bad data if applicable + if bad_data is not None: + try: # check that bad_data contains only numerical values + sum_of_bad_data = sum(bad_data) + except: + raise TypeError, "bad_data must be either None \ + or a list of numbers. Sorry." + x, y, z = self._remove_bad_data(x, y, z, bad_data) # select proper dataypes and make arrays self._xdtype = dtype_register.setdefault(type(x[0]), dtype_default) Modified: branches/Interpolate1D/setup.py =================================================================== --- branches/Interpolate1D/setup.py 2008-08-12 17:15:10 UTC (rev 4642) +++ branches/Interpolate1D/setup.py 2008-08-12 19:15:11 UTC (rev 4643) @@ -41,7 +41,7 @@ ) # implements algorithm 526 for 2D interpolation - config.add_extension('interp_526', + config.add_extension('_interp_526', sources = ['extensions/interp_526a.pyf', 'extensions/interp_526.f'] ) From scipy-svn at scipy.org Tue Aug 12 15:20:32 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 12 Aug 2008 14:20:32 -0500 (CDT) Subject: [Scipy-svn] r4644 - branches/Interpolate1D/extensions Message-ID: <20080812192032.81BD439C021@scipy.org> Author: fcady Date: 2008-08-12 14:20:31 -0500 (Tue, 12 Aug 2008) New Revision: 4644 Modified: branches/Interpolate1D/extensions/interp_526a.pyf Log: renamed interp_526 module _interp_526 Modified: branches/Interpolate1D/extensions/interp_526a.pyf =================================================================== --- branches/Interpolate1D/extensions/interp_526a.pyf 2008-08-12 19:15:11 UTC (rev 4643) +++ branches/Interpolate1D/extensions/interp_526a.pyf 2008-08-12 19:20:31 UTC (rev 4644) @@ -1,9 +1,9 @@ ! -*- f90 -*- ! Note: the context of this file is case sensitive. -python module interp_526 ! in +python module _interp_526 ! in ! blubber foo bar - interface ! in :interp_526 + interface ! in :_interp_526 subroutine idbvip(md,ncp,ndp,xd,yd,zd,nip,xi,yi,zi,iwk,wk) ! in :interp_526:interp_526a.f integer optional,check((md>=1)&&(md<=3)):: md = 1 integer optional,check((ncp>=2)&&(ncp Author: wnbell Date: 2008-08-14 15:44:07 -0500 (Thu, 14 Aug 2008) New Revision: 4645 Modified: trunk/scipy/sparse/sparsetools/bsr.py trunk/scipy/sparse/sparsetools/coo.py trunk/scipy/sparse/sparsetools/csc.py trunk/scipy/sparse/sparsetools/csr.py trunk/scipy/sparse/sparsetools/csr_wrap.cxx trunk/scipy/sparse/sparsetools/dia.py trunk/scipy/sparse/sparsetools/numpy.i Log: update SWIG wrappers to use PyArray_SimpleNew Modified: trunk/scipy/sparse/sparsetools/bsr.py =================================================================== --- trunk/scipy/sparse/sparsetools/bsr.py 2008-08-12 19:20:31 UTC (rev 4644) +++ trunk/scipy/sparse/sparsetools/bsr.py 2008-08-14 20:44:07 UTC (rev 4645) @@ -51,483 +51,484 @@ def bsr_diagonal(*args): + """ + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + signed char Ax, signed char Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned char Ax, unsigned char Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + short Ax, short Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned short Ax, unsigned short Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + int Ax, int Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned int Ax, unsigned int Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long long Ax, long long Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned long long Ax, unsigned long long Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + float Ax, float Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + double Ax, double Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long double Ax, long double Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, npy_cfloat_wrapper Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, npy_cdouble_wrapper Yx) + bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Yx) """ - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - signed char Ax, signed char Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned char Ax, unsigned char Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - short Ax, short Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned short Ax, unsigned short Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - int Ax, int Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned int Ax, unsigned int Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long long Ax, long long Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned long long Ax, unsigned long long Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - float Ax, float Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - double Ax, double Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long double Ax, long double Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, npy_cfloat_wrapper Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, npy_cdouble_wrapper Yx) - bsr_diagonal(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Yx) - """ - return _bsr.bsr_diagonal(*args) + return _bsr.bsr_diagonal(*args) def bsr_scale_rows(*args): + """ + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + signed char Ax, signed char Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned char Ax, unsigned char Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + short Ax, short Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned short Ax, unsigned short Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + int Ax, int Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned int Ax, unsigned int Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long long Ax, long long Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned long long Ax, unsigned long long Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + float Ax, float Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + double Ax, double Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long double Ax, long double Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx) + bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx) """ - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - signed char Ax, signed char Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned char Ax, unsigned char Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - short Ax, short Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned short Ax, unsigned short Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - int Ax, int Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned int Ax, unsigned int Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long long Ax, long long Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned long long Ax, unsigned long long Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - float Ax, float Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - double Ax, double Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long double Ax, long double Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx) - bsr_scale_rows(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx) - """ - return _bsr.bsr_scale_rows(*args) + return _bsr.bsr_scale_rows(*args) def bsr_scale_columns(*args): + """ + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + signed char Ax, signed char Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned char Ax, unsigned char Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + short Ax, short Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned short Ax, unsigned short Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + int Ax, int Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned int Ax, unsigned int Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long long Ax, long long Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned long long Ax, unsigned long long Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + float Ax, float Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + double Ax, double Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long double Ax, long double Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx) + bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx) """ - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - signed char Ax, signed char Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned char Ax, unsigned char Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - short Ax, short Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned short Ax, unsigned short Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - int Ax, int Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned int Ax, unsigned int Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long long Ax, long long Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned long long Ax, unsigned long long Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - float Ax, float Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - double Ax, double Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long double Ax, long double Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx) - bsr_scale_columns(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx) - """ - return _bsr.bsr_scale_columns(*args) + return _bsr.bsr_scale_columns(*args) def bsr_transpose(*args): + """ + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + signed char Ax, int Bp, int Bj, signed char Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned char Ax, int Bp, int Bj, unsigned char Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + short Ax, int Bp, int Bj, short Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned short Ax, int Bp, int Bj, unsigned short Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + int Ax, int Bp, int Bj, int Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned int Ax, int Bp, int Bj, unsigned int Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long long Ax, int Bp, int Bj, long long Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned long long Ax, int Bp, int Bj, unsigned long long Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + float Ax, int Bp, int Bj, float Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + double Ax, int Bp, int Bj, double Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long double Ax, int Bp, int Bj, long double Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx) + bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, int Bp, int Bj, + npy_clongdouble_wrapper Bx) """ - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - signed char Ax, int Bp, int Bj, signed char Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned char Ax, int Bp, int Bj, unsigned char Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - short Ax, int Bp, int Bj, short Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned short Ax, int Bp, int Bj, unsigned short Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - int Ax, int Bp, int Bj, int Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned int Ax, int Bp, int Bj, unsigned int Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long long Ax, int Bp, int Bj, long long Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned long long Ax, int Bp, int Bj, unsigned long long Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - float Ax, int Bp, int Bj, float Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - double Ax, int Bp, int Bj, double Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long double Ax, int Bp, int Bj, long double Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx) - bsr_transpose(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, int Bp, int Bj, - npy_clongdouble_wrapper Bx) - """ - return _bsr.bsr_transpose(*args) + return _bsr.bsr_transpose(*args) def bsr_matmat_pass2(*args): + """ + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, signed char Ax, int Bp, int Bj, signed char Bx, + int Cp, int Cj, signed char Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, unsigned char Ax, int Bp, int Bj, unsigned char Bx, + int Cp, int Cj, unsigned char Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, short Ax, int Bp, int Bj, short Bx, + int Cp, int Cj, short Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, unsigned short Ax, int Bp, int Bj, + unsigned short Bx, int Cp, int Cj, unsigned short Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, int Ax, int Bp, int Bj, int Bx, int Cp, + int Cj, int Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, unsigned int Ax, int Bp, int Bj, unsigned int Bx, + int Cp, int Cj, unsigned int Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, long long Ax, int Bp, int Bj, long long Bx, + int Cp, int Cj, long long Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, unsigned long long Ax, int Bp, int Bj, + unsigned long long Bx, int Cp, int Cj, unsigned long long Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, float Ax, int Bp, int Bj, float Bx, + int Cp, int Cj, float Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, double Ax, int Bp, int Bj, double Bx, + int Cp, int Cj, double Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, long double Ax, int Bp, int Bj, long double Bx, + int Cp, int Cj, long double Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, npy_cfloat_wrapper Ax, int Bp, int Bj, + npy_cfloat_wrapper Bx, int Cp, int Cj, npy_cfloat_wrapper Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, npy_cdouble_wrapper Ax, int Bp, int Bj, + npy_cdouble_wrapper Bx, int Cp, int Cj, + npy_cdouble_wrapper Cx) + bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, + int Aj, npy_clongdouble_wrapper Ax, int Bp, + int Bj, npy_clongdouble_wrapper Bx, int Cp, + int Cj, npy_clongdouble_wrapper Cx) """ - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, signed char Ax, int Bp, int Bj, signed char Bx, - int Cp, int Cj, signed char Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, unsigned char Ax, int Bp, int Bj, unsigned char Bx, - int Cp, int Cj, unsigned char Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, short Ax, int Bp, int Bj, short Bx, - int Cp, int Cj, short Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, unsigned short Ax, int Bp, int Bj, - unsigned short Bx, int Cp, int Cj, unsigned short Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, int Ax, int Bp, int Bj, int Bx, int Cp, - int Cj, int Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, unsigned int Ax, int Bp, int Bj, unsigned int Bx, - int Cp, int Cj, unsigned int Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, long long Ax, int Bp, int Bj, long long Bx, - int Cp, int Cj, long long Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, unsigned long long Ax, int Bp, int Bj, - unsigned long long Bx, int Cp, int Cj, unsigned long long Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, float Ax, int Bp, int Bj, float Bx, - int Cp, int Cj, float Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, double Ax, int Bp, int Bj, double Bx, - int Cp, int Cj, double Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, long double Ax, int Bp, int Bj, long double Bx, - int Cp, int Cj, long double Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, npy_cfloat_wrapper Ax, int Bp, int Bj, - npy_cfloat_wrapper Bx, int Cp, int Cj, npy_cfloat_wrapper Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, npy_cdouble_wrapper Ax, int Bp, int Bj, - npy_cdouble_wrapper Bx, int Cp, int Cj, - npy_cdouble_wrapper Cx) - bsr_matmat_pass2(int n_brow, int n_bcol, int R, int C, int N, int Ap, - int Aj, npy_clongdouble_wrapper Ax, int Bp, - int Bj, npy_clongdouble_wrapper Bx, int Cp, - int Cj, npy_clongdouble_wrapper Cx) - """ - return _bsr.bsr_matmat_pass2(*args) + return _bsr.bsr_matmat_pass2(*args) def bsr_matvec(*args): + """ + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + signed char Ax, signed char Xx, signed char Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned char Ax, unsigned char Xx, unsigned char Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + short Ax, short Xx, short Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned short Ax, unsigned short Xx, unsigned short Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + int Ax, int Xx, int Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned int Ax, unsigned int Xx, unsigned int Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long long Ax, long long Xx, long long Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned long long Ax, unsigned long long Xx, + unsigned long long Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + float Ax, float Xx, float Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + double Ax, double Xx, double Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long double Ax, long double Xx, long double Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx, + npy_cfloat_wrapper Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx, + npy_cdouble_wrapper Yx) + bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx, + npy_clongdouble_wrapper Yx) """ - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - signed char Ax, signed char Xx, signed char Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned char Ax, unsigned char Xx, unsigned char Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - short Ax, short Xx, short Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned short Ax, unsigned short Xx, unsigned short Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - int Ax, int Xx, int Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned int Ax, unsigned int Xx, unsigned int Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long long Ax, long long Xx, long long Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned long long Ax, unsigned long long Xx, - unsigned long long Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - float Ax, float Xx, float Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - double Ax, double Xx, double Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long double Ax, long double Xx, long double Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx, - npy_cfloat_wrapper Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx, - npy_cdouble_wrapper Yx) - bsr_matvec(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx, - npy_clongdouble_wrapper Yx) - """ - return _bsr.bsr_matvec(*args) + return _bsr.bsr_matvec(*args) def bsr_matvecs(*args): + """ + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, signed char Ax, signed char Xx, + signed char Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, unsigned char Ax, unsigned char Xx, + unsigned char Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, short Ax, short Xx, short Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, unsigned short Ax, unsigned short Xx, + unsigned short Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, int Ax, int Xx, int Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, unsigned int Ax, unsigned int Xx, + unsigned int Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, long long Ax, long long Xx, long long Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, unsigned long long Ax, unsigned long long Xx, + unsigned long long Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, float Ax, float Xx, float Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, double Ax, double Xx, double Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, long double Ax, long double Xx, + long double Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx, + npy_cfloat_wrapper Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx, + npy_cdouble_wrapper Yx) + bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, + int Aj, npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx, + npy_clongdouble_wrapper Yx) """ - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, signed char Ax, signed char Xx, - signed char Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, unsigned char Ax, unsigned char Xx, - unsigned char Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, short Ax, short Xx, short Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, unsigned short Ax, unsigned short Xx, - unsigned short Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, int Ax, int Xx, int Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, unsigned int Ax, unsigned int Xx, - unsigned int Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, long long Ax, long long Xx, long long Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, unsigned long long Ax, unsigned long long Xx, - unsigned long long Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, float Ax, float Xx, float Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, double Ax, double Xx, double Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, long double Ax, long double Xx, - long double Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx, - npy_cfloat_wrapper Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx, - npy_cdouble_wrapper Yx) - bsr_matvecs(int n_brow, int n_bcol, int n_vecs, int R, int C, int Ap, - int Aj, npy_clongdouble_wrapper Ax, npy_clongdouble_wrapper Xx, - npy_clongdouble_wrapper Yx) - """ - return _bsr.bsr_matvecs(*args) + return _bsr.bsr_matvecs(*args) def bsr_elmul_bsr(*args): + """ + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + signed char Ax, int Bp, int Bj, signed char Bx, + int Cp, int Cj, signed char Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned char Ax, int Bp, int Bj, unsigned char Bx, + int Cp, int Cj, unsigned char Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + short Ax, int Bp, int Bj, short Bx, int Cp, + int Cj, short Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned short Ax, int Bp, int Bj, unsigned short Bx, + int Cp, int Cj, unsigned short Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, + int Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned int Ax, int Bp, int Bj, unsigned int Bx, + int Cp, int Cj, unsigned int Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long long Ax, int Bp, int Bj, long long Bx, + int Cp, int Cj, long long Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + float Ax, int Bp, int Bj, float Bx, int Cp, + int Cj, float Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + double Ax, int Bp, int Bj, double Bx, int Cp, + int Cj, double Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long double Ax, int Bp, int Bj, long double Bx, + int Cp, int Cj, long double Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, int Bp, int Bj, + npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - signed char Ax, int Bp, int Bj, signed char Bx, - int Cp, int Cj, signed char Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned char Ax, int Bp, int Bj, unsigned char Bx, - int Cp, int Cj, unsigned char Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - short Ax, int Bp, int Bj, short Bx, int Cp, - int Cj, short Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned short Ax, int Bp, int Bj, unsigned short Bx, - int Cp, int Cj, unsigned short Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, - int Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned int Ax, int Bp, int Bj, unsigned int Bx, - int Cp, int Cj, unsigned int Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long long Ax, int Bp, int Bj, long long Bx, - int Cp, int Cj, long long Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - float Ax, int Bp, int Bj, float Bx, int Cp, - int Cj, float Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - double Ax, int Bp, int Bj, double Bx, int Cp, - int Cj, double Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long double Ax, int Bp, int Bj, long double Bx, - int Cp, int Cj, long double Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - bsr_elmul_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, int Bp, int Bj, - npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) - """ - return _bsr.bsr_elmul_bsr(*args) + return _bsr.bsr_elmul_bsr(*args) def bsr_eldiv_bsr(*args): + """ + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + signed char Ax, int Bp, int Bj, signed char Bx, + int Cp, int Cj, signed char Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned char Ax, int Bp, int Bj, unsigned char Bx, + int Cp, int Cj, unsigned char Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + short Ax, int Bp, int Bj, short Bx, int Cp, + int Cj, short Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned short Ax, int Bp, int Bj, unsigned short Bx, + int Cp, int Cj, unsigned short Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, + int Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned int Ax, int Bp, int Bj, unsigned int Bx, + int Cp, int Cj, unsigned int Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long long Ax, int Bp, int Bj, long long Bx, + int Cp, int Cj, long long Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + float Ax, int Bp, int Bj, float Bx, int Cp, + int Cj, float Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + double Ax, int Bp, int Bj, double Bx, int Cp, + int Cj, double Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long double Ax, int Bp, int Bj, long double Bx, + int Cp, int Cj, long double Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, int Bp, int Bj, + npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - signed char Ax, int Bp, int Bj, signed char Bx, - int Cp, int Cj, signed char Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned char Ax, int Bp, int Bj, unsigned char Bx, - int Cp, int Cj, unsigned char Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - short Ax, int Bp, int Bj, short Bx, int Cp, - int Cj, short Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned short Ax, int Bp, int Bj, unsigned short Bx, - int Cp, int Cj, unsigned short Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, - int Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned int Ax, int Bp, int Bj, unsigned int Bx, - int Cp, int Cj, unsigned int Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long long Ax, int Bp, int Bj, long long Bx, - int Cp, int Cj, long long Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - float Ax, int Bp, int Bj, float Bx, int Cp, - int Cj, float Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - double Ax, int Bp, int Bj, double Bx, int Cp, - int Cj, double Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long double Ax, int Bp, int Bj, long double Bx, - int Cp, int Cj, long double Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - bsr_eldiv_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, int Bp, int Bj, - npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) - """ - return _bsr.bsr_eldiv_bsr(*args) + return _bsr.bsr_eldiv_bsr(*args) def bsr_plus_bsr(*args): + """ + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + signed char Ax, int Bp, int Bj, signed char Bx, + int Cp, int Cj, signed char Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned char Ax, int Bp, int Bj, unsigned char Bx, + int Cp, int Cj, unsigned char Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + short Ax, int Bp, int Bj, short Bx, int Cp, + int Cj, short Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned short Ax, int Bp, int Bj, unsigned short Bx, + int Cp, int Cj, unsigned short Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, + int Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned int Ax, int Bp, int Bj, unsigned int Bx, + int Cp, int Cj, unsigned int Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long long Ax, int Bp, int Bj, long long Bx, + int Cp, int Cj, long long Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + float Ax, int Bp, int Bj, float Bx, int Cp, + int Cj, float Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + double Ax, int Bp, int Bj, double Bx, int Cp, + int Cj, double Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long double Ax, int Bp, int Bj, long double Bx, + int Cp, int Cj, long double Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, int Bp, int Bj, + npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - signed char Ax, int Bp, int Bj, signed char Bx, - int Cp, int Cj, signed char Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned char Ax, int Bp, int Bj, unsigned char Bx, - int Cp, int Cj, unsigned char Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - short Ax, int Bp, int Bj, short Bx, int Cp, - int Cj, short Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned short Ax, int Bp, int Bj, unsigned short Bx, - int Cp, int Cj, unsigned short Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, - int Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned int Ax, int Bp, int Bj, unsigned int Bx, - int Cp, int Cj, unsigned int Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long long Ax, int Bp, int Bj, long long Bx, - int Cp, int Cj, long long Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - float Ax, int Bp, int Bj, float Bx, int Cp, - int Cj, float Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - double Ax, int Bp, int Bj, double Bx, int Cp, - int Cj, double Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long double Ax, int Bp, int Bj, long double Bx, - int Cp, int Cj, long double Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - bsr_plus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, int Bp, int Bj, - npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) - """ - return _bsr.bsr_plus_bsr(*args) + return _bsr.bsr_plus_bsr(*args) def bsr_minus_bsr(*args): + """ + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + signed char Ax, int Bp, int Bj, signed char Bx, + int Cp, int Cj, signed char Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned char Ax, int Bp, int Bj, unsigned char Bx, + int Cp, int Cj, unsigned char Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + short Ax, int Bp, int Bj, short Bx, int Cp, + int Cj, short Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned short Ax, int Bp, int Bj, unsigned short Bx, + int Cp, int Cj, unsigned short Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, + int Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned int Ax, int Bp, int Bj, unsigned int Bx, + int Cp, int Cj, unsigned int Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long long Ax, int Bp, int Bj, long long Bx, + int Cp, int Cj, long long Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + float Ax, int Bp, int Bj, float Bx, int Cp, + int Cj, float Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + double Ax, int Bp, int Bj, double Bx, int Cp, + int Cj, double Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long double Ax, int Bp, int Bj, long double Bx, + int Cp, int Cj, long double Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, int Bp, int Bj, + npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - signed char Ax, int Bp, int Bj, signed char Bx, - int Cp, int Cj, signed char Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned char Ax, int Bp, int Bj, unsigned char Bx, - int Cp, int Cj, unsigned char Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - short Ax, int Bp, int Bj, short Bx, int Cp, - int Cj, short Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned short Ax, int Bp, int Bj, unsigned short Bx, - int Cp, int Cj, unsigned short Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - int Ax, int Bp, int Bj, int Bx, int Cp, int Cj, - int Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned int Ax, int Bp, int Bj, unsigned int Bx, - int Cp, int Cj, unsigned int Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long long Ax, int Bp, int Bj, long long Bx, - int Cp, int Cj, long long Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned long long Ax, int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - float Ax, int Bp, int Bj, float Bx, int Cp, - int Cj, float Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - double Ax, int Bp, int Bj, double Bx, int Cp, - int Cj, double Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long double Ax, int Bp, int Bj, long double Bx, - int Cp, int Cj, long double Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - bsr_minus_bsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, int Bp, int Bj, - npy_clongdouble_wrapper Bx, int Cp, int Cj, npy_clongdouble_wrapper Cx) - """ - return _bsr.bsr_minus_bsr(*args) + return _bsr.bsr_minus_bsr(*args) def bsr_sort_indices(*args): + """ + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + signed char Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned char Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + short Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned short Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + int Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned int Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long long Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + unsigned long long Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + float Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + double Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + long double Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax) + bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax) """ - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - signed char Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned char Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - short Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned short Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - int Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned int Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long long Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - unsigned long long Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - float Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - double Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - long double Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax) - bsr_sort_indices(int n_brow, int n_bcol, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax) - """ - return _bsr.bsr_sort_indices(*args) + return _bsr.bsr_sort_indices(*args) + Modified: trunk/scipy/sparse/sparsetools/coo.py =================================================================== --- trunk/scipy/sparse/sparsetools/coo.py 2008-08-12 19:20:31 UTC (rev 4644) +++ trunk/scipy/sparse/sparsetools/coo.py 2008-08-14 20:44:07 UTC (rev 4645) @@ -51,129 +51,130 @@ def coo_tocsr(*args): + """ + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, signed char Ax, + int Bp, int Bj, signed char Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned char Ax, + int Bp, int Bj, unsigned char Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, short Ax, + int Bp, int Bj, short Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned short Ax, + int Bp, int Bj, unsigned short Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, int Ax, + int Bp, int Bj, int Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned int Ax, + int Bp, int Bj, unsigned int Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, long long Ax, + int Bp, int Bj, long long Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned long long Ax, + int Bp, int Bj, unsigned long long Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, float Ax, + int Bp, int Bj, float Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, double Ax, + int Bp, int Bj, double Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, long double Ax, + int Bp, int Bj, long double Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bj, npy_cfloat_wrapper Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bj, npy_cdouble_wrapper Bx) + coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bj, npy_clongdouble_wrapper Bx) """ - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, signed char Ax, - int Bp, int Bj, signed char Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned char Ax, - int Bp, int Bj, unsigned char Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, short Ax, - int Bp, int Bj, short Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned short Ax, - int Bp, int Bj, unsigned short Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, int Ax, - int Bp, int Bj, int Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned int Ax, - int Bp, int Bj, unsigned int Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, long long Ax, - int Bp, int Bj, long long Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned long long Ax, - int Bp, int Bj, unsigned long long Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, float Ax, - int Bp, int Bj, float Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, double Ax, - int Bp, int Bj, double Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, long double Ax, - int Bp, int Bj, long double Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bj, npy_cfloat_wrapper Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bj, npy_cdouble_wrapper Bx) - coo_tocsr(int n_row, int n_col, int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bj, npy_clongdouble_wrapper Bx) - """ - return _coo.coo_tocsr(*args) + return _coo.coo_tocsr(*args) def coo_tocsc(*args): + """ + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, signed char Ax, + int Bp, int Bi, signed char Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned char Ax, + int Bp, int Bi, unsigned char Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, short Ax, + int Bp, int Bi, short Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned short Ax, + int Bp, int Bi, unsigned short Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, int Ax, + int Bp, int Bi, int Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned int Ax, + int Bp, int Bi, unsigned int Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, long long Ax, + int Bp, int Bi, long long Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned long long Ax, + int Bp, int Bi, unsigned long long Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, float Ax, + int Bp, int Bi, float Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, double Ax, + int Bp, int Bi, double Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, long double Ax, + int Bp, int Bi, long double Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bi, npy_cfloat_wrapper Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bi, npy_cdouble_wrapper Bx) + coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bi, npy_clongdouble_wrapper Bx) """ - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, signed char Ax, - int Bp, int Bi, signed char Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned char Ax, - int Bp, int Bi, unsigned char Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, short Ax, - int Bp, int Bi, short Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned short Ax, - int Bp, int Bi, unsigned short Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, int Ax, - int Bp, int Bi, int Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned int Ax, - int Bp, int Bi, unsigned int Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, long long Ax, - int Bp, int Bi, long long Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned long long Ax, - int Bp, int Bi, unsigned long long Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, float Ax, - int Bp, int Bi, float Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, double Ax, - int Bp, int Bi, double Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, long double Ax, - int Bp, int Bi, long double Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bi, npy_cfloat_wrapper Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bi, npy_cdouble_wrapper Bx) - coo_tocsc(int n_row, int n_col, int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bi, npy_clongdouble_wrapper Bx) - """ - return _coo.coo_tocsc(*args) + return _coo.coo_tocsc(*args) def coo_todense(*args): + """ + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, signed char Ax, + signed char Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned char Ax, + unsigned char Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, short Ax, + short Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned short Ax, + unsigned short Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, int Ax, + int Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned int Ax, + unsigned int Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, long long Ax, + long long Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned long long Ax, + unsigned long long Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, float Ax, + float Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, double Ax, + double Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, long double Ax, + long double Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Bx) + coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Bx) """ - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, signed char Ax, - signed char Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned char Ax, - unsigned char Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, short Ax, - short Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned short Ax, - unsigned short Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, int Ax, - int Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned int Ax, - unsigned int Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, long long Ax, - long long Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, unsigned long long Ax, - unsigned long long Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, float Ax, - float Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, double Ax, - double Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, long double Ax, - long double Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Bx) - coo_todense(int n_row, int n_col, int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Bx) - """ - return _coo.coo_todense(*args) + return _coo.coo_todense(*args) def coo_matvec(*args): + """ + coo_matvec(int nnz, int Ai, int Aj, signed char Ax, signed char Xx, + signed char Yx) + coo_matvec(int nnz, int Ai, int Aj, unsigned char Ax, unsigned char Xx, + unsigned char Yx) + coo_matvec(int nnz, int Ai, int Aj, short Ax, short Xx, short Yx) + coo_matvec(int nnz, int Ai, int Aj, unsigned short Ax, unsigned short Xx, + unsigned short Yx) + coo_matvec(int nnz, int Ai, int Aj, int Ax, int Xx, int Yx) + coo_matvec(int nnz, int Ai, int Aj, unsigned int Ax, unsigned int Xx, + unsigned int Yx) + coo_matvec(int nnz, int Ai, int Aj, long long Ax, long long Xx, + long long Yx) + coo_matvec(int nnz, int Ai, int Aj, unsigned long long Ax, unsigned long long Xx, + unsigned long long Yx) + coo_matvec(int nnz, int Ai, int Aj, float Ax, float Xx, float Yx) + coo_matvec(int nnz, int Ai, int Aj, double Ax, double Xx, double Yx) + coo_matvec(int nnz, int Ai, int Aj, long double Ax, long double Xx, + long double Yx) + coo_matvec(int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx, + npy_cfloat_wrapper Yx) + coo_matvec(int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx, + npy_cdouble_wrapper Yx) + coo_matvec(int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Xx, npy_clongdouble_wrapper Yx) """ - coo_matvec(int nnz, int Ai, int Aj, signed char Ax, signed char Xx, - signed char Yx) - coo_matvec(int nnz, int Ai, int Aj, unsigned char Ax, unsigned char Xx, - unsigned char Yx) - coo_matvec(int nnz, int Ai, int Aj, short Ax, short Xx, short Yx) - coo_matvec(int nnz, int Ai, int Aj, unsigned short Ax, unsigned short Xx, - unsigned short Yx) - coo_matvec(int nnz, int Ai, int Aj, int Ax, int Xx, int Yx) - coo_matvec(int nnz, int Ai, int Aj, unsigned int Ax, unsigned int Xx, - unsigned int Yx) - coo_matvec(int nnz, int Ai, int Aj, long long Ax, long long Xx, - long long Yx) - coo_matvec(int nnz, int Ai, int Aj, unsigned long long Ax, unsigned long long Xx, - unsigned long long Yx) - coo_matvec(int nnz, int Ai, int Aj, float Ax, float Xx, float Yx) - coo_matvec(int nnz, int Ai, int Aj, double Ax, double Xx, double Yx) - coo_matvec(int nnz, int Ai, int Aj, long double Ax, long double Xx, - long double Yx) - coo_matvec(int nnz, int Ai, int Aj, npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx, - npy_cfloat_wrapper Yx) - coo_matvec(int nnz, int Ai, int Aj, npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx, - npy_cdouble_wrapper Yx) - coo_matvec(int nnz, int Ai, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Xx, npy_clongdouble_wrapper Yx) - """ - return _coo.coo_matvec(*args) + return _coo.coo_matvec(*args) + Modified: trunk/scipy/sparse/sparsetools/csc.py =================================================================== --- trunk/scipy/sparse/sparsetools/csc.py 2008-08-12 19:20:31 UTC (rev 4644) +++ trunk/scipy/sparse/sparsetools/csc.py 2008-08-14 20:44:07 UTC (rev 4645) @@ -50,356 +50,357 @@ def csc_matmat_pass1(*args): + """ + csc_matmat_pass1(int n_row, int n_col, int Ap, int Ai, int Bp, int Bi, + int Cp) """ - csc_matmat_pass1(int n_row, int n_col, int Ap, int Ai, int Bp, int Bi, - int Cp) - """ - return _csc.csc_matmat_pass1(*args) + return _csc.csc_matmat_pass1(*args) def csc_diagonal(*args): + """ + csc_diagonal(int n_row, int n_col, int Ap, int Aj, signed char Ax, + signed char Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + unsigned char Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, short Ax, short Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + unsigned short Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, int Ax, int Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + unsigned int Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, long long Ax, + long long Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + unsigned long long Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, float Ax, float Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, double Ax, double Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, long double Ax, + long double Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Yx) + csc_diagonal(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Yx) """ - csc_diagonal(int n_row, int n_col, int Ap, int Aj, signed char Ax, - signed char Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - unsigned char Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, short Ax, short Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - unsigned short Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, int Ax, int Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - unsigned int Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, long long Ax, - long long Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - unsigned long long Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, float Ax, float Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, double Ax, double Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, long double Ax, - long double Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Yx) - csc_diagonal(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Yx) - """ - return _csc.csc_diagonal(*args) + return _csc.csc_diagonal(*args) def csc_tocsr(*args): + """ + csc_tocsr(int n_row, int n_col, int Ap, int Ai, signed char Ax, + int Bp, int Bj, signed char Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, + int Bp, int Bj, unsigned char Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, + int Bj, short Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, + int Bp, int Bj, unsigned short Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, + int Bj, int Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, + int Bp, int Bj, unsigned int Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, long long Ax, + int Bp, int Bj, long long Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, + int Bp, int Bj, unsigned long long Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, + int Bj, float Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, + int Bj, double Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, long double Ax, + int Bp, int Bj, long double Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, + int Bp, int Bj, npy_cfloat_wrapper Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, + int Bp, int Bj, npy_cdouble_wrapper Bx) + csc_tocsr(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, + int Bp, int Bj, npy_clongdouble_wrapper Bx) """ - csc_tocsr(int n_row, int n_col, int Ap, int Ai, signed char Ax, - int Bp, int Bj, signed char Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, - int Bp, int Bj, unsigned char Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, - int Bj, short Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, - int Bp, int Bj, unsigned short Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, - int Bj, int Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, - int Bp, int Bj, unsigned int Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, long long Ax, - int Bp, int Bj, long long Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, - int Bp, int Bj, unsigned long long Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, - int Bj, float Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, - int Bj, double Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, long double Ax, - int Bp, int Bj, long double Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, - int Bp, int Bj, npy_cfloat_wrapper Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, - int Bp, int Bj, npy_cdouble_wrapper Bx) - csc_tocsr(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, - int Bp, int Bj, npy_clongdouble_wrapper Bx) - """ - return _csc.csc_tocsr(*args) + return _csc.csc_tocsr(*args) def csc_matmat_pass2(*args): + """ + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, signed char Ax, + int Bp, int Bi, signed char Bx, int Cp, int Ci, + signed char Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, + int Bp, int Bi, unsigned char Bx, int Cp, + int Ci, unsigned char Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, + int Bi, short Bx, int Cp, int Ci, short Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, + int Bp, int Bi, unsigned short Bx, int Cp, + int Ci, unsigned short Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, + int Bi, int Bx, int Cp, int Ci, int Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, + int Bp, int Bi, unsigned int Bx, int Cp, + int Ci, unsigned int Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, long long Ax, + int Bp, int Bi, long long Bx, int Cp, int Ci, + long long Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, + int Bp, int Bi, unsigned long long Bx, + int Cp, int Ci, unsigned long long Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, + int Bi, float Bx, int Cp, int Ci, float Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, + int Bi, double Bx, int Cp, int Ci, double Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, long double Ax, + int Bp, int Bi, long double Bx, int Cp, int Ci, + long double Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, + int Bp, int Bi, npy_cfloat_wrapper Bx, + int Cp, int Ci, npy_cfloat_wrapper Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, + int Bp, int Bi, npy_cdouble_wrapper Bx, + int Cp, int Ci, npy_cdouble_wrapper Cx) + csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, + int Bp, int Bi, npy_clongdouble_wrapper Bx, + int Cp, int Ci, npy_clongdouble_wrapper Cx) """ - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, signed char Ax, - int Bp, int Bi, signed char Bx, int Cp, int Ci, - signed char Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, - int Bp, int Bi, unsigned char Bx, int Cp, - int Ci, unsigned char Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, - int Bi, short Bx, int Cp, int Ci, short Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, - int Bp, int Bi, unsigned short Bx, int Cp, - int Ci, unsigned short Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, - int Bi, int Bx, int Cp, int Ci, int Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, - int Bp, int Bi, unsigned int Bx, int Cp, - int Ci, unsigned int Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, long long Ax, - int Bp, int Bi, long long Bx, int Cp, int Ci, - long long Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, - int Bp, int Bi, unsigned long long Bx, - int Cp, int Ci, unsigned long long Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, - int Bi, float Bx, int Cp, int Ci, float Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, - int Bi, double Bx, int Cp, int Ci, double Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, long double Ax, - int Bp, int Bi, long double Bx, int Cp, int Ci, - long double Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, - int Bp, int Bi, npy_cfloat_wrapper Bx, - int Cp, int Ci, npy_cfloat_wrapper Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, - int Bp, int Bi, npy_cdouble_wrapper Bx, - int Cp, int Ci, npy_cdouble_wrapper Cx) - csc_matmat_pass2(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, - int Bp, int Bi, npy_clongdouble_wrapper Bx, - int Cp, int Ci, npy_clongdouble_wrapper Cx) - """ - return _csc.csc_matmat_pass2(*args) + return _csc.csc_matmat_pass2(*args) def csc_matvec(*args): + """ + csc_matvec(int n_row, int n_col, int Ap, int Ai, signed char Ax, + signed char Xx, signed char Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, + unsigned char Xx, unsigned char Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, short Ax, short Xx, + short Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, + unsigned short Xx, unsigned short Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, int Ax, int Xx, + int Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, + unsigned int Xx, unsigned int Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, long long Ax, + long long Xx, long long Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, + unsigned long long Xx, unsigned long long Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, float Ax, float Xx, + float Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, double Ax, double Xx, + double Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, long double Ax, + long double Xx, long double Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Xx, npy_cfloat_wrapper Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Xx, npy_cdouble_wrapper Yx) + csc_matvec(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Xx, npy_clongdouble_wrapper Yx) """ - csc_matvec(int n_row, int n_col, int Ap, int Ai, signed char Ax, - signed char Xx, signed char Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, - unsigned char Xx, unsigned char Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, short Ax, short Xx, - short Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, - unsigned short Xx, unsigned short Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, int Ax, int Xx, - int Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, - unsigned int Xx, unsigned int Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, long long Ax, - long long Xx, long long Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, - unsigned long long Xx, unsigned long long Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, float Ax, float Xx, - float Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, double Ax, double Xx, - double Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, long double Ax, - long double Xx, long double Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Xx, npy_cfloat_wrapper Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Xx, npy_cdouble_wrapper Yx) - csc_matvec(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Xx, npy_clongdouble_wrapper Yx) - """ - return _csc.csc_matvec(*args) + return _csc.csc_matvec(*args) def csc_matvecs(*args): + """ + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, signed char Ax, + signed char Xx, signed char Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned char Ax, + unsigned char Xx, unsigned char Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, short Ax, + short Xx, short Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned short Ax, + unsigned short Xx, unsigned short Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, int Ax, + int Xx, int Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned int Ax, + unsigned int Xx, unsigned int Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, long long Ax, + long long Xx, long long Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned long long Ax, + unsigned long long Xx, + unsigned long long Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, float Ax, + float Xx, float Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, double Ax, + double Xx, double Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, long double Ax, + long double Xx, long double Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Xx, + npy_cfloat_wrapper Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Xx, + npy_cdouble_wrapper Yx) + csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Xx, + npy_clongdouble_wrapper Yx) """ - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, signed char Ax, - signed char Xx, signed char Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned char Ax, - unsigned char Xx, unsigned char Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, short Ax, - short Xx, short Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned short Ax, - unsigned short Xx, unsigned short Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, int Ax, - int Xx, int Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned int Ax, - unsigned int Xx, unsigned int Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, long long Ax, - long long Xx, long long Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, unsigned long long Ax, - unsigned long long Xx, - unsigned long long Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, float Ax, - float Xx, float Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, double Ax, - double Xx, double Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, long double Ax, - long double Xx, long double Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Xx, - npy_cfloat_wrapper Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Xx, - npy_cdouble_wrapper Yx) - csc_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Ai, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Xx, - npy_clongdouble_wrapper Yx) - """ - return _csc.csc_matvecs(*args) + return _csc.csc_matvecs(*args) def csc_elmul_csc(*args): + """ + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, + int Bp, int Bi, signed char Bx, int Cp, int Ci, + signed char Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, + int Bp, int Bi, unsigned char Bx, int Cp, + int Ci, unsigned char Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, + int Bi, short Bx, int Cp, int Ci, short Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, + int Bp, int Bi, unsigned short Bx, int Cp, + int Ci, unsigned short Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, + int Bi, int Bx, int Cp, int Ci, int Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, + int Bp, int Bi, unsigned int Bx, int Cp, + int Ci, unsigned int Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, + int Bp, int Bi, long long Bx, int Cp, int Ci, + long long Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, + int Bp, int Bi, unsigned long long Bx, + int Cp, int Ci, unsigned long long Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, + int Bi, float Bx, int Cp, int Ci, float Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, + int Bi, double Bx, int Cp, int Ci, double Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, + int Bp, int Bi, long double Bx, int Cp, int Ci, + long double Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, + int Bp, int Bi, npy_cfloat_wrapper Bx, + int Cp, int Ci, npy_cfloat_wrapper Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, + int Bp, int Bi, npy_cdouble_wrapper Bx, + int Cp, int Ci, npy_cdouble_wrapper Cx) + csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, + int Bp, int Bi, npy_clongdouble_wrapper Bx, + int Cp, int Ci, npy_clongdouble_wrapper Cx) """ - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, - int Bp, int Bi, signed char Bx, int Cp, int Ci, - signed char Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, - int Bp, int Bi, unsigned char Bx, int Cp, - int Ci, unsigned char Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, - int Bi, short Bx, int Cp, int Ci, short Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, - int Bp, int Bi, unsigned short Bx, int Cp, - int Ci, unsigned short Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, - int Bi, int Bx, int Cp, int Ci, int Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, - int Bp, int Bi, unsigned int Bx, int Cp, - int Ci, unsigned int Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, - int Bp, int Bi, long long Bx, int Cp, int Ci, - long long Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, - int Bp, int Bi, unsigned long long Bx, - int Cp, int Ci, unsigned long long Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, - int Bi, float Bx, int Cp, int Ci, float Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, - int Bi, double Bx, int Cp, int Ci, double Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, - int Bp, int Bi, long double Bx, int Cp, int Ci, - long double Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, - int Bp, int Bi, npy_cfloat_wrapper Bx, - int Cp, int Ci, npy_cfloat_wrapper Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, - int Bp, int Bi, npy_cdouble_wrapper Bx, - int Cp, int Ci, npy_cdouble_wrapper Cx) - csc_elmul_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, - int Bp, int Bi, npy_clongdouble_wrapper Bx, - int Cp, int Ci, npy_clongdouble_wrapper Cx) - """ - return _csc.csc_elmul_csc(*args) + return _csc.csc_elmul_csc(*args) def csc_eldiv_csc(*args): + """ + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, + int Bp, int Bi, signed char Bx, int Cp, int Ci, + signed char Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, + int Bp, int Bi, unsigned char Bx, int Cp, + int Ci, unsigned char Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, + int Bi, short Bx, int Cp, int Ci, short Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, + int Bp, int Bi, unsigned short Bx, int Cp, + int Ci, unsigned short Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, + int Bi, int Bx, int Cp, int Ci, int Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, + int Bp, int Bi, unsigned int Bx, int Cp, + int Ci, unsigned int Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, + int Bp, int Bi, long long Bx, int Cp, int Ci, + long long Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, + int Bp, int Bi, unsigned long long Bx, + int Cp, int Ci, unsigned long long Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, + int Bi, float Bx, int Cp, int Ci, float Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, + int Bi, double Bx, int Cp, int Ci, double Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, + int Bp, int Bi, long double Bx, int Cp, int Ci, + long double Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, + int Bp, int Bi, npy_cfloat_wrapper Bx, + int Cp, int Ci, npy_cfloat_wrapper Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, + int Bp, int Bi, npy_cdouble_wrapper Bx, + int Cp, int Ci, npy_cdouble_wrapper Cx) + csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, + int Bp, int Bi, npy_clongdouble_wrapper Bx, + int Cp, int Ci, npy_clongdouble_wrapper Cx) """ - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, - int Bp, int Bi, signed char Bx, int Cp, int Ci, - signed char Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, - int Bp, int Bi, unsigned char Bx, int Cp, - int Ci, unsigned char Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, - int Bi, short Bx, int Cp, int Ci, short Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, - int Bp, int Bi, unsigned short Bx, int Cp, - int Ci, unsigned short Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, - int Bi, int Bx, int Cp, int Ci, int Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, - int Bp, int Bi, unsigned int Bx, int Cp, - int Ci, unsigned int Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, - int Bp, int Bi, long long Bx, int Cp, int Ci, - long long Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, - int Bp, int Bi, unsigned long long Bx, - int Cp, int Ci, unsigned long long Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, - int Bi, float Bx, int Cp, int Ci, float Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, - int Bi, double Bx, int Cp, int Ci, double Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, - int Bp, int Bi, long double Bx, int Cp, int Ci, - long double Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, - int Bp, int Bi, npy_cfloat_wrapper Bx, - int Cp, int Ci, npy_cfloat_wrapper Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, - int Bp, int Bi, npy_cdouble_wrapper Bx, - int Cp, int Ci, npy_cdouble_wrapper Cx) - csc_eldiv_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, - int Bp, int Bi, npy_clongdouble_wrapper Bx, - int Cp, int Ci, npy_clongdouble_wrapper Cx) - """ - return _csc.csc_eldiv_csc(*args) + return _csc.csc_eldiv_csc(*args) def csc_plus_csc(*args): + """ + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, + int Bp, int Bi, signed char Bx, int Cp, int Ci, + signed char Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, + int Bp, int Bi, unsigned char Bx, int Cp, + int Ci, unsigned char Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, + int Bi, short Bx, int Cp, int Ci, short Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, + int Bp, int Bi, unsigned short Bx, int Cp, + int Ci, unsigned short Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, + int Bi, int Bx, int Cp, int Ci, int Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, + int Bp, int Bi, unsigned int Bx, int Cp, + int Ci, unsigned int Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, + int Bp, int Bi, long long Bx, int Cp, int Ci, + long long Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, + int Bp, int Bi, unsigned long long Bx, + int Cp, int Ci, unsigned long long Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, + int Bi, float Bx, int Cp, int Ci, float Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, + int Bi, double Bx, int Cp, int Ci, double Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, + int Bp, int Bi, long double Bx, int Cp, int Ci, + long double Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, + int Bp, int Bi, npy_cfloat_wrapper Bx, + int Cp, int Ci, npy_cfloat_wrapper Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, + int Bp, int Bi, npy_cdouble_wrapper Bx, + int Cp, int Ci, npy_cdouble_wrapper Cx) + csc_plus_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, + int Bp, int Bi, npy_clongdouble_wrapper Bx, + int Cp, int Ci, npy_clongdouble_wrapper Cx) """ - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, - int Bp, int Bi, signed char Bx, int Cp, int Ci, - signed char Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, - int Bp, int Bi, unsigned char Bx, int Cp, - int Ci, unsigned char Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, - int Bi, short Bx, int Cp, int Ci, short Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, - int Bp, int Bi, unsigned short Bx, int Cp, - int Ci, unsigned short Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, - int Bi, int Bx, int Cp, int Ci, int Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, - int Bp, int Bi, unsigned int Bx, int Cp, - int Ci, unsigned int Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, - int Bp, int Bi, long long Bx, int Cp, int Ci, - long long Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, - int Bp, int Bi, unsigned long long Bx, - int Cp, int Ci, unsigned long long Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, - int Bi, float Bx, int Cp, int Ci, float Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, - int Bi, double Bx, int Cp, int Ci, double Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, - int Bp, int Bi, long double Bx, int Cp, int Ci, - long double Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, - int Bp, int Bi, npy_cfloat_wrapper Bx, - int Cp, int Ci, npy_cfloat_wrapper Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, - int Bp, int Bi, npy_cdouble_wrapper Bx, - int Cp, int Ci, npy_cdouble_wrapper Cx) - csc_plus_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, - int Bp, int Bi, npy_clongdouble_wrapper Bx, - int Cp, int Ci, npy_clongdouble_wrapper Cx) - """ - return _csc.csc_plus_csc(*args) + return _csc.csc_plus_csc(*args) def csc_minus_csc(*args): + """ + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, + int Bp, int Bi, signed char Bx, int Cp, int Ci, + signed char Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, + int Bp, int Bi, unsigned char Bx, int Cp, + int Ci, unsigned char Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, + int Bi, short Bx, int Cp, int Ci, short Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, + int Bp, int Bi, unsigned short Bx, int Cp, + int Ci, unsigned short Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, + int Bi, int Bx, int Cp, int Ci, int Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, + int Bp, int Bi, unsigned int Bx, int Cp, + int Ci, unsigned int Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, + int Bp, int Bi, long long Bx, int Cp, int Ci, + long long Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, + int Bp, int Bi, unsigned long long Bx, + int Cp, int Ci, unsigned long long Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, + int Bi, float Bx, int Cp, int Ci, float Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, + int Bi, double Bx, int Cp, int Ci, double Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, + int Bp, int Bi, long double Bx, int Cp, int Ci, + long double Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, + int Bp, int Bi, npy_cfloat_wrapper Bx, + int Cp, int Ci, npy_cfloat_wrapper Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, + int Bp, int Bi, npy_cdouble_wrapper Bx, + int Cp, int Ci, npy_cdouble_wrapper Cx) + csc_minus_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, + int Bp, int Bi, npy_clongdouble_wrapper Bx, + int Cp, int Ci, npy_clongdouble_wrapper Cx) """ - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, signed char Ax, - int Bp, int Bi, signed char Bx, int Cp, int Ci, - signed char Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned char Ax, - int Bp, int Bi, unsigned char Bx, int Cp, - int Ci, unsigned char Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, short Ax, int Bp, - int Bi, short Bx, int Cp, int Ci, short Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned short Ax, - int Bp, int Bi, unsigned short Bx, int Cp, - int Ci, unsigned short Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, int Ax, int Bp, - int Bi, int Bx, int Cp, int Ci, int Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned int Ax, - int Bp, int Bi, unsigned int Bx, int Cp, - int Ci, unsigned int Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, long long Ax, - int Bp, int Bi, long long Bx, int Cp, int Ci, - long long Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, unsigned long long Ax, - int Bp, int Bi, unsigned long long Bx, - int Cp, int Ci, unsigned long long Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, float Ax, int Bp, - int Bi, float Bx, int Cp, int Ci, float Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, double Ax, int Bp, - int Bi, double Bx, int Cp, int Ci, double Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, long double Ax, - int Bp, int Bi, long double Bx, int Cp, int Ci, - long double Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax, - int Bp, int Bi, npy_cfloat_wrapper Bx, - int Cp, int Ci, npy_cfloat_wrapper Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, - int Bp, int Bi, npy_cdouble_wrapper Bx, - int Cp, int Ci, npy_cdouble_wrapper Cx) - csc_minus_csc(int n_row, int n_col, int Ap, int Ai, npy_clongdouble_wrapper Ax, - int Bp, int Bi, npy_clongdouble_wrapper Bx, - int Cp, int Ci, npy_clongdouble_wrapper Cx) - """ - return _csc.csc_minus_csc(*args) + return _csc.csc_minus_csc(*args) + Modified: trunk/scipy/sparse/sparsetools/csr.py =================================================================== --- trunk/scipy/sparse/sparsetools/csr.py 2008-08-12 19:20:31 UTC (rev 4644) +++ trunk/scipy/sparse/sparsetools/csr.py 2008-08-14 20:44:07 UTC (rev 4645) @@ -50,568 +50,569 @@ def expandptr(*args): - """expandptr(int n_row, int Ap, int Bi)""" - return _csr.expandptr(*args) + """expandptr(int n_row, int Ap, int Bi)""" + return _csr.expandptr(*args) def csr_count_blocks(*args): - """csr_count_blocks(int n_row, int n_col, int R, int C, int Ap, int Aj) -> int""" - return _csr.csr_count_blocks(*args) + """csr_count_blocks(int n_row, int n_col, int R, int C, int Ap, int Aj) -> int""" + return _csr.csr_count_blocks(*args) def csr_matmat_pass1(*args): + """ + csr_matmat_pass1(int n_row, int n_col, int Ap, int Aj, int Bp, int Bj, + int Cp) """ - csr_matmat_pass1(int n_row, int n_col, int Ap, int Aj, int Bp, int Bj, - int Cp) - """ - return _csr.csr_matmat_pass1(*args) + return _csr.csr_matmat_pass1(*args) def csr_has_sorted_indices(*args): - """csr_has_sorted_indices(int n_row, int Ap, int Aj) -> bool""" - return _csr.csr_has_sorted_indices(*args) + """csr_has_sorted_indices(int n_row, int Ap, int Aj) -> bool""" + return _csr.csr_has_sorted_indices(*args) def csr_diagonal(*args): + """ + csr_diagonal(int n_row, int n_col, int Ap, int Aj, signed char Ax, + signed char Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + unsigned char Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, short Ax, short Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + unsigned short Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, int Ax, int Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + unsigned int Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, long long Ax, + long long Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + unsigned long long Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, float Ax, float Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, double Ax, double Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, long double Ax, + long double Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Yx) + csr_diagonal(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Yx) """ - csr_diagonal(int n_row, int n_col, int Ap, int Aj, signed char Ax, - signed char Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - unsigned char Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, short Ax, short Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - unsigned short Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, int Ax, int Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - unsigned int Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, long long Ax, - long long Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - unsigned long long Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, float Ax, float Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, double Ax, double Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, long double Ax, - long double Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Yx) - csr_diagonal(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Yx) - """ - return _csr.csr_diagonal(*args) + return _csr.csr_diagonal(*args) def csr_scale_rows(*args): + """ + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, signed char Ax, + signed char Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + unsigned char Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, short Ax, short Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + unsigned short Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, int Ax, int Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + unsigned int Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, long long Ax, + long long Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + unsigned long long Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, float Ax, float Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, double Ax, double Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, long double Ax, + long double Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Xx) + csr_scale_rows(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Xx) """ - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, signed char Ax, - signed char Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - unsigned char Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, short Ax, short Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - unsigned short Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, int Ax, int Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - unsigned int Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, long long Ax, - long long Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - unsigned long long Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, float Ax, float Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, double Ax, double Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, long double Ax, - long double Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Xx) - csr_scale_rows(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Xx) - """ - return _csr.csr_scale_rows(*args) + return _csr.csr_scale_rows(*args) def csr_scale_columns(*args): + """ + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, signed char Ax, + signed char Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + unsigned char Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, short Ax, short Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + unsigned short Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, int Ax, int Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + unsigned int Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, long long Ax, + long long Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + unsigned long long Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, float Ax, float Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, double Ax, double Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, long double Ax, + long double Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Xx) + csr_scale_columns(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Xx) """ - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, signed char Ax, - signed char Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - unsigned char Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, short Ax, short Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - unsigned short Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, int Ax, int Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - unsigned int Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, long long Ax, - long long Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - unsigned long long Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, float Ax, float Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, double Ax, double Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, long double Ax, - long double Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Xx) - csr_scale_columns(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Xx) - """ - return _csr.csr_scale_columns(*args) + return _csr.csr_scale_columns(*args) def csr_tocsc(*args): + """ + csr_tocsc(int n_row, int n_col, int Ap, int Aj, signed char Ax, + int Bp, int Bi, signed char Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + int Bp, int Bi, unsigned char Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, + int Bi, short Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + int Bp, int Bi, unsigned short Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, + int Bi, int Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + int Bp, int Bi, unsigned int Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, long long Ax, + int Bp, int Bi, long long Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + int Bp, int Bi, unsigned long long Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, + int Bi, float Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, + int Bi, double Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, long double Ax, + int Bp, int Bi, long double Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bi, npy_cfloat_wrapper Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bi, npy_cdouble_wrapper Bx) + csr_tocsc(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bi, npy_clongdouble_wrapper Bx) """ - csr_tocsc(int n_row, int n_col, int Ap, int Aj, signed char Ax, - int Bp, int Bi, signed char Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - int Bp, int Bi, unsigned char Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, - int Bi, short Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - int Bp, int Bi, unsigned short Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, - int Bi, int Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - int Bp, int Bi, unsigned int Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, long long Ax, - int Bp, int Bi, long long Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - int Bp, int Bi, unsigned long long Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, - int Bi, float Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, - int Bi, double Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, long double Ax, - int Bp, int Bi, long double Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bi, npy_cfloat_wrapper Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bi, npy_cdouble_wrapper Bx) - csr_tocsc(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bi, npy_clongdouble_wrapper Bx) - """ - return _csr.csr_tocsc(*args) + return _csr.csr_tocsc(*args) def csr_tobsr(*args): + """ + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + signed char Ax, int Bp, int Bj, signed char Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned char Ax, int Bp, int Bj, unsigned char Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + short Ax, int Bp, int Bj, short Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned short Ax, int Bp, int Bj, unsigned short Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + int Ax, int Bp, int Bj, int Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned int Ax, int Bp, int Bj, unsigned int Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long long Ax, int Bp, int Bj, long long Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + unsigned long long Ax, int Bp, int Bj, unsigned long long Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + float Ax, int Bp, int Bj, float Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + double Ax, int Bp, int Bj, double Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + long double Ax, int Bp, int Bj, long double Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx) + csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, + npy_clongdouble_wrapper Ax, int Bp, int Bj, + npy_clongdouble_wrapper Bx) """ - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - signed char Ax, int Bp, int Bj, signed char Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned char Ax, int Bp, int Bj, unsigned char Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - short Ax, int Bp, int Bj, short Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned short Ax, int Bp, int Bj, unsigned short Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - int Ax, int Bp, int Bj, int Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned int Ax, int Bp, int Bj, unsigned int Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long long Ax, int Bp, int Bj, long long Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - unsigned long long Ax, int Bp, int Bj, unsigned long long Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - float Ax, int Bp, int Bj, float Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - double Ax, int Bp, int Bj, double Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - long double Ax, int Bp, int Bj, long double Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cfloat_wrapper Ax, int Bp, int Bj, npy_cfloat_wrapper Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_cdouble_wrapper Ax, int Bp, int Bj, npy_cdouble_wrapper Bx) - csr_tobsr(int n_row, int n_col, int R, int C, int Ap, int Aj, - npy_clongdouble_wrapper Ax, int Bp, int Bj, - npy_clongdouble_wrapper Bx) - """ - return _csr.csr_tobsr(*args) + return _csr.csr_tobsr(*args) def csr_matmat_pass2(*args): + """ + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, signed char Ax, + int Bp, int Bj, signed char Bx, int Cp, int Cj, + signed char Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + int Bp, int Bj, unsigned char Bx, int Cp, + int Cj, unsigned char Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, + int Bj, short Bx, int Cp, int Cj, short Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + int Bp, int Bj, unsigned short Bx, int Cp, + int Cj, unsigned short Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, + int Bj, int Bx, int Cp, int Cj, int Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + int Bp, int Bj, unsigned int Bx, int Cp, + int Cj, unsigned int Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, long long Ax, + int Bp, int Bj, long long Bx, int Cp, int Cj, + long long Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, + int Bj, float Bx, int Cp, int Cj, float Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, + int Bj, double Bx, int Cp, int Cj, double Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, long double Ax, + int Bp, int Bj, long double Bx, int Cp, int Cj, + long double Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bj, npy_clongdouble_wrapper Bx, + int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, signed char Ax, - int Bp, int Bj, signed char Bx, int Cp, int Cj, - signed char Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - int Bp, int Bj, unsigned char Bx, int Cp, - int Cj, unsigned char Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, - int Bj, short Bx, int Cp, int Cj, short Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - int Bp, int Bj, unsigned short Bx, int Cp, - int Cj, unsigned short Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, - int Bj, int Bx, int Cp, int Cj, int Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - int Bp, int Bj, unsigned int Bx, int Cp, - int Cj, unsigned int Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, long long Ax, - int Bp, int Bj, long long Bx, int Cp, int Cj, - long long Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, - int Bj, float Bx, int Cp, int Cj, float Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, - int Bj, double Bx, int Cp, int Cj, double Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, long double Ax, - int Bp, int Bj, long double Bx, int Cp, int Cj, - long double Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - csr_matmat_pass2(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bj, npy_clongdouble_wrapper Bx, - int Cp, int Cj, npy_clongdouble_wrapper Cx) - """ - return _csr.csr_matmat_pass2(*args) + return _csr.csr_matmat_pass2(*args) def csr_matvec(*args): + """ + csr_matvec(int n_row, int n_col, int Ap, int Aj, signed char Ax, + signed char Xx, signed char Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + unsigned char Xx, unsigned char Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, short Ax, short Xx, + short Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + unsigned short Xx, unsigned short Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, int Ax, int Xx, + int Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + unsigned int Xx, unsigned int Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, long long Ax, + long long Xx, long long Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + unsigned long long Xx, unsigned long long Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, float Ax, float Xx, + float Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, double Ax, double Xx, + double Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, long double Ax, + long double Xx, long double Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Xx, npy_cfloat_wrapper Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Xx, npy_cdouble_wrapper Yx) + csr_matvec(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Xx, npy_clongdouble_wrapper Yx) """ - csr_matvec(int n_row, int n_col, int Ap, int Aj, signed char Ax, - signed char Xx, signed char Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - unsigned char Xx, unsigned char Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, short Ax, short Xx, - short Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - unsigned short Xx, unsigned short Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, int Ax, int Xx, - int Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - unsigned int Xx, unsigned int Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, long long Ax, - long long Xx, long long Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - unsigned long long Xx, unsigned long long Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, float Ax, float Xx, - float Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, double Ax, double Xx, - double Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, long double Ax, - long double Xx, long double Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Xx, npy_cfloat_wrapper Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Xx, npy_cdouble_wrapper Yx) - csr_matvec(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Xx, npy_clongdouble_wrapper Yx) - """ - return _csr.csr_matvec(*args) + return _csr.csr_matvec(*args) def csr_matvecs(*args): + """ + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, signed char Ax, + signed char Xx, signed char Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned char Ax, + unsigned char Xx, unsigned char Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, short Ax, + short Xx, short Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned short Ax, + unsigned short Xx, unsigned short Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, int Ax, + int Xx, int Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned int Ax, + unsigned int Xx, unsigned int Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, long long Ax, + long long Xx, long long Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned long long Ax, + unsigned long long Xx, + unsigned long long Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, float Ax, + float Xx, float Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, double Ax, + double Xx, double Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, long double Ax, + long double Xx, long double Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, npy_cfloat_wrapper Ax, + npy_cfloat_wrapper Xx, + npy_cfloat_wrapper Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, npy_cdouble_wrapper Ax, + npy_cdouble_wrapper Xx, + npy_cdouble_wrapper Yx) + csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, npy_clongdouble_wrapper Ax, + npy_clongdouble_wrapper Xx, + npy_clongdouble_wrapper Yx) """ - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, signed char Ax, - signed char Xx, signed char Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned char Ax, - unsigned char Xx, unsigned char Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, short Ax, - short Xx, short Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned short Ax, - unsigned short Xx, unsigned short Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, int Ax, - int Xx, int Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned int Ax, - unsigned int Xx, unsigned int Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, long long Ax, - long long Xx, long long Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, unsigned long long Ax, - unsigned long long Xx, - unsigned long long Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, float Ax, - float Xx, float Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, double Ax, - double Xx, double Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, long double Ax, - long double Xx, long double Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, npy_cfloat_wrapper Ax, - npy_cfloat_wrapper Xx, - npy_cfloat_wrapper Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, npy_cdouble_wrapper Ax, - npy_cdouble_wrapper Xx, - npy_cdouble_wrapper Yx) - csr_matvecs(int n_row, int n_col, int n_vecs, int Ap, int Aj, npy_clongdouble_wrapper Ax, - npy_clongdouble_wrapper Xx, - npy_clongdouble_wrapper Yx) - """ - return _csr.csr_matvecs(*args) + return _csr.csr_matvecs(*args) def csr_elmul_csr(*args): + """ + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, + int Bp, int Bj, signed char Bx, int Cp, int Cj, + signed char Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + int Bp, int Bj, unsigned char Bx, int Cp, + int Cj, unsigned char Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, + int Bj, short Bx, int Cp, int Cj, short Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + int Bp, int Bj, unsigned short Bx, int Cp, + int Cj, unsigned short Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, + int Bj, int Bx, int Cp, int Cj, int Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + int Bp, int Bj, unsigned int Bx, int Cp, + int Cj, unsigned int Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, + int Bp, int Bj, long long Bx, int Cp, int Cj, + long long Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, + int Bj, float Bx, int Cp, int Cj, float Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, + int Bj, double Bx, int Cp, int Cj, double Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, + int Bp, int Bj, long double Bx, int Cp, int Cj, + long double Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bj, npy_clongdouble_wrapper Bx, + int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, - int Bp, int Bj, signed char Bx, int Cp, int Cj, - signed char Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - int Bp, int Bj, unsigned char Bx, int Cp, - int Cj, unsigned char Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, - int Bj, short Bx, int Cp, int Cj, short Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - int Bp, int Bj, unsigned short Bx, int Cp, - int Cj, unsigned short Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, - int Bj, int Bx, int Cp, int Cj, int Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - int Bp, int Bj, unsigned int Bx, int Cp, - int Cj, unsigned int Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, - int Bp, int Bj, long long Bx, int Cp, int Cj, - long long Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, - int Bj, float Bx, int Cp, int Cj, float Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, - int Bj, double Bx, int Cp, int Cj, double Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, - int Bp, int Bj, long double Bx, int Cp, int Cj, - long double Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bj, npy_clongdouble_wrapper Bx, - int Cp, int Cj, npy_clongdouble_wrapper Cx) - """ - return _csr.csr_elmul_csr(*args) + return _csr.csr_elmul_csr(*args) def csr_eldiv_csr(*args): + """ + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, + int Bp, int Bj, signed char Bx, int Cp, int Cj, + signed char Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + int Bp, int Bj, unsigned char Bx, int Cp, + int Cj, unsigned char Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, + int Bj, short Bx, int Cp, int Cj, short Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + int Bp, int Bj, unsigned short Bx, int Cp, + int Cj, unsigned short Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, + int Bj, int Bx, int Cp, int Cj, int Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + int Bp, int Bj, unsigned int Bx, int Cp, + int Cj, unsigned int Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, + int Bp, int Bj, long long Bx, int Cp, int Cj, + long long Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, + int Bj, float Bx, int Cp, int Cj, float Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, + int Bj, double Bx, int Cp, int Cj, double Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, + int Bp, int Bj, long double Bx, int Cp, int Cj, + long double Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bj, npy_clongdouble_wrapper Bx, + int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, - int Bp, int Bj, signed char Bx, int Cp, int Cj, - signed char Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - int Bp, int Bj, unsigned char Bx, int Cp, - int Cj, unsigned char Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, - int Bj, short Bx, int Cp, int Cj, short Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - int Bp, int Bj, unsigned short Bx, int Cp, - int Cj, unsigned short Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, - int Bj, int Bx, int Cp, int Cj, int Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - int Bp, int Bj, unsigned int Bx, int Cp, - int Cj, unsigned int Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, - int Bp, int Bj, long long Bx, int Cp, int Cj, - long long Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, - int Bj, float Bx, int Cp, int Cj, float Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, - int Bj, double Bx, int Cp, int Cj, double Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, - int Bp, int Bj, long double Bx, int Cp, int Cj, - long double Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - csr_eldiv_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bj, npy_clongdouble_wrapper Bx, - int Cp, int Cj, npy_clongdouble_wrapper Cx) - """ - return _csr.csr_eldiv_csr(*args) + return _csr.csr_eldiv_csr(*args) def csr_plus_csr(*args): + """ + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, + int Bp, int Bj, signed char Bx, int Cp, int Cj, + signed char Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + int Bp, int Bj, unsigned char Bx, int Cp, + int Cj, unsigned char Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, + int Bj, short Bx, int Cp, int Cj, short Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + int Bp, int Bj, unsigned short Bx, int Cp, + int Cj, unsigned short Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, + int Bj, int Bx, int Cp, int Cj, int Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + int Bp, int Bj, unsigned int Bx, int Cp, + int Cj, unsigned int Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, + int Bp, int Bj, long long Bx, int Cp, int Cj, + long long Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, + int Bj, float Bx, int Cp, int Cj, float Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, + int Bj, double Bx, int Cp, int Cj, double Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, + int Bp, int Bj, long double Bx, int Cp, int Cj, + long double Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + csr_plus_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bj, npy_clongdouble_wrapper Bx, + int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, - int Bp, int Bj, signed char Bx, int Cp, int Cj, - signed char Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - int Bp, int Bj, unsigned char Bx, int Cp, - int Cj, unsigned char Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, - int Bj, short Bx, int Cp, int Cj, short Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - int Bp, int Bj, unsigned short Bx, int Cp, - int Cj, unsigned short Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, - int Bj, int Bx, int Cp, int Cj, int Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - int Bp, int Bj, unsigned int Bx, int Cp, - int Cj, unsigned int Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, - int Bp, int Bj, long long Bx, int Cp, int Cj, - long long Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, - int Bj, float Bx, int Cp, int Cj, float Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, - int Bj, double Bx, int Cp, int Cj, double Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, - int Bp, int Bj, long double Bx, int Cp, int Cj, - long double Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - csr_plus_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bj, npy_clongdouble_wrapper Bx, - int Cp, int Cj, npy_clongdouble_wrapper Cx) - """ - return _csr.csr_plus_csr(*args) + return _csr.csr_plus_csr(*args) def csr_minus_csr(*args): + """ + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, + int Bp, int Bj, signed char Bx, int Cp, int Cj, + signed char Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + int Bp, int Bj, unsigned char Bx, int Cp, + int Cj, unsigned char Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, + int Bj, short Bx, int Cp, int Cj, short Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + int Bp, int Bj, unsigned short Bx, int Cp, + int Cj, unsigned short Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, + int Bj, int Bx, int Cp, int Cj, int Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + int Bp, int Bj, unsigned int Bx, int Cp, + int Cj, unsigned int Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, + int Bp, int Bj, long long Bx, int Cp, int Cj, + long long Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + int Bp, int Bj, unsigned long long Bx, + int Cp, int Cj, unsigned long long Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, + int Bj, float Bx, int Cp, int Cj, float Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, + int Bj, double Bx, int Cp, int Cj, double Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, + int Bp, int Bj, long double Bx, int Cp, int Cj, + long double Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + int Bp, int Bj, npy_cfloat_wrapper Bx, + int Cp, int Cj, npy_cfloat_wrapper Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + int Bp, int Bj, npy_cdouble_wrapper Bx, + int Cp, int Cj, npy_cdouble_wrapper Cx) + csr_minus_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + int Bp, int Bj, npy_clongdouble_wrapper Bx, + int Cp, int Cj, npy_clongdouble_wrapper Cx) """ - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, - int Bp, int Bj, signed char Bx, int Cp, int Cj, - signed char Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - int Bp, int Bj, unsigned char Bx, int Cp, - int Cj, unsigned char Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, short Ax, int Bp, - int Bj, short Bx, int Cp, int Cj, short Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - int Bp, int Bj, unsigned short Bx, int Cp, - int Cj, unsigned short Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, int Ax, int Bp, - int Bj, int Bx, int Cp, int Cj, int Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - int Bp, int Bj, unsigned int Bx, int Cp, - int Cj, unsigned int Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, long long Ax, - int Bp, int Bj, long long Bx, int Cp, int Cj, - long long Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - int Bp, int Bj, unsigned long long Bx, - int Cp, int Cj, unsigned long long Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, float Ax, int Bp, - int Bj, float Bx, int Cp, int Cj, float Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, double Ax, int Bp, - int Bj, double Bx, int Cp, int Cj, double Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, long double Ax, - int Bp, int Bj, long double Bx, int Cp, int Cj, - long double Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - int Bp, int Bj, npy_cfloat_wrapper Bx, - int Cp, int Cj, npy_cfloat_wrapper Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - int Bp, int Bj, npy_cdouble_wrapper Bx, - int Cp, int Cj, npy_cdouble_wrapper Cx) - csr_minus_csr(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - int Bp, int Bj, npy_clongdouble_wrapper Bx, - int Cp, int Cj, npy_clongdouble_wrapper Cx) - """ - return _csr.csr_minus_csr(*args) + return _csr.csr_minus_csr(*args) def csr_sort_indices(*args): + """ + csr_sort_indices(int n_row, int Ap, int Aj, signed char Ax) + csr_sort_indices(int n_row, int Ap, int Aj, unsigned char Ax) + csr_sort_indices(int n_row, int Ap, int Aj, short Ax) + csr_sort_indices(int n_row, int Ap, int Aj, unsigned short Ax) + csr_sort_indices(int n_row, int Ap, int Aj, int Ax) + csr_sort_indices(int n_row, int Ap, int Aj, unsigned int Ax) + csr_sort_indices(int n_row, int Ap, int Aj, long long Ax) + csr_sort_indices(int n_row, int Ap, int Aj, unsigned long long Ax) + csr_sort_indices(int n_row, int Ap, int Aj, float Ax) + csr_sort_indices(int n_row, int Ap, int Aj, double Ax) + csr_sort_indices(int n_row, int Ap, int Aj, long double Ax) + csr_sort_indices(int n_row, int Ap, int Aj, npy_cfloat_wrapper Ax) + csr_sort_indices(int n_row, int Ap, int Aj, npy_cdouble_wrapper Ax) + csr_sort_indices(int n_row, int Ap, int Aj, npy_clongdouble_wrapper Ax) """ - csr_sort_indices(int n_row, int Ap, int Aj, signed char Ax) - csr_sort_indices(int n_row, int Ap, int Aj, unsigned char Ax) - csr_sort_indices(int n_row, int Ap, int Aj, short Ax) - csr_sort_indices(int n_row, int Ap, int Aj, unsigned short Ax) - csr_sort_indices(int n_row, int Ap, int Aj, int Ax) - csr_sort_indices(int n_row, int Ap, int Aj, unsigned int Ax) - csr_sort_indices(int n_row, int Ap, int Aj, long long Ax) - csr_sort_indices(int n_row, int Ap, int Aj, unsigned long long Ax) - csr_sort_indices(int n_row, int Ap, int Aj, float Ax) - csr_sort_indices(int n_row, int Ap, int Aj, double Ax) - csr_sort_indices(int n_row, int Ap, int Aj, long double Ax) - csr_sort_indices(int n_row, int Ap, int Aj, npy_cfloat_wrapper Ax) - csr_sort_indices(int n_row, int Ap, int Aj, npy_cdouble_wrapper Ax) - csr_sort_indices(int n_row, int Ap, int Aj, npy_clongdouble_wrapper Ax) - """ - return _csr.csr_sort_indices(*args) + return _csr.csr_sort_indices(*args) def csr_eliminate_zeros(*args): + """ + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, signed char Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned char Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, short Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned short Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, int Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned int Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, long long Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, float Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, double Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, long double Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax) + csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax) """ - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, signed char Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned char Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, short Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned short Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, int Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned int Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, long long Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, float Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, double Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, long double Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax) - csr_eliminate_zeros(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax) - """ - return _csr.csr_eliminate_zeros(*args) + return _csr.csr_eliminate_zeros(*args) def csr_sum_duplicates(*args): + """ + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, signed char Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned char Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, short Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned short Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, int Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned int Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, long long Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, float Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, double Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, long double Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax) + csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax) """ - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, signed char Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned char Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, short Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned short Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, int Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned int Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, long long Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, float Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, double Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, long double Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax) - csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax) - """ - return _csr.csr_sum_duplicates(*args) + return _csr.csr_sum_duplicates(*args) def get_csr_submatrix(*args): + """ + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, signed char Ax, + int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(signed char)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, + int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(unsigned char)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, short Ax, int ir0, + int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(short)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, + int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(unsigned short)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, int Ax, int ir0, + int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(int)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, + int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(unsigned int)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, long long Ax, + int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(long long)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, + int ir0, int ir1, int ic0, int ic1, + std::vector<(int)> Bp, std::vector<(int)> Bj, + std::vector<(unsigned long long)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, float Ax, int ir0, + int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(float)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, double Ax, int ir0, + int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(double)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, long double Ax, + int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, + std::vector<(int)> Bj, std::vector<(long double)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, + int ir0, int ir1, int ic0, int ic1, + std::vector<(int)> Bp, std::vector<(int)> Bj, + std::vector<(npy_cfloat_wrapper)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, + int ir0, int ir1, int ic0, int ic1, + std::vector<(int)> Bp, std::vector<(int)> Bj, + std::vector<(npy_cdouble_wrapper)> Bx) + get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, + int ir0, int ir1, int ic0, int ic1, + std::vector<(int)> Bp, std::vector<(int)> Bj, + std::vector<(npy_clongdouble_wrapper)> Bx) """ - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, signed char Ax, - int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(signed char)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned char Ax, - int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(unsigned char)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, short Ax, int ir0, - int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(short)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned short Ax, - int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(unsigned short)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, int Ax, int ir0, - int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(int)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned int Ax, - int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(unsigned int)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, long long Ax, - int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(long long)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, unsigned long long Ax, - int ir0, int ir1, int ic0, int ic1, - std::vector<(int)> Bp, std::vector<(int)> Bj, - std::vector<(unsigned long long)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, float Ax, int ir0, - int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(float)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, double Ax, int ir0, - int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(double)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, long double Ax, - int ir0, int ir1, int ic0, int ic1, std::vector<(int)> Bp, - std::vector<(int)> Bj, std::vector<(long double)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax, - int ir0, int ir1, int ic0, int ic1, - std::vector<(int)> Bp, std::vector<(int)> Bj, - std::vector<(npy_cfloat_wrapper)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax, - int ir0, int ir1, int ic0, int ic1, - std::vector<(int)> Bp, std::vector<(int)> Bj, - std::vector<(npy_cdouble_wrapper)> Bx) - get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, npy_clongdouble_wrapper Ax, - int ir0, int ir1, int ic0, int ic1, - std::vector<(int)> Bp, std::vector<(int)> Bj, - std::vector<(npy_clongdouble_wrapper)> Bx) - """ - return _csr.get_csr_submatrix(*args) + return _csr.get_csr_submatrix(*args) + Modified: trunk/scipy/sparse/sparsetools/csr_wrap.cxx =================================================================== --- trunk/scipy/sparse/sparsetools/csr_wrap.cxx 2008-08-12 19:20:31 UTC (rev 4644) +++ trunk/scipy/sparse/sparsetools/csr_wrap.cxx 2008-08-14 20:44:07 UTC (rev 4645) @@ -42270,23 +42270,23 @@ get_csr_submatrix< int,signed char >(arg1,arg2,(int const (*))arg3,(int const (*))arg4,(signed char const (*))arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); resultobj = SWIG_Py_Void(); { - int length = (arg10)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg10))[0]),sizeof(int)*length); + npy_intp length = (arg10)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg10))[0]), sizeof(int)*length); delete arg10; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg11)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg11))[0]),sizeof(int)*length); + npy_intp length = (arg11)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg11))[0]), sizeof(int)*length); delete arg11; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg12)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_BYTE); - memcpy(PyArray_DATA(obj),&((*(arg12))[0]),sizeof(signed char)*length); + npy_intp length = (arg12)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_BYTE); + memcpy(PyArray_DATA(obj), &((*(arg12))[0]), sizeof(signed char)*length); delete arg12; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } @@ -42447,23 +42447,23 @@ get_csr_submatrix< int,unsigned char >(arg1,arg2,(int const (*))arg3,(int const (*))arg4,(unsigned char const (*))arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); resultobj = SWIG_Py_Void(); { - int length = (arg10)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg10))[0]),sizeof(int)*length); + npy_intp length = (arg10)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg10))[0]), sizeof(int)*length); delete arg10; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg11)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg11))[0]),sizeof(int)*length); + npy_intp length = (arg11)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg11))[0]), sizeof(int)*length); delete arg11; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg12)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_UBYTE); - memcpy(PyArray_DATA(obj),&((*(arg12))[0]),sizeof(unsigned char)*length); + npy_intp length = (arg12)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_UBYTE); + memcpy(PyArray_DATA(obj), &((*(arg12))[0]), sizeof(unsigned char)*length); delete arg12; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } @@ -42624,23 +42624,23 @@ get_csr_submatrix< int,short >(arg1,arg2,(int const (*))arg3,(int const (*))arg4,(short const (*))arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); resultobj = SWIG_Py_Void(); { - int length = (arg10)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg10))[0]),sizeof(int)*length); + npy_intp length = (arg10)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg10))[0]), sizeof(int)*length); delete arg10; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg11)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg11))[0]),sizeof(int)*length); + npy_intp length = (arg11)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg11))[0]), sizeof(int)*length); delete arg11; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg12)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_SHORT); - memcpy(PyArray_DATA(obj),&((*(arg12))[0]),sizeof(short)*length); + npy_intp length = (arg12)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_SHORT); + memcpy(PyArray_DATA(obj), &((*(arg12))[0]), sizeof(short)*length); delete arg12; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } @@ -42801,23 +42801,23 @@ get_csr_submatrix< int,unsigned short >(arg1,arg2,(int const (*))arg3,(int const (*))arg4,(unsigned short const (*))arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); resultobj = SWIG_Py_Void(); { - int length = (arg10)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg10))[0]),sizeof(int)*length); + npy_intp length = (arg10)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg10))[0]), sizeof(int)*length); delete arg10; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg11)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg11))[0]),sizeof(int)*length); + npy_intp length = (arg11)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg11))[0]), sizeof(int)*length); delete arg11; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg12)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_USHORT); - memcpy(PyArray_DATA(obj),&((*(arg12))[0]),sizeof(unsigned short)*length); + npy_intp length = (arg12)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_USHORT); + memcpy(PyArray_DATA(obj), &((*(arg12))[0]), sizeof(unsigned short)*length); delete arg12; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } @@ -42978,23 +42978,23 @@ get_csr_submatrix< int,int >(arg1,arg2,(int const (*))arg3,(int const (*))arg4,(int const (*))arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); resultobj = SWIG_Py_Void(); { - int length = (arg10)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg10))[0]),sizeof(int)*length); + npy_intp length = (arg10)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg10))[0]), sizeof(int)*length); delete arg10; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg11)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg11))[0]),sizeof(int)*length); + npy_intp length = (arg11)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg11))[0]), sizeof(int)*length); delete arg11; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg12)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg12))[0]),sizeof(int)*length); + npy_intp length = (arg12)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg12))[0]), sizeof(int)*length); delete arg12; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } @@ -43155,23 +43155,23 @@ get_csr_submatrix< int,unsigned int >(arg1,arg2,(int const (*))arg3,(int const (*))arg4,(unsigned int const (*))arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); resultobj = SWIG_Py_Void(); { - int length = (arg10)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg10))[0]),sizeof(int)*length); + npy_intp length = (arg10)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg10))[0]), sizeof(int)*length); delete arg10; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg11)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg11))[0]),sizeof(int)*length); + npy_intp length = (arg11)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg11))[0]), sizeof(int)*length); delete arg11; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg12)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_UINT); - memcpy(PyArray_DATA(obj),&((*(arg12))[0]),sizeof(unsigned int)*length); + npy_intp length = (arg12)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_UINT); + memcpy(PyArray_DATA(obj), &((*(arg12))[0]), sizeof(unsigned int)*length); delete arg12; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } @@ -43332,23 +43332,23 @@ get_csr_submatrix< int,long long >(arg1,arg2,(int const (*))arg3,(int const (*))arg4,(long long const (*))arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); resultobj = SWIG_Py_Void(); { - int length = (arg10)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg10))[0]),sizeof(int)*length); + npy_intp length = (arg10)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg10))[0]), sizeof(int)*length); delete arg10; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg11)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg11))[0]),sizeof(int)*length); + npy_intp length = (arg11)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg11))[0]), sizeof(int)*length); delete arg11; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg12)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_LONGLONG); - memcpy(PyArray_DATA(obj),&((*(arg12))[0]),sizeof(long long)*length); + npy_intp length = (arg12)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_LONGLONG); + memcpy(PyArray_DATA(obj), &((*(arg12))[0]), sizeof(long long)*length); delete arg12; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } @@ -43509,23 +43509,23 @@ get_csr_submatrix< int,unsigned long long >(arg1,arg2,(int const (*))arg3,(int const (*))arg4,(unsigned long long const (*))arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); resultobj = SWIG_Py_Void(); { - int length = (arg10)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg10))[0]),sizeof(int)*length); + npy_intp length = (arg10)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg10))[0]), sizeof(int)*length); delete arg10; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg11)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg11))[0]),sizeof(int)*length); + npy_intp length = (arg11)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg11))[0]), sizeof(int)*length); delete arg11; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg12)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_ULONGLONG); - memcpy(PyArray_DATA(obj),&((*(arg12))[0]),sizeof(unsigned long long)*length); + npy_intp length = (arg12)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_ULONGLONG); + memcpy(PyArray_DATA(obj), &((*(arg12))[0]), sizeof(unsigned long long)*length); delete arg12; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } @@ -43686,23 +43686,23 @@ get_csr_submatrix< int,float >(arg1,arg2,(int const (*))arg3,(int const (*))arg4,(float const (*))arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); resultobj = SWIG_Py_Void(); { - int length = (arg10)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg10))[0]),sizeof(int)*length); + npy_intp length = (arg10)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg10))[0]), sizeof(int)*length); delete arg10; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg11)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg11))[0]),sizeof(int)*length); + npy_intp length = (arg11)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg11))[0]), sizeof(int)*length); delete arg11; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg12)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_FLOAT); - memcpy(PyArray_DATA(obj),&((*(arg12))[0]),sizeof(float)*length); + npy_intp length = (arg12)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_FLOAT); + memcpy(PyArray_DATA(obj), &((*(arg12))[0]), sizeof(float)*length); delete arg12; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } @@ -43863,23 +43863,23 @@ get_csr_submatrix< int,double >(arg1,arg2,(int const (*))arg3,(int const (*))arg4,(double const (*))arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); resultobj = SWIG_Py_Void(); { - int length = (arg10)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg10))[0]),sizeof(int)*length); + npy_intp length = (arg10)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg10))[0]), sizeof(int)*length); delete arg10; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg11)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg11))[0]),sizeof(int)*length); + npy_intp length = (arg11)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg11))[0]), sizeof(int)*length); delete arg11; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg12)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_DOUBLE); - memcpy(PyArray_DATA(obj),&((*(arg12))[0]),sizeof(double)*length); + npy_intp length = (arg12)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_DOUBLE); + memcpy(PyArray_DATA(obj), &((*(arg12))[0]), sizeof(double)*length); delete arg12; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } @@ -44040,23 +44040,23 @@ get_csr_submatrix< int,long double >(arg1,arg2,(int const (*))arg3,(int const (*))arg4,(long double const (*))arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); resultobj = SWIG_Py_Void(); { - int length = (arg10)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg10))[0]),sizeof(int)*length); + npy_intp length = (arg10)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg10))[0]), sizeof(int)*length); delete arg10; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg11)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg11))[0]),sizeof(int)*length); + npy_intp length = (arg11)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg11))[0]), sizeof(int)*length); delete arg11; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg12)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_LONGDOUBLE); - memcpy(PyArray_DATA(obj),&((*(arg12))[0]),sizeof(long double)*length); + npy_intp length = (arg12)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_LONGDOUBLE); + memcpy(PyArray_DATA(obj), &((*(arg12))[0]), sizeof(long double)*length); delete arg12; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } @@ -44217,23 +44217,23 @@ get_csr_submatrix< int,npy_cfloat_wrapper >(arg1,arg2,(int const (*))arg3,(int const (*))arg4,(npy_cfloat_wrapper const (*))arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); resultobj = SWIG_Py_Void(); { - int length = (arg10)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg10))[0]),sizeof(int)*length); + npy_intp length = (arg10)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg10))[0]), sizeof(int)*length); delete arg10; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg11)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg11))[0]),sizeof(int)*length); + npy_intp length = (arg11)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg11))[0]), sizeof(int)*length); delete arg11; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg12)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_CFLOAT); - memcpy(PyArray_DATA(obj),&((*(arg12))[0]),sizeof(npy_cfloat_wrapper)*length); + npy_intp length = (arg12)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_CFLOAT); + memcpy(PyArray_DATA(obj), &((*(arg12))[0]), sizeof(npy_cfloat_wrapper)*length); delete arg12; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } @@ -44394,23 +44394,23 @@ get_csr_submatrix< int,npy_cdouble_wrapper >(arg1,arg2,(int const (*))arg3,(int const (*))arg4,(npy_cdouble_wrapper const (*))arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); resultobj = SWIG_Py_Void(); { - int length = (arg10)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg10))[0]),sizeof(int)*length); + npy_intp length = (arg10)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg10))[0]), sizeof(int)*length); delete arg10; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg11)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg11))[0]),sizeof(int)*length); + npy_intp length = (arg11)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg11))[0]), sizeof(int)*length); delete arg11; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg12)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_CDOUBLE); - memcpy(PyArray_DATA(obj),&((*(arg12))[0]),sizeof(npy_cdouble_wrapper)*length); + npy_intp length = (arg12)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_CDOUBLE); + memcpy(PyArray_DATA(obj), &((*(arg12))[0]), sizeof(npy_cdouble_wrapper)*length); delete arg12; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } @@ -44571,23 +44571,23 @@ get_csr_submatrix< int,npy_clongdouble_wrapper >(arg1,arg2,(int const (*))arg3,(int const (*))arg4,(npy_clongdouble_wrapper const (*))arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); resultobj = SWIG_Py_Void(); { - int length = (arg10)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg10))[0]),sizeof(int)*length); + npy_intp length = (arg10)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg10))[0]), sizeof(int)*length); delete arg10; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg11)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_INT); - memcpy(PyArray_DATA(obj),&((*(arg11))[0]),sizeof(int)*length); + npy_intp length = (arg11)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_INT); + memcpy(PyArray_DATA(obj), &((*(arg11))[0]), sizeof(int)*length); delete arg11; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } { - int length = (arg12)->size(); - PyObject *obj = PyArray_FromDims(1, &length,PyArray_CLONGDOUBLE); - memcpy(PyArray_DATA(obj),&((*(arg12))[0]),sizeof(npy_clongdouble_wrapper)*length); + npy_intp length = (arg12)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length,PyArray_CLONGDOUBLE); + memcpy(PyArray_DATA(obj), &((*(arg12))[0]), sizeof(npy_clongdouble_wrapper)*length); delete arg12; resultobj = helper_appendToTuple( resultobj, (PyObject *)obj ); } Modified: trunk/scipy/sparse/sparsetools/dia.py =================================================================== --- trunk/scipy/sparse/sparsetools/dia.py 2008-08-12 19:20:31 UTC (rev 4644) +++ trunk/scipy/sparse/sparsetools/dia.py 2008-08-14 20:44:07 UTC (rev 4645) @@ -51,39 +51,40 @@ def dia_matvec(*args): + """ + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + signed char diags, signed char Xx, signed char Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + unsigned char diags, unsigned char Xx, unsigned char Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + short diags, short Xx, short Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + unsigned short diags, unsigned short Xx, + unsigned short Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + int diags, int Xx, int Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + unsigned int diags, unsigned int Xx, unsigned int Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + long long diags, long long Xx, long long Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + unsigned long long diags, unsigned long long Xx, + unsigned long long Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + float diags, float Xx, float Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + double diags, double Xx, double Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + long double diags, long double Xx, long double Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + npy_cfloat_wrapper diags, npy_cfloat_wrapper Xx, + npy_cfloat_wrapper Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + npy_cdouble_wrapper diags, npy_cdouble_wrapper Xx, + npy_cdouble_wrapper Yx) + dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, + npy_clongdouble_wrapper diags, npy_clongdouble_wrapper Xx, + npy_clongdouble_wrapper Yx) """ - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - signed char diags, signed char Xx, signed char Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - unsigned char diags, unsigned char Xx, unsigned char Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - short diags, short Xx, short Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - unsigned short diags, unsigned short Xx, - unsigned short Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - int diags, int Xx, int Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - unsigned int diags, unsigned int Xx, unsigned int Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - long long diags, long long Xx, long long Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - unsigned long long diags, unsigned long long Xx, - unsigned long long Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - float diags, float Xx, float Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - double diags, double Xx, double Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - long double diags, long double Xx, long double Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - npy_cfloat_wrapper diags, npy_cfloat_wrapper Xx, - npy_cfloat_wrapper Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - npy_cdouble_wrapper diags, npy_cdouble_wrapper Xx, - npy_cdouble_wrapper Yx) - dia_matvec(int n_row, int n_col, int n_diags, int L, int offsets, - npy_clongdouble_wrapper diags, npy_clongdouble_wrapper Xx, - npy_clongdouble_wrapper Yx) - """ - return _dia.dia_matvec(*args) + return _dia.dia_matvec(*args) + Modified: trunk/scipy/sparse/sparsetools/numpy.i =================================================================== --- trunk/scipy/sparse/sparsetools/numpy.i 2008-08-12 19:20:31 UTC (rev 4644) +++ trunk/scipy/sparse/sparsetools/numpy.i 2008-08-14 20:44:07 UTC (rev 4645) @@ -522,9 +522,9 @@ $1 = tmp; }; %typemap( argout ) std::vector* array_argout { - int length = ($1)->size(); - PyObject *obj = PyArray_FromDims(1, &length, ##atype); - memcpy(PyArray_DATA(obj),&((*($1))[0]),sizeof(ctype)*length); + npy_intp length = ($1)->size(); + PyObject *obj = PyArray_SimpleNew(1, &length, ##atype); + memcpy(PyArray_DATA(obj), &((*($1))[0]), sizeof(ctype)*length); delete $1; $result = helper_appendToTuple( $result, (PyObject *)obj ); }; From scipy-svn at scipy.org Sat Aug 16 20:13:41 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Sat, 16 Aug 2008 19:13:41 -0500 (CDT) Subject: [Scipy-svn] r4646 - branches Message-ID: <20080817001341.C352239C018@scipy.org> Author: jarrod.millman Date: 2008-08-16 19:13:32 -0500 (Sat, 16 Aug 2008) New Revision: 4646 Added: branches/sandbox/ Log: preparing to remove the sandbox from scipy mainline Copied: branches/sandbox (from rev 4645, trunk) From scipy-svn at scipy.org Sat Aug 16 20:29:04 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Sat, 16 Aug 2008 19:29:04 -0500 (CDT) Subject: [Scipy-svn] r4647 - in trunk/scipy: . sparse/linalg/eigen/lobpcg/tests sparse/linalg/isolve Message-ID: <20080817002904.A26FB39C018@scipy.org> Author: jarrod.millman Date: 2008-08-16 19:28:59 -0500 (Sat, 16 Aug 2008) New Revision: 4647 Removed: trunk/scipy/sandbox/ Modified: trunk/scipy/__init__.py trunk/scipy/setup.py trunk/scipy/setupscons.py trunk/scipy/sparse/linalg/eigen/lobpcg/tests/benchmark.py trunk/scipy/sparse/linalg/isolve/minres.py Log: remove sandbox Modified: trunk/scipy/__init__.py =================================================================== --- trunk/scipy/__init__.py 2008-08-17 00:13:32 UTC (rev 4646) +++ trunk/scipy/__init__.py 2008-08-17 00:28:59 UTC (rev 4647) @@ -66,7 +66,7 @@ # Remove subpackage names from __all__ such that they are not imported via # "from scipy import *". This works around a numpy bug present in < 1.2. subpackages = """cluster constants fftpack integrate interpolate io lib linalg -linsolve maxentropy misc ndimage odr optimize sandbox signal sparse special +linsolve maxentropy misc ndimage odr optimize signal sparse special splinalg stats stsci weave""".split() for name in subpackages: try: Modified: trunk/scipy/setup.py =================================================================== --- trunk/scipy/setup.py 2008-08-17 00:13:32 UTC (rev 4646) +++ trunk/scipy/setup.py 2008-08-17 00:28:59 UTC (rev 4647) @@ -15,7 +15,6 @@ config.add_subpackage('misc') config.add_subpackage('odr') config.add_subpackage('optimize') - config.add_subpackage('sandbox') config.add_subpackage('signal') config.add_subpackage('sparse') config.add_subpackage('special') Modified: trunk/scipy/setupscons.py =================================================================== --- trunk/scipy/setupscons.py 2008-08-17 00:13:32 UTC (rev 4646) +++ trunk/scipy/setupscons.py 2008-08-17 00:28:59 UTC (rev 4647) @@ -19,7 +19,6 @@ config.add_subpackage('misc') config.add_subpackage('odr') config.add_subpackage('optimize') - config.add_subpackage('sandbox') config.add_subpackage('signal') config.add_subpackage('sparse') config.add_subpackage('special') Modified: trunk/scipy/sparse/linalg/eigen/lobpcg/tests/benchmark.py =================================================================== --- trunk/scipy/sparse/linalg/eigen/lobpcg/tests/benchmark.py 2008-08-17 00:13:32 UTC (rev 4646) +++ trunk/scipy/sparse/linalg/eigen/lobpcg/tests/benchmark.py 2008-08-17 00:28:59 UTC (rev 4647) @@ -1,5 +1,5 @@ from scipy import * -from scipy.sandbox import lobpcg +from scipy.sparese.linalg import lobpcg from symeig import symeig from pylab import plot, show, legend, xlabel, ylabel set_printoptions(precision=3,linewidth=90) Modified: trunk/scipy/sparse/linalg/isolve/minres.py =================================================================== --- trunk/scipy/sparse/linalg/isolve/minres.py 2008-08-17 00:13:32 UTC (rev 4646) +++ trunk/scipy/sparse/linalg/isolve/minres.py 2008-08-17 00:28:59 UTC (rev 4647) @@ -281,7 +281,6 @@ from scipy.linalg import norm from scipy.sparse import spdiags from scipy.sparse.linalg import cg - #from scipy.sandbox.multigrid import * n = 10 From scipy-svn at scipy.org Sat Aug 16 20:34:29 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Sat, 16 Aug 2008 19:34:29 -0500 (CDT) Subject: [Scipy-svn] r4648 - trunk/scipy/sparse/linalg/eigen/lobpcg/tests Message-ID: <20080817003429.A8C7939C018@scipy.org> Author: jarrod.millman Date: 2008-08-16 19:34:27 -0500 (Sat, 16 Aug 2008) New Revision: 4648 Modified: trunk/scipy/sparse/linalg/eigen/lobpcg/tests/benchmark.py Log: typo Modified: trunk/scipy/sparse/linalg/eigen/lobpcg/tests/benchmark.py =================================================================== --- trunk/scipy/sparse/linalg/eigen/lobpcg/tests/benchmark.py 2008-08-17 00:28:59 UTC (rev 4647) +++ trunk/scipy/sparse/linalg/eigen/lobpcg/tests/benchmark.py 2008-08-17 00:34:27 UTC (rev 4648) @@ -1,5 +1,5 @@ from scipy import * -from scipy.sparese.linalg import lobpcg +from scipy.sparse.linalg import lobpcg from symeig import symeig from pylab import plot, show, legend, xlabel, ylabel set_printoptions(precision=3,linewidth=90) From scipy-svn at scipy.org Mon Aug 18 01:37:28 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 18 Aug 2008 00:37:28 -0500 (CDT) Subject: [Scipy-svn] r4649 - in branches/sandbox/scipy/sandbox/mkufunc: . examples mkufunc Message-ID: <20080818053728.E375D39C0F7@scipy.org> Author: ilan Date: 2008-08-18 00:37:28 -0500 (Mon, 18 Aug 2008) New Revision: 4649 Modified: branches/sandbox/scipy/sandbox/mkufunc/TODO.txt branches/sandbox/scipy/sandbox/mkufunc/examples/benchmark.py branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_c.py branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_py.py branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py branches/sandbox/scipy/sandbox/mkufunc/setup.py Log: Made things work with Python 2.4 and added items to TODO Modified: branches/sandbox/scipy/sandbox/mkufunc/TODO.txt =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/TODO.txt 2008-08-17 00:34:27 UTC (rev 4648) +++ branches/sandbox/scipy/sandbox/mkufunc/TODO.txt 2008-08-18 05:37:28 UTC (rev 4649) @@ -7,3 +7,9 @@ - add Csrc attribute to ufunc object + +- improved function hash + +- rename to fast_vectorize + +- which python version should this work with? Modified: branches/sandbox/scipy/sandbox/mkufunc/examples/benchmark.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/examples/benchmark.py 2008-08-17 00:34:27 UTC (rev 4648) +++ branches/sandbox/scipy/sandbox/mkufunc/examples/benchmark.py 2008-08-18 05:37:28 UTC (rev 4649) @@ -1,6 +1,7 @@ #!/usr/bin/env python from math import sin, cos -import time, hashlib +import time +import md5 from numpy import linspace, vectorize, allclose, empty_like from scipy import weave @@ -51,7 +52,7 @@ ufunc_info = weave.base_info.custom_info() ufunc_info.add_header('"numpy/ufuncobject.h"') -ufunc = weave.inline('/*' + hashlib.md5(support_code).hexdigest() + '''*/ +ufunc = weave.inline('/*' + md5.md5(support_code).hexdigest() + '''*/ import_ufunc(); return_val = PyUFunc_FromFuncAndData( Modified: branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_c.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_c.py 2008-08-17 00:34:27 UTC (rev 4648) +++ branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_c.py 2008-08-18 05:37:28 UTC (rev 4649) @@ -1,5 +1,5 @@ #!/usr/bin/env python -import hashlib +import md5 from numpy import array from scipy import weave @@ -53,7 +53,7 @@ ufunc_info = weave.base_info.custom_info() ufunc_info.add_header('"numpy/ufuncobject.h"') -mandel = weave.inline('/*' + hashlib.md5(support_code).hexdigest() + '''*/ +mandel = weave.inline('/*' + md5.md5(support_code).hexdigest() + '''*/ import_ufunc(); return_val = PyUFunc_FromFuncAndData( @@ -78,5 +78,5 @@ assert mandel(-1, .3) == 36 assert mandel(0, 0) == -1 assert mandel(10, 10) == 1 - assert all(mandel(array([-1, 0, 10]), array([.3, 0, 10])) == - array([36, -1, 1])) + assert (mandel(array([-1, 0, 10]), array([.3, 0, 10])) == + array([36, -1, 1])).all() Modified: branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_py.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_py.py 2008-08-17 00:34:27 UTC (rev 4648) +++ branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_py.py 2008-08-18 05:37:28 UTC (rev 4649) @@ -27,5 +27,6 @@ assert mandel(-1, .3) == 36 assert mandel(0, 0) == -1 assert mandel(10, 10) == 1 - assert all(mandel(array([-1, 0, 10]), array([.3, 0, 10])) == - array([36, -1, 1])) + assert (mandel(array([-1, 0, 10]), array([.3, 0, 10])) == + array([36, -1, 1])).all() + Modified: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py 2008-08-17 00:34:27 UTC (rev 4648) +++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py 2008-08-18 05:37:28 UTC (rev 4649) @@ -7,7 +7,7 @@ import re import os, os.path import cStringIO -import hashlib +import md5 from types import FunctionType import numpy @@ -21,8 +21,7 @@ """ Return a MD5 hash for a function object as string. """ co = f.func_code - return hashlib.md5(co.co_code + repr(co.co_names) + repr(salt) - ).hexdigest() + return md5.md5(co.co_code + repr(co.co_names) + repr(salt)).hexdigest() def translate(f, argtypes): Modified: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py 2008-08-17 00:34:27 UTC (rev 4648) +++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py 2008-08-18 05:37:28 UTC (rev 4649) @@ -1,6 +1,6 @@ import unittest -from mkufunc.api import func_hash +from api import func_hash class Tests(unittest.TestCase): Modified: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py 2008-08-17 00:34:27 UTC (rev 4648) +++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py 2008-08-18 05:37:28 UTC (rev 4649) @@ -243,8 +243,10 @@ def f(i): return i % 5 - self.assert_(all(f(range(7)) == array([0, 1, 2, 3, 4, 0, 1]))) - self.assert_(all(f(arange(8)) == array([0, 1, 2, 3, 4, 0, 1, 2]))) + for i in xrange(100): + self.assertEqual(f(i), i % 5) + + self.assert_((f(arange(8)) == array([0, 1, 2, 3, 4, 0, 1, 2])).all()) class Control_Flow_Tests(unittest.TestCase): Modified: branches/sandbox/scipy/sandbox/mkufunc/setup.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/setup.py 2008-08-17 00:34:27 UTC (rev 4648) +++ branches/sandbox/scipy/sandbox/mkufunc/setup.py 2008-08-18 05:37:28 UTC (rev 4649) @@ -6,10 +6,9 @@ description = 'C compiled UFuncs from python source', name = "mkufunc", - version = "0.1", - + zip_safe = False, package_data = {'': ['*.h']}, - packages = find_packages(), - install_requires = ['scipy >= 0.6.0'] + packages = find_packages() + #install_requires = ['scipy >= 0.6.0'] ) From scipy-svn at scipy.org Mon Aug 18 16:40:55 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 18 Aug 2008 15:40:55 -0500 (CDT) Subject: [Scipy-svn] r4650 - in branches/sandbox/scipy/sandbox/mkufunc: . examples mkufunc Message-ID: <20080818204055.3634439C0F7@scipy.org> Author: ilan Date: 2008-08-18 15:40:53 -0500 (Mon, 18 Aug 2008) New Revision: 4650 Added: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/fast_vectorize.py branches/sandbox/scipy/sandbox/mkufunc/mkufunc/func_hash.py branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_fast_vectorize.py Removed: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py Modified: branches/sandbox/scipy/sandbox/mkufunc/TODO.txt branches/sandbox/scipy/sandbox/mkufunc/examples/benchmark.py branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_py.py branches/sandbox/scipy/sandbox/mkufunc/examples/primes.py branches/sandbox/scipy/sandbox/mkufunc/mkufunc/__init__.py branches/sandbox/scipy/sandbox/mkufunc/mkufunc/driver.py branches/sandbox/scipy/sandbox/mkufunc/mkufunc/interactive.py branches/sandbox/scipy/sandbox/mkufunc/setup.py Log: Numerous changes: renaming, improved hash functions, cleanup. Modified: branches/sandbox/scipy/sandbox/mkufunc/TODO.txt =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/TODO.txt 2008-08-18 05:37:28 UTC (rev 4649) +++ branches/sandbox/scipy/sandbox/mkufunc/TODO.txt 2008-08-18 20:40:53 UTC (rev 4650) @@ -1,15 +1,9 @@ - Documentation -- improve caching of pypy compiler output - - think about shipping issues (using weave ext_tools) - add Csrc attribute to ufunc object +- see if monkeypatch of pypy modules is feasible/desired -- improved function hash - -- rename to fast_vectorize - -- which python version should this work with? Modified: branches/sandbox/scipy/sandbox/mkufunc/examples/benchmark.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/examples/benchmark.py 2008-08-18 05:37:28 UTC (rev 4649) +++ branches/sandbox/scipy/sandbox/mkufunc/examples/benchmark.py 2008-08-18 20:40:53 UTC (rev 4650) @@ -6,7 +6,9 @@ from numpy import linspace, vectorize, allclose, empty_like from scipy import weave -from mkufunc.api import mkufunc +import sys +sys.path.append('../mkufunc') +from fast_vectorize import fast_vectorize def f(x): @@ -15,7 +17,7 @@ vfunc = vectorize(f) -mfunc = mkufunc([(float, float)])(f) +mfunc = fast_vectorize([(float, float)])(f) ##################################################################### support_code = ''' @@ -94,7 +96,7 @@ start_time = time.time() m_y = mfunc(x) m_time = time.time() - start_time -print 'mkufunc: %.6f sec' % m_time +print 'fast_vectorize: %.6f sec' % m_time start_time = time.time() u_y = ufunc(x) Modified: branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_py.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_py.py 2008-08-18 05:37:28 UTC (rev 4649) +++ branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_py.py 2008-08-18 20:40:53 UTC (rev 4650) @@ -1,11 +1,15 @@ #!/usr/bin/env python from numpy import array -from mkufunc.api import mkufunc +import sys +sys.path.append('../mkufunc') +from fast_vectorize import fast_vectorize + + D = 1000 - at mkufunc([(float, float, int)]) + at fast_vectorize([(float, float, int)]) def mandel(cr, ci): d = 1 zr = cr Modified: branches/sandbox/scipy/sandbox/mkufunc/examples/primes.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/examples/primes.py 2008-08-18 05:37:28 UTC (rev 4649) +++ branches/sandbox/scipy/sandbox/mkufunc/examples/primes.py 2008-08-18 20:40:53 UTC (rev 4650) @@ -7,8 +7,10 @@ src = 1 +import sys +sys.path.append('../mkufunc') +from fast_vectorize import fast_vectorize -from mkufunc.api import mkufunc def count_primes(N): @@ -27,7 +29,7 @@ print 'Python: %.6f sec' % (time.time() - start_time) -count_primes = mkufunc(int, src=src)(count_primes) +count_primes = fast_vectorize(int, src=src)(count_primes) start_time = time.time() Modified: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/__init__.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/__init__.py 2008-08-18 05:37:28 UTC (rev 4649) +++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/__init__.py 2008-08-18 20:40:53 UTC (rev 4650) @@ -0,0 +1 @@ +from fast_vectorize import * Deleted: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py 2008-08-18 05:37:28 UTC (rev 4649) +++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py 2008-08-18 20:40:53 UTC (rev 4650) @@ -1,362 +0,0 @@ -""" mkufunc (make U function) - - -Author: Ilan Schnell (with help from Travis Oliphant and Eric Jones) -""" -import sys -import re -import os, os.path -import cStringIO -import md5 -from types import FunctionType - -import numpy -from scipy import weave - - -verbose = 0 -showC = 0 - -def func_hash(f, salt=None): - """ Return a MD5 hash for a function object as string. - """ - co = f.func_code - return md5.md5(co.co_code + repr(co.co_names) + repr(salt)).hexdigest() - - -def translate(f, argtypes): - """ Return pypy's C output for a given function and argument types. - The cache files are in weave's directory. - """ - cache_file_name = os.path.join(weave.catalog.default_dir(), - 'pypy_%s.c' % func_hash(f, salt=argtypes)) - try: - return open(cache_file_name).read() - - except IOError: - from interactive import Translation - - t = Translation(f, backend='c') - t.annotate(argtypes) - t.source() - - os.rename(t.driver.c_source_filename, cache_file_name) - - return translate(f, argtypes) - - -class Ctype: - def __init__(self, npy, c): - self.npy = npy - self.c = c - -typedict = { - int: Ctype('NPY_LONG', 'long' ), - float: Ctype('NPY_DOUBLE', 'double'), -} - - -class Cfunc(object): - """ C compiled python functions - - >>> def sqr(x): - ... return x * x - - >>> signature = [int, int] # only the input arguments are used here - - compilation is done upon initialization - >>> x = Cfunc(sqr, signature, 123) - ... - >>> x.nin # number of input arguments - 1 - >>> x.nout # number of output arguments (must be 1 for now) - 1 - >>> x.sig - [, ] - - Attributes: - f -- the Python function object - n -- id number - sig -- signature - nin -- number of input arguments - nout -- number of output arguments - cname -- name of the C function - - Methods: - decl() -- returns the C declaration for the function - cfunc() -- returns the C function (as string) - ufunc_support_code() - -- generate the C support code to make this - function part work with PyUFuncGenericFunction - """ - def __init__(self, f, signature, n): - self.f = f - self.n = n - self.sig = signature - self.nin = f.func_code.co_argcount - self.nout = len(self.sig) - self.nin - assert self.nout == 1 # for now - - src = translate(f, signature[:self.nin]) - - self._prefix = 'f%i_' % self.n - self._allCsrc = src.replace('pypy_', self._prefix + 'pypy_') - self.cname = self._prefix + 'pypy_g_' + f.__name__ - - def cfunc(self): - p = re.compile( - r''' - ^\w+ # return type of function - [\s]+ # whitespace - %s # function name - \s* # possibly whitespace - \([^)]*\) # argument types - \s* # possibly whitespace - \{.*?\n\}\n # function body ending with } in single line - ''' % self.cname, - re.DOTALL | re.MULTILINE | re.VERBOSE) - - found = p.findall(self._allCsrc) - assert len(found) == 1 - res = found[0] - res = res.replace(self._prefix + 'pypy_g_ll_math_ll_math_', '') - if showC: - print '------------------' - print res - print '------------------' - - return 'inline %s\n' % res - - def ufunc_support_code(self): - # Unfortunately the code in here is very hard to read. - # In order to make the code clearer, one would need a real template - # engine link Cheetah (http://cheetahtemplate.org/). - # However, somehting like that would be too much overhead for scipy. - n = self.n - nin = self.nin - cname = self.cname - - def varname(i): - return chr(i + ord('a')) - - declargs = ', '.join('%s %s' % (typedict[self.sig[i]].c, varname(i)) - for i in xrange(self.nin)) - - args = ', '.join(varname(i) for i in xrange(self.nin)) - - isn_steps = '\n\t'.join('npy_intp is%i = steps[%i];' % (i, i) - for i in xrange(self.nin)) - - ipn_args = '\n\t'.join('char *ip%i = args[%i];' % (i, i) - for i in xrange(self.nin)) - - body1d_in = '\n\t\t'.join('%s *in%i = (%s *)ip%i;' % - (2*(typedict[self.sig[i]].c, i)) - for i in xrange(self.nin)) - - body1d_add = '\n\t\t'.join('ip%i += is%i;' % (i, i) - for i in xrange(self.nin)) - - ptrargs = ', '.join('*in%i' % i for i in xrange(self.nin)) - - rettype = typedict[self.sig[-1]].c - - return ''' -static %(rettype)s wrap_%(cname)s(%(declargs)s) -{ - return %(cname)s(%(args)s); -} - -typedef %(rettype)s Func_%(n)i(%(declargs)s); - -static void -PyUFunc_%(n)i(char **args, npy_intp *dimensions, npy_intp *steps, void *func) -{ - npy_intp i, n; - %(isn_steps)s - npy_intp os = steps[%(nin)s]; - %(ipn_args)s - char *op = args[%(nin)s]; - Func_%(n)i *f = (Func_%(n)i *) func; - n = dimensions[0]; - - for(i = 0; i < n; i++) { - %(body1d_in)s - %(rettype)s *out = (%(rettype)s *)op; - - *out = (%(rettype)s) f(%(ptrargs)s); - - %(body1d_add)s - op += os; - } -} -''' % locals() - - -def support_code(cfuncs): - """ Given a list of Cfunc instances, return the support code for weave. - """ - acc = cStringIO.StringIO() - - acc.write('/********************* start pypy.h **************/\n\n') - acc.write(open(os.path.join(os.path.dirname(__file__), - 'pypy.h')).read()) - acc.write('/********************** end pypy.h ****************/\n\n') - - for cf in cfuncs: - acc.write(cf.cfunc()) - acc.write(cf.ufunc_support_code()) - - fname = cfuncs[0].f.__name__ - - pyufuncs = ''.join('\tPyUFunc_%i,\n' % cf.n for cf in cfuncs) - - data = ''.join('\t(void *) wrap_%s,\n' % cf.cname for cf in cfuncs) - - types = ''.join('\t%s /* %i */\n' % - (''.join(typedict[t].npy + ', ' for t in cf.sig), cf.n) - for cf in cfuncs) - - acc.write(''' -static PyUFuncGenericFunction %(fname)s_functions[] = { -%(pyufuncs)s}; - -static void *%(fname)s_data[] = { -%(data)s}; - -static char %(fname)s_types[] = { -%(types)s}; -''' % locals()) - - if verbose: - print '------------------ start support_code -----------------' - print acc.getvalue() - print '------------------- end support_code ------------------' - - return acc.getvalue() - - -def code(f, signatures): - """ Return the code for weave. - """ - nin = f.func_code.co_argcount - ntypes = len(signatures) - fname = f.__name__ - fhash = func_hash(f) - - res = ''' -import_ufunc(); - -/**************************************************************************** -** function name: %(fname)s -** signatures: %(signatures)r -** fhash: %(fhash)s -*****************************************************************************/ - -return_val = PyUFunc_FromFuncAndData( - %(fname)s_functions, - %(fname)s_data, - %(fname)s_types, - %(ntypes)i, /* ntypes */ - %(nin)i, /* nin */ - 1, /* nout */ - PyUFunc_None, /* identity */ - "%(fname)s", /* name */ - "UFunc created by mkufunc", /* doc */ - 0); -''' % locals() - - if verbose: - print '---------------------- start code ---------------------' - print res - print '----------------------- end code ----------------------' - - return res - - -def genufunc(f, signatures): - """ Return the Ufunc Python object for given function and signatures. - """ - if len(signatures) == 0: - raise ValueError("At least one signature needed") - - signatures.sort(key=lambda sig: [numpy.dtype(typ).num for typ in sig]) - - cfuncs = [Cfunc(f, sig, n) for n, sig in enumerate(signatures)] - - ufunc_info = weave.base_info.custom_info() - ufunc_info.add_header('"numpy/ufuncobject.h"') - - return weave.inline(code(f, signatures), - verbose=verbose, - support_code=support_code(cfuncs), - customize=ufunc_info) - - -def mkufunc(arg0=[float], src=0): - """ Python decorator which returns compiled UFunc of the function given. - - >>> from numpy import arange - >>> from mkufunc.api import mkufunc - >>> @mkufunc - ... def foo(x): - ... return 4.2 * x * x - x + 6.3 - ... - >>> a = arange(5) - >>> a - array([0, 1, 2, 3, 4]) - >>> foo(a) - array([ 6.3, 9.5, 21.1, 41.1, 69.5]) - """ - class UFunc(object): - - def __init__(self, f): - nin = f.func_code.co_argcount - nout = 1 - for i, sig in enumerate(signatures): - if isinstance(sig, tuple): - pass - elif sig in typedict.keys(): - signatures[i] = (nin + nout) * (sig,) - else: - raise TypeError("no match for %r" % sig) - - for sig in signatures: - assert isinstance(sig, tuple) - if len(sig) != nin + nout: - raise TypeError("signature %r does not match the " - "number of args of function %s" % - (sig, f.__name__)) - for t in sig: - if t not in typedict.keys(): - raise TypeError("no match for %r" % t) - - self.ufunc = genufunc(f, signatures) - - def __call__(self, *args): - return self.ufunc(*args) - - global showC - showC = src - - if isinstance(arg0, FunctionType): - f = arg0 - signatures = [float] - return UFunc(f) - - elif isinstance(arg0, list): - signatures = arg0 - return UFunc - - elif arg0 in typedict.keys(): - signatures = [arg0] - return UFunc - - else: - raise TypeError("first argument has to be a function, a type, or " - "a list of signatures") - - -if __name__ == '__main__': - import doctest - doctest.testmod() Modified: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/driver.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/driver.py 2008-08-18 05:37:28 UTC (rev 4649) +++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/driver.py 2008-08-18 20:40:53 UTC (rev 4650) @@ -1,3 +1,7 @@ +""" +This file is essentially the file pypy-dist/pypy/translator/driver.py +with some modifications to get the c_source_filename. +""" import sys, os from pypy.translator.translator import TranslationContext, graphof @@ -131,7 +135,7 @@ explicit_task = task parts = task.split('_') if len(parts) == 1: - if task in ('annotate'): + if task in ('annotate',): expose_task(task) else: task, postfix = parts @@ -186,7 +190,7 @@ def _maybe_skip(self): maybe_skip = [] if self._disabled: - for goal in self.backend_select_goals(self._disabled): + for goal in self.backend_select_goals(self._disabled): maybe_skip.extend(self._depending_on_closure(goal)) return dict.fromkeys(maybe_skip).keys() Copied: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/fast_vectorize.py (from rev 4649, branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py) =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py 2008-08-18 05:37:28 UTC (rev 4649) +++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/fast_vectorize.py 2008-08-18 20:40:53 UTC (rev 4650) @@ -0,0 +1,380 @@ +"""fast_vectorize: creates a U function from python source code + +Author: Ilan Schnell +Thanks: Travis Oliphant and Eric Jones +""" +import sys +import re +import os +import cStringIO +import md5 +from types import FunctionType + +import numpy +from scipy import weave + +# Local imports +from func_hash import func_hash + + +_verbose = 0 +_showc = 0 +_force = 0 + +def c_source_filename(f, argtypes): + try: + import pypy + except ImportError: + raise ImportError(""" +################################################################ +weave.fast_vectorize requires pypy to be installed. + +You can download... +################################################################ +""") + + from interactive import Translation + + t = Translation(f, backend='c') + t.annotate(argtypes) + t.source() + return t.driver.c_source_filename + + +def translate(f, argtypes): + """ Return pypy's C output for a given function and argument types. + The cache files are in weave's directory. + """ + if _force: + filename = c_source_filename(f, argtypes) + return open(filename).read() + + cache_file_name = os.path.join(weave.catalog.default_dir(), + 'pypy_%s.c' % func_hash(f, salt=argtypes)) + try: + return open(cache_file_name).read() + + except IOError: + os.rename(c_source_filename(f, argtypes), cache_file_name) + + return translate(f, argtypes) + + +class Ctype: + def __init__(self, npy, c): + self.npy = npy + self.c = c + +typedict = { + int: Ctype('NPY_LONG', 'long' ), + float: Ctype('NPY_DOUBLE', 'double'), +} + + +class Cfunc(object): + """ C compiled python functions + + >>> def sqr(x): + ... return x * x + + >>> signature = [int, int] # only the input arguments are used here + + compilation is done upon initialization + >>> x = Cfunc(sqr, signature, 123) + ... + >>> x.nin # number of input arguments + 1 + >>> x.nout # number of output arguments (must be 1 for now) + 1 + >>> x.sig + [, ] + + Attributes: + f -- the Python function object + n -- id number + sig -- signature + nin -- number of input arguments + nout -- number of output arguments + cname -- name of the C function + + Methods: + decl() -- returns the C declaration for the function + cfunc() -- returns the C function (as string) + ufunc_support_code() + -- generate the C support code to make this + function part work with PyUFuncGenericFunction + """ + def __init__(self, f, signature, n): + self.f = f + self.n = n + self.sig = signature + self.nin = f.func_code.co_argcount + self.nout = len(self.sig) - self.nin + assert self.nout == 1 # for now + + src = translate(f, signature[:self.nin]) + + self._prefix = 'f%i_' % self.n + self._allCsrc = src.replace('pypy_', self._prefix + 'pypy_') + self.cname = self._prefix + 'pypy_g_' + f.__name__ + + def cfunc(self): + p = re.compile( + r''' + ^\w+ # return type of function + [\s]+ # whitespace + %s # function name + \s* # possibly whitespace + \([^)]*\) # argument types + \s* # possibly whitespace + \{.*?\n\}\n # function body ending with } in single line + ''' % self.cname, + re.DOTALL | re.MULTILINE | re.VERBOSE) + + found = p.findall(self._allCsrc) + assert len(found) == 1 + res = found[0] + res = res.replace(self._prefix + 'pypy_g_ll_math_ll_math_', '') + if _showc: + print '------------------' + print res + print '------------------' + + return 'inline %s\n' % res + + def ufunc_support_code(self): + # Unfortunately the code in here is very hard to read. + # In order to make the code clearer, one would need a real template + # engine link Cheetah (http://cheetahtemplate.org/). + # However, somehting like that would be too much overhead for scipy. + n = self.n + nin = self.nin + cname = self.cname + + def varname(i): + return chr(i + ord('a')) + + declargs = ', '.join('%s %s' % (typedict[self.sig[i]].c, varname(i)) + for i in xrange(self.nin)) + + args = ', '.join(varname(i) for i in xrange(self.nin)) + + isn_steps = '\n\t'.join('npy_intp is%i = steps[%i];' % (i, i) + for i in xrange(self.nin)) + + ipn_args = '\n\t'.join('char *ip%i = args[%i];' % (i, i) + for i in xrange(self.nin)) + + body1d_in = '\n\t\t'.join('%s *in%i = (%s *)ip%i;' % + (2*(typedict[self.sig[i]].c, i)) + for i in xrange(self.nin)) + + body1d_add = '\n\t\t'.join('ip%i += is%i;' % (i, i) + for i in xrange(self.nin)) + + ptrargs = ', '.join('*in%i' % i for i in xrange(self.nin)) + + rettype = typedict[self.sig[-1]].c + + return ''' +static %(rettype)s wrap_%(cname)s(%(declargs)s) +{ + return %(cname)s(%(args)s); +} + +typedef %(rettype)s Func_%(n)i(%(declargs)s); + +static void +PyUFunc_%(n)i(char **args, npy_intp *dimensions, npy_intp *steps, void *func) +{ + npy_intp i, n; + %(isn_steps)s + npy_intp os = steps[%(nin)s]; + %(ipn_args)s + char *op = args[%(nin)s]; + Func_%(n)i *f = (Func_%(n)i *) func; + n = dimensions[0]; + + for(i = 0; i < n; i++) { + %(body1d_in)s + %(rettype)s *out = (%(rettype)s *)op; + + *out = (%(rettype)s) f(%(ptrargs)s); + + %(body1d_add)s + op += os; + } +} +''' % locals() + + +def support_code(cfuncs): + """ Given a list of Cfunc instances, return the support code for weave. + """ + acc = cStringIO.StringIO() + + acc.write('/********************* start pypy.h **************/\n\n') + acc.write(open(os.path.join(os.path.dirname(__file__), + 'pypy.h')).read()) + acc.write('/********************** end pypy.h ****************/\n\n') + + for cf in cfuncs: + acc.write(cf.cfunc()) + acc.write(cf.ufunc_support_code()) + + fname = cfuncs[0].f.__name__ + + pyufuncs = ''.join('\tPyUFunc_%i,\n' % cf.n for cf in cfuncs) + + data = ''.join('\t(void *) wrap_%s,\n' % cf.cname for cf in cfuncs) + + types = ''.join('\t%s /* %i */\n' % + (''.join(typedict[t].npy + ', ' for t in cf.sig), cf.n) + for cf in cfuncs) + + acc.write(''' +static PyUFuncGenericFunction %(fname)s_functions[] = { +%(pyufuncs)s}; + +static void *%(fname)s_data[] = { +%(data)s}; + +static char %(fname)s_types[] = { +%(types)s}; +''' % locals()) + + if _verbose: + print '------------------ start support_code -----------------' + print acc.getvalue() + print '------------------- end support_code ------------------' + + return acc.getvalue() + + +def code(f, signatures): + """ Return the code for weave. + """ + nin = f.func_code.co_argcount + ntypes = len(signatures) + fname = f.__name__ + fhash = func_hash(f) + + res = ''' +import_ufunc(); + +/**************************************************************************** +** function name: %(fname)s +** signatures: %(signatures)r +** fhash: %(fhash)s +*****************************************************************************/ + +return_val = PyUFunc_FromFuncAndData( + %(fname)s_functions, + %(fname)s_data, + %(fname)s_types, + %(ntypes)i, /* ntypes */ + %(nin)i, /* nin */ + 1, /* nout */ + PyUFunc_None, /* identity */ + "%(fname)s", /* name */ + "UFunc created by fast_vectorize", /* doc */ + 0); +''' % locals() + + if _verbose: + print '---------------------- start code ---------------------' + print res + print '----------------------- end code ----------------------' + + return res + + +def genufunc(f, signatures): + """ Return the Ufunc Python object for given function and signatures. + """ + if len(signatures) == 0: + raise ValueError("At least one signature needed") + + signatures.sort(key=lambda sig: [numpy.dtype(typ).num for typ in sig]) + + cfuncs = [Cfunc(f, sig, n) for n, sig in enumerate(signatures)] + + ufunc_info = weave.base_info.custom_info() + ufunc_info.add_header('"numpy/ufuncobject.h"') + + return weave.inline(code(f, signatures), + verbose = _verbose, + force = _force, + support_code = support_code(cfuncs), + customize = ufunc_info) + + + +def fast_vectorize(arg0=[float], showc=0, force=0, verbose=0): + """ Python decorator which returns compiled UFunc of the function given. + + >>> from numpy import arange + >>> @fast_vectorize + ... def foo(x): + ... return 4.2 * x * x - x + 6.3 + ... + >>> a = arange(5) + >>> a + array([0, 1, 2, 3, 4]) + >>> foo(a) + array([ 6.3, 9.5, 21.1, 41.1, 69.5]) + """ + class UFunc(object): + + def __init__(self, f): + nin = f.func_code.co_argcount + nout = 1 + for i, sig in enumerate(signatures): + if isinstance(sig, tuple): + pass + elif sig in typedict.keys(): + signatures[i] = (nin + nout) * (sig,) + else: + raise TypeError("no match for %r" % sig) + + for sig in signatures: + assert isinstance(sig, tuple) + if len(sig) != nin + nout: + raise TypeError("signature %r does not match the " + "number of args of function %s" % + (sig, f.__name__)) + for t in sig: + if t not in typedict.keys(): + raise TypeError("no match for %r" % t) + + self.ufunc = genufunc(f, signatures) + + def __call__(self, *args): + return self.ufunc(*args) + + global _showc, _force, _verbose + _showc = showc + _force = force + _verbose = verbose + + if isinstance(arg0, FunctionType): + f = arg0 + signatures = [float] + return UFunc(f) + + elif isinstance(arg0, list): + signatures = arg0 + return UFunc + + elif arg0 in typedict.keys(): + signatures = [arg0] + return UFunc + + else: + raise TypeError("first argument has to be a function, a type, or " + "a list of signatures") + + +if __name__ == '__main__': + import doctest + doctest.testmod() Property changes on: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/fast_vectorize.py ___________________________________________________________________ Name: svn:mergeinfo + Added: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/func_hash.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/func_hash.py 2008-08-18 05:37:28 UTC (rev 4649) +++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/func_hash.py 2008-08-18 20:40:53 UTC (rev 4650) @@ -0,0 +1,40 @@ +""" + +Author: Ilan Schnell +""" +import md5 +import re +from types import CodeType, FunctionType + +def md5sum(s): + return md5.md5(s).hexdigest() + + +pat_hex = re.compile(r'0x[0-9a-f]{4,}', re.I) + + +def func_hash(f, salt=None): + """ Return a MD5 hash for a function or code object as string. + """ + if type(f) == FunctionType: + co = f.func_code + elif type(f) == CodeType: + co = f + else: + raise TypeError("Object %r is not function or code object.") + + res = [] + for name in dir(co): + if not name.startswith('co_'): + continue + if name == 'co_consts': + for c in getattr(co, name): + if type(c) == CodeType or \ + type(c) == FunctionType: + res.append(func_hash(c)) + else: + res.append(repr(c)) + else: + res.append(repr(getattr(co, name))) + + return md5sum(''.join(res) + repr(salt)) Modified: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/interactive.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/interactive.py 2008-08-18 05:37:28 UTC (rev 4649) +++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/interactive.py 2008-08-18 20:40:53 UTC (rev 4650) @@ -1,3 +1,8 @@ +""" +This file is essentially the file pypy-dist/pypy/translator/interactive.py +with some modifications to get the c_source_filename. +""" + import driver from pypy.translator.translator import TranslationContext Copied: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_fast_vectorize.py (from rev 4649, branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py) =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py 2008-08-18 05:37:28 UTC (rev 4649) +++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_fast_vectorize.py 2008-08-18 20:40:53 UTC (rev 4650) @@ -0,0 +1,323 @@ +import math +import unittest + +from numpy import array, arange, allclose + +from fast_vectorize import Cfunc, genufunc, fast_vectorize + + +class Util: + + def assertClose(self, x, y): + self.assert_(allclose(x, y), '%s != %s' % (x, y)) + + +class Internal_Tests(unittest.TestCase, Util): + + def test_Cfunc(self): + def sqr(x): + return x * x + cf = Cfunc(sqr, [int, int], 42) + self.assertEqual(cf.nin, 1) + self.assertEqual(cf.nout, 1) + self.assertEqual(cf.cname, 'f42_pypy_g_sqr') + + def test_genufunc(self): + def foo(x): + return x + 17 + uf = genufunc(foo, [ + (float, float), + (int, int), + ]) + self.assertEqual(uf(4), 21) + x = array([1.1, 2.3]) + y = uf(x) + self.assertClose(y, [18.1, 19.3]) + self.assert_(str(y.dtype).startswith('float')) + + x = array([1, 4]) + y = uf(x) + self.assertEqual(list(y), [18, 21]) + self.assert_(str(y.dtype).startswith('int')) + + +class Arg_Tests(unittest.TestCase, Util): + + def check_ufunc(self, f): + for arg in (array([0.0, 1.0, 2.5]), + [0.0, 1.0, 2.5], + (0.0, 1.0, 2.5)): + self.assertClose(f(arg), [0.0, 1.0, 6.25]) + + self.assertEqual(f(3), 9) + self.assert_(f(-2.5) - 6.25 < 1E-10) + + def test_direct(self): + @fast_vectorize + def f(x): + return x * x + self.check_ufunc(f) + + def test_noargs(self): + @fast_vectorize() + def f(x): + return x * x + self.check_ufunc(f) + + def test_varargs(self): + for arg in (float, + [float], + [(float, float)]): + @fast_vectorize(arg) + def f(x): + return x * x + self.check_ufunc(f) + + def test_int(self): + @fast_vectorize(int) + def f(x): + return x * x + self.assertEqual(f(3), 9) + self.assert_(isinstance(f(42), int)) + + def test_mixed(self): + @fast_vectorize([(int, float, int), float]) + def f(n, x): + return n + x * x + + y = f(2, 3.9) # Note that int(2 + 3.9 * 3.9) = 17 + self.assertEqual(y, 17) + self.assert_(isinstance(y, int)) + + y = f(2.0, 3.9) + self.assertClose(y, 17.21) + self.assert_(isinstance(y, float)) + + def test_exceptions(self): + def f(x): + return x + + self.assertRaises(TypeError, fast_vectorize, {}) + self.assertRaises(TypeError, fast_vectorize([(float,)]), f) + self.assertRaises(TypeError, fast_vectorize([3*(float,)]), f) + self.assertRaises(TypeError, fast_vectorize([{}]), f) + self.assertRaises(TypeError, fast_vectorize([(int, {})]), f) + self.assertRaises(ValueError, fast_vectorize([]), f) + + +class Math_Tests(unittest.TestCase, Util): + + def assertFuncsEqual(self, uf, f): + x = 0.4376 + a = uf(x) + b = f(x) + self.assertClose(a, b) + xx = arange(0.1, 0.9, 0.01) + a = uf(xx) + b = [f(x) for x in xx] + self.assertClose(a, b) + + def test_pi(self): + @fast_vectorize + def f(x): return math.pi * x + self.assertFuncsEqual(f, lambda x: math.pi * x) + + def test_e(self): + @fast_vectorize + def f(x): return math.e * x + self.assertFuncsEqual(f, lambda x: math.e * x) + + def test_exp(self): + @fast_vectorize + def f(x): return math.exp(x) + self.assertFuncsEqual(f, math.exp) + + def test_log(self): + @fast_vectorize + def f(x): return math.log(x) + self.assertFuncsEqual(f, math.log) + + def test_log10(self): + @fast_vectorize + def f(x): return math.log10(x) + self.assertFuncsEqual(f, math.log10) + + def test_sqrt(self): + @fast_vectorize + def f(x): return math.sqrt(x) + self.assertFuncsEqual(f, math.sqrt) + + def test_cos(self): + @fast_vectorize + def f(x): return math.cos(x) + self.assertFuncsEqual(f, math.cos) + + def test_sin(self): + @fast_vectorize + def f(x): return math.sin(x) + self.assertFuncsEqual(f, math.sin) + + def test_tan(self): + @fast_vectorize + def f(x): return math.tan(x) + self.assertFuncsEqual(f, math.tan) + + def test_cosh(self): + @fast_vectorize + def f(x): return math.cosh(x) + self.assertFuncsEqual(f, math.cosh) + + def test_sinh(self): + @fast_vectorize + def f(x): return math.sinh(x) + self.assertFuncsEqual(f, math.sinh) + + def test_tanh(self): + @fast_vectorize + def f(x): return math.tanh(x) + self.assertFuncsEqual(f, math.tanh) + + def test_acos(self): + @fast_vectorize + def f(x): return math.acos(x) + self.assertFuncsEqual(f, math.acos) + + def test_asin(self): + @fast_vectorize + def f(x): return math.asin(x) + self.assertFuncsEqual(f, math.asin) + + def test_atan(self): + @fast_vectorize + def f(x): return math.atan(x) + self.assertFuncsEqual(f, math.atan) + + def test_atan2(self): + @fast_vectorize + def f(x, y): + return math.atan2(x, y) + + self.assertClose(f(4, 5), math.atan2(4, 5)) + + xx = array([1.0, 3.0, -2.4, 3.1, -2.3, -1.0]) + yy = array([1.0, 2.0, 7.5, -8.7, 0.0, -3.2]) + a = f(xx, yy) + b = [math.atan2(x, y) for x, y in zip(xx, yy)] + self.assertClose(a, b) + + def test_pow(self): + @fast_vectorize + def f(x, y): + return math.pow(x, y) + + self.assertClose(f(2, 3), 8) + + xx = array([1.0, 3.0, 2.4, 0.0, 0.0, 0.0, 2.3, 2.0]) + yy = array([1.0, 2.0, 7.5, 0.0, 0.5, 1.0, 0.0, -1.0]) + a = f(xx, yy) + b = [math.pow(x, y) for x, y in zip(xx, yy)] + self.assertClose(a, b) + + def test_hypot(self): + @fast_vectorize + def f(x, y): + return math.hypot(x, y) + + self.assertClose(f(3, 4), 5) + + xx = array([3.0, 2.4, -2.4, 3.1, -2.3, -1.0]) + yy = array([4.0, 7.5, 7.5, -8.7, 0.0, -3.2]) + a = f(xx, yy) + b = [math.hypot(x, y) for x, y in zip(xx, yy)] + self.assertClose(a, b) + + def test_arithmetic(self): + def f(x): + return (4 * x + 2) / (x * x - 7 * x + 1) + uf = fast_vectorize(f) + x = arange(0, 2, 0.1) + self.assertClose(uf(x), f(x)) + + def test_modulo(self): + @fast_vectorize(int) + def f(i): + return i % 5 + + for i in xrange(100): + self.assertEqual(f(i), i % 5) + + self.assert_((f(arange(8)) == array([0, 1, 2, 3, 4, 0, 1, 2])).all()) + + +class Control_Flow_Tests(unittest.TestCase): + + def test_if(self): + @fast_vectorize(int) + def f(n): + if n < 4: + return n + else: + return n * n + + self.assertEqual(f(3), 3) + self.assertEqual(f(4), 16) + + def test_switch(self): + @fast_vectorize(int) + def f(n): + if n < 4: + return n + elif n == 4: + return 42 + elif n == 5: + return 73 + else: + return n * n + + self.assertEqual(f(3), 3) + self.assertEqual(f(4), 42) + self.assertEqual(f(5), 73) + self.assertEqual(f(6), 36) + + def test_loop(self): + @fast_vectorize(int) + def f(n): + res = 0 + for i in xrange(n): + res += i*i + return res + + self.assertEqual(f(3), 5) + self.assertEqual(f(95), 281295) + + +class FreeVariable_Tests(unittest.TestCase, Util): + + def test_const(self): + a = 13.6 + @fast_vectorize + def f(x): + return a * x + + x = arange(0, 1, 0.1) + self.assertClose(f(x), a * x) + + +class Misc_Tests(unittest.TestCase, Util): + + def test_lambda(self): + self.assertRaises(AssertionError, fast_vectorize, lambda x: x*x + 2) + + def test_angle(self): + from math import sin, pi, sqrt + @fast_vectorize + def sin_deg(angle): + return sin(angle / 180.0 * pi) + + self.assertClose(sin_deg([0, 30, 45, 60, 90, 180, 270, 360]), + [0, 0.5, 1/sqrt(2), sqrt(3)/2, 1, 0, -1, 0]) + + + +if __name__ == '__main__': + unittest.main() Property changes on: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_fast_vectorize.py ___________________________________________________________________ Name: svn:mergeinfo + Deleted: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py 2008-08-18 05:37:28 UTC (rev 4649) +++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py 2008-08-18 20:40:53 UTC (rev 4650) @@ -1,48 +0,0 @@ -import unittest - -from api import func_hash - - -class Tests(unittest.TestCase): - - # These tests are very (Python) version specific. - - def test_simple(self): - - def f(x): - return 2.5 * x * x + 4.7 * x - - self.assertEqual(func_hash(f), - '5f12e97debf1d2cb9e0a2f92e045b1fb') - - - def test_extra(self): - - def f(x): - return 2.5 * x * x + 4.7 * x - - self.assertEqual(func_hash(f, salt=[(int, int), (float, float)]), - 'e637d9825ef20cb56d364041118ca72e') - - def test_const(self): - - def add_a(b): - return a + b # a in globals - - self.assertEqual(func_hash(add_a), - '9ff237f372bf233470ce940edd58f60d') - - def test_inner(self): - - def foo(x): - inner1 = lambda t: t/3.0 - def inner2(n): - return n + 3 - return inner1(x) + inner2(int(x)) - - self.assertEqual(func_hash(foo), - '814c113dfc77e7ebb52915dd3ce9c37a') - - -if __name__ == '__main__': - unittest.main() Deleted: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py 2008-08-18 05:37:28 UTC (rev 4649) +++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py 2008-08-18 20:40:53 UTC (rev 4650) @@ -1,324 +0,0 @@ -import math -import unittest - -from numpy import array, arange, allclose - -from api import Cfunc, genufunc, mkufunc - - -class Util: - - def assertClose(self, x, y): - self.assert_(allclose(x, y), '%s != %s' % (x, y)) - - -class Internal_Tests(unittest.TestCase, Util): - - def test_Cfunc(self): - def sqr(x): - return x * x - cf = Cfunc(sqr, [int, int], 42) - self.assertEqual(cf.nin, 1) - self.assertEqual(cf.nout, 1) - self.assertEqual(cf.cname, 'f42_pypy_g_sqr') - - def test_genufunc(self): - def foo(x): - return x + 17 - uf = genufunc(foo, [ - (float, float), - (int, int), - ]) - self.assertEqual(uf(4), 21) - x = array([1.1, 2.3]) - y = uf(x) - self.assertClose(y, [18.1, 19.3]) - self.assert_(str(y.dtype).startswith('float')) - - x = array([1, 4]) - y = uf(x) - self.assertEqual(list(y), [18, 21]) - self.assert_(str(y.dtype).startswith('int')) - - -class Arg_Tests(unittest.TestCase, Util): - - def check_ufunc(self, f): - for arg in (array([0.0, 1.0, 2.5]), - [0.0, 1.0, 2.5], - (0.0, 1.0, 2.5)): - self.assertClose(f(arg), [0.0, 1.0, 6.25]) - - self.assertEqual(f(3), 9) - self.assert_(f(-2.5) - 6.25 < 1E-10) - - def test_direct(self): - @mkufunc - def f(x): - return x * x - self.check_ufunc(f) - - def test_noargs(self): - @mkufunc() - def f(x): - return x * x - self.check_ufunc(f) - - def test_varargs(self): - for arg in (float, - [float], - [(float, float)]): - @mkufunc(arg) - def f(x): - return x * x - self.check_ufunc(f) - - def test_int(self): - @mkufunc(int) - def f(x): - return x * x - self.assertEqual(f(3), 9) - self.assert_(isinstance(f(42), int)) - - def test_mixed(self): - @mkufunc([(int, float, int), float]) - def f(n, x): - return n + x * x - - y = f(2, 3.9) # Note that int(2 + 3.9 * 3.9) = 17 - self.assertEqual(y, 17) - self.assert_(isinstance(y, int)) - - y = f(2.0, 3.9) - self.assertClose(y, 17.21) - self.assert_(isinstance(y, float)) - - def test_exceptions(self): - def f(x): - return x - - self.assertRaises(TypeError, mkufunc, {}) - self.assertRaises(TypeError, mkufunc([(float,)]), f) - self.assertRaises(TypeError, mkufunc([3*(float,)]), f) - self.assertRaises(TypeError, mkufunc([{}]), f) - self.assertRaises(TypeError, mkufunc([(int, {})]), f) - self.assertRaises(ValueError, mkufunc([]), f) - - -class Math_Tests(unittest.TestCase, Util): - - def assertFuncsEqual(self, uf, f): - x = 0.4376 - a = uf(x) - b = f(x) - self.assertClose(a, b) - xx = arange(0.1, 0.9, 0.01) - a = uf(xx) - b = [f(x) for x in xx] - self.assertClose(a, b) - - def test_pi(self): - @mkufunc - def f(x): return math.pi * x - self.assertFuncsEqual(f, lambda x: math.pi * x) - - def test_e(self): - @mkufunc - def f(x): return math.e * x - self.assertFuncsEqual(f, lambda x: math.e * x) - - def test_exp(self): - @mkufunc - def f(x): return math.exp(x) - self.assertFuncsEqual(f, math.exp) - - def test_log(self): - @mkufunc - def f(x): return math.log(x) - self.assertFuncsEqual(f, math.log) - - def test_log10(self): - @mkufunc - def f(x): return math.log10(x) - self.assertFuncsEqual(f, math.log10) - - def test_sqrt(self): - @mkufunc - def f(x): return math.sqrt(x) - self.assertFuncsEqual(f, math.sqrt) - - def test_cos(self): - @mkufunc - def f(x): return math.cos(x) - self.assertFuncsEqual(f, math.cos) - - def test_sin(self): - @mkufunc - def f(x): return math.sin(x) - self.assertFuncsEqual(f, math.sin) - - def test_tan(self): - @mkufunc - def f(x): return math.tan(x) - self.assertFuncsEqual(f, math.tan) - - def test_cosh(self): - @mkufunc - def f(x): return math.cosh(x) - self.assertFuncsEqual(f, math.cosh) - - def test_sinh(self): - @mkufunc - def f(x): return math.sinh(x) - self.assertFuncsEqual(f, math.sinh) - - def test_tanh(self): - @mkufunc - def f(x): return math.tanh(x) - self.assertFuncsEqual(f, math.tanh) - - def test_acos(self): - @mkufunc - def f(x): return math.acos(x) - self.assertFuncsEqual(f, math.acos) - - def test_asin(self): - @mkufunc - def f(x): return math.asin(x) - self.assertFuncsEqual(f, math.asin) - - def test_atan(self): - @mkufunc - def f(x): return math.atan(x) - self.assertFuncsEqual(f, math.atan) - - def test_atan2(self): - @mkufunc - def f(x, y): - return math.atan2(x, y) - - self.assertClose(f(4, 5), math.atan2(4, 5)) - - xx = array([1.0, 3.0, -2.4, 3.1, -2.3, -1.0]) - yy = array([1.0, 2.0, 7.5, -8.7, 0.0, -3.2]) - a = f(xx, yy) - b = [math.atan2(x, y) for x, y in zip(xx, yy)] - self.assertClose(a, b) - - def test_pow(self): - @mkufunc - def f(x, y): - return math.pow(x, y) - - self.assertClose(f(2, 3), 8) - - xx = array([1.0, 3.0, 2.4, 0.0, 0.0, 0.0, 2.3, 2.0]) - yy = array([1.0, 2.0, 7.5, 0.0, 0.5, 1.0, 0.0, -1.0]) - a = f(xx, yy) - b = [math.pow(x, y) for x, y in zip(xx, yy)] - self.assertClose(a, b) - - def test_hypot(self): - @mkufunc - def f(x, y): - return math.hypot(x, y) - - self.assertClose(f(3, 4), 5) - - xx = array([3.0, 2.4, -2.4, 3.1, -2.3, -1.0]) - yy = array([4.0, 7.5, 7.5, -8.7, 0.0, -3.2]) - a = f(xx, yy) - b = [math.hypot(x, y) for x, y in zip(xx, yy)] - self.assertClose(a, b) - - def test_arithmetic(self): - def f(x): - return (4 * x + 2) / (x * x - 7 * x + 1) - uf = mkufunc(f) - x = arange(0, 2, 0.1) - self.assertClose(uf(x), f(x)) - - def test_modulo(self): - @mkufunc(int) - def f(i): - return i % 5 - - for i in xrange(100): - self.assertEqual(f(i), i % 5) - - self.assert_((f(arange(8)) == array([0, 1, 2, 3, 4, 0, 1, 2])).all()) - - -class Control_Flow_Tests(unittest.TestCase): - - def test_if(self): - @mkufunc(int) - def f(n): - if n < 4: - return n - else: - return n * n - - self.assertEqual(f(3), 3) - self.assertEqual(f(4), 16) - - def test_switch(self): - @mkufunc(int) - def f(n): - if n < 4: - return n - elif n == 4: - return 42 - elif n == 5: - return 73 - else: - return n * n - - self.assertEqual(f(3), 3) - self.assertEqual(f(4), 42) - self.assertEqual(f(5), 73) - self.assertEqual(f(6), 36) - - def test_loop(self): - @mkufunc(int) - def f(n): - res = 0 - for i in xrange(n): - res += i*i - return res - - self.assertEqual(f(3), 5) - self.assertEqual(f(95), 281295) - - -class FreeVariable_Tests(unittest.TestCase, Util): - - def test_const(self): - a = 13.6 - @mkufunc - def f(x): - return a * x - - x = arange(0, 1, 0.1) - self.assertClose(f(x), a * x) - - -class Misc_Tests(unittest.TestCase, Util): - - def test_lambda(self): - self.assertRaises(AssertionError, mkufunc, lambda x: x*x + 2) - - def test_angle(self): - from math import sin, pi, sqrt - @mkufunc - def sin_deg(angle): - return sin(angle / 180.0 * pi) - - self.assertClose(sin_deg([0, 30, 45, 60, 90, 180, 270, 360]), - [0, 0.5, 1/sqrt(2), sqrt(3)/2, 1, 0, -1, 0]) - - - - -if __name__ == '__main__': - unittest.main() Modified: branches/sandbox/scipy/sandbox/mkufunc/setup.py =================================================================== --- branches/sandbox/scipy/sandbox/mkufunc/setup.py 2008-08-18 05:37:28 UTC (rev 4649) +++ branches/sandbox/scipy/sandbox/mkufunc/setup.py 2008-08-18 20:40:53 UTC (rev 4650) @@ -10,5 +10,4 @@ zip_safe = False, package_data = {'': ['*.h']}, packages = find_packages() - #install_requires = ['scipy >= 0.6.0'] ) From scipy-svn at scipy.org Mon Aug 18 16:58:28 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 18 Aug 2008 15:58:28 -0500 (CDT) Subject: [Scipy-svn] r4651 - in branches: . fast_vectorize sandbox/scipy/sandbox Message-ID: <20080818205828.9A78339C0F7@scipy.org> Author: ilan Date: 2008-08-18 15:58:28 -0500 (Mon, 18 Aug 2008) New Revision: 4651 Added: branches/fast_vectorize/ Removed: branches/sandbox/scipy/sandbox/mkufunc/ Log: Moved my project into root of branches. Copied: branches/fast_vectorize (from rev 4650, branches/sandbox/scipy/sandbox/mkufunc) Property changes on: branches/fast_vectorize ___________________________________________________________________ Name: svn:mergeinfo + From scipy-svn at scipy.org Tue Aug 19 15:02:05 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 19 Aug 2008 14:02:05 -0500 (CDT) Subject: [Scipy-svn] r4652 - in branches/Interpolate1D: . docs tests Message-ID: <20080819190205.E325339C100@scipy.org> Author: fcady Date: 2008-08-19 14:02:03 -0500 (Tue, 19 Aug 2008) New Revision: 4652 Modified: branches/Interpolate1D/__init__.py branches/Interpolate1D/docs/tutorial.rst branches/Interpolate1D/interpolate1d.py branches/Interpolate1D/interpolate2d.py branches/Interpolate1D/setup.py branches/Interpolate1D/tests/test_interpolate2d.py Log: minor changes, some in preparation for ND scattered interpolation Modified: branches/Interpolate1D/__init__.py =================================================================== --- branches/Interpolate1D/__init__.py 2008-08-18 20:58:28 UTC (rev 4651) +++ branches/Interpolate1D/__init__.py 2008-08-19 19:02:03 UTC (rev 4652) @@ -18,3 +18,5 @@ # wrapper around Fortran implementing Tom's algorithm 526 from algorithm526_wrapper import algorithm526 +from interpSNd import InterpolateSNd + Modified: branches/Interpolate1D/docs/tutorial.rst =================================================================== --- branches/Interpolate1D/docs/tutorial.rst 2008-08-18 20:58:28 UTC (rev 4651) +++ branches/Interpolate1D/docs/tutorial.rst 2008-08-19 19:02:03 UTC (rev 4652) @@ -166,9 +166,9 @@ interpolated. --------------------------------------- +----------------------------------------------------------- User-defined Interpolation Methods --------------------------------------- +----------------------------------------------------------- The string interface is designed to conveniently take care of most things a user would want to do in a way that is easy and, when something goes wrong, informative and helpful. @@ -579,8 +579,8 @@ newz = interp2d(x, y, z, newx, newy, kind='linear', out=NaN) -where x, y, z, are 1D arrays or lists, and newx and newy may be either arrays, lists or scalars. -If they are scalars or zero-dimensional arrays, newz will be a scalar as well. Otherwise +where x, y, z, are arrays (1D or 2D) or lists, and newx and newy may be either arrays, lists or scalars. +If newx and newy are scalars or zero-dimensional arrays, newz will be a scalar as well. Otherwise a vector is returned. The only differences from intper1d are #) The known data points are specified by 3 arrays (x, y and z) rather than 2 (x and y). @@ -737,8 +737,22 @@ ND Scattered Interpolation ================================================ - Still in development. +Still in development. - Ideally the range of interpolation would be the convex hull of the known - data points, and a Delaunay tesselation would be determined and stored - at instantiation. Then again, that would be very expensive. \ No newline at end of file +Ideally the range of interpolation would be the convex hull of the known +data points, and a Delaunay tesselation would be determined and stored +at instantiation. Then again, that would be very expensive. + +InterpolateNd suffers from the requirement that data points be on a uniformly +spaced grid. This problem is solved by the callable class InterpolateSNd and +the function interpSNd, which interpolate *scattered* N-dimensional data. + +First off a warning. The code is in a rather preliminary stage which, while functioning, +is VERY slow and not extensively tested. This state of affairs is still being improved. + +The valid interpolation range is the convex hull of the data points. + + + + +This functionality is still preliminary. \ No newline at end of file Modified: branches/Interpolate1D/interpolate1d.py =================================================================== --- branches/Interpolate1D/interpolate1d.py 2008-08-18 20:58:28 UTC (rev 4651) +++ branches/Interpolate1D/interpolate1d.py 2008-08-19 19:02:03 UTC (rev 4652) @@ -164,7 +164,7 @@ interpolate from. Note that 2-dimensional y is not supported. - newx -- list of 1D numpy array + newx (when calling) -- list of 1D numpy array x values at which to interpolate the value of the function Modified: branches/Interpolate1D/interpolate2d.py =================================================================== --- branches/Interpolate1D/interpolate2d.py 2008-08-18 20:58:28 UTC (rev 4651) +++ branches/Interpolate1D/interpolate2d.py 2008-08-19 19:02:03 UTC (rev 4652) @@ -36,26 +36,137 @@ # functional interface: creates and calls an instance of objective interface def interp2d(x, y, z, newx, newy, kind='linear', out=NaN, bad_data=None): + """ A function for interpolation of 2D, real-valued data. + + Parameters + ----------- + + x -- list or NumPy array + x includes the x-values for the data set to + interpolate from. If it is in array, it must be + 1 or 2-dimensional + + y -- list or NumPy array + y includes the y-values for the data set to + interpolate from. If it is in array, it must be + 1 or 2-dimensional + + z -- list or 1D NumPy array + z includes the z-values for the data set to + interpolate from. If it is in array, it must be + 1 or 2-dimensional + + newx -- list or NumPy array + newx includes the x-values for the points at + which to perform interpolation. If it is in array, + it must be 1 or 2-dimensional + + newy -- list or NumPy array + newy includes the y-values for the points at + which to perform interpolation. If it is in array, + it must be 1 or 2-dimensional + + Optional Arguments + ------------------- + + kind -- Usually a string. But can be any type. + Specifies the type of interpolation to use for values within + the range of x. + + By default, linear interpolation is used. + + See below for details on other options. + + out -- same as for kind + How to extrapolate values for outside the rectangle defined by + min(x) <= newx[i] <= max(x) , min(y) <= newy[i] <= max(y) + Same options as for 'kind'. Defaults to returning numpy.NaN ('not + a number') for all values below the region. + + bad_data -- list of numbers + List of numerical values (in x, y or z) which indicate unacceptable data. + + If bad_data is not None (its default), all points whose x, y or z coordinate is in + bad_data, OR ones of whose coordinates is NaN, will be removed. Note that + bad_data != None means NaNs will be removed even if they are not in + bad_data. + + Some Acceptable Input Strings + ------------------------ + + "linear" -- linear interpolation : default + "spline" -- spline interpolation of default order + "quad", "quadratic" -- spline interpolation order 2 + "cubic" -- spline interpolation order 3 + "quartic" -- spline interpolation order 4 + "quintic" -- spline interpolation order 5 + "526" -- TOMS algorithm 526 + + Other options for kind and out + --------------------------------------------------- + + If you choose to use a non-string argument, you must + be careful to use correct formatting. + + If a function is passed, it will be called when interpolating. + It is assumed to have the form + newz = interp(x, y, z, newx, newy), + where x, y, newx, and newy are all numpy arrays. + + If a callable class is passed, it is assumed to have format + instance = Class(x, y, z). + which can then be called by + newz = instance(newx, newy) + + If a callable object with method "init_xyz" or "set_xyz" is + passed, that method will be used to set x and y as follows + instance.set_xy(x, y) + and the object will be called during interpolation. + newz = instance(newx, newy) + If the "init_xyz" and "set_xyz" are not present, it will be called as + newz = argument(x, y, z, newx, newy) + + A primitive type which is not a string signifies a function + which is identically that value (e.g. val and + lambda x, y, newx : val are equivalent). + + Example + --------- + + >>> import numpy + >>> from interpolate import Interpolate2d + >>> x = range(5) # note list is permitted + >>> y = numpy.arange(5.) + >>> z = x+y + >>> newx = [.2, 2.3, 2.6, 7.0] + >>> newy = [1, 1, 1, 1] + >>> interp_func = Interpolate2d(x, y, z) + >>> interp_func(newx, newy) + array([1.2, 3.3, 3.6, NaN]) + """ return Interpolate2d(x, y, z, kind=kind, out=out, bad_data=bad_data)(newx, newy) # objective interface class Interpolate2d: - """ A callable class for interpolation of 1D, real-valued data. + """ A callable class for interpolation of 2D, real-valued data. Parameters ----------- - x -- list or 1D NumPy array + x -- list or NumPy array x includes the x-values for the data set to - interpolate from. + interpolate from. If it is in array, it must be + 1 or 2-dimensional - y -- list or 1D NumPy array + y -- list or NumPy array y includes the y-values for the data set to - interpolate from. + interpolate from. If it is in array, it must be + 1 or 2-dimensional z -- list or 1D NumPy array z includes the z-values for the data set to - interpolate from. + interpolate from. If it is in array, it must be + 1 or 2-dimensional Optional Arguments ------------------- @@ -91,6 +202,7 @@ "cubic" -- spline interpolation order 3 "quartic" -- spline interpolation order 4 "quintic" -- spline interpolation order 5 + "526" -- TOMS algorithm 526 Other options for kind and out --------------------------------------------------- @@ -131,9 +243,8 @@ >>> newx = [.2, 2.3, 2.6, 7.0] >>> newy = [1, 1, 1, 1] >>> interp_func = Interpolate2d(x, y, z) - >>> interp_fuc(newx, newy) + >>> interp_func(newx, newy) array([1.2, 3.3, 3.6, NaN]) - """ def __init__(self, x, y, z, kind='linear', out=NaN, bad_data=None): @@ -148,15 +259,15 @@ # FIXME : perhaps allow 2D input if it is inthe form of meshgrid # check acceptable sizes and dimensions + # and make data 1D x = np.atleast_1d(x) y = np.atleast_1d(y) z = np.atleast_1d(z) - assert len(x) > 0 and len(y) > 0 and len(z)>0, "Arrays cannot be of zero length" - assert x.ndim == 1 , "x must be one-dimensional" - assert y.ndim == 1 , "y must be one-dimensional" - assert z.ndim == 1 , "z must be one-dimensional" - assert len(x) == len(y) , "x and y must be of the same length" - assert len(x) == len(z) , "x and z must be of the same length" + assert x.shape == y.shape, "x and y must be the same shape" + assert x.shape == z.shape, "z must be the same shape as x and y" + assert x.ndim in [1, 2], "x and y must be at most 2-dimensional" + assert np.size(x) >= 0, "x, y and z cannot be of size zero" + x, y, z = map(np.ravel, [x, y, z]) # remove bad data if applicable if bad_data is not None: @@ -246,18 +357,22 @@ isinstance( newx , np.ndarray ) and np.shape(newx) == () or \ isinstance( newy , np.ndarray ) and np.shape(newy) == () - # make input into a nice 1d, contiguous array - newx = atleast_1d_and_contiguous(newx, dtype=self._xdtype) - newy = atleast_1d_and_contiguous(newy, dtype=self._ydtype) - assert newx.ndim == 1, "newx can be at most 1-dimensional" - assert newy.ndim == 1, "newy can be at most 1-dimensional" - assert len(newx) == len(newy), "newx and newy must be the same length" + # check acceptable sizes and dimensions, record the shape of the input, + # and make data 1D + newx = np.atleast_1d(newx) + newy = np.atleast_1d(newy) + assert newx.shape == newy.shape, "newx and newy must be the same shape" + assert newx.ndim in [1, 2], "newx and newy must be at most 2-dimensional" + assert np.size(newx) >= 0, "newx and newy must be of size greater than zero" + shape_of_newx = newx.shape + newx, newy= map(np.ravel, [newx, newy]) + # finding which points are in the valid interpolation range in_range_mask = (min(self._x) <= newx) & (newx <= max(self._x)) & \ (min(self._y) <= newy) & (newy <= max(self._y)) - # filling array of interpolated z-values - result = np.zeros(np.shape(newx), dtype = self._zdtype) + # making array of interpolated z-values + result = np.empty(np.shape(newx), dtype = self._zdtype) if sum(in_range_mask) > 0: # if there are in-range values. hack to deal # with behavior of np.vectorize on arrays of length 0 result[in_range_mask] = self.kind(newx[in_range_mask], newy[in_range_mask]) @@ -267,5 +382,7 @@ # revert to scalar if applicable if input_is_scalar: result = result[0] + else: + result = np.reshape(result, shape_of_newx) return result \ No newline at end of file Modified: branches/Interpolate1D/setup.py =================================================================== --- branches/Interpolate1D/setup.py 2008-08-18 20:58:28 UTC (rev 4651) +++ branches/Interpolate1D/setup.py 2008-08-19 19:02:03 UTC (rev 4652) @@ -46,10 +46,12 @@ 'extensions/interp_526.f'] ) + # include tutorial on the module config.add_data_dir('docs') return config if __name__ == '__main__': + #from setuptools import setup from numpy.distutils.core import setup setup(**configuration().todict()) \ No newline at end of file Modified: branches/Interpolate1D/tests/test_interpolate2d.py =================================================================== --- branches/Interpolate1D/tests/test_interpolate2d.py 2008-08-18 20:58:28 UTC (rev 4651) +++ branches/Interpolate1D/tests/test_interpolate2d.py 2008-08-19 19:02:03 UTC (rev 4652) @@ -17,7 +17,72 @@ def assertAllclose(self, x, y): self.assert_(np.allclose(atleast_1d_and_contiguous(x), atleast_1d_and_contiguous(y))) + + def test_string_linear(self): + """ make sure : string 'linear' works + """ + N = 7 + X, Y = meshgrid(arange(N), arange(N)) + Z = X + Y + x, y, z = map(ravel, [X, Y, Z] ) + newx = np.arange(1, N)-0.5 + newy = newx + + interp_func = Interpolate2d(x, y, z, kind='linear', out='linear') + newz = interp_func(newx, newy) + + self.assertAllclose(newz, newx+newy) + + def test_string_quadratic(self): + """ make sure : string 'quadratic' works + """ + N = 7 + X, Y = meshgrid(arange(N), arange(N)) + Z = X + Y + x, y, z = map(ravel, [X, Y, Z] ) + + newx = np.arange(1, N)-0.5 + newy = newx + + interp_func = Interpolate2d(x, y, z, kind='quadratic', out='quad') + newz = interp_func(newx, newy) + + self.assertAllclose(newz, newx+newy) + + def test_string_cubic(self): + """make sure : string "cubic" works + """ + N = 7 + X, Y = meshgrid(arange(N), arange(N)) + Z = X + Y + x, y, z = map(ravel, [X, Y, Z] ) + + newx = np.arange(1, N)-0.5 + newy = newx + + interp_func = Interpolate2d(x, y, z, kind='cubic', out='cubic') + newz = interp_func(newx, newy) + + self.assertAllclose(newz, newx+newy) + + def test_string_526(self): + """ make sure : keyword '526' works + ie that TOMS algorithm 526 works + """ + N = 7 + X, Y = meshgrid(arange(N), arange(N)) + Z = X + Y + x, y, z = map(ravel, [X, Y, Z] ) + + newx = np.arange(1, N)-0.5 + newy = newx + + interp_func = Interpolate2d(x, y, z, kind='526', out='526') + newz = interp_func(newx, newy) + + self.assertAllclose(newz, newx+newy) + def test_callable_class_interpolation(self): """ make sure : instance of callable class with xyz not initiated works """ @@ -126,70 +191,21 @@ self.assert_( np.isnan(newz[0]) ) self.assert_( np.isnan(newz[-1]) ) - def test_string_linear(self): - """ make sure : string 'linear' works + + def test_2D_input(self): + """ make sure : newx and newy can be 2D, and the result is also 2D """ N = 7 X, Y = meshgrid(arange(N), arange(N)) Z = X + Y x, y, z = map(ravel, [X, Y, Z] ) - newx = np.arange(1, N)-0.5 - newy = newx + newx, newy = meshgrid(arange(1, N)-.2, arange(1,N)-.2) interp_func = Interpolate2d(x, y, z, kind='linear', out='linear') newz = interp_func(newx, newy) self.assertAllclose(newz, newx+newy) - def test_string_quadratic(self): - """ make sure : string 'quadratic' works - """ - N = 7 - X, Y = meshgrid(arange(N), arange(N)) - Z = X + Y - x, y, z = map(ravel, [X, Y, Z] ) - - newx = np.arange(1, N)-0.5 - newy = newx - - interp_func = Interpolate2d(x, y, z, kind='quadratic', out='quad') - newz = interp_func(newx, newy) - - self.assertAllclose(newz, newx+newy) - - def test_string_cubic(self): - """make sure : string "cubic" works - """ - N = 7 - X, Y = meshgrid(arange(N), arange(N)) - Z = X + Y - x, y, z = map(ravel, [X, Y, Z] ) - - newx = np.arange(1, N)-0.5 - newy = newx - - interp_func = Interpolate2d(x, y, z, kind='cubic', out='cubic') - newz = interp_func(newx, newy) - - self.assertAllclose(newz, newx+newy) - - def test_string_526(self): - """ make sure : keyword '526' works - ie that TOMS algorithm 526 works - """ - N = 7 - X, Y = meshgrid(arange(N), arange(N)) - Z = X + Y - x, y, z = map(ravel, [X, Y, Z] ) - - newx = np.arange(1, N)-0.5 - newy = newx - - interp_func = Interpolate2d(x, y, z, kind='526', out='526') - newz = interp_func(newx, newy) - - self.assertAllclose(newz, newx+newy) - if __name__ == '__main__': unittest.main() \ No newline at end of file From scipy-svn at scipy.org Tue Aug 19 15:07:10 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 19 Aug 2008 14:07:10 -0500 (CDT) Subject: [Scipy-svn] r4653 - branches Message-ID: <20080819190710.1E91639C100@scipy.org> Author: fcady Date: 2008-08-19 14:07:08 -0500 (Tue, 19 Aug 2008) New Revision: 4653 Added: branches/interpolate/ Log: rename Interpolate1D -> interpolate. Much better since supports interpolation in many dimensions Copied: branches/interpolate (from rev 4651, branches/Interpolate1D) From scipy-svn at scipy.org Tue Aug 19 15:12:22 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 19 Aug 2008 14:12:22 -0500 (CDT) Subject: [Scipy-svn] r4654 - in branches/interpolate: . interpSNd Message-ID: <20080819191222.DE8DD39C100@scipy.org> Author: fcady Date: 2008-08-19 14:12:18 -0500 (Tue, 19 Aug 2008) New Revision: 4654 Added: branches/interpolate/interpSNd/ branches/interpolate/interpSNd/_triang.cpp branches/interpolate/interpSNd/dewall.py branches/interpolate/interpSNd/dewall.pyc branches/interpolate/interpSNd/example.py branches/interpolate/interpSNd/interp.py branches/interpolate/interpSNd/interpolateSNd.py branches/interpolate/interpSNd/interpolateSNd.pyc branches/interpolate/interpSNd/output.txt branches/interpolate/interpSNd/script.py branches/interpolate/interpSNd/setup.py branches/interpolate/interpSNd/test.py Log: added ND scattered interpolation Added: branches/interpolate/interpSNd/_triang.cpp =================================================================== --- branches/interpolate/interpSNd/_triang.cpp 2008-08-19 19:07:08 UTC (rev 4653) +++ branches/interpolate/interpSNd/_triang.cpp 2008-08-19 19:12:18 UTC (rev 4654) @@ -0,0 +1,85 @@ +/*This will become an extension module used to speed up the slow steps + in InterpolateSNd. + + The best step to speed up is calculation of the circumcircle. +*/ + +#include "Python.h" +#include +#include +#include + +#include "numpy/arrayobject.h" // required to use arrays +#include "numpy/ufuncobject.h" + +using namespace std; + +extern "C" { + +/* test function */ +PyObject * sayHello(PyObject *self, PyObject *args) +{ + int x; + PyObject *other_arg; + if (!PyArg_ParseTuple(args, "iO", x, &other_arg)){ + return NULL; + } + printf("\nhello world\n"); + return other_arg; +} + + + +/* merely return first element of a matrix */ +PyObject * upperleft(PyObject *self, PyObject *args) +{ + PyArrayObject *data_coordinates; + + // parse tuple + if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &data_coordinates)){ + return NULL; + } + + // make sure floats + if (data_coordinates->descr->type_num != PyArray_DOUBLE){ + PyErr_SetString(PyExc_ValueError, + "array must be of type float"); + return NULL; + } + + //first element of array + double ans; + ans = *(double *)(data_coordinates->data); + + return PyFloat_FromDouble(ans); + +} + + +/* tell Python which methods are available */ +static PyMethodDef triang_methods[]={ + {"sayHello", (PyCFunction)sayHello, METH_VARARGS, "says hi"}, + {"upperleft", (PyCFunction)upperleft, METH_VARARGS, ""}, + //{"lookup", (PyCFunction)lookup, METH_VARARGS, ""},*/ + {NULL, NULL, 0, NULL} +}; + + +/* initialize the module */ +PyMODINIT_FUNC init_triang(void) +{ + PyObject* m; + m = Py_InitModule3("_triang", triang_methods, + "stupid, useless module that will get better\n" + ); + if (m == NULL) + return; + import_array(); //required at initialization in order to use arrays +} + + + + + + +} //extern "C" \ No newline at end of file Added: branches/interpolate/interpSNd/dewall.py =================================================================== --- branches/interpolate/interpSNd/dewall.py 2008-08-19 19:07:08 UTC (rev 4653) +++ branches/interpolate/interpSNd/dewall.py 2008-08-19 19:12:18 UTC (rev 4654) @@ -0,0 +1,393 @@ +# implements algorithm found at +# http://vcg.isti.cnr.it/publications/papers/dewall.pdf + +# WARNING +# This code is grotesquely inefficient and messy. +# The goal is to have it be 1) correct, and 2) understandable +# The next phase is to rewrite it using arrays and efficient algorithms. +# After that, the slow parts should be translated into C. + +# In particular, calculation of the circumcircle is a purely +# mathematical operation that really should be made into C. + +import numpy as np +from numpy.linalg import norm + +eps =1e-5 +compare_first_elem = lambda t1, t2 : cmp(t1[0], t2[0]) +point_in_list = lambda p, L : np.any([ (p==elem).all() for elem in L ]) +face_in_list = lambda f, L : np.any([ np.alltrue([point_in_list(p,face) for p in f]) for face in L]) +compare_pointlists = lambda L1, L2 : np.alltrue([ point_in_list(l1, L2) for l1 in L1]) and \ + np.alltrue([ point_in_list(l2, L1) for l2 in L2]) + +def dewall (P, #set of points + AFL = [], # list of faces: (d-1)face list + ): + + # checking input + assert isinstance(P, list) + if len(P)>0: + assert isinstance(P[0], np.ndarray) + assert isinstance(AFL, list) + if len(AFL)>0: + #print "AFL[0]: ", AFL[0] + assert isinstance(AFL[0],tuple) + assert isinstance(AFL[0][0], list) + assert isinstance(AFL[0][0][0], np.ndarray) + assert isinstance(AFL[0][1], np.ndarray) + + # base case + if len(P) == 0: return [] + if len(P) <= len(P[0]): return [] # better to return [] whenever points are co-hyper-planar + + # lists of active faces + # elem = ( [list of d points] , outvec ) + AFL_alpha = [] + AFL1 = [] + AFL2 = [] + + # list of simplices + Sigma= [] + + alpha = select_alpha(P, AFL) + + # divide points into two sets separated by alpha + P1, P2 = pointset_partition(P, alpha) # both lists of points + + # Simplex Wall Construction + just_starting = False #source of problem? + if len(AFL) == 0: + just_starting = True + first_simplex = make_first_simplex(P, alpha) + AFL = [ (face, get_out_vec(face,first_simplex))\ + for face in faces(first_simplex)] # d+1 of them + Sigma.append(first_simplex) + for face, outvec in AFL: + if is_intersected(face, alpha): # not counting as intersected + AFL_alpha.append((face, \ + get_out_vec(face,first_simplex) if just_starting \ + else outvec)) + if is_subset(face, P1): + AFL1.append((face,outvec)) + if is_subset(face, P2): + AFL2.append((face,outvec)) + while len(AFL_alpha) != 0: + + face, outvec = AFL_alpha.pop() + + if outvec is not None: + outward_points = filter( lambda p: (np.dot(p,outvec)>np.dot(face[0],outvec)),\ + P) + else: + outward_points = filter( lambda p: np.all([not point_in_list(p,vertex) for vertex in face]), P) + + t = make_simplex(face, outward_points) # make only over outer half space + if t is not None: + Sigma.append(t) + # for f0 != f in faces(t) , ie for new outward faces + for f0 in filter(lambda f: not face_in_list(f,[face]), faces(t)): + new_pair = (f0, get_out_vec(f0, t)) + if is_intersected(f0, alpha): + # continue building wall out in that direction + AFL_alpha = update(new_pair, AFL_alpha) + if is_subset(f0, P1): + AFL1 = update(new_pair, AFL1) + if is_subset(f0, P2): + AFL2 = update(new_pair, AFL2) + + # now Sigma contains all simplices that intersect alpha + + # Recursive Triangulation + if len(AFL2)!=0: + Sigma = Sigma + dewall(P2,AFL2) + if len(AFL1)!=0: + Sigma = Sigma + dewall(P1,AFL1) # not doing this branch of recursion + return Sigma + +def select_alpha(P, AFL): + # dividing plane. This must divide points into 2 non-empty parts + # must intersect active face if there is one + # must not intersect any points + + #assert isinstance(P, list) + #if len(P)>0: + # assert isinstance(P[0], np.ndarray) + #assert isinstance(AFL, list) + #if len(AFL)>0: + # assert isinstance(AFL[0],list) + # assert isinstance(AFL[0][0], list) + # assert isinstance(AFL[0][0][0], np.ndarray) + # assert isinstance(AFL[0][1], np.ndarray) + + d = len(P[0]) + + # plane through avg of cluster. Guarantees separation + # must also make sure intersects face in AFL + if len(AFL) != 0: + mid = sum(AFL[0][0])/(d) + else: + mid = sum(P)/len(P) + if norm(mid)==0: + direction = np.random.random_sample((d)) + alpha = ( direction/norm(direction), 0) + else: + alpha =(mid/norm(mid), norm(mid)) + + return alpha + +def get_out_vec(face, simplex): #SEEMS GOOD + # face is a face of simplex + # returns vector normal to face pointing out of simplex + assert len(face)==len(face[0]), "face needs d points" + assert len(simplex)-len(face)==1, "simplex needs one more point" + + d = len(face[0]) # dimension + + # get point in simplex that's not in face + # vector must face away from it + other_point = filter(lambda p: not point_in_list(p, face), + simplex)[0] + + # determinants of submatrices give components of a vector + # that is orthogonal to each row + vecs_along_face = np.array([point-face[0] for point in face[1:]]) + normal_vector = np.zeros(d) + + # normal vector must be orthogonal to each element of matrix_of_diffs + # components given by determinants of submatrices + for i in range(d): + normal_vector[i] = ((-1)**i)*\ + np.linalg.det(vecs_along_face[:,np.arange(d)!=i]) + unit_normal = normal_vector/norm(normal_vector) + + # return unit_normal point in correct direction + if np.dot(other_point, unit_normal) < np.dot(face[0], unit_normal): + return unit_normal + else: + return -1*unit_normal + +def is_subset(S1, S2): + # both are lists of arrays + return np.alltrue([ point_in_list(s1, S2) for s1 in S1]) + +def update (face_pair, face_pair_list): + # returns face_list with face_pair added if it wasn't there, else deleted + face, outvec = face_pair + face_list = [face for face, outvec in face_pair_list] + if face_in_list(face, face_pair_list): + f_not_equal_face = lambda f : not np.alltrue([ point_in_list(p, f[0]) for p in face ]) + face_pair_list = filter(f_not_equal_face, face_pair_list) + else: + face_pair_list.append(face_pair) + return face_pair_list + +def pointset_partition(P, alpha): #WORKS + P1 = [p for p in P if np.dot(p,alpha[0])< alpha[1]] + P2 = [p for p in P if np.dot(p,alpha[0])>=alpha[1]] + return P1, P2 + +def is_intersected(f, alpha): #WORKS + assert isinstance(f, list), "the face must be a list: "+str(f) + assert isinstance(alpha, tuple), "alpha must be tuple: "+str(alpha) + assert isinstance(alpha[0],np.ndarray), "normal vector: "+str(alpha[0]) + assert isinstance(f[0],np.ndarray), "point in f: "+str(f[0]) + list_of_dot_prods = [np.dot(alpha[0], point) for point in f] + all_dots_nonneg = [ prod >= alpha[1] for prod in list_of_dot_prods] + all_dots_nonpos = [ prod <= alpha[1] for prod in list_of_dot_prods] + return not (np.all(all_dots_nonneg) or np.all(all_dots_nonpos)) + +def faces(simplex): #WORKS + # given simplex (as list of points) returns list of faces (each face a list of points) + faces = [] + for point in simplex: + faces.append( [p for p in simplex if (p!=point).any()] ) + return faces + +def make_first_simplex(P, alpha): #WORKS + # alpha = unit_normal_vec, distance + # assume no points on plane + + d = len(P[0]) + unit_normal, distance = alpha + points_and_distances = [(np.dot(unit_normal, point), point) for point in P] + + points_and_dist_from_alpha = [ (norm(distance-dist), point) for (dist, point) in points_and_distances] + + first_point = sorted(points_and_dist_from_alpha, + cmp = compare_first_elem \ + )[0][1] # closest to alpha + + possible_second_pts = [ (circumcircle([first_point, point])[1], point) \ + for point in P if (point != first_point).any() and \ + (np.dot(unit_normal, first_point)-distance)*(np.dot(unit_normal, point)-distance)<=0 \ + ] + second_point = sorted(possible_second_pts, \ + cmp = compare_first_elem \ + )[0][1] + simplex = [first_point, second_point] + for i in range(d-1): + radii_of_circumcircles = [(circumcircle( copy_list(simplex)+[point.copy()] )[1], point) \ + for point in P if not point_in_list(point, simplex) ] + new_point = sorted(radii_of_circumcircles, \ + cmp = compare_first_elem \ + )[0][1] + simplex.append(new_point) + + return simplex + +def copy_list(list_of_arrays): #WORKS + # returns a list of copies of the arrays + # use if want to modify an array list without + result = [array.copy() for array in list_of_arrays] + return result + + + +def make_simplex(f,P): #WORKS + # must be only in the outer halfspace + + # returns the simlex + + # clean up by making sure only points not in hyperplane(f) are in P + + valid_points = [p for p in P if not point_in_list(p,f)] + if len(valid_points) == 0: + return None + delaunay_distances = [(delaunay_dist(f,p) ,p) for p in valid_points] + new_point = sorted(delaunay_distances, cmp = compare_first_elem)[0][1] + simplex = f+[new_point] + return simplex + +def delaunay_dist(f, p): #WORKS + # |distance| = radius of circumcircles + # sign depends on whether center is on same side as p + + # FIXME : don't let pathological stuff come in + + normal, distance = spanning_hyperplane(f) + center, radius = circumcircle( [elem.copy() for elem in f]+[p] ) #need copy of f and add to it + if (np.dot(normal,center) >= distance and np.dot(normal,p) >= distance) \ + or (np.dot(normal,center) <= distance and np.dot(normal,p) <= distance) \ + or radius == np.Inf: + return radius + else: + return -1*radius + +def spanning_hyperplane(f): #WORKS + # f=list of points + # return outward unit normal to hyperplane they define + # and distance to hyperplane from the origin + d = len(f[0]) + + # determinants of submatrices give components of a vector + # that is orthogonal to each row + matrix_of_diffs = np.array([point-f[0] for point in f[1:]]) + normal_vector = np.zeros(d) + + # normal vector must be orthogonal to each element of matrix_of_diffs + # components given by determinants of submatrices + for i in range(d): + normal_vector[i] = ((-1)**i)*np.linalg.det(\ + matrix_of_diffs[:,np.arange(d)!=i]) + unit_normal = normal_vector/norm(normal_vector) + distance = np.dot(unit_normal, f[0]) + + # want a positive distance + if distance < 0: + return -1*unit_normal, -1*distance + return unit_normal, distance + +def circumcircle(Points): #WORKS + # P = list of distinct points + # n distinct points, with n<= d+1 + # returns (center=array, radius) + + # FIXME : account for collinear/same and error check + + # calculates center by forming system of linear constraints + # on its components, and calculates radius after that + + d = len(Points[0]) # dimensionality of space + n = len(Points) + + # need "infinitely big" circle in this case + if not linearly_independent(Points): + return np.Inf*np.ones(d), np.Inf + + matrix = np.zeros((d,d), dtype=np.float64) # d constraints to find the center + vector = np.zeros((d,1), dtype=np.float64) + + difference_vecs = [(Points[i]-Points[0])/norm(Points[i]-Points[0]) \ + for i in range(1,n) if norm(Points[i]-Points[0])>eps] # n-1 difference vectors. Point along hyperplane + n = len(difference_vecs) + 1 # correct for possible degeneracies in the input + + # for each P[0] -- P[i] line segment, center is along the middle of it + for i in range(n-1): + matrix[i,:] = difference_vecs[i] + vector[i,0] = np.dot( difference_vecs[i] , (Points[0]+Points[i+1])/2) + + # center is in the hyperplane defined by the points + # ie its componeny orthogonal to difference_vecs is same as that of all points + orthog_comp = orthogonal_complement(difference_vecs) + m = len(orthog_comp) # m+n = d + if m+(n-1) != d: + assert False, "messed up. m=%i, and n=%i " % (m, n) + for i in range(m): + matrix[n-1+i,:] = orthog_comp[i] + vector[n-1+i,0] = np.dot(Points[0], orthog_comp[i]) + + # calculating and returning + center = np.linalg.solve(matrix, vector) + radius = norm(center-np.reshape(Points[0],(d,1))) + return np.reshape(center,(d)), radius + +def orthogonal_complement(P): #WORKS + # return orthogonal complement of P of unit length + # in = list of 1D arrays + # out = list of 1D arrays + + # nothing here can be pathological + + P = copy_list(P) # this way won't harm original P + d = len(P[0]) # dimensionality + n = len(P) # number of points. <= d + + # Graham-Schmidt orthonormalization of input vectors + for j in range(n): + for k in range(j): + P[j] = P[j] - np.dot(P[k],P[j])*P[k] + if norm(P[j]) > eps: + P[j]=P[j]/norm(P[j]) + + # remove linear dependencies and normalize + P = np.array([point/norm(point) for point in P if norm(point)>eps]) + + orthog = np.eye(d,d) + for j in range(d): + # remove component of Oj in P + for k in range(len(P)): + orthog[j,:] = orthog[j,:] - np.dot(P[k,:],orthog[j,:])*P[k,:] + + # remove component of Oj in Oi with i eps: + orthog[j,:] = orthog[j,:]/norm(orthog[j,:]) + + # return each non-zero vector + return [np.reshape(orthog[j,:],(d)) for j in range(d) if norm(orthog[j,:])>eps] + +def linearly_independent(P): + # return true if the vectors are linearly independent + # needs n points + d=len(P[0]) + if len(P)>d: return False + matrix = np.array(P).reshape((d,len(P))) + return np.rank(matrix)==len(P) + + + + + \ No newline at end of file Added: branches/interpolate/interpSNd/dewall.pyc =================================================================== (Binary files differ) Property changes on: branches/interpolate/interpSNd/dewall.pyc ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: branches/interpolate/interpSNd/example.py =================================================================== --- branches/interpolate/interpSNd/example.py 2008-08-19 19:07:08 UTC (rev 4653) +++ branches/interpolate/interpSNd/example.py 2008-08-19 19:12:18 UTC (rev 4654) @@ -0,0 +1,12 @@ +# example sript +import _triang as _t +import numpy as np + +print "dir(_t): ", dir(_t) +a = _t.sayHello(5 ,'foo') +print "it worked? I won't see this" +print "a equals: ", a + +arr = np.array([1.0, 2.3, 4.8]) +print "other answer: ", _t.triangulate(arr) +print "now at end" \ No newline at end of file Added: branches/interpolate/interpSNd/interp.py =================================================================== --- branches/interpolate/interpSNd/interp.py 2008-08-19 19:07:08 UTC (rev 4653) +++ branches/interpolate/interpSNd/interp.py 2008-08-19 19:12:18 UTC (rev 4654) @@ -0,0 +1,18 @@ +import interpolateSNd as SN +import numpy as np + +reload(SN) + +points = np.array([[ 1.,0.,1.,0.],[0.,0.,1.,1.]]) +z = np.array([1.,0.,2.,1.]) +interp = SN.InterpolateSNd(points,z) + +print "triangulation:\n",interp._triangulation + +X=np.array([[1.4,.1,.55],[.4,.1,.3]]) +print "X values:\n",X +# last component is .1 too much + +output = interp(X) + +print "output:\n", output \ No newline at end of file Added: branches/interpolate/interpSNd/interpolateSNd.py =================================================================== --- branches/interpolate/interpSNd/interpolateSNd.py 2008-08-19 19:07:08 UTC (rev 4653) +++ branches/interpolate/interpSNd/interpolateSNd.py 2008-08-19 19:12:18 UTC (rev 4654) @@ -0,0 +1,200 @@ +""" ND Scattered interpolation +""" + +import dewall as dw +import numpy as np + +class InterpolateSNd: + """ Interpolation of scatter data in arbitrarily many dimensions + + ******* + WARNING : this code is currently extremely slow. It is very much still + ******* + in development, but because it functions correctly it is being + presented. + + Parameters: + ------------ + + points : 2D numpy array + dxn array, where d is dimensionality of the data and + there are n data points. Each column of the array is + a data point. + + fvals : 1D numpy array + Must have length n. fvals[j] is the value of the function + at point point[:,j] + + newX (when calling) : 2D numpy array + shape dxm. Each column is a point at which to interpolate + the function value. + + The valid interpolation range is the convex hull of the points. All in-range + points will be linearly interolated, and all out-of-bounds points will return + NaN. + """ + + def __init__(self, P, fvals): + # P = array of points, where each column is a point + # points must be distinct + # fvals = array of known function values + + assert P.ndim == 2, "P must be 2-dimensional" + d, n = P.shape + assert len(fvals)==n, "fvals must have length n,\ + where n is number of points" + + # remember dimensionality of space + self.ndim = d + + # store list of points + self.points = P.copy() + + # store function values + self.fvals = fvals.copy() + + # calculate and store delaunay triangulation + list_of_points = [P[:,i].reshape(d) for i in range(n)] + self._triangulation = dw.dewall(list_of_points) + + # for each simplex, indices of its points in self.points + # lists of tuples(lists) of integers + indices_list = [] + for simplex in self._triangulation: + indices_for_current_point = [] + for point in simplex: + for i in range(n): + # if ith col = point, append i to list + if (point.reshape((d)) == np.reshape(P[:,i],(d))).all(): + indices_for_current_point.append(i) + indices_list.append(indices_for_current_point) + self._indices_list = indices_list + + # FIXME : store list of (simplex, vals) tuples ???? + + def __call__(self, X): + # X = dxm array of points at which to interpolate + d, m = X.shape + assert d==self.ndim, "input must have correct dimensionality" + + # break input into a list of points for list comprehensions. + # yeah, it's very slow, but it's elegant for now + list_of_points = [X[:,i].reshape((d,1)) for i in range(m)] + + # Tuples of form (simplex , vals_at_vertices, point) + simplices_vals_points = [(self._get_simplex(pt), self._get_fvals(pt), pt) \ + for pt in list_of_points] + + result = [self.linear_interp( simplex, vals, point ) \ + for simplex, vals, point in simplices_vals_points] + + return result + + def _get_fvals(self, pt): + assert pt.shape == (self.ndim, 1), "point shape: "+str(pt.shape) + indices = self._get_simplex_indices(pt) + if indices==None: + return None + return self.fvals[indices] + + def _get_simplex(self, pt): + assert pt.shape == (self.ndim, 1), "point shape: "+str(pt.shape) + indices = self._get_simplex_indices(pt) + if indices==None: + return None + return self.points[:,indices] + + def _get_simplex_indices(self, pt): + # returns tuple indicating vertices of simplex containing pt + assert pt.shape == (self.ndim, 1), "point shape: "+str(pt.shape) + indices = None + for i in range(len(self._indices_list)): + if self.point_is_in_simplex(pt.reshape((self.ndim,1)), self.points[:,self._indices_list[i]]): + indices = self._indices_list[i] + break + return indices + + def point_is_in_simplex(self, point, simplex): + # point = array + # simplex = matrix + assert point.shape == (self.ndim, 1), "wrong shape of point: "+str(point.shape) + assert simplex.shape == (self.ndim, self.ndim+1), "wrong shape of simplex: "+str(simplex.shape) + weights_vec = self.calculate_weights(simplex, point) + weight_in_range = (0<= weights_vec) & (weights_vec <= 1) + return np.alltrue(weight_in_range, axis=0) + + def linear_interp(self, simplex, vals, point): + if simplex == None or vals == None: # point is out of range + return np.NaN + + # testing + assert point.shape == (self.ndim, 1), \ + "wrong shape of point: "+str(point.shape) + assert simplex.shape == (self.ndim, self.ndim+1), \ + "wrong shape of simplex: "+str(simplex.shape) + assert vals.shape == (self.ndim+1,), \ + "vals wrong shape: "+str(vals.shape)+"need: "+str((self.ndim,)) + + weights = self.calculate_weights(simplex, point) + return np.dot(np.ravel(weights), np.ravel(vals)) + + def calculate_weights(self, simplex, points): + """ Each column in points is a weighted average + of columns in simplex. Returns matrix where + jth column gives these weights for the jth column + of points. + """ + assert simplex.shape == (self.ndim, self.ndim+1), "simplex shape: "+str(simplex.shape) + d, V = simplex.shape + d, P = points.shape + + matrix_to_solve = np.concatenate((simplex, \ + np.ones((1,V)) + ), + axis = 0 + ) + vec_to_solve = np.concatenate((points, \ + np.ones((1,P)) + ), + axis = 0 + ) + + weights_vecs = np.linalg.solve(matrix_to_solve, vec_to_solve) + + return weights_vecs + +def point_is_in_simplex(point, simplex): + # point = array + # simplex = matrix + #assert point.shape == (self.ndim, 1), "wrong shape of point: "+str(point.shape) + #assert simplex.shape == (self.ndim, self.ndim+1), "wrong shape of simplex: "+str(simplex.shape) + weights_vec = calculate_weights(simplex, point) + print "weights:\n", weights_vec + weight_in_range = (0.<= weights_vec) & \ + (weights_vec <= 1.) + print "in_range:\n", weight_in_range + return np.alltrue(weight_in_range, axis=0) + +def calculate_weights(simplex, points): + """ Each column in points is a weighted average + of columns in simplex. Returns matrix where + jth column gives these weights for the jth column + of points. + """ + N, V = simplex.shape + N, P = points.shape + + matrix_to_solve = np.concatenate((simplex, \ + np.ones((1,V)) + ), + axis = 0 + ) + vec_to_solve = np.concatenate((points, \ + np.ones((1,P)) + ), + axis = 0 + ) + + weights_vecs = np.linalg.solve(matrix_to_solve, vec_to_solve) + + return weights_vecs \ No newline at end of file Added: branches/interpolate/interpSNd/interpolateSNd.pyc =================================================================== (Binary files differ) Property changes on: branches/interpolate/interpSNd/interpolateSNd.pyc ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: branches/interpolate/interpSNd/output.txt =================================================================== --- branches/interpolate/interpSNd/output.txt 2008-08-19 19:07:08 UTC (rev 4653) +++ branches/interpolate/interpSNd/output.txt 2008-08-19 19:12:18 UTC (rev 4654) @@ -0,0 +1,40 @@ + +face: [array([ 0.78256165, 1.25794206]), array([ 5.5867473 , 0.30561524])] +points: [] + +face: [array([ 5.5867473 , 0.30561524]), array([ 0.84738355, 0.4417885 ])] +points: [array([ 0.49630621, 0.38945595])] +delaunay distances: +[(14.481574504701088, array([ 0.49630621, 0.38945595]))] + +face: [array([ 5.5867473 , 0.30561524]), array([ 0.49630621, 0.38945595])] +points: [] + +face: [array([ 0.78256165, 1.25794206]), array([ 0.84738355, 0.4417885 ])] +points: [array([ 0.45697308, 1.26267539]), array([ 0.49630621, 0.38945595]), array([ 0.15363154, 0.794239 ])] +delaunay distances: +[(0.45650505613020009, array([ 0.45697308, 1.26267539])), (0.45830428089834485, array([ 0.49630621, 0.38945595])), (0.45808830610514073, array([ 0.15363154, 0.794239 ]))] + +face: [array([ 0.84738355, 0.4417885 ]), array([ 0.45697308, 1.26267539])] +points: [array([ 0.49630621, 0.38945595]), array([ 0.15363154, 0.794239 ])] +delaunay distances: +[(0.45691821155399881, array([ 0.49630621, 0.38945595])), (0.45699647524242137, array([ 0.15363154, 0.794239 ]))] + +face: [array([ 0.45697308, 1.26267539]), array([ 0.49630621, 0.38945595])] +points: [array([ 0.15363154, 0.794239 ])] +delaunay distances: +[(-0.45659643493482976, array([ 0.15363154, 0.794239 ]))] + +face: [array([ 0.45697308, 1.26267539]), array([ 0.15363154, 0.794239 ])] +points: [] + +face: [array([ 0.84738355, 0.4417885 ]), array([ 0.49630621, 0.38945595])] +points: [] + +face: [array([ 0.84738355, 0.4417885 ]), array([ 0.49630621, 0.38945595])] +points: [array([ 0.15363154, 0.794239 ])] +delaunay distances: +[(0.45765190740816952, array([ 0.15363154, 0.794239 ]))] + +face: [array([ 0.84738355, 0.4417885 ]), array([ 0.15363154, 0.794239 ])] +points: [] Added: branches/interpolate/interpSNd/script.py =================================================================== --- branches/interpolate/interpSNd/script.py 2008-08-19 19:07:08 UTC (rev 4653) +++ branches/interpolate/interpSNd/script.py 2008-08-19 19:12:18 UTC (rev 4654) @@ -0,0 +1,49 @@ +# example script + +import dewall as dw +import numpy as np +from numpy import array +import matplotlib.pyplot as pyplot + +Pa=[array([1.1,1.1]), array([-1.,1.]), array([-1.,-1.]), \ + array([1.,-1.]), array([1.5,1.5])] + +def segments(T): + seg0 = [ [T[0][0],T[1][0]] , [T[0][1],T[1][1]] ] + seg1 = [ [T[0][0],T[2][0]] , [T[0][1],T[2][1]] ] + seg2 = [ [T[1][0],T[2][0]] , [T[1][1],T[2][1]] ] + return [seg0, seg1, seg2] + +def plot_circle(circle): + center, radius = circle + t = np.linspace(0,2*np.pi,500) + x_offset = radius*np.sin(t) + y_offset = radius*np.cos(t) + x = center[0] + x_offset + y = center[1] + y_offset + pyplot.plot(x,y) + +Pb=[array([.25, -.25]), array([0,.75])] + +P = Pa+Pb + +P = [ np.array([np.random.gamma(1), np.random.gamma(1)]) \ + for j in range(6) ] + +triangul = dw.dewall(P) + +# plotting the known data points +for p in P: pyplot.scatter([p[0]],[p[1]]) + +# plotting the triangulation +for tri in triangul: + for seg in segments(tri): + pyplot.plot(seg[0],seg[1]) + +# plotting the circumcircles +for tri in triangul: + plot_circle(dw.circumcircle(tri)) + +pyplot.show() + +print triangul \ No newline at end of file Added: branches/interpolate/interpSNd/setup.py =================================================================== --- branches/interpolate/interpSNd/setup.py 2008-08-19 19:07:08 UTC (rev 4653) +++ branches/interpolate/interpSNd/setup.py 2008-08-19 19:12:18 UTC (rev 4654) @@ -0,0 +1,19 @@ +"""setup""" + +import os, sys, setuptools + +def configuration(parent_package='', top_path=None): + from numpy.distutils.misc_util import Configuration + config = Configuration('', parent_package, top_path) + config.add_extension('_triang', + sources = ['_triang.cpp'], + depends = [], + ) + + return config + +if __name__ == '__main__': + from numpy.distutils.core import setup + setup( + **configuration().todict() + ) Added: branches/interpolate/interpSNd/test.py =================================================================== --- branches/interpolate/interpSNd/test.py 2008-08-19 19:07:08 UTC (rev 4653) +++ branches/interpolate/interpSNd/test.py 2008-08-19 19:12:18 UTC (rev 4654) @@ -0,0 +1,53 @@ +# P for pathological +import unittest +import numpy as np +from numpy import array +import dewall as dw +import interpolateSNd as SNd +reload(dw) + +class Test(unittest.TestCase): + + def compare_array(self, a, b): + return np.allclose(a,b) + + ## test Delaunay triangulation itself + + # testing pathological cases with + + def test_square(self): + P = [array([0.,1.]), array([0.,0.]), array([1.,0.]), array([1.,1.])] + tri = dw.dewall(P) + self.assert_( len(tri)==2 ) + self.assert_( len(tri[0])==3 ) + self.assert_( len(tri[1])==3 ) + print "square triangulation:\n", tri + + def test_linear(self): + P = [array([0.,1.]), array([0.,0.]), array([0.,-1.])] + tri = dw.dewall(P) + print "line triang:\n", tri + + # testing general case using random data + + ## test interpolation, and thus also triangulation by extension + def test_linear_on_cube(self): + x = array([0., 1, 0, 1, 0, 1, 0, 1]) + y = array([0., 0, 1, 1, 0, 0, 1, 1]) + z = array([0., 0, 0, 0, 1, 1, 1, 1]) + points = array([x,y,z]).reshape((3,8)) + fvals = x+y-z + + interp = SNd.InterpolateSNd(points, fvals) + + newdata = np.random.random_sample((3,20)) + interpvals = interp(newdata) + + realvals = newdata[0,:]+newdata[1,:]-newdata[2,:] + + self.assert_(compare_array(np.ravel(interpvals), np.ravel(realvals))) + + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file From scipy-svn at scipy.org Tue Aug 19 18:26:18 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 19 Aug 2008 17:26:18 -0500 (CDT) Subject: [Scipy-svn] r4655 - branches/fast_vectorize/mkufunc Message-ID: <20080819222618.CD66839C100@scipy.org> Author: ilan Date: 2008-08-19 17:26:16 -0500 (Tue, 19 Aug 2008) New Revision: 4655 Removed: branches/fast_vectorize/mkufunc/driver.py branches/fast_vectorize/mkufunc/interactive.py Modified: branches/fast_vectorize/mkufunc/fast_vectorize.py branches/fast_vectorize/mkufunc/func_hash.py Log: Did some cleanup, got rid of driver.py and interactive.py. Deleted: branches/fast_vectorize/mkufunc/driver.py =================================================================== --- branches/fast_vectorize/mkufunc/driver.py 2008-08-19 19:12:18 UTC (rev 4654) +++ branches/fast_vectorize/mkufunc/driver.py 2008-08-19 22:26:16 UTC (rev 4655) @@ -1,732 +0,0 @@ -""" -This file is essentially the file pypy-dist/pypy/translator/driver.py -with some modifications to get the c_source_filename. -""" -import sys, os - -from pypy.translator.translator import TranslationContext, graphof -from pypy.translator.tool.taskengine import SimpleTaskEngine -from pypy.translator.goal import query -from pypy.translator.goal.timing import Timer -from pypy.annotation import model as annmodel -from pypy.annotation.listdef import s_list_of_strings -from pypy.annotation import policy as annpolicy -from py.compat import optparse -from pypy.tool.udir import udir - -import py -from pypy.tool.ansi_print import ansi_log -log = py.log.Producer("translation") -py.log.setconsumer("translation", ansi_log) - -DEFAULTS = { - 'translation.gc': 'ref', - 'translation.cc': None, - 'translation.profopt': None, - - 'translation.thread': False, # influences GC policy - - 'translation.stackless': False, - 'translation.debug': True, - 'translation.insist': False, - 'translation.backend': 'c', - 'translation.fork_before': None, - 'translation.backendopt.raisingop2direct_call' : False, - 'translation.backendopt.merge_if_blocks': True, -} - - -def taskdef(taskfunc, deps, title, new_state=None, expected_states=[], - idemp=False, earlycheck=None): - taskfunc.task_deps = deps - taskfunc.task_title = title - taskfunc.task_newstate = None - taskfunc.task_expected_states = expected_states - taskfunc.task_idempotent = idemp - taskfunc.task_earlycheck = earlycheck - return taskfunc - -# TODO: -# sanity-checks using states - -_BACKEND_TO_TYPESYSTEM = { - 'c': 'lltype', - 'llvm': 'lltype' -} - -def backend_to_typesystem(backend): - return _BACKEND_TO_TYPESYSTEM.get(backend, 'ootype') - -# set of translation steps to profile -PROFILE = set([]) - -class Instrument(Exception): - pass - - -class ProfInstrument(object): - name = "profinstrument" - def __init__(self, datafile, compiler): - self.datafile = datafile - self.compiler = compiler - - def first(self): - self.compiler._build() - - def probe(self, exe, args): - from py.compat import subprocess - env = os.environ.copy() - env['_INSTRUMENT_COUNTERS'] = str(self.datafile) - subprocess.call("'%s' %s" % (exe, args), env=env, shell=True) - - def after(self): - # xxx - os._exit(0) - - -class TranslationDriver(SimpleTaskEngine): - - def __init__(self, setopts=None, default_goal=None, - disable=[], - exe_name=None, extmod_name=None, - config=None, overrides=None): - self.timer = Timer() - SimpleTaskEngine.__init__(self) - - self.log = log - - if config is None: - from pypy.config.pypyoption import get_pypy_config - config = get_pypy_config(DEFAULTS, translating=True) - self.config = config - if overrides is not None: - self.config.override(overrides) - - if setopts is not None: - self.config.set(**setopts) - - self.exe_name = exe_name - self.extmod_name = extmod_name - - self.done = {} - - self.disable(disable) - - if default_goal: - default_goal, = self.backend_select_goals([default_goal]) - if default_goal in self._maybe_skip(): - default_goal = None - - self.default_goal = default_goal - self.extra_goals = [] - self.exposed = [] - - # expose tasks - def expose_task(task, backend_goal=None): - if backend_goal is None: - backend_goal = task - def proc(): - return self.proceed(backend_goal) - self.exposed.append(task) - setattr(self, task, proc) - - backend, ts = self.get_backend_and_type_system() - for task in self.tasks: - explicit_task = task - parts = task.split('_') - if len(parts) == 1: - if task in ('annotate',): - expose_task(task) - else: - task, postfix = parts - if task in ('rtype', 'backendopt', 'llinterpret', - 'prehannotatebackendopt', 'hintannotate', - 'timeshift'): - if ts: - if ts == postfix: - expose_task(task, explicit_task) - else: - expose_task(explicit_task) - elif task in ('source', 'compile', 'run'): - if backend: - if backend == postfix: - expose_task(task, explicit_task) - elif ts: - if ts == backend_to_typesystem(postfix): - expose_task(explicit_task) - else: - expose_task(explicit_task) - - def set_extra_goals(self, goals): - self.extra_goals = goals - - def get_info(self): # XXX more? - d = {'backend': self.config.translation.backend} - return d - - def get_backend_and_type_system(self): - type_system = self.config.translation.type_system - backend = self.config.translation.backend - return backend, type_system - - def backend_select_goals(self, goals): - backend, ts = self.get_backend_and_type_system() - postfixes = [''] + ['_'+p for p in (backend, ts) if p] - l = [] - for goal in goals: - for postfix in postfixes: - cand = "%s%s" % (goal, postfix) - if cand in self.tasks: - new_goal = cand - break - else: - raise Exception, "cannot infer complete goal from: %r" % goal - l.append(new_goal) - return l - - def disable(self, to_disable): - self._disabled = to_disable - - def _maybe_skip(self): - maybe_skip = [] - if self._disabled: - for goal in self.backend_select_goals(self._disabled): - maybe_skip.extend(self._depending_on_closure(goal)) - return dict.fromkeys(maybe_skip).keys() - - - def setup(self, entry_point, inputtypes, policy=None, extra={}, empty_translator=None): - standalone = inputtypes is None - self.standalone = standalone - - if standalone: - inputtypes = [s_list_of_strings] - self.inputtypes = inputtypes - - if policy is None: - policy = annpolicy.AnnotatorPolicy() - if standalone: - policy.allow_someobjects = False - self.policy = policy - - self.extra = extra - - if empty_translator: - translator = empty_translator - else: - translator = TranslationContext(config=self.config) - - self.entry_point = entry_point - self.translator = translator - self.libdef = None - - self.translator.driver_instrument_result = self.instrument_result - - def setup_library(self, libdef, policy=None, extra={}, empty_translator=None): - self.setup(None, None, policy, extra, empty_translator) - self.libdef = libdef - - def instrument_result(self, args): - backend, ts = self.get_backend_and_type_system() - if backend != 'c' or sys.platform == 'win32': - raise Exception("instrumentation requires the c backend" - " and unix for now") - from pypy.tool.udir import udir - - datafile = udir.join('_instrument_counters') - makeProfInstrument = lambda compiler: ProfInstrument(datafile, compiler) - - pid = os.fork() - if pid == 0: - # child compiling and running with instrumentation - self.config.translation.instrument = True - self.config.translation.instrumentctl = (makeProfInstrument, - args) - raise Instrument - else: - pid, status = os.waitpid(pid, 0) - if os.WIFEXITED(status): - status = os.WEXITSTATUS(status) - if status != 0: - raise Exception, "instrumentation child failed: %d" % status - else: - raise Exception, "instrumentation child aborted" - import array, struct - n = datafile.size()//struct.calcsize('L') - datafile = datafile.open('rb') - counters = array.array('L') - counters.fromfile(datafile, n) - datafile.close() - return counters - - def info(self, msg): - log.info(msg) - - def _profile(self, goal, func): - from cProfile import Profile - from pypy.tool.lsprofcalltree import KCacheGrind - d = {'func':func} - prof = Profile() - prof.runctx("res = func()", globals(), d) - KCacheGrind(prof).output(open(goal + ".out", "w")) - return d['res'] - - def _do(self, goal, func, *args, **kwds): - title = func.task_title - if goal in self.done: - self.log.info("already done: %s" % title) - return - else: - self.log.info("%s..." % title) - self.timer.start_event(goal) - try: - instrument = False - try: - if goal in PROFILE: - res = self._profile(goal, func) - else: - res = func() - except Instrument: - instrument = True - if not func.task_idempotent: - self.done[goal] = True - if instrument: - self.proceed('compile') - assert False, 'we should not get here' - finally: - self.timer.end_event(goal) - return res - - def task_annotate(self): - # includes annotation and annotatation simplifications - translator = self.translator - policy = self.policy - self.log.info('with policy: %s.%s' % - (policy.__class__.__module__, policy.__class__.__name__)) - - annmodel.DEBUG = self.config.translation.debug - annotator = translator.buildannotator(policy=policy) - - if self.entry_point: - s = annotator.build_types(self.entry_point, self.inputtypes) - - self.sanity_check_annotation() - if self.standalone and s.knowntype != int: - raise Exception("stand-alone program entry point must return an " - "int (and not, e.g., None or always raise an " - "exception).") - annotator.simplify() - return s - else: - assert self.libdef is not None - for func, inputtypes in self.libdef.functions: - annotator.build_types(func, inputtypes) - self.sanity_check_annotation() - annotator.simplify() - # - task_annotate = taskdef(task_annotate, [], "Annotating&simplifying") - - - def sanity_check_annotation(self): - translator = self.translator - irreg = query.qoutput(query.check_exceptblocks_qgen(translator)) - if irreg: - self.log.info("Some exceptblocks seem insane") - - lost = query.qoutput(query.check_methods_qgen(translator)) - assert not lost, "lost methods, something gone wrong with the annotation of method defs" - - so = query.qoutput(query.polluted_qgen(translator)) - tot = len(translator.graphs) - percent = int(tot and (100.0*so / tot) or 0) - # if there are a few SomeObjects even if the policy doesn't allow - # them, it means that they were put there in a controlled way - # and then it's not a warning. - if not translator.annotator.policy.allow_someobjects: - pr = self.log.info - elif percent == 0: - pr = self.log.info - else: - pr = log.WARNING - pr("-- someobjectness %2d%% (%d of %d functions polluted by SomeObjects)" % (percent, so, tot)) - - - - def task_rtype_lltype(self): - rtyper = self.translator.buildrtyper(type_system='lltype') - insist = not self.config.translation.insist - rtyper.specialize(dont_simplify_again=True, - crash_on_first_typeerror=insist) - # - task_rtype_lltype = taskdef(task_rtype_lltype, ['annotate'], "RTyping") - RTYPE = 'rtype_lltype' - - def task_rtype_ootype(self): - # Maybe type_system should simply be an option used in task_rtype - insist = not self.config.translation.insist - rtyper = self.translator.buildrtyper(type_system="ootype") - rtyper.specialize(dont_simplify_again=True, - crash_on_first_typeerror=insist) - # - task_rtype_ootype = taskdef(task_rtype_ootype, ['annotate'], "ootyping") - OOTYPE = 'rtype_ootype' - - def task_prehannotatebackendopt_lltype(self): - from pypy.translator.backendopt.all import backend_optimizations - backend_optimizations(self.translator, - inline_threshold=0, - merge_if_blocks=True, - constfold=True, - raisingop2direct_call=False, - remove_asserts=True) - # - task_prehannotatebackendopt_lltype = taskdef( - task_prehannotatebackendopt_lltype, - [RTYPE], - "Backendopt before Hint-annotate") - - def task_hintannotate_lltype(self): - from pypy.jit.hintannotator.annotator import HintAnnotator - from pypy.jit.hintannotator.model import OriginFlags - from pypy.jit.hintannotator.model import SomeLLAbstractConstant - - get_portal = self.extra['portal'] - PORTAL, POLICY = get_portal(self) - t = self.translator - self.portal_graph = graphof(t, PORTAL) - - hannotator = HintAnnotator(base_translator=t, policy=POLICY) - self.hint_translator = hannotator.translator - hs = hannotator.build_types(self.portal_graph, - [SomeLLAbstractConstant(v.concretetype, - {OriginFlags(): True}) - for v in self.portal_graph.getargs()]) - count = hannotator.bookkeeper.nonstuboriggraphcount - stubcount = hannotator.bookkeeper.stuboriggraphcount - self.log.info("The hint-annotator saw %d graphs" - " (and made stubs for %d graphs)." % (count, stubcount)) - n = len(list(hannotator.translator.graphs[0].iterblocks())) - self.log.info("portal has %d blocks" % n) - self.hannotator = hannotator - # - task_hintannotate_lltype = taskdef(task_hintannotate_lltype, - ['prehannotatebackendopt_lltype'], - "Hint-annotate") - - def task_timeshift_lltype(self): - from pypy.jit.timeshifter.hrtyper import HintRTyper - from pypy.jit.codegen import detect_cpu - cpu = detect_cpu.autodetect() - if cpu == 'i386': - from pypy.jit.codegen.i386.rgenop import RI386GenOp as RGenOp - RGenOp.MC_SIZE = 32 * 1024 * 1024 - elif cpu == 'ppc': - from pypy.jit.codegen.ppc.rgenop import RPPCGenOp as RGenOp - RGenOp.MC_SIZE = 32 * 1024 * 1024 - else: - raise Exception('Unsuported cpu %r'%cpu) - - del self.hint_translator - ha = self.hannotator - t = self.translator - # make the timeshifted graphs - hrtyper = HintRTyper(ha, t.rtyper, RGenOp) - hrtyper.specialize(origportalgraph=self.portal_graph, view=False) - # - task_timeshift_lltype = taskdef(task_timeshift_lltype, - ["hintannotate_lltype"], - "Timeshift") - - def task_backendopt_lltype(self): - from pypy.translator.backendopt.all import backend_optimizations - backend_optimizations(self.translator) - # - task_backendopt_lltype = taskdef(task_backendopt_lltype, - [RTYPE, - '??timeshift_lltype'], - "lltype back-end optimisations") - BACKENDOPT = 'backendopt_lltype' - - def task_backendopt_ootype(self): - from pypy.translator.backendopt.all import backend_optimizations - backend_optimizations(self.translator) - # - task_backendopt_ootype = taskdef(task_backendopt_ootype, - [OOTYPE], "ootype back-end optimisations") - OOBACKENDOPT = 'backendopt_ootype' - - - def task_stackcheckinsertion_lltype(self): - from pypy.translator.transform import insert_ll_stackcheck - count = insert_ll_stackcheck(self.translator) - self.log.info("inserted %d stack checks." % (count,)) - - task_stackcheckinsertion_lltype = taskdef( - task_stackcheckinsertion_lltype, - ['?'+BACKENDOPT, RTYPE, 'annotate'], - "inserting stack checks") - STACKCHECKINSERTION = 'stackcheckinsertion_lltype' - - def possibly_check_for_boehm(self): - if self.config.translation.gc == "boehm": - from pypy.translator.tool.cbuild import check_boehm_presence - from pypy.translator.tool.cbuild import CompilationError - try: - check_boehm_presence(noerr=False) - except CompilationError, e: - i = 'Boehm GC not installed. Try e.g. "translate.py --gc=hybrid"' - raise CompilationError('%s\n--------------------\n%s' % (e, i)) - - def task_database_c(self): - translator = self.translator - if translator.annotator is not None: - translator.frozen = True - - standalone = self.standalone - - if standalone: - from pypy.translator.c.genc import CStandaloneBuilder as CBuilder - else: - from pypy.translator.c.genc import CExtModuleBuilder as CBuilder - cbuilder = CBuilder(self.translator, self.entry_point, - config=self.config) - cbuilder.stackless = self.config.translation.stackless - if not standalone: # xxx more messy - cbuilder.modulename = self.extmod_name - database = cbuilder.build_database() - self.log.info("database for generating C source was created") - self.cbuilder = cbuilder - self.database = database - # - task_database_c = taskdef(task_database_c, - [STACKCHECKINSERTION, '?'+BACKENDOPT, RTYPE, '?annotate'], - "Creating database for generating c source", - earlycheck = possibly_check_for_boehm) - - def task_source_c(self): # xxx messy - translator = self.translator - cbuilder = self.cbuilder - database = self.database - c_source_filename = cbuilder.generate_source(database) - self.log.info("written: %s" % (c_source_filename,)) - self.c_source_filename = str(c_source_filename) - # - task_source_c = taskdef(task_source_c, ['database_c'], "Generating c source") - - def task_compile_c(self): # xxx messy - cbuilder = self.cbuilder - cbuilder.compile() - - if self.standalone: - self.c_entryp = cbuilder.executable_name - self.create_exe() - else: - self.c_entryp = cbuilder.get_entry_point() - # - task_compile_c = taskdef(task_compile_c, ['source_c'], "Compiling c source") - - - def task_run_c(self): - self.backend_run('c') - # - task_run_c = taskdef(task_run_c, ['compile_c'], - "Running compiled c source", - idemp=True) - - def task_llinterpret_lltype(self): - from pypy.rpython.llinterp import LLInterpreter - py.log.setconsumer("llinterp operation", None) - - translator = self.translator - interp = LLInterpreter(translator.rtyper) - bk = translator.annotator.bookkeeper - graph = bk.getdesc(self.entry_point).getuniquegraph() - v = interp.eval_graph(graph, - self.extra.get('get_llinterp_args', - lambda: [])()) - - log.llinterpret.event("result -> %s" % v) - # - task_llinterpret_lltype = taskdef(task_llinterpret_lltype, - [STACKCHECKINSERTION, '?'+BACKENDOPT, RTYPE], - "LLInterpreting") - - def task_source_llvm(self): - translator = self.translator - if translator.annotator is None: - raise ValueError, "llvm requires annotation." - - from pypy.translator.llvm import genllvm - - self.llvmgen = genllvm.GenLLVM(translator, self.standalone) - - llvm_filename = self.llvmgen.gen_source(self.entry_point) - self.log.info("written: %s" % (llvm_filename,)) - # - task_source_llvm = taskdef(task_source_llvm, - [STACKCHECKINSERTION, BACKENDOPT, RTYPE], - "Generating llvm source") - - def task_compile_llvm(self): - gen = self.llvmgen - if self.standalone: - exe_name = (self.exe_name or 'testing') % self.get_info() - self.c_entryp = gen.compile_standalone(exe_name) - self.create_exe() - else: - self.c_module, self.c_entryp = gen.compile_module() - # - task_compile_llvm = taskdef(task_compile_llvm, - ['source_llvm'], - "Compiling llvm source") - - def task_run_llvm(self): - self.backend_run('llvm') - # - task_run_llvm = taskdef(task_run_llvm, ['compile_llvm'], - "Running compiled llvm source", - idemp=True) - - def task_source_js(self): - from pypy.translator.js.js import JS - self.gen = JS(self.translator, functions=[self.entry_point], - stackless=self.config.translation.stackless) - filename = self.gen.write_source() - self.log.info("Wrote %s" % (filename,)) - task_source_js = taskdef(task_source_js, - [OOTYPE], - 'Generating Javascript source') - - def task_compile_js(self): - pass - task_compile_js = taskdef(task_compile_js, ['source_js'], - 'Skipping Javascript compilation') - - def task_run_js(self): - pass - task_run_js = taskdef(task_run_js, ['compile_js'], - 'Please manually run the generated code') - - def task_source_cli(self): - from pypy.translator.cli.gencli import GenCli - from pypy.translator.cli.entrypoint import get_entrypoint - - if self.entry_point is not None: # executable mode - entry_point_graph = self.translator.graphs[0] - entry_point = get_entrypoint(entry_point_graph) - else: - # library mode - assert self.libdef is not None - bk = self.translator.annotator.bookkeeper - entry_point = self.libdef.get_entrypoint(bk) - - self.gen = GenCli(udir, self.translator, entry_point, config=self.config) - filename = self.gen.generate_source() - self.log.info("Wrote %s" % (filename,)) - task_source_cli = taskdef(task_source_cli, ["?" + OOBACKENDOPT, OOTYPE], - 'Generating CLI source') - - def task_compile_cli(self): - from pypy.translator.oosupport.support import unpatch_os - from pypy.translator.cli.test.runtest import CliFunctionWrapper - filename = self.gen.build_exe() - self.c_entryp = CliFunctionWrapper(filename) - # restore original os values - if hasattr(self, 'old_cli_defs'): - unpatch_os(self.old_cli_defs) - - self.log.info("Compiled %s" % filename) - if self.standalone and self.exe_name: - self.copy_cli_exe() - task_compile_cli = taskdef(task_compile_cli, ['source_cli'], - 'Compiling CLI source') - - def task_run_cli(self): - pass - task_run_cli = taskdef(task_run_cli, ['compile_cli'], - 'XXX') - - def task_source_jvm(self): - from pypy.translator.jvm.genjvm import GenJvm - from pypy.translator.jvm.node import EntryPoint - - entry_point_graph = self.translator.graphs[0] - is_func = not self.standalone - entry_point = EntryPoint(entry_point_graph, is_func, is_func) - self.gen = GenJvm(udir, self.translator, entry_point) - self.jvmsource = self.gen.generate_source() - self.log.info("Wrote JVM code") - task_source_jvm = taskdef(task_source_jvm, ["?" + OOBACKENDOPT, OOTYPE], - 'Generating JVM source') - - def task_compile_jvm(self): - from pypy.translator.oosupport.support import unpatch_os - from pypy.translator.jvm.test.runtest import JvmGeneratedSourceWrapper - self.jvmsource.compile() - self.c_entryp = JvmGeneratedSourceWrapper(self.jvmsource) - # restore original os values - if hasattr(self, 'old_cli_defs'): - unpatch_os(self.old_cli_defs) - self.log.info("Compiled JVM source") - if self.standalone and self.exe_name: - self.copy_jvm_jar() - task_compile_jvm = taskdef(task_compile_jvm, ['source_jvm'], - 'Compiling JVM source') - - def task_run_jvm(self): - pass - task_run_jvm = taskdef(task_run_jvm, ['compile_jvm'], - 'XXX') - - def proceed(self, goals): - if not goals: - if self.default_goal: - goals = [self.default_goal] - else: - self.log.info("nothing to do") - return - elif isinstance(goals, str): - goals = [goals] - goals.extend(self.extra_goals) - goals = self.backend_select_goals(goals) - return self._execute(goals, task_skip = self._maybe_skip()) - - def from_targetspec(targetspec_dic, config=None, args=None, - empty_translator=None, - disable=[], - default_goal=None): - if args is None: - args = [] - - driver = TranslationDriver(config=config, default_goal=default_goal, - disable=disable) - # patch some attributes of the os module to make sure they - # have the same value on every platform. - backend, ts = driver.get_backend_and_type_system() - if backend in ('cli', 'jvm'): - from pypy.translator.oosupport.support import patch_os - driver.old_cli_defs = patch_os() - - target = targetspec_dic['target'] - spec = target(driver, args) - - try: - entry_point, inputtypes, policy = spec - except ValueError: - entry_point, inputtypes = spec - policy = None - - driver.setup(entry_point, inputtypes, - policy=policy, - extra=targetspec_dic, - empty_translator=empty_translator) - - return driver - - from_targetspec = staticmethod(from_targetspec) - - def prereq_checkpt_rtype(self): - assert 'pypy.rpython.rmodel' not in sys.modules, ( - "cannot fork because the rtyper has already been imported") - prereq_checkpt_rtype_lltype = prereq_checkpt_rtype - prereq_checkpt_rtype_ootype = prereq_checkpt_rtype Modified: branches/fast_vectorize/mkufunc/fast_vectorize.py =================================================================== --- branches/fast_vectorize/mkufunc/fast_vectorize.py 2008-08-19 19:12:18 UTC (rev 4654) +++ branches/fast_vectorize/mkufunc/fast_vectorize.py 2008-08-19 22:26:16 UTC (rev 4655) @@ -1,4 +1,4 @@ -"""fast_vectorize: creates a U function from python source code +"""fast_vectorize: creates U functions from python source code Author: Ilan Schnell Thanks: Travis Oliphant and Eric Jones @@ -7,7 +7,6 @@ import re import os import cStringIO -import md5 from types import FunctionType import numpy @@ -21,45 +20,56 @@ _showc = 0 _force = 0 -def c_source_filename(f, argtypes): +def get_C_source_filename(f, argtypes): + """ + Return the filename of pypy's C output for a given function + and argument types. + """ try: import pypy except ImportError: raise ImportError(""" -################################################################ -weave.fast_vectorize requires pypy to be installed. +############################################################ +scipy.weave.fast_vectorize requires pypy, see + http://codespeak.net/pypy/dist/pypy/doc/home.html +to be installed. -You can download... -################################################################ +Use SVN to download the pypy source: +svn co http://codespeak.net/svn/pypy/dist pypy-dist + +Make sure pypy can be imported, e.g. set your PYTHONPATH: +export PYTHONPATH= + +############################################################ """) + from pypy.translator.interactive import Translation - from interactive import Translation - t = Translation(f, backend='c') t.annotate(argtypes) t.source() - return t.driver.c_source_filename + + return str(t.driver.cbuilder.c_source_filename) -def translate(f, argtypes): - """ Return pypy's C output for a given function and argument types. - The cache files are in weave's directory. +def translate_cached(f, argtypes): """ + Return pypy's C output for a given function and argument types + as a string. This function caches the pypy's C output file in + weave's cache directory. + """ if _force: - filename = c_source_filename(f, argtypes) - return open(filename).read() + return open(get_C_source_filename(f, argtypes)).read() cache_file_name = os.path.join(weave.catalog.default_dir(), 'pypy_%s.c' % func_hash(f, salt=argtypes)) - try: + + if os.access(cache_file_name, os.R_OK): return open(cache_file_name).read() - except IOError: - os.rename(c_source_filename(f, argtypes), cache_file_name) + os.rename(get_C_source_filename(f, argtypes), cache_file_name) + return translate_cached(f, argtypes) - return translate(f, argtypes) - class Ctype: def __init__(self, npy, c): self.npy = npy @@ -72,7 +82,8 @@ class Cfunc(object): - """ C compiled python functions + """ + C compiled python functions >>> def sqr(x): ... return x * x @@ -112,7 +123,7 @@ self.nout = len(self.sig) - self.nin assert self.nout == 1 # for now - src = translate(f, signature[:self.nin]) + src = translate_cached(f, signature[:self.nin]) self._prefix = 'f%i_' % self.n self._allCsrc = src.replace('pypy_', self._prefix + 'pypy_') @@ -209,8 +220,9 @@ def support_code(cfuncs): - """ Given a list of Cfunc instances, return the support code for weave. """ + Given a list of Cfunc instances, return the support code for weave. + """ acc = cStringIO.StringIO() acc.write('/********************* start pypy.h **************/\n\n') @@ -252,8 +264,9 @@ def code(f, signatures): - """ Return the code for weave. """ + Return C code which is input for weave. + """ nin = f.func_code.co_argcount ntypes = len(signatures) fname = f.__name__ @@ -290,8 +303,9 @@ def genufunc(f, signatures): - """ Return the Ufunc Python object for given function and signatures. """ + Return the Ufunc Python object for given function and signatures. + """ if len(signatures) == 0: raise ValueError("At least one signature needed") @@ -311,8 +325,9 @@ def fast_vectorize(arg0=[float], showc=0, force=0, verbose=0): - """ Python decorator which returns compiled UFunc of the function given. - + """ + Python decorator which returns compiled UFunc of the function given. + >>> from numpy import arange >>> @fast_vectorize ... def foo(x): Modified: branches/fast_vectorize/mkufunc/func_hash.py =================================================================== --- branches/fast_vectorize/mkufunc/func_hash.py 2008-08-19 19:12:18 UTC (rev 4654) +++ branches/fast_vectorize/mkufunc/func_hash.py 2008-08-19 22:26:16 UTC (rev 4655) @@ -1,18 +1,7 @@ -""" - -Author: Ilan Schnell -""" import md5 -import re from types import CodeType, FunctionType -def md5sum(s): - return md5.md5(s).hexdigest() - -pat_hex = re.compile(r'0x[0-9a-f]{4,}', re.I) - - def func_hash(f, salt=None): """ Return a MD5 hash for a function or code object as string. """ @@ -37,4 +26,4 @@ else: res.append(repr(getattr(co, name))) - return md5sum(''.join(res) + repr(salt)) + return md5.md5(''.join(res) + repr(salt)).hexdigest() Deleted: branches/fast_vectorize/mkufunc/interactive.py =================================================================== --- branches/fast_vectorize/mkufunc/interactive.py 2008-08-19 19:12:18 UTC (rev 4654) +++ branches/fast_vectorize/mkufunc/interactive.py 2008-08-19 22:26:16 UTC (rev 4655) @@ -1,120 +0,0 @@ -""" -This file is essentially the file pypy-dist/pypy/translator/interactive.py -with some modifications to get the c_source_filename. -""" - -import driver - -from pypy.translator.translator import TranslationContext - - -DEFAULTS = { - 'translation.backend': None, - 'translation.type_system': None, - 'translation.verbose': False, -} - -class Translation(object): - - def __init__(self, entry_point, argtypes=None, **kwds): - self.driver = driver.TranslationDriver(overrides=DEFAULTS) - self.config = self.driver.config - - self.entry_point = entry_point - self.context = TranslationContext(config=self.config) - - # hook into driver events - driver_own_event = self.driver._event - def _event(kind, goal, func): - self.driver_event(kind, goal, func) - driver_own_event(kind, goal, func) - self.driver._event = _event - self.driver_setup = False - - self.update_options(argtypes, kwds) - # for t.view() to work just after construction - graph = self.context.buildflowgraph(entry_point) - self.context._prebuilt_graphs[entry_point] = graph - - def driver_event(self, kind, goal, func): - if kind == 'pre': - self.ensure_setup() - - def ensure_setup(self, argtypes=None, policy=None, standalone=False): - if not self.driver_setup: - if standalone: - assert argtypes is None - else: - if argtypes is None: - argtypes = [] - self.driver.setup(self.entry_point, argtypes, policy, - empty_translator=self.context) - self.ann_argtypes = argtypes - self.ann_policy = policy - self.driver_setup = True - else: - # check consistency - if standalone: - assert argtypes is None - assert self.ann_argtypes is None - elif argtypes is not None and argtypes != self.ann_argtypes: - raise Exception("inconsistent argtype supplied") - if policy is not None and policy != self.ann_policy: - raise Exception("inconsistent annotation polish supplied") - - def update_options(self, argtypes, kwds): - if argtypes or kwds.get('policy') or kwds.get('standalone'): - self.ensure_setup(argtypes, kwds.get('policy'), - kwds.get('standalone')) - kwds.pop('policy', None) - kwds.pop('standalone', None) - self.config.translation.set(**kwds) - - def ensure_opt(self, name, value=None, fallback=None): - if value is not None: - self.update_options(None, {name: value}) - return value - val = getattr(self.config.translation, name, None) - if fallback is not None and val is None: - self.update_options(None, {name: fallback}) - return fallback - if val is not None: - return val - raise Exception( - "the %r option should have been specified at this point" %name) - - def ensure_type_system(self, type_system=None): - if self.config.translation.backend is not None: - return self.ensure_opt('type_system') - return self.ensure_opt('type_system', type_system, 'lltype') - - def ensure_backend(self, backend=None): - backend = self.ensure_opt('backend', backend) - self.ensure_type_system() - return backend - - # backend independent - - def annotate(self, argtypes=None, **kwds): - self.update_options(argtypes, kwds) - return self.driver.annotate() - - # type system dependent - - def rtype(self, argtypes=None, **kwds): - self.update_options(argtypes, kwds) - ts = self.ensure_type_system() - return getattr(self.driver, 'rtype_'+ts)() - - # backend depedent - - def source(self, argtypes=None, **kwds): - self.update_options(argtypes, kwds) - backend = self.ensure_backend() - self.driver.source_c() - - def compile(self, argtypes=None, **kwds): - self.update_options(argtypes, kwds) - backend = self.ensure_backend() - self.driver.compile_c() - return self.driver.c_entryp From scipy-svn at scipy.org Tue Aug 19 19:39:20 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 19 Aug 2008 18:39:20 -0500 (CDT) Subject: [Scipy-svn] r4656 - branches/interpolate/interpSNd Message-ID: <20080819233920.0A11B39C100@scipy.org> Author: fcady Date: 2008-08-19 18:39:17 -0500 (Tue, 19 Aug 2008) New Revision: 4656 Removed: branches/interpolate/interpSNd/interpolateSNd.pyc branches/interpolate/interpSNd/output.txt Modified: branches/interpolate/interpSNd/dewall.py branches/interpolate/interpSNd/dewall.pyc branches/interpolate/interpSNd/interp.py branches/interpolate/interpSNd/interpolateSNd.py branches/interpolate/interpSNd/test.py Log: fixed a bug in 3D and higher Modified: branches/interpolate/interpSNd/dewall.py =================================================================== --- branches/interpolate/interpSNd/dewall.py 2008-08-19 22:26:16 UTC (rev 4655) +++ branches/interpolate/interpSNd/dewall.py 2008-08-19 23:39:17 UTC (rev 4656) @@ -23,14 +23,13 @@ def dewall (P, #set of points AFL = [], # list of faces: (d-1)face list ): - + # checking input assert isinstance(P, list) if len(P)>0: assert isinstance(P[0], np.ndarray) assert isinstance(AFL, list) if len(AFL)>0: - #print "AFL[0]: ", AFL[0] assert isinstance(AFL[0],tuple) assert isinstance(AFL[0][0], list) assert isinstance(AFL[0][0][0], np.ndarray) @@ -53,10 +52,10 @@ # divide points into two sets separated by alpha P1, P2 = pointset_partition(P, alpha) # both lists of points - + # Simplex Wall Construction just_starting = False #source of problem? - if len(AFL) == 0: + if len(AFL) == 0: # This is only executed once, at the start of the algorithm just_starting = True first_simplex = make_first_simplex(P, alpha) AFL = [ (face, get_out_vec(face,first_simplex))\ @@ -79,9 +78,10 @@ outward_points = filter( lambda p: (np.dot(p,outvec)>np.dot(face[0],outvec)),\ P) else: - outward_points = filter( lambda p: np.all([not point_in_list(p,vertex) for vertex in face]), P) + outward_points = []#filter( lambda p: np.all([not point_in_list(p,vertex) for vertex in face]), P) t = make_simplex(face, outward_points) # make only over outer half space + if t is not None: Sigma.append(t) # for f0 != f in faces(t) , ie for new outward faces @@ -90,6 +90,7 @@ if is_intersected(f0, alpha): # continue building wall out in that direction AFL_alpha = update(new_pair, AFL_alpha) + #np.random.shuffle(AFL_alpha) if is_subset(f0, P1): AFL1 = update(new_pair, AFL1) if is_subset(f0, P2): @@ -109,16 +110,6 @@ # must intersect active face if there is one # must not intersect any points - #assert isinstance(P, list) - #if len(P)>0: - # assert isinstance(P[0], np.ndarray) - #assert isinstance(AFL, list) - #if len(AFL)>0: - # assert isinstance(AFL[0],list) - # assert isinstance(AFL[0][0], list) - # assert isinstance(AFL[0][0][0], np.ndarray) - # assert isinstance(AFL[0][1], np.ndarray) - d = len(P[0]) # plane through avg of cluster. Guarantees separation @@ -174,8 +165,8 @@ # returns face_list with face_pair added if it wasn't there, else deleted face, outvec = face_pair face_list = [face for face, outvec in face_pair_list] - if face_in_list(face, face_pair_list): - f_not_equal_face = lambda f : not np.alltrue([ point_in_list(p, f[0]) for p in face ]) + if face_in_list(face, face_list): + f_not_equal_face = lambda face_pair : not np.alltrue([ point_in_list(p, face_pair[0]) for p in face ]) face_pair_list = filter(f_not_equal_face, face_pair_list) else: face_pair_list.append(face_pair) Modified: branches/interpolate/interpSNd/dewall.pyc =================================================================== (Binary files differ) Modified: branches/interpolate/interpSNd/interp.py =================================================================== --- branches/interpolate/interpSNd/interp.py 2008-08-19 22:26:16 UTC (rev 4655) +++ branches/interpolate/interpSNd/interp.py 2008-08-19 23:39:17 UTC (rev 4656) @@ -1,18 +1,40 @@ import interpolateSNd as SN import numpy as np +import dewall as dw reload(SN) -points = np.array([[ 1.,0.,1.,0.],[0.,0.,1.,1.]]) -z = np.array([1.,0.,2.,1.]) -interp = SN.InterpolateSNd(points,z) +if False: + points = np.array([[ 1.,0.,1.,0.],[0.,0.,1.,1.]]) + z = np.array([1.,0.,2.,1.]) + interp = SN.InterpolateSNd(points,z) -print "triangulation:\n",interp._triangulation + print "triangulation:\n",interp._triangulation -X=np.array([[1.4,.1,.55],[.4,.1,.3]]) -print "X values:\n",X -# last component is .1 too much + X=np.array([[1.4,.1,.55],[.4,.1,.3]]) + print "X values:\n",X -output = interp(X) + output = interp(X) -print "output:\n", output \ No newline at end of file + print "output:\n", output + + +if True: + points = np.array([ [0., 0, 0, 1.,.2], + [0., 1., 0, 0, .2], + [0., 0, 1., 0, .2] ]) + z = np.array([.1,1.,1.,1.,.6]) + interp = SN.InterpolateSNd(points,z) + + X = np.array([ [.1,.2,.1,.1], + [.1,.1,.2,.1], + [.1,.1,.1,.2] ]) + + output = interp(X) + + print "output:\n",output + +if False: + P = [np.random.random_sample(3) for i in range(7)] + print "P:",P + tri = dw.dewall(P) \ No newline at end of file Modified: branches/interpolate/interpSNd/interpolateSNd.py =================================================================== --- branches/interpolate/interpSNd/interpolateSNd.py 2008-08-19 22:26:16 UTC (rev 4655) +++ branches/interpolate/interpSNd/interpolateSNd.py 2008-08-19 23:39:17 UTC (rev 4656) @@ -41,8 +41,8 @@ assert P.ndim == 2, "P must be 2-dimensional" d, n = P.shape - assert len(fvals)==n, "fvals must have length n,\ - where n is number of points" + assert len(fvals)==n, \ + "fvals must have length n, where n is number of points" # remember dimensionality of space self.ndim = d Deleted: branches/interpolate/interpSNd/interpolateSNd.pyc =================================================================== (Binary files differ) Deleted: branches/interpolate/interpSNd/output.txt =================================================================== --- branches/interpolate/interpSNd/output.txt 2008-08-19 22:26:16 UTC (rev 4655) +++ branches/interpolate/interpSNd/output.txt 2008-08-19 23:39:17 UTC (rev 4656) @@ -1,40 +0,0 @@ - -face: [array([ 0.78256165, 1.25794206]), array([ 5.5867473 , 0.30561524])] -points: [] - -face: [array([ 5.5867473 , 0.30561524]), array([ 0.84738355, 0.4417885 ])] -points: [array([ 0.49630621, 0.38945595])] -delaunay distances: -[(14.481574504701088, array([ 0.49630621, 0.38945595]))] - -face: [array([ 5.5867473 , 0.30561524]), array([ 0.49630621, 0.38945595])] -points: [] - -face: [array([ 0.78256165, 1.25794206]), array([ 0.84738355, 0.4417885 ])] -points: [array([ 0.45697308, 1.26267539]), array([ 0.49630621, 0.38945595]), array([ 0.15363154, 0.794239 ])] -delaunay distances: -[(0.45650505613020009, array([ 0.45697308, 1.26267539])), (0.45830428089834485, array([ 0.49630621, 0.38945595])), (0.45808830610514073, array([ 0.15363154, 0.794239 ]))] - -face: [array([ 0.84738355, 0.4417885 ]), array([ 0.45697308, 1.26267539])] -points: [array([ 0.49630621, 0.38945595]), array([ 0.15363154, 0.794239 ])] -delaunay distances: -[(0.45691821155399881, array([ 0.49630621, 0.38945595])), (0.45699647524242137, array([ 0.15363154, 0.794239 ]))] - -face: [array([ 0.45697308, 1.26267539]), array([ 0.49630621, 0.38945595])] -points: [array([ 0.15363154, 0.794239 ])] -delaunay distances: -[(-0.45659643493482976, array([ 0.15363154, 0.794239 ]))] - -face: [array([ 0.45697308, 1.26267539]), array([ 0.15363154, 0.794239 ])] -points: [] - -face: [array([ 0.84738355, 0.4417885 ]), array([ 0.49630621, 0.38945595])] -points: [] - -face: [array([ 0.84738355, 0.4417885 ]), array([ 0.49630621, 0.38945595])] -points: [array([ 0.15363154, 0.794239 ])] -delaunay distances: -[(0.45765190740816952, array([ 0.15363154, 0.794239 ]))] - -face: [array([ 0.84738355, 0.4417885 ]), array([ 0.15363154, 0.794239 ])] -points: [] Modified: branches/interpolate/interpSNd/test.py =================================================================== --- branches/interpolate/interpSNd/test.py 2008-08-19 22:26:16 UTC (rev 4655) +++ branches/interpolate/interpSNd/test.py 2008-08-19 23:39:17 UTC (rev 4656) @@ -8,7 +8,7 @@ class Test(unittest.TestCase): - def compare_array(self, a, b): + def compare_arrays(self, a, b): return np.allclose(a,b) ## test Delaunay triangulation itself @@ -21,16 +21,48 @@ self.assert_( len(tri)==2 ) self.assert_( len(tri[0])==3 ) self.assert_( len(tri[1])==3 ) - print "square triangulation:\n", tri def test_linear(self): P = [array([0.,1.]), array([0.,0.]), array([0.,-1.])] tri = dw.dewall(P) - print "line triang:\n", tri # testing general case using random data + + def test_2d(self): + print "TESTING 2D" + P = [np.random.random_sample(2) for i in range(15)] + tri = dw.dewall(P) + # not checking if its correct, just if it runs. + + def test_3d(self): + print "TESTING 3D" + P = [np.random.random_sample(3) for i in range(9)] + tri = dw.dewall(P) + # not checking if its correct, just if it runs. + def test_4d(self): + print "TESTING 4D" + P = [np.random.random_sample(4) for i in range(9)] + tri = dw.dewall(P) + # not checking if its correct, just if it runs. + + def test_5d(self): + P = [np.random.random_sample(5) for i in range(9)] + tri = dw.dewall(P) + # not checking if its correct, just if it runs. + ## test interpolation, and thus also triangulation by extension + + def test_2d(self): + points = np.array([[ 1.,0.,1.,0.],[0.,0.,1.,1.]]) + z = np.array([1.,0.,2.,1.]) + interp = SNd.InterpolateSNd(points,z) + + X=np.array([[.4,.1,.55],[.4,.1,.3]]) + + output = interp(X) + self.assert_(self.compare_arrays(output, array([.8,.2,.85]))) + def test_linear_on_cube(self): x = array([0., 1, 0, 1, 0, 1, 0, 1]) y = array([0., 0, 1, 1, 0, 0, 1, 1]) @@ -40,14 +72,24 @@ interp = SNd.InterpolateSNd(points, fvals) - newdata = np.random.random_sample((3,20)) + newdata = np.random.random_sample((3,8)) interpvals = interp(newdata) - realvals = newdata[0,:]+newdata[1,:]-newdata[2,:] - self.assert_(compare_array(np.ravel(interpvals), np.ravel(realvals))) + self.assert_(self.compare_arrays(np.ravel(interpvals), np.ravel(realvals))) + + def test_linear_5d(self): + P = [np.random.random_sample(5) for i in range(9)] + points = array(P).reshape((5,9)) + fvals = points[:,0]+points[:,1]+points[:,2]+points[:,3]+points[:,4] + interp = SNd.InterpolateSNd(points, fvals) + newdata = np.random.random_sample((5,8)) + interpvals = interp(newdata) + realvals = np.sum(newdata, axis=0) + self.assert_(self.compare_arrays(np.ravel(interpvals), np.ravel(realvals))) + if __name__ == "__main__": unittest.main() \ No newline at end of file From scipy-svn at scipy.org Tue Aug 19 19:53:07 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 19 Aug 2008 18:53:07 -0500 (CDT) Subject: [Scipy-svn] r4657 - branches/fast_vectorize/examples Message-ID: <20080819235307.182D139C100@scipy.org> Author: ilan Date: 2008-08-19 18:53:07 -0500 (Tue, 19 Aug 2008) New Revision: 4657 Modified: branches/fast_vectorize/examples/mandel_mkImage.py Log: Made the example work. Modified: branches/fast_vectorize/examples/mandel_mkImage.py =================================================================== --- branches/fast_vectorize/examples/mandel_mkImage.py 2008-08-19 23:39:17 UTC (rev 4656) +++ branches/fast_vectorize/examples/mandel_mkImage.py 2008-08-19 23:53:07 UTC (rev 4657) @@ -3,45 +3,45 @@ # Before running this be sure to apply Travis Oliphant's patch to PIL: # http://www.scipy.org/Cookbook/PIL -import numpy +from numpy import asarray, concatenate, ogrid, uint8 from PIL import Image -from mkufunc.api import mkufunc -from mandel_c import mandel +import sys +sys.path.append('../mkufunc') +from fast_vectorize import fast_vectorize - at mkufunc(int) -def color(i): - return (i * 10) % 256 +from mandel_c import mandel - n = i % 3 - if n == 0: - c = (255, 127, 128) - elif n == 1: - c = (128, 255, 0) - else: - c = (0, 128, 255) - return c[0] + (c[1] + c[2]*256)*256 + at fast_vectorize(int) +def red(i): + if i == -1: return 0 + return (i * 5) % 256 + at fast_vectorize(int) +def green(i): + if i == -1: return 0 + return (i % 16) * 15 + at fast_vectorize(int) +def blue(i): + if i == -1: return 0 + return 255 -w, h = 1024, 768 -x, y = numpy.ogrid[-2.5:+1.5:w*1j, -1.5:+1.5:h*1j] +w, h = 1200, 900 -img = mandel(x, y) +y, x = ogrid[-1.5:+1.5:h*1j, -2.75:+1.15:w*1j] -print img.dtype -print img.shape +mand = mandel(x, y) -img = color(img) -img.dtype = numpy.uint8 -img = img.reshape(h, w, 4) +r = asarray(red(mand), dtype=uint8).reshape(h, w, 1) +g = asarray(green(mand), dtype=uint8).reshape(h, w, 1) +b = asarray(blue(mand), dtype=uint8).reshape(h, w, 1) -print img.dtype -print img.shape +a = concatenate((r, g, b), axis=2).reshape(h, w, 3) -pilImage = Image.fromarray(img) -pilImage.save('mandel.png') +im = Image.fromarray(a) +im.save('mandel.png') From scipy-svn at scipy.org Tue Aug 19 20:35:59 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 19 Aug 2008 19:35:59 -0500 (CDT) Subject: [Scipy-svn] r4658 - in branches/fast_vectorize: . mkufunc Message-ID: <20080820003559.1A6E239C100@scipy.org> Author: ilan Date: 2008-08-19 19:35:58 -0500 (Tue, 19 Aug 2008) New Revision: 4658 Removed: branches/fast_vectorize/mkufunc/func_hash.py Modified: branches/fast_vectorize/README.txt branches/fast_vectorize/TODO.txt branches/fast_vectorize/mkufunc/fast_vectorize.py Log: Merged function hash into fast_vectorize.py, updated TODO list, and added things to the README file. Modified: branches/fast_vectorize/README.txt =================================================================== --- branches/fast_vectorize/README.txt 2008-08-19 23:53:07 UTC (rev 4657) +++ branches/fast_vectorize/README.txt 2008-08-20 00:35:58 UTC (rev 4658) @@ -1,6 +1,8 @@ +============== +fast_vectorize +============== -mkufunc (make universal function) is a tool which lets you create -a C compiled version of a universal function (UFunc). +fast_vectorize lets you create U functions from python source code. It works by translating the python function into C and then uses scipy.weave to create a UFunc which calls the appropriate C function @@ -10,10 +12,11 @@ are very large). Requirements: - pypy -You need the pypy path in your PYTHONPATH environment: -$ export PYTHONPATH=/<...>/pypy-dist +Use SVN to download the pypy source: +svn co http://codespeak.net/svn/pypy/dist pypy-dist +Make sure pypy can be imported, e.g. set your PYTHONPATH: +export PYTHONPATH= Modified: branches/fast_vectorize/TODO.txt =================================================================== --- branches/fast_vectorize/TODO.txt 2008-08-19 23:53:07 UTC (rev 4657) +++ branches/fast_vectorize/TODO.txt 2008-08-20 00:35:58 UTC (rev 4658) @@ -1,9 +1,5 @@ -- Documentation +* Documentation -- think about shipping issues (using weave ext_tools) +* think about shipping issues (using weave ext_tools) -- add Csrc attribute to ufunc object - -- see if monkeypatch of pypy modules is feasible/desired - Modified: branches/fast_vectorize/mkufunc/fast_vectorize.py =================================================================== --- branches/fast_vectorize/mkufunc/fast_vectorize.py 2008-08-19 23:53:07 UTC (rev 4657) +++ branches/fast_vectorize/mkufunc/fast_vectorize.py 2008-08-20 00:35:58 UTC (rev 4658) @@ -3,19 +3,16 @@ Author: Ilan Schnell Thanks: Travis Oliphant and Eric Jones """ -import sys import re import os import cStringIO -from types import FunctionType +import md5 +from types import CodeType, FunctionType import numpy from scipy import weave -# Local imports -from func_hash import func_hash - _verbose = 0 _showc = 0 _force = 0 @@ -51,6 +48,34 @@ return str(t.driver.cbuilder.c_source_filename) +def func_hash(f, salt=None): + """ + Return a MD5 hash for a function or code object as hexadecimal string. + """ + if type(f) == FunctionType: + co = f.func_code + elif type(f) == CodeType: + co = f + else: + raise TypeError("Object %r is not function or code object.") + + res = [] + for name in dir(co): + if not name.startswith('co_'): + continue + if name == 'co_consts': + for c in getattr(co, name): + if type(c) == CodeType or \ + type(c) == FunctionType: + res.append(func_hash(c)) + else: + res.append(repr(c)) + else: + res.append(repr(getattr(co, name))) + + return md5.md5(''.join(res) + repr(salt)).hexdigest() + + def translate_cached(f, argtypes): """ Return pypy's C output for a given function and argument types Deleted: branches/fast_vectorize/mkufunc/func_hash.py =================================================================== --- branches/fast_vectorize/mkufunc/func_hash.py 2008-08-19 23:53:07 UTC (rev 4657) +++ branches/fast_vectorize/mkufunc/func_hash.py 2008-08-20 00:35:58 UTC (rev 4658) @@ -1,29 +0,0 @@ -import md5 -from types import CodeType, FunctionType - - -def func_hash(f, salt=None): - """ Return a MD5 hash for a function or code object as string. - """ - if type(f) == FunctionType: - co = f.func_code - elif type(f) == CodeType: - co = f - else: - raise TypeError("Object %r is not function or code object.") - - res = [] - for name in dir(co): - if not name.startswith('co_'): - continue - if name == 'co_consts': - for c in getattr(co, name): - if type(c) == CodeType or \ - type(c) == FunctionType: - res.append(func_hash(c)) - else: - res.append(repr(c)) - else: - res.append(repr(getattr(co, name))) - - return md5.md5(''.join(res) + repr(salt)).hexdigest() From scipy-svn at scipy.org Wed Aug 20 14:54:39 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Wed, 20 Aug 2008 13:54:39 -0500 (CDT) Subject: [Scipy-svn] r4659 - branches/interpolate/interpSNd Message-ID: <20080820185439.4C12E39C140@scipy.org> Author: fcady Date: 2008-08-20 13:54:38 -0500 (Wed, 20 Aug 2008) New Revision: 4659 Modified: branches/interpolate/interpSNd/dewall.py branches/interpolate/interpSNd/dewall.pyc branches/interpolate/interpSNd/interp.py branches/interpolate/interpSNd/interpolateSNd.py branches/interpolate/interpSNd/script.py branches/interpolate/interpSNd/test.py Log: fixed a bug in dewall. It hadn't alwayds been calculating the complete convex hull. Still not perfect, but appears to only miss interior points Modified: branches/interpolate/interpSNd/dewall.py =================================================================== --- branches/interpolate/interpSNd/dewall.py 2008-08-20 00:35:58 UTC (rev 4658) +++ branches/interpolate/interpSNd/dewall.py 2008-08-20 18:54:38 UTC (rev 4659) @@ -10,6 +10,10 @@ # In particular, calculation of the circumcircle is a purely # mathematical operation that really should be made into C. +# WARNING +# This code doesn't always work. Occasionally a point that is +# interior to the convex hull is missed. + import numpy as np from numpy.linalg import norm @@ -49,6 +53,7 @@ Sigma= [] alpha = select_alpha(P, AFL) + print "\nalpha:\n", alpha # divide points into two sets separated by alpha P1, P2 = pointset_partition(P, alpha) # both lists of points @@ -58,6 +63,7 @@ if len(AFL) == 0: # This is only executed once, at the start of the algorithm just_starting = True first_simplex = make_first_simplex(P, alpha) + print "\nfirst simplex:\n",first_simplex AFL = [ (face, get_out_vec(face,first_simplex))\ for face in faces(first_simplex)] # d+1 of them Sigma.append(first_simplex) @@ -71,6 +77,7 @@ if is_subset(face, P2): AFL2.append((face,outvec)) while len(AFL_alpha) != 0: + print "\nAFL_alpha start:",[face for face, vec in AFL_alpha] face, outvec = AFL_alpha.pop() @@ -78,9 +85,10 @@ outward_points = filter( lambda p: (np.dot(p,outvec)>np.dot(face[0],outvec)),\ P) else: - outward_points = []#filter( lambda p: np.all([not point_in_list(p,vertex) for vertex in face]), P) + outward_points = filter( lambda p: np.all([not point_in_list(p,vertex) for vertex in face]), P) t = make_simplex(face, outward_points) # make only over outer half space + print "\nnew simplex:\n",t if t is not None: Sigma.append(t) @@ -96,6 +104,7 @@ if is_subset(f0, P2): AFL2 = update(new_pair, AFL2) + print "\nAFL_alpha end:",[face for face, vec in AFL_alpha] # now Sigma contains all simplices that intersect alpha # Recursive Triangulation @@ -161,14 +170,20 @@ # both are lists of arrays return np.alltrue([ point_in_list(s1, S2) for s1 in S1]) -def update (face_pair, face_pair_list): +def update (face_pair, face_pair_list): # this func has been problematic # returns face_list with face_pair added if it wasn't there, else deleted face, outvec = face_pair - face_list = [face for face, outvec in face_pair_list] + face=face_pair[0] + print "face_pair: ", face_pair + face_list = [Face for Face, outvec in face_pair_list] + print "face: ", face + print "face_list: ", face_list if face_in_list(face, face_list): + print "face in list" f_not_equal_face = lambda face_pair : not np.alltrue([ point_in_list(p, face_pair[0]) for p in face ]) face_pair_list = filter(f_not_equal_face, face_pair_list) else: + print "face not in list" face_pair_list.append(face_pair) return face_pair_list Modified: branches/interpolate/interpSNd/dewall.pyc =================================================================== (Binary files differ) Modified: branches/interpolate/interpSNd/interp.py =================================================================== --- branches/interpolate/interpSNd/interp.py 2008-08-20 00:35:58 UTC (rev 4658) +++ branches/interpolate/interpSNd/interp.py 2008-08-20 18:54:38 UTC (rev 4659) @@ -4,7 +4,7 @@ reload(SN) -if False: +if True: points = np.array([[ 1.,0.,1.,0.],[0.,0.,1.,1.]]) z = np.array([1.,0.,2.,1.]) interp = SN.InterpolateSNd(points,z) Modified: branches/interpolate/interpSNd/interpolateSNd.py =================================================================== --- branches/interpolate/interpSNd/interpolateSNd.py 2008-08-20 00:35:58 UTC (rev 4658) +++ branches/interpolate/interpSNd/interpolateSNd.py 2008-08-20 18:54:38 UTC (rev 4659) @@ -3,6 +3,7 @@ import dewall as dw import numpy as np +from numpy.linalg import norm class InterpolateSNd: """ Interpolation of scatter data in arbitrarily many dimensions @@ -135,7 +136,7 @@ assert vals.shape == (self.ndim+1,), \ "vals wrong shape: "+str(vals.shape)+"need: "+str((self.ndim,)) - weights = self.calculate_weights(simplex, point) + weights = self.calculate_weights(simplex, point) # None if point is not weighted average return np.dot(np.ravel(weights), np.ravel(vals)) def calculate_weights(self, simplex, points): @@ -143,6 +144,10 @@ of columns in simplex. Returns matrix where jth column gives these weights for the jth column of points. + + If columns of simplex don't span the space, returns None. + FIXME : return correct weight if columns don't span space, + so long as point is still a weighted average """ assert simplex.shape == (self.ndim, self.ndim+1), "simplex shape: "+str(simplex.shape) d, V = simplex.shape @@ -159,30 +164,43 @@ axis = 0 ) - weights_vecs = np.linalg.solve(matrix_to_solve, vec_to_solve) + if rank(matrix_to_solve) < d: + print "matrix rank: "+str(np.rank(matrix_to_solve)) + print "needed dim: "+str(d) + weights_vec = None + else: + weights_vec = np.linalg.solve(matrix_to_solve, vec_to_solve) - return weights_vecs + return weights_vec -def point_is_in_simplex(point, simplex): - # point = array - # simplex = matrix - #assert point.shape == (self.ndim, 1), "wrong shape of point: "+str(point.shape) - #assert simplex.shape == (self.ndim, self.ndim+1), "wrong shape of simplex: "+str(simplex.shape) - weights_vec = calculate_weights(simplex, point) - print "weights:\n", weights_vec - weight_in_range = (0.<= weights_vec) & \ - (weights_vec <= 1.) - print "in_range:\n", weight_in_range - return np.alltrue(weight_in_range, axis=0) +def rank(matrix): + matrix = matrix.copy() + n, m = matrix.shape + # Graham-Schmidt orthonormalization of input vectors + for j in range(m): + for k in range(j): + matrix[:,j] = matrix[:,j] - np.dot(matrix[:,k],matrix[:,j])*matrix[:,k] + if norm(matrix[:,j]) > dw.eps: + matrix[:,j]=matrix[:,j]/norm(matrix[:,j]) + + norm_of_each_vec = np.sum( matrix*matrix , axis=0) + + return int(np.sum(norm_of_each_vec)) + def calculate_weights(simplex, points): """ Each column in points is a weighted average of columns in simplex. Returns matrix where jth column gives these weights for the jth column of points. + + If columns of simplex don't span the space, returns None. + FIXME : return correct weight if columns don't span space, + so long as point is still a weighted average """ - N, V = simplex.shape - N, P = points.shape + #assert simplex.shape == (self.ndim, self.ndim+1), "simplex shape: "+str(simplex.shape) + d, V = simplex.shape + d, P = points.shape matrix_to_solve = np.concatenate((simplex, \ np.ones((1,V)) @@ -195,6 +213,11 @@ axis = 0 ) - weights_vecs = np.linalg.solve(matrix_to_solve, vec_to_solve) + if np.rank(matrix_to_solve) < d: + print "matrix rank: "+str(rank(matrix_to_solve)) + print "needed dim: "+str(d) + weights_vec = None + else: + weights_vec = np.linalg.solve(matrix_to_solve, vec_to_solve) - return weights_vecs \ No newline at end of file + return weights_vec \ No newline at end of file Modified: branches/interpolate/interpSNd/script.py =================================================================== --- branches/interpolate/interpSNd/script.py 2008-08-20 00:35:58 UTC (rev 4658) +++ branches/interpolate/interpSNd/script.py 2008-08-20 18:54:38 UTC (rev 4659) @@ -23,12 +23,12 @@ y = center[1] + y_offset pyplot.plot(x,y) -Pb=[array([.25, -.25]), array([0,.75])] +Pb=[]#[array([.25, -.25]), array([0,.75])] P = Pa+Pb P = [ np.array([np.random.gamma(1), np.random.gamma(1)]) \ - for j in range(6) ] + for j in range(10) ] triangul = dw.dewall(P) @@ -42,8 +42,8 @@ # plotting the circumcircles for tri in triangul: - plot_circle(dw.circumcircle(tri)) + pass#plot_circle(dw.circumcircle(tri)) pyplot.show() -print triangul \ No newline at end of file +print "triangulation:\n",triangul \ No newline at end of file Modified: branches/interpolate/interpSNd/test.py =================================================================== --- branches/interpolate/interpSNd/test.py 2008-08-20 00:35:58 UTC (rev 4658) +++ branches/interpolate/interpSNd/test.py 2008-08-20 18:54:38 UTC (rev 4659) @@ -9,61 +9,59 @@ class Test(unittest.TestCase): def compare_arrays(self, a, b): - return np.allclose(a,b) + return np.allclose(a,b,rtol=1e-3) | (np.isnan(a)&np.isnan(b)) ## test Delaunay triangulation itself # testing pathological cases with - def test_square(self): + def _test_square(self): P = [array([0.,1.]), array([0.,0.]), array([1.,0.]), array([1.,1.])] tri = dw.dewall(P) self.assert_( len(tri)==2 ) self.assert_( len(tri[0])==3 ) self.assert_( len(tri[1])==3 ) - def test_linear(self): + def _test_linear(self): P = [array([0.,1.]), array([0.,0.]), array([0.,-1.])] tri = dw.dewall(P) # testing general case using random data - def test_2d(self): - print "TESTING 2D" - P = [np.random.random_sample(2) for i in range(15)] + def _test_2d(self): + ndim = 2 + nold = 15 + print "TESTING %iD"%ndim + corner_points_matrix = corners(ndim) + corner_points = [corner_points_matrix[:,i] for i in range(2**ndim)] + interior_points = [np.random.random_sample(ndim) for i in range(nold)] + P = corner_points+interior_points + + # not checking if its correct, just if it runs. tri = dw.dewall(P) - # not checking if its correct, just if it runs. + + # making sure it's correct - def test_3d(self): + def _test_3d(self): print "TESTING 3D" P = [np.random.random_sample(3) for i in range(9)] tri = dw.dewall(P) # not checking if its correct, just if it runs. - def test_4d(self): + def _test_4d(self): print "TESTING 4D" P = [np.random.random_sample(4) for i in range(9)] tri = dw.dewall(P) # not checking if its correct, just if it runs. - def test_5d(self): + def _test_5d(self): P = [np.random.random_sample(5) for i in range(9)] tri = dw.dewall(P) # not checking if its correct, just if it runs. ## test interpolation, and thus also triangulation by extension - def test_2d(self): - points = np.array([[ 1.,0.,1.,0.],[0.,0.,1.,1.]]) - z = np.array([1.,0.,2.,1.]) - interp = SNd.InterpolateSNd(points,z) - - X=np.array([[.4,.1,.55],[.4,.1,.3]]) - - output = interp(X) - self.assert_(self.compare_arrays(output, array([.8,.2,.85]))) - - def test_linear_on_cube(self): + def _test_linear_on_cube(self): x = array([0., 1, 0, 1, 0, 1, 0, 1]) y = array([0., 0, 1, 1, 0, 0, 1, 1]) z = array([0., 0, 0, 0, 1, 1, 1, 1]) @@ -78,18 +76,49 @@ self.assert_(self.compare_arrays(np.ravel(interpvals), np.ravel(realvals))) - def test_linear_5d(self): - P = [np.random.random_sample(5) for i in range(9)] - points = array(P).reshape((5,9)) - fvals = points[:,0]+points[:,1]+points[:,2]+points[:,3]+points[:,4] + def test_linear_2d(self): + ndim = 2 # num dimensions + nold = 5 # num known data points + nnew = 5 # num points at which to interpolate + print "%iD Interpolation"%ndim + + P = [np.random.random_sample(ndim) for i in range(nold)] + # points at corners of hypercube and radnimly scattered in the interior + points = np.concatenate((corners(ndim) , array(P).reshape((ndim,nold))), axis=1) + fvals = np.zeros((1,points.shape[1])) + for i in range(ndim): + fvals = fvals+points[i,:] + fvals = fvals.reshape((points.shape[1])) + + print "points:\n",points + print "fvals:\n",fvals + interp = SNd.InterpolateSNd(points, fvals) - newdata = np.random.random_sample((5,8)) + print "\ntriang:" + for x in interp._triangulation: print x + + newdata = np.random.random_sample((ndim,nnew)) + print "\nnewdata:\n",newdata interpvals = interp(newdata) realvals = np.sum(newdata, axis=0) - self.assert_(self.compare_arrays(np.ravel(interpvals), np.ravel(realvals))) + print "%iD interpvals: "%ndim, interpvals + print "%iD realvals: "%ndim, realvals + #self.assert_(self.compare_arrays(np.ravel(interpvals), np.ravel(realvals))) + assert self.compare_arrays(np.ravel(interpvals), np.ravel(realvals)), "wrong data" + +def corners(ndim): + # returns matrix indicating corners of unit cube + result = np.zeros((ndim,2**ndim)) + for i in range(ndim): + # each block is 2**i spaces wide + for j in range(2**ndim): + if ( j%(2**(i+1)) )/(2**i) == 1: result[i,j]=1. + return result + + if __name__ == "__main__": unittest.main() \ No newline at end of file From scipy-svn at scipy.org Wed Aug 20 20:01:13 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Wed, 20 Aug 2008 19:01:13 -0500 (CDT) Subject: [Scipy-svn] r4660 - in branches/interpolate: docs interpSNd Message-ID: <20080821000113.C80B139C036@scipy.org> Author: fcady Date: 2008-08-20 19:01:08 -0500 (Wed, 20 Aug 2008) New Revision: 4660 Modified: branches/interpolate/docs/tutorial.rst branches/interpolate/interpSNd/dewall.py branches/interpolate/interpSNd/dewall.pyc branches/interpolate/interpSNd/interp.py branches/interpolate/interpSNd/interpolateSNd.py branches/interpolate/interpSNd/script.py branches/interpolate/interpSNd/test.py Log: more work, but there are still MAJOR bugs in dewall.py Modified: branches/interpolate/docs/tutorial.rst =================================================================== --- branches/interpolate/docs/tutorial.rst 2008-08-20 18:54:38 UTC (rev 4659) +++ branches/interpolate/docs/tutorial.rst 2008-08-21 00:01:08 UTC (rev 4660) @@ -737,8 +737,14 @@ ND Scattered Interpolation ================================================ - Still in development. + InterpolateND has the significant disadvantage of requiring uniformly spaced + data, which is often not available in applications. To remedy this problem, + there is a callable class in development that does linear interpolation over the + convex hull of the known data points. - Ideally the range of interpolation would be the convex hull of the known - data points, and a Delaunay tesselation would be determined and stored - at instantiation. Then again, that would be very expensive. \ No newline at end of file + The class is InterpolateSNd, for "scattered n-dimensional" data. However, the + code is still extremely slow, and more importantly there are significant bugs remaining. + Depending on chance (the algorithm uses randomness) and the data used, the convex + hull can be improperly calculated, and there is even the possibility of infinite recursion. + That said, the algorithm works in other cases, and is expected to improve greatly in + the future. \ No newline at end of file Modified: branches/interpolate/interpSNd/dewall.py =================================================================== --- branches/interpolate/interpSNd/dewall.py 2008-08-20 18:54:38 UTC (rev 4659) +++ branches/interpolate/interpSNd/dewall.py 2008-08-21 00:01:08 UTC (rev 4660) @@ -11,8 +11,8 @@ # mathematical operation that really should be made into C. # WARNING -# This code doesn't always work. Occasionally a point that is -# interior to the convex hull is missed. +# This code doesn't always work. There are still significant +# bugs to be fixed. import numpy as np from numpy.linalg import norm @@ -28,6 +28,8 @@ AFL = [], # list of faces: (d-1)face list ): + print "DEWALL: ",len(AFL) + # checking input assert isinstance(P, list) if len(P)>0: @@ -42,6 +44,7 @@ # base case if len(P) == 0: return [] if len(P) <= len(P[0]): return [] # better to return [] whenever points are co-hyper-planar + if len(P) == len(P[0])+1: return P if linearly_independent([ point-P[0] for point in P[1:]]) else [] # simplex iff not on same hyperplane # lists of active faces # elem = ( [list of d points] , outvec ) @@ -53,7 +56,7 @@ Sigma= [] alpha = select_alpha(P, AFL) - print "\nalpha:\n", alpha + print "alpha:\n", alpha # divide points into two sets separated by alpha P1, P2 = pointset_partition(P, alpha) # both lists of points @@ -61,40 +64,59 @@ # Simplex Wall Construction just_starting = False #source of problem? if len(AFL) == 0: # This is only executed once, at the start of the algorithm - just_starting = True + #just_starting = True first_simplex = make_first_simplex(P, alpha) - print "\nfirst simplex:\n",first_simplex + print "first_simplex:" + display(first_simplex) AFL = [ (face, get_out_vec(face,first_simplex))\ for face in faces(first_simplex)] # d+1 of them Sigma.append(first_simplex) for face, outvec in AFL: if is_intersected(face, alpha): # not counting as intersected AFL_alpha.append((face, \ - get_out_vec(face,first_simplex) if just_starting \ - else outvec)) - if is_subset(face, P1): + outvec))#get_out_vec(face,first_simplex) if just_starting \ + #else outvec)) + elif is_subset(face, P1): AFL1.append((face,outvec)) - if is_subset(face, P2): + elif is_subset(face, P2): AFL2.append((face,outvec)) while len(AFL_alpha) != 0: - print "\nAFL_alpha start:",[face for face, vec in AFL_alpha] + print "\nLENGTH: ",len(AFL_alpha) + print "AFL_alpha" + for FACE, VEC in AFL_alpha: + print "face" + display(FACE) + print "AFL1" + for FACE, VEC in AFL1: + print "face" + display(FACE) + print "AFL2" + for FACE, VEC in AFL2: + print "face" + display(FACE) face, outvec = AFL_alpha.pop() + print '\nprocessing face:' + display(face) + if outvec is not None: outward_points = filter( lambda p: (np.dot(p,outvec)>np.dot(face[0],outvec)),\ P) else: - outward_points = filter( lambda p: np.all([not point_in_list(p,vertex) for vertex in face]), P) + outward_points = []#filter( lambda p: np.all([not point_in_list(p,vertex) for vertex in face]), P) + #outward_points = filter( lambda p: (np.dot(p,outvec)>np.dot(face[0],outvec)),\ + # P) - t = make_simplex(face, outward_points) # make only over outer half space - print "\nnew simplex:\n",t + t = make_simplex(face, outward_points) + print "\nnew simplex:" + display(t) if t is not None: Sigma.append(t) # for f0 != f in faces(t) , ie for new outward faces for f0 in filter(lambda f: not face_in_list(f,[face]), faces(t)): - new_pair = (f0, get_out_vec(f0, t)) + new_pair = (f0, get_out_vec(f0,t) ) if is_intersected(f0, alpha): # continue building wall out in that direction AFL_alpha = update(new_pair, AFL_alpha) @@ -104,21 +126,34 @@ if is_subset(f0, P2): AFL2 = update(new_pair, AFL2) - print "\nAFL_alpha end:",[face for face, vec in AFL_alpha] # now Sigma contains all simplices that intersect alpha # Recursive Triangulation + if len(AFL1)!=0: + print "RECURSING P1" + print "P1:" + display(P1) + print "AFL1:" + for face, vec in AFL1: display(face) + Sigma = Sigma + dewall(P1,AFL1) if len(AFL2)!=0: + print "RECURSING P2" + print "P2:" + display(P2) + print "AFL2:" + for face, vec in AFL2: display(face) Sigma = Sigma + dewall(P2,AFL2) - if len(AFL1)!=0: - Sigma = Sigma + dewall(P1,AFL1) # not doing this branch of recursion return Sigma - +def display(FACE): + if FACE==None: print 'NONE' + else: + for arr in FACE: print arr def select_alpha(P, AFL): # dividing plane. This must divide points into 2 non-empty parts - # must intersect active face if there is one - # must not intersect any points + # creates random plane which divides into 2 non-empty parts + # and, if AFL not empty, passes through one of its faces + d = len(P[0]) # plane through avg of cluster. Guarantees separation @@ -127,11 +162,14 @@ mid = sum(AFL[0][0])/(d) else: mid = sum(P)/len(P) + direction = np.random.random_sample((d)) + direction = direction/norm(direction) if norm(mid)==0: - direction = np.random.random_sample((d)) - alpha = ( direction/norm(direction), 0) + alpha = ( direction , 0) else: - alpha =(mid/norm(mid), norm(mid)) + alpha =(direction, np.dot(direction,mid)) + if alpha[1] < 0: + alpha = (-1*alpha[0], -1*alpha[1]) return alpha @@ -170,22 +208,22 @@ # both are lists of arrays return np.alltrue([ point_in_list(s1, S2) for s1 in S1]) -def update (face_pair, face_pair_list): # this func has been problematic +def update (face_pair, Face_pair_list): # this func has been problematic # returns face_list with face_pair added if it wasn't there, else deleted - face, outvec = face_pair - face=face_pair[0] - print "face_pair: ", face_pair - face_list = [Face for Face, outvec in face_pair_list] - print "face: ", face - print "face_list: ", face_list - if face_in_list(face, face_list): - print "face in list" - f_not_equal_face = lambda face_pair : not np.alltrue([ point_in_list(p, face_pair[0]) for p in face ]) - face_pair_list = filter(f_not_equal_face, face_pair_list) + face = face_pair[0] #list of arrays + Face_list = [Face_pair[0] for Face_pair in Face_pair_list] #list of lists(or arrays) + if face_in_list(face, Face_list): + #print "face in list" + def Face_pair_not_equal_face(Pair): + Face = Pair[0] + vertex_of_face_in_Face = [point_in_list(vert,Face) for vert in face] + return not np.all(vertex_of_face_in_Face) + #Face_pair_not_equal_face = lambda Pair : not np.alltrue([ point_in_list(p, Pair[0]) for p in face ]) + Face_pair_list = filter(Face_pair_not_equal_face, Face_pair_list) else: - print "face not in list" - face_pair_list.append(face_pair) - return face_pair_list + #print "not in list" + Face_pair_list.append(face_pair) + return Face_pair_list def pointset_partition(P, alpha): #WORKS P1 = [p for p in P if np.dot(p,alpha[0])< alpha[1]] @@ -211,7 +249,7 @@ def make_first_simplex(P, alpha): #WORKS # alpha = unit_normal_vec, distance - # assume no points on plane + # ENSURE!! no points on same hyperplane d = len(P[0]) unit_normal, distance = alpha @@ -222,21 +260,33 @@ first_point = sorted(points_and_dist_from_alpha, cmp = compare_first_elem \ )[0][1] # closest to alpha - + print "first points:\n" + display(first_point) possible_second_pts = [ (circumcircle([first_point, point])[1], point) \ - for point in P if (point != first_point).any() and \ + for point in P if \ + (point != first_point).any() and \ (np.dot(unit_normal, first_point)-distance)*(np.dot(unit_normal, point)-distance)<=0 \ ] second_point = sorted(possible_second_pts, \ cmp = compare_first_elem \ )[0][1] + print "second point:\n" + display(second_point) simplex = [first_point, second_point] for i in range(d-1): radii_of_circumcircles = [(circumcircle( copy_list(simplex)+[point.copy()] )[1], point) \ - for point in P if not point_in_list(point, simplex) ] - new_point = sorted(radii_of_circumcircles, \ + for point in P if \ + not point_in_list(point, simplex) and \ + linearly_independent([(point-first_point)]+[ (p-first_point) for p in simplex[1:] ]) \ + ] + #new_point = sorted(radii_of_circumcircles, \ + # cmp = compare_first_elem \ + # )[0][1] + new_point_pair = sorted(radii_of_circumcircles, \ cmp = compare_first_elem \ - )[0][1] + )[0] + new_point = new_point_pair[1] + print "new point:\n", new_point simplex.append(new_point) return simplex @@ -249,14 +299,14 @@ -def make_simplex(f,P): #WORKS +def make_simplex(f,outward_points): #WORKS # must be only in the outer halfspace # returns the simlex # clean up by making sure only points not in hyperplane(f) are in P - valid_points = [p for p in P if not point_in_list(p,f)] + valid_points = outward_points#[p for p in P if not point_in_list(p,f)] if len(valid_points) == 0: return None delaunay_distances = [(delaunay_dist(f,p) ,p) for p in valid_points] @@ -391,9 +441,24 @@ d=len(P[0]) if len(P)>d: return False matrix = np.array(P).reshape((d,len(P))) - return np.rank(matrix)==len(P) + return rank(matrix)==len(P) + +def rank(matrix): + matrix = matrix.copy() + n, m = matrix.shape + # Graham-Schmidt orthonormalization of input vectors + for j in range(m): + for k in range(j): + matrix[:,j] = matrix[:,j] - np.dot(matrix[:,k],matrix[:,j])*matrix[:,k] + if norm(matrix[:,j]) > eps: + matrix[:,j]=matrix[:,j]/norm(matrix[:,j]) + norm_of_each_vec = np.sum( matrix*matrix , axis=0) + return int(np.sum(norm_of_each_vec)) + + + \ No newline at end of file Modified: branches/interpolate/interpSNd/dewall.pyc =================================================================== (Binary files differ) Modified: branches/interpolate/interpSNd/interp.py =================================================================== --- branches/interpolate/interpSNd/interp.py 2008-08-20 18:54:38 UTC (rev 4659) +++ branches/interpolate/interpSNd/interp.py 2008-08-21 00:01:08 UTC (rev 4660) @@ -4,7 +4,7 @@ reload(SN) -if True: +if False: points = np.array([[ 1.,0.,1.,0.],[0.,0.,1.,1.]]) z = np.array([1.,0.,2.,1.]) interp = SN.InterpolateSNd(points,z) @@ -20,12 +20,14 @@ if True: - points = np.array([ [0., 0, 0, 1.,.2], - [0., 1., 0, 0, .2], - [0., 0, 1., 0, .2] ]) - z = np.array([.1,1.,1.,1.,.6]) + points = np.array([ [0., 0, 0, 1., 1., 1., 0., 1., .2], + [0., 1., 0, 0, 1., 0., 1., 1., .2], + [0., 0, 1., 0, 0., 1., 1., 1., .2] ]) + z = np.sum(points,axis=0).reshape(points.shape[1]) interp = SN.InterpolateSNd(points,z) + print "*"*100+'\nMADE IT' + X = np.array([ [.1,.2,.1,.1], [.1,.1,.2,.1], [.1,.1,.1,.2] ]) Modified: branches/interpolate/interpSNd/interpolateSNd.py =================================================================== --- branches/interpolate/interpSNd/interpolateSNd.py 2008-08-20 18:54:38 UTC (rev 4659) +++ branches/interpolate/interpSNd/interpolateSNd.py 2008-08-21 00:01:08 UTC (rev 4660) @@ -165,7 +165,7 @@ ) if rank(matrix_to_solve) < d: - print "matrix rank: "+str(np.rank(matrix_to_solve)) + print "matrix rank: "+str(rank(matrix_to_solve)) print "needed dim: "+str(d) weights_vec = None else: Modified: branches/interpolate/interpSNd/script.py =================================================================== --- branches/interpolate/interpSNd/script.py 2008-08-20 18:54:38 UTC (rev 4659) +++ branches/interpolate/interpSNd/script.py 2008-08-21 00:01:08 UTC (rev 4660) @@ -31,12 +31,15 @@ for j in range(10) ] triangul = dw.dewall(P) +print "triangulation:\n",triangul + # plotting the known data points for p in P: pyplot.scatter([p[0]],[p[1]]) # plotting the triangulation for tri in triangul: + print "triangle:\n", tri for seg in segments(tri): pyplot.plot(seg[0],seg[1]) @@ -46,4 +49,3 @@ pyplot.show() -print "triangulation:\n",triangul \ No newline at end of file Modified: branches/interpolate/interpSNd/test.py =================================================================== --- branches/interpolate/interpSNd/test.py 2008-08-20 18:54:38 UTC (rev 4659) +++ branches/interpolate/interpSNd/test.py 2008-08-21 00:01:08 UTC (rev 4660) @@ -9,7 +9,7 @@ class Test(unittest.TestCase): def compare_arrays(self, a, b): - return np.allclose(a,b,rtol=1e-3) | (np.isnan(a)&np.isnan(b)) + return np.allclose(a,b,rtol=1e-3) or (np.isnan(a)&np.isnan(b)).all() ## test Delaunay triangulation itself @@ -27,7 +27,6 @@ tri = dw.dewall(P) # testing general case using random data - def _test_2d(self): ndim = 2 nold = 15 @@ -60,7 +59,6 @@ # not checking if its correct, just if it runs. ## test interpolation, and thus also triangulation by extension - def _test_linear_on_cube(self): x = array([0., 1, 0, 1, 0, 1, 0, 1]) y = array([0., 0, 1, 1, 0, 0, 1, 1]) @@ -110,6 +108,40 @@ #self.assert_(self.compare_arrays(np.ravel(interpvals), np.ravel(realvals))) assert self.compare_arrays(np.ravel(interpvals), np.ravel(realvals)), "wrong data" + def test_linear_3d(self): + ndim = 3 # num dimensions + nold = 1 # num known data points + nnew = 5 # num points at which to interpolate + + print "%iD Interpolation"%ndim + + P = [np.random.random_sample(ndim) for i in range(nold)] + # points at corners of hypercube and radnimly scattered in the interior + points = np.concatenate((corners(ndim) , array(P).reshape((ndim,nold))), axis=1) + fvals = np.zeros((1,points.shape[1])) + for i in range(ndim): + fvals = fvals+points[i,:] + fvals = fvals.reshape((points.shape[1])) + + #print "points:\n",points + #print "fvals:\n",fvals + + interp = SNd.InterpolateSNd(points, fvals) + + #print "\ntriang:" + #for x in interp._triangulation: print x + + newdata = np.random.random_sample((ndim,nnew)) + #print "\nnewdata:\n",newdata + interpvals = interp(newdata) + realvals = np.sum(newdata, axis=0) + + print "%iD interpvals: "%ndim, interpvals + print "%iD realvals: "%ndim, realvals + + #self.assert_(self.compare_arrays(np.ravel(interpvals), np.ravel(realvals))) + assert self.compare_arrays(np.ravel(interpvals), np.ravel(realvals)), "wrong data" + def corners(ndim): # returns matrix indicating corners of unit cube result = np.zeros((ndim,2**ndim)) From scipy-svn at scipy.org Wed Aug 20 20:35:53 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Wed, 20 Aug 2008 19:35:53 -0500 (CDT) Subject: [Scipy-svn] r4661 - branches/fast_vectorize/examples Message-ID: <20080821003553.6D73439C036@scipy.org> Author: ilan Date: 2008-08-20 19:35:44 -0500 (Wed, 20 Aug 2008) New Revision: 4661 Added: branches/fast_vectorize/examples/compdec.py branches/fast_vectorize/examples/mandel.py Modified: branches/fast_vectorize/examples/benchmark.py Log: Added examples, and decreased array size for benchmark. Modified: branches/fast_vectorize/examples/benchmark.py =================================================================== --- branches/fast_vectorize/examples/benchmark.py 2008-08-21 00:01:08 UTC (rev 4660) +++ branches/fast_vectorize/examples/benchmark.py 2008-08-21 00:35:44 UTC (rev 4661) @@ -75,7 +75,7 @@ ############################################################# -x = linspace(0, 1, 10000*1000) +x = linspace(0, 1, 1000*1000) start_time = time.time() b_y = empty_like(x) Added: branches/fast_vectorize/examples/compdec.py =================================================================== --- branches/fast_vectorize/examples/compdec.py 2008-08-21 00:01:08 UTC (rev 4660) +++ branches/fast_vectorize/examples/compdec.py 2008-08-21 00:35:44 UTC (rev 4661) @@ -0,0 +1,34 @@ +""" +I have written a class which allows using the compiled version of a +Python functions simply by adding a decorator to the function. +The nice thing about doing things this way is that all the code is pure +Python code, and switching between the compiled and uncompiled version +of the function is as simple as possible. +""" +from pypy.translator.interactive import Translation + +class compdec: + def __init__(self, func): + self.func = func + self.argtypes = None + + def __call__(self, *args): + argtypes = tuple(type(arg) for arg in args) + if argtypes != self.argtypes: + self.argtypes = argtypes + t = Translation(self.func) + t.annotate(argtypes) + self.cfunc = t.compile_c() + + return self.cfunc(*args) + + at compdec +def is_prime(n): + if n < 2: + return False + for i in xrange(2, n): + if n%i == 0: + return False + return True + +print sum(is_prime(n) for n in xrange(100000)) Added: branches/fast_vectorize/examples/mandel.py =================================================================== --- branches/fast_vectorize/examples/mandel.py 2008-08-21 00:01:08 UTC (rev 4660) +++ branches/fast_vectorize/examples/mandel.py 2008-08-21 00:35:44 UTC (rev 4661) @@ -0,0 +1,54 @@ +#!/usr/bin/env python +from numpy import asarray, concatenate, ogrid, uint8 +from PIL import Image + +import sys +sys.path.append('../mkufunc') +from fast_vectorize import fast_vectorize + + + at fast_vectorize([(float, float, int)]) +def mandel(cr, ci): + d = 1 + zr = cr + zi = ci + for d in xrange(1, 1000): + zr2 = zr * zr + zi2 = zi * zi + if zr2 + zi2 > 16: + return d + zi = 2.0 * zr * zi + ci + zr = zr2 - zi2 + cr + else: + return -1 + + at fast_vectorize(int) +def red(i): + if i == -1: return 0 + return (i * 5) % 256 + + at fast_vectorize(int) +def green(i): + if i == -1: return 0 + return (i % 16) * 15 + + at fast_vectorize(int) +def blue(i): + if i == -1: return 0 + return 255 + + +w, h = 1200, 900 + +y, x = ogrid[-1.5:+1.5:h*1j, -2.75:+1.15:w*1j] + +mand = mandel(x, y) + +r = asarray(red(mand), dtype=uint8).reshape(h, w, 1) +g = asarray(green(mand), dtype=uint8).reshape(h, w, 1) +b = asarray(blue(mand), dtype=uint8).reshape(h, w, 1) + +a = concatenate((r, g, b), axis=2).reshape(h, w, 3) + +im = Image.fromarray(a) +im.save('mandel.png') From scipy-svn at scipy.org Thu Aug 21 15:06:55 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Thu, 21 Aug 2008 14:06:55 -0500 (CDT) Subject: [Scipy-svn] r4662 - in trunk/scipy/signal: . tests Message-ID: <20080821190655.6CD4839C185@scipy.org> Author: stefan Date: 2008-08-21 14:05:50 -0500 (Thu, 21 Aug 2008) New Revision: 4662 Modified: trunk/scipy/signal/signaltools.py trunk/scipy/signal/tests/test_signaltools.py Log: Fix calculation of Chebyshev polynomial in chebwin. Closes #581. Modified: trunk/scipy/signal/signaltools.py =================================================================== --- trunk/scipy/signal/signaltools.py 2008-08-21 00:35:44 UTC (rev 4661) +++ trunk/scipy/signal/signaltools.py 2008-08-21 19:05:50 UTC (rev 4662) @@ -854,30 +854,31 @@ M = M+1 # compute the parameter beta - beta = cosh(1.0/(M-1.0)*arccosh(10**(at/20.))) + order = M - 1.0 + beta = cosh(1.0/order * arccosh(10**(abs(at)/20.))) k = r_[0:M]*1.0 x = beta*cos(pi*k/M) #find the window's DFT coefficients - p = zeros(x.shape) * 1.0 - for i in range(len(x)): - if x[i] < 1: - p[i] = cos((M - 1) * arccos(x[i])) - else: - p[i] = cosh((M - 1) * arccosh(x[i])) + # Use analytic definition of Chebyshev polynomial instead of expansion + # from scipy.special. Using the expansion in scipy.special leads to errors. + p = zeros(x.shape) + p[x > 1] = cosh(order * arccosh(x[x > 1])) + p[x < -1] = (1 - 2*(order%2)) * cosh(order * arccosh(-x[x < -1])) + p[numpy.abs(x) <=1 ] = cos(order * arccos(x[numpy.abs(x) <= 1])) # Appropriate IDFT and filling up # depending on even/odd M if M % 2: - w = real(fft(p)); - n = (M + 1) / 2; - w = w[:n] / w[0]; + w = real(fft(p)) + n = (M + 1) / 2 + w = w[:n] / w[0] w = concatenate((w[n - 1:0:-1], w)) else: p = p * exp(1.j*pi / M * r_[0:M]) - w = real(fft(p)); - n = M / 2 + 1; - w = w / w[1]; - w = concatenate((w[n - 1:0:-1], w[1:n])); + w = real(fft(p)) + n = M / 2 + 1 + w = w / w[1] + w = concatenate((w[n - 1:0:-1], w[1:n])) if not sym and not odd: w = w[:-1] return w Modified: trunk/scipy/signal/tests/test_signaltools.py =================================================================== --- trunk/scipy/signal/tests/test_signaltools.py 2008-08-21 00:35:44 UTC (rev 4661) +++ trunk/scipy/signal/tests/test_signaltools.py 2008-08-21 19:05:50 UTC (rev 4662) @@ -55,5 +55,48 @@ assert_array_equal(signal.order_filter([1,2,3],[1,0,1],1), [2,3,2]) +class TestChebWin: + def test_cheb_odd(self): + cheb_odd_true = array([0.200938, 0.107729, 0.134941, 0.165348, + 0.198891, 0.235450, 0.274846, 0.316836, + 0.361119, 0.407338, 0.455079, 0.503883, + 0.553248, 0.602637, 0.651489, 0.699227, + 0.745266, 0.789028, 0.829947, 0.867485, + 0.901138, 0.930448, 0.955010, 0.974482, + 0.988591, 0.997138, 1.000000, 0.997138, + 0.988591, 0.974482, 0.955010, 0.930448, + 0.901138, 0.867485, 0.829947, 0.789028, + 0.745266, 0.699227, 0.651489, 0.602637, + 0.553248, 0.503883, 0.455079, 0.407338, + 0.361119, 0.316836, 0.274846, 0.235450, + 0.198891, 0.165348, 0.134941, 0.107729, + 0.200938]) + + cheb_odd = signal.chebwin(53, at=-40) + assert_array_almost_equal(cheb_odd, cheb_odd_true, decimal=4) + + def test_cheb_even(self): + cheb_even_true = array([0.203894, 0.107279, 0.133904, + 0.163608, 0.196338, 0.231986, + 0.270385, 0.311313, 0.354493, + 0.399594, 0.446233, 0.493983, + 0.542378, 0.590916, 0.639071, + 0.686302, 0.732055, 0.775783, + 0.816944, 0.855021, 0.889525, + 0.920006, 0.946060, 0.967339, + 0.983557, 0.994494, 1.000000, + 1.000000, 0.994494, 0.983557, + 0.967339, 0.946060, 0.920006, + 0.889525, 0.855021, 0.816944, + 0.775783, 0.732055, 0.686302, + 0.639071, 0.590916, 0.542378, + 0.493983, 0.446233, 0.399594, + 0.354493, 0.311313, 0.270385, + 0.231986, 0.196338, 0.163608, + 0.133904, 0.107279, 0.203894]) + + cheb_even = signal.chebwin(54, at=-40) + assert_array_almost_equal(cheb_even, cheb_even_true, decimal=4) + if __name__ == "__main__": run_module_suite() From scipy-svn at scipy.org Fri Aug 22 02:38:01 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 22 Aug 2008 01:38:01 -0500 (CDT) Subject: [Scipy-svn] r4663 - trunk Message-ID: <20080822063801.7418139C232@scipy.org> Author: jarrod.millman Date: 2008-08-22 01:37:59 -0500 (Fri, 22 Aug 2008) New Revision: 4663 Modified: trunk/MANIFEST.in trunk/new_manifest.sh Log: cleaning up after removing sandbox Modified: trunk/MANIFEST.in =================================================================== --- trunk/MANIFEST.in 2008-08-21 19:05:50 UTC (rev 4662) +++ trunk/MANIFEST.in 2008-08-22 06:37:59 UTC (rev 4663) @@ -6,64 +6,3 @@ include setup.py include *.txt include scipy/*.py -# -# The following files are in the sandbox and wouldn't normally get included in sdist: -# -include scipy/sandbox/arpack/* -include scipy/sandbox/arpack/ARPACK/* -include scipy/sandbox/arpack/ARPACK/LAPACK/* -include scipy/sandbox/arpack/ARPACK/SRC/* -include scipy/sandbox/arpack/ARPACK/UTIL/* -include scipy/sandbox/arpack/tests/* -include scipy/sandbox/buildgrid/* -include scipy/sandbox/cdavid/* -include scipy/sandbox/cdavid/src/* -include scipy/sandbox/cdavid/tests/* -include scipy/sandbox/constants/* -include scipy/sandbox/delaunay/* -include scipy/sandbox/delaunay/tests/* -include scipy/sandbox/dhuard/* -include scipy/sandbox/exmplpackage/* -include scipy/sandbox/exmplpackage/tests/* -include scipy/sandbox/exmplpackage/yyy/* -include scipy/sandbox/exmplpackage/yyy/tests/* -include scipy/sandbox/fdfpack/* -include scipy/sandbox/fdfpack/src/* -include scipy/sandbox/fdfpack/tests/* -include scipy/sandbox/fdfpack/utils/* -include scipy/sandbox/ga/* -include scipy/sandbox/image/* -include scipy/sandbox/lobpcg/* -include scipy/sandbox/lobpcg/tests/* -include scipy/sandbox/montecarlo/* -include scipy/sandbox/montecarlo/examples/* -include scipy/sandbox/montecarlo/src/* -include scipy/sandbox/montecarlo/tests/* -include scipy/sandbox/multigrid/* -include scipy/sandbox/multigrid/multigridtools/* -include scipy/sandbox/multigrid/tests/* -include scipy/sandbox/multigrid/tests/sample_data/* -include scipy/sandbox/netcdf/* -include scipy/sandbox/newoptimize/* -include scipy/sandbox/newoptimize/tnc/* -include scipy/sandbox/numexpr/* -include scipy/sandbox/numexpr/bench/* -include scipy/sandbox/numexpr/tests/* -include scipy/sandbox/oliphant/* -include scipy/sandbox/pyloess/* -include scipy/sandbox/pyloess/doc/* -include scipy/sandbox/pyloess/src/* -include scipy/sandbox/pyloess/tests/* -include scipy/sandbox/rbf/* -include scipy/sandbox/rbf/tests/* -include scipy/sandbox/rkern/* -include scipy/sandbox/spline/* -include scipy/sandbox/spline/fitpack/* -include scipy/sandbox/spline/tests/* -include scipy/sandbox/stats/* -include scipy/sandbox/timeseries/* -include scipy/sandbox/timeseries/include/* -include scipy/sandbox/timeseries/lib/* -include scipy/sandbox/timeseries/lib/tests/* -include scipy/sandbox/timeseries/src/* -include scipy/sandbox/timeseries/tests/* Modified: trunk/new_manifest.sh =================================================================== --- trunk/new_manifest.sh 2008-08-21 19:05:50 UTC (rev 4662) +++ trunk/new_manifest.sh 2008-08-22 06:37:59 UTC (rev 4663) @@ -6,7 +6,6 @@ # would otherwise leave these files out. MANIFEST_IN=MANIFEST.in -SANDBOX_DIR="scipy/sandbox" cat < $MANIFEST_IN # This automatically generated by new_manifest.sh @@ -17,13 +16,4 @@ include setup.py include *.txt include scipy/*.py -# -# The following files are in the sandbox and wouldn't normally get included in sdist: -# EOF - -for i in `svn ls -R $SANDBOX_DIR`; do - if test -d $SANDBOX_DIR/$i; then - echo "include $SANDBOX_DIR/$i*" >> $MANIFEST_IN - fi -done From scipy-svn at scipy.org Fri Aug 22 02:38:50 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 22 Aug 2008 01:38:50 -0500 (CDT) Subject: [Scipy-svn] r4664 - trunk Message-ID: <20080822063850.093D939C232@scipy.org> Author: jarrod.millman Date: 2008-08-22 01:38:49 -0500 (Fri, 22 Aug 2008) New Revision: 4664 Modified: trunk/TOCHANGE.txt Log: cleaning up sandbox removal Modified: trunk/TOCHANGE.txt =================================================================== --- trunk/TOCHANGE.txt 2008-08-22 06:37:59 UTC (rev 4663) +++ trunk/TOCHANGE.txt 2008-08-22 06:38:49 UTC (rev 4664) @@ -25,17 +25,8 @@ * Improve testing (e.g., increased coverage) -* Get rid of sandbox - * move packages to - * scipy - - * scikits - - * or a branch - - Documentation ------------- From scipy-svn at scipy.org Fri Aug 22 20:42:18 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 22 Aug 2008 19:42:18 -0500 (CDT) Subject: [Scipy-svn] r4665 - trunk/scipy/cluster Message-ID: <20080823004218.9FFFB39C02D@scipy.org> Author: damian.eads Date: 2008-08-22 19:42:16 -0500 (Fri, 22 Aug 2008) New Revision: 4665 Modified: trunk/scipy/cluster/distance.py Log: Converted the documentation to restructured text. Modified: trunk/scipy/cluster/distance.py =================================================================== --- trunk/scipy/cluster/distance.py 2008-08-22 06:38:49 UTC (rev 4664) +++ trunk/scipy/cluster/distance.py 2008-08-23 00:42:16 UTC (rev 4665) @@ -1,32 +1,90 @@ """ + +Function Reference +------------------ + Distance matrix computation from a collection of raw observation vectors +stored in a rectangular array. - pdist computes distances between each observation pair. ++------------------+-------------------------------------------------+ +|pdist | computes distances between observation pairs. | ++------------------+-------------------------------------------------+ -Distance functions between two vectors u and v +Distance functions between two vectors ``u`` and ``v``. Computing +distances over a large collection of vectors is inefficient for these +functions. Use ``pdist`` for this purpose. - braycurtis the Bray-Curtis distance. - canberra the Canberra distance. - chebyshev the Chebyshev distance. - cityblock the Manhattan distance. - correlation the Correlation distance. - cosine the Cosine distance. - dice the Dice dissimilarity (boolean). - euclidean the Euclidean distance. - hamming the Hamming distance (boolean). - jaccard the Jaccard distance (boolean). - kulsinski the Kulsinski distance (boolean). - mahalanobis the Mahalanobis distance. - matching the matching dissimilarity (boolean). - minkowski the Minkowski distance. - rogerstanimoto the Rogers-Tanimoto dissimilarity (boolean). - russellrao the Russell-Rao dissimilarity (boolean). - seuclidean the normalized Euclidean distance. - sokalmichener the Sokal-Michener dissimilarity (boolean). - sokalsneath the Sokal-Sneath dissimilarity (boolean). - sqeuclidean the squared Euclidean distance. - yule the Yule dissimilarity (boolean). ++------------------+-------------------------------------------------+ +|braycurtis | the Bray-Curtis distance. | +|canberra | the Canberra distance. | +|chebyshev | the Chebyshev distance. | +|cityblock | the Manhattan distance. | +|correlation | the Correlation distance. | +|cosine | the Cosine distance. | +|dice | the Dice dissimilarity (boolean). | +|euclidean | the Euclidean distance. | +|hamming | the Hamming distance (boolean). | +|jaccard | the Jaccard distance (boolean). | +|kulsinski | the Kulsinski distance (boolean). | +|mahalanobis | the Mahalanobis distance. | +|matching | the matching dissimilarity (boolean). | +|minkowski | the Minkowski distance. | +|rogerstanimoto | the Rogers-Tanimoto dissimilarity (boolean). | +|russellrao | the Russell-Rao dissimilarity (boolean). | +|seuclidean | the normalized Euclidean distance. | +|sokalmichener | the Sokal-Michener dissimilarity (boolean). | +|sokalsneath | the Sokal-Sneath dissimilarity (boolean). | +|sqeuclidean | the squared Euclidean distance. | +|yule | the Yule dissimilarity (boolean). | ++------------------+-------------------------------------------------+ + +References +---------- + +.. [Sta07] "Statistics toolbox." API Reference Documentation. The MathWorks. + http://www.mathworks.com/access/helpdesk/help/toolbox/stats/. + Accessed October 1, 2007. + +.. [Mti07] "Hierarchical clustering." API Reference Documentation. + The Wolfram Research, Inc. + http://reference.wolfram.com/mathematica/HierarchicalClustering/tutorial/HierarchicalClustering.html. + Accessed October 1, 2007. + +.. [Gow69] Gower, JC and Ross, GJS. "Minimum Spanning Trees and Single Linkage + Cluster Analysis." Applied Statistics. 18(1): pp. 54--64. 1969. + +.. [War63] Ward Jr, JH. "Hierarchical grouping to optimize an objective + function." Journal of the American Statistical Association. 58(301): + pp. 236--44. 1963. + +.. [Joh66] Johnson, SC. "Hierarchical clustering schemes." Psychometrika. + 32(2): pp. 241--54. 1966. + +.. [Sne62] Sneath, PH and Sokal, RR. "Numerical taxonomy." Nature. 193: pp. + 855--60. 1962. + +.. [Bat95] Batagelj, V. "Comparing resemblance measures." Journal of + Classification. 12: pp. 73--90. 1995. + +.. [Sok58] Sokal, RR and Michener, CD. "A statistical method for evaluating + systematic relationships." Scientific Bulletins. 38(22): + pp. 1409--38. 1958. + +.. [Ede79] Edelbrock, C. "Mixture model tests of hierarchical clustering + algorithms: the problem of classifying everybody." Multivariate + Behavioral Research. 14: pp. 367--84. 1979. + +.. [Jai88] Jain, A., and Dubes, R., "Algorithms for Clustering Data." + Prentice-Hall. Englewood Cliffs, NJ. 1988. + +.. [Fis36] Fisher, RA "The use of multiple measurements in taxonomic + problems." Annals of Eugenics, 7(2): 179-188. 1936 + + +Copyright Notice +---------------- + Copyright (C) Damian Eads, 2007-2008. New BSD License. """ @@ -72,11 +130,24 @@ def minkowski(u, v, p): """ - d = minkowski(u, v, p) + Computes the Minkowski distance between two vectors ``u`` and ``v``, + defined as - Returns the Minkowski distance between two vectors u and v, + .. math:: - ||u-v||_p = (\sum {|u_i - v_i|^p})^(1/p). + {||u-v||}_p = (\sum {|u_i - v_i|^p})^(1/p). + + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. + p : ndarray + The norm of the difference :math:`${||u-v||}_p$`. + + :Returns: + d : double + The Minkowski distance between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -86,9 +157,22 @@ def euclidean(u, v): """ - d = euclidean(u, v) + Computes the Euclidean distance between two n-vectors ``u`` and ``v``, + which is defined as - Computes the Euclidean distance between two n-vectors u and v, ||u-v||_2 + .. math:: + + {||u-v||}_2 + + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. + + :Returns: + d : double + The Euclidean distance between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -97,10 +181,23 @@ def sqeuclidean(u, v): """ - d = sqeuclidean(u, v) + Computes the squared Euclidean distance between two n-vectors u and v, + which is defined as - Computes the squared Euclidean distance between two n-vectors u and v, - (||u-v||_2)^2. + .. math:: + + {||u-v||}_2^2. + + + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. + + :Returns: + d : double + The squared Euclidean distance between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -108,10 +205,22 @@ def cosine(u, v): """ - d = cosine(u, v) + Computes the Cosine distance between two n-vectors u and v, which + is defined as - Computes the Cosine distance between two n-vectors u and v, - (1-uv^T)/(||u||_2 * ||v||_2). + .. math:: + + \frac{1-uv^T}/\frac{||u||_2 ||v||_2}. + + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. + + :Returns: + d : double + The Cosine distance between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -120,16 +229,26 @@ def correlation(u, v): """ - d = correlation(u, v) + Computes the correlation distance between two n-vectors ``u`` and + ``v``, which is defined as - Computes the correlation distance between two n-vectors u and v, + .. math:: - 1 - (u - n|u|_1)(v - n|v|_1)^T - --------------------------------- , - |(u - n|u|_1)|_2 |(v - n|v|_1)|^T + \frac{1 - (u - n{|u|}_1){(v - n{|v|}_1)}^T} + {{|(u - n{|u|}_1)|}_2 {|(v - n{|v|}_1)|}^T} - where |*|_1 is the Manhattan norm and n is the common dimensionality - of the vectors. + where :math:`$|*|_1$` is the Manhattan norm and ``n`` is the + common dimensionality of the vectors. + + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. + + :Returns: + d : double + The correlation distance between vectors ``u`` and ``v``. """ umu = u.mean() vmu = v.mean() @@ -141,19 +260,28 @@ def hamming(u, v): """ - d = hamming(u, v) + Computes the Hamming distance between two n-vectors ``u`` and + ``v``, which is simply the proportion of disagreeing components in + ``u`` and ``v``. If ``u`` and ``v`` are boolean vectors, the Hamming + distance is - Computes the Hamming distance between two n-vectors u and v, - which is simply the proportion of disagreeing components in u - and v. If u and v are boolean vectors, the hamming distance is + .. math: - (c_{01} + c_{10}) / n + \frac{c_{01} + c_{10}}{n} - where c_{ij} is the number of occurrences of + where :math:`$c_{ij}$` is the number of occurrences of + :math:`$\mathtt{u[k]}` = i$ and :math:`$\mathtt{v[k]} = j$` for + :math:`$k < n$`. - u[k] == i and v[k] == j + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. - for k < n. + :Returns: + d : double + The Hamming distance between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -161,20 +289,27 @@ def jaccard(u, v): """ - d = jaccard(u, v) + Computes the Jaccard-Needham dissimilarity between two boolean + n-vectors u and v, which is - Computes the Jaccard-Needham dissimilarity between two boolean - n-vectors u and v, which is + .. math:: - c_{TF} + c_{FT} - ------------------------ - c_{TT} + c_{FT} + c_{TF} + \frac{c_{TF} + c_{FT}} + {c_{TT} + c_{FT} + c_{TF}} - where c_{ij} is the number of occurrences of + where :math:`$c_{ij}$` is the number of occurrences of + :math:`$\mathtt{u[k]}` = i$ and :math:`$\mathtt{v[k]} = j$` for + :math:`$k < n$`. - u[k] == i and v[k] == j + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. - for k < n. + :Returns: + d : double + The Jaccard distance between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -184,20 +319,27 @@ def kulsinski(u, v): """ - d = kulsinski(u, v) + Computes the Kulsinski dissimilarity between two boolean n-vectors + u and v, which is defined as - Computes the Kulsinski dissimilarity between two boolean n-vectors - u and v, which is + .. math: - c_{TF} + c_{FT} - c_{TT} + n - ---------------------------- - c_{FT} + c_{TF} + n + \frac{c_{TF} + c_{FT} - c_{TT} + n} + {c_{FT} + c_{TF} + n} - where c_{ij} is the number of occurrences of + where :math:`$c_{ij}$` is the number of occurrences of + :math:`$\mathtt{u[k]}` = i$ and :math:`$\mathtt{v[k]} = j$` for + :math:`$k < n$`. - u[k] == i and v[k] == j + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. - for k < n. + :Returns: + d : double + The Kulsinski distance between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -208,11 +350,20 @@ def seuclidean(u, v, V): """ - d = seuclidean(u, v, V) + Returns the standardized Euclidean distance between two n-vectors + ``u`` and ``v``. ``V`` is an m-dimensional vector of component + variances. It is usually computed among a larger collection + vectors. - Returns the standardized Euclidean distance between two - n-vectors u and v. V is a m-dimensional vector of component - variances. It is usually computed among a larger collection vectors. + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. + + :Returns: + d : double + The standardized Euclidean distance between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -223,10 +374,22 @@ def cityblock(u, v): """ - d = cityblock(u, v) + Computes the Manhattan distance between two n-vectors u and v, + which is defined as - Computes the Manhattan distance between two n-vectors u and v, - \sum {u_i-v_i}. + .. math: + + \sum_i {u_i-v_i}. + + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. + + :Returns: + d : double + The City Block distance between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -234,11 +397,23 @@ def mahalanobis(u, v, VI): """ - d = mahalanobis(u, v, VI) + Computes the Mahalanobis distance between two n-vectors ``u`` and ``v``, + which is defiend as - Computes the Mahalanobis distance between two n-vectors u and v, - (u-v)VI(u-v)^T - where VI is the inverse covariance matrix. + .. math: + (u-v)V^{-1}(u-v)^T + + where ``VI`` is the inverse covariance matrix :math:`$V^{-1}$`. + + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. + + :Returns: + d : double + The Mahalanobis distance between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -247,10 +422,21 @@ def chebyshev(u, v): """ - d = chebyshev(u, v) + Computes the Chebyshev distance between two n-vectors u and v, + which is defined as - Computes the Chebyshev distance between two n-vectors u and v, - \max {|u_i-v_i|}. + .. math: + \max_i {|u_i-v_i|}. + + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. + + :Returns: + d : double + The Chebyshev distance between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -258,10 +444,22 @@ def braycurtis(u, v): """ - d = braycurtis(u, v) + Computes the Bray-Curtis distance between two n-vectors ``u`` and + ``v``, which is defined as - Computes the Bray-Curtis distance between two n-vectors u and v, - \sum{|u_i-v_i|} / \sum{|u_i+v_i|}. + .. math: + + \sum{|u_i-v_i|} / \sum{|u_i+v_i|}. + + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. + + :Returns: + d : double + The Bray-Curtis distance between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -269,10 +467,24 @@ def canberra(u, v): """ - d = canberra(u, v) + Computes the Canberra distance between two n-vectors u and v, + which is defined as - Computes the Canberra distance between two n-vectors u and v, - \sum{|u_i-v_i|} / \sum{|u_i|+|v_i}. + .. math: + + \frac{\sum_i {|u_i-v_i|}} + {\sum_i {|u_i|+|v_i|}}. + + + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. + + :Returns: + d : double + The Canberra distance between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -318,20 +530,28 @@ def yule(u, v): """ - d = yule(u, v) - Computes the Yule dissimilarity between two boolean n-vectors u and v, + Computes the Yule dissimilarity between two boolean n-vectors u and v, + which is defined as - R - --------------------- - c_{TT} + c_{FF} + R/2 - where c_{ij} is the number of occurrences of + .. math: - u[k] == i and v[k] == j + \frac{R} + \frac{c_{TT} + c_{FF} + \frac{R}{2}} - for k < n, and + where :math:`$c_{ij}$` is the number of occurrences of + :math:`$\mathtt{u[k]}` = i$ and :math:`$\mathtt{v[k]} = j$` for + :math:`$k < n$` and :math:`$R = 2.0 * (c_{TF} + c_{FT})$`. - R = 2.0 * (c_{TF} + c_{FT}). + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. + + :Returns: + d : double + The Yule dissimilarity between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -341,18 +561,26 @@ def matching(u, v): """ - d = matching(u, v) + Computes the Matching dissimilarity between two boolean n-vectors + u and v, which is defined as - Computes the Matching dissimilarity between two boolean n-vectors - u and v, which is + .. math: - (c_{TF} + c_{FT}) / n + \frac{c_{TF} + c_{FT}}{n} - where c_{ij} is the number of occurrences of + where :math:`$c_{ij}$` is the number of occurrences of + :math:`$\mathtt{u[k]}` = i$ and :math:`$\mathtt{v[k]} = j$` for + :math:`$k < n$`. - u[k] == i and v[k] == j + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. - for k < n. + :Returns: + d : double + The Matching dissimilarity between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -361,20 +589,27 @@ def dice(u, v): """ - d = dice(u, v) + Computes the Dice dissimilarity between two boolean n-vectors + ``u`` and ``v``, which is - Computes the Dice dissimilarity between two boolean n-vectors - u and v, which is + .. math: - c_{TF} + c_{FT} - ---------------------------- - 2 * c_{TT} + c_{FT} + c_{TF} + \frac{c_{TF} + c_{FT} + {2c_{TT} + c_{FT} + c_{TF}} - where c_{ij} is the number of occurrences of + where :math:`$c_{ij}$` is the number of occurrences of + :math:`$\mathtt{u[k]}` = i$ and :math:`$\mathtt{v[k]} = j$` for + :math:`$k < n$`. - u[k] == i and v[k] == j + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. - for k < n. + :Returns: + d : double + The Dice dissimilarity between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -387,23 +622,27 @@ def rogerstanimoto(u, v): """ - d = rogerstanimoto(u, v) + Computes the Rogers-Tanimoto dissimilarity between two boolean + n-vectors ``u`` and ``v``, which is defined as - Computes the Rogers-Tanimoto dissimilarity between two boolean - n-vectors u and v, + .. math: + \frac{R} + {c_{TT} + c_{FF} + R} - R - ------------------- - c_{TT} + c_{FF} + R + where :math:`$c_{ij}$` is the number of occurrences of + :math:`$\mathtt{u[k]}` = i$ and :math:`$\mathtt{v[k]} = j$` for + :math:`$k < n$` and :math:`$R = 2(c_{TF} + c_{FT})$`. - where c_{ij} is the number of occurrences of + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. - u[k] == i and v[k] == j - - for k < n, and - - R = 2.0 * (c_{TF} + c_{FT}). - + :Returns: + d : double + The Rogers-Tanimoto dissimilarity between vectors + ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -412,11 +651,27 @@ def russellrao(u, v): """ - d = russellrao(u, v) + Computes the Russell-Rao dissimilarity between two boolean n-vectors + ``u`` and ``v``, which is defined as - Computes the Russell-Rao dissimilarity between two boolean n-vectors - u and v, (n - c_{TT}) / n where c_{ij} is the number of occurrences - of u[k] == i and v[k] == j for k < n. + .. math: + + \frac{n - c_{TT}} + {n} + + where :math:`$c_{ij}$` is the number of occurrences of + :math:`$\mathtt{u[k]}` = i$ and :math:`$\mathtt{v[k]} = j$` for + :math:`$k < n$`. + + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. + + :Returns: + d : double + The Russell-Rao dissimilarity between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -428,12 +683,28 @@ def sokalmichener(u, v): """ - d = sokalmichener(u, v) + Computes the Sokal-Michener dissimilarity between two boolean vectors + ``u`` and ``v``, which is defined as - Computes the Sokal-Michener dissimilarity between two boolean vectors - u and v, 2R / (S + 2R) where c_{ij} is the number of occurrences of - u[k] == i and v[k] == j for k < n and R = 2 * (c_{TF} + c{FT}) and - S = c_{FF} + c_{TT}. + .. math: + + \frac{2R} + {S + 2R} + + where :math:`$c_{ij}$` is the number of occurrences of + :math:`$\mathtt{u[k]}` = i$ and :math:`$\mathtt{v[k]} = j$` for + :math:`$k < n$`, :math:`$R = 2 * (c_{TF} + c{FT})$` and + :math:`$S = c_{FF} + c_{TT}$`. + + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. + + :Returns: + d : double + The Sokal-Michener dissimilarity between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -448,11 +719,27 @@ def sokalsneath(u, v): """ - d = sokalsneath(u, v) + Computes the Sokal-Sneath dissimilarity between two boolean vectors + ``u`` and ``v``, - Computes the Sokal-Sneath dissimilarity between two boolean vectors - u and v, 2R / (c_{TT} + 2R) where c_{ij} is the number of occurrences - of u[k] == i and v[k] == j for k < n and R = 2 * (c_{TF} + c{FT}). + .. math: + + \frac{2R} + {c_{TT} + 2R} + + where :math:`$c_{ij}$` is the number of occurrences of + :math:`$\mathtt{u[k]}` = i$ and :math:`$\mathtt{v[k]} = j$` for + :math:`$k < n$` and :math:`$R = 2(c_{TF} + c{FT})$`. + + :Parameters: + u : ndarray + An :math:`n`-dimensional vector. + v : ndarray + An :math:`n`-dimensional vector. + + :Returns: + d : double + The Sokal-Sneath dissimilarity between vectors ``u`` and ``v``. """ u = np.asarray(u) v = np.asarray(v) @@ -465,176 +752,211 @@ def pdist(X, metric='euclidean', p=2, V=None, VI=None): - """ Y = pdist(X, method='euclidean', p=2) + """ + Computes the distance between m original observations in + n-dimensional space. Returns a condensed distance matrix Y. For + each :math:`$i$` and :math:`$j$` (where :math:`$i=1. + 1. ``Y = pdist(X, 'euclidean')`` - 3. Y = pdist(X, 'cityblock') + Computes the distance between m points using Euclidean distance + (2-norm) as the distance metric between the points. The points + are arranged as m n-dimensional row vectors in the matrix X. - Computes the city block or Manhattan distance between the - points. + 2. ``Y = pdist(X, 'minkowski', p)`` - 4. Y = pdist(X, 'seuclidean', V=None) + Computes the distances using the Minkowski distance + :math:`$||u-v||_p$` (p-norm) where :math:`$p \geq 1$`. - Computes the standardized Euclidean distance. The standardized - Euclidean distance between two n-vectors u and v is + 3. ``Y = pdist(X, 'cityblock')`` - sqrt(\sum {(u_i-v_i)^2 / V[x_i]}). + Computes the city block or Manhattan distance between the + points. - V is the variance vector; V[i] is the variance computed over all + 4. ``Y = pdist(X, 'seuclidean', V=None)`` + + Computes the standardized Euclidean distance. The standardized + Euclidean distance between two n-vectors ``u`` and ``v`` is + + .. math: + + sqrt(\sum {(u_i-v_i)^2 / V[x_i]}). + + V is the variance vector; V[i] is the variance computed over all the i'th components of the points. If not passed, it is automatically computed. - 5. Y = pdist(X, 'sqeuclidean') + 5. ``Y = pdist(X, 'sqeuclidean')`` - Computes the squared Euclidean distance ||u-v||_2^2 between - the vectors. + Computes the squared Euclidean distance ||u-v||_2^2 between + the vectors. - 6. Y = pdist(X, 'cosine') + 6. ``Y = pdist(X, 'cosine')`` - Computes the cosine distance between vectors u and v, + Computes the cosine distance between vectors u and v, - 1 - uv^T - ----------- - |u|_2 |v|_2 + .. math: - where |*|_2 is the 2 norm of its argument *. + \frac{1 - uv^T} + {{|u|}_2 {|v|}_2} - 7. Y = pdist(X, 'correlation') + where |*|_2 is the 2 norm of its argument *. - Computes the correlation distance between vectors u and v. This is + 7. ``Y = pdist(X, 'correlation')`` - 1 - (u - n|u|_1)(v - n|v|_1)^T - --------------------------------- , - |(u - n|u|_1)|_2 |(v - n|v|_1)|^T + Computes the correlation distance between vectors u and v. This is - where |*|_1 is the Manhattan (or 1-norm) of its argument *, - and n is the common dimensionality of the vectors. + .. math: - 8. Y = pdist(X, 'hamming') + \frac{1 - (u - n{|u|}_1){(v - n{|v|}_1)}^T} + {{|(u - n{|u|}_1)|}_2 {|(v - n{|v|}_1)|}^T} - Computes the normalized Hamming distance, or the proportion - of those vector elements between two n-vectors u and v which - disagree. To save memory, the matrix X can be of type boolean. + where :math:`$|*|_1$` is the Manhattan (or 1-norm) of its + argument, and :math:`$n$` is the common dimensionality of the + vectors. - 9. Y = pdist(X, 'jaccard') + 8. ``Y = pdist(X, 'hamming')`` - Computes the Jaccard distance between the points. Given two - vectors, u and v, the Jaccard distance is the proportion of - those elements u_i and v_i that disagree where at least one - of them is non-zero. + Computes the normalized Hamming distance, or the proportion of + those vector elements between two n-vectors ``u`` and ``v`` + which disagree. To save memory, the matrix ``X`` can be of type + boolean. - 10. Y = pdist(X, 'chebyshev') + 9. ``Y = pdist(X, 'jaccard')`` - Computes the Chebyshev distance between the points. The - Chebyshev distance between two n-vectors u and v is the maximum - norm-1 distance between their respective elements. More - precisely, the distance is given by + Computes the Jaccard distance between the points. Given two + vectors, ``u`` and ``v``, the Jaccard distance is the + proportion of those elements ``u[i]`` and ``v[i]`` that + disagree where at least one of them is non-zero. - d(u,v) = max {|u_i-v_i|}. + 10. ``Y = pdist(X, 'chebyshev')`` - 11. Y = pdist(X, 'canberra') + Computes the Chebyshev distance between the points. The + Chebyshev distance between two n-vectors ``u`` and ``v`` is the + maximum norm-1 distance between their respective elements. More + precisely, the distance is given by - Computes the Canberra distance between the points. The - Canberra distance between two points u and v is + .. math: - |u_1-v_1| |u_2-v_2| |u_n-v_n| - d(u,v) = ----------- + ----------- + ... + ----------- - |u_1|+|v_1| |u_2|+|v_2| |u_n|+|v_n| + d(u,v) = max_i {|u_i-v_i|}. - 12. Y = pdist(X, 'braycurtis') + 11. ``Y = pdist(X, 'canberra')`` - Computes the Bray-Curtis distance between the points. The - Bray-Curtis distance between two points u and v is + Computes the Canberra distance between the points. The + Canberra distance between two points ``u`` and ``v`` is - |u_1-v_1| + |u_2-v_2| + ... + |u_n-v_n| - d(u,v) = --------------------------------------- - |u_1+v_1| + |u_2+v_2| + ... + |u_n+v_n| + .. math: - 13. Y = pdist(X, 'mahalanobis', VI=None) + d(u,v) = \sum_u {|u_i-v_i|} + {|u_i|+|v_i|} + - Computes the Mahalanobis distance between the points. The - Mahalanobis distance between two points u and v is - (u-v)(1/V)(u-v)^T - where (1/V) is the inverse covariance. If VI is not None, - VI will be used as the inverse covariance matrix. + 12. ``Y = pdist(X, 'braycurtis')`` - 14. Y = pdist(X, 'yule') + Computes the Bray-Curtis distance between the points. The + Bray-Curtis distance between two points ``u`` and ``v`` is - Computes the Yule distance between each pair of boolean - vectors. (see yule function documentation) - 15. Y = pdist(X, 'matching') + .. math: - Computes the matching distance between each pair of boolean - vectors. (see matching function documentation) + d(u,v) = \frac{\sum_i {u_i-v_i}} + {\sum_i {u_i+v_i}} - 16. Y = pdist(X, 'dice') + 13. ``Y = pdist(X, 'mahalanobis', VI=None)`` - Computes the Dice distance between each pair of boolean - vectors. (see dice function documentation) + Computes the Mahalanobis distance between the points. The + Mahalanobis distance between two points ``u`` and ``v`` is + :math:`$(u-v)(1/V)(u-v)^T$` where :math:`$(1/V)$` (the ``VI`` + variable) is the inverse covariance. If ``VI`` is not None, + ``VI`` will be used as the inverse covariance matrix. - 17. Y = pdist(X, 'kulsinski') + 14. ``Y = pdist(X, 'yule')`` - Computes the Kulsinski distance between each pair of - boolean vectors. (see kulsinski function documentation) + Computes the Yule distance between each pair of boolean + vectors. (see yule function documentation) - 17. Y = pdist(X, 'rogerstanimoto') + 15. ``Y = pdist(X, 'matching')`` - Computes the Rogers-Tanimoto distance between each pair of - boolean vectors. (see rogerstanimoto function documentation) + Computes the matching distance between each pair of boolean + vectors. (see matching function documentation) - 18. Y = pdist(X, 'russellrao') + 16. ``Y = pdist(X, 'dice')`` - Computes the Russell-Rao distance between each pair of - boolean vectors. (see russellrao function documentation) + Computes the Dice distance between each pair of boolean + vectors. (see dice function documentation) - 19. Y = pdist(X, 'sokalmichener') + 17. ``Y = pdist(X, 'kulsinski')`` - Computes the Sokal-Michener distance between each pair of - boolean vectors. (see sokalmichener function documentation) + Computes the Kulsinski distance between each pair of + boolean vectors. (see kulsinski function documentation) - 20. Y = pdist(X, 'sokalsneath') + 18. ``Y = pdist(X, 'rogerstanimoto')`` - Computes the Sokal-Sneath distance between each pair of - boolean vectors. (see sokalsneath function documentation) + Computes the Rogers-Tanimoto distance between each pair of + boolean vectors. (see rogerstanimoto function documentation) - 21. Y = pdist(X, f) + 19. ``Y = pdist(X, 'russellrao')`` - Computes the distance between all pairs of vectors in X - using the user supplied 2-arity function f. For example, - Euclidean distance between the vectors could be computed - as follows, + Computes the Russell-Rao distance between each pair of + boolean vectors. (see russellrao function documentation) - dm = pdist(X, (lambda u, v: np.sqrt(((u-v)*(u-v).T).sum()))) + 20. ``Y = pdist(X, 'sokalmichener')`` - Note that you should avoid passing a reference to one of - the distance functions defined in this library. For example, + Computes the Sokal-Michener distance between each pair of + boolean vectors. (see sokalmichener function documentation) - dm = pdist(X, sokalsneath) + 21. ``Y = pdist(X, 'sokalsneath')`` - would calculate the pair-wise distances between the vectors - in X using the Python function sokalsneath. This would result - in sokalsneath being called {n \choose 2} times, which is - inefficient. Instead, the optimized C version is more - efficient, and we call it using the following syntax. + Computes the Sokal-Sneath distance between each pair of + boolean vectors. (see sokalsneath function documentation) - dm = pdist(X, 'sokalsneath') + 22. ``Y = pdist(X, f)`` + + Computes the distance between all pairs of vectors in X + using the user supplied 2-arity function f. For example, + Euclidean distance between the vectors could be computed + as follows:: + + dm = pdist(X, (lambda u, v: np.sqrt(((u-v)*(u-v).T).sum()))) + + Note that you should avoid passing a reference to one of + the distance functions defined in this library. For example,:: + + dm = pdist(X, sokalsneath) + + would calculate the pair-wise distances between the vectors in + X using the Python function sokalsneath. This would result in + sokalsneath being called :math:`${n \choose 2}$` times, which + is inefficient. Instead, the optimized C version is more + efficient, and we call it using the following syntax.:: + + dm = pdist(X, 'sokalsneath') + """ # 21. Y = pdist(X, 'test_Y') # From scipy-svn at scipy.org Sat Aug 23 01:21:16 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Sat, 23 Aug 2008 00:21:16 -0500 (CDT) Subject: [Scipy-svn] r4666 - in trunk/scipy/cluster: . src tests Message-ID: <20080823052116.732D839C072@scipy.org> Author: damian.eads Date: 2008-08-23 00:21:05 -0500 (Sat, 23 Aug 2008) New Revision: 4666 Modified: trunk/scipy/cluster/distance.py trunk/scipy/cluster/hierarchy.py trunk/scipy/cluster/src/distance.c trunk/scipy/cluster/src/distance.h trunk/scipy/cluster/src/distance_wrap.c trunk/scipy/cluster/src/hierarchy.c trunk/scipy/cluster/src/hierarchy.h trunk/scipy/cluster/src/hierarchy_wrap.c trunk/scipy/cluster/tests/test_distance.py trunk/scipy/cluster/tests/test_hierarchy.py Log: Moved some remaining distance-related functions from scipy.distance to scipy.cluster. Modified: trunk/scipy/cluster/distance.py =================================================================== --- trunk/scipy/cluster/distance.py 2008-08-23 00:42:16 UTC (rev 4665) +++ trunk/scipy/cluster/distance.py 2008-08-23 05:21:05 UTC (rev 4666) @@ -7,36 +7,74 @@ stored in a rectangular array. +------------------+-------------------------------------------------+ +|*Function* | *Description* | ++------------------+-------------------------------------------------+ |pdist | computes distances between observation pairs. | +------------------+-------------------------------------------------+ +|squareform | converts a square distance matrix to a | +| | condensed one and vice versa. | ++------------------+-------------------------------------------------+ +Predicates for checking the validity of distance matrices, both +condensed and redundant. + ++------------------+-------------------------------------------------+ +|*Function* | *Description* | ++------------------+-------------------------------------------------+ +|is_valid_dm | checks for a valid distance matrix. | ++------------------+-------------------------------------------------+ +|is_valid_y | checks for a valid condensed distance matrix. ++------------------+-------------------------------------------------+ + Distance functions between two vectors ``u`` and ``v``. Computing distances over a large collection of vectors is inefficient for these functions. Use ``pdist`` for this purpose. +------------------+-------------------------------------------------+ -|braycurtis | the Bray-Curtis distance. | -|canberra | the Canberra distance. | -|chebyshev | the Chebyshev distance. | -|cityblock | the Manhattan distance. | -|correlation | the Correlation distance. | -|cosine | the Cosine distance. | -|dice | the Dice dissimilarity (boolean). | -|euclidean | the Euclidean distance. | -|hamming | the Hamming distance (boolean). | -|jaccard | the Jaccard distance (boolean). | -|kulsinski | the Kulsinski distance (boolean). | -|mahalanobis | the Mahalanobis distance. | -|matching | the matching dissimilarity (boolean). | -|minkowski | the Minkowski distance. | -|rogerstanimoto | the Rogers-Tanimoto dissimilarity (boolean). | -|russellrao | the Russell-Rao dissimilarity (boolean). | -|seuclidean | the normalized Euclidean distance. | -|sokalmichener | the Sokal-Michener dissimilarity (boolean). | -|sokalsneath | the Sokal-Sneath dissimilarity (boolean). | -|sqeuclidean | the squared Euclidean distance. | -|yule | the Yule dissimilarity (boolean). | +|*Function* | *Description* | +------------------+-------------------------------------------------+ +| braycurtis | the Bray-Curtis distance. | ++------------------+-------------------------------------------------+ +| canberra | the Canberra distance. | ++------------------+-------------------------------------------------+ +| chebyshev | the Chebyshev distance. | ++------------------+-------------------------------------------------+ +| cityblock | the Manhattan distance. | ++------------------+-------------------------------------------------+ +| correlation | the Correlation distance. | ++------------------+-------------------------------------------------+ +| cosine | the Cosine distance. | ++------------------+-------------------------------------------------+ +| dice | the Dice dissimilarity (boolean). | ++------------------+-------------------------------------------------+ +| euclidean | the Euclidean distance. | ++------------------+-------------------------------------------------+ +| hamming | the Hamming distance (boolean). | ++------------------+-------------------------------------------------+ +| jaccard | the Jaccard distance (boolean). | ++------------------+-------------------------------------------------+ +| kulsinski | the Kulsinski distance (boolean). | ++------------------+-------------------------------------------------+ +| mahalanobis | the Mahalanobis distance. | ++------------------+-------------------------------------------------+ +| matching | the matching dissimilarity (boolean). | ++------------------+-------------------------------------------------+ +| minkowski | the Minkowski distance. | ++------------------+-------------------------------------------------+ +| rogerstanimoto | the Rogers-Tanimoto dissimilarity (boolean). | ++------------------+-------------------------------------------------+ +| russellrao | the Russell-Rao dissimilarity (boolean). | ++------------------+-------------------------------------------------+ +| seuclidean | the normalized Euclidean distance. | ++------------------+-------------------------------------------------+ +| sokalmichener | the Sokal-Michener dissimilarity (boolean). | ++------------------+-------------------------------------------------+ +| sokalsneath | the Sokal-Sneath dissimilarity (boolean). | ++------------------+-------------------------------------------------+ +| sqeuclidean | the squared Euclidean distance. | ++------------------+-------------------------------------------------+ +| yule | the Yule dissimilarity (boolean). | ++------------------+-------------------------------------------------+ References @@ -1161,3 +1199,296 @@ else: raise TypeError('2nd argument metric must be a string identifier or a function.') return dm +def squareform(X, force="no", checks=True): + """ + Converts a vector-form distance vector to a square-form distance + matrix, and vice-versa. + + :Parameters: + X : ndarray + Either a condensed or redundant distance matrix. + + :Returns: + Y : ndarray + If a condensed distance matrix is passed, a redundant + one is returned, or if a redundant one is passed, a + condensed distance matrix is returned. + + force : string + As with MATLAB(TM), if force is equal to 'tovector' or + 'tomatrix', the input will be treated as a distance matrix + or distance vector respectively. + + checks : bool + If ``checks`` is set to ``False``, no checks will be made + for matrix symmetry nor zero diagonals. This is useful if + it is known that ``X - X.T1`` is small and ``diag(X)`` is + close to zero. These values are ignored any way so they do + not disrupt the squareform transformation. + + + Calling Conventions + ------------------- + + 1. v = squareform(X) + + Given a square d by d symmetric distance matrix ``X``, + ``v=squareform(X)`` returns a :math:`$d*(d-1)/2$` (or + `${n \choose 2}$`) sized vector v. + + v[{n \choose 2}-{n-i \choose 2} + (j-i-1)] is the distance + between points i and j. If X is non-square or asymmetric, an error + is returned. + + X = squareform(v) + + Given a d*d(-1)/2 sized v for some integer d>=2 encoding distances + as described, X=squareform(v) returns a d by d distance matrix X. The + X[i, j] and X[j, i] values are set to + v[{n \choose 2}-{n-i \choose 2} + (j-u-1)] and all + diagonal elements are zero. + + """ + + X = _convert_to_double(np.asarray(X)) + + if not np.issubsctype(X, np.double): + raise TypeError('A double array must be passed.') + + s = X.shape + + # X = squareform(v) + if len(s) == 1 and force != 'tomatrix': + if X.shape[0] == 0: + return np.zeros((1,1), dtype=np.double) + + # Grab the closest value to the square root of the number + # of elements times 2 to see if the number of elements + # is indeed a binomial coefficient. + d = int(np.ceil(np.sqrt(X.shape[0] * 2))) + + # Check that v is of valid dimensions. + if d * (d - 1) / 2 != int(s[0]): + raise ValueError('Incompatible vector size. It must be a binomial coefficient n choose 2 for some integer n >= 2.') + + # Allocate memory for the distance matrix. + M = np.zeros((d, d), dtype=np.double) + + # Since the C code does not support striding using strides. + # The dimensions are used instead. + [X] = _copy_arrays_if_base_present([X]) + + # Fill in the values of the distance matrix. + _distance_wrap.to_squareform_from_vector_wrap(M, X) + + # Return the distance matrix. + M = M + M.transpose() + return M + elif len(s) != 1 and force.lower() == 'tomatrix': + raise ValueError("Forcing 'tomatrix' but input X is not a distance vector.") + elif len(s) == 2 and force.lower() != 'tovector': + if s[0] != s[1]: + raise ValueError('The matrix argument must be square.') + if checks: + if np.sum(np.sum(X == X.transpose())) != np.product(X.shape): + raise ValueError('The distance matrix array must be symmetrical.') + if (X.diagonal() != 0).any(): + raise ValueError('The distance matrix array must have zeros along the diagonal.') + + # One-side of the dimensions is set here. + d = s[0] + + if d <= 1: + return np.array([], dtype=np.double) + + # Create a vector. + v = np.zeros(((d * (d - 1) / 2),), dtype=np.double) + + # Since the C code does not support striding using strides. + # The dimensions are used instead. + [X] = _copy_arrays_if_base_present([X]) + + # Convert the vector to squareform. + _distance_wrap.to_vector_from_squareform_wrap(X, v) + return v + elif len(s) != 2 and force.lower() == 'tomatrix': + raise ValueError("Forcing 'tomatrix' but input X is not a distance vector.") + else: + raise ValueError('The first argument must be one or two dimensional array. A %d-dimensional array is not permitted' % len(s)) + +def is_valid_dm(D, tol=0.0, throw=False, name="D", warning=False): + """ + Returns True if the variable D passed is a valid distance matrix. + Distance matrices must be 2-dimensional numpy arrays containing + doubles. They must have a zero-diagonal, and they must be symmetric. + + :Parameters: + D : ndarray + The candidate object to test for validity. + tol : double + The distance matrix should be symmetric. tol is the maximum + difference between the :math:`$ij$`th entry and the + :math:`$ji$`th entry for the distance metric to be + considered symmetric. + throw : bool + An exception is thrown if the distance matrix passed is not + valid. + name : string + the name of the variable to checked. This is useful ifa + throw is set to ``True`` so the offending variable can be + identified in the exception message when an exception is + thrown. + warning : boolx + Instead of throwing an exception, a warning message is + raised. + + :Returns: + Returns ``True`` if the variable ``D`` passed is a valid + distance matrix. Small numerical differences in ``D`` and + ``D.T`` and non-zeroness of the diagonal are ignored if they are + within the tolerance specified by ``tol``. + """ + D = np.asarray(D) + valid = True + try: + if type(D) != np.ndarray: + if name: + raise TypeError('\'%s\' passed as a distance matrix is not a numpy array.' % name) + else: + raise TypeError('Variable is not a numpy array.') + s = D.shape + if D.dtype != np.double: + if name: + raise TypeError('Distance matrix \'%s\' must contain doubles (double).' % name) + else: + raise TypeError('Distance matrix must contain doubles (double).') + if len(D.shape) != 2: + if name: + raise ValueError('Distance matrix \'%s\' must have shape=2 (i.e. be two-dimensional).' % name) + else: + raise ValueError('Distance matrix must have shape=2 (i.e. be two-dimensional).') + if tol == 0.0: + if not (D == D.T).all(): + if name: + raise ValueError('Distance matrix \'%s\' must be symmetric.' % name) + else: + raise ValueError('Distance matrix must be symmetric.') + if not (D[xrange(0, s[0]), xrange(0, s[0])] == 0).all(): + if name: + raise ValueError('Distance matrix \'%s\' diagonal must be zero.' % name) + else: + raise ValueError('Distance matrix diagonal must be zero.') + else: + if not (D - D.T <= tol).all(): + if name: + raise ValueError('Distance matrix \'%s\' must be symmetric within tolerance %d.' % (name, tol)) + else: + raise ValueError('Distance matrix must be symmetric within tolerance %5.5f.' % tol) + if not (D[xrange(0, s[0]), xrange(0, s[0])] <= tol).all(): + if name: + raise ValueError('Distance matrix \'%s\' diagonal must be close to zero within tolerance %5.5f.' % (name, tol)) + else: + raise ValueError('Distance matrix \'%s\' diagonal must be close to zero within tolerance %5.5f.' % tol) + except Exception, e: + if throw: + raise + if warning: + _warning(str(e)) + valid = False + return valid + +def is_valid_y(y, warning=False, throw=False, name=None): + """ + Returns ``True`` if the variable ``y`` passed is a valid condensed + distance matrix. Condensed distance matrices must be 1-dimensional + numpy arrays containing doubles. Their length must be a binomial + coefficient :math:`${n \choose 2}$` for some positive integer n. + + + :Parameters: + y : ndarray + The condensed distance matrix. + + warning : bool + Invokes a warning if the variable passed is not a valid + condensed distance matrix. The warning message explains why + the distance matrix is not valid. 'name' is used when + referencing the offending variable. + + throws : throw + Throws an exception if the variable passed is not a valid + condensed distance matrix. + + name : bool + Used when referencing the offending variable in the + warning or exception message. + + """ + y = np.asarray(y) + valid = True + try: + if type(y) != np.ndarray: + if name: + raise TypeError('\'%s\' passed as a condensed distance matrix is not a numpy array.' % name) + else: + raise TypeError('Variable is not a numpy array.') + if y.dtype != np.double: + if name: + raise TypeError('Condensed distance matrix \'%s\' must contain doubles (double).' % name) + else: + raise TypeError('Condensed distance matrix must contain doubles (double).') + if len(y.shape) != 1: + if name: + raise ValueError('Condensed distance matrix \'%s\' must have shape=1 (i.e. be one-dimensional).' % name) + else: + raise ValueError('Condensed distance matrix must have shape=1 (i.e. be one-dimensional).') + n = y.shape[0] + d = int(np.ceil(np.sqrt(n * 2))) + if (d*(d-1)/2) != n: + if name: + raise ValueError('Length n of condensed distance matrix \'%s\' must be a binomial coefficient, i.e. there must be a k such that (k \choose 2)=n)!' % name) + else: + raise ValueError('Length n of condensed distance matrix must be a binomial coefficient, i.e. there must be a k such that (k \choose 2)=n)!') + except Exception, e: + if throw: + raise + if warning: + _warning(str(e)) + valid = False + return valid + +def numobs_dm(D): + """ + Returns the number of original observations that correspond to a + square, redudant distance matrix D. + + :Parameters: + D : ndarray + The target distance matrix. + + :Returns: + The number of observations in the redundant distance matrix. + """ + D = np.asarray(D) + is_valid_dm(D, tol=np.inf, throw=True, name='D') + return D.shape[0] + +def numobs_y(Y): + """ + Returns the number of original observations that correspond to a + condensed distance matrix Y. + + :Parameters: + Y : ndarray + The number of original observations in the condensed + observation ``Y``. + + :Returns: + n : int + The number of observations in the condensed distance matrix + passed. + """ + Y = np.asarray(Y) + is_valid_y(Y, throw=True, name='Y') + d = int(np.ceil(np.sqrt(Y.shape[0] * 2))) + return d Modified: trunk/scipy/cluster/hierarchy.py =================================================================== --- trunk/scipy/cluster/hierarchy.py 2008-08-23 00:42:16 UTC (rev 4665) +++ trunk/scipy/cluster/hierarchy.py 2008-08-23 05:21:05 UTC (rev 4666) @@ -22,8 +22,6 @@ median the median/WPGMC algorithm. (alias) ward the Ward/incremental algorithm. (alias) - squareform converts a sq. D.M. to a condensed one and vice versa. - Statistic computations on hierarchies cophenet computes the cophenetic distance between leaves. @@ -46,10 +44,8 @@ Predicates - is_valid_dm checks for a valid distance matrix. is_valid_im checks for a valid inconsistency matrix. is_valid_linkage checks for a valid hierarchical clustering. - is_valid_y checks for a valid condensed distance matrix. is_isomorphic checks if two flat clusterings are isomorphic. is_monotonic checks if a linkage is monotonic. Z_y_correspond checks for validity of distance matrix given a linkage. @@ -57,8 +53,6 @@ Utility Functions numobs_dm # of observations in a distance matrix. - numobs_linkage # of observations in a linkage. - numobs_y # of observations in a condensed distance matrix. Legal stuff @@ -186,12 +180,6 @@ l = [_copy_array_if_base_present(a) for a in T] return l - -def copying(): - """ Displays the license for this package.""" - print _copyingtxt - return None - def _randdm(pnts): """ Generates a random distance matrix stored in condensed form. A pnts * (pnts - 1) / 2 sized vector is returned. @@ -204,53 +192,68 @@ def single(y): """ - Z = single(y) - Performs single/min/nearest linkage on the condensed distance - matrix Z. See linkage for more information on the return structure - and algorithm. + matrix ``y``. See ``linkage`` for more information on the return + structure and algorithm. - (a condensed alias for single) + :Parameters: + y : ndarray + The upper triangular of the distance matrix y. The result of + ``pdist`` is returned in this form. + + :Returns: + Z : ndarray + The linkage matrix. + """ return linkage(y, method='single', metric='euclidean') def complete(y): """ - Z = complete(y) - Performs complete complete/max/farthest point linkage on the - condensed distance matrix Z. See linkage for more information - on the return structure and algorithm. + condensed distance matrix ``y``. See ``linkage`` for more + information on the return structure and algorithm. - (a condensed alias for linkage) + :Parameters: + y : ndarray + The upper triangular of the distance matrix y. The result of + ``pdist`` is returned in this form. + """ return linkage(y, method='complete', metric='euclidean') def average(y): """ - Z = average(y) + Performs average/UPGMA linkage on the condensed distance matrix + ``y``. See ``linkage`` for more information on the return + structure and algorithm. - Performs average/UPGMA linkage on the condensed distance matrix Z. See - linkage for more information on the return structure and algorithm. - - (a condensed alias for linkage) + :Parameters: + y : ndarray + The upper triangular of the distance matrix y. The result of + ``pdist`` is returned in this form. """ return linkage(y, method='average', metric='euclidean') def weighted(y): """ - Z = weighted(y) + Performs weighted/WPGMA linkage on the condensed distance matrix + ``y``. See ``linkage`` for more information on the return + structure and algorithm. - Performs weighted/WPGMA linkage on the condensed distance matrix Z. - See linkage for more information on the return structure and - algorithm. - - (a condensed alias for linkage) + :Parameters: + y : ndarray + The upper triangular of the distance matrix y. The result of + ``pdist`` is returned in this form. """ return linkage(y, method='weighted', metric='euclidean') def centroid(y): """ + Performs centroid/UPGMC linkage. See ``linkage`` for more + information on the return structure and algorithm. + + Z = centroid(y) Performs centroid/UPGMC linkage on the condensed distance matrix Z. @@ -652,107 +655,6 @@ else: return nd -def squareform(X, force="no", checks=True): - """ - ... = squareform(...) - - Converts a vector-form distance vector to a square-form distance - matrix, and vice-versa. - - v = squareform(X) - - Given a square d by d symmetric distance matrix X, v=squareform(X) - returns a d*(d-1)/2 (or {n \choose 2}) sized vector v. - - v[{n \choose 2}-{n-i \choose 2} + (j-i-1)] is the distance - between points i and j. If X is non-square or asymmetric, an error - is returned. - - X = squareform(v) - - Given a d*d(-1)/2 sized v for some integer d>=2 encoding distances - as described, X=squareform(v) returns a d by d distance matrix X. The - X[i, j] and X[j, i] values are set to - v[{n \choose 2}-{n-i \choose 2} + (j-u-1)] and all - diagonal elements are zero. - - As with MATLAB(TM), if force is equal to 'tovector' or 'tomatrix', - the input will be treated as a distance matrix or distance vector - respectively. - - If checks is set to False, no checks will be made for matrix - symmetry nor zero diagonals. This is useful if it is known that - X - X.T is small and diag(X) is close to zero. These values are - ignored any way so they do not disrupt the squareform - transformation. - """ - - X = _convert_to_double(np.asarray(X)) - - if not np.issubsctype(X, np.double): - raise TypeError('A double array must be passed.') - - s = X.shape - - # X = squareform(v) - if len(s) == 1 and force != 'tomatrix': - if X.shape[0] == 0: - return np.zeros((1,1), dtype=np.double) - - # Grab the closest value to the square root of the number - # of elements times 2 to see if the number of elements - # is indeed a binomial coefficient. - d = int(np.ceil(np.sqrt(X.shape[0] * 2))) - - # Check that v is of valid dimensions. - if d * (d - 1) / 2 != int(s[0]): - raise ValueError('Incompatible vector size. It must be a binomial coefficient n choose 2 for some integer n >= 2.') - - # Allocate memory for the distance matrix. - M = np.zeros((d, d), dtype=np.double) - - # Since the C code does not support striding using strides. - # The dimensions are used instead. - [X] = _copy_arrays_if_base_present([X]) - - # Fill in the values of the distance matrix. - _hierarchy_wrap.to_squareform_from_vector_wrap(M, X) - - # Return the distance matrix. - M = M + M.transpose() - return M - elif len(s) != 1 and force.lower() == 'tomatrix': - raise ValueError("Forcing 'tomatrix' but input X is not a distance vector.") - elif len(s) == 2 and force.lower() != 'tovector': - if s[0] != s[1]: - raise ValueError('The matrix argument must be square.') - if checks: - if np.sum(np.sum(X == X.transpose())) != np.product(X.shape): - raise ValueError('The distance matrix array must be symmetrical.') - if (X.diagonal() != 0).any(): - raise ValueError('The distance matrix array must have zeros along the diagonal.') - - # One-side of the dimensions is set here. - d = s[0] - - if d <= 1: - return np.array([], dtype=np.double) - - # Create a vector. - v = np.zeros(((d * (d - 1) / 2),), dtype=np.double) - - # Since the C code does not support striding using strides. - # The dimensions are used instead. - [X] = _copy_arrays_if_base_present([X]) - - # Convert the vector to squareform. - _hierarchy_wrap.to_vector_from_squareform_wrap(X, v) - return v - elif len(s) != 2 and force.lower() == 'tomatrix': - raise ValueError("Forcing 'tomatrix' but input X is not a distance vector.") - else: - raise ValueError('The first argument must be one or two dimensional array. A %d-dimensional array is not permitted' % len(s)) - def _convert_to_bool(X): if X.dtype != np.bool: X = np.bool_(X) @@ -1035,140 +937,6 @@ valid = False return valid -def is_valid_y(y, warning=False, throw=False, name=None): - """ - is_valid_y(y) - - Returns True if the variable y passed is a valid condensed - distance matrix. Condensed distance matrices must be - 1-dimensional numpy arrays containing doubles. Their length - must be a binomial coefficient {n \choose 2} for some positive - integer n. - - is_valid_y(..., warning=True, name='V') - - Invokes a warning if the variable passed is not a valid condensed distance - matrix. The warning message explains why the distance matrix is not valid. - 'name' is used when referencing the offending variable. - - is_valid_y(..., throw=True, name='V') - - Throws an exception if the variable passed is not a valid condensed distance - matrix. The message explains why variable is not valid. 'name' is used when - referencing the offending variable. - - """ - y = np.asarray(y) - valid = True - try: - if type(y) != np.ndarray: - if name: - raise TypeError('\'%s\' passed as a condensed distance matrix is not a numpy array.' % name) - else: - raise TypeError('Variable is not a numpy array.') - if y.dtype != np.double: - if name: - raise TypeError('Condensed distance matrix \'%s\' must contain doubles (double).' % name) - else: - raise TypeError('Condensed distance matrix must contain doubles (double).') - if len(y.shape) != 1: - if name: - raise ValueError('Condensed distance matrix \'%s\' must have shape=1 (i.e. be one-dimensional).' % name) - else: - raise ValueError('Condensed distance matrix must have shape=1 (i.e. be one-dimensional).') - n = y.shape[0] - d = int(np.ceil(np.sqrt(n * 2))) - if (d*(d-1)/2) != n: - if name: - raise ValueError('Length n of condensed distance matrix \'%s\' must be a binomial coefficient, i.e. there must be a k such that (k \choose 2)=n)!' % name) - else: - raise ValueError('Length n of condensed distance matrix must be a binomial coefficient, i.e. there must be a k such that (k \choose 2)=n)!') - except Exception, e: - if throw: - raise - if warning: - _warning(str(e)) - valid = False - return valid - - -def is_valid_dm(D, tol=0.0, throw=False, name="D"): - """ - is_valid_dm(D) - - Returns True if the variable D passed is a valid distance matrix. - Distance matrices must be 2-dimensional numpy arrays containing - doubles. They must have a zero-diagonal, and they must be symmetric. - - is_valid_dm(D, tol) - - Returns True if the variable D passed is a valid distance matrix. - Small numerical differences in D and D.T and non-zeroness of the - diagonal are ignored if they are within the tolerance specified - by tol. - - is_valid_dm(..., warning=True, name='V') - - Invokes a warning if the variable passed is not a valid distance matrix. - The warning message explains why the distance matrix is not valid. 'name' - is used when referencing the offending variable. - - is_valid_dm(..., throw=True, name='V') - - Throws an exception if the varible passed is not valid. The message - explains why the variable is not valid. 'name' is used when referencing - the offending variable. - - """ - D = np.asarray(D) - valid = True - try: - if type(D) != np.ndarray: - if name: - raise TypeError('\'%s\' passed as a distance matrix is not a numpy array.' % name) - else: - raise TypeError('Variable is not a numpy array.') - s = D.shape - if D.dtype != np.double: - if name: - raise TypeError('Distance matrix \'%s\' must contain doubles (double).' % name) - else: - raise TypeError('Distance matrix must contain doubles (double).') - if len(D.shape) != 2: - if name: - raise ValueError('Distance matrix \'%s\' must have shape=2 (i.e. be two-dimensional).' % name) - else: - raise ValueError('Distance matrix must have shape=2 (i.e. be two-dimensional).') - if tol == 0.0: - if not (D == D.T).all(): - if name: - raise ValueError('Distance matrix \'%s\' must be symmetric.' % name) - else: - raise ValueError('Distance matrix must be symmetric.') - if not (D[xrange(0, s[0]), xrange(0, s[0])] == 0).all(): - if name: - raise ValueError('Distance matrix \'%s\' diagonal must be zero.' % name) - else: - raise ValueError('Distance matrix diagonal must be zero.') - else: - if not (D - D.T <= tol).all(): - if name: - raise ValueError('Distance matrix \'%s\' must be symmetric within tolerance %d.' % (name, tol)) - else: - raise ValueError('Distance matrix must be symmetric within tolerance %5.5f.' % tol) - if not (D[xrange(0, s[0]), xrange(0, s[0])] <= tol).all(): - if name: - raise ValueError('Distance matrix \'%s\' diagonal must be close to zero within tolerance %5.5f.' % (name, tol)) - else: - raise ValueError('Distance matrix \'%s\' diagonal must be close to zero within tolerance %5.5f.' % tol) - except Exception, e: - if throw: - raise - if warning: - _warning(str(e)) - valid = False - return valid - def numobs_linkage(Z): """ Returns the number of original observations that correspond to a @@ -1178,29 +946,6 @@ is_valid_linkage(Z, throw=True, name='Z') return (Z.shape[0] + 1) -def numobs_dm(D): - """ - numobs_dm(D) - - Returns the number of original observations that correspond to a - square, non-condensed distance matrix D. - """ - D = np.asarray(D) - is_valid_dm(D, tol=np.inf, throw=True, name='D') - return D.shape[0] - -def numobs_y(Y): - """ - numobs_y(Y) - - Returns the number of original observations that correspond to a - condensed distance matrix Y. - """ - Y = np.asarray(Y) - is_valid_y(Y, throw=True, name='Y') - d = int(np.ceil(np.sqrt(Y.shape[0] * 2))) - return d - def Z_y_correspond(Z, Y): """ yesno = Z_y_correspond(Z, Y) @@ -1213,7 +958,7 @@ """ Z = np.asarray(Z) Y = np.asarray(Y) - return numobs_y(Y) == numobs_Z(Z) + return numobs_y(Y) == numobs_linkage(Z) def fcluster(Z, t, criterion='inconsistent', depth=2, R=None, monocrit=None): """ Modified: trunk/scipy/cluster/src/distance.c =================================================================== --- trunk/scipy/cluster/src/distance.c 2008-08-23 00:42:16 UTC (rev 4665) +++ trunk/scipy/cluster/src/distance.c 2008-08-23 05:21:05 UTC (rev 4666) @@ -590,3 +590,29 @@ } } } + +void dist_to_squareform_from_vector(double *M, const double *v, int n) { + double *it; + const double *cit; + int i, j; + cit = v; + for (i = 0; i < n - 1; i++) { + it = M + (i * n) + i + 1; + for (j = i + 1; j < n; j++, it++, cit++) { + *it = *cit; + } + } +} + +void dist_to_vector_from_squareform(const double *M, double *v, int n) { + double *it; + const double *cit; + int i, j; + it = v; + for (i = 0; i < n - 1; i++) { + cit = M + (i * n) + i + 1; + for (j = i + 1; j < n; j++, it++, cit++) { + *it = *cit; + } + } +} Modified: trunk/scipy/cluster/src/distance.h =================================================================== --- trunk/scipy/cluster/src/distance.h 2008-08-23 00:42:16 UTC (rev 4665) +++ trunk/scipy/cluster/src/distance.h 2008-08-23 05:21:05 UTC (rev 4666) @@ -37,6 +37,8 @@ #ifndef _CPY_DISTANCE_H #define _CPY_DISTANCE_H +void dist_to_squareform_from_vector(double *M, const double *v, int n); +void dist_to_vector_from_squareform(const double *M, double *v, int n); void pdist_euclidean(const double *X, double *dm, int m, int n); void pdist_seuclidean(const double *X, const double *var, double *dm, int m, int n); Modified: trunk/scipy/cluster/src/distance_wrap.c =================================================================== --- trunk/scipy/cluster/src/distance_wrap.c 2008-08-23 00:42:16 UTC (rev 4665) +++ trunk/scipy/cluster/src/distance_wrap.c 2008-08-23 05:21:05 UTC (rev 4666) @@ -493,7 +493,45 @@ return Py_BuildValue(""); } +extern PyObject *to_squareform_from_vector_wrap(PyObject *self, PyObject *args) { + PyArrayObject *M_, *v_; + int n; + const double *v; + double *M; + if (!PyArg_ParseTuple(args, "O!O!", + &PyArray_Type, &M_, + &PyArray_Type, &v_)) { + return 0; + } + else { + M = (double*)M_->data; + v = (const double*)v_->data; + n = M_->dimensions[0]; + dist_to_squareform_from_vector(M, v, n); + } + return Py_BuildValue("d", 0.0); +} +extern PyObject *to_vector_from_squareform_wrap(PyObject *self, PyObject *args) { + PyArrayObject *M_, *v_; + int n; + double *v; + const double *M; + if (!PyArg_ParseTuple(args, "O!O!", + &PyArray_Type, &M_, + &PyArray_Type, &v_)) { + return 0; + } + else { + M = (const double*)M_->data; + v = (double*)v_->data; + n = M_->dimensions[0]; + dist_to_vector_from_squareform(M, v, n); + } + return Py_BuildValue("d", 0.0); +} + + static PyMethodDef _distanceWrapMethods[] = { {"pdist_bray_curtis_wrap", pdist_bray_curtis_wrap, METH_VARARGS}, {"pdist_canberra_wrap", pdist_canberra_wrap, METH_VARARGS}, @@ -516,6 +554,10 @@ {"pdist_sokalmichener_bool_wrap", pdist_sokalmichener_bool_wrap, METH_VARARGS}, {"pdist_sokalsneath_bool_wrap", pdist_sokalsneath_bool_wrap, METH_VARARGS}, {"pdist_yule_bool_wrap", pdist_yule_bool_wrap, METH_VARARGS}, + {"to_squareform_from_vector_wrap", + to_squareform_from_vector_wrap, METH_VARARGS}, + {"to_vector_from_squareform_wrap", + to_vector_from_squareform_wrap, METH_VARARGS}, {NULL, NULL} /* Sentinel - marks the end of this structure */ }; Modified: trunk/scipy/cluster/src/hierarchy.c =================================================================== --- trunk/scipy/cluster/src/hierarchy.c 2008-08-23 00:42:16 UTC (rev 4665) +++ trunk/scipy/cluster/src/hierarchy.c 2008-08-23 05:21:05 UTC (rev 4666) @@ -871,32 +871,6 @@ free(centroids); } -void dist_to_squareform_from_vector(double *M, const double *v, int n) { - double *it; - const double *cit; - int i, j; - cit = v; - for (i = 0; i < n - 1; i++) { - it = M + (i * n) + i + 1; - for (j = i + 1; j < n; j++, it++, cit++) { - *it = *cit; - } - } -} - -void dist_to_vector_from_squareform(const double *M, double *v, int n) { - double *it; - const double *cit; - int i, j; - it = v; - for (i = 0; i < n - 1; i++) { - cit = M + (i * n) + i + 1; - for (j = i + 1; j < n; j++, it++, cit++) { - *it = *cit; - } - } -} - void cpy_to_tree(const double *Z, cnode **tnodes, int n) { const double *row; cnode *node; Modified: trunk/scipy/cluster/src/hierarchy.h =================================================================== --- trunk/scipy/cluster/src/hierarchy.h 2008-08-23 00:42:16 UTC (rev 4665) +++ trunk/scipy/cluster/src/hierarchy.h 2008-08-23 05:21:05 UTC (rev 4666) @@ -86,9 +86,6 @@ typedef void (distfunc) (cinfo *info, int mini, int minj, int np, int n); -void dist_to_squareform_from_vector(double *M, const double *v, int n); -void dist_to_vector_from_squareform(const double *M, double *v, int n); - void inconsistency_calculation(const double *Z, double *R, int n, int d); void inconsistency_calculation_alt(const double *Z, double *R, int n, int d); Modified: trunk/scipy/cluster/src/hierarchy_wrap.c =================================================================== --- trunk/scipy/cluster/src/hierarchy_wrap.c 2008-08-23 00:42:16 UTC (rev 4665) +++ trunk/scipy/cluster/src/hierarchy_wrap.c 2008-08-23 05:21:05 UTC (rev 4666) @@ -304,7 +304,6 @@ return Py_BuildValue("d", 0.0); } - extern PyObject *chopmin_ns_i_wrap(PyObject *self, PyObject *args) { int mini, n; PyArrayObject *row; @@ -332,44 +331,7 @@ return Py_BuildValue("d", 0.0); } -extern PyObject *to_squareform_from_vector_wrap(PyObject *self, PyObject *args) { - PyArrayObject *M_, *v_; - int n; - const double *v; - double *M; - if (!PyArg_ParseTuple(args, "O!O!", - &PyArray_Type, &M_, - &PyArray_Type, &v_)) { - return 0; - } - else { - M = (double*)M_->data; - v = (const double*)v_->data; - n = M_->dimensions[0]; - dist_to_squareform_from_vector(M, v, n); - } - return Py_BuildValue("d", 0.0); -} -extern PyObject *to_vector_from_squareform_wrap(PyObject *self, PyObject *args) { - PyArrayObject *M_, *v_; - int n; - double *v; - const double *M; - if (!PyArg_ParseTuple(args, "O!O!", - &PyArray_Type, &M_, - &PyArray_Type, &v_)) { - return 0; - } - else { - M = (const double*)M_->data; - v = (double*)v_->data; - n = M_->dimensions[0]; - dist_to_vector_from_squareform(M, v, n); - } - return Py_BuildValue("d", 0.0); -} - extern PyObject *leaders_wrap(PyObject *self, PyObject *args) { PyArrayObject *Z_, *T_, *L_, *M_; int kk, n, res; @@ -408,10 +370,6 @@ {"linkage_euclid_wrap", linkage_euclid_wrap, METH_VARARGS}, {"linkage_wrap", linkage_wrap, METH_VARARGS}, {"prelist_wrap", prelist_wrap, METH_VARARGS}, - {"to_squareform_from_vector_wrap", - to_squareform_from_vector_wrap, METH_VARARGS}, - {"to_vector_from_squareform_wrap", - to_vector_from_squareform_wrap, METH_VARARGS}, {NULL, NULL} /* Sentinel - marks the end of this structure */ }; Modified: trunk/scipy/cluster/tests/test_distance.py =================================================================== --- trunk/scipy/cluster/tests/test_distance.py 2008-08-23 00:42:16 UTC (rev 4665) +++ trunk/scipy/cluster/tests/test_distance.py 2008-08-23 05:21:05 UTC (rev 4666) @@ -39,8 +39,8 @@ import numpy as np from numpy.testing import * -from scipy.cluster.hierarchy import squareform, linkage, from_mlab_linkage, numobs_dm, numobs_y, numobs_linkage -from scipy.cluster.distance import pdist, matching, jaccard, dice, sokalsneath, rogerstanimoto, russellrao, yule +from scipy.cluster.hierarchy import linkage, from_mlab_linkage, numobs_dm, numobs_y, numobs_linkage +from scipy.cluster.distance import squareform, pdist, matching, jaccard, dice, sokalsneath, rogerstanimoto, russellrao, yule #from scipy.cluster.hierarchy import pdist, euclidean @@ -946,3 +946,69 @@ def within_tol(a, b, tol): return np.abs(a - b).max() < tol + + +class TestSquareForm(TestCase): + + ################### squareform + def test_squareform_empty_matrix(self): + "Tests squareform on an empty matrix." + A = np.zeros((0,0)) + rA = squareform(np.array(A, dtype='double')) + self.failUnless(rA.shape == (0,)) + + def test_squareform_empty_vector(self): + v = np.zeros((0,)) + rv = squareform(np.array(v, dtype='double')) + self.failUnless(rv.shape == (1,1)) + self.failUnless(rv[0, 0] == 0) + + def test_squareform_1by1_matrix(self): + "Tests squareform on a 1x1 matrix." + A = np.zeros((1,1)) + rA = squareform(np.array(A, dtype='double')) + self.failUnless(rA.shape == (0,)) + + def test_squareform_one_vector(self): + "Tests squareform on a 1-D array, length=1." + v = np.ones((1,)) * 8.3 + rv = squareform(np.array(v, dtype='double')) + self.failUnless(rv.shape == (2,2)) + self.failUnless(rv[0,1] == 8.3) + self.failUnless(rv[1,0] == 8.3) + + def test_squareform_2by2_matrix(self): + "Tests squareform on a 2x2 matrix." + A = np.zeros((2,2)) + A[0,1]=0.8 + A[1,0]=0.8 + rA = squareform(np.array(A, dtype='double')) + self.failUnless(rA.shape == (1,)) + self.failUnless(rA[0] == 0.8) + + def test_squareform_multi_matrix(self): + "Tests squareform on a square matrices of multiple sizes." + for n in xrange(2, 5): + yield self.check_squareform_multi_matrix(n) + + def check_squareform_multi_matrix(self, n): + X = np.random.rand(n, 4) + Y = pdist(X) + self.failUnless(len(Y.shape) == 1) + A = squareform(Y) + Yr = squareform(A) + s = A.shape + k = 0 + if verbose >= 3: + print A.shape, Y.shape, Yr.shape + self.failUnless(len(s) == 2) + self.failUnless(len(Yr.shape) == 1) + self.failUnless(s[0] == s[1]) + for i in xrange(0, s[0]): + for j in xrange(i+1, s[1]): + if i != j: + #print i, j, k, A[i, j], Y[k] + self.failUnless(A[i, j] == Y[k]) + k += 1 + else: + self.failUnless(A[i, j] == 0) Modified: trunk/scipy/cluster/tests/test_hierarchy.py =================================================================== --- trunk/scipy/cluster/tests/test_hierarchy.py 2008-08-23 00:42:16 UTC (rev 4665) +++ trunk/scipy/cluster/tests/test_hierarchy.py 2008-08-23 05:21:05 UTC (rev 4666) @@ -39,8 +39,8 @@ import numpy as np from numpy.testing import * -from scipy.cluster.hierarchy import squareform, linkage, from_mlab_linkage, numobs_dm, numobs_y, numobs_linkage, inconsistent -from scipy.cluster.distance import pdist, matching, jaccard, dice, sokalsneath, rogerstanimoto, russellrao, yule +from scipy.cluster.hierarchy import linkage, from_mlab_linkage, numobs_dm, numobs_y, numobs_linkage, inconsistent +from scipy.cluster.distance import squareform, pdist, matching, jaccard, dice, sokalsneath, rogerstanimoto, russellrao, yule _tdist = np.array([[0, 662, 877, 255, 412, 996], [662, 0, 295, 468, 268, 400], @@ -86,71 +86,6 @@ load_testing_files() -class TestSquareForm(TestCase): - - ################### squareform - def test_squareform_empty_matrix(self): - "Tests squareform on an empty matrix." - A = np.zeros((0,0)) - rA = squareform(np.array(A, dtype='double')) - self.failUnless(rA.shape == (0,)) - - def test_squareform_empty_vector(self): - v = np.zeros((0,)) - rv = squareform(np.array(v, dtype='double')) - self.failUnless(rv.shape == (1,1)) - self.failUnless(rv[0, 0] == 0) - - def test_squareform_1by1_matrix(self): - "Tests squareform on a 1x1 matrix." - A = np.zeros((1,1)) - rA = squareform(np.array(A, dtype='double')) - self.failUnless(rA.shape == (0,)) - - def test_squareform_one_vector(self): - "Tests squareform on a 1-D array, length=1." - v = np.ones((1,)) * 8.3 - rv = squareform(np.array(v, dtype='double')) - self.failUnless(rv.shape == (2,2)) - self.failUnless(rv[0,1] == 8.3) - self.failUnless(rv[1,0] == 8.3) - - def test_squareform_2by2_matrix(self): - "Tests squareform on a 2x2 matrix." - A = np.zeros((2,2)) - A[0,1]=0.8 - A[1,0]=0.8 - rA = squareform(np.array(A, dtype='double')) - self.failUnless(rA.shape == (1,)) - self.failUnless(rA[0] == 0.8) - - def test_squareform_multi_matrix(self): - "Tests squareform on a square matrices of multiple sizes." - for n in xrange(2, 5): - yield self.check_squareform_multi_matrix(n) - - def check_squareform_multi_matrix(self, n): - X = np.random.rand(n, 4) - Y = pdist(X) - self.failUnless(len(Y.shape) == 1) - A = squareform(Y) - Yr = squareform(A) - s = A.shape - k = 0 - if verbose >= 3: - print A.shape, Y.shape, Yr.shape - self.failUnless(len(s) == 2) - self.failUnless(len(Yr.shape) == 1) - self.failUnless(s[0] == s[1]) - for i in xrange(0, s[0]): - for j in xrange(i+1, s[1]): - if i != j: - #print i, j, k, A[i, j], Y[k] - self.failUnless(A[i, j] == Y[k]) - k += 1 - else: - self.failUnless(A[i, j] == 0) - class TestNumObs(TestCase): ############## numobs_dm From scipy-svn at scipy.org Sat Aug 23 13:56:26 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Sat, 23 Aug 2008 12:56:26 -0500 (CDT) Subject: [Scipy-svn] r4667 - in trunk/scipy/cluster: . tests Message-ID: <20080823175626.DE9B139C021@scipy.org> Author: damian.eads Date: 2008-08-23 12:56:19 -0500 (Sat, 23 Aug 2008) New Revision: 4667 Modified: trunk/scipy/cluster/distance.py trunk/scipy/cluster/hierarchy.py trunk/scipy/cluster/tests/test_distance.py trunk/scipy/cluster/tests/test_hierarchy.py Log: Converted the scipy.cluster.hierarchy header so it conforms to RST. Fixed minor bug in test program when moving some distance-related functions from scipy.cluster.hierarchy to scipy.cluster.distance. Modified: trunk/scipy/cluster/distance.py =================================================================== --- trunk/scipy/cluster/distance.py 2008-08-23 05:21:05 UTC (rev 4666) +++ trunk/scipy/cluster/distance.py 2008-08-23 17:56:19 UTC (rev 4667) @@ -16,7 +16,8 @@ +------------------+-------------------------------------------------+ Predicates for checking the validity of distance matrices, both -condensed and redundant. +condensed and redundant. Also contained in this module are functions +for computing the number of observations in a distance matrix. +------------------+-------------------------------------------------+ |*Function* | *Description* | @@ -25,6 +26,8 @@ +------------------+-------------------------------------------------+ |is_valid_y | checks for a valid condensed distance matrix. +------------------+-------------------------------------------------+ +|numobs_dm # of observations in a distance matrix. ++------------------+-------------------------------------------------+ Distance functions between two vectors ``u`` and ``v``. Computing distances over a large collection of vectors is inefficient for these Modified: trunk/scipy/cluster/hierarchy.py =================================================================== --- trunk/scipy/cluster/hierarchy.py 2008-08-23 05:21:05 UTC (rev 4666) +++ trunk/scipy/cluster/hierarchy.py 2008-08-23 17:56:19 UTC (rev 4667) @@ -1,107 +1,152 @@ """ ------------------------------------------ -Hierarchical Clustering Library for Scipy - Copyright (C) Damian Eads, 2007-2008. - New BSD License ------------------------------------------ +Function Reference +------------------ -Flat cluster formation +These functions cut hierarchical clusterings into flat clusterings +or find the roots of the forest formed by a cut by providing the flat +cluster ids of each observation. - fcluster forms flat clusters from hierarchical clusters. - fclusterdata forms flat clusters directly from data. - leaders singleton root nodes for flat cluster. ++------------------+-------------------------------------------------+ +|*Function* | *Description* | ++------------------+-------------------------------------------------+ +|fcluster |forms flat clusters from hierarchical clusters. | ++------------------+-------------------------------------------------+ +|fclusterdata |forms flat clusters directly from data. | ++------------------+-------------------------------------------------+ +|leaders |singleton root nodes for flat cluster. | ++------------------+-------------------------------------------------+ -Agglomerative cluster formation +These are routines for agglomerative clustering. - linkage agglomeratively clusters original observations. - single the single/min/nearest algorithm. (alias) - complete the complete/max/farthest algorithm. (alias) - average the average/UPGMA algorithm. (alias) - weighted the weighted/WPGMA algorithm. (alias) - centroid the centroid/UPGMC algorithm. (alias) - median the median/WPGMC algorithm. (alias) - ward the Ward/incremental algorithm. (alias) ++------------------+-------------------------------------------------+ +|*Function* | *Description* | ++------------------+-------------------------------------------------+ +|linkage |agglomeratively clusters original observations. | ++------------------+-------------------------------------------------+ +|single |the single/min/nearest algorithm. (alias) | ++------------------+-------------------------------------------------+ +|complete |the complete/max/farthest algorithm. (alias) | ++------------------+-------------------------------------------------+ +|average |the average/UPGMA algorithm. (alias) | ++------------------+-------------------------------------------------+ +|weighted |the weighted/WPGMA algorithm. (alias) | ++------------------+-------------------------------------------------+ +|centroid |the centroid/UPGMC algorithm. (alias) | ++------------------+-------------------------------------------------+ +|median |the median/WPGMC algorithm. (alias) | ++------------------+-------------------------------------------------+ +|ward |the Ward/incremental algorithm. (alias) | ++------------------+-------------------------------------------------+ -Statistic computations on hierarchies +These routines compute statistics on hierarchies. - cophenet computes the cophenetic distance between leaves. - from_mlab_linkage converts a linkage produced by MATLAB(TM). - inconsistent the inconsistency coefficients for cluster. - maxinconsts the maximum inconsistency coefficient for each cluster. - maxdists the maximum distance for each cluster. - maxRstat the maximum specific statistic for each cluster. - to_mlab_linkage converts a linkage to one MATLAB(TM) can understand. ++------------------+-------------------------------------------------+ +|*Function* | *Description* | ++------------------+-------------------------------------------------+ +|cophenet |computes the cophenetic distance between leaves. | ++------------------+-------------------------------------------------+ +|from_mlab_linkage |converts a linkage produced by MATLAB(TM). | ++------------------+-------------------------------------------------+ +|inconsistent |the inconsistency coefficients for cluster. | ++------------------+-------------------------------------------------+ +|maxinconsts |the maximum inconsistency coefficient for each | +| |cluster. | ++------------------+-------------------------------------------------+ +|maxdists |the maximum distance for each cluster. | ++------------------+-------------------------------------------------+ +|maxRstat |the maximum specific statistic for each cluster. | ++------------------+-------------------------------------------------+ +|to_mlab_linkage |converts a linkage to one MATLAB(TM) can | +| |understand. | ++------------------+-------------------------------------------------+ -Visualization +Routines for visualizing flat clusters. - dendrogram visualizes linkages (requires matplotlib). ++------------------+-------------------------------------------------+ +|*Function* | *Description* | ++------------------+-------------------------------------------------+ +|dendrogram |visualizes linkages (requires matplotlib). | ++------------------+-------------------------------------------------+ -Tree representations of hierarchies +These are data structures and routines for representing hierarchies as +tree objects. - cnode represents cluster nodes in a cluster hierarchy. - lvlist a left-to-right traversal of the leaves. - totree represents a linkage matrix as a tree object. ++------------------+-------------------------------------------------+ +|*Function* | *Description* | ++------------------+-------------------------------------------------+ +|cnode |represents cluster nodes in a cluster hierarchy. | ++------------------+-------------------------------------------------+ +|lvlist |a left-to-right traversal of the leaves. | ++------------------+-------------------------------------------------+ +|totree |represents a linkage matrix as a tree object. | ++------------------+-------------------------------------------------+ -Predicates +These are predicates for checking the validity of linkage and +inconsistency matrices, both condensed and redundant. - is_valid_im checks for a valid inconsistency matrix. - is_valid_linkage checks for a valid hierarchical clustering. - is_isomorphic checks if two flat clusterings are isomorphic. - is_monotonic checks if a linkage is monotonic. - Z_y_correspond checks for validity of distance matrix given a linkage. ++------------------+-------------------------------------------------+ +|*Function* | *Description* | ++------------------+-------------------------------------------------+ +|is_valid_im |checks for a valid inconsistency matrix. | ++------------------+-------------------------------------------------+ +|is_valid_linkage |checks for a valid hierarchical clustering. | ++------------------+-------------------------------------------------+ +|is_isomorphic |checks if two flat clusterings are isomorphic. | ++------------------+-------------------------------------------------+ +|is_monotonic |checks if a linkage is monotonic. | ++------------------+-------------------------------------------------+ +|Z_y_correspond |checks for validity of distance matrix given a | +| |linkage. | ++------------------+-------------------------------------------------+ -Utility Functions - numobs_dm # of observations in a distance matrix. +* MATLAB and MathWorks are registered trademarks of The MathWorks, Inc. -Legal stuff +* Mathematica is a registered trademark of The Wolfram Research, Inc. - copying Displays the license for this package. +References +---------- - MATLAB and MathWorks are registered trademarks of The MathWorks, Inc. - Mathematica is a registered trademark of The Wolfram Research, Inc. +.. [Sta07] "Statistics toolbox." API Reference Documentation. The MathWorks. + http://www.mathworks.com/access/helpdesk/help/toolbox/stats/. + Accessed October 1, 2007. -References: +.. [Mti07] "Hierarchical clustering." API Reference Documentation. + The Wolfram Research, Inc. + http://reference.wolfram.com/mathematica/HierarchicalClustering/tutorial/HierarchicalClustering.html. + Accessed October 1, 2007. - [1] "Statistics toolbox." API Reference Documentation. The MathWorks. - http://www.mathworks.com/access/helpdesk/help/toolbox/stats/. - Accessed October 1, 2007. +.. [Gow69] Gower, JC and Ross, GJS. "Minimum Spanning Trees and Single Linkage + Cluster Analysis." Applied Statistics. 18(1): pp. 54--64. 1969. - [2] "Hierarchical clustering." API Reference Documentation. - The Wolfram Research, Inc. http://reference.wolfram.com/... - ...mathematica/HierarchicalClustering/tutorial/... - HierarchicalClustering.html. Accessed October 1, 2007. +.. [War63] Ward Jr, JH. "Hierarchical grouping to optimize an objective + function." Journal of the American Statistical Association. 58(301): + pp. 236--44. 1963. - [3] Gower, JC and Ross, GJS. "Minimum Spanning Trees and Single Linkage - Cluster Analysis." Applied Statistics. 18(1): pp. 54--64. 1969. +.. [Joh66] Johnson, SC. "Hierarchical clustering schemes." Psychometrika. + 32(2): pp. 241--54. 1966. - [4] Ward Jr, JH. "Hierarchical grouping to optimize an objective - function." Journal of the American Statistical Association. 58(301): - pp. 236--44. 1963. +.. [Sne62] Sneath, PH and Sokal, RR. "Numerical taxonomy." Nature. 193: pp. + 855--60. 1962. - [5] Johnson, SC. "Hierarchical clustering schemes." Psychometrika. - 32(2): pp. 241--54. 1966. +.. [Bat95] Batagelj, V. "Comparing resemblance measures." Journal of + Classification. 12: pp. 73--90. 1995. - [6] Sneath, PH and Sokal, RR. "Numerical taxonomy." Nature. 193: pp. - 855--60. 1962. +.. [Sok58] Sokal, RR and Michener, CD. "A statistical method for evaluating + systematic relationships." Scientific Bulletins. 38(22): + pp. 1409--38. 1958. - [7] Batagelj, V. "Comparing resemblance measures." Journal of - Classification. 12: pp. 73--90. 1995. +.. [Ede79] Edelbrock, C. "Mixture model tests of hierarchical clustering + algorithms: the problem of classifying everybody." Multivariate + Behavioral Research. 14: pp. 367--84. 1979. - [8] Sokal, RR and Michener, CD. "A statistical method for evaluating - systematic relationships." Scientific Bulletins. 38(22): - pp. 1409--38. 1958. +.. [Jai88] Jain, A., and Dubes, R., "Algorithms for Clustering Data." + Prentice-Hall. Englewood Cliffs, NJ. 1988. - [9] Edelbrock, C. "Mixture model tests of hierarchical clustering - algorithms: the problem of classifying everybody." Multivariate - Behavioral Research. 14: pp. 367--84. 1979. +.. [Fis36] Fisher, RA "The use of multiple measurements in taxonomic + problems." Annals of Eugenics, 7(2): 179-188. 1936 -[10] Jain, A., and Dubes, R., "Algorithms for Clustering Data." - Prentice-Hall. Englewood Cliffs, NJ. 1988. - -[11] Fisher, RA "The use of multiple measurements in taxonomic - problems." Annals of Eugenics, 7(2): 179-188. 1936 """ _copyingtxt=""" @@ -423,7 +468,7 @@ s = y.shape if len(s) == 1: - is_valid_y(y, throw=True, name='y') + distance.is_valid_y(y, throw=True, name='y') d = np.ceil(np.sqrt(s[0] * 2)) if method not in _cpy_non_euclid_methods.keys(): raise ValueError("Valid methods when the raw observations are omitted are 'single', 'complete', 'weighted', and 'average'.") @@ -719,7 +764,7 @@ Y = args[1] Ys = Y.shape - is_valid_y(Y, throw=True, name='Y') + distance.is_valid_y(Y, throw=True, name='Y') z = zz.mean() y = Y.mean() Modified: trunk/scipy/cluster/tests/test_distance.py =================================================================== --- trunk/scipy/cluster/tests/test_distance.py 2008-08-23 05:21:05 UTC (rev 4666) +++ trunk/scipy/cluster/tests/test_distance.py 2008-08-23 17:56:19 UTC (rev 4667) @@ -39,8 +39,8 @@ import numpy as np from numpy.testing import * -from scipy.cluster.hierarchy import linkage, from_mlab_linkage, numobs_dm, numobs_y, numobs_linkage -from scipy.cluster.distance import squareform, pdist, matching, jaccard, dice, sokalsneath, rogerstanimoto, russellrao, yule +from scipy.cluster.hierarchy import linkage, from_mlab_linkage, numobs_linkage +from scipy.cluster.distance import squareform, pdist, matching, jaccard, dice, sokalsneath, rogerstanimoto, russellrao, yule, numobs_dm, numobs_y #from scipy.cluster.hierarchy import pdist, euclidean Modified: trunk/scipy/cluster/tests/test_hierarchy.py =================================================================== --- trunk/scipy/cluster/tests/test_hierarchy.py 2008-08-23 05:21:05 UTC (rev 4666) +++ trunk/scipy/cluster/tests/test_hierarchy.py 2008-08-23 17:56:19 UTC (rev 4667) @@ -39,8 +39,8 @@ import numpy as np from numpy.testing import * -from scipy.cluster.hierarchy import linkage, from_mlab_linkage, numobs_dm, numobs_y, numobs_linkage, inconsistent -from scipy.cluster.distance import squareform, pdist, matching, jaccard, dice, sokalsneath, rogerstanimoto, russellrao, yule +from scipy.cluster.hierarchy import linkage, from_mlab_linkage, numobs_linkage, inconsistent +from scipy.cluster.distance import squareform, pdist, matching, jaccard, dice, sokalsneath, rogerstanimoto, russellrao, yule, numobs_dm, numobs_y _tdist = np.array([[0, 662, 877, 255, 412, 996], [662, 0, 295, 468, 268, 400], From scipy-svn at scipy.org Sat Aug 23 14:10:49 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Sat, 23 Aug 2008 13:10:49 -0500 (CDT) Subject: [Scipy-svn] r4668 - trunk/scipy/cluster Message-ID: <20080823181049.9A16239C05F@scipy.org> Author: damian.eads Date: 2008-08-23 13:10:44 -0500 (Sat, 23 Aug 2008) New Revision: 4668 Modified: trunk/scipy/cluster/distance.py trunk/scipy/cluster/hierarchy.py Log: Finished RSTifying linkage alias functions. Modified: trunk/scipy/cluster/distance.py =================================================================== --- trunk/scipy/cluster/distance.py 2008-08-23 17:56:19 UTC (rev 4667) +++ trunk/scipy/cluster/distance.py 2008-08-23 18:10:44 UTC (rev 4668) @@ -79,7 +79,6 @@ | yule | the Yule dissimilarity (boolean). | +------------------+-------------------------------------------------+ - References ---------- Modified: trunk/scipy/cluster/hierarchy.py =================================================================== --- trunk/scipy/cluster/hierarchy.py 2008-08-23 17:56:19 UTC (rev 4667) +++ trunk/scipy/cluster/hierarchy.py 2008-08-23 18:10:44 UTC (rev 4668) @@ -243,13 +243,15 @@ :Parameters: y : ndarray - The upper triangular of the distance matrix y. The result of + The upper triangular of the distance matrix. The result of ``pdist`` is returned in this form. :Returns: Z : ndarray The linkage matrix. + :SeeAlso: + - linkage: for advanced creation of hierarchical clusterings. """ return linkage(y, method='single', metric='euclidean') @@ -261,9 +263,14 @@ :Parameters: y : ndarray - The upper triangular of the distance matrix y. The result of + The upper triangular of the distance matrix. The result of ``pdist`` is returned in this form. + :Returns: + Z : ndarray + A linkage matrix containing the hierarchical clustering. See + the ``linkage`` function documentation for more information + on its structure. """ return linkage(y, method='complete', metric='euclidean') @@ -275,8 +282,17 @@ :Parameters: y : ndarray - The upper triangular of the distance matrix y. The result of + The upper triangular of the distance matrix. The result of ``pdist`` is returned in this form. + + :Returns: + Z : ndarray + A linkage matrix containing the hierarchical clustering. See + the ``linkage`` function documentation for more information + on its structure. + + :SeeAlso: + - linkage: for advanced creation of hierarchical clusterings. """ return linkage(y, method='average', metric='euclidean') @@ -288,8 +304,17 @@ :Parameters: y : ndarray - The upper triangular of the distance matrix y. The result of + The upper triangular of the distance matrix. The result of ``pdist`` is returned in this form. + + :Returns: + Z : ndarray + A linkage matrix containing the hierarchical clustering. See + the ``linkage`` function documentation for more information + on its structure. + + :SeeAlso: + - linkage: for advanced creation of hierarchical clusterings. """ return linkage(y, method='weighted', metric='euclidean') @@ -298,56 +323,105 @@ Performs centroid/UPGMC linkage. See ``linkage`` for more information on the return structure and algorithm. + :Parameters: + Q : ndarray + A condensed or redundant distance matrix. A condensed + distance matrix is a flat array containing the upper + triangular of the distance matrix. This is the form that + ``pdist`` returns. Alternatively, a collection of + m observation vectors in n dimensions may be passed as + a m by n array. - Z = centroid(y) + :Returns: + Z : ndarray + A linkage matrix containing the hierarchical clustering. See + the ``linkage`` function documentation for more information + on its structure. - Performs centroid/UPGMC linkage on the condensed distance matrix Z. - See linkage for more information on the return structure and - algorithm. + Calling Conventions + ------------------- - (a condensed alias for linkage) + 1. Z = centroid(y) - Z = centroid(X) + Performs centroid/UPGMC linkage on the condensed distance + matrix ``y``. See ``linkage`` for more information on the return + structure and algorithm. - Performs centroid/UPGMC linkage on the observation matrix X using - Euclidean distance as the distance metric. See linkage for more - information on the return structure and algorithm. + 2. Z = centroid(X) + Performs centroid/UPGMC linkage on the observation matrix ``X`` + using Euclidean distance as the distance metric. See ``linkage`` + for more information on the return structure and algorithm. + + :SeeAlso: + - linkage: for advanced creation of hierarchical clusterings. """ return linkage(y, method='centroid', metric='euclidean') def median(y): """ - Z = median(y) + Performs median/WPGMC linkage. See ``linkage`` for more + information on the return structure and algorithm. - Performs median/WPGMC linkage on the condensed distance matrix Z. - See linkage for more information on the return structure and - algorithm. + :Parameters: + Q : ndarray + A condensed or redundant distance matrix. A condensed + distance matrix is a flat array containing the upper + triangular of the distance matrix. This is the form that + ``pdist`` returns. Alternatively, a collection of + m observation vectors in n dimensions may be passed as + a m by n array. - Z = median(X) + Calling Conventions + ------------------- - Performs median/WPGMC linkage on the observation matrix X using - Euclidean distance as the distance metric. See linkage for more - information on the return structure and algorithm. + 1. Z = median(y) - (a condensed alias for linkage) + Performs median/WPGMC linkage on the condensed distance matrix + ``y``. See ``linkage`` for more information on the return + structure and algorithm. + + 2. Z = median(X) + + Performs median/WPGMC linkage on the observation matrix ``X`` + using Euclidean distance as the distance metric. See linkage + for more information on the return structure and algorithm. + + :SeeAlso: + - linkage: for advanced creation of hierarchical clusterings. """ return linkage(y, method='median', metric='euclidean') def ward(y): """ - Z = ward(y) + Performs Ward's linkage on a condensed or redundant distance + matrix. See linkage for more information on the return structure + and algorithm. - Performs Ward's linkage on the condensed distance matrix Z. See - linkage for more information on the return structure and algorithm. + :Parameters: + Q : ndarray + A condensed or redundant distance matrix. A condensed + distance matrix is a flat array containing the upper + triangular of the distance matrix. This is the form that + ``pdist`` returns. Alternatively, a collection of + m observation vectors in n dimensions may be passed as + a m by n array. - Z = ward(X) + Calling Conventions + ------------------- - Performs Ward's linkage on the observation matrix X using Euclidean - distance as the distance metric. See linkage for more information - on the return structure and algorithm. + 1. Z = ward(y) + Performs Ward's linkage on the condensed distance matrix Z. See + linkage for more information on the return structure and + algorithm. - (a condensed alias for linkage) + 2. Z = ward(X) + Performs Ward's linkage on the observation matrix X using + Euclidean distance as the distance metric. See linkage for more + information on the return structure and algorithm. + + :SeeAlso: + - linkage: for advanced creation of hierarchical clusterings. """ return linkage(y, method='ward', metric='euclidean') From scipy-svn at scipy.org Sat Aug 23 14:44:24 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Sat, 23 Aug 2008 13:44:24 -0500 (CDT) Subject: [Scipy-svn] r4669 - branches/fast_vectorize/examples Message-ID: <20080823184424.B122D39C021@scipy.org> Author: ilan Date: 2008-08-23 13:44:21 -0500 (Sat, 23 Aug 2008) New Revision: 4669 Added: branches/fast_vectorize/examples/README.txt Removed: branches/fast_vectorize/examples/mandel_mkImage.py branches/fast_vectorize/examples/mandel_py.py Modified: branches/fast_vectorize/examples/benchmark.py branches/fast_vectorize/examples/compdec.py branches/fast_vectorize/examples/primes.py Log: Improved documentation of the examples. Added: branches/fast_vectorize/examples/README.txt =================================================================== --- branches/fast_vectorize/examples/README.txt 2008-08-23 18:10:44 UTC (rev 4668) +++ branches/fast_vectorize/examples/README.txt 2008-08-23 18:44:21 UTC (rev 4669) @@ -0,0 +1,21 @@ + + +benchmark.py + Some speed comparisons between dirrerent ways of vectorizing + and calculating a simple polynom. + +compdec.py + A small example illustrates how PyPy's translator package can + be used to write compile decorator. + +mandel.py + A program which uses fast_vectorize to calulate an image file + of the well-known Mandelbort set. + +mandel_c.py + A program which illustrates how to create a Ufunc by writing + C code into weave. + +primes.py + A Python function for counting primes is first executed as a + regular function, as well as after "fast_vectorization". Property changes on: branches/fast_vectorize/examples/benchmark.py ___________________________________________________________________ Name: svn:executable - * Modified: branches/fast_vectorize/examples/compdec.py =================================================================== --- branches/fast_vectorize/examples/compdec.py 2008-08-23 18:10:44 UTC (rev 4668) +++ branches/fast_vectorize/examples/compdec.py 2008-08-23 18:44:21 UTC (rev 4669) @@ -1,9 +1,10 @@ """ -I have written a class which allows using the compiled version of a -Python functions simply by adding a decorator to the function. -The nice thing about doing things this way is that all the code is pure -Python code, and switching between the compiled and uncompiled version -of the function is as simple as possible. +This small example illustrates how PyPy's translator package can +be used to write compile decorator. This is done by a class which allows +using the compiled version of a Python functions simply by adding a +decorator to the function. The nice thing about doing things this way +is that all the code is pure Python code, and switching between the +compiled and uncompiled version of the function is very simple. """ from pypy.translator.interactive import Translation @@ -22,13 +23,14 @@ return self.cfunc(*args) - at compdec -def is_prime(n): - if n < 2: - return False - for i in xrange(2, n): - if n%i == 0: +if __name__ == '__main__': + @compdec + def is_prime(n): + if n < 2: return False - return True + for i in xrange(2, n): + if n%i == 0: + return False + return True -print sum(is_prime(n) for n in xrange(100000)) + print sum(is_prime(n) for n in xrange(100000)) Deleted: branches/fast_vectorize/examples/mandel_mkImage.py =================================================================== --- branches/fast_vectorize/examples/mandel_mkImage.py 2008-08-23 18:10:44 UTC (rev 4668) +++ branches/fast_vectorize/examples/mandel_mkImage.py 2008-08-23 18:44:21 UTC (rev 4669) @@ -1,47 +0,0 @@ -#!/usr/bin/env python - -# Before running this be sure to apply Travis Oliphant's patch to PIL: -# http://www.scipy.org/Cookbook/PIL - -from numpy import asarray, concatenate, ogrid, uint8 -from PIL import Image - - -import sys -sys.path.append('../mkufunc') -from fast_vectorize import fast_vectorize - - -from mandel_c import mandel - - - at fast_vectorize(int) -def red(i): - if i == -1: return 0 - return (i * 5) % 256 - - at fast_vectorize(int) -def green(i): - if i == -1: return 0 - return (i % 16) * 15 - - at fast_vectorize(int) -def blue(i): - if i == -1: return 0 - return 255 - - -w, h = 1200, 900 - -y, x = ogrid[-1.5:+1.5:h*1j, -2.75:+1.15:w*1j] - -mand = mandel(x, y) - -r = asarray(red(mand), dtype=uint8).reshape(h, w, 1) -g = asarray(green(mand), dtype=uint8).reshape(h, w, 1) -b = asarray(blue(mand), dtype=uint8).reshape(h, w, 1) - -a = concatenate((r, g, b), axis=2).reshape(h, w, 3) - -im = Image.fromarray(a) -im.save('mandel.png') Deleted: branches/fast_vectorize/examples/mandel_py.py =================================================================== --- branches/fast_vectorize/examples/mandel_py.py 2008-08-23 18:10:44 UTC (rev 4668) +++ branches/fast_vectorize/examples/mandel_py.py 2008-08-23 18:44:21 UTC (rev 4669) @@ -1,36 +0,0 @@ -#!/usr/bin/env python -from numpy import array - -import sys -sys.path.append('../mkufunc') -from fast_vectorize import fast_vectorize - - -D = 1000 - - - at fast_vectorize([(float, float, int)]) -def mandel(cr, ci): - d = 1 - zr = cr - zi = ci - for d in xrange(1, D): - zr2 = zr * zr - zi2 = zi * zi - if zr2 + zi2 > 16: - return d - zi = 2.0 * zr * zi + ci - zr = zr2 - zi2 + cr - else: - return -1 - - - -if __name__ == '__main__': - - assert mandel(-1, .3) == 36 - assert mandel(0, 0) == -1 - assert mandel(10, 10) == 1 - assert (mandel(array([-1, 0, 10]), array([.3, 0, 10])) == - array([36, -1, 1])).all() - Property changes on: branches/fast_vectorize/examples/primes.py ___________________________________________________________________ Name: svn:executable - * From scipy-svn at scipy.org Sat Aug 23 15:04:55 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Sat, 23 Aug 2008 14:04:55 -0500 (CDT) Subject: [Scipy-svn] r4670 - trunk/scipy/cluster Message-ID: <20080823190455.6870739C021@scipy.org> Author: damian.eads Date: 2008-08-23 14:04:52 -0500 (Sat, 23 Aug 2008) New Revision: 4670 Modified: trunk/scipy/cluster/hierarchy.py Log: Finished RSTifying scipy.cluster.hierarchy.linkage function. Modified: trunk/scipy/cluster/hierarchy.py =================================================================== --- trunk/scipy/cluster/hierarchy.py 2008-08-23 18:44:21 UTC (rev 4669) +++ trunk/scipy/cluster/hierarchy.py 2008-08-23 19:04:52 UTC (rev 4670) @@ -427,114 +427,153 @@ def linkage(y, method='single', metric='euclidean'): - """ Z = linkage(y, method) + """ + Performs hierarchical/agglomerative clustering on the + condensed distance matrix y. y must be a {n \choose 2} sized + vector where n is the number of original observations paired + in the distance matrix. The behavior of this function is very + similar to the MATLAB(TM) linkage function. - Performs hierarchical/agglomerative clustering on the - condensed distance matrix y. y must be a {n \choose 2} sized - vector where n is the number of original observations paired - in the distance matrix. The behavior of this function is very - similar to the MATLAB(TM) linkage function. + A 4 by :math:`$(n-1)$` matrix ``Z`` is returned. At the + :math:`$i$`th iteration, clusters with indices ``Z[i, 0]`` and + ``Z[i, 1]`` are combined to form cluster :math:`$n + i$`. A + cluster with an index less than :math:`$n$` corresponds to one of + the :math:`$n$` original observations. The distance between + clusters ``Z[i, 0]`` and ``Z[i, 1]`` is given by ``Z[i, 2]``. The + fourth value ``Z[i, 3]`` represents the number of original + observations in the newly formed cluster. - A (n - 1) * 4 matrix Z is returned. At the i'th iteration, - clusters with indices Z[i, 0] and Z[i, 1] are combined to - form cluster n + i. A cluster with an index less than n - corresponds to one of the n original observations. The - distance between clusters Z[i, 0] and Z[i, 1] is given by - Z[i, 2]. The fourth value Z[i, 3] represents the number of - original observations in the newly formed cluster. + The following linkage methods are used to compute the distance + :math:`$d(s, t)$` between two clusters :math:`$s$` and + :math:`$t$`. The algorithm begins with a forest of clusters that + have yet to be used in the hierarchy being formed. When two + clusters :math:`$s$` and :math:`$t$` from this forest are combined + into a single cluster :math:`$u$`, :math:`$s$` and :math:`$t$` are + removed from the forest, and :math:`$u$` is added to the + forest. When only one cluster remains in the forest, the algorithm + stops, and this cluster becomes the root. - The following linkage methods are used to compute the - distance dist(s, t) between two clusters s and t. The - algorithm begins with a forest of clusters that have yet - to be used in the hierarchy being formed. When two clusters - s and t from this forest are combined into a single cluster u, - s and t are removed from the forest, and u is added to - the forest. When only one cluster remains in the forest, - the algorithm stops, and this cluster becomes the root. + A distance matrix is maintained at each iteration. The ``d[i,j]`` + entry corresponds to the distance between cluster :math:`$i$` and + :math:`$j$` in the original forest. - A distance matrix is maintained at each iteration. The - d[i,j] entry corresponds to the distance between cluster - i and j in the original forest. + At each iteration, the algorithm must update the distance matrix + to reflect the distance of the newly formed cluster u with the + remaining clusters in the forest. - At each iteration, the algorithm must update the distance - matrix to reflect the distance of the newly formed cluster - u with the remaining clusters in the forest. + Suppose there are :math:`$|u|$` original observations + :math:`$u[0], \ldots, u[|u|-1]$` in cluster :math:`$u$` and + :math:`$|v|$` original objects :math:`$v[0], \ldots, v[|v|-1]$` in + cluster :math:`$v$`. Recall :math:`$s$` and :math:`$t$` are + combined to form cluster :math:`$u$`. Let :math:`$v$` be any + remaining cluster in the forest that is not :math:`$u$`. - Suppose there are |u| original observations u[0], ..., u[|u|-1] - in cluster u and |v| original objects v[0], ..., v[|v|-1] - in cluster v. Recall s and t are combined to form cluster - u. Let v be any remaining cluster in the forest that is not - u. + :Parameters: + Q : ndarray + A condensed or redundant distance matrix. A condensed + distance matrix is a flat array containing the upper + triangular of the distance matrix. This is the form that + ``pdist`` returns. Alternatively, a collection of + :math:`$m$` observation vectors in n dimensions may be passed as + a :math:`$m$` by :math:`$n$` array. + method : string + The linkage algorithm to use. See the ``Linkage Methods`` + section below for full descriptions. + metric : string + The distance metric to use. See the ``Distance Metric`` + section below for full descriptions. - The following are methods for calculating the distance between - the newly formed cluster u and each v. + Linkage Methods + --------------- - * method='single' assigns dist(u,v) = MIN(dist(u[i],v[j]) - for all points i in cluster u and j in cluster v. + The following are methods for calculating the distance between the + newly formed cluster :math:`$u$` and each :math:`$v$`. - (also called Nearest Point Algorithm) + * method=``single`` assigns - * method='complete' assigns dist(u,v) = MAX(dist(u[i],v[j]) - for all points i in cluster u and j in cluster v. + .. math: + d(u,v) = \min(dist(u[i],v[j])) - (also called Farthest Point Algorithm - or the Voor Hees Algorithm) + for all points :math:`$i$` in cluster :math:`$u$` and + :math:`$j$` in cluster :math:`$v$`. This is also known as the + Nearest Point Algorithm. - * method='average' assigns dist(u,v) = - \sum_{ij} { dist(u[i], v[j]) } / (|u|*|v|) - for all points i and j where |u| and |v| are the - cardinalities of clusters u and v, respectively. + * method=``complete`` assigns - (also called UPGMA) + .. math: + d(u, v) = \max(dist(u[i],v[j])) - * method='weighted' assigns + for all points :math:`$i$` in cluster u and :math:`$j$` in + cluster :math:`$v$`. This is also known by the Farthest Point + Algorithm or Voor Hees Algorithm. - dist(u,v) = (dist(s,v) + dist(t,v))/2 + * method=``average`` assigns - where cluster u was formed with cluster s and t and v - is a remaining cluster in the forest. (also called WPGMA) + .. math: + d(u,v) = \sum_{ij} \frac{d(u[i], v[j])} + {(|u|*|v|) - Z = linkage(X, method, metric='euclidean') + for all points :math:`$i$` and :math:`$j$` where :math:`$|u|$` + and :math:`$|v|$` are the cardinalities of clusters :math:`$u$` + and :math:`$v$`, respectively. This is also called the UPGMA + algorithm. This is called UPGMA. - Performs hierarchical clustering on the objects defined by the - n by m observation matrix X. + * method='weighted' assigns - If the metric is 'euclidean' then the following methods may be - used: + .. math: + d(u,v) = (dist(s,v) + dist(t,v))/2 - * method='centroid' assigns dist(s,t) = euclid(c_s, c_t) where - c_s and c_t are the centroids of clusters s and t, - respectively. When two clusters s and t are combined into a new - cluster u, the new centroid is computed over all the original - objects in clusters s and t. The distance then becomes - the Euclidean distance between the centroid of u and the - centroid of a remaining cluster v in the forest. - (also called UPGMC) + where cluster u was formed with cluster s and t and v + is a remaining cluster in the forest. (also called WPGMA) - * method='median' assigns dist(s,t) as above. When two clusters - s and t are combined into a new cluster u, the average of - centroids s and t give the new centroid u. (also called WPGMC) - * method='ward' uses the Ward variance minimization algorithm. - The new entry dist(u, v) is computed as follows, + * method='centroid' assigns - dist(u,v) = + .. math: + dist(s,t) = euclid(c_s, c_t) - ---------------------------------------------------- - | |v|+|s| |v|+|t| |v| - | ------- d(v,s)^2 + ------- d(v,t)^2 - --- d(s,t)^2 - \| T T T + where :math:`$c_s$` and :math:`$c_t$` are the centroids of + clusters :math:`$s$` and :math:`$t$`, respectively. When two + clusters :math:`$s$` and :math:`$t$` are combined into a new + cluster :math:`$u$`, the new centroid is computed over all the + original objects in clusters :math:`$s$` and :math:`$t$`. The + distance then becomes the Euclidean distance between the + centroid of :math:`$u$` and the centroid of a remaining cluster + :math:`$v$` in the forest. This is also known as the UPGMC + algorithm. - where u is the newly joined cluster consisting of clusters - s and t, v is an unused cluster in the forest, T=|v|+|s|+|t|, - and |*| is the cardinality of its argument. - (also called incremental) + * method='median' assigns math:`$d(s,t)$` like the ``centroid`` + method. When two clusters s and t are combined into a new + cluster :math:`$u$`, the average of centroids s and t give the + new centroid :math:`$u$`. This is also known as the WPGMC + algorithm. - Warning to MATLAB(TM) users: when the minimum distance pair in - the forest is chosen, there may be two or more pairs with the - same minimum distance. This implementation may chose a - different minimum than the MATLAB(TM) version. - """ + * method='ward' uses the Ward variance minimization algorithm. + The new entry :math:`$d(u,v)$` is computed as follows, + + .. math: + + d(u,v) = \sqrt{\frac{|v|+|s|} + {T}d(v,s)^2 + + \frac{|v|+|t|} + {T}d(v,t)^2 + + \frac{|v|} + {T}d(s,t)^2} + + where :math:`$u$` is the newly joined cluster consisting of + clusters :math:`$s$` and :math:`$t$`, :math:`$v$` is an unused + cluster in the forest, :math:`$T=|v|+|s|+|t|$`, and + :math:`$|*|$` is the cardinality of its argument. This is also + known as the incremental algorithm. + + Warning + ------- + + When the minimum distance pair in the forest is chosen, there may + be two or more pairs with the same minimum distance. This + implementation may chose a different minimum than the MATLAB(TM) + version. + """ if not isinstance(method, str): raise TypeError("Argument 'method' must be a string.") From scipy-svn at scipy.org Sat Aug 23 15:19:07 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Sat, 23 Aug 2008 14:19:07 -0500 (CDT) Subject: [Scipy-svn] r4671 - trunk/scipy/cluster Message-ID: <20080823191907.09F3339C021@scipy.org> Author: damian.eads Date: 2008-08-23 14:19:03 -0500 (Sat, 23 Aug 2008) New Revision: 4671 Modified: trunk/scipy/cluster/hierarchy.py Log: Working on RSTifying the cnode class in hierarchy. Modified: trunk/scipy/cluster/hierarchy.py =================================================================== --- trunk/scipy/cluster/hierarchy.py 2008-08-23 19:04:52 UTC (rev 4670) +++ trunk/scipy/cluster/hierarchy.py 2008-08-23 19:19:03 UTC (rev 4671) @@ -480,8 +480,8 @@ The linkage algorithm to use. See the ``Linkage Methods`` section below for full descriptions. metric : string - The distance metric to use. See the ``Distance Metric`` - section below for full descriptions. + The distance metric to use. See the ``distance.pdist`` + function for a list of valid distance metrics. Linkage Methods --------------- @@ -642,62 +642,78 @@ def getId(self): """ - i = nd.getId() + The identifier of the target node. For :math:`$0 leq i < n$`, + :math:`$i$` corresponds to original observation + :math:`$i$`. For :math:`$n \leq i$` < :math:`$2n-1$`, + :math:`$i$` corresponds to non-singleton cluster formed at + iteration :math:`$i-n$`. - Returns the id number of the node nd. For 0 <= i < n, i - corresponds to original observation i. For n <= i < 2n - 1, - i corresponds to non-singleton cluster formed at iteration i-n. + :Returns: + + id : int + The identifier of the target node. + """ return self.id def getCount(self): """ - c = nd.getCount() + The number of leaf nodes (original observations) belonging to + the cluster node nd. If the target node is a leaf, 1 is + returned. + + :Returns: - Returns the number of leaf nodes (original observations) - belonging to the cluster node nd. If the nd is a leaf, c=1. + c : int + The number of leaf nodes below the target node. """ return self.count def getLeft(self): """ - left = nd.getLeft() + Returns a reference to the left child tree object. If the node + is a leaf, None is returned. - Returns a reference to the left child. If the node is a - leaf, None is returned. + :Returns: + left : cnode + The left child of the target node. """ return self.left def getRight(self): """ - left = nd.getLeft() + Returns a reference to the right child tree object. If the node + is a leaf, None is returned. - Returns a reference to the right child. If the node is a - leaf, None is returned. + :Returns: + right : cnode + The left child of the target node. """ return self.right def isLeaf(self): """ - Returns True if the node is a leaf. + Returns True iff the target node is a leaf. + + :Returns: + leafness : bool + True if the target node is a leaf node. """ return self.left is None def preOrder(self, func=(lambda x: x.id)): """ - vlst = preOrder(func) + Performs preorder traversal without recursive function calls. + When a leaf node is first encountered, ``func`` is called with + the leaf node as its argument, and its result is appended to + the list. - Performs preorder traversal without recursive function calls. - When a leaf node is first encountered, func is called with the - leaf node as its argument, and its result is appended to the - list vlst. + For example, the statement: + + ids = root.preOrder(lambda x: x.id) - For example, the statement - - ids = root.preOrder(lambda x: x.id) - - returns a list of the node ids corresponding to the leaf - nodes of the tree as they appear from left to right. + returns a list of the node ids corresponding to the leaf nodes + of the tree as they appear from left to right. """ # Do a preorder traversal, caching the result. To avoid having to do From scipy-svn at scipy.org Sat Aug 23 21:26:08 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Sat, 23 Aug 2008 20:26:08 -0500 (CDT) Subject: [Scipy-svn] r4672 - trunk/scipy/cluster Message-ID: <20080824012608.6883639C080@scipy.org> Author: damian.eads Date: 2008-08-23 20:26:07 -0500 (Sat, 23 Aug 2008) New Revision: 4672 Modified: trunk/scipy/cluster/hierarchy.py Log: More conversion of hierarchy docs to RST format. Modified: trunk/scipy/cluster/hierarchy.py =================================================================== --- trunk/scipy/cluster/hierarchy.py 2008-08-23 19:19:03 UTC (rev 4671) +++ trunk/scipy/cluster/hierarchy.py 2008-08-24 01:26:07 UTC (rev 4672) @@ -619,6 +619,10 @@ The totree function converts a matrix returned by the linkage function into an easy-to-use tree representation. + + :SeeAlso: + + - totree: for converting a linkage matrix Z into a tree object. """ def __init__(self, id, left=None, right=None, dist=0, count=1): @@ -714,6 +718,19 @@ returns a list of the node ids corresponding to the leaf nodes of the tree as they appear from left to right. + + :Parameters: + + - func : function + Applied to each leaf cnode object in the pre-order + traversal. Given the i'th leaf node in the pre-order + traversal ``n[i]``, the result of func(n[i]) is stored in + L[i]. If not provided, the index of the original observation + to which the node corresponds is used. + + :Returns: + - L : list + The pre-order traversal. """ # Do a preorder traversal, caching the result. To avoid having to do @@ -753,30 +770,34 @@ def totree(Z, rd=False): """ - r = totree(Z) + Converts a hierarchical clustering encoded in the matrix Z (by + linkage) into an easy-to-use tree object. The reference r to the + root cnode object is returned. + + Each cnode object has a left, right, dist, id, and count + attribute. The left and right attributes point to cnode objects + that were combined to generate the cluster. If both are None then + the cnode object is a leaf node, its count must be 1, and its + distance is meaningless but set to 0. - Converts a hierarchical clustering encoded in the matrix Z - (by linkage) into an easy-to-use tree object. The reference r - to the root cnode object is returned. + :Parameters: - Each cnode object has a left, right, dist, id, and count - attribute. The left and right attributes point to cnode - objects that were combined to generate the cluster. If - both are None then the cnode object is a leaf node, its - count must be 1, and its distance is meaningless but set - to 0. + Z : ndarray + The linkage matrix in proper form (see the ``linkage`` + function documentation). - (r, d) = totree(Z, rd=True) + r : bool + When ``False``, a reference to the root cnode object is + returned. Otherwise, a tuple (r,d) is returned. ``r`` is a + reference to the root node while ``d`` is a dictionary + mapping cluster ids to cnode references. If a cluster id is + less than n, then it corresponds to a singleton cluster + (leaf node). See ``linkage`` for more information on the + assignment of cluster ids to clusters. - Same as totree(Z) except a tuple is returned where r is - the reference to the root cnode and d is a reference to a - dictionary mapping cluster ids to cnodes. If a cluster id - is less than n, then it corresponds to a singleton cluster - (leaf node). - - Note: This function is provided for the convenience of the - library user. cnodes are not used as input to any of the - functions in this library. + Note: This function is provided for the convenience of the library + user. cnodes are not used as input to any of the functions in this + library. """ Z = np.asarray(Z) @@ -845,29 +866,38 @@ def cophenet(*args, **kwargs): """ - d = cophenet(Z) + + Calling Conventions + ------------------- + + 1. ``d = cophenet(Z)`` + Calculates the cophenetic distances between each observation in the - hierarchical clustering defined by the linkage Z. + hierarchical clustering defined by the linkage ``Z``. - Suppose p and q are original observations in disjoint clusters - s and t, respectively and s and t are joined by a direct parent - cluster u. The cophenetic distance between observations i and j - is simply the distance between clusters s and t. + Suppose :math:`$p$` and :math:`$q$` are original observations in + disjoint clusters :math:`$s$` and :math:`$t$`, respectively and + :math:`$s$` and :math:`$t$` are joined by a direct parent + cluster :math:`$u$`. The cophenetic distance between + observations :math:`$i$` and :math:`$j$` is simply the distance + between clusters :math:`$s$` and :math:`$t$`. - d is cophenetic distance matrix in condensed form. The ij'th - entry is the cophenetic distance between original observations - i and j. + ``d`` is cophenetic distance matrix in condensed form. The + :math:`$ij$`th entry is the cophenetic distance between original + observations :math:`$i$` and :math:`$j$`. - c = cophenet(Z, Y) + 2. ``c = cophenet(Z, Y)`` - Calculates the cophenetic correlation coefficient c of a hierarchical - clustering Z of a set of n observations in m dimensions. Y is the - condensed distance matrix from which Z was generated. + Calculates the cophenetic correlation coefficient ``c`` of a + hierarchical clustering defined by the linkage matrix ``Z`` of a + set of :math:`$n$` observations in :math:`$m$` dimensions. ``Y`` + is the condensed distance matrix from which ``Z`` was generated. - (c, d) = cophenet(Z, Y, []) + 3. ``(c, d) = cophenet(Z, Y, [])`` - Also returns the cophenetic distance matrix in condensed form. + Returns a tuple instead, (c, d). The cophenetic distance matrix + ``d`` is included in condensed (upper triangular) form. """ Z = np.asarray(Z) From scipy-svn at scipy.org Sun Aug 24 17:05:25 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Sun, 24 Aug 2008 16:05:25 -0500 (CDT) Subject: [Scipy-svn] r4673 - in trunk/scipy/stats: . tests Message-ID: <20080824210525.C4A7F39C080@scipy.org> Author: rkern Date: 2008-08-24 16:05:23 -0500 (Sun, 24 Aug 2008) New Revision: 4673 Modified: trunk/scipy/stats/distributions.py trunk/scipy/stats/tests/test_distributions.py Log: BUG: Fix loggamma, fatigue life and a few other distributions. Bump up the power on the unit tests for the distributions. Comment on remaining failures. Keep around the extra descriptive information that used to get consumed by generating the docstrings for further use by other tools introspecting the distributions. Modified: trunk/scipy/stats/distributions.py =================================================================== --- trunk/scipy/stats/distributions.py 2008-08-24 01:26:07 UTC (rev 4672) +++ trunk/scipy/stats/distributions.py 2008-08-24 21:05:23 UTC (rev 4673) @@ -14,7 +14,8 @@ zeros, floor, logical_and, log, sqrt, exp, arctanh, tan, sin, arcsin, \ arctan, tanh, ndarray, cos, cosh, sinh, newaxis, array from numpy import atleast_1d, polyval, angle, ceil, place, extract, \ - any, argsort, argmax, vectorize, r_, asarray, nan, inf, pi, isnan, isinf + any, argsort, argmax, vectorize, r_, asarray, nan, inf, pi, isnan, isinf, \ + power import numpy import numpy.random as mtrand from numpy import flatnonzero as nonzero @@ -308,6 +309,8 @@ pdf_signature = inspect.getargspec(self._pdf.im_func) numargs2 = len(pdf_signature[0]) - 2 self.numargs = max(numargs1, numargs2) + self.shapes = shapes + self.extradoc = extradoc if momtype == 0: self.generic_moment = sgf(self._mom0_sc,otypes='d') else: @@ -828,15 +831,23 @@ ## Normal distribution # loc = mu, scale = std +# Keep these implementations out of the class definition so they can be reused +# by other distributions. +def _norm_pdf(x): + return 1.0/sqrt(2*pi)*exp(-x**2/2.0) +def _norm_cdf(x): + return special.ndtr(x) +def _norm_ppf(q): + return special.ndtri(q) class norm_gen(rv_continuous): def _rvs(self): return mtrand.standard_normal(self._size) def _pdf(self,x): - return 1.0/sqrt(2*pi)*exp(-x**2/2.0) + return _norm_pdf(x) def _cdf(self,x): - return special.ndtr(x) + return _norm_cdf(x) def _ppf(self,q): - return special.ndtri(q) + return _norm_ppf(q) def _stats(self): return 0.0, 1.0, 0.0, 0.0 def _entropy(self): @@ -1354,16 +1365,14 @@ """ ) -## Faigue-Life (Birnbaum-Sanders) +## Fatigue-Life (Birnbaum-Sanders) class fatiguelife_gen(rv_continuous): def _rvs(self, c): z = norm.rvs(size=self._size) - U = random(size=self._size) - fac = 2 + c*c*z*z - det = sqrt(fac*fac - 4) - t1 = fac + det - t2 = fac - det - return t1*(U>0.5) + t2*(U<0.5) + x = 0.5*c*z + x2 = x*x + t = 1.0 + 2*x2 + 2*x*sqrt(1 + x2) + return t def _pdf(self, x, c): return (x+1)/arr(2*c*sqrt(2*pi*x**3))*exp(-(x-1)**2/arr((2.0*x*c**2))) def _cdf(self, x, c): @@ -2241,12 +2250,14 @@ ## Log Gamma # class loggamma_gen(rv_continuous): + def _rvs(self, c): + return log(mtrand.gamma(c, size=self._size)) def _pdf(self, x, c): return exp(c*x-exp(x)-special.gammaln(c)) def _cdf(self, x, c): - return special.gammainc(c, exp(x))/ special.gamma(c) + return special.gammainc(c, exp(x)) def _ppf(self, q, c): - return log(special.gammaincinv(c,q*special.gamma(c))) + return log(special.gammaincinv(c,q)) loggamma = loggamma_gen(name='loggamma', longname="A log gamma", extradoc=""" @@ -2713,14 +2724,14 @@ # Power Normal -class powernorm_gen(norm_gen): +class powernorm_gen(rv_continuous): def _pdf(self, x, c): - return c*norm_gen._pdf(self, x)* \ - (norm_gen._cdf(self, -x)**(c-1.0)) + return c*norm.pdf(x)* \ + (norm.cdf(-x)**(c-1.0)) def _cdf(self, x, c): - return 1.0-norm_gen._cdf(self, -x)**(c*1.0) + return 1.0-norm.cdf(-x)**(c*1.0) def _ppf(self, q, c): - return -norm_gen._ppf(self, pow(1.0-q,1.0/c)) + return -norm.ppf(pow(1.0-q,1.0/c)) powernorm = powernorm_gen(name='powernorm', longname="A power normal", shapes="c", extradoc=""" @@ -2734,6 +2745,7 @@ # R-distribution ( a general-purpose distribution with a # variety of shapes. +# FIXME: PPF does not work. class rdist_gen(rv_continuous): def _pdf(self, x, c): return pow((1.0-x*x),c/2.0-1) / special.beta(0.5,c/2.0) @@ -2812,6 +2824,7 @@ # Rice distribution +# FIXME: PPF does not work. class rice_gen(rv_continuous): def _pdf(self, x, b): return x*exp(-(x*x+b*b)/2.0)*special.i0(x*b) @@ -2833,6 +2846,7 @@ # Reciprocal Inverse Gaussian +# FIXME: PPF does not work. class recipinvgauss_gen(rv_continuous): def _pdf(self, x, mu): return 1.0/sqrt(2*pi*x)*exp(-(1-mu*x)**2.0 / (2*x*mu**2.0)) @@ -2978,6 +2992,7 @@ # to u-shape (lam = 0.5) # to Uniform from -1 to 1 (lam = 1) +# FIXME: RVS does not work. class tukeylambda_gen(rv_continuous): def _pdf(self, x, lam): Fx = arr(special.tklmbda(x,lam)) @@ -3368,6 +3383,8 @@ self._cdfvec = sgf(self._cdfsingle,otypes='d') self.return_integers = 1 self.vecentropy = vectorize(self._entropy) + self.shapes = shapes + self.extradoc = extradoc if values is not None: self.xk, self.pk = values @@ -3880,9 +3897,12 @@ return mtrand.negative_binomial(n, pr, self._size) def _argcheck(self, n, pr): return (n >= 0) & (pr >= 0) & (pr <= 1) + def _pmf(self, x, n, pr): + coeff = exp(special.gammaln(n+x) - special.gammaln(x+1) - special.gammaln(n)) + return coeff * power(pr,n) * power(1-pr,x) def _cdf(self, x, n, pr): k = floor(x) - return special.nbdtr(k,n,pr) + return special.betainc(n, k+1, pr) def _sf(self, x, n, pr): k = floor(x) return special.nbdtrc(k,n,pr) @@ -3999,7 +4019,7 @@ ) ## Logarithmic (Log-Series), (Series) distribution - +# FIXME: Fails _cdfvec class logser_gen(rv_discrete): def _rvs(self, pr): return mtrand.logseries(pr,size=self._size) @@ -4047,8 +4067,8 @@ return special.pdtrc(k,mu) def _ppf(self, q, mu): vals = ceil(special.pdtrik(q,mu)) - temp = special.pdtr(vals-1,mu) - # fixme: vals1 = vals-1? + vals1 = vals-1 + temp = special.pdtr(vals1,mu) return where((temp >= q), vals1, vals) def _stats(self, mu): var = mu @@ -4080,7 +4100,7 @@ return 0 # lambda_ = 0 def _pmf(self, k, lambda_): fact = (1-exp(-lambda_)) - return fact*exp(-lambda_(k)) + return fact*exp(-lambda_*k) def _cdf(self, x, lambda_): k = floor(x) return 1-exp(-lambda_*(k+1)) @@ -4111,7 +4131,7 @@ class boltzmann_gen(rv_discrete): def _pmf(self, k, lambda_, N): fact = (1-exp(-lambda_))/(1-exp(-lambda_*N)) - return fact*exp(-lambda_(k)) + return fact*exp(-lambda_*k) def _cdf(self, x, lambda_, N): k = floor(x) return (1-exp(-lambda_*(k+1)))/(1-exp(-lambda_*N)) @@ -4197,6 +4217,7 @@ # Zipf distribution +# FIXME: problems sampling. class zipf_gen(rv_discrete): def _rvs(self, a): return mtrand.zipf(a, size=self._size) Modified: trunk/scipy/stats/tests/test_distributions.py =================================================================== --- trunk/scipy/stats/tests/test_distributions.py 2008-08-24 01:26:07 UTC (rev 4672) +++ trunk/scipy/stats/tests/test_distributions.py 2008-08-24 21:05:23 UTC (rev 4673) @@ -37,18 +37,18 @@ # check function for test generator def check_distribution(dist, args, alpha): - D,pval = stats.kstest(dist,'', args=args, N=30) + D,pval = stats.kstest(dist,'', args=args, N=1000) if (pval < alpha): - D,pval = stats.kstest(dist,'',args=args, N=30) + D,pval = stats.kstest(dist,'',args=args, N=1000) #if (pval < alpha): - # D,pval = stats.kstest(dist,'',args=args, N=30) + # D,pval = stats.kstest(dist,'',args=args, N=1000) assert (pval > alpha), "D = " + str(D) + "; pval = " + str(pval) + \ "; alpha = " + str(alpha) + "\nargs = " + str(args) # nose test generator def test_all_distributions(): for dist in dists: - distfunc = eval('stats.'+dist) + distfunc = getattr(stats, dist) nargs = distfunc.numargs alpha = 0.01 if dist == 'fatiguelife': From scipy-svn at scipy.org Mon Aug 25 08:11:05 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 25 Aug 2008 07:11:05 -0500 (CDT) Subject: [Scipy-svn] r4674 - in trunk/scipy/cluster: src tests Message-ID: <20080825121105.714C439C635@scipy.org> Author: damian.eads Date: 2008-08-25 07:10:57 -0500 (Mon, 25 Aug 2008) New Revision: 4674 Modified: trunk/scipy/cluster/src/distance.c trunk/scipy/cluster/tests/test_distance.py trunk/scipy/cluster/tests/test_hierarchy.py Log: Fixed bug in C version of Canberra. Modified: trunk/scipy/cluster/src/distance.c =================================================================== --- trunk/scipy/cluster/src/distance.c 2008-08-24 21:05:23 UTC (rev 4673) +++ trunk/scipy/cluster/src/distance.c 2008-08-25 12:10:57 UTC (rev 4674) @@ -73,11 +73,13 @@ static inline double canberra_distance(const double *u, const double *v, int n) { int i; - double s = 0.0; + double snum = 0.0, sdenom_u = 0.0, sdenom_v = 0.0; for (i = 0; i < n; i++) { - s += (fabs(u[i] - v[i]) / (fabs(u[i]) + fabs(v[i]))); + snum += fabs(u[i] - v[i]); + sdenom_u += fabs(u[i]); + sdenom_v += fabs(v[i]); } - return s; + return snum / (sdenom_u + sdenom_v); } static inline double bray_curtis_distance(const double *u, const double *v, int n) { Modified: trunk/scipy/cluster/tests/test_distance.py =================================================================== --- trunk/scipy/cluster/tests/test_distance.py 2008-08-24 21:05:23 UTC (rev 4673) +++ trunk/scipy/cluster/tests/test_distance.py 2008-08-25 12:10:57 UTC (rev 4674) @@ -944,6 +944,17 @@ print np.abs(y1-y2).max() self.failUnless(within_tol(y1, y2, eps)) + def test_pdist_canberra_match(self): + "Tests pdist(X, 'canberra') to see if the two implementations match on random double input data." + D = eo['iris'] + print D.shape, D.dtype + eps = 1e-10 + y1 = pdist(D, "canberra") + y2 = pdist(D, "test_canberra") + print np.abs(y1-y2).max() + self.failUnless(within_tol(y1, y2, eps)) + + def within_tol(a, b, tol): return np.abs(a - b).max() < tol Modified: trunk/scipy/cluster/tests/test_hierarchy.py =================================================================== --- trunk/scipy/cluster/tests/test_hierarchy.py 2008-08-24 21:05:23 UTC (rev 4673) +++ trunk/scipy/cluster/tests/test_hierarchy.py 2008-08-25 12:10:57 UTC (rev 4674) @@ -43,11 +43,11 @@ from scipy.cluster.distance import squareform, pdist, matching, jaccard, dice, sokalsneath, rogerstanimoto, russellrao, yule, numobs_dm, numobs_y _tdist = np.array([[0, 662, 877, 255, 412, 996], - [662, 0, 295, 468, 268, 400], - [877, 295, 0, 754, 564, 138], - [255, 468, 754, 0, 219, 869], - [412, 268, 564, 219, 0, 669], - [996, 400, 138, 869, 669, 0 ]], dtype='double') + [662, 0, 295, 468, 268, 400], + [877, 295, 0, 754, 564, 138], + [255, 468, 754, 0, 219, 869], + [412, 268, 564, 219, 0, 669], + [996, 400, 138, 869, 669, 0 ]], dtype='double') _ytdist = squareform(_tdist) From scipy-svn at scipy.org Mon Aug 25 08:33:59 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 25 Aug 2008 07:33:59 -0500 (CDT) Subject: [Scipy-svn] r4675 - trunk/scipy/cluster/tests Message-ID: <20080825123359.63A4C39C635@scipy.org> Author: damian.eads Date: 2008-08-25 07:33:58 -0500 (Mon, 25 Aug 2008) New Revision: 4675 Modified: trunk/scipy/cluster/tests/test_distance.py Log: Added tests for Canberra bug reported in ticket 711. Modified: trunk/scipy/cluster/tests/test_distance.py =================================================================== --- trunk/scipy/cluster/tests/test_distance.py 2008-08-25 12:10:57 UTC (rev 4674) +++ trunk/scipy/cluster/tests/test_distance.py 2008-08-25 12:33:58 UTC (rev 4675) @@ -945,7 +945,7 @@ self.failUnless(within_tol(y1, y2, eps)) def test_pdist_canberra_match(self): - "Tests pdist(X, 'canberra') to see if the two implementations match on random double input data." + "Tests pdist(X, 'canberra') to see if the two implementations match on the Iris data set." D = eo['iris'] print D.shape, D.dtype eps = 1e-10 @@ -954,6 +954,13 @@ print np.abs(y1-y2).max() self.failUnless(within_tol(y1, y2, eps)) + def test_pdist_canberra_ticket_711(self): + "Tests pdist(X, 'canberra') to see if Canberra gives the right result as reported in Scipy bug report 711." + eps = 1e-10 + pdist_y = pdist(([3.3], [3.4]), "canberra") + right_y = array([ 0.01492537]) + print np.abs(pdist_y-right_y).max() + self.failUnless(within_tol(y1, y2, eps)) def within_tol(a, b, tol): return np.abs(a - b).max() < tol From scipy-svn at scipy.org Mon Aug 25 12:51:37 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Mon, 25 Aug 2008 11:51:37 -0500 (CDT) Subject: [Scipy-svn] r4676 - trunk/scipy/cluster/tests Message-ID: <20080825165137.2296239C635@scipy.org> Author: damian.eads Date: 2008-08-25 11:51:35 -0500 (Mon, 25 Aug 2008) New Revision: 4676 Modified: trunk/scipy/cluster/tests/test_distance.py Log: Fixed typo in Canberra test. Modified: trunk/scipy/cluster/tests/test_distance.py =================================================================== --- trunk/scipy/cluster/tests/test_distance.py 2008-08-25 12:33:58 UTC (rev 4675) +++ trunk/scipy/cluster/tests/test_distance.py 2008-08-25 16:51:35 UTC (rev 4676) @@ -956,11 +956,11 @@ def test_pdist_canberra_ticket_711(self): "Tests pdist(X, 'canberra') to see if Canberra gives the right result as reported in Scipy bug report 711." - eps = 1e-10 + eps = 1e-8 pdist_y = pdist(([3.3], [3.4]), "canberra") - right_y = array([ 0.01492537]) + right_y = 0.01492537 print np.abs(pdist_y-right_y).max() - self.failUnless(within_tol(y1, y2, eps)) + self.failUnless(within_tol(pdist_y, right_y, eps)) def within_tol(a, b, tol): return np.abs(a - b).max() < tol From scipy-svn at scipy.org Thu Aug 28 22:01:20 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Thu, 28 Aug 2008 21:01:20 -0500 (CDT) Subject: [Scipy-svn] r4677 - trunk/scipy/weave/tests Message-ID: <20080829020120.0436039C05F@scipy.org> Author: alan.mcintyre Date: 2008-08-28 21:01:12 -0500 (Thu, 28 Aug 2008) New Revision: 4677 Modified: trunk/scipy/weave/tests/test_c_spec.py trunk/scipy/weave/tests/test_numpy_scalar_spec.py trunk/scipy/weave/tests/test_slice_handler.py trunk/scipy/weave/tests/test_standard_array_spec.py trunk/scipy/weave/tests/weave_test_utils.py Log: Remove redundant identical definitions of print_assert_equal (this function is now available from numpy.testing). Modified: trunk/scipy/weave/tests/test_c_spec.py =================================================================== --- trunk/scipy/weave/tests/test_c_spec.py 2008-08-25 16:51:35 UTC (rev 4676) +++ trunk/scipy/weave/tests/test_c_spec.py 2008-08-29 02:01:12 UTC (rev 4677) @@ -27,22 +27,6 @@ out = out.replace("\n","") return out -def print_assert_equal(test_string,actual,desired): - """this should probably be in scipy_test.testing - """ - import pprint - try: - assert(actual == desired) - except AssertionError: - import cStringIO - msg = cStringIO.StringIO() - msg.write(test_string) - msg.write(' failed\nACTUAL: \n') - pprint.pprint(actual,msg) - msg.write('DESIRED: \n') - pprint.pprint(desired,msg) - raise AssertionError, msg.getvalue() - #---------------------------------------------------------------------------- # Scalar conversion test classes # int, float, complex Modified: trunk/scipy/weave/tests/test_numpy_scalar_spec.py =================================================================== --- trunk/scipy/weave/tests/test_numpy_scalar_spec.py 2008-08-25 16:51:35 UTC (rev 4676) +++ trunk/scipy/weave/tests/test_numpy_scalar_spec.py 2008-08-29 02:01:12 UTC (rev 4677) @@ -28,22 +28,6 @@ out = out.replace("\n","") return out -def print_assert_equal(test_string,actual,desired): - """this should probably be in scipy_test.testing - """ - import pprint - try: - assert(actual == desired) - except AssertionError: - import cStringIO - msg = cStringIO.StringIO() - msg.write(test_string) - msg.write(' failed\nACTUAL: \n') - pprint.pprint(actual,msg) - msg.write('DESIRED: \n') - pprint.pprint(desired,msg) - raise AssertionError, msg.getvalue() - #---------------------------------------------------------------------------- # Scalar conversion test classes # int, float, complex Modified: trunk/scipy/weave/tests/test_slice_handler.py =================================================================== --- trunk/scipy/weave/tests/test_slice_handler.py 2008-08-25 16:51:35 UTC (rev 4676) +++ trunk/scipy/weave/tests/test_slice_handler.py 2008-08-29 02:01:12 UTC (rev 4677) @@ -1,27 +1,9 @@ - from numpy.testing import * from scipy.weave import slice_handler from scipy.weave.slice_handler import indexed_array_pattern from scipy.weave.ast_tools import * - -def print_assert_equal(test_string,actual,desired): - """this should probably be in scipy_test.testing - """ - import pprint - try: - assert(actual == desired) - except AssertionError: - import cStringIO - msg = cStringIO.StringIO() - msg.write(test_string) - msg.write(' failed\nACTUAL: \n') - pprint.pprint(actual,msg) - msg.write('DESIRED: \n') - pprint.pprint(desired,msg) - raise AssertionError, msg.getvalue() - class TestBuildSliceAtom(TestCase): def generic_check(self,slice_vars,desired): pos = slice_vars['pos'] Modified: trunk/scipy/weave/tests/test_standard_array_spec.py =================================================================== --- trunk/scipy/weave/tests/test_standard_array_spec.py 2008-08-25 16:51:35 UTC (rev 4676) +++ trunk/scipy/weave/tests/test_standard_array_spec.py 2008-08-29 02:01:12 UTC (rev 4677) @@ -1,4 +1,3 @@ - from numpy import * from numpy.testing import * @@ -10,22 +9,6 @@ out = out.replace("\n","") return out -def print_assert_equal(test_string,actual,desired): - """this should probably be in scipy_test.testing - """ - import pprint - try: - assert(actual == desired) - except AssertionError: - import cStringIO - msg = cStringIO.StringIO() - msg.write(test_string) - msg.write(' failed\nACTUAL: \n') - pprint.pprint(actual,msg) - msg.write('DESIRED: \n') - pprint.pprint(desired,msg) - raise AssertionError, msg.getvalue() - class TestArrayConverter(TestCase): def test_type_match_string(self): s = standard_array_spec.array_converter() Modified: trunk/scipy/weave/tests/weave_test_utils.py =================================================================== --- trunk/scipy/weave/tests/weave_test_utils.py 2008-08-25 16:51:35 UTC (rev 4676) +++ trunk/scipy/weave/tests/weave_test_utils.py 2008-08-29 02:01:12 UTC (rev 4677) @@ -9,21 +9,6 @@ out = out.replace("\n","") return out -def print_assert_equal(test_string,actual,desired): - """this should probably be in scipy_test.testing - """ - try: - assert(actual == desired) - except AssertionError: - import cStringIO - msg = cStringIO.StringIO() - msg.write(test_string) - msg.write(' failed\nACTUAL: \n') - pprint.pprint(actual,msg) - msg.write('DESIRED: \n') - pprint.pprint(desired,msg) - raise AssertionError, msg.getvalue() - ################################################### # mainly used by catalog tests ################################################### From scipy-svn at scipy.org Fri Aug 29 03:15:01 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 29 Aug 2008 02:15:01 -0500 (CDT) Subject: [Scipy-svn] r4678 - in trunk/scipy/sparse: . tests Message-ID: <20080829071501.6D67839C05F@scipy.org> Author: wnbell Date: 2008-08-29 02:14:57 -0500 (Fri, 29 Aug 2008) New Revision: 4678 Modified: trunk/scipy/sparse/lil.py trunk/scipy/sparse/tests/test_base.py Log: fixed inplace operations on lil_matrix Modified: trunk/scipy/sparse/lil.py =================================================================== --- trunk/scipy/sparse/lil.py 2008-08-29 02:01:12 UTC (rev 4677) +++ trunk/scipy/sparse/lil.py 2008-08-29 07:14:57 UTC (rev 4678) @@ -292,8 +292,15 @@ if isscalar(x): x = self.dtype.type(x) elif not isinstance(x, spmatrix): - x = numpy.asarray(x, dtype=self.dtype) + x = lil_matrix(x) + if isspmatrix(x) and index == (slice(None), slice(None)): + # self[:,:] = other_sparse + x = lil_matrix(x) + self.rows = x.rows + self.data = x.data + return + try: i, j = index except (ValueError, TypeError): Modified: trunk/scipy/sparse/tests/test_base.py =================================================================== --- trunk/scipy/sparse/tests/test_base.py 2008-08-29 02:01:12 UTC (rev 4677) +++ trunk/scipy/sparse/tests/test_base.py 2008-08-29 07:14:57 UTC (rev 4678) @@ -1193,25 +1193,22 @@ B[0,:] = A[0,:] assert_array_equal(A[0,:].A, B[0,:].A) - def tst_inplace_op(self,op,arr,other,result): - cpy = arr - getattr(arr,"__i%s__" % op)(other) - assert_array_equal(cpy.todense(),arr.todense()) - assert_array_equal(arr.todense(),result) + def test_inplace_ops(self): + A = lil_matrix([[0,2,3],[4,0,6]]) + B = lil_matrix([[0,1,0],[0,2,3]]) - def testip_inplace_ops(self): - B = self.B[:3,:3].copy() - B[:,:] = B-B - C = B.todense() + data = {'add': (B,A + B), + 'sub': (B,A - B), + 'mul': (3,A * 3)} - data = {'add':(B,C+C), - 'sub':(B,zeros(B.shape)), - 'mul':(3,C*3)} + for op,(other,expected) in data.iteritems(): + result = A.copy() + getattr(result, '__i%s__' % op)(other) - return [(self.tst_inplace_op,op,B,other,result) - for op,(other,result) in data.iteritems()] + assert_array_equal(result.todense(), expected.todense()) + def test_lil_slice_assignment(self): B = lil_matrix((4,3)) B[0,0] = 5 From scipy-svn at scipy.org Fri Aug 29 19:27:19 2008 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Fri, 29 Aug 2008 18:27:19 -0500 (CDT) Subject: [Scipy-svn] r4679 - in trunk/scipy/sparse/linalg/isolve: . tests Message-ID: <20080829232719.CBDB039C018@scipy.org> Author: wnbell Date: 2008-08-29 18:27:17 -0500 (Fri, 29 Aug 2008) New Revision: 4679 Modified: trunk/scipy/sparse/linalg/isolve/iterative.py trunk/scipy/sparse/linalg/isolve/tests/test_iterative.py Log: (mostly) fixes ticket #728 Modified: trunk/scipy/sparse/linalg/isolve/iterative.py =================================================================== --- trunk/scipy/sparse/linalg/isolve/iterative.py 2008-08-29 07:14:57 UTC (rev 4678) +++ trunk/scipy/sparse/linalg/isolve/iterative.py 2008-08-29 23:27:17 UTC (rev 4679) @@ -400,8 +400,8 @@ have a typecode attribute use xtype=0 for the same type as b or use xtype='f','d','F',or 'D' callback -- an optional user-supplied function to call after each - iteration. It is called as callback(xk), where xk is the - current parameter vector. + iteration. It is called as callback(rk), where rk is the + the current relative residual """ A,M,x,b,postprocess = make_system(A,M,x0,b,xtype) @@ -427,31 +427,53 @@ ftflag = True bnrm2 = -1.0 iter_ = maxiter + old_ijob = ijob + first_pass = True + resid_ready = False + iter_num = 1 while True: olditer = iter_ x, iter_, resid, info, ndx1, ndx2, sclr1, sclr2, ijob = \ revcom(b, x, restrt, work, work2, iter_, resid, info, ndx1, ndx2, ijob) - if callback is not None and iter_ > olditer: - callback(x) + #if callback is not None and iter_ > olditer: + # callback(x) slice1 = slice(ndx1-1, ndx1-1+n) slice2 = slice(ndx2-1, ndx2-1+n) - if (ijob == -1): + if (ijob == -1): # gmres success, update last residual + if resid_ready and callback is not None: + callback(resid) + resid_ready = False + break elif (ijob == 1): work[slice2] *= sclr2 work[slice2] += sclr1*matvec(x) elif (ijob == 2): work[slice1] = psolve(work[slice2]) + if not first_pass and old_ijob==3: + resid_ready = True + + first_pass = False elif (ijob == 3): work[slice2] *= sclr2 work[slice2] += sclr1*matvec(work[slice1]) + if resid_ready and callback is not None: + callback(resid) + resid_ready = False + iter_num = iter_num+1 + elif (ijob == 4): if ftflag: info = -1 ftflag = False bnrm2, resid, info = stoptest(work[slice1], b, bnrm2, tol, info) + + old_ijob = ijob ijob = 2 + if iter_num > maxiter: + break + return postprocess(x), info Modified: trunk/scipy/sparse/linalg/isolve/tests/test_iterative.py =================================================================== --- trunk/scipy/sparse/linalg/isolve/tests/test_iterative.py 2008-08-29 07:14:57 UTC (rev 4678) +++ trunk/scipy/sparse/linalg/isolve/tests/test_iterative.py 2008-08-29 23:27:17 UTC (rev 4679) @@ -4,10 +4,10 @@ from numpy.testing import * -from numpy import zeros, dot, diag, ones, arange, array +from numpy import zeros, dot, diag, ones, arange, array, abs, max from numpy.random import rand from scipy.linalg import norm -from scipy.sparse import spdiags +from scipy.sparse import spdiags, csr_matrix from scipy.sparse.linalg.isolve import cg, cgs, bicg, bicgstab, gmres, qmr, minres @@ -21,11 +21,12 @@ #TODO test complex matrices #TODO test both preconditioner methods -data = ones((3,10)) +N = 40 +data = ones((3,N)) data[0,:] = 2 data[1,:] = -1 data[2,:] = -1 -Poisson1D = spdiags( data, [0,-1,1], 10, 10, format='csr') +Poisson1D = spdiags( data, [0,-1,1], N, N, format='csr') data = array([[6, -5, 2, 7, -1, 10, 4, -3, -8, 9]],dtype='d') RandDiag = spdiags( data, [0], 10, 10, format='csr' ) @@ -61,9 +62,28 @@ #data[1,:] = -1 #A = spdiags( data, [0,-1], 10, 10, format='csr') #self.cases.append( (A,False,True) ) + + def test_maxiter(self): + """test whether maxiter is respected""" + A = Poisson1D + for solver,req_sym,req_pos in self.solvers: + b = arange(A.shape[0], dtype=float) + x0 = 0*b + residuals = [] + def callback(x): + residuals.append( norm(b - A*x) ) + + x, info = solver(A, b, x0=x0, tol=1e-8, maxiter=3, callback=callback) + + assert(len(residuals) in [2,3]) + + # TODO enforce this condition instead! + #assert_equal(len(residuals), 2) + + def test_convergence(self): """test whether all methods converge""" @@ -149,5 +169,23 @@ assert( norm(b - A*x) < 1e-8*norm(b) ) +class TestGMRES(TestCase): + def test_callback(self): + + def store_residual(r, rvec): + rvec[rvec.nonzero()[0].max()+1] = r + + #Define, A,b + A = csr_matrix(array([[-2,1,0,0,0,0],[1,-2,1,0,0,0],[0,1,-2,1,0,0],[0,0,1,-2,1,0],[0,0,0,1,-2,1],[0,0,0,0,1,-2]])) + b = ones((A.shape[0],)) + maxiter=1 + rvec = zeros(maxiter+1) + rvec[0] = 1.0 + callback = lambda r:store_residual(r, rvec) + x,flag = gmres(A, b, x0=zeros(A.shape[0]), tol=1e-16, maxiter=maxiter, callback=callback) + diff = max(abs((rvec - array([1.0, 0.81649658092772603])))) + assert(diff < 1e-5) + + if __name__ == "__main__": nose.run(argv=['', __file__])